# dmm_decoder.py import json class DMMDecoder: """Base class for DMM screen/binary decoders.""" def __init__(self, config): self.xorkey = self.str2hexarray(config["xorkey"]) self.icon_regions = config["icon_regions"]["default"] self.icon_table = config["icon_table"] @staticmethod def str2hexarray(string): string = string.replace(' ', '').lower() return [int(string[i:i+2], 16) for i in range(0, len(string), 2)] @staticmethod def bytewise_XOR(array, xorkey): return [array[x] ^ xorkey[x % len(xorkey)] for x in range(len(array))] @staticmethod def hex2bin(array): return [bin(x)[2:].zfill(8) for x in array] @staticmethod def flip_bits(array): return [b[::-1] for b in array] @staticmethod def array2str(array): return ''.join(array) def extract_icon_bits(self, bitstring): bits = self.icon_regions # Concatenate bit ranges return bitstring[bits[0]:bits[1]] + bitstring[bits[2]:bits[3]] def decode_icons(self, icon_bits): return [self.icon_table[i] for i, b in enumerate(icon_bits) if b == '1' and i < len(self.icon_table)] def decode_packet(self, hexstring): encoded_array = self.str2hexarray(hexstring) # pad xorkey if needed xorkey = (self.xorkey * ((len(encoded_array) // len(self.xorkey)) + 1))[:len(encoded_array)] xordecoded = self.bytewise_XOR(encoded_array, xorkey) binary = self.hex2bin(xordecoded) flipped = self.flip_bits(binary) bitstring = self.array2str(flipped) icon_bits = self.extract_icon_bits(bitstring) icons = self.decode_icons(icon_bits) return {'icons': icons} # Example derived decoder for ZT-5B (can be extended for other models) class ZT5BDecoder(DMMDecoder): def __init__(self, config): super().__init__(config) # add any ZT-5B-specific setup here if needed # --- Usage Example --- if __name__ == "__main__": # Minimal config example config = { "xorkey": "41217355a2c1327166aa3bd0e2a833142021aabb", "icon_regions": { "default": [24, 28, 60, 87] }, "icon_table": [ "LowBattery","Delta","BT","BUZ","HOLD","ºF","ºC","DIODE", "MAX","MIN","%","AC","F","u(F)","m(F)","n(F)","Hz", "ohm","K(ohm)","M(ohm)","V","m(V)","DC","A","AUTO", "?7","u(A)","m(A)","?8","?9","?10","?11" ] } decoder = ZT5BDecoder(config) hexstring = "1b847195453ad9fa668a" result = decoder.decode_packet(hexstring) print(json.dumps(result, ensure_ascii=False, indent=2))