157 lines
4.9 KiB
Python
157 lines
4.9 KiB
Python
"""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)
|