diff --git a/scripts/mqtt_read.py b/scripts/mqtt_read.py index 613dc8a..049dadf 100644 --- a/scripts/mqtt_read.py +++ b/scripts/mqtt_read.py @@ -22,18 +22,22 @@ class OutputFormat(enum.Enum): JSON = "json" TABLE = "table" + class ConnectionError(Exception): pass + def get_enum_name(enum, value): try: return enum(value).name except ValueError: return None + def get_payload_type(payload_type): return get_enum_name(InfuseType, payload_type) + def print_metadata_table(data): metadata_table = [ ["Device ID", data["deviceId"]], @@ -41,15 +45,17 @@ def print_metadata_table(data): ["Timestamp", data["time"]], ["Payload Type", get_payload_type(data["payloadType"])], ["Sequence", data["sequence"]], - ["Key ID", base64.b64decode(data["keyId"]).hex()] + ["Key ID", base64.b64decode(data["keyId"]).hex()], ] print("[Metadata]") print(tabulate.tabulate(metadata_table, tablefmt="grid")) + def get_interface_type(interface_type): return get_enum_name(InterfaceID, interface_type) + def print_route_table(route): route_table = [ ["Type", get_interface_type(route["type"])], @@ -64,11 +70,11 @@ def print_route_table(route): route_table.append(["UDP Address", route["udp"]["address"]]) route_table.append(["Arrival Time", route["udp"]["time"]]) - print("[Route]") print(tabulate.tabulate(route_table, tablefmt="grid")) -def flatten_tdf(tdf, parent_key=''): + +def flatten_tdf(tdf, parent_key=""): items = [] for k, v in tdf.items(): new_key = f"{parent_key}->{k}" if parent_key else k @@ -80,6 +86,7 @@ def flatten_tdf(tdf, parent_key=''): items.append((new_key, v)) return dict(items) + def print_tdfs_table(tdfs, packet_time): table = [] for tdf in tdfs: @@ -89,13 +96,12 @@ def print_tdfs_table(tdfs, packet_time): tdf_time = tdf.get("time", packet_time) for key, value in flatten_tdf(tdf["fields"]).items(): - table.append( - [tdf_id, tdf_name, key, value, tdf_time] - ) + table.append([tdf_id, tdf_name, key, value, tdf_time]) print("[TDFs]") print(tabulate.tabulate(table, headers=["TDF ID", "Name", "Field", "Value", "Time"], tablefmt="grid")) + def print_table(data): print_metadata_table(data) @@ -107,6 +113,7 @@ def print_table(data): print() + def on_message(client, userdata, message): payload = message.payload.decode("utf-8") output = userdata["output"] @@ -116,6 +123,7 @@ def on_message(client, userdata, message): data = json.loads(payload) print_table(data) + def on_connect(client, userdata, flags, reason_code, properties): if reason_code != 0: raise ConnectionError(reason_code) @@ -127,6 +135,7 @@ def on_connect(client, userdata, flags, reason_code, properties): topic = userdata["topic"] client.subscribe(topic) + def main(host, port, username, password, organisation, device, output): topic = f"organisation/{organisation}" if device: @@ -150,6 +159,7 @@ def main(host, port, username, password, organisation, device, output): except ConnectionError as e: sys.exit(f"Connection failed: {e}") + if __name__ == "__main__": parser = argparse.ArgumentParser( description="Read device packets from the Infuse-IoT Cloud MQTT broker", @@ -157,42 +167,45 @@ def main(host, port, username, password, organisation, device, output): ) parser.add_argument( - "--broker", "-b", + "--broker", + "-b", type=str, default="mqtt.dev.infuse-iot.com", help="MQTT broker address", ) parser.add_argument( - "--port", "-p", + "--port", + "-p", type=int, default=1883, help="MQTT broker port", ) parser.add_argument( - "--username", "-u", + "--username", + "-u", type=str, required=True, help="MQTT username", ) + parser.add_argument("--password", "-P", type=str, required=True, help="MQTT password") parser.add_argument( - "--password", "-P", - type=str, - required=True, - help="MQTT password") - parser.add_argument( - "--organisation", "--org", "-O", + "--organisation", + "--org", + "-O", type=str, required=True, help="ID of organisation to read packets from", ) parser.add_argument( - "--device", "-d", + "--device", + "-d", type=lambda x: int(x, 0), required=False, help="Infuse ID of device to read packets from (in hex)", ) parser.add_argument( - "--output", "-o", + "--output", + "-o", type=OutputFormat, default=OutputFormat.JSON, choices=list(OutputFormat), diff --git a/src/infuse_iot/tools/cloud.py b/src/infuse_iot/tools/cloud.py index 9c8afeb..46b9ce8 100644 --- a/src/infuse_iot/tools/cloud.py +++ b/src/infuse_iot/tools/cloud.py @@ -18,7 +18,11 @@ get_board_by_id, get_boards, ) -from infuse_iot.api_client.api.device import get_device_by_device_id, get_device_state_by_id +from infuse_iot.api_client.api.device import ( + get_device_by_device_id, + get_device_last_route_by_device_id, + get_device_state_by_id, +) from infuse_iot.api_client.api.organisation import ( create_organisation, get_all_organisations, @@ -180,6 +184,7 @@ def info(self, client): org = get_organisation_by_id.sync(client=client, id=info.organisation_id) board = get_board_by_id.sync(client=client, id=info.board_id) state = get_device_state_by_id.sync(client=client, id=info.id) + route = get_device_last_route_by_device_id.sync(client=client, device_id=id_str) table: list[tuple[str, Any]] = [ ("UUID", info.id), @@ -201,8 +206,13 @@ def info(self, client): table += [("Application ID", f"0x{state.application_id:08x}")] if v: table += [("Version", f"{v.major}.{v.minor}.{v.revision}+{v.build_num:08x}")] - if state.last_route_interface: - table += [("Last Heard", state.last_route_interface)] + if route is not None: + table += [ + ("~~~Latest Route~~~", ""), + ("Interface", route.interface.upper()), + ] + if route.bt_adv: + table += [("BT Address", f"{route.bt_adv.address} ({route.bt_adv.type_})")] print(tabulate(table)) diff --git a/src/infuse_iot/tools/rpc_cloud.py b/src/infuse_iot/tools/rpc_cloud.py index 5c72e46..fd1bd15 100644 --- a/src/infuse_iot/tools/rpc_cloud.py +++ b/src/infuse_iot/tools/rpc_cloud.py @@ -34,7 +34,7 @@ def add_parser(cls, parser): parser_queue = subparser.add_parser("queue", help="Queue a RPC to be sent") parser_queue.set_defaults(_tool_action="queue") parser_queue.add_argument("--id", required=True, type=lambda x: int(x, 0), help="Infuse ID to run command on") - parser_queue.add_argument("--timeout", type=int, default=600, help="Timeout to send command in seconds") + parser_queue.add_argument("--queue-timeout", type=int, default=600, help="Timeout to send command in seconds") command_list_parser = parser_queue.add_subparsers(title="commands", metavar="", required=True) for _, name, _ in pkgutil.walk_packages(wrappers.__path__): @@ -62,7 +62,7 @@ def __init__(self, args: argparse.Namespace): def queue(self, client: Client): infuse_id = f"{self._args.id:016x}" command: InfuseRpcCommand = self._args.rpc_class(self._args) - timeout_ms = 1000 * self._args.timeout + timeout_ms = 1000 * self._args.queue_timeout assert hasattr(command, "COMMAND_ID")