diff --git a/src/infuse_iot/epacket/packet.py b/src/infuse_iot/epacket/packet.py index 1a6ba04..27bc53e 100644 --- a/src/infuse_iot/epacket/packet.py +++ b/src/infuse_iot/epacket/packet.py @@ -189,8 +189,11 @@ def from_serial(cls, database: DeviceDatabase, serial_frame: bytes) -> list[Self decr_header = CtypePacketReceived.DecryptedHeader.from_buffer_copy(packet_bytes) del packet_bytes[: ctypes.sizeof(decr_header)] - # Notify database of BT Addr -> Infuse ID mapping - database.observe_device(decr_header.device_id, bt_addr=addr.val) + # Notify database of BT Addr -> Infuse ID mapping and key metadata + if decr_header.flags & Flags.ENCR_DEVICE: + database.observe_device(decr_header.device_id, device_key_id=decr_header.key_id, bt_addr=addr.val) + else: + database.observe_device(decr_header.device_id, network_id=decr_header.key_id, bt_addr=addr.val) bt_hop = HopReceived( decr_header.device_id, diff --git a/src/infuse_iot/tools/gateway.py b/src/infuse_iot/tools/gateway.py index 5600f30..309aa75 100644 --- a/src/infuse_iot/tools/gateway.py +++ b/src/infuse_iot/tools/gateway.py @@ -21,7 +21,7 @@ import infuse_iot.definitions.rpc as defs import infuse_iot.definitions.tdf as tdf_defs import infuse_iot.epacket.interface as interface -from infuse_iot import rpc, tdf +from infuse_iot import tdf from infuse_iot.commands import InfuseCommand from infuse_iot.common import InfuseID, InfuseType from infuse_iot.database import ( @@ -295,8 +295,8 @@ def _pub_keys_cb(self, pkt: PacketReceived, rc: int, response: bytes, _): # Notify connection success self._connected_notification(infuse_id) - def _bt_connect_cb(self, pkt: PacketReceived, rc: int, response: bytes, _): - resp = defs.bt_connect_infuse.response.from_buffer_copy(pkt.payload[ctypes.sizeof(rpc.ResponseHeader) :]) + def _bt_connect_cb(self, _pkt: PacketReceived, rc: int, response: bytes, _): + resp = defs.bt_connect_infuse.response.from_buffer_copy(response) if_addr = interface.Address.BluetoothLeAddr.from_rpc_struct(resp.peer) infuse_id = self._common.ddb.infuse_id_from_bluetooth(if_addr) diff --git a/src/infuse_iot/tools/ota_upgrade.py b/src/infuse_iot/tools/ota_upgrade.py index ebed674..02d7108 100644 --- a/src/infuse_iot/tools/ota_upgrade.py +++ b/src/infuse_iot/tools/ota_upgrade.py @@ -21,7 +21,7 @@ from infuse_iot.commands import InfuseCommand from infuse_iot.common import InfuseID -from infuse_iot.definitions.rpc import bt_file_copy_basic, file_write_basic, rpc_enum_file_action +from infuse_iot.definitions.rpc import bt_file_copy_basic, file_write_basic, rpc_enum_file_action, time_set from infuse_iot.epacket.packet import Auth, HopReceived from infuse_iot.generated.tdf_definitions import readings from infuse_iot.rpc_client import RpcClient @@ -29,6 +29,7 @@ GatewayRequestConnectionRequest, LocalClient, ) +from infuse_iot.time import InfuseTime from infuse_iot.util.argparse import InfuseDeviceId, ValidFile, ValidRelease, add_server_port_parser from infuse_iot.util.crc import crc16_ccitt from infuse_iot.zephyr.errno import errno @@ -163,6 +164,20 @@ def gateway_diff_load(self): sys.exit(f"Failed to save diff file to gateway (({errno.strerror(-return_code)}))") print(f"'{self._single_diff}' written to gateway") + def set_device_time(self, mtu: int, infuse_id: int) -> bool: + rpc_client = RpcClient(self._client, mtu, infuse_id) + rpc_client.set_timeout(2.0) + + params = time_set.request(InfuseTime.epoch_time_from_unix(time.time())) + hdr, _rsp = rpc_client.run_standard_cmd( + time_set.COMMAND_ID, + Auth.DEVICE, + bytes(params), + time_set.response.from_buffer_copy, + ) + # Command completed and succeeded + return hdr is not None and hdr.return_code == 0 + def run_file_upload(self, live: Live, mtu: int, source: HopReceived): self.state_update(live, f"Uploading patch file to {source.infuse_id:016X}") rpc_client = RpcClient(self._client, mtu, source.infuse_id) @@ -186,6 +201,7 @@ def run_file_upload(self, live: Live, mtu: int, source: HopReceived): def run_file_copy(self, live: Live, mtu: int, source: HopReceived): self.state_update(live, f"Copying patch file to {source.infuse_id:016X}") rpc_client = RpcClient(self._client, mtu, InfuseID.GATEWAY) + rpc_client.set_timeout(60.0) params = bt_file_copy_basic.request( source.interface_address.val.to_rpc_struct(), @@ -215,6 +231,11 @@ def run(self): if self._single_diff: self.gateway_diff_load() + # Set the gateways time at script startup + with self._client.connection(InfuseID.GATEWAY, GatewayRequestConnectionRequest.DataType.COMMAND, 10) as mtu: + if not self.set_device_time(mtu, InfuseID.GATEWAY): + sys.exit("Failed to set time on local gateway") + with Live(self.progress_table(), refresh_per_second=4) as live: for source, announce in self._client.observe_announce(): self.state_update(live, "Scanning") @@ -302,6 +323,9 @@ def run(self): with self._client.connection( source.infuse_id, GatewayRequestConnectionRequest.DataType.COMMAND, self._conn_timeout ) as mtu: + # Set time on the remote device to keep keys in sync + if not self.set_device_time(mtu, source.infuse_id): + break if self._single_diff: self.run_file_copy(live, mtu, source) else: