"""Explicit interpretation of ProtoCAN registers with the UMP 167/v1 map. This is a manually selected dictionary, not detection of the legacy service CAN packet format or a claim that a particular firmware implements ProtoCAN. """ from protocan import protocan as pc from protocan.gas_167 import REGISTERS, describe_word def decode_gas167(frame, node): result = pc.decode(frame.can_id, frame.data, ide=frame.ide, rtr=frame.rtr) result.device_label = "УМП %d (выбран вручную)" % node result.protocol = "УМП %d / ProtoCAN GAS 167/v1" % node if not frame.ide or frame.rtr or frame.is_error: return result if result.id.msg_type not in (pc.MsgType.GENERAL_ADDRESS_SPACE, pc.MsgType.MODBUS_HOLDING): return result if result.id.msg_type == pc.MsgType.GENERAL_ADDRESS_SPACE: start = result.id.body else: start, _count = pc.split_modbus(result.id.body) words = result.registers if words is None: return result labels = [] for address, value in words or [(start, None)]: offset = address if 0 <= address < 128 else address - 0x5000 label = "0x%04X" % address if 0 <= offset < len(REGISTERS): entry = REGISTERS[offset] label += " · " + entry['description'] result.fields += [ (" УМП 167/v1 0x%04X" % address, entry['description']), (" Назначенные ID УМП 1/2", "%d / %d" % (entry['ump1_id'], entry['ump2_id'])), (" Доступ", entry['access']), ] else: label += " · вне карты 167/v1" if value is not None: label += " = %d [0x%04X]" % (value, value) description = describe_word(offset, value) if description: label += " — " + description result.fields.append((" Биты 0x%04X" % address, description)) labels.append(label) result.summary = "УМП %d · GAS 167/v1%s: %s" % ( node, " запрос" if not words else "", "; ".join(labels)) result.fields.append((" Карта", "167/v1 выбрана вручную")) return result