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", \
|
||||
"_slc_devoff", "_slc_inp", "_slc_inpoff", "_slc_mem", \
|
||||
"_slc_memoff", "_slc_out", "_slc_outoff", "_shared_procimg", \
|
||||
"_shared_write", \
|
||||
"bmk", "catalognr", "comment", "extend", \
|
||||
"guid", "id", "inpvariant", "outvariant", "type"
|
||||
|
||||
@@ -148,6 +149,7 @@ class Device(object):
|
||||
self.__my_io_list = []
|
||||
self._selfupdate = False
|
||||
self._shared_procimg = parentmodio._shared_procimg
|
||||
self._shared_write = []
|
||||
|
||||
# Wertzuweisung aus dict_device
|
||||
self._name = dict_device.get("name")
|
||||
@@ -511,6 +513,8 @@ class Device(object):
|
||||
|
||||
:param activate: Set True to activate process image sharing
|
||||
"""
|
||||
with self._filelock:
|
||||
self._shared_write.clear()
|
||||
self._shared_procimg = True if activate else False
|
||||
|
||||
def syncoutputs(self) -> bool:
|
||||
|
||||
@@ -536,7 +536,20 @@ class ProcimgWriter(Thread):
|
||||
|
||||
for dev in self._modio._lst_refresh:
|
||||
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
|
||||
dev._ba_devdata[:] = bytesbuff[dev._slc_devoff]
|
||||
if self.__eventwork \
|
||||
|
||||
@@ -532,6 +532,80 @@ class IOBase(object):
|
||||
raise ValueError("Value must be <class 'bool'>")
|
||||
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):
|
||||
"""
|
||||
Gibt die Defaultvalue von piCtory zurueck.
|
||||
@@ -624,54 +698,14 @@ class IOBase(object):
|
||||
# Versuchen egal welchen Typ in Bool zu konvertieren
|
||||
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
|
||||
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
|
||||
int_byte = self._parentdevice._ba_devdata[self._slc_address.start]
|
||||
|
||||
@@ -704,18 +738,11 @@ class IOBase(object):
|
||||
)
|
||||
)
|
||||
|
||||
if self._parentdevice._shared_procimg:
|
||||
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
|
||||
if self._parentdevice._shared_procimg \
|
||||
and self not in self._parentdevice._shared_write:
|
||||
with self._parentdevice._filelock:
|
||||
# Mark this IO as changed
|
||||
self._parentdevice._shared_write.append(self)
|
||||
|
||||
self._parentdevice._ba_devdata[self._slc_address] = value
|
||||
|
||||
|
||||
@@ -1227,13 +1227,21 @@ class RevPiModIO(object):
|
||||
mylist = [dev]
|
||||
|
||||
global_ex = None
|
||||
workokay = True
|
||||
for dev in mylist:
|
||||
if dev._shared_procimg:
|
||||
if dev._selfupdate:
|
||||
# Do not update this device
|
||||
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
|
||||
self._myfh_lck.acquire()
|
||||
try:
|
||||
@@ -1241,23 +1249,22 @@ class RevPiModIO(object):
|
||||
self._myfh.write(dev._ba_devdata[dev._slc_out])
|
||||
except IOError as e:
|
||||
global_ex = e
|
||||
workokay = False
|
||||
finally:
|
||||
self._myfh_lck.release()
|
||||
|
||||
dev._filelock.release()
|
||||
dev._filelock.release()
|
||||
|
||||
if self._buffedwrite:
|
||||
try:
|
||||
self._myfh.flush()
|
||||
except IOError as e:
|
||||
global_ex = e
|
||||
workokay = False
|
||||
|
||||
if not workokay:
|
||||
if global_ex:
|
||||
self._gotioerror("writeprocimg", global_ex)
|
||||
return False
|
||||
|
||||
return workokay
|
||||
return True
|
||||
|
||||
debug = property(_get_debug, _set_debug)
|
||||
configrsc = property(_get_configrsc)
|
||||
|
||||
Reference in New Issue
Block a user