360 runtimefile.write(svghmiservercode) |
360 runtimefile.write(svghmiservercode) |
361 runtimefile.close() |
361 runtimefile.close() |
362 |
362 |
363 # Backup HMI Tree in XML form so that it can be loaded without building |
363 # Backup HMI Tree in XML form so that it can be loaded without building |
364 hmitree_backup_path = os.path.join(buildpath, "hmitree.xml") |
364 hmitree_backup_path = os.path.join(buildpath, "hmitree.xml") |
365 hmitree_backup_file = open(hmitree_backup_path, 'w') |
365 hmitree_backup_file = open(hmitree_backup_path, 'wb') |
366 hmitree_backup_file.write(etree.tostring(hmi_tree_root.etree())) |
366 hmitree_backup_file.write(etree.tostring(hmi_tree_root.etree())) |
367 hmitree_backup_file.close() |
367 hmitree_backup_file.close() |
368 |
368 |
369 return ((["svghmi"], [(gen_svghmi_c_path, IECCFLAGS)], True), "", |
369 return ((["svghmi"], [(gen_svghmi_c_path, IECCFLAGS)], True), "", |
370 ("runtime_00_svghmi.py", open(runtimefile_path, "rb"))) |
370 ("runtime_00_svghmi.py", open(runtimefile_path, "rb"))) |
600 |
600 |
601 res = ([], "", False) |
601 res = ([], "", False) |
602 |
602 |
603 target_fname = "svghmi_"+location_str+".xhtml" |
603 target_fname = "svghmi_"+location_str+".xhtml" |
604 |
604 |
605 target_path = os.path.join(self._getBuildPath(), target_fname) |
605 build_path = self._getBuildPath() |
606 target_file = open(target_path, 'wb') |
606 target_path = os.path.join(build_path, target_fname) |
|
607 hash_path = os.path.join(build_path, "svghmi.md5") |
607 |
608 |
608 self.GetCTRoot().logger.write("SVGHMI:\n") |
609 self.GetCTRoot().logger.write("SVGHMI:\n") |
609 |
610 |
610 if os.path.exists(svgfile): |
611 if os.path.exists(svgfile): |
611 |
612 |
612 # TODO : move to __init__ |
613 hasher = hashlib.md5() |
613 transform = XSLTransform(os.path.join(ScriptDirectory, "gen_index_xhtml.xslt"), |
614 hmi_tree_root._hash(hasher) |
614 [("GetSVGGeometry", lambda *_ignored:self.GetSVGGeometry()), |
615 with open(svgfile, 'rb') as afile: |
615 ("GetHMITree", lambda *_ignored:self.GetHMITree()), |
616 while True: |
616 ("GetTranslations", self.GetTranslations), |
617 buf = afile.read(65536) |
617 ("ProgressStart", lambda _ign,k,m:self.ProgressStart(str(k),str(m))), |
618 if len(buf) > 0: |
618 ("ProgressEnd", lambda _ign,k:self.ProgressEnd(str(k)))]) |
619 hasher.update(buf) |
619 |
620 else: |
620 self.ProgressStart("svg", "source SVG parsing") |
621 break |
621 |
622 digest = hasher.hexdigest() |
622 # load svg as a DOM with Etree |
623 |
623 svgdom = etree.parse(svgfile) |
624 if os.path.exists(hash_path): |
624 |
625 with open(hash_path, 'rb') as digest_file: |
625 self.ProgressEnd("svg") |
626 last_digest = digest_file.read() |
626 |
627 else: |
627 # call xslt transform on Inkscape's SVG to generate XHTML |
628 last_digest = None |
628 try: |
629 |
629 self.ProgressStart("xslt", "XSLT transform") |
630 if digest != last_digest: |
630 result = transform.transform(svgdom) # , profile_run=True) |
631 |
631 self.ProgressEnd("xslt") |
632 transform = XSLTransform(os.path.join(ScriptDirectory, "gen_index_xhtml.xslt"), |
632 except XSLTApplyError as e: |
633 [("GetSVGGeometry", lambda *_ignored:self.GetSVGGeometry()), |
633 self.FatalError("SVGHMI " + view_name + ": " + e.message) |
634 ("GetHMITree", lambda *_ignored:self.GetHMITree()), |
634 finally: |
635 ("GetTranslations", self.GetTranslations), |
635 for entry in transform.get_error_log(): |
636 ("ProgressStart", lambda _ign,k,m:self.ProgressStart(str(k),str(m))), |
636 message = "SVGHMI: "+ entry.message + "\n" |
637 ("ProgressEnd", lambda _ign,k:self.ProgressEnd(str(k)))]) |
637 self.GetCTRoot().logger.write_warning(message) |
638 |
638 |
639 self.ProgressStart("svg", "source SVG parsing") |
639 result.write(target_file, encoding="utf-8") |
640 |
640 # print(str(result)) |
641 # load svg as a DOM with Etree |
641 # print(transform.xslt.error_log) |
642 svgdom = etree.parse(svgfile) |
642 # print(etree.tostring(result.xslt_profile,pretty_print=True)) |
643 |
643 |
644 self.ProgressEnd("svg") |
644 # TODO |
645 |
645 # - Errors on HMI semantics |
646 # call xslt transform on Inkscape's SVG to generate XHTML |
646 # - ... maybe something to have a global view of what is declared in SVG. |
647 try: |
|
648 self.ProgressStart("xslt", "XSLT transform") |
|
649 result = transform.transform(svgdom) # , profile_run=True) |
|
650 self.ProgressEnd("xslt") |
|
651 except XSLTApplyError as e: |
|
652 self.FatalError("SVGHMI " + view_name + ": " + e.message) |
|
653 finally: |
|
654 for entry in transform.get_error_log(): |
|
655 message = "SVGHMI: "+ entry.message + "\n" |
|
656 self.GetCTRoot().logger.write_warning(message) |
|
657 |
|
658 target_file = open(target_path, 'wb') |
|
659 result.write(target_file, encoding="utf-8") |
|
660 target_file.close() |
|
661 |
|
662 # print(str(result)) |
|
663 # print(transform.xslt.error_log) |
|
664 # print(etree.tostring(result.xslt_profile,pretty_print=True)) |
|
665 |
|
666 with open(hash_path, 'wb') as digest_file: |
|
667 digest_file.write(digest) |
|
668 else: |
|
669 self.GetCTRoot().logger.write(" No changes - XSLT transformation skipped\n") |
647 |
670 |
648 else: |
671 else: |
649 # TODO : use default svg that expose the HMI tree as-is |
672 target_file = open(target_path, 'wb') |
650 target_file.write("""<!DOCTYPE html> |
673 target_file.write("""<!DOCTYPE html> |
651 <html> |
674 <html> |
652 <body> |
675 <body> |
653 <h1> No SVG file provided </h1> |
676 <h1> No SVG file provided </h1> |
654 </body> |
677 </body> |
655 </html> |
678 </html> |
656 """) |
679 """) |
657 |
680 target_file.close() |
658 target_file.close() |
|
659 |
681 |
660 res += ((target_fname, open(target_path, "rb")),) |
682 res += ((target_fname, open(target_path, "rb")),) |
661 |
683 |
662 svghmi_cmds = {} |
684 svghmi_cmds = {} |
663 for thing in ["Start", "Stop", "Watchdog"]: |
685 for thing in ["Start", "Stop", "Watchdog"]: |