"""Transport selector, operation codes and command ids. Recovered from the object pool (``pp.txt``) of ``libapp.so`` — see ``docs/RE_DART_FINDINGS.md`` §2, §4. """ from __future__ import annotations from enum import IntEnum class CommunicationMode(IntEnum): """Transport selector (raw values as in the Dart enum).""" MQTT = 0 SOCKET = 1 BLUETOOTH = 2 HTTP = 3 LOCAL = 4 class CommunicationOperate(IntEnum): """``type`` field of the wire envelope.""" QUERY = 0 SET = 1 COMMAND = 2 MODIFY = 5 class CommunicationCmd(IntEnum): """``cmdType`` field of the wire envelope. Gaps 0x09, 0x1B, 0x2C, 0x31 are not surfaced as instances in the pool. ``WIFI_FREQUECY`` keeps the app's spelling. """ QUERY_DEVICE_INFO = 0x00 NETWORK_INFO = 0x01 RESOURCE_ADDRESS = 0x02 SUNSPEC_MODBUS = 0x03 NETWORK_SWITCH = 0x04 FEEDING_GRID_POWER = 0x05 MODE = 0x06 MODE_V2 = 0x07 MODE_SETTING_V2 = 0x08 SOLAR_INFO = 0x0A ENERGY_MANAGE_INFO = 0x0B GENERATOR_INFO = 0x0C BLUETOOTH_HEARTBEAT = 0x0D SCAN_WIFI_LIST = 0x0E CONNECT_WIFI = 0x0F CONNECTION_STATUS = 0x10 NETWORK_CHANNEL_STATUS = 0x11 NETWORK_CHANNEL = 0x12 PAIR_POWER = 0x13 PROCESS_PAIR_POWER = 0x14 CHECK_BLUETOOTH_PASSWORD = 0x15 GO_OFF_GRID_STATUS = 0x16 A_POWER_LED_SWITCH = 0x17 DEVICE_DETAIL_INFO = 0x18 DEVICE_APOWER_INFO = 0x19 DEVICE_ALARMS = 0x1A PE = 0x1C BMS = 0x1D EMS = 0x1E MPPT = 0x1F A_HUB = 0x20 CT_TEST_REVERSE = 0x21 DEVICE_DATA = 0x22 LOAD_STATUS = 0x23 LOAD_STATUS_2 = 0x24 SMART_LOAD = 0x25 SMART_LOAD_2 = 0x26 REBOOT_DEVICE = 0x27 DEBUG_MODE = 0x28 POWER_ON = 0x29 CHARGE_DEVICE = 0x2A CLEAR_FAULT = 0x2B DEVICE_ADDRESS_INFO = 0x2D OVERLOAD_CUT_OFF = 0x2E WIFI_FREQUECY = 0x2F # sic BREAKER_COMMISSION_NOTIFY = 0x30 BREAKER_COM_STATE = 0x32 BREAKER_LOAD_STATUS = 0x33 BREAKER_IDENTIFY_ME = 0x34 #: ``cmdType`` values on the socket/Bluetooth/local transports. #: #: ``CommunicationCmd::cmd(cmd, mode)`` returns the *second* id field #: (``off_14`` in the pool) for ``socket``/``bluetooth``/``local`` modes and #: throws for ``http`` — verified live: a PCAPdroid capture of the app shows #: ``{"cmdType":1101, ...}`` (``QUERY_DEVICE_INFO`` here, ``off_8`` ``0x00``) #: with the S1-plaintext-first framing (see ``docs/RE_DART_FINDINGS.md`` #: §5). The ``off_8`` values above are *not* used on the wire for these #: transports. Entries mapped to ``None`` have no pool id (``0xFFFF…``). SOCKET_CMD_TYPE = { CommunicationCmd.QUERY_DEVICE_INFO: 0x44D, CommunicationCmd.NETWORK_INFO: 0x45D, CommunicationCmd.RESOURCE_ADDRESS: 0x4B5, CommunicationCmd.SUNSPEC_MODBUS: 0x4B5, CommunicationCmd.NETWORK_SWITCH: 0x45F, CommunicationCmd.FEEDING_GRID_POWER: 0x6A5, CommunicationCmd.MODE: 0x57B, CommunicationCmd.MODE_V2: 0x6BD, CommunicationCmd.MODE_SETTING_V2: 0x6BF, CommunicationCmd.SOLAR_INFO: 0x76F, CommunicationCmd.ENERGY_MANAGE_INFO: 0x4B3, CommunicationCmd.GENERATOR_INFO: 0x76D, CommunicationCmd.BLUETOOTH_HEARTBEAT: 0x7D7, CommunicationCmd.SCAN_WIFI_LIST: 0x455, CommunicationCmd.CONNECT_WIFI: 0x457, CommunicationCmd.CONNECTION_STATUS: 0x459, CommunicationCmd.NETWORK_CHANNEL_STATUS: 0x46D, CommunicationCmd.NETWORK_CHANNEL: 0x46B, CommunicationCmd.PAIR_POWER: 0x44F, CommunicationCmd.PROCESS_PAIR_POWER: 0x451, CommunicationCmd.CHECK_BLUETOOTH_PASSWORD: 0x7D5, CommunicationCmd.GO_OFF_GRID_STATUS: 0x6BB, CommunicationCmd.A_POWER_LED_SWITCH: None, CommunicationCmd.DEVICE_DETAIL_INFO: 0x515, CommunicationCmd.DEVICE_APOWER_INFO: 0x51B, CommunicationCmd.DEVICE_ALARMS: 0x725, CommunicationCmd.PE: 0x6A7, CommunicationCmd.BMS: 0x6A9, CommunicationCmd.EMS: 0x6AB, CommunicationCmd.MPPT: 0x6B5, CommunicationCmd.A_HUB: 0x771, CommunicationCmd.CT_TEST_REVERSE: None, CommunicationCmd.DEVICE_DATA: None, CommunicationCmd.LOAD_STATUS: 0x583, CommunicationCmd.LOAD_STATUS_2: 0x587, CommunicationCmd.SMART_LOAD: 0x581, CommunicationCmd.SMART_LOAD_2: 0x585, CommunicationCmd.REBOOT_DEVICE: 0x6B9, CommunicationCmd.DEBUG_MODE: 0x71D, CommunicationCmd.POWER_ON: 0x71F, CommunicationCmd.CHARGE_DEVICE: 0x721, CommunicationCmd.CLEAR_FAULT: 0x6AD, CommunicationCmd.DEVICE_ADDRESS_INFO: 0x4B1, CommunicationCmd.OVERLOAD_CUT_OFF: 0x6A5, CommunicationCmd.WIFI_FREQUECY: 0x46F, CommunicationCmd.BREAKER_COMMISSION_NOTIFY: None, CommunicationCmd.BREAKER_COM_STATE: None, CommunicationCmd.BREAKER_LOAD_STATUS: 0x471, CommunicationCmd.BREAKER_IDENTIFY_ME: 0x473, } def socket_cmd_type(cmd: CommunicationCmd) -> int: """Wire ``cmdType`` for *cmd* on the socket transport (``cmd()``).""" value = SOCKET_CMD_TYPE[cmd] if value is None: raise KeyError(f"{cmd} has no socket-transport command id") return int(value)