diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index 3c2bb08..3872073 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -358,7 +358,7 @@ object

Class Attributes

- +
None
length
name
offset
position
producttype

Class Methods

@@ -396,6 +396,12 @@ Methods _devconfigure Funktion zum ueberschreiben von abgeleiteten Klassen. +_get_offset +Gibt den Deviceoffset im Prozessabbild zurueck. + +_get_producttype +Gibt den Produkttypen des device zurueck. + autorefresh Registriert dieses Device fuer die automatische Synchronisierung. @@ -542,7 +548,29 @@ Device._devconfigure _devconfigure()

Funktion zum ueberschreiben von abgeleiteten Klassen. -

+

+

+Device._get_offset

+_get_offset() +

+Gibt den Deviceoffset im Prozessabbild zurueck. +

+
Returns:
+
+Deviceoffset +
+
+

+Device._get_producttype

+_get_producttype() +

+Gibt den Produkttypen des device zurueck. +

+
Returns:
+
+Deviceprodukttyp +
+

Device.autorefresh

autorefresh(activate=True) diff --git a/doc/revpimodio2.io.html b/doc/revpimodio2.io.html index 6a4d96d..2b9c16f 100644 --- a/doc/revpimodio2.io.html +++ b/doc/revpimodio2.io.html @@ -141,6 +141,9 @@ Methods __bool__ -Wert der Klasse. +__len__ +Gibt die Bytelaenge des IO zurueck. + __str__ -Wert der Klasse. @@ -153,12 +156,6 @@ Methods _get_iotype Gibt io.Type zurueck. -_get_length -Gibt die Bytelaenge des IO zurueck. - -_get_name -Gibt den Namen des IOs zurueck. - get_defaultvalue Gibt die Defaultvalue von piCtory zurueck. @@ -220,6 +217,17 @@ IOBase.__bool__
Nur False wenn False oder 0 sonst True
+ +

+IOBase.__len__

+__len__() +

+Gibt die Bytelaenge des IO zurueck. +

+
Returns:
+
+Bytelaenge des IO - 0 bei BITs +

IOBase.__str__

@@ -264,28 +272,6 @@ Gibt io.Type zurueck.
io.Type
- -

-IOBase._get_length

-_get_length() -

-Gibt die Bytelaenge des IO zurueck. -

-
Returns:
-
-Bytelaenge des IO -
-
-

-IOBase._get_name

-_get_name() -

-Gibt den Namen des IOs zurueck. -

-
Returns:
-
-IO Name -

IOBase.get_defaultvalue

@@ -832,10 +818,10 @@ struct formatierung (1 Zeichen)
kwargs
Weitere Parameter: - - bmk: Bezeichnung fuer Output + - bmk: Bezeichnung fuer IO - bit: Registriert IO als 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

diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index 49b6e46..6c11d5c 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -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 diff --git a/revpimodio2/device.py b/revpimodio2/device.py index c75d664..3433812 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -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) diff --git a/revpimodio2/io.py b/revpimodio2/io.py index 617ddfd..33769ea 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -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,19 +278,20 @@ 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: - 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] + if len(valuelist[1]) == self._length: + self._defaultvalue = valuelist[1] else: - self._defaultvalue = bytes(self._length) + raise ValueError( + "given bytes for default value must have a length " + "of {} but {} was given" + "".format(self._length, len(valuelist[1])) + ) + else: + self._defaultvalue = bytes(self._length) else: # Höhere Bits als 7 auf nächste Bytes umbrechen @@ -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): """-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): """-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 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 oder """ @@ -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,8 +677,9 @@ class IntIO(IOBase): @param value 'little' or 'big'""" if not (value == "little" or value == "big"): raise ValueError("byteorder must be 'little' or 'big'") - self._byteorder = value - self._defaultvalue = self._defaultvalue[::-1] + if self._byteorder != value: + self._byteorder = value + self._defaultvalue = self._defaultvalue[::-1] def _set_signed(self, value): """Left fest, ob der Wert Vorzeichenbehaftet behandelt werden soll. @@ -713,41 +742,51 @@ 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 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): - - bitlength = "1" if bitaddress.isdigit() else \ - struct.calcsize(bofrm + frm) * 8 - - # [name,default,anzbits,adressbyte,export,adressid,bmk,bitaddress] - valuelist = [ - name, - kwargs.get("defaultvalue", 0), - bitlength, - parentio._slc_address.start, - False, - str(parentio._slc_address.start).rjust(4, "0"), - kwargs.get("bmk", ""), - bitaddress - ] + 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 + # 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: - raise AttributeError( - "bitaddress must be a value between 0 and 7" - ) + bitaddress = "" + bitlength = struct.calcsize(bofrm + frm) * 8 + + # [name,default,anzbits,adressbyte,export,adressid,bmk,bitaddress] + valuelist = [ + name, + kwargs.get("defaultvalue", None), + bitlength, + parentio._slc_address.start, + False, + str(parentio._slc_address.start).rjust(4, "0"), + kwargs.get("bmk", ""), + bitaddress + ] else: raise AttributeError("parameter frm has to be a single sign") diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index cd751c7..c904153 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -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]