mirror of
https://github.com/naruxde/revpimodio2.git
synced 2025-11-08 13:53:53 +01:00
Sync write of outputs with autorefresh/cycle or .writeprocimg, if shared_procimg=True
If shared_procimg=True, ModIO wrote the new set values directly to the process image without cycle sync mechanisms. As a result, the IOs could change status several times within the cycleloop, which is wrong.
This commit is contained in:
@@ -129,6 +129,7 @@ class Device(object):
|
|||||||
"_offset", "_position", "_producttype", "_selfupdate", \
|
"_offset", "_position", "_producttype", "_selfupdate", \
|
||||||
"_slc_devoff", "_slc_inp", "_slc_inpoff", "_slc_mem", \
|
"_slc_devoff", "_slc_inp", "_slc_inpoff", "_slc_mem", \
|
||||||
"_slc_memoff", "_slc_out", "_slc_outoff", "_shared_procimg", \
|
"_slc_memoff", "_slc_out", "_slc_outoff", "_shared_procimg", \
|
||||||
|
"_shared_write", \
|
||||||
"bmk", "catalognr", "comment", "extend", \
|
"bmk", "catalognr", "comment", "extend", \
|
||||||
"guid", "id", "inpvariant", "outvariant", "type"
|
"guid", "id", "inpvariant", "outvariant", "type"
|
||||||
|
|
||||||
@@ -148,6 +149,7 @@ class Device(object):
|
|||||||
self.__my_io_list = []
|
self.__my_io_list = []
|
||||||
self._selfupdate = False
|
self._selfupdate = False
|
||||||
self._shared_procimg = parentmodio._shared_procimg
|
self._shared_procimg = parentmodio._shared_procimg
|
||||||
|
self._shared_write = []
|
||||||
|
|
||||||
# Wertzuweisung aus dict_device
|
# Wertzuweisung aus dict_device
|
||||||
self._name = dict_device.get("name")
|
self._name = dict_device.get("name")
|
||||||
@@ -511,6 +513,8 @@ class Device(object):
|
|||||||
|
|
||||||
:param activate: Set True to activate process image sharing
|
:param activate: Set True to activate process image sharing
|
||||||
"""
|
"""
|
||||||
|
with self._filelock:
|
||||||
|
self._shared_write.clear()
|
||||||
self._shared_procimg = True if activate else False
|
self._shared_procimg = True if activate else False
|
||||||
|
|
||||||
def syncoutputs(self) -> bool:
|
def syncoutputs(self) -> bool:
|
||||||
|
|||||||
@@ -536,7 +536,20 @@ class ProcimgWriter(Thread):
|
|||||||
|
|
||||||
for dev in self._modio._lst_refresh:
|
for dev in self._modio._lst_refresh:
|
||||||
with dev._filelock:
|
with dev._filelock:
|
||||||
if self._modio._monitoring or dev._shared_procimg:
|
if self._modio._monitoring:
|
||||||
|
# Inputs und Outputs in Puffer
|
||||||
|
dev._ba_devdata[:] = bytesbuff[dev._slc_devoff]
|
||||||
|
if self.__eventwork \
|
||||||
|
and len(dev._dict_events) > 0 \
|
||||||
|
and dev._ba_datacp != dev._ba_devdata:
|
||||||
|
self.__check_change(dev)
|
||||||
|
|
||||||
|
elif dev._shared_procimg:
|
||||||
|
for io in dev._shared_write:
|
||||||
|
if not io._write_to_procimg():
|
||||||
|
raise IOError("error on _write_to_procimg")
|
||||||
|
dev._shared_write.clear()
|
||||||
|
|
||||||
# Inputs und Outputs in Puffer
|
# Inputs und Outputs in Puffer
|
||||||
dev._ba_devdata[:] = bytesbuff[dev._slc_devoff]
|
dev._ba_devdata[:] = bytesbuff[dev._slc_devoff]
|
||||||
if self.__eventwork \
|
if self.__eventwork \
|
||||||
|
|||||||
@@ -532,6 +532,80 @@ class IOBase(object):
|
|||||||
raise ValueError("Value must be <class 'bool'>")
|
raise ValueError("Value must be <class 'bool'>")
|
||||||
self._export = 2 + int(value)
|
self._export = 2 + int(value)
|
||||||
|
|
||||||
|
def _write_to_procimg(self) -> bool:
|
||||||
|
"""
|
||||||
|
Write value of io directly to the process image.
|
||||||
|
|
||||||
|
:return: True after successful write operation
|
||||||
|
"""
|
||||||
|
if not self._parentdevice._shared_procimg:
|
||||||
|
raise RuntimeError("device is not marked for shared_procimg")
|
||||||
|
|
||||||
|
# note: Will not be removed from _shared_write on direct call
|
||||||
|
|
||||||
|
if self._bitshift:
|
||||||
|
# Write single bit to process image
|
||||||
|
value = \
|
||||||
|
self._parentdevice._ba_devdata[self._slc_address.start] & \
|
||||||
|
self._bitshift
|
||||||
|
if self._parentdevice._modio._run_on_pi:
|
||||||
|
# IOCTL auf dem RevPi
|
||||||
|
with self._parentdevice._modio._myfh_lck:
|
||||||
|
try:
|
||||||
|
# Set value durchführen (Funktion K+16)
|
||||||
|
ioctl(
|
||||||
|
self._parentdevice._modio._myfh,
|
||||||
|
19216,
|
||||||
|
self.__bit_ioctl_on if value
|
||||||
|
else self.__bit_ioctl_off
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self._parentdevice._modio._gotioerror("ioset", e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
elif hasattr(self._parentdevice._modio._myfh, "ioctl"):
|
||||||
|
# IOCTL über Netzwerk
|
||||||
|
with self._parentdevice._modio._myfh_lck:
|
||||||
|
try:
|
||||||
|
self._parentdevice._modio._myfh.ioctl(
|
||||||
|
19216,
|
||||||
|
self.__bit_ioctl_on if value
|
||||||
|
else self.__bit_ioctl_off
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self._parentdevice._modio._gotioerror(
|
||||||
|
"net_ioset", e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
else:
|
||||||
|
# IOCTL in Datei simulieren
|
||||||
|
try:
|
||||||
|
# Set value durchführen (Funktion K+16)
|
||||||
|
self._parentdevice._modio._simulate_ioctl(
|
||||||
|
19216,
|
||||||
|
self.__bit_ioctl_on if value
|
||||||
|
else self.__bit_ioctl_off
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self._parentdevice._modio._gotioerror("file_ioset", e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
else:
|
||||||
|
value = bytes(self._parentdevice._ba_devdata[self._slc_address])
|
||||||
|
with self._parentdevice._modio._myfh_lck:
|
||||||
|
try:
|
||||||
|
self._parentdevice._modio._myfh.seek(
|
||||||
|
self._get_address()
|
||||||
|
)
|
||||||
|
self._parentdevice._modio._myfh.write(value)
|
||||||
|
if self._parentdevice._modio._buffedwrite:
|
||||||
|
self._parentdevice._modio._myfh.flush()
|
||||||
|
except IOError as e:
|
||||||
|
self._parentdevice._modio._gotioerror("ioset", e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def get_defaultvalue(self):
|
def get_defaultvalue(self):
|
||||||
"""
|
"""
|
||||||
Gibt die Defaultvalue von piCtory zurueck.
|
Gibt die Defaultvalue von piCtory zurueck.
|
||||||
@@ -624,54 +698,14 @@ class IOBase(object):
|
|||||||
# Versuchen egal welchen Typ in Bool zu konvertieren
|
# Versuchen egal welchen Typ in Bool zu konvertieren
|
||||||
value = bool(value)
|
value = bool(value)
|
||||||
|
|
||||||
if self._parentdevice._shared_procimg:
|
|
||||||
# Direktes Schreiben der Outputs
|
|
||||||
|
|
||||||
if self._parentdevice._modio._run_on_pi:
|
|
||||||
# IOCTL auf dem RevPi
|
|
||||||
with self._parentdevice._modio._myfh_lck:
|
|
||||||
try:
|
|
||||||
# Set value durchführen (Funktion K+16)
|
|
||||||
ioctl(
|
|
||||||
self._parentdevice._modio._myfh,
|
|
||||||
19216,
|
|
||||||
self.__bit_ioctl_on if value
|
|
||||||
else self.__bit_ioctl_off
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
self._parentdevice._modio._gotioerror("ioset", e)
|
|
||||||
return
|
|
||||||
|
|
||||||
elif hasattr(self._parentdevice._modio._myfh, "ioctl"):
|
|
||||||
# IOCTL über Netzwerk
|
|
||||||
with self._parentdevice._modio._myfh_lck:
|
|
||||||
try:
|
|
||||||
self._parentdevice._modio._myfh.ioctl(
|
|
||||||
19216,
|
|
||||||
self.__bit_ioctl_on if value
|
|
||||||
else self.__bit_ioctl_off
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
self._parentdevice._modio._gotioerror(
|
|
||||||
"net_ioset", e)
|
|
||||||
return
|
|
||||||
|
|
||||||
else:
|
|
||||||
# IOCTL in Datei simulieren
|
|
||||||
try:
|
|
||||||
# Set value durchführen (Funktion K+16)
|
|
||||||
self._parentdevice._modio._simulate_ioctl(
|
|
||||||
19216,
|
|
||||||
self.__bit_ioctl_on if value
|
|
||||||
else self.__bit_ioctl_off
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
self._parentdevice._modio._gotioerror("file_ioset", e)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Für Bitoperationen sperren
|
# Für Bitoperationen sperren
|
||||||
self._parentdevice._filelock.acquire()
|
self._parentdevice._filelock.acquire()
|
||||||
|
|
||||||
|
if self._parentdevice._shared_procimg \
|
||||||
|
and self not in self._parentdevice._shared_write:
|
||||||
|
# Mark this IO for write operations
|
||||||
|
self._parentdevice._shared_write.append(self)
|
||||||
|
|
||||||
# Hier gibt es immer nur ein byte, als int holen
|
# Hier gibt es immer nur ein byte, als int holen
|
||||||
int_byte = self._parentdevice._ba_devdata[self._slc_address.start]
|
int_byte = self._parentdevice._ba_devdata[self._slc_address.start]
|
||||||
|
|
||||||
@@ -704,18 +738,11 @@ class IOBase(object):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._parentdevice._shared_procimg:
|
if self._parentdevice._shared_procimg \
|
||||||
with self._parentdevice._modio._myfh_lck:
|
and self not in self._parentdevice._shared_write:
|
||||||
try:
|
with self._parentdevice._filelock:
|
||||||
self._parentdevice._modio._myfh.seek(
|
# Mark this IO as changed
|
||||||
self._get_address()
|
self._parentdevice._shared_write.append(self)
|
||||||
)
|
|
||||||
self._parentdevice._modio._myfh.write(value)
|
|
||||||
if self._parentdevice._modio._buffedwrite:
|
|
||||||
self._parentdevice._modio._myfh.flush()
|
|
||||||
except IOError as e:
|
|
||||||
self._parentdevice._modio._gotioerror("ioset", e)
|
|
||||||
return
|
|
||||||
|
|
||||||
self._parentdevice._ba_devdata[self._slc_address] = value
|
self._parentdevice._ba_devdata[self._slc_address] = value
|
||||||
|
|
||||||
|
|||||||
@@ -1227,13 +1227,21 @@ class RevPiModIO(object):
|
|||||||
mylist = [dev]
|
mylist = [dev]
|
||||||
|
|
||||||
global_ex = None
|
global_ex = None
|
||||||
workokay = True
|
|
||||||
for dev in mylist:
|
for dev in mylist:
|
||||||
if dev._shared_procimg:
|
if dev._selfupdate:
|
||||||
|
# Do not update this device
|
||||||
continue
|
continue
|
||||||
elif not dev._selfupdate:
|
|
||||||
dev._filelock.acquire()
|
|
||||||
|
|
||||||
|
dev._filelock.acquire()
|
||||||
|
|
||||||
|
if dev._shared_procimg:
|
||||||
|
for io in dev._shared_write:
|
||||||
|
if not io._write_to_procimg():
|
||||||
|
global_ex = IOError(
|
||||||
|
"error on shared procimg while write"
|
||||||
|
)
|
||||||
|
dev._shared_write.clear()
|
||||||
|
else:
|
||||||
# Outpus auf Bus schreiben
|
# Outpus auf Bus schreiben
|
||||||
self._myfh_lck.acquire()
|
self._myfh_lck.acquire()
|
||||||
try:
|
try:
|
||||||
@@ -1241,23 +1249,22 @@ class RevPiModIO(object):
|
|||||||
self._myfh.write(dev._ba_devdata[dev._slc_out])
|
self._myfh.write(dev._ba_devdata[dev._slc_out])
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
global_ex = e
|
global_ex = e
|
||||||
workokay = False
|
|
||||||
finally:
|
finally:
|
||||||
self._myfh_lck.release()
|
self._myfh_lck.release()
|
||||||
|
|
||||||
dev._filelock.release()
|
dev._filelock.release()
|
||||||
|
|
||||||
if self._buffedwrite:
|
if self._buffedwrite:
|
||||||
try:
|
try:
|
||||||
self._myfh.flush()
|
self._myfh.flush()
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
global_ex = e
|
global_ex = e
|
||||||
workokay = False
|
|
||||||
|
|
||||||
if not workokay:
|
if global_ex:
|
||||||
self._gotioerror("writeprocimg", global_ex)
|
self._gotioerror("writeprocimg", global_ex)
|
||||||
|
return False
|
||||||
|
|
||||||
return workokay
|
return True
|
||||||
|
|
||||||
debug = property(_get_debug, _set_debug)
|
debug = property(_get_debug, _set_debug)
|
||||||
configrsc = property(_get_configrsc)
|
configrsc = property(_get_configrsc)
|
||||||
|
|||||||
Reference in New Issue
Block a user