diff --git a/src/infuse_iot/generated/rpc_definitions.py b/src/infuse_iot/generated/rpc_definitions.py index c2f3812..5a9b193 100644 --- a/src/infuse_iot/generated/rpc_definitions.py +++ b/src/infuse_iot/generated/rpc_definitions.py @@ -161,3 +161,533 @@ class rpc_enum_infuse_bt_characteristic(enum.IntEnum): DATA = 2 LOGGING = 4 + +class rpc_enum_data_logger(enum.IntEnum): + """Data Logger identifier""" + + FLASH_ONBOARD = 1 + FLASH_REMOVABLE = 2 + + +class reboot: + """Reboot the device after a delay""" + + HELP = "Reboot the device after a delay" + DESCRIPTION = "Reboot the device after a delay" + COMMAND_ID = 1 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("delay_ms", ctypes.c_uint32), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("delay_ms", ctypes.c_uint32), + ] + _pack_ = 1 + + +class fault: + """Immediately trigger an exception on the device""" + + HELP = "Immediately trigger an exception on the device" + DESCRIPTION = "Immediately trigger an exception on the device" + COMMAND_ID = 2 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("fault", ctypes.c_uint8), + ("zero", ctypes.c_uint32), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + +class time_get: + """Get the current time knowledge of the device""" + + HELP = "Get the current time knowledge of the device" + DESCRIPTION = "Get the current time knowledge of the device" + COMMAND_ID = 3 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("time_source", ctypes.c_uint8), + ("epoch_time", ctypes.c_uint64), + ("sync_age", ctypes.c_uint32), + ] + _pack_ = 1 + + +class time_set: + """Set the current time of the device""" + + HELP = "Set the current time of the device" + DESCRIPTION = "Set the current time of the device" + COMMAND_ID = 4 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("epoch_time", ctypes.c_uint64), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + +class kv_write: + """Write values to the KV store""" + + HELP = "Write values to the KV store" + DESCRIPTION = "Write values to the KV store" + COMMAND_ID = 5 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("num", ctypes.c_uint8), + ("values", 0 * rpc_struct_kv_store_value), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("rc", 0 * ctypes.c_int16), + ] + _pack_ = 1 + + +class kv_read: + """Read values from the KV store""" + + HELP = "Read values from the KV store" + DESCRIPTION = "Read values from the KV store" + COMMAND_ID = 6 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("num", ctypes.c_uint8), + ("keys", 0 * ctypes.c_uint16), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("values", 0 * rpc_struct_kv_store_value), + ] + _pack_ = 1 + + +class kv_reflect_crcs: + """Read KV store CRC's""" + + HELP = "Read KV store CRC's" + DESCRIPTION = "Read KV store CRC's" + COMMAND_ID = 7 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("offset", ctypes.c_uint16), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("num", ctypes.c_uint16), + ("remaining", ctypes.c_uint16), + ("crcs", 0 * rpc_struct_kv_store_crc), + ] + _pack_ = 1 + + +class zbus_channel_state: + """Query current state of zbus channel""" + + HELP = "Query current state of zbus channel" + DESCRIPTION = "Query current state of zbus channel" + COMMAND_ID = 8 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("channel_id", ctypes.c_uint32), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("publish_timestamp", ctypes.c_uint64), + ("publish_count", ctypes.c_uint32), + ("publish_period_avg_ms", ctypes.c_uint32), + ("data", 0 * ctypes.c_uint8), + ] + _pack_ = 1 + + +class application_info: + """Query basic application versions and state""" + + HELP = "Query basic application versions and state" + DESCRIPTION = "Query basic application versions and state" + COMMAND_ID = 9 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("application_id", ctypes.c_uint32), + ("version", rpc_struct_mcuboot_img_sem_ver), + ("network_id", ctypes.c_uint32), + ("uptime", ctypes.c_uint32), + ("reboots", ctypes.c_uint32), + ("kv_crc", ctypes.c_uint32), + ("data_blocks_internal", ctypes.c_uint32), + ("data_blocks_external", ctypes.c_uint32), + ] + _pack_ = 1 + + +class wifi_scan: + """Scan for WiFi networks""" + + HELP = "Scan for WiFi networks" + DESCRIPTION = "Scan for WiFi networks" + COMMAND_ID = 10 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("network_count", ctypes.c_uint8), + ("networks", 0 * rpc_struct_wifi_scan_result), + ] + _pack_ = 1 + + +class wifi_state: + """Get current WiFi interface state""" + + HELP = "Get current WiFi interface state" + DESCRIPTION = "Get current WiFi interface state" + COMMAND_ID = 11 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("common", rpc_struct_network_state), + ("wifi", rpc_struct_wifi_state), + ] + _pack_ = 1 + + +class last_reboot: + """Retrieve information pertaining to the previous reboot""" + + HELP = "Retrieve information pertaining to the previous reboot" + DESCRIPTION = "Retrieve information pertaining to the previous reboot" + COMMAND_ID = 12 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("reason", ctypes.c_uint8), + ("epoch_time_source", ctypes.c_uint8), + ("epoch_time", ctypes.c_uint64), + ("hardware_flags", ctypes.c_uint32), + ("uptime", ctypes.c_uint32), + ("param_1", ctypes.c_uint32), + ("param_2", ctypes.c_uint32), + ("thread", 8 * ctypes.c_char), + ] + _pack_ = 1 + + +class data_logger_state: + """Get state of a data logger""" + + HELP = "Get state of a data logger" + DESCRIPTION = "Get state of a data logger" + COMMAND_ID = 13 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("logger", ctypes.c_uint8), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("logical_blocks", ctypes.c_uint32), + ("physical_blocks", ctypes.c_uint32), + ("current_block", ctypes.c_uint32), + ("earliest_block", ctypes.c_uint32), + ("block_size", ctypes.c_uint16), + ("block_overhead", ctypes.c_uint16), + ("erase_unit", ctypes.c_uint16), + ] + _pack_ = 1 + + +class data_logger_read: + """Read data from data logger""" + + HELP = "Read data from data logger" + DESCRIPTION = "Read data from data logger" + COMMAND_ID = 14 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("logger", ctypes.c_uint8), + ("start_block", ctypes.c_uint32), + ("last_block", ctypes.c_uint32), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("sent_len", ctypes.c_uint32), + ("sent_crc", ctypes.c_uint32), + ] + _pack_ = 1 + + +class lte_at_cmd: + """Run AT command against LTE modem""" + + HELP = "Run AT command against LTE modem" + DESCRIPTION = "Run AT command against LTE modem" + COMMAND_ID = 20 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("cmd", 0 * ctypes.c_char), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("rsp", 0 * ctypes.c_char), + ] + _pack_ = 1 + + +class lte_state: + """Get current LTE interface state""" + + HELP = "Get current LTE interface state" + DESCRIPTION = "Get current LTE interface state" + COMMAND_ID = 21 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("common", rpc_struct_network_state), + ("lte", rpc_struct_lte_state), + ] + _pack_ = 1 + + +class coap_download: + """Download a file from a COAP server (Infuse-IoT DTLS protected)""" + + HELP = "Download a file from a COAP server (Infuse-IoT DTLS protected)" + DESCRIPTION = "Download a file from a COAP server (Infuse-IoT DTLS protected)" + COMMAND_ID = 30 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("server_address", 48 * ctypes.c_char), + ("server_port", ctypes.c_uint16), + ("block_timeout_ms", ctypes.c_uint16), + ("action", ctypes.c_uint8), + ("resource_len", ctypes.c_uint32), + ("resource_crc", ctypes.c_uint32), + ("resource", 0 * ctypes.c_char), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("resource_len", ctypes.c_uint32), + ("resource_crc", ctypes.c_uint32), + ] + _pack_ = 1 + + +class file_write_basic: + """Write a file to the device""" + + HELP = "Write a file to the device" + DESCRIPTION = "Write a file to the device" + COMMAND_ID = 40 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("action", ctypes.c_uint8), + ("file_crc", ctypes.c_uint32), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("recv_len", ctypes.c_uint32), + ("recv_crc", ctypes.c_uint32), + ] + _pack_ = 1 + + +class bt_connect_infuse: + """Connect to an Infuse-IoT Bluetooth device""" + + HELP = "Connect to an Infuse-IoT Bluetooth device" + DESCRIPTION = "Connect to an Infuse-IoT Bluetooth device" + COMMAND_ID = 50 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("peer", rpc_struct_bt_addr_le), + ("conn_timeout_ms", ctypes.c_uint16), + ("subscribe", ctypes.c_uint8), + ("inactivity_timeout_ms", ctypes.c_uint16), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("cloud_public_key", 32 * ctypes.c_uint8), + ("device_public_key", 32 * ctypes.c_uint8), + ("network_id", ctypes.c_uint32), + ] + _pack_ = 1 + + +class bt_disconnect: + """Disconnect from a Bluetooth device""" + + HELP = "Disconnect from a Bluetooth device" + DESCRIPTION = "Disconnect from a Bluetooth device" + COMMAND_ID = 51 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("peer", rpc_struct_bt_addr_le), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + +class security_state: + """Query current security state and validate identity""" + + HELP = "Query current security state and validate identity" + DESCRIPTION = "Query current security state and validate identity" + COMMAND_ID = 30000 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("challenge", 16 * ctypes.c_uint8), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("cloud_public_key", 32 * ctypes.c_uint8), + ("device_public_key", 32 * ctypes.c_uint8), + ("network_id", ctypes.c_uint32), + ("challenge_response_type", ctypes.c_uint8), + ("challenge_response", 0 * ctypes.c_uint8), + ] + _pack_ = 1 + + +class data_sender: + """Send multiple INFUSE_RPC_DATA packets""" + + HELP = "Send multiple INFUSE_RPC_DATA packets" + DESCRIPTION = "Send multiple INFUSE_RPC_DATA packets" + COMMAND_ID = 32765 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + +class data_receiver: + """Receive multiple INFUSE_RPC_DATA packets""" + + HELP = "Receive multiple INFUSE_RPC_DATA packets" + DESCRIPTION = "Receive multiple INFUSE_RPC_DATA packets" + COMMAND_ID = 32766 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("recv_len", ctypes.c_uint32), + ("recv_crc", ctypes.c_uint32), + ] + _pack_ = 1 + + +class echo: + """Echo any input data in the response""" + + HELP = "Echo any input data in the response" + DESCRIPTION = "Echo any input data in the response" + COMMAND_ID = 32767 + + class request(ctypes.LittleEndianStructure): + _fields_ = [ + ("array", 0 * ctypes.c_uint8), + ] + _pack_ = 1 + + class response(ctypes.LittleEndianStructure): + _fields_ = [ + ("array", 0 * ctypes.c_uint8), + ] + _pack_ = 1 + diff --git a/src/infuse_iot/rpc_wrappers/application_info.py b/src/infuse_iot/rpc_wrappers/application_info.py index dcc6bad..7ce8bcd 100644 --- a/src/infuse_iot/rpc_wrappers/application_info.py +++ b/src/infuse_iot/rpc_wrappers/application_info.py @@ -1,33 +1,10 @@ #!/usr/bin/env python3 -import ctypes - from infuse_iot.commands import InfuseRpcCommand -from infuse_iot.generated.rpc_definitions import rpc_struct_mcuboot_img_sem_ver - - -class application_info(InfuseRpcCommand): - HELP = "Get the current application info" - DESCRIPTION = "Get the current application info" - COMMAND_ID = 9 - - class request(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 +import infuse_iot.generated.rpc_definitions as defs - class response(ctypes.LittleEndianStructure): - _fields_ = [ - ("application_id", ctypes.c_uint32), - ("version", rpc_struct_mcuboot_img_sem_ver), - ("network_id", ctypes.c_uint32), - ("uptime", ctypes.c_uint32), - ("reboots", ctypes.c_uint32), - ("kv_crc", ctypes.c_uint32), - ("data_blocks_internal", ctypes.c_uint32), - ("data_blocks_external", ctypes.c_uint32), - ] - _pack_ = 1 +class application_info(InfuseRpcCommand, defs.application_info): @classmethod def add_parser(cls, _parser): pass diff --git a/src/infuse_iot/rpc_wrappers/bt_connect_infuse.py b/src/infuse_iot/rpc_wrappers/bt_connect_infuse.py index 3e4c000..04bcb99 100644 --- a/src/infuse_iot/rpc_wrappers/bt_connect_infuse.py +++ b/src/infuse_iot/rpc_wrappers/bt_connect_infuse.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import ctypes from infuse_iot.commands import InfuseRpcCommand from infuse_iot.generated.rpc_definitions import ( @@ -10,30 +9,10 @@ ) from infuse_iot.util.argparse import BtLeAddress from infuse_iot.util.ctypes import bytes_to_uint8 +import infuse_iot.generated.rpc_definitions as defs -class bt_connect_infuse(InfuseRpcCommand): - HELP = "Connect to an Infuse-IoT Bluetooth device" - DESCRIPTION = "Connect to an Infuse-IoT Bluetooth device" - COMMAND_ID = 50 - - class request(ctypes.LittleEndianStructure): - _fields_ = [ - ("peer", rpc_struct_bt_addr_le), - ("conn_timeout_ms", ctypes.c_uint16), - ("subscribe", ctypes.c_uint8), - ("inactivity_timeout_ms", ctypes.c_uint16), - ] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [ - ("cloud_public_key", 32 * ctypes.c_uint8), - ("device_public_key", 32 * ctypes.c_uint8), - ("network_id", ctypes.c_uint32), - ] - _pack_ = 1 - +class bt_connect_infuse(InfuseRpcCommand, defs.bt_connect_infuse): @classmethod def add_parser(cls, parser): parser.add_argument( diff --git a/src/infuse_iot/rpc_wrappers/bt_disconnect.py b/src/infuse_iot/rpc_wrappers/bt_disconnect.py index 6ddba02..d3e75cb 100644 --- a/src/infuse_iot/rpc_wrappers/bt_disconnect.py +++ b/src/infuse_iot/rpc_wrappers/bt_disconnect.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import ctypes from infuse_iot.commands import InfuseRpcCommand from infuse_iot.generated.rpc_definitions import ( @@ -9,23 +8,10 @@ ) from infuse_iot.util.argparse import BtLeAddress from infuse_iot.util.ctypes import bytes_to_uint8 +import infuse_iot.generated.rpc_definitions as defs -class bt_disconnect(InfuseRpcCommand): - HELP = "Disconnect from a Bluetooth device" - DESCRIPTION = "Disconnect from a Bluetooth device" - COMMAND_ID = 51 - - class request(ctypes.LittleEndianStructure): - _fields_ = [ - ("peer", rpc_struct_bt_addr_le), - ] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - +class bt_disconnect(InfuseRpcCommand, defs.bt_disconnect): @classmethod def add_parser(cls, parser): addr_group = parser.add_mutually_exclusive_group(required=True) diff --git a/src/infuse_iot/rpc_wrappers/coap_download.py b/src/infuse_iot/rpc_wrappers/coap_download.py index 2cd512c..d4ae48c 100644 --- a/src/infuse_iot/rpc_wrappers/coap_download.py +++ b/src/infuse_iot/rpc_wrappers/coap_download.py @@ -4,20 +4,10 @@ from infuse_iot.commands import InfuseRpcCommand from infuse_iot.generated.rpc_definitions import rpc_enum_file_action +import infuse_iot.generated.rpc_definitions as defs -class coap_download(InfuseRpcCommand): - HELP = "Download a file from a COAP server (Infuse-IoT DTLS protected)" - DESCRIPTION = "Download a file from a COAP server (Infuse-IoT DTLS protected)" - COMMAND_ID = 30 - - class response(ctypes.LittleEndianStructure): - _fields_ = [ - ("resource_len", ctypes.c_uint32), - ("resource_crc", ctypes.c_uint32), - ] - _pack_ = 1 - +class coap_download(InfuseRpcCommand, defs.coap_download): @classmethod def add_parser(cls, parser): parser.add_argument( @@ -69,7 +59,6 @@ def __init__(self, args): self.action = args.action def request_struct(self): - class request(ctypes.LittleEndianStructure): _fields_ = [ ("server_address", 48 * ctypes.c_char), diff --git a/src/infuse_iot/rpc_wrappers/epacket_udp_reconnect.py b/src/infuse_iot/rpc_wrappers/epacket_udp_reconnect.py deleted file mode 100644 index 788a618..0000000 --- a/src/infuse_iot/rpc_wrappers/epacket_udp_reconnect.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 - -import ctypes - -from infuse_iot.commands import InfuseRpcCommand - - -class epacket_udp_reconnect(InfuseRpcCommand): - HELP = "Request device to reconnect to UDP server" - DESCRIPTION = "Request device to reconnect to UDP server" - COMMAND_ID = 15 - - class request(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - - @classmethod - def add_parser(cls, parser): - pass - - def __init__(self, args): - pass - - def request_struct(self): - return self.request() - - def handle_response(self, return_code, response): - print(return_code) - if return_code != 0: - print(f"Failed to request reconnect ({return_code})") - return diff --git a/src/infuse_iot/rpc_wrappers/fault.py b/src/infuse_iot/rpc_wrappers/fault.py index f0f37c3..b9cadcb 100644 --- a/src/infuse_iot/rpc_wrappers/fault.py +++ b/src/infuse_iot/rpc_wrappers/fault.py @@ -1,26 +1,10 @@ #!/usr/bin/env python3 -import ctypes - from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs -class fault(InfuseRpcCommand): - HELP = "Trigger a fault on the device" - DESCRIPTION = "Trigger a fault on the device" - COMMAND_ID = 2 - - class request(ctypes.LittleEndianStructure): - _fields_ = [ - ("fault", ctypes.c_uint8), - ("zero", ctypes.c_uint32), - ] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - +class fault(InfuseRpcCommand, defs.fault): @classmethod def add_parser(cls, parser): group = parser.add_mutually_exclusive_group(required=True) diff --git a/src/infuse_iot/rpc_wrappers/file_write_basic.py b/src/infuse_iot/rpc_wrappers/file_write_basic.py index 319109f..5cbf00b 100644 --- a/src/infuse_iot/rpc_wrappers/file_write_basic.py +++ b/src/infuse_iot/rpc_wrappers/file_write_basic.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import binascii -import ctypes from rich.progress import ( Progress, @@ -11,29 +10,12 @@ from infuse_iot.commands import InfuseRpcCommand, Auth from infuse_iot.generated.rpc_definitions import rpc_enum_file_action +import infuse_iot.generated.rpc_definitions as defs -class file_write_basic(InfuseRpcCommand): - HELP = "Write a file to a device" - DESCRIPTION = "Write a file to a device" - COMMAND_ID = 40 +class file_write_basic(InfuseRpcCommand, defs.file_write_basic): RPC_DATA = True - class request(ctypes.LittleEndianStructure): - - _fields_ = [ - ("action", ctypes.c_uint8), - ("crc", ctypes.c_uint32), - ] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [ - ("recv_len", ctypes.c_uint32), - ("recv_crc", ctypes.c_uint32), - ] - _pack_ = 1 - @classmethod def add_parser(cls, parser): parser.add_argument( @@ -97,7 +79,6 @@ def auth_level(self): return Auth.NETWORK def request_struct(self): - print(f"FILE CRC {binascii.crc32(self.payload):08x}") return self.request(self.action, binascii.crc32(self.payload)) def data_payload(self): diff --git a/src/infuse_iot/rpc_wrappers/kv_read.py b/src/infuse_iot/rpc_wrappers/kv_read.py index f7e23c3..2d879b9 100644 --- a/src/infuse_iot/rpc_wrappers/kv_read.py +++ b/src/infuse_iot/rpc_wrappers/kv_read.py @@ -4,13 +4,10 @@ import errno from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs -class kv_read(InfuseRpcCommand): - HELP = "Read KV store values" - DESCRIPTION = "Read KV store values" - COMMAND_ID = 6 - +class kv_read(InfuseRpcCommand, defs.kv_read): class request(ctypes.LittleEndianStructure): _fields_ = [ ("num", ctypes.c_uint8), @@ -50,7 +47,9 @@ class kv_store_value(ctypes.LittleEndianStructure): @classmethod def add_parser(cls, parser): - parser.add_argument("--keys", "-k", type=int, nargs="+", help="Keys to read") + parser.add_argument( + "--keys", "-k", required=True, type=int, nargs="+", help="Keys to read" + ) def __init__(self, args): self.keys = args.keys diff --git a/src/infuse_iot/rpc_wrappers/last_reboot.py b/src/infuse_iot/rpc_wrappers/last_reboot.py new file mode 100644 index 0000000..baecf23 --- /dev/null +++ b/src/infuse_iot/rpc_wrappers/last_reboot.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs + + +class last_reboot(InfuseRpcCommand, defs.last_reboot): + @classmethod + def add_parser(cls, parser): + pass + + def __init__(self, args): + pass + + def request_struct(self): + return self.request() + + def handle_response(self, return_code, response): + if return_code != 0: + print(f"Failed to query reboot info ({return_code})") + return + + from infuse_iot.time import InfuseTime, InfuseTimeSource + + t_remote = InfuseTime.unix_time_from_epoch(response.epoch_time) + + print(f"\t Reason: {response.reason}") + print(f"\t Hardware: 0x{response.hardware_flags:08x}") + print( + f"\tReboot Time: {InfuseTime.utc_time_string(t_remote)} ({InfuseTimeSource(response.epoch_time_source)})" + ) + print(f"\t Uptime: {response.uptime}") + print(f"\t Param 1: 0x{response.param_1:08x}") + print(f"\t Param 2: 0x{response.param_2:08x}") + print(f"\t Thread: {response.thread.decode('utf-8')}") diff --git a/src/infuse_iot/rpc_wrappers/lte_at_cmd.py b/src/infuse_iot/rpc_wrappers/lte_at_cmd.py index 7520a33..476dd58 100644 --- a/src/infuse_iot/rpc_wrappers/lte_at_cmd.py +++ b/src/infuse_iot/rpc_wrappers/lte_at_cmd.py @@ -4,13 +4,10 @@ import errno from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs -class lte_at_cmd(InfuseRpcCommand): - HELP = "Run AT command on LTE modem" - DESCRIPTION = "Run AT command on LTE modem" - COMMAND_ID = 20 - +class lte_at_cmd(InfuseRpcCommand, defs.lte_at_cmd): class request(ctypes.LittleEndianStructure): _fields_ = [] _pack_ = 1 diff --git a/src/infuse_iot/rpc_wrappers/lte_modem_info.py b/src/infuse_iot/rpc_wrappers/lte_modem_info.py index 9d2237f..2824a1f 100644 --- a/src/infuse_iot/rpc_wrappers/lte_modem_info.py +++ b/src/infuse_iot/rpc_wrappers/lte_modem_info.py @@ -3,14 +3,14 @@ import ctypes from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs from . import kv_read, lte_pdp_ctx -class lte_modem_info(InfuseRpcCommand): +class lte_modem_info(InfuseRpcCommand, defs.kv_read): HELP = "Get LTE modem information" DESCRIPTION = "Get LTE modem information" - COMMAND_ID = 6 class request(kv_read.kv_read.request): pass diff --git a/src/infuse_iot/rpc_wrappers/lte_pdp_ctx.py b/src/infuse_iot/rpc_wrappers/lte_pdp_ctx.py index 02bd6cc..f9cac7f 100644 --- a/src/infuse_iot/rpc_wrappers/lte_pdp_ctx.py +++ b/src/infuse_iot/rpc_wrappers/lte_pdp_ctx.py @@ -4,12 +4,12 @@ import enum from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs -class lte_pdp_ctx(InfuseRpcCommand): +class lte_pdp_ctx(InfuseRpcCommand, defs.kv_write): HELP = "Set the WiFi network SSID and PSK" DESCRIPTION = "Set the WiFi network SSID and PSK" - COMMAND_ID = 5 class request(ctypes.LittleEndianStructure): _fields_ = [ diff --git a/src/infuse_iot/rpc_wrappers/lte_state.py b/src/infuse_iot/rpc_wrappers/lte_state.py index de9ae24..12746cd 100644 --- a/src/infuse_iot/rpc_wrappers/lte_state.py +++ b/src/infuse_iot/rpc_wrappers/lte_state.py @@ -6,6 +6,7 @@ from infuse_iot.commands import InfuseRpcCommand from infuse_iot.zephyr import net_if as z_nif from infuse_iot.zephyr import lte as z_lte +import infuse_iot.generated.rpc_definitions as defs class interface_state(ctypes.LittleEndianStructure): @@ -60,15 +61,7 @@ def access_technology(self): return z_lte.AccessTechnology(self._act) -class lte_state(InfuseRpcCommand): - HELP = "Get LTE state" - DESCRIPTION = "Get LTE state" - COMMAND_ID = 21 - - class request(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - +class lte_state(InfuseRpcCommand, defs.lte_state): class response(ctypes.LittleEndianStructure): _fields_ = [ ("common", interface_state), diff --git a/src/infuse_iot/rpc_wrappers/reboot.py b/src/infuse_iot/rpc_wrappers/reboot.py index 5d73207..f943ae6 100644 --- a/src/infuse_iot/rpc_wrappers/reboot.py +++ b/src/infuse_iot/rpc_wrappers/reboot.py @@ -1,27 +1,10 @@ #!/usr/bin/env python3 -import ctypes - from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs -class reboot(InfuseRpcCommand): - HELP = "Reboot the device" - DESCRIPTION = "Reboot the device" - COMMAND_ID = 1 - - class request(ctypes.LittleEndianStructure): - _fields_ = [ - ("delay_ms", ctypes.c_uint32), - ] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [ - ("delay_ms", ctypes.c_uint32), - ] - _pack_ = 1 - +class reboot(InfuseRpcCommand, defs.reboot): @classmethod def add_parser(cls, parser): parser.add_argument( diff --git a/src/infuse_iot/rpc_wrappers/security_state.py b/src/infuse_iot/rpc_wrappers/security_state.py index 9fee66d..abd513a 100644 --- a/src/infuse_iot/rpc_wrappers/security_state.py +++ b/src/infuse_iot/rpc_wrappers/security_state.py @@ -9,8 +9,10 @@ from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 from infuse_iot.util.argparse import ValidFile +from infuse_iot.util.ctypes import bytes_to_uint8 from infuse_iot.commands import InfuseRpcCommand from infuse_iot.epacket import Auth +import infuse_iot.generated.rpc_definitions as defs class challenge_response_header(ctypes.LittleEndianStructure): @@ -43,24 +45,7 @@ class challenge_response_basic(ctypes.LittleEndianStructure): _pack_ = 1 -class security_state(InfuseRpcCommand): - HELP = "Get the current device security state" - DESCRIPTION = "Get the current device security state" - COMMAND_ID = 30000 - - class request(ctypes.LittleEndianStructure): - _fields_ = [ - ("challenge", 16 * ctypes.c_char), - ] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [ - ("header", challenge_response_header), - ("response", challenge_response_basic_encr), - ] - _pack_ = 1 - +class security_state(InfuseRpcCommand, defs.security_state): @classmethod def add_parser(cls, parser): parser.add_argument( @@ -68,7 +53,7 @@ def add_parser(cls, parser): ) def __init__(self, args): - self.challenge = random.randbytes(16) + self.challenge = bytes_to_uint8(random.randbytes(16)) self.pem = args.pem def auth_level(self): @@ -78,7 +63,6 @@ def request_struct(self): return self.request(self.challenge) def _decrypt_response(self, response): - hdr = response.header rsp = response.response rb = bytes(response.response) @@ -87,7 +71,7 @@ def _decrypt_response(self, response): f.read().encode("utf-8"), password=None ) device_public_key = x25519.X25519PublicKey.from_public_bytes( - bytes(hdr.device_public_key) + bytes(response.device_public_key) ) shared_secret = cloud_private_key.exchange(device_public_key) hkdf = HKDF( @@ -108,12 +92,10 @@ def handle_response(self, return_code, response): return # Decrypt identity information - hdr = response.header - print("Security State:") - print(f"\tDevice Public Key: {bytes(hdr.device_public_key).hex()}") - print(f"\t Cloud Public Key: {bytes(hdr.cloud_public_key).hex()}") - print(f"\t Network: 0x{hdr.network_id:06x}") + print(f"\tDevice Public Key: {bytes(response.device_public_key).hex()}") + print(f"\t Cloud Public Key: {bytes(response.cloud_public_key).hex()}") + print(f"\t Network: 0x{response.network_id:06x}") if self.pem is None: print("\t Identity: Cannot validate") else: diff --git a/src/infuse_iot/rpc_wrappers/time_get.py b/src/infuse_iot/rpc_wrappers/time_get.py index d8f44e7..7fe70b0 100644 --- a/src/infuse_iot/rpc_wrappers/time_get.py +++ b/src/infuse_iot/rpc_wrappers/time_get.py @@ -1,27 +1,10 @@ #!/usr/bin/env python3 -import ctypes - from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs -class time_get(InfuseRpcCommand): - HELP = "Get the current device time" - DESCRIPTION = "Get the current device time" - COMMAND_ID = 3 - - class request(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [ - ("time_source", ctypes.c_uint8), - ("epoch_time", ctypes.c_uint64), - ("sync_age", ctypes.c_uint32), - ] - _pack_ = 1 - +class time_get(InfuseRpcCommand, defs.time_get): @classmethod def add_parser(cls, parser): pass diff --git a/src/infuse_iot/rpc_wrappers/time_set.py b/src/infuse_iot/rpc_wrappers/time_set.py index 62e1dd3..4b45a6f 100644 --- a/src/infuse_iot/rpc_wrappers/time_set.py +++ b/src/infuse_iot/rpc_wrappers/time_set.py @@ -1,25 +1,10 @@ #!/usr/bin/env python3 -import ctypes - from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs -class time_set(InfuseRpcCommand): - HELP = "Set the current device time" - DESCRIPTION = "Set the current device time" - COMMAND_ID = 4 - - class request(ctypes.LittleEndianStructure): - _fields_ = [ - ("epoch_time", ctypes.c_uint64), - ] - _pack_ = 1 - - class response(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - +class time_set(InfuseRpcCommand, defs.time_set): @classmethod def add_parser(cls, parser): pass diff --git a/src/infuse_iot/rpc_wrappers/wifi_configure.py b/src/infuse_iot/rpc_wrappers/wifi_configure.py index d76f9bb..b7181dc 100644 --- a/src/infuse_iot/rpc_wrappers/wifi_configure.py +++ b/src/infuse_iot/rpc_wrappers/wifi_configure.py @@ -3,12 +3,12 @@ import ctypes from infuse_iot.commands import InfuseRpcCommand +import infuse_iot.generated.rpc_definitions as defs -class wifi_configure(InfuseRpcCommand): +class wifi_configure(InfuseRpcCommand, defs.kv_write): HELP = "Set the WiFi network SSID and PSK" DESCRIPTION = "Set the WiFi network SSID and PSK" - COMMAND_ID = 5 class request(ctypes.LittleEndianStructure): _fields_ = [ diff --git a/src/infuse_iot/rpc_wrappers/wifi_scan.py b/src/infuse_iot/rpc_wrappers/wifi_scan.py index 1f49ab5..db86cb2 100644 --- a/src/infuse_iot/rpc_wrappers/wifi_scan.py +++ b/src/infuse_iot/rpc_wrappers/wifi_scan.py @@ -5,17 +5,10 @@ from infuse_iot.commands import InfuseRpcCommand from infuse_iot.zephyr import wifi as z_wifi +import infuse_iot.generated.rpc_definitions as defs -class wifi_scan(InfuseRpcCommand): - HELP = "Scan for WiFi networks" - DESCRIPTION = "Scan for WiFi networks" - COMMAND_ID = 10 - - class request(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - +class wifi_scan(InfuseRpcCommand, defs.wifi_scan): class response(ctypes.LittleEndianStructure): @classmethod def from_buffer_copy(cls, source, offset=0): diff --git a/src/infuse_iot/rpc_wrappers/wifi_state.py b/src/infuse_iot/rpc_wrappers/wifi_state.py index f6f4e9a..c13fdf9 100644 --- a/src/infuse_iot/rpc_wrappers/wifi_state.py +++ b/src/infuse_iot/rpc_wrappers/wifi_state.py @@ -6,6 +6,7 @@ from infuse_iot.commands import InfuseRpcCommand from infuse_iot.zephyr import net_if as z_nif from infuse_iot.zephyr import wifi as z_wifi +import infuse_iot.generated.rpc_definitions as defs class interface_state(ctypes.LittleEndianStructure): @@ -69,15 +70,7 @@ def security_type(self): return z_wifi.SecurityType(self._security) -class wifi_state(InfuseRpcCommand): - HELP = "Get WiFi state" - DESCRIPTION = "Get WiFi state" - COMMAND_ID = 11 - - class request(ctypes.LittleEndianStructure): - _fields_ = [] - _pack_ = 1 - +class wifi_state(InfuseRpcCommand, defs.wifi_state): class response(ctypes.LittleEndianStructure): _fields_ = [ ("common", interface_state), diff --git a/src/infuse_iot/rpc_wrappers/zbus_channel_state.py b/src/infuse_iot/rpc_wrappers/zbus_channel_state.py index 18255a3..f07a8eb 100644 --- a/src/infuse_iot/rpc_wrappers/zbus_channel_state.py +++ b/src/infuse_iot/rpc_wrappers/zbus_channel_state.py @@ -5,19 +5,10 @@ from infuse_iot.commands import InfuseRpcCommand from infuse_iot.tdf import tdf_definitions as defs +import infuse_iot.generated.rpc_definitions as rpc_defs -class zbus_channel_state(InfuseRpcCommand): - HELP = "Current state of zbus channel" - DESCRIPTION = "Current state of zbus channel" - COMMAND_ID = 8 - - class request(ctypes.LittleEndianStructure): - _fields_ = [ - ("channel_id", ctypes.c_uint32), - ] - _pack_ = 1 - +class zbus_channel_state(InfuseRpcCommand, rpc_defs.zbus_channel_state): class response(InfuseRpcCommand.VariableSizeResponse): base_fields = [ ("pub_timestamp", ctypes.c_uint64),