277 class SVGHMI(object): |
277 class SVGHMI(object): |
278 XSD = """<?xml version="1.0" encoding="utf-8" ?> |
278 XSD = """<?xml version="1.0" encoding="utf-8" ?> |
279 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
279 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
280 <xsd:element name="SVGHMI"> |
280 <xsd:element name="SVGHMI"> |
281 <xsd:complexType> |
281 <xsd:complexType> |
282 <xsd:attribute name="OnStart" type="xsd:string" use="optional"/> |
282 <xsd:attribute name="OnStart" type="xsd:string" use="optional" default="chromium {url}"/> |
283 <xsd:attribute name="OnStop" type="xsd:string" use="optional"/> |
283 <xsd:attribute name="OnStop" type="xsd:string" use="optional" default="echo 'please close chromium window at {url}'"/> |
284 <xsd:attribute name="OnWatchdog" type="xsd:string" use="optional"/> |
284 <xsd:attribute name="EnableWatchdog" type="xsd:boolean" use="optional" default="false"/> |
285 <xsd:attribute name="WatchdogInitial" type="xsd:integer" use="optional"/> |
285 <xsd:attribute name="OnWatchdog" type="xsd:string" use="optional" default="chromium {url}"/> |
286 <xsd:attribute name="WatchdogInterval" type="xsd:integer" use="optional"/> |
286 <xsd:attribute name="WatchdogInitial" type="xsd:integer" use="optional" default="30"/> |
|
287 <xsd:attribute name="WatchdogInterval" type="xsd:integer" use="optional" default="5"/> |
|
288 <xsd:attribute name="Port" type="xsd:integer" use="optional" default="8008"/> |
|
289 <xsd:attribute name="Interface" type="xsd:string" use="optional" default="localhost"/> |
|
290 <xsd:attribute name="Path" type="xsd:string" use="optional" default=""/> |
287 </xsd:complexType> |
291 </xsd:complexType> |
288 </xsd:element> |
292 </xsd:element> |
289 </xsd:schema> |
293 </xsd:schema> |
290 """ |
294 """ |
291 |
295 |
530 """) |
534 """) |
531 target_file.close() |
535 target_file.close() |
532 |
536 |
533 res += ((target_fname, open(target_path, "rb")),) |
537 res += ((target_fname, open(target_path, "rb")),) |
534 |
538 |
|
539 port = self.GetParamsAttributes("SVGHMI.Port")["value"] |
|
540 interface = self.GetParamsAttributes("SVGHMI.Interface")["value"] |
|
541 path = self.GetParamsAttributes("SVGHMI.Path")["value"].format(name=view_name) |
|
542 enable_watchdog = self.GetParamsAttributes("SVGHMI.EnableWatchdog")["value"] |
|
543 url="http://"+interface+("" if port==80 else (":"+str(port)) |
|
544 ) + (("/"+path) if path else "" |
|
545 ) + ("#watchdog" if enable_watchdog else "") |
|
546 |
535 svghmi_cmds = {} |
547 svghmi_cmds = {} |
536 for thing in ["Start", "Stop", "Watchdog"]: |
548 for thing in ["Start", "Stop", "Watchdog"]: |
537 given_command = self.GetParamsAttributes("SVGHMI.On"+thing)["value"] |
549 given_command = self.GetParamsAttributes("SVGHMI.On"+thing)["value"] |
538 svghmi_cmds[thing] = ( |
550 svghmi_cmds[thing] = ( |
539 "Popen(" + |
551 "Popen(" + |
540 repr(shlex.split(given_command.format(port="8008", name=view_name))) + |
552 repr(shlex.split(given_command.format( |
|
553 port=port, |
|
554 name=view_name, |
|
555 url=url))) + |
541 ")") if given_command else "pass # no command given" |
556 ")") if given_command else "pass # no command given" |
542 |
557 |
543 runtimefile_path = os.path.join(buildpath, "runtime_%s_svghmi_.py" % location_str) |
558 runtimefile_path = os.path.join(buildpath, "runtime_%s_svghmi_.py" % location_str) |
544 runtimefile = open(runtimefile_path, 'w') |
559 runtimefile = open(runtimefile_path, 'w') |
545 runtimefile.write(""" |
560 runtimefile.write(""" |
546 # TODO : multiple watchdog (one for each svghmi instance) |
561 # TODO : multiple watchdog (one for each svghmi instance) |
547 def svghmi_watchdog_trigger(): |
562 def svghmi_{location}_watchdog_trigger(): |
548 {svghmi_cmds[Watchdog]} |
563 {svghmi_cmds[Watchdog]} |
549 |
564 |
550 svghmi_watchdog = None |
565 svghmi_watchdog = None |
551 |
566 |
552 def _runtime_{location}_svghmi_start(): |
567 def _runtime_{location}_svghmi_start(): |
553 global svghmi_watchdog |
568 global svghmi_watchdog, svghmi_servers |
|
569 |
|
570 srv = svghmi_servers.get("{interface}:{port}", None) |
|
571 if srv is not None: |
|
572 svghmi_root, svghmi_listener, path_list = srv |
|
573 if '{path}' in path_list: |
|
574 raise Exception("SVGHMI {view_name}: path {path} already used on {interface}:{port}") |
|
575 else: |
|
576 svghmi_root = Resource() |
|
577 svghmi_root.putChild("ws", WebSocketResource(HMIWebSocketServerFactory())) |
|
578 |
|
579 svghmi_listener = reactor.listenTCP({port}, Site(svghmi_root), interface='{interface}') |
|
580 path_list = [] |
|
581 svghmi_servers["{interface}:{port}"] = (svghmi_root, svghmi_listener, path_list) |
|
582 |
554 svghmi_root.putChild( |
583 svghmi_root.putChild( |
555 '{view_name}', |
584 '{path}', |
556 NoCacheFile('{xhtml}', |
585 NoCacheFile('{xhtml}', |
557 defaultType='application/xhtml+xml')) |
586 defaultType='application/xhtml+xml')) |
|
587 |
|
588 path_list.append("{path}") |
558 |
589 |
559 {svghmi_cmds[Start]} |
590 {svghmi_cmds[Start]} |
560 |
591 |
561 svghmi_watchdog = Watchdog( |
592 if {enable_watchdog}: |
562 {watchdog_initial}, |
593 if svghmi_watchdog is None: |
563 {watchdog_interval}, |
594 svghmi_watchdog = Watchdog( |
564 svghmi_watchdog_trigger) |
595 {watchdog_initial}, |
|
596 {watchdog_interval}, |
|
597 svghmi_{location}_watchdog_trigger) |
|
598 else: |
|
599 raise Exception("SVGHMI {view_name}: only one watchdog allowed") |
|
600 |
565 |
601 |
566 def _runtime_{location}_svghmi_stop(): |
602 def _runtime_{location}_svghmi_stop(): |
567 global svghmi_watchdog |
603 global svghmi_watchdog, svghmi_servers |
|
604 |
568 if svghmi_watchdog is not None: |
605 if svghmi_watchdog is not None: |
569 svghmi_watchdog.cancel() |
606 svghmi_watchdog.cancel() |
570 svghmi_watchdog = None |
607 svghmi_watchdog = None |
571 |
608 |
572 svghmi_root.delEntity('{view_name}') |
609 svghmi_root, svghmi_listener, path_list = svghmi_servers["{interface}:{port}"] |
|
610 svghmi_root.delEntity('{path}') |
|
611 |
|
612 path_list.remove('{path}') |
|
613 |
|
614 if len(path_list)==0: |
|
615 svghmi_root.delEntity("ws") |
|
616 svghmi_listener.stopListening() |
|
617 svghmi_servers.pop("{interface}:{port}") |
|
618 |
573 {svghmi_cmds[Stop]} |
619 {svghmi_cmds[Stop]} |
574 |
620 |
575 """.format(location=location_str, |
621 """.format(location=location_str, |
576 xhtml=target_fname, |
622 xhtml=target_fname, |
577 view_name=view_name, |
623 view_name=view_name, |
578 svghmi_cmds=svghmi_cmds, |
624 svghmi_cmds=svghmi_cmds, |
|
625 port = port, |
|
626 interface = interface, |
|
627 path = path, |
|
628 enable_watchdog = enable_watchdog, |
579 watchdog_initial = self.GetParamsAttributes("SVGHMI.WatchdogInitial")["value"], |
629 watchdog_initial = self.GetParamsAttributes("SVGHMI.WatchdogInitial")["value"], |
580 watchdog_interval = self.GetParamsAttributes("SVGHMI.WatchdogInterval")["value"], |
630 watchdog_interval = self.GetParamsAttributes("SVGHMI.WatchdogInterval")["value"], |
581 )) |
631 )) |
582 |
632 |
583 runtimefile.close() |
633 runtimefile.close() |