replace_io kann Bits >7 bei längeren Datentypen festlegen

Klassenattribute für Device angelegt
Intern nur auf interne _Variablen zugreifen
StructIO berechnet _defaultvalue aus gelöschten IOs
This commit is contained in:
2017-08-27 14:46:28 +02:00
parent 4e9abf794b
commit dcc8c22428
6 changed files with 199 additions and 122 deletions

View File

@@ -358,7 +358,7 @@ object
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>None</td></tr>
<tr><td>length</td></tr><tr><td>name</td></tr><tr><td>offset</td></tr><tr><td>position</td></tr><tr><td>producttype</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
@@ -396,6 +396,12 @@ Methods</h3>
<td><a style="color:#0000FF" href="#Device._devconfigure">_devconfigure</a></td>
<td>Funktion zum ueberschreiben von abgeleiteten Klassen.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#Device._get_offset">_get_offset</a></td>
<td>Gibt den Deviceoffset im Prozessabbild zurueck.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#Device._get_producttype">_get_producttype</a></td>
<td>Gibt den Produkttypen des device zurueck.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#Device.autorefresh">autorefresh</a></td>
<td>Registriert dieses Device fuer die automatische Synchronisierung.</td>
</tr><tr>
@@ -542,7 +548,29 @@ Device._devconfigure</h3>
<b>_devconfigure</b>(<i></i>)
<p>
Funktion zum ueberschreiben von abgeleiteten Klassen.
</p><a NAME="Device.autorefresh" ID="Device.autorefresh"></a>
</p><a NAME="Device._get_offset" ID="Device._get_offset"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Device._get_offset</h3>
<b>_get_offset</b>(<i></i>)
<p>
Gibt den Deviceoffset im Prozessabbild zurueck.
</p><dl>
<dt>Returns:</dt>
<dd>
Deviceoffset
</dd>
</dl><a NAME="Device._get_producttype" ID="Device._get_producttype"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Device._get_producttype</h3>
<b>_get_producttype</b>(<i></i>)
<p>
Gibt den Produkttypen des device zurueck.
</p><dl>
<dt>Returns:</dt>
<dd>
Deviceprodukttyp
</dd>
</dl><a NAME="Device.autorefresh" ID="Device.autorefresh"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Device.autorefresh</h3>
<b>autorefresh</b>(<i>activate=True</i>)

View File

@@ -141,6 +141,9 @@ Methods</h3>
<td><a style="color:#0000FF" href="#IOBase.__bool__">__bool__</a></td>
<td><class 'bool'>-Wert der Klasse.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IOBase.__len__">__len__</a></td>
<td>Gibt die Bytelaenge des IO zurueck.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IOBase.__str__">__str__</a></td>
<td><class 'str'>-Wert der Klasse.</td>
</tr><tr>
@@ -153,12 +156,6 @@ Methods</h3>
<td><a style="color:#0000FF" href="#IOBase._get_iotype">_get_iotype</a></td>
<td>Gibt io.Type zurueck.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IOBase._get_length">_get_length</a></td>
<td>Gibt die Bytelaenge des IO zurueck.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IOBase._get_name">_get_name</a></td>
<td>Gibt den Namen des IOs zurueck.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IOBase.get_defaultvalue">get_defaultvalue</a></td>
<td>Gibt die Defaultvalue von piCtory zurueck.</td>
</tr><tr>
@@ -220,6 +217,17 @@ IOBase.__bool__</h3>
<dd>
<class 'bool'> Nur False wenn False oder 0 sonst True
</dd>
</dl><a NAME="IOBase.__len__" ID="IOBase.__len__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IOBase.__len__</h3>
<b>__len__</b>(<i></i>)
<p>
Gibt die Bytelaenge des IO zurueck.
</p><dl>
<dt>Returns:</dt>
<dd>
Bytelaenge des IO - 0 bei BITs
</dd>
</dl><a NAME="IOBase.__str__" ID="IOBase.__str__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IOBase.__str__</h3>
@@ -264,28 +272,6 @@ Gibt io.Type zurueck.
<dd>
<class 'int'> io.Type
</dd>
</dl><a NAME="IOBase._get_length" ID="IOBase._get_length"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IOBase._get_length</h3>
<b>_get_length</b>(<i></i>)
<p>
Gibt die Bytelaenge des IO zurueck.
</p><dl>
<dt>Returns:</dt>
<dd>
Bytelaenge des IO
</dd>
</dl><a NAME="IOBase._get_name" ID="IOBase._get_name"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IOBase._get_name</h3>
<b>_get_name</b>(<i></i>)
<p>
Gibt den Namen des IOs zurueck.
</p><dl>
<dt>Returns:</dt>
<dd>
IO Name
</dd>
</dl><a NAME="IOBase.get_defaultvalue" ID="IOBase.get_defaultvalue"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IOBase.get_defaultvalue</h3>
@@ -832,10 +818,10 @@ struct formatierung (1 Zeichen)
</dd><dt><i>kwargs</i></dt>
<dd>
Weitere Parameter:
- bmk: Bezeichnung fuer Output
- bmk: Bezeichnung fuer IO
- bit: Registriert IO als <class 'bool'> am angegebenen Bit im Byte
- byteorder: Byteorder fuer den Input, Standardwert=little
- defaultvalue: Standardwert fuer Output, Standard ist 0
- byteorder: Byteorder fuer IO, Standardwert vom ersetzter IO
- defaultvalue: Standardwert fuer IO, Standard vom ersetzter IO
</dd>
</dl><a NAME="StructIO._get_frm" ID="StructIO._get_frm"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">

View File

@@ -28,11 +28,18 @@ revpimodio2.device.Core.temperatur?4()
revpimodio2.device.Core.unconfdevice?4()
revpimodio2.device.Device._buildio?5(dict_io, iotype)
revpimodio2.device.Device._devconfigure?5()
revpimodio2.device.Device._get_offset?5()
revpimodio2.device.Device._get_producttype?5()
revpimodio2.device.Device.autorefresh?4(activate=True)
revpimodio2.device.Device.get_allios?4()
revpimodio2.device.Device.get_inputs?4()
revpimodio2.device.Device.get_memmories?4()
revpimodio2.device.Device.get_outputs?4()
revpimodio2.device.Device.length?7
revpimodio2.device.Device.name?7
revpimodio2.device.Device.offset?7
revpimodio2.device.Device.position?7
revpimodio2.device.Device.producttype?7
revpimodio2.device.Device.readprocimg?4()
revpimodio2.device.Device.setdefaultvalues?4()
revpimodio2.device.Device.syncoutputs?4()
@@ -70,8 +77,6 @@ revpimodio2.io.DeadIO?1(deadio)
revpimodio2.io.IOBase._get_address?5()
revpimodio2.io.IOBase._get_byteorder?5()
revpimodio2.io.IOBase._get_iotype?5()
revpimodio2.io.IOBase._get_length?5()
revpimodio2.io.IOBase._get_name?5()
revpimodio2.io.IOBase.address?7
revpimodio2.io.IOBase.byteorder?7
revpimodio2.io.IOBase.defaultvalue?7

View File

@@ -37,15 +37,15 @@ class DeviceList(object):
# Reinigungsjobs
dev_del.autorefresh(False)
for io in dev_del:
delattr(dev_del._modio.io, io.name)
delattr(dev_del._modio.io, io._name)
del self.__dict_position[dev_del.position]
del self.__dict_position[dev_del._position]
object.__delattr__(self, key)
def __delitem__(self, key):
"""Entfernt Device an angegebener Position.
@param key Deviceposition zum entfernen"""
self.__delattr__(self[key].name)
self.__delattr__(self[key]._name)
def __getitem__(self, key):
"""Gibt angegebenes Device zurueck.
@@ -75,7 +75,7 @@ class DeviceList(object):
@param value Attributobjekt"""
if issubclass(type(value), Device):
object.__setattr__(self, key, value)
self.__dict_position[value.position] = value
self.__dict_position[value._position] = value
elif key == "_DeviceList__dict_position":
object.__setattr__(self, key, value)
@@ -106,10 +106,10 @@ class Device(object):
self._selfupdate = False
# Wertzuweisung aus dict_device
self.name = dict_device.pop("name")
self.offset = int(dict_device.pop("offset"))
self.position = int(dict_device.pop("position"))
self.producttype = int(dict_device.pop("productType"))
self._name = dict_device.pop("name")
self._offset = int(dict_device.pop("offset"))
self._position = int(dict_device.pop("position"))
self._producttype = int(dict_device.pop("productType"))
# IOM-Objekte erstellen und Adressen in SLCs speichern
if simulator:
@@ -127,15 +127,18 @@ class Device(object):
)
# SLCs mit offset berechnen
self._slc_devoff = slice(self.offset, self.offset + self._length)
self._slc_devoff = slice(self._offset, self._offset + self._length)
self._slc_inpoff = slice(
self._slc_inp.start + self.offset, self._slc_inp.stop + self.offset
self._slc_inp.start + self._offset,
self._slc_inp.stop + self._offset
)
self._slc_outoff = slice(
self._slc_out.start + self.offset, self._slc_out.stop + self.offset
self._slc_out.start + self._offset,
self._slc_out.stop + self._offset
)
self._slc_memoff = slice(
self._slc_mem.start + self.offset, self._slc_mem.stop + self.offset
self._slc_mem.start + self._offset,
self._slc_mem.stop + self._offset
)
# Neues bytearray und Kopie für mainloop anlegen
@@ -172,7 +175,7 @@ class Device(object):
def __int__(self):
"""Gibt die Positon im RevPi Bus zurueck.
@return Positionsnummer"""
return self.position
return self._position
def __iter__(self):
"""Gibt Iterator aller IOs zurueck.
@@ -189,7 +192,7 @@ class Device(object):
def __str__(self):
"""Gibt den Namen des Devices zurueck.
@return Devicename"""
return self.name
return self._name
def _buildio(self, dict_io, iotype):
"""Erstellt aus der piCtory-Liste die IOs fuer dieses Device.
@@ -206,7 +209,7 @@ class Device(object):
for key in sorted(dict_io, key=lambda x: int(x)):
# Neuen IO anlegen
if bool(dict_io[key][7]) or self.producttype == 95:
if bool(dict_io[key][7]) or self._producttype == 95:
# Bei Bitwerten oder Core RevPiIOBase verwenden
io_new = iomodule.IOBase(
self, dict_io[key], iotype, "little", False
@@ -216,7 +219,7 @@ class Device(object):
self, dict_io[key],
iotype,
"little",
self.producttype == 103
self._producttype == 103
)
# IO registrieren
@@ -236,6 +239,16 @@ class Device(object):
"""Funktion zum ueberschreiben von abgeleiteten Klassen."""
pass
def _get_offset(self):
"""Gibt den Deviceoffset im Prozessabbild zurueck.
@return Deviceoffset"""
return self._offset
def _get_producttype(self):
"""Gibt den Produkttypen des device zurueck.
@return Deviceprodukttyp"""
return self._producttype
def autorefresh(self, activate=True):
"""Registriert dieses Device fuer die automatische Synchronisierung.
@param activate Default True fuegt Device zur Synchronisierung hinzu"""
@@ -336,6 +349,12 @@ class Device(object):
RevPiModIO.writeprocimg()"""
self._modio.writeprocimg(self)
length = property(__len__)
name = property(__str__)
offset = property(_get_offset)
position = property(__int__)
producttype = property(_get_producttype)
class Core(Device):
@@ -380,11 +399,11 @@ class Core(Device):
# Für RS485 errors defaults laden sollte procimg NULL sein
if self._ioerrorlimit1 is not None:
self.__lst_io[self._ioerrorlimit1].set_value(
self.__lst_io[self._ioerrorlimit1].defaultvalue
self.__lst_io[self._ioerrorlimit1]._defaultvalue
)
if self._ioerrorlimit2 is not None:
self.__lst_io[self._ioerrorlimit2].set_value(
self.__lst_io[self._ioerrorlimit2].defaultvalue
self.__lst_io[self._ioerrorlimit2]._defaultvalue
)
# RS485 errors schreiben
self._modio.writeprocimg(self)

View File

@@ -127,8 +127,19 @@ class IOList(object):
def __private_replace_oldio_with_newio(self, io):
"""Ersetzt bestehende IOs durch den neu Registrierten.
@param io Neuer IO der eingefuegt werden soll"""
int_length = 1 if io._length == 0 else io._length
for i in range(io.address, io.address + int_length):
# Scanbereich festlegen
if io._bitaddress < 0:
scan_start = io.address
scan_stop = scan_start + (1 if io._length == 0 else io._length)
else:
scan_start = io._parentio_address
scan_stop = scan_start + io._parentio_length
# Defaultvalue über mehrere Bytes sammeln
calc_defaultvalue = b''
for i in range(scan_start, scan_stop):
for oldio in self.__dict_iobyte[i]:
if type(oldio) == StructIO:
@@ -151,26 +162,42 @@ class IOList(object):
# IOs im Speicherbereich des neuen IO merken
if io._bitaddress >= 0:
# ios für ref bei bitaddress speichern
self.__dict_iorefname[oldio.name] = DeadIO(oldio)
self.__dict_iorefname[oldio._name] = DeadIO(oldio)
else:
# Defaultwert berechnen
oldio.byteorder = io._byteorder
if io._byteorder == "little":
calc_defaultvalue += oldio._defaultvalue
else:
calc_defaultvalue = \
oldio._defaultvalue + calc_defaultvalue
# ios aus listen entfernen
delattr(self, oldio.name)
delattr(self, oldio._name)
if io._defaultvalue is None:
if io._bitaddress < 0:
io._defaultvalue = calc_defaultvalue
else:
io._defaultvalue = bool(io._parentio_defaultvalue[
io._parentio_address - io.address
] & (1 << io._bitaddress))
def _private_register_new_io_object(self, new_io):
"""Registriert neues IO Objekt unabhaenging von __setattr__.
@param new_io Neues IO Objekt"""
if issubclass(type(new_io), IOBase):
if hasattr(self, new_io.name):
if hasattr(self, new_io._name):
raise AttributeError(
"attribute {} already exists - can not set io".format(
new_io.name
new_io._name
)
)
if type(new_io) is StructIO:
self.__private_replace_oldio_with_newio(new_io)
object.__setattr__(self, new_io.name, new_io)
object.__setattr__(self, new_io._name, new_io)
# Bytedict für Adresszugriff anpassen
if new_io._bitaddress < 0:
@@ -251,17 +278,18 @@ class IOBase(object):
self._defaultvalue = int(valuelist[1]).to_bytes(
self._length, byteorder=self._byteorder
)
else:
elif valuelist[1] is None and type(self) == StructIO:
self._defaultvalue = None
elif type(valuelist[1]) == bytes:
# Defaultvalue direkt von bytes übernehmen
if type(valuelist[1]) == bytes:
if len(valuelist[1]) != self._length:
if len(valuelist[1]) == self._length:
self._defaultvalue = valuelist[1]
else:
raise ValueError(
"given bytes for default value must have a length "
"of {} but {} was given"
"".format(self._length, len(valuelist[1]))
)
else:
self._defaultvalue = valuelist[1]
else:
self._defaultvalue = bytes(self._length)
@@ -271,7 +299,8 @@ class IOBase(object):
self._slc_address = slice(
int_startaddress, int_startaddress + 1
)
self._defaultvalue = bool(int(valuelist[1]))
self._defaultvalue = None if valuelist[1] is None \
else bool(int(valuelist[1]))
def __bool__(self):
"""<class 'bool'>-Wert der Klasse.
@@ -285,6 +314,11 @@ class IOBase(object):
else:
return bool(self._parentdevice._ba_devdata[self._slc_address])
def __len__(self):
"""Gibt die Bytelaenge des IO zurueck.
@return Bytelaenge des IO - 0 bei BITs"""
return 0 if self._bitaddress > 0 else self._length
def __str__(self):
"""<class 'str'>-Wert der Klasse.
@return Namen des IOs"""
@@ -293,7 +327,7 @@ class IOBase(object):
def _get_address(self):
"""Gibt die absolute Byteadresse im Prozessabbild zurueck.
@return Absolute Byteadresse"""
return self._parentdevice.offset + self._slc_address.start
return self._parentdevice._offset + self._slc_address.start
def _get_byteorder(self):
"""Gibt konfigurierte Byteorder zurueck.
@@ -305,16 +339,6 @@ class IOBase(object):
@return <class 'int'> io.Type"""
return self._iotype
def _get_length(self):
"""Gibt die Bytelaenge des IO zurueck.
@return Bytelaenge des IO"""
return self._length
def _get_name(self):
"""Gibt den Namen des IOs zurueck.
@return IO Name"""
return self._name
def get_defaultvalue(self):
"""Gibt die Defaultvalue von piCtory zurueck.
@return Defaultvalue als <class 'byte'> oder <class 'bool'>"""
@@ -404,6 +428,10 @@ class IOBase(object):
"this function can be used for ios on gatway or virtual "
"devices only"
)
if type(self) == StructIO:
raise RuntimeError(
"this io is already a replaced one"
)
# StructIO erzeugen
io_new = StructIO(
@@ -555,7 +583,7 @@ class IOBase(object):
raise RuntimeError(
"autorefresh is not activated for device '{}|{}' - there "
"will never be new data".format(
self._parentdevice.position, self._parentdevice.name
self._parentdevice._position, self._parentdevice._name
)
)
@@ -612,8 +640,8 @@ class IOBase(object):
address = property(_get_address)
byteorder = property(_get_byteorder)
defaultvalue = property(get_defaultvalue)
length = property(_get_length)
name = property(_get_name)
length = property(__len__)
name = property(__str__)
type = property(_get_iotype)
value = property(get_value, set_value)
@@ -649,6 +677,7 @@ class IntIO(IOBase):
@param value <class 'str'> 'little' or 'big'"""
if not (value == "little" or value == "big"):
raise ValueError("byteorder must be 'little' or 'big'")
if self._byteorder != value:
self._byteorder = value
self._defaultvalue = self._defaultvalue[::-1]
@@ -713,29 +742,44 @@ class StructIO(IOBase):
@param name Name des neuen IO
@param frm struct formatierung (1 Zeichen)
@param kwargs Weitere Parameter:
- bmk: Bezeichnung fuer Output
- bmk: Bezeichnung fuer IO
- bit: Registriert IO als <class 'bool'> am angegebenen Bit im Byte
- byteorder: Byteorder fuer den Input, Standardwert=little
- defaultvalue: Standardwert fuer Output, Standard ist 0
- byteorder: Byteorder fuer IO, Standardwert vom ersetzter IO
- defaultvalue: Standardwert fuer IO, Standard vom ersetzter IO
"""
if len(frm) == 1:
# Byteorder prüfen und übernehmen
byteorder = kwargs.get("byteorder", "little")
byteorder = kwargs.get("byteorder", parentio._byteorder)
if not (byteorder == "little" or byteorder == "big"):
raise ValueError("byteorder must be 'little' or 'big'")
bofrm = "<" if byteorder == "little" else ">"
bitaddress = "" if frm != "?" else str(kwargs.get("bit", 0))
if bitaddress == "" or (0 <= int(bitaddress) < 8):
if frm == "?":
bitaddress = kwargs.get("bit", 0)
max_bits = parentio._length * 8
if not (0 <= bitaddress < max_bits):
raise AttributeError(
"bitaddress must be a value between 0 and {}"
"".format(max_bits - 1)
)
bitlength = 1
bitlength = "1" if bitaddress.isdigit() else \
struct.calcsize(bofrm + frm) * 8
# Bitweise Ersetzung erfordert diese Informationen zusätzlich
if parentio._byteorder == byteorder:
self._parentio_defaultvalue = parentio._defaultvalue
else:
self._parentio_defaultvalue = parentio._defaultvalue[::-1]
self._parentio_address = parentio.address
self._parentio_length = parentio._length
else:
bitaddress = ""
bitlength = struct.calcsize(bofrm + frm) * 8
# [name,default,anzbits,adressbyte,export,adressid,bmk,bitaddress]
valuelist = [
name,
kwargs.get("defaultvalue", 0),
kwargs.get("defaultvalue", None),
bitlength,
parentio._slc_address.start,
False,
@@ -743,11 +787,6 @@ class StructIO(IOBase):
kwargs.get("bmk", ""),
bitaddress
]
else:
raise AttributeError(
"bitaddress must be a value between 0 and 7"
)
else:
raise AttributeError("parameter frm has to be a single sign")

View File

@@ -177,17 +177,17 @@ class RevPiModIO(object):
if dev_new is not None:
# Offset prüfen, muss mit Länge übereinstimmen
if self._length < dev_new.offset:
self._length = dev_new.offset
if self._length < dev_new._offset:
self._length = dev_new._offset
self._length += dev_new._length
# Auf doppelte Namen prüfen, da piCtory dies zulässt
if hasattr(self.device, dev_new.name):
err_names.append(dev_new.name)
if hasattr(self.device, dev_new._name):
err_names.append(dev_new._name)
# DeviceList für direkten Zugriff aufbauen
setattr(self.device, dev_new.name, dev_new)
setattr(self.device, dev_new._name, dev_new)
# Namenszugriff zerstören, wenn doppelte Namen vorhanden sind
for errdev in err_names:
@@ -561,13 +561,13 @@ class RevPiModIO(object):
or regfunc[1] == RISING and boolor \
or regfunc[1] == FALLING and not boolor:
lst_fire.append(
(regfunc, io_event.name, io_event.value)
(regfunc, io_event._name, io_event.value)
)
else:
for regfunc in dev._dict_events[io_event]:
lst_fire.append(
(regfunc, io_event.name, io_event.value)
(regfunc, io_event._name, io_event.value)
)
# Nach Verarbeitung aller IOs die Bytes kopieren
@@ -619,7 +619,7 @@ class RevPiModIO(object):
if dev._selfupdate:
raise RuntimeError(
"can not read process image, while device '{}|{}'"
"is in autorefresh mode".format(dev.position, dev.name)
"is in autorefresh mode".format(dev._position, dev._name)
)
mylist = [dev]
@@ -694,7 +694,7 @@ class RevPiModIO(object):
if dev._selfupdate:
raise RuntimeError(
"can not sync process image, while device '{}|{}'"
"is in autorefresh mode".format(dev.position, dev.name)
"is in autorefresh mode".format(dev._position, dev._name)
)
mylist = [dev]
@@ -737,7 +737,7 @@ class RevPiModIO(object):
if dev._selfupdate:
raise RuntimeError(
"can not write process image, while device '{}|{}'"
"is in autorefresh mode".format(dev.position, dev.name)
"is in autorefresh mode".format(dev._position, dev._name)
)
mylist = [dev]