From cea7f887a01786c3f7168d1b2c13a5e001f99450 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Thu, 16 Apr 2026 13:51:41 +1000 Subject: [PATCH 1/4] generated: regenerate definitions Update definitions from infuse-iot. Signed-off-by: Jordan Yates --- src/infuse_iot/generated/kv_definitions.py | 12 ++++++ src/infuse_iot/generated/rpc_definitions.py | 48 +++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/infuse_iot/generated/kv_definitions.py b/src/infuse_iot/generated/kv_definitions.py index 7063097..5b2f0d9 100644 --- a/src/infuse_iot/generated/kv_definitions.py +++ b/src/infuse_iot/generated/kv_definitions.py @@ -228,6 +228,17 @@ class fixed_location(VLACompatLittleEndianStruct): ] _pack_ = 1 + class broadcast_fixed_indoors(VLACompatLittleEndianStruct): + """Device is fixed indoors and should broadcast the fact""" + + NAME = "BROADCAST_FIXED_INDOORS" + BASE_ID = 11 + RANGE = 1 + _fields_ = [ + ("indoors", ctypes.c_uint8), + ] + _pack_ = 1 + class wifi_ssid(VLACompatLittleEndianStruct): """WiFi network name""" @@ -576,6 +587,7 @@ class secure_storage_reserved(VLACompatLittleEndianStruct): 7: board_target, 8: secondary_remote_public_key, 10: fixed_location, + 11: broadcast_fixed_indoors, 20: wifi_ssid, 21: wifi_psk, 22: wifi_channels, diff --git a/src/infuse_iot/generated/rpc_definitions.py b/src/infuse_iot/generated/rpc_definitions.py index 21ddbb5..fcca833 100644 --- a/src/infuse_iot/generated/rpc_definitions.py +++ b/src/infuse_iot/generated/rpc_definitions.py @@ -244,6 +244,16 @@ class rpc_struct_thread_stats(VLACompatLittleEndianStruct): _pack_ = 1 +class rpc_struct_data_logger_flushed(VLACompatLittleEndianStruct): + """IPv6 address""" + + _fields_ = [ + ("logger", ctypes.c_uint8), + ("num", ctypes.c_uint16), + ] + _pack_ = 1 + + class rpc_enum_bt_le_addr_type(enum.IntEnum): """Bluetooth LE address type""" @@ -279,6 +289,17 @@ class rpc_enum_data_logger(enum.IntEnum): UDP = 3 +class rpc_enum_tdf_data_logger(enum.IntEnum): + """TDF data Logger identifier""" + + FLASH_ONBOARD = 1 + FLASH_REMOVABLE = 2 + SERIAL = 4 + UDP = 8 + BT_ADV = 16 + BT_PERIPH = 32 + + class rpc_enum_zperf_data_source(enum.IntEnum): """Source for zperf data upload""" @@ -1039,6 +1060,29 @@ class response(VLACompatLittleEndianStruct): _pack_ = 1 +class tdf_data_logger_flush(RPCDefinitionBase): + """Write an annotation to the device""" + + NAME = "tdf_data_logger_flush" + HELP = "Write an annotation to the device" + DESCRIPTION = "Write an annotation to the device" + COMMAND_ID = 42 + + class request(VLACompatLittleEndianStruct): + _fields_ = [ + ("loggers", ctypes.c_uint8), + ] + _pack_ = 1 + + class response(VLACompatLittleEndianStruct): + _fields_ = [ + ("num", ctypes.c_uint8), + ] + vla_field = ("flushed", 0 * rpc_struct_data_logger_flushed) + vla_counted_by = "num" + _pack_ = 1 + + class bt_connect_infuse(RPCDefinitionBase): """Connect to an Infuse-IoT Bluetooth device""" @@ -1371,6 +1415,7 @@ class response(VLACompatLittleEndianStruct): coap_download_v2.COMMAND_ID: coap_download_v2, file_write_basic.COMMAND_ID: file_write_basic, annotate.COMMAND_ID: annotate, + tdf_data_logger_flush.COMMAND_ID: tdf_data_logger_flush, bt_connect_infuse.COMMAND_ID: bt_connect_infuse, bt_disconnect.COMMAND_ID: bt_disconnect, bt_file_copy_basic.COMMAND_ID: bt_file_copy_basic, @@ -1406,10 +1451,12 @@ class response(VLACompatLittleEndianStruct): "rpc_struct_data_logger_chunk", "rpc_struct_public_key_info_256bit", "rpc_struct_thread_stats", + "rpc_struct_data_logger_flushed", "rpc_enum_bt_le_addr_type", "rpc_enum_file_action", "rpc_enum_infuse_bt_characteristic", "rpc_enum_data_logger", + "rpc_enum_tdf_data_logger", "rpc_enum_zperf_data_source", "rpc_enum_key_id", "rpc_enum_key_action", @@ -1445,6 +1492,7 @@ class response(VLACompatLittleEndianStruct): "coap_download_v2", "file_write_basic", "annotate", + "tdf_data_logger_flush", "bt_connect_infuse", "bt_disconnect", "bt_file_copy_basic", From d2a02ce3beff20823ec1a943f2e4aa37d3b36cc1 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Thu, 16 Apr 2026 13:45:25 +1000 Subject: [PATCH 2/4] tools: rpc_cloud: string format error codes If a RPC query returns an error code, print the string version of the code as well. Signed-off-by: Jordan Yates --- src/infuse_iot/tools/rpc_cloud.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/infuse_iot/tools/rpc_cloud.py b/src/infuse_iot/tools/rpc_cloud.py index 20c8978..15d7066 100644 --- a/src/infuse_iot/tools/rpc_cloud.py +++ b/src/infuse_iot/tools/rpc_cloud.py @@ -23,6 +23,7 @@ from infuse_iot.credentials import get_api_key from infuse_iot.definitions.rpc import id_type_mapping from infuse_iot.util.ctypes import UINT32_MAX +from infuse_iot.zephyr.errno import errno class SubCommand(InfuseCommand): @@ -125,7 +126,8 @@ def query(self, client: Client): if downlink.status == DownlinkMessageStatus.COMPLETED: rpc_rsp = downlink.rpc_rsp assert isinstance(rpc_rsp, RpcRsp) - print(f" Result: {rpc_rsp.return_code}") + extra = f" ({errno(-rpc_rsp.return_code).name})" if rpc_rsp.return_code < 0 else "" + print(f" Result: {rpc_rsp.return_code}{extra}") if rpc_rsp.params: print(json.dumps(rpc_rsp.params.additional_properties, indent=4)) elif rpc_rsp.params_encoded: From 0ec67c8b8d527858a662c7582f042f5d3426b9a1 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Thu, 16 Apr 2026 13:46:17 +1000 Subject: [PATCH 3/4] tools: cloud: `kv_state` show write-only properly Fix the display of `infuse cloud kv_state` for write-only values. Signed-off-by: Jordan Yates --- src/infuse_iot/tools/cloud.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/infuse_iot/tools/cloud.py b/src/infuse_iot/tools/cloud.py index 7eac5c9..3ae9e29 100644 --- a/src/infuse_iot/tools/cloud.py +++ b/src/infuse_iot/tools/cloud.py @@ -276,7 +276,10 @@ def kv_state(self, client: Client): continue if isinstance(element.data, Unset): - table.append((key, "Not set")) + if element.crc: + table.append((key, f"Write-only (CRC: 0x{element.crc:08x})")) + else: + table.append((key, "Not set")) else: if isinstance(element.decoded, Unset): table.append((key, element.data)) From bf8783b292746a25af14e07e8334f81101bd9d3f Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Thu, 16 Apr 2026 13:43:52 +1000 Subject: [PATCH 4/4] database: try cache first Try the cache first before hitting the cloud, as the cloud request can block for many seconds if there is not network connectivity. Signed-off-by: Jordan Yates --- src/infuse_iot/database.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/infuse_iot/database.py b/src/infuse_iot/database.py index d11b127..ad6466c 100644 --- a/src/infuse_iot/database.py +++ b/src/infuse_iot/database.py @@ -158,21 +158,20 @@ def observe_security_state( self.devices[infuse_id].network_id = network_id self.devices[infuse_id].device_public_key = device_pub_key - client = Client(base_url="https://api.infuse-iot.com").with_headers({"x-api-key": f"Bearer {get_api_key()}"}) + # Try the cache first + cache_key = self._from_cache(infuse_id, device_pub_key) + if cache_key is not None: + self.devices[infuse_id].shared_key = cache_key + return + client = Client(base_url="https://api.infuse-iot.com").with_headers({"x-api-key": f"Bearer {get_api_key()}"}) with client as client: body = Key(base64.b64encode(device_pub_key).decode("utf-8")) - try: - response = get_shared_secret.sync(client=client, body=body) - if response is not None: - key = base64.b64decode(response.key) - self.devices[infuse_id].shared_key = key - self._update_cache(infuse_id, device_pub_key, key) - except Exception as e: - cache_key = self._from_cache(infuse_id, device_pub_key) - if cache_key is None: - raise e - self.devices[infuse_id].shared_key = cache_key + response = get_shared_secret.sync(client=client, body=body) + if response is not None: + key = base64.b64decode(response.key) + self.devices[infuse_id].shared_key = key + self._update_cache(infuse_id, device_pub_key, key) def _network_key(self, network_id: int, interface: bytes, gps_time: int) -> bytes: if network_id not in self._network_keys: