def getStructs(data: bytes, logger=None): dn = xdlms.DataNotification.from_bytes(data) # The first 3 bytes should be ignored. result = parse_as_dlms_data(dn.body) # First is date date_row = result.pop(0) #clock_obis = Obis.from_bytes(date_row) clock, stats = datetime_from_bytes(date_row) if logger is not None: logger.debug(f"Clock object: datetime={clock}") else: print(f"Clock object: datetime={clock}") offset = 0 structs = {"system": (clock, stats)} while offset < len(result): try: structs[Obis.from_bytes(result[offset]).to_string()] = ( result[offset+1:offset+3] ) offset += 3 except ValueError: structs["id"] = result[offset] offset += 1 return structs
def object_exists(self, object_obis: Obis) -> bool: return object_obis.dotted_repr() in self.objects.keys()
def force_obis(maybe_obis: Union[str, Obis]): if isinstance(maybe_obis, Obis): return maybe_obis else: return Obis.from_dotted(maybe_obis)
class ObisNames: ActiveEnergy_in = Obis.from_string("1.0.1.8.0.255") ActiveEnergy_out = Obis.from_string("1.0.2.8.0.255") RealPower_in = Obis.from_string("1.0.1.7.0.255") RealPower_out = Obis.from_string("1.0.2.7.0.255") VoltageL1 = Obis.from_string("1.0.32.7.0.255") VoltageL2 = Obis.from_string("1.0.52.7.0.255") VoltageL3 = Obis.from_string("1.0.72.7.0.255") CurrentL1 = Obis.from_string("1.0.31.7.0.255") CurrentL2 = Obis.from_string("1.0.51.7.0.255") CurrentL3 = Obis.from_string("1.0.71.7.0.255") PowerFactor = Obis.from_string("1.0.13.7.0.255") ActiveEnergy_in_str = ActiveEnergy_in.to_string() ActiveEnergy_out_str = ActiveEnergy_out.to_string() RealPower_in_str = RealPower_in.to_string() RealPower_out_str = RealPower_out.to_string() VoltageL1_str = VoltageL1.to_string() VoltageL2_str = VoltageL2.to_string() VoltageL3_str = VoltageL3.to_string() CurrentL1_str = CurrentL1.to_string() CurrentL2_str = CurrentL2.to_string() CurrentL3_str = CurrentL3.to_string() PowerFactor_str = PowerFactor.to_string() @staticmethod def getFriendlyName(obis: Union[str, Obis]): if isinstance(obis, Obis): obis = obis.to_string() match obis: case ObisNames.ActiveEnergy_in_str: return "Wirkenergie +" case ObisNames.ActiveEnergy_out_str: return "Wirkenergie -" case ObisNames.RealPower_in_str: return "Momentanleistung +" case ObisNames.RealPower_out_str: return "Momentanleistung -" case ObisNames.VoltageL1_str: return "Spannung L1" case ObisNames.VoltageL2_str: return "Spannung L2" case ObisNames.VoltageL3_str: return "Spannung L3" case ObisNames.CurrentL1_str: return "Strom L1" case ObisNames.CurrentL2_str: return "Strom L2" case ObisNames.CurrentL3_str: return "Strom L3" case ObisNames.PowerFactor_str: return "Leistungsfaktor" case _: return None @staticmethod def getDeviceClass(obis: Union[str, Obis]): if isinstance(obis, Obis): obis = obis.to_string() match obis: case (ObisNames.ActiveEnergy_in_str | ObisNames.ActiveEnergy_out_str): return SensorDeviceClasses.ENERGY case (ObisNames.RealPower_in_str | ObisNames.RealPower_out_str): return SensorDeviceClasses.POWER case (ObisNames.VoltageL1_str | ObisNames.VoltageL2_str | ObisNames.VoltageL3_str): return SensorDeviceClasses.VOLTAGE case (ObisNames.CurrentL1_str | ObisNames.CurrentL2_str | ObisNames.CurrentL3_str): return SensorDeviceClasses.CURRENT case ObisNames.PowerFactor_str: return SensorDeviceClasses.POWER_FACTOR case _: return SensorDeviceClasses.GENERIC_SENSOR
dn = xdlms.DataNotification.from_bytes(bytes.fromhex(hdlc_data_hex)) # The first 3 bytes should be ignored. result = parse_as_dlms_data(dn.body) # First is date date_row = result.pop(0) #clock_obis = Obis.from_bytes(date_row) clock, stats = datetime_from_bytes(date_row) print(f"Clock object: datetime={clock}") offset = 0 structs = {} while offset < len(result): try: structs[Obis.from_bytes(result[offset]).to_string()] = ( result[offset+1:offset+3] ) offset += 3 except ValueError: structs["id"] = result[offset] offset += 1 print(structs) print(getValue(structs[ObisNames.ActiveEnergy_in.to_string()])) # rest is data #for item in result: # try: # obis = Obis.from_bytes(item) # value = item[1] # print(f"{obis.to_string()}={value}")
"0f00161b020309060100030700ff06000005e302020f00161d020309060100040700ff060000000002" "020f00161d0203090601001f0700ff10000002020fff1621020309060100330700ff10004b02020fff" "1621020309060100470700ff10000002020fff1621020309060100200700ff12090302020fff162302" "0309060100340700ff1209c302020fff1623020309060100480700ff12090402020fff162302030906" "0100150700ff060000000002020f00161b020309060100160700ff060000000002020f00161b020309" "060100170700ff060000000002020f00161d020309060100180700ff060000000002020f00161d0203" "09060100290700ff060000046202020f00161b0203090601002a0700ff060000000002020f00161b02" "03090601002b0700ff06000005e202020f00161d0203090601002c0700ff060000000002020f00161d" "0203090601003d0700ff060000000002020f00161b0203090601003e0700ff060000000002020f0016" "1b0203090601003f0700ff060000000002020f00161d020309060100400700ff060000000002020f00" "161d020309060100010800ff060099598602020f00161e020309060100020800ff060000000802020f" "00161e020309060100030800ff060064ed4b02020f001620020309060100040800ff06000000050202" "0f001620be407e") ui = frames.UnnumberedInformationFrame.from_bytes(bytes.fromhex(hdlc_data_hex)) dn = xdlms.DataNotification.from_bytes( ui.payload[3:]) # The first 3 bytes should be ignored. result = parse_as_dlms_data(dn.body) # First is date date_row = result.pop(0) clock_obis = Obis.from_bytes(date_row[0]) clock, stats = datetime_from_bytes(date_row[1]) print(f"Clock object: {clock_obis.to_string()}, datetime={clock}") # rest is data for item in result: obis = Obis.from_bytes(item[0]) value = item[1] print(f"{obis.to_string()}={value}")