# HG changeset patch # User Edouard Tisserant # Date 1644782719 -3600 # Node ID c2c366964913bbdc4720e45b7fcb063cce1118b3 # Parent ee3b84d09ccf439d2c049b1f5779a0758b161b57# Parent 70ef15fca0280bd21389df61f349342c31bb1c25 merged default diff -r ee3b84d09ccf -r c2c366964913 Beremiz_service.py --- a/Beremiz_service.py Sun Feb 13 21:01:27 2022 +0100 +++ b/Beremiz_service.py Sun Feb 13 21:05:19 2022 +0100 @@ -32,6 +32,7 @@ import threading import shlex import traceback +import threading from threading import Thread, Semaphore, Lock, currentThread from builtins import str as text from past.builtins import execfile @@ -46,6 +47,14 @@ from runtime.Stunnel import ensurePSK import util.paths as paths +# In case system time is ajusted, it is better to use +# monotonic timers for timers and other timeout based operations. +# hot-patch threading module to force using monitonic time for all +# Thread/Timer/Event/Condition + +from runtime.monotonic_time import monotonic +threading._time = monotonic + try: from runtime.spawn_subprocess import Popen except ImportError: diff -r ee3b84d09ccf -r c2c366964913 ProjectController.py --- a/ProjectController.py Sun Feb 13 21:01:27 2022 +0100 +++ b/ProjectController.py Sun Feb 13 21:05:19 2022 +0100 @@ -796,7 +796,7 @@ # Compute offset before ST resulting of transformation from user POUs self.ProgramOffset = IECCodeContent.count("\n") - IECCodeContent += open(self._getIECgeneratedcodepath(), "r").read() + POUsIECCodeContent = open(self._getIECgeneratedcodepath(), "r").read() IECcodepath = self._getIECcodepath() @@ -805,9 +805,11 @@ with open(IECcodepath, "w") as plc_file: plc_file.write(IECCodeContent) + plc_file.write(POUsIECCodeContent) hasher = hashlib.md5() hasher.update(IECCodeContent) + hasher.update(POUsIECCodeContent) self.IECcodeDigest = hasher.hexdigest() return True diff -r ee3b84d09ccf -r c2c366964913 runtime/monotonic_time.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/runtime/monotonic_time.py Sun Feb 13 21:05:19 2022 +0100 @@ -0,0 +1,159 @@ +# vi: set ft=python sw=4 ts=4 et: + +'''monotonic time for Python 2 and 3, on Linux, FreeBSD, Mac OS X, and Windows. + +Copyright 2010, 2011, 2017 Gavin Beatty + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +''' + +from __future__ import print_function +from __future__ import unicode_literals + +__author__ = 'Gavin Beatty ' +__version__ = '2.1.0.dev0' +__date__ = '2017-05-28' +__all__ = ['monotonic'] + +import contextlib +import ctypes +import errno +import os +import platform +import sys +import time + +_machine64 = (platform.machine(), sys.maxsize > 2**32) + + +class _NS(): + pass + + +class _mach_timespec(ctypes.Structure): + _fields_ = [('tv_sec', ctypes.c_uint), ('tv_nsec', ctypes.c_int)] + + +class _posix_timespec(ctypes.Structure): + _fields_ = [('tv_sec', ctypes.c_long), ('tv_nsec', ctypes.c_long)] + + +def _timespec_to_seconds(ts): + return float(ts.tv_sec) + float(ts.tv_nsec) * 1e-9 + + +def _get_ctypes_libmacho_macho_functions(): + libmacho = ctypes.CDLL('/usr/lib/system/libmacho.dylib', use_errno=True) + macho = _NS() + macho.get_host = libmacho.mach_host_self + macho.get_host.argtypes = [] + macho.get_host.restype = ctypes.c_uint + macho.get_clock = libmacho.host_get_clock_service + macho.get_clock.argtypes = [ctypes.c_uint, + ctypes.c_int, + ctypes.POINTER(ctypes.c_uint) + ] + macho.get_time = libmacho.clock_get_time + macho.get_time.argtypes = [ctypes.c_uint, ctypes.POINTER(_mach_timespec)] + macho.deallocate = libmacho.mach_port_deallocate + macho.deallocate.argtypes = [ctypes.c_uint, ctypes.c_uint] + return libmacho, macho + + +def _get_ctypes_clock_gettime(library): + clock_gettime = ctypes.CDLL(library, use_errno=True).clock_gettime + clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(_posix_timespec)] + return clock_gettime + + +def _call_ctypes_clock_gettime(clock_gettime, clockid): + timespec = _posix_timespec() + ret = clock_gettime(clockid, ctypes.pointer(timespec)) + if int(ret) != 0: + errno_ = ctypes.get_errno() + raise OSError(errno_, os.strerror(errno_)) + return timespec + + +_py_monotonic = getattr(time, 'monotonic', None) +if _py_monotonic is not None: + monotonic = _py_monotonic +elif sys.platform.startswith('linux'): + _clock_gettime = _get_ctypes_clock_gettime('librt.so.1') + + def monotonic(): + clockid = ctypes.c_int(1) + timespec = _call_ctypes_clock_gettime(_clock_gettime, clockid) + return _timespec_to_seconds(timespec) +elif sys.platform.startswith('freebsd'): + _clock_gettime = _get_ctypes_clock_gettime('libc.so') + + def monotonic(): + clockid = ctypes.c_int(4) + timespec = _call_ctypes_clock_gettime(_clock_gettime, clockid) + return _timespec_to_seconds(timespec) +elif sys.platform.startswith('darwin') and _machine64 == ('x86_64', True): + _libmacho, _macho = _get_ctypes_libmacho_macho_functions() + + @contextlib.contextmanager + def _deallocate(task, port): + try: + yield + finally: + if int(_macho.deallocate(task, port)) == 0: + return + errno_ = ctypes.get_errno() + raise OSError(errno_, os.strerror(errno_)) + + def monotonic(): + task = ctypes.c_uint.in_dll(_libmacho, 'mach_task_self_') + host = _macho.get_host() + with _deallocate(task, host): + clock = ctypes.c_uint(0) + clockid = ctypes.c_int(0) + ret = _macho.get_clock(host, clockid, ctypes.pointer(clock)) + if int(ret) != 0: + errno_ = ctypes.get_errno() + raise OSError(errno_, os.strerror(errno_)) + with _deallocate(task, clock): + timespec = _mach_timespec() + ret = _macho.get_time(clock, ctypes.pointer(timespec)) + if int(ret) != 0: + errno_ = ctypes.get_errno() + raise OSError(errno_, os.strerror(errno_)) + return _timespec_to_seconds(timespec) +elif sys.platform.startswith('win32'): + _GetTickCount = getattr(ctypes.windll.kernel32, 'GetTickCount64', None) + + if _GetTickCount is not None: + _GetTickCount.restype = ctypes.c_uint64 + else: + _GetTickCount = ctypes.windll.kernel32.GetTickCount + _GetTickCount.restype = ctypes.c_uint32 + + def monotonic(): + return float(_GetTickCount()) * 1e-3 +else: + def monotonic(): + msg = 'monotonic not supported on your platform' + raise OSError(errno.ENOSYS, msg) + + +if __name__ == '__main__': + print(monotonic()) diff -r ee3b84d09ccf -r c2c366964913 svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Sun Feb 13 21:01:27 2022 +0100 +++ b/svghmi/gen_index_xhtml.xslt Sun Feb 13 21:05:19 2022 +0100 @@ -1459,8 +1459,6 @@ this.element = id(elt_id); - if(freq !== undefined) this.frequency = freq; - this.args = args; this.indexes = indexes; @@ -1477,6 +1475,8 @@ this.bound_unhinibit = this.unhinibit.bind(this); + this.forced_frequency = freq; + } @@ -2402,7 +2402,7 @@ console.log("Entering state - "); + ", this.frequency); } @@ -8237,6 +8237,10 @@ } + if(widget.forced_frequency !== undefined) + + widget.frequency = widget.forced_frequency; + }); }; @@ -8801,8 +8805,6 @@ function send_hmi_value(index, value) { - console.log("send_hmi_value("+index+", "+value+")") - if(index > last_remote_index){ updates.set(index, value); @@ -8851,7 +8853,9 @@ function apply_hmi_value(index, new_val) { - console.log("apply_hmi_value("+index+", "+new_val+")") + // Similarly to previous comment, taking decision to update based + + // on cache content is bad and can lead to inconsistency /*let old_val = cache[index];*/ diff -r ee3b84d09ccf -r c2c366964913 svghmi/svghmi.js --- a/svghmi/svghmi.js Sun Feb 13 21:01:27 2022 +0100 +++ b/svghmi/svghmi.js Sun Feb 13 21:05:19 2022 +0100 @@ -26,6 +26,8 @@ console.log(err); } } + if(widget.forced_frequency !== undefined) + widget.frequency = widget.forced_frequency; }); }; diff -r ee3b84d09ccf -r c2c366964913 svghmi/widget_button.ysl2 --- a/svghmi/widget_button.ysl2 Sun Feb 13 21:01:27 2022 +0100 +++ b/svghmi/widget_button.ysl2 Sun Feb 13 21:05:19 2022 +0100 @@ -146,7 +146,7 @@ } template "state", mode="actions" { | «@name»_action(){ - | console.log("Entering state «@name»"); + // | console.log("Entering state «@name»", this.frequency); apply "*", mode="actions"; | } } @@ -163,7 +163,6 @@ function "generated_button_class" { param "fsm"; - | frequency = 5; | display = "inactive"; | state = "init"; @@ -202,6 +201,7 @@ widget_class("Button"){ + | frequency = 5; const "fsm","exsl:node-set($_button_fsm)"; call "generated_button_class" with "fsm", "$fsm"; } @@ -211,6 +211,7 @@ } widget_class("PushButton"){ + | frequency = 20; const "fsm","exsl:node-set($_push_button_fsm)"; call "generated_button_class" with "fsm", "$fsm"; } diff -r ee3b84d09ccf -r c2c366964913 svghmi/widgets_common.ysl2 --- a/svghmi/widgets_common.ysl2 Sun Feb 13 21:01:27 2022 +0100 +++ b/svghmi/widgets_common.ysl2 Sun Feb 13 21:05:19 2022 +0100 @@ -174,7 +174,6 @@ constructor(elt_id, freq, args, indexes, minmaxes, members){ this.element_id = elt_id; this.element = id(elt_id); - if(freq !== undefined) this.frequency = freq; this.args = args; this.indexes = indexes; this.minmaxes = minmaxes; @@ -183,6 +182,7 @@ this.inhibit = indexes.map(() => undefined); this.pending = indexes.map(() => undefined); this.bound_unhinibit = this.unhinibit.bind(this); + this.forced_frequency = freq; } unsub(){ diff -r ee3b84d09ccf -r c2c366964913 tests/projects/svghmi/svghmi_0@svghmi/svghmi.svg --- a/tests/projects/svghmi/svghmi_0@svghmi/svghmi.svg Sun Feb 13 21:01:27 2022 +0100 +++ b/tests/projects/svghmi/svghmi_0@svghmi/svghmi.svg Sun Feb 13 21:05:19 2022 +0100 @@ -128,11 +128,11 @@ inkscape:current-layer="hmi0" showgrid="false" units="px" - inkscape:zoom="0.40092402" - inkscape:cx="-239.69441" - inkscape:cy="-2504.0401" - inkscape:window-width="3840" - inkscape:window-height="2096" + inkscape:zoom="0.20046201" + inkscape:cx="1401.1703" + inkscape:cy="-1495.7332" + inkscape:window-width="1600" + inkscape:window-height="836" inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1" @@ -7612,7 +7612,7 @@