class DPTXlator8BitEncAbsValue(DPTXlatorBase): """ DPTXlator class for 8-Bit-Absolute-Encoding-Value (N8) KNX Datapoint Type - 1 Byte: NNNNNNNN - N: Byte [0:255] . """ DPT_Generic = DPT("20.xxx", "Generic", (0, 255)) DPT_OccMode = DPT("20.003", "Occupancy mode", ("occupied", "standby", "not occupied")) def __init__(self, dptId): super(DPTXlator8BitEncAbsValue, self).__init__(dptId, 1) def checkData(self, data): if not 0x00 <= data <= 0xff: raise DPTXlatorValueError("data %s not in (0x00, 0xff)" % hex(data)) def checkValue(self, value): if self.dpt is self.DPT_Generic: if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("value not in range %s" % repr(self._dpt.limits)) elif value not in self._dpt.limits: raise DPTXlatorValueError("value not in %r" % repr(self._dpt.limits)) def dataToValue(self, data): if self.dpt is self.DPT_Generic: value = data else: value = self._dpt.limits[data] #logger.debug("DPTXlator8BitEncAbsValue.dataToValue(): value=%d" % value) return value def valueToData(self, value): #logger.debug("DPTXlator8BitEncAbsValue.valueToData(): value=%d" % value) self.checkValue(value) if self.dpt is self.DPT_Generic: data = value else: data = self._dpt.limits.index(value) #logger.debug("DPTXlator8BitEncAbsValue.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">B", data)) def frameToData(self, frame): data = struct.unpack(">B", frame)[0] return data
class DPTXlator8BitSigned(DPTXlatorBase): """ DPTXlator class for 8-Bit-Signed (V8) KNX Datapoint Type - 1 Byte: VVVVVVVV - V: Byte [-128:127] . """ DPT_Generic = DPT("6.xxx", "Generic", (-128, 127)) DPT_Percent_V8 = DPT("6.001", "Percent (8 bit)", (-128, 127), "%") DPT_Value_1_Count = DPT("6.010", "Signed count", (-128, 127), "pulses") #DPT_Status_Mode3 = DPT("6.020", "Status mode 3", (, )) def __init__(self, dptId): super(DPTXlator8BitSigned, self).__init__(dptId, 1) def checkData(self, data): if not 0x00 <= data <= 0xff: raise DPTXlatorValueError("data %s not in (0x00, 0xff)" % hex(data)) def checkValue(self, value): if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): if data >= 0x80: value = -((data - 1) ^ 0xff) # invert twos complement else: value = data #logger.debug("DPTXlator8BitSigned._toValue(): value=%d" % value) return value def valueToData(self, value): if value < 0: value = (abs(value) ^ 0xff) + 1 # twos complement data = value #logger.debug("DPTXlator8BitSigned.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">B", data)) def frameToData(self, frame): data = struct.unpack(">B", frame)[0] return data
class DPTXlatorTime(DPTXlatorBase): """ DPTXlator class for Time (N3U5r2U6r2U6) KNX Datapoint Type - 3 Byte: NNNHHHHH rrMMMMMM rrSSSSSS - N: Week day [0:7] - H: Hour [0:23] - M: Minute [0:59] - S: Second [0:59] - r: reserved (0) . """ DPT_Generic = DPT("10.xxx", "Generic", (0, 16777215)) DPT_TimeOfDay = DPT("10.001", "Time of day", ((0, 0, 0, 0), (7, 23, 59, 59))) def __init__(self, dptId): super(DPTXlatorTime, self).__init__(dptId, 3) def checkData(self, data): if not 0x000000 <= data <= 0xffffff: raise DPTXlatorValueError("data %s not in (0x000000, 0xffffff)" % hex(data)) def checkValue(self, value): for index in range(4): if not self._dpt.limits[0][index] <= value[ index] <= self._dpt.limits[1][index]: raise DPTXlatorValueError("value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): wDay = (data >> 21) & 0x07 hour = (data >> 16) & 0x1f min_ = (data >> 8) & 0x3f sec = data & 0x3f value = (wDay, hour, min_, sec) #logger.debug("DPTXlatorTime._toValue(): value=%d" % value) return value def valueToData(self, value): # add from string and from int (sec)? wDay = value[0] hour = value[1] min_ = value[2] sec = value[3] data = wDay << 21 | hour << 16 | min_ << 8 | sec #logger.debug("DPTXlatorTime.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): data = [(data >> shift) & 0xff for shift in range(16, -1, -8)] return bytearray(struct.pack(">3B", *data)) def frameToData(self, frame): data = struct.unpack(">3B", frame) data = data[0] << 16 | data[1] << 8 | data[2] return data @property def weekDay(self): wDay = self.value[0] hour = self.value[1] min_ = self.value[2] sec = self.value[3] if wDay == 0: format_ = "No day" # "No day, %H:%M:%S" else: format_ = "%a" s = time.strftime(format_, (0, 0, 0, hour, min_, sec, wDay - 1, 0, 0)) return s @property def hour(self): return self.value[1] @property def minute(self): return self.value[2] @property def second(self): return self.value[3]
class DPTXlatorString(DPTXlatorBase): """ DPTXlator class for String (A112) KNX Datapoint Type - 14 Byte: AAAAAAAA ... AAAAAAAA - A: Char [0:255] . """ DPT_Generic = DPT("16.xxx", "Generic", (0, 5192296858534827628530496329220095)) DPT_String_ASCII = DPT("16.000", "String", (14 * (0, ), 14 * (127, ))) DPT_String_8859_1 = DPT("16.001", "String", (14 * (0, ), 14 * (255, ))) def __init__(self, dptId): super(DPTXlatorString, self).__init__(dptId, 14) def checkData(self, data): if not 0x0000000000000000000000000000 <= data <= 0xffffffffffffffffffffffffffff: raise DPTXlatorValueError( "data %s not in (0x0000000000000000000000000000, 0xffffffffffffffffffffffffffff)" % hex(data)) def checkValue(self, value): for index in range(14): if not self._dpt.limits[0][index] <= value[ index] <= self._dpt.limits[1][index]: raise DPTXlatorValueError("value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): value = tuple( [int((data >> shift) & 0xff) for shift in range(104, -1, -8)]) #logger.debug("DPTXlatorString._toValue(): value=%d" % value) return value def valueToData(self, value): data = 0x00 for shift in range(104, -1, -8): data |= value[13 - shift // 8] << shift #logger.debug("DPTXlatorString.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">14B", *self.dataToValue(data))) def frameToData(self, frame): value = struct.unpack(">14B", frame) data = self.valueToData(value) return data @property def day(self): return self.value[0] @property def month(self): return self.value[1] @property def year(self): return self.value[2]
class DPTXlatorBoolean(DPTXlatorBase): """ DPTXlator class for 1-Bit (b0) KNX Datapoint Type - 1 Byte: 00000000B - B: Binary [0, 1] . """ DPT_Generic = DPT("1.xxx", "Generic", (0, 1)) DPT_Switch = DPT("1.001", "Switch", ("Off", "On")) DPT_Bool = DPT("1.002", "Boolean", (False, True)) DPT_Enable = DPT("1.003", "Enable", ("Disable", "Enable")) DPT_Ramp = DPT("1.004", "Ramp", ("No ramp", "Ramp")) DPT_Alarm = DPT("1.005", "Alarm", ("No alarm", "Alarm")) DPT_BinaryValue = DPT("1.006", "Binary value", ("Low", "High")) DPT_Step = DPT("1.007", "Step", ("Decrease", "Increase")) DPT_UpDown = DPT("1.008", "Up/Down", ("Up", "Down")) DPT_OpenClose = DPT("1.009", "Open/Close", ("Open", "Close")) DPT_Start = DPT("1.010", "Start", ("Stop", "Start")) DPT_State = DPT("1.011", "State", ("Inactive", "Active")) DPT_Invert = DPT("1.012", "Invert", ("Not inverted", "Inverted")) DPT_DimSendStyle = DPT("1.013", "Dimmer send-style", ("Start/stop", "Cyclically")) DPT_InputSource = DPT("1.014", "Input source", ("Fixed", "Calculated")) DPT_Reset = DPT("1.015", "Reset", ("No action", "Reset")) DPT_Ack = DPT("1.016", "Acknowledge", ("No action", "Acknowledge")) DPT_Trigger = DPT("1.017", "Trigger", ("Trigger", "Trigger")) DPT_Occupancy = DPT("1.018", "Occupancy", ("Not occupied", "Occupied")) DPT_Window_Door = DPT("1.019", "Window/Door", ("Closed", "Open")) DPT_LogicalFunction = DPT("1.021", "Logical function", ("OR", "AND")) DPT_Scene_AB = DPT("1.022", "Scene A/B", ("Scene A", "Scene B")) DPT_ShutterBlinds_Mode = DPT( "1.023", "Shutter/Blinds mode", ("Only move Up/Down", "Move Up/Down + StepStop")) def __init__(self, dptId): super(DPTXlatorBoolean, self).__init__(dptId, 0) def checkData(self, data): if data not in (0x00, 0x01): try: raise DPTXlatorValueError("data %s not in (0x00, 0x01)" % hex(data)) except TypeError: raise DPTXlatorValueError("data not in (0x00, 0x01)") def checkValue(self, value): if value not in self._dpt.limits and value not in self.DPT_Generic.limits: raise DPTXlatorValueError("value %s not in %s" % (value, str(self._dpt.limits))) def dataToValue(self, data): #data = int(data, 16)#TODO LUCANO ADDED value = self._dpt.limits[data] #logger.debug("DPTXlatorBoolean.dataToValue(): value=%d" % value) return value def valueToData(self, value): #logger.debug("DPTXlatorBoolean.valueToData(): value=%d" % value) self.checkValue(value) try: data = self._dpt.limits.index(value) except ValueError: raise ValueError("Index not in tuple", self._dpt.limits, value) #logger.debug("DPTXlatorBoolean.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">B", data)) def frameToData(self, frame): data = struct.unpack(">B", frame)[0] return data
class DPTXlator4ByteSigned(DPTXlatorBase): """ DPTXlator class for 4-Byte-Signed (V32) KNX Datapoint Type - 4 Byte Signed: VVVVVVVV VVVVVVVV VVVVVVVV VVVVVVVV - V: Bytes [-2147483648:2147483647] . """ DPT_Generic = DPT("13.xxx", "Generic", (-2147483648, 2147483647)) DPT_Value_4_Count = DPT("13.001", "Signed count", (-2147483648, 2147483647), "pulses") DPT_Value_FlowRate_m3h = DPT("13.001", "Flow rate", (-214748.3648, 214748.3647), "m³/h") DPT_ActiveEnergy = DPT("13.010", "Active energy", (-214748.3648, 214748.3647), "W.h") DPT_ApparentEnergy = DPT("13.011", "Apparent energy", (-214748.3648, 214748.3647), "VA.h") DPT_ReactiveEnergy = DPT("13.012", "Reactive energy", (-214748.3648, 214748.3647), "VAR.h") DPT_ActiveEnergy_kWh = DPT("13.013", "Active energy (kWh)", (-214748.3648, 214748.3647), "kW.h") DPT_ApparentEnergy_kVAh = DPT("13.014", "Apparent energy (kVAh)", (-214748.3648, 214748.3647), "kVA.h") DPT_ReactiveEnergy_KVARh = DPT("13.015", "Reactive energy (kVARh)", (-214748.3648, 214748.3647), "kVAR.h") DPT_LongDeltaTimeSec = DPT("13.100", "Long delta time", (-214748.3648, 214748.3647), "s") def __init__(self, dptId): super(DPTXlator4ByteSigned, self).__init__(dptId, 4) def checkData(self, data): if not 0x00000000 <= data <= 0xffffffff: raise DPTXlatorValueError( "data %s not in (0x00000000, 0xffffffff)" % hex(data)) def checkValue(self, value): if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("Value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): if data >= 0x80000000: data = -((data - 1) ^ 0xffffffff) # invert twos complement else: data = data if self._dpt is self.DPT_Value_FlowRate_m3h: value = data / 10000. else: value = data #logger.debug("DPTXlator4ByteSigned._toValue(): value=%d" % value) return value def valueToData(self, value): if value < 0: value = (abs(value) ^ 0xffffffff) + 1 # twos complement if self._dpt is self.DPT_Value_FlowRate_m3h: data = int(round(value * 10000.)) else: data = value #logger.debug("DPTXlator4ByteSigned.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">L", data)) def frameToData(self, frame): data = struct.unpack(">L", frame)[0] return data
class DPTXlator2ByteUnsigned(DPTXlatorBase): """ DPTXlator class for 2-Byte-Unsigned (U16) KNX Datapoint Type - 2 Byte Unsigned: UUUUUUUU UUUUUUUU - U: Bytes [0:65535] . """ DPT_Generic = DPT("7.xxx", "Generic", (0, 65535)) DPT_Value_2_Ucount = DPT("7.001", "Unsigned count", (0, 65535), "pulses") DPT_TimePeriodMsec = DPT("7.002", "Time period (resol. 1ms)", (0, 65535), "ms") DPT_TimePeriod10Msec = DPT("7.003", "Time period (resol. 10ms)", (0, 655350), "ms") DPT_TimePeriod100Msec = DPT("7.004", "Time period (resol. 100ms)", (0, 6553500), "ms") DPT_TimePeriodSec = DPT("7.005", "Time period (resol. 1s)", (0, 65535), "s") DPT_TimePeriodMin = DPT("7.006", "Time period (resol. 1min)", (0, 65535), "min") DPT_TimePeriodHrs = DPT("7.007", "Time period (resol. 1h)", (0, 65535), "h") DPT_PropDataType = DPT("7.010", "Interface object property ID", (0, 65535)) DPT_Length_mm = DPT("7.011", "Length", (0, 65535), "mm") #DPT_UEICurrentmA = DPT("7.012", "Electrical current", (0, 65535), "mA") # Add special meaning for 0 (create Limit object) DPT_Brightness = DPT("7.013", "Brightness", (0, 65535), "lx") def __init__(self, dptId): super(DPTXlator2ByteUnsigned, self).__init__(dptId, 2) def checkData(self, data): if not 0x0000 <= data <= 0xffff: raise DPTXlatorValueError("data %s not in (0x0000, 0xffff)" % hex(data)) def checkValue(self, value): if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("Value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): if self._dpt is self.DPT_TimePeriod10Msec: value = data * 10. elif self._dpt is self.DPT_TimePeriod100Msec: value = data * 100. else: value = data #logger.debug("DPTXlator2ByteUnsigned._toValue(): value=%d" % value) return value def valueToData(self, value): if self._dpt is self.DPT_TimePeriod10Msec: data = int(round(value / 10.)) elif self._dpt is self.DPT_TimePeriod100Msec: data = int(round(value / 100.)) else: data = value #logger.debug("DPTXlator2ByteUnsigned.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">H", data)) def frameToData(self, frame): data = struct.unpack(">H", frame)[0] return data
class DPTXlator2ByteSigned(DPTXlatorBase): """ DPTXlator class for 2-Byte-Unsigned (V16) KNX Datapoint Type - 2 Byte Signed: VVVVVVVV VVVVVVVV - V: Bytes [-32768:32767] . """ DPT_Generic = DPT("8.xxx", "Generic", (-32768, 32767)) DPT_Value_2_Count = DPT("8.001", "Signed count", (-32768, 32767), "pulses") DPT_DeltaTimeMsec = DPT("8.002", "Delta time (ms)", (-32768, 32767), "ms") DPT_DeltaTime10Msec = DPT("8.003", "Delta time (10ms)", (-327680, 327670), "ms") DPT_DeltaTime100Msec = DPT("8.004", "Delta time (100ms)", (-3276800, 3276700), "ms") DPT_DeltaTimeSec = DPT("8.005", "Delta time (s)", (-32768, 32767), "s") DPT_DeltaTimeMin = DPT("8.006", "Delta time (min)", (-32768, 32767), "min") DPT_DeltaTimeHrs = DPT("8.007", "Delta time (h)", (-32768, 32767), "h") DPT_Percent_V16 = DPT("8.010", "Percent (16 bit)", (-327.68, 327.67), "%") DPT_Rotation_Angle = DPT("8.011", "Rotation angle", (-32768, 32767), "°") def __init__(self, dptId): super(DPTXlator2ByteSigned, self).__init__(dptId, 2) def checkData(self, data): if not 0x0000 <= data <= 0xffff: raise DPTXlatorValueError("data %s not in (0x0000, 0xffff)" % hex(data)) def checkValue(self, value): if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("Value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): if data >= 0x8000: data = -((data - 1) ^ 0xffff) # invert twos complement else: data = data if self._dpt is self.DPT_DeltaTime10Msec: value = data * 10. elif self._dpt is self.DPT_DeltaTime100Msec: value = data * 100. elif self._dpt is self.DPT_Percent_V16: value = data / 100. else: value = data #logger.debug("DPTXlator2ByteSigned._toValue(): value=%d" % value) return value def valueToData(self, value): if value < 0: value = (abs(value) ^ 0xffff) + 1 # twos complement if self._dpt is self.DPT_DeltaTime10Msec: data = int(round(value / 10.)) elif self._dpt is self.DPT_DeltaTime100Msec: data = int(round(value / 100.)) elif self._dpt is self.DPT_Percent_V16: data = int(round(value * 100.)) else: data = value #logger.debug("DPTXlator2ByteSigned.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">H", data)) def frameToData(self, frame): data = struct.unpack(">H", frame)[0] return data
class DPTXlatorDate(DPTXlatorBase): """ DPTXlator class for Date (r3U5r4U4r1U7) KNX Datapoint Type - 3 Byte: rrrDDDDD rrrrMMMM rYYYYYYY - D: Day [1:31] - M: Month [1:12] - Y: Year [0:99] - r: reserved (0) . """ DPT_Generic = DPT("11.xxx", "Generic", (0, 16777215)) DPT_Date = DPT("11.001", "Date", ((1, 1, 1969), (31, 12, 2068))) def __init__(self, dptId): super(DPTXlatorDate, self).__init__(dptId, 3) def checkData(self, data): if not 0x000000 <= data <= 0xffffff: raise DPTXlatorValueError("data %s not in (0x000000, 0xffffff)" % hex(data)) def checkValue(self, value): for index in range(3): if not self._dpt.limits[0][index] <= value[ index] <= self._dpt.limits[1][index]: raise DPTXlatorValueError("value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): day = (data >> 16) & 0x1f month = (data >> 8) & 0x0f year = data & 0x7f if year >= 69: year += 1900 else: year += 2000 value = (day, month, year) #logger.debug("DPTXlatorDate._toValue(): value=%d" % value) return value def valueToData(self, value): day = value[0] month = value[1] year = value[2] if year >= 2000: year -= 2000 else: year -= 1900 data = day << 16 | month << 8 | year #logger.debug("DPTXlatorDate.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): data = [(data >> shift) & 0xff for shift in range(16, -1, -8)] return bytearray(struct.pack(">3B", *data)) def frameToData(self, frame): data = struct.unpack(">3B", frame) data = data[0] << 16 | data[1] << 8 | data[2] return data @property def day(self): return self.value[0] @property def month(self): return self.value[1] @property def year(self): return self.value[2]
class DPTXlator8BitUnsigned(DPTXlatorBase): """ DPTXlator class for 8-Bit-Unsigned (U8) KNX Datapoint Type - 1 Byte: UUUUUUUU - U: Byte [0:255] . """ DPT_Generic = DPT("5.xxx", "Generic", (0, 255)) DPT_Scaling = DPT("5.001", "Scaling", (0, 100), "%") DPT_Angle = DPT("5.003", "Angle", (0, 360), "°") DPT_Percent_U8 = DPT("5.004", "Percent (8 bit)", (0, 255), "%") DPT_DecimalFactor = DPT("5.005", "Decimal factor", (0, 1), "ratio") #DPT_Tariff = DPT("5.006", "Tariff", (0, 254), "ratio") DPT_Value_1_Ucount = DPT("5.010", "Unsigned count", (0, 255), "pulses") def __init__(self, dptId): super(DPTXlator8BitUnsigned, self).__init__(dptId, 1) def checkData(self, data): if not 0x00 <= data <= 0xff: raise DPTXlatorValueError("data %s not in (0x00, 0xff)" % hex(data)) def checkValue(self, value): if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): #if type(data) is str: ##TODO ADDED LUCANO # data = float (data) ##TODO ADDED LUCANO if data is None: print("incorrect data value. Data can not be 'None' ") else: value = data if self._dpt is self.DPT_Scaling: # PERCENTAGE value = value * 100.0 / 255.0 elif self._dpt is self.DPT_Angle: value = value * 360. / 255. elif self._dpt is self.DPT_DecimalFactor: value = value / 255. #logger.debug("DPTXlator8BitUnsigned.dataToValue(): value=%d" % value) return value def valueToData(self, value): if self._dpt is self.DPT_Scaling: data = int(round(value * 255 / 100.)) elif self._dpt is self.DPT_Angle: data = int(round(value * 255 / 360.)) elif self._dpt is self.DPT_DecimalFactor: data = int(round(value * 255)) else: data = value #logger.debug("DPTXlator8BitUnsigned.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): try: return bytearray(struct.pack(">B", data)) except: return def frameToData(self, frame): data = struct.unpack(">B", frame)[0] return data
class DPTXlator3BitControl(DPTXlatorBase): """ DPTXlator class for 3-Bit-Control (b0U3) KNX Datapoint Type This is a composite DPT. - 1 Byte: 0000CSSSS - C: Control bit [0, 1] - S: StepCode [0:7] The _data param of this DPT only handles the stepCode; the control bit is handled by the sub-DPT. @todo: create and use a DPTCompositeConverterBase? @ivar _dpt: sub-DPT @type _dpt: L{DPT} """ DPT_Generic = DPT("3.xxx", "Generic", (-7, 7)) DPT_Control_Dimming = DPT("3.007", "Dimming", (-7, 7)) DPT_Control_Blinds = DPT("3.008", "Blinds", (-7, 7)) def __init__(self, dptId): super(DPTXlator3BitControl, self).__init__(dptId, 0) sub = self.dpt.id.sub if sub is None: sub = 'xxx' dptId_ = '1.' + sub self._dpt2 = DPTXlatorBoolean(dptId_) def checkData(self, data): if not 0x00 <= data <= 0x0f: raise DPTXlatorValueError("data %s not in (0x00, 0x0f)" % hex(data)) def checkValue(self, value): if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("value %d not in range %s" % (value, repr(self._dpt.limits))) def dataToValue(self, data): ctrl = (data & 0x08) >> 3 stepCode = data & 0x07 value = stepCode if ctrl else -stepCode return value def valueToData(self, value): ctrl = 1 if value > 0 else 0 stepCode = abs(value) & 0x07 data = ctrl << 3 | stepCode return data # Add properties control and stepCode + helper methods (+ intervals?) def dataToFrame(self, data): return bytearray(struct.pack(">B", data)) def frameToData(self, frame): # Note the usage of self.data, and not data! data = struct.unpack(">B", frame)[0] return data
class DPTXlator4ByteFloat(DPTXlatorBase): """ DPTXlator class for 4-Byte-Float (F32) KNX Datapoint Type - 2 Byte Float: SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF (IEEE 754) - S: Sign [0, 1] - E: Exponent [0:255] - F: Fraction [0:8388607] . """ DPT_Generic = DPT("14.xxx", "Generic", (-3.4028234663852886e+38, 3.4028234663852886e+38)) #DPT_Generic = DPT("14.xxx", "Generic", (-340282346638528859811704183484516925440, 340282346638528859811704183484516925440)) DPT_Value_Acceleration = DPT( "14.000", "Acceleration", (-3.4028234663852886e+38, 3.4028234663852886e+38), "m/s²") DPT_Value_Acceleration_Angular = DPT( "14.001", "Acceleration, angular", (-3.4028234663852886e+38, 3.4028234663852886e+38), "rad/s²") DPT_Value_Activation_Energy = DPT( "14.002", "Activation energy", (-3.4028234663852886e+38, 3.4028234663852886e+38), "J/mol") DPT_Value_Activity = DPT("14.003", "Activity (radioactive)", (-3.4028234663852886e+38, 3.4028234663852886e+38), "s⁻¹") DPT_Value_Mol = DPT("14.004", "Amount of substance", (-3.4028234663852886e+38, 3.4028234663852886e+38), "mol") DPT_Value_Amplitude = DPT( "14.005", "Amplitude", (-3.4028234663852886e+38, 3.4028234663852886e+38)) DPT_Value_AngleRad = DPT("14.006", "Angle, radiant", (-3.4028234663852886e+38, 3.4028234663852886e+38), "rad") DPT_Value_AngleDeg = DPT("14.007", "Angle, degree", (-3.4028234663852886e+38, 3.4028234663852886e+38), "°") DPT_Value_Angular_Momentum = DPT( "14.008", "Angular momentum", (-3.4028234663852886e+38, 3.4028234663852886e+38), "J.s") DPT_Value_Angular_Velocity = DPT( "14.009", "Angular velocity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "rad/s") DPT_Value_Area = DPT("14.010", "Area", (-3.4028234663852886e+38, 3.4028234663852886e+38), "m²") DPT_Value_Capacitance = DPT( "14.011", "Capacitance", (-3.4028234663852886e+38, 3.4028234663852886e+38), "F") DPT_Value_Charge_DensitySurface = DPT( "14.012", "Charge density (surface)", (-3.4028234663852886e+38, 3.4028234663852886e+38), "C/m²") DPT_Value_Charge_DensityVolume = DPT( "14.013", "Charge density (volume)", (-3.4028234663852886e+38, 3.4028234663852886e+38), "C/m³") DPT_Value_Compressibility = DPT( "14.014", "Compressibility", (-3.4028234663852886e+38, 3.4028234663852886e+38), "m²/N") DPT_Value_Conductance = DPT( "14.015", "Conductance", (-3.4028234663852886e+38, 3.4028234663852886e+38), "S") DPT_Value_Electrical_Conductivity = DPT( "14.016", "Conductivity, electrical", (-3.4028234663852886e+38, 3.4028234663852886e+38), "S/m") DPT_Value_Density = DPT("14.017", "Density", (-3.4028234663852886e+38, 3.4028234663852886e+38), "kg/m³") DPT_Value_Electric_Charge = DPT( "14.018", "Electric charge", (-3.4028234663852886e+38, 3.4028234663852886e+38), "C") DPT_Value_Electric_Current = DPT( "14.019", "Electric current", (-3.4028234663852886e+38, 3.4028234663852886e+38), "A") DPT_Value_CurrentDensity = DPT( "14.020", "Electric current density", (-3.4028234663852886e+38, 3.4028234663852886e+38), "A/m²") DPT_Value_Electric_DipoleMoment = DPT( "14.021", "Electric dipole moment", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Cm") DPT_Value_Electric_Displacement = DPT( "14.022", "Electric displacement", (-3.4028234663852886e+38, 3.4028234663852886e+38), "C/m²") DPT_Value_Electric_FieldStrength = DPT( "14.023", "Electric field strength", (-3.4028234663852886e+38, 3.4028234663852886e+38), "V/m") DPT_Value_Electric_Flux = DPT( "14.024", "Electric flux", (-3.4028234663852886e+38, 3.4028234663852886e+38), "c") # unit??? C DPT_Value_Electric_FluxDensity = DPT( "14.025", "Electric flux density", (-3.4028234663852886e+38, 3.4028234663852886e+38), "C/m²") DPT_Value_Electric_Polarization = DPT( "14.026", "Electric polarization", (-3.4028234663852886e+38, 3.4028234663852886e+38), "C/m²") DPT_Value_Electric_Potential = DPT( "14.027", "Electric potential", (-3.4028234663852886e+38, 3.4028234663852886e+38), "V") DPT_Value_Electric_PotentialDifference = DPT( "14.028", "Electric potential difference", (-3.4028234663852886e+38, 3.4028234663852886e+38), "V") DPT_Value_ElectromagneticMoment = DPT( "14.029", "Electromagnetic moment", (-3.4028234663852886e+38, 3.4028234663852886e+38), "A.m²") DPT_Value_Electromotive_Force = DPT( "14.030", "Electromotive force", (-3.4028234663852886e+38, 3.4028234663852886e+38), "V") DPT_Value_Energy = DPT("14.031", "Energy", (-3.4028234663852886e+38, 3.4028234663852886e+38), "J") DPT_Value_Force = DPT("14.032", "Force", (-3.4028234663852886e+38, 3.4028234663852886e+38), "N") DPT_Value_Frequency = DPT( "14.033", "Frequency", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Hz") DPT_Value_Angular_Frequency = DPT( "14.034", "Frequency, angular (pulsatance)", (-3.4028234663852886e+38, 3.4028234663852886e+38), "rad/s") DPT_Value_Heat_Capacity = DPT( "14.035", "Heat capacity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "J/K") DPT_Value_Heat_FlowRate = DPT( "14.036", "Heat flow rate", (-3.4028234663852886e+38, 3.4028234663852886e+38), "W") DPT_Value_Heat_Quantity = DPT( "14.037", "Heat quantity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "J") DPT_Value_Impedance = DPT( "14.038", "Impedance", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Ohm") DPT_Value_Length = DPT("14.039", "Length", (-3.4028234663852886e+38, 3.4028234663852886e+38), "m") DPT_Value_Light_Quantity = DPT( "14.040", "Light quantity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "J") DPT_Value_Luminance = DPT( "14.041", "Luminance", (-3.4028234663852886e+38, 3.4028234663852886e+38), "cd/m²") DPT_Value_Luminous_Flux = DPT( "14.042", "Luminous flux", (-3.4028234663852886e+38, 3.4028234663852886e+38), "lm") DPT_Value_Luminous_Intensity = DPT( "14.043", "Luminous intensity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "cd") DPT_Value_Magnetic_FieldStrength = DPT( "14.044", "Magnetic field strengh", (-3.4028234663852886e+38, 3.4028234663852886e+38), "A/m") DPT_Value_Magnetic_FLux = DPT( "14.045", "Magnetic flux", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Wb") DPT_Value_Magnetic_FluxDensity = DPT( "14.046", "Magnetic flux density", (-3.4028234663852886e+38, 3.4028234663852886e+38), "T") DPT_Value_Magnetic_Moment = DPT( "14.047", "Magnetic moment", (-3.4028234663852886e+38, 3.4028234663852886e+38), "A.m²") DPT_Value_Magnetic_Polarization = DPT( "14.048", "Magnetic polarization", (-3.4028234663852886e+38, 3.4028234663852886e+38), "T") DPT_Value_Magnetization = DPT( "14.049", "Magnetization", (-3.4028234663852886e+38, 3.4028234663852886e+38), "A/m") DPT_Value_MagnetomotiveForce = DPT( "14.050", "Magnetomotive force", (-3.4028234663852886e+38, 3.4028234663852886e+38), "A") DPT_Value_Mass = DPT("14.051", "Mass", (-3.4028234663852886e+38, 3.4028234663852886e+38), "kg") DPT_Value_MassFlux = DPT("14.052", "Mass flux", (-3.4028234663852886e+38, 3.4028234663852886e+38), "kg/s") DPT_Value_Momentum = DPT("14.053", "Momentum", (-3.4028234663852886e+38, 3.4028234663852886e+38), "N/s") DPT_Value_Phase_AngleRad = DPT( "14.054", "Phase angle, radiant", (-3.4028234663852886e+38, 3.4028234663852886e+38), "rad") DPT_Value_Phase_AngleDeg = DPT( "14.055", "Phase angle, degree", (-3.4028234663852886e+38, 3.4028234663852886e+38), "°") DPT_Value_Power = DPT("14.056", "Power", (-3.4028234663852886e+38, 3.4028234663852886e+38), "W") DPT_Value_Power_Factor = DPT( "14.057", "Power factor", (-3.4028234663852886e+38, 3.4028234663852886e+38), "cos phi") DPT_Value_Pressure = DPT("14.058", "Pressure", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Pa") DPT_Value_Reactance = DPT( "14.059", "Reactance", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Ohm") DPT_Value_Resistance = DPT( "14.060", "Resistance", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Ohm") DPT_Value_Resistivity = DPT( "14.061", "Resistivity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Ohm.m") DPT_Value_SelfInductance = DPT( "14.062", "Self inductance", (-3.4028234663852886e+38, 3.4028234663852886e+38), "H") DPT_Value_SolidAngle = DPT( "14.063", "Solid angle", (-3.4028234663852886e+38, 3.4028234663852886e+38), "sr") DPT_Value_Sound_Intensity = DPT( "14.064", "Sound intensity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "W/m²") DPT_Value_Speed = DPT("14.065", "Speed", (-3.4028234663852886e+38, 3.4028234663852886e+38), "m/s") DPT_Value_Stress = DPT("14.066", "Stress", (-3.4028234663852886e+38, 3.4028234663852886e+38), "Pa") DPT_Value_Surface_Tension = DPT( "14.067", "Surface tension", (-3.4028234663852886e+38, 3.4028234663852886e+38), "N/m") DPT_Value_Common_Temperature = DPT( "14.068", "Temperature, common", (-3.4028234663852886e+38, 3.4028234663852886e+38), "°C") DPT_Value_Absolute_Temperature = DPT( "14.069", "Temperature, absolute", (-3.4028234663852886e+38, 3.4028234663852886e+38), "K") DPT_Value_TemperatureDifference = DPT( "14.070", "Temperature difference", (-3.4028234663852886e+38, 3.4028234663852886e+38), "K") DPT_Value_Thermal_Capacity = DPT( "14.071", "Thermal capacity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "J/K") DPT_Value_Thermal_Conductivity = DPT( "14.072", "Thermal conductivity", (-3.4028234663852886e+38, 3.4028234663852886e+38), "W/m/K") DPT_Value_ThermoelectricPower = DPT( "14.073", "Thermoelectric power", (-3.4028234663852886e+38, 3.4028234663852886e+38), "V/K") DPT_Value_Time = DPT("14.074", "Time", (-3.4028234663852886e+38, 3.4028234663852886e+38), "s") DPT_Value_Torque = DPT("14.075", "Torque", (-3.4028234663852886e+38, 3.4028234663852886e+38), "N.m") DPT_Value_Volume = DPT("14.076", "Volume", (-3.4028234663852886e+38, 3.4028234663852886e+38), "m³") DPT_Value_Volume_Flux = DPT( "14.077", "Volume flux", (-3.4028234663852886e+38, 3.4028234663852886e+38), "m³/s") DPT_Value_Weight = DPT("14.078", "Weight", (-3.4028234663852886e+38, 3.4028234663852886e+38), "N") DPT_Value_Work = DPT("14.079", "Work", (-3.4028234663852886e+38, 3.4028234663852886e+38), "J") def __init__(self, dptId): super(DPTXlator4ByteFloat, self).__init__(dptId, 4) def checkData(self, data): if not 0x00000000 <= data <= 0xffffffff: raise DPTXlatorValueError( "data %s not in (0x00000000, 0xffffffff)" % hex(data)) def checkValue(self, value): if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("Value not in range %s" % repr(self._dpt.limits)) def dataToValue(self, data): value = struct.unpack(">f", struct.pack( ">L", data))[0] # struct.unpack(">f", self.toFrame())[0] #logger.debug("DPTXlator4ByteFloat.dataToValue(): value=%f" % value) return value def valueToData(self, value): data = struct.unpack(">L", struct.pack( ">f", value))[0] # self.frameToData(struct.pack(">f", value)) #logger.debug("DPTXlator4ByteFloat.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">L", data)) def frameToData(self, frame): data = struct.unpack(">L", frame)[0] return data
class DPTXlator2ByteFloat(DPTXlatorBase): """ DPTXlator class for 2-Byte-Float (F16) KNX Datapoint Type - 2 Byte Float: SEEEEMMM MMMMMMMM - S: Sign [0, 1] - E: Exponent [0:15] - M: Significand (Mantissa) [-2048:2047] For all Datapoint Types 9.xxx, the encoded value 7FFFh shall always be used to denote invalid data. """ DPT_Generic = DPT("9.xxx", "Generic", (-671088.64, +670760.96)) DPT_Value_Temp = DPT("9.001", "Temperature", (-273., +670760.), "°C") DPT_Value_Tempd = DPT("9.002", "Temperature difference", (-670760., +670760.), "K") DPT_Value_Tempa = DPT("9.003", "Temperature gradient", (-670760., +670760.), "K/h") DPT_Value_Lux = DPT("9.004", "Luminous emittance", (0., +670760.), "lx") DPT_Value_Wsp = DPT("9.005", "Wind speed", (0., +670760.), "m/s") DPT_Value_Pres = DPT("9.006", "Air pressure", (0., +670760.), "Pa") DPT_Value_Humidity = DPT("9.007", "Humidity", (0., +670760.), "%") DPT_Value_AirQuality = DPT("9.008", "Air quality", (0., +670760.), "ppm") DPT_Value_Time1 = DPT("9.010", "Time difference 1", (-670760., +670760.), "s") DPT_Value_Time2 = DPT("9.011", "Time difference 2", (-670760., +670760.), "ms") DPT_Value_Volt = DPT("9.020", "Electrical voltage", (-670760., +670760.), "mV") DPT_Value_Current = DPT("9.021", "Electric current", (-670760., +670760.), "mA") DPT_PowerDensity = DPT("9.022", "Power density", (-670760., +670760.), "W/m²") DPT_KelvinPerPercent = DPT("9.023", "Kelvin/percent", (-670760., +670760.), "K/%") DPT_Power = DPT("9.024", "Power", (-670760., +670760.), "kW") DPT_Value_Volume_Flow = DPT("9.025", "Volume flow", (-670760., 670760.), "l/h") DPT_Rain_Amount = DPT("9.026", "Rain amount", (-670760., 670760.), "l/m²") DPT_Value_Temp_F = DPT("9.027", "Temperature (°F)", (-459.6, 670760.), "°F") DPT_Value_Wsp_kmh = DPT("9.028", "Wind speed (km/h)", (0., 670760.), "km/h") def __init__(self, dptId): super(DPTXlator2ByteFloat, self).__init__(dptId, 2) def checkData(self, data): if not 0x0000 <= data <= 0xffff: raise DPTXlatorValueError("data %s not in (0x0000, 0xffff)" % hex(data)) def checkValue(self, value): if not self._dpt.limits[0] <= value <= self._dpt.limits[1]: raise DPTXlatorValueError("Value not in range %s" % repr(self._dpt.limits)) #def dataToValueNew(self, data): # data= b'FF f8 \n' # data= b'80 00 \n' # dataConverted = convertHex2(data) # data2 = int(dataConverted,2) # #data2= int(b'FFf8 \n',16) # #int("0xfe43", 0) # #int("fe43", 16) # #data2=int('FF',16) # x_sign=int('0x8000',0) # x_exp=int('0x7800',0) # x_mant=int('0x07ff',0) # #varExp= b'0x7800' # #varMant= b'0x07ff' # sign = (data2 & x_sign) >> 15 # exp = (data2 & x_exp) >> 11 # mant = data2 & x_mant # if sign != 0: # mant = -(~(mant - 1) & x_mant) # value = (1 << exp) * 0.01 * mant # #logger.debug("DPT2ByteFloat.dataToValue(): sign=%d, exp=%d, mant=%r" % (sign, exp, mant)) # #logger.debug("DPT2ByteFloat.dataToValue(): value=%.2f" % value) # return value def dataToValue(self, data): #data = convertHex2Int(data) ##TODO LUCANO ADDED sign = (data & 0x8000) >> 15 exp = (data & 0x7800) >> 11 mant = data & 0x07ff if sign != 0: mant = -(~(mant - 1) & 0x07ff) value = (1 << exp) * 0.01 * mant #logger.debug("DPT2ByteFloat.dataToValue(): sign=%d, exp=%d, mant=%r" % (sign, exp, mant)) #logger.debug("DPT2ByteFloat.dataToValue(): value=%.2f" % value) return value def valueToData(self, value): sign = 0 exp = 0 if value < 0: sign = 1 mant = int(value * 100) while not -2048 <= mant <= 2047: mant = mant >> 1 exp += 1 #logger.debug("DPT2ByteFloat.valueToData(): sign=%d, exp=%d, mant=%r" % (sign, exp, mant)) data = (sign << 15) | (exp << 11) | (int(mant) & 0x07ff) #logger.debug("DPT2ByteFloat.valueToData(): data=%s" % hex(data)) return data def dataToFrame(self, data): return bytearray(struct.pack(">H", data)) def frameToData(self, frame): data = struct.unpack(">H", frame)[0] return data