From 1c6c2e56ecdee127d27014964d6e6cc318882a9c Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 2 Aug 2026 10:39:20 +1000 Subject: [PATCH 1/3] scripts: add file documentation Add file level documentation to all scripts in the repository. This includes a brief description of the script's purpose, usage instructions, and any relevant notes or warnings. Assisted-by: GPT-5.5 Signed-off-by: Jordan Yates --- scripts/apn_set.py | 7 +++++++ scripts/custom_tools/custom_tool.py | 7 ++++++- scripts/device_kv_update.py | 7 +++++++ scripts/elf_task_schedules.py | 8 ++++++++ scripts/mqtt_read.py | 7 ++++++- scripts/reboot_count_reset.py | 7 +++++++ scripts/regenerate_api_client.py | 7 ++++++- 7 files changed, 47 insertions(+), 3 deletions(-) diff --git a/scripts/apn_set.py b/scripts/apn_set.py index 4de53d2f..3769e6ef 100755 --- a/scripts/apn_set.py +++ b/scripts/apn_set.py @@ -1,4 +1,11 @@ #!/usr/bin/env python3 +"""Configure LTE APN settings on locally discoverable Infuse-IoT devices. + +The script listens for announce packets for a target application ID, opens a +local command connection to each matching device, and writes the LTE PDP +configuration KV slot with the requested APN and IP family. A live table tracks +devices that were updated or already held the requested value. +""" import argparse import ctypes diff --git a/scripts/custom_tools/custom_tool.py b/scripts/custom_tools/custom_tool.py index 406549d1..e6a814b4 100644 --- a/scripts/custom_tools/custom_tool.py +++ b/scripts/custom_tools/custom_tool.py @@ -1,6 +1,11 @@ #!/usr/bin/env python3 -"""Example out-of-tree tool""" +"""Provide a minimal example of an out-of-tree Infuse command. + +The command registers a custom subcommand that accepts an ``--echo`` argument +and prints it back, demonstrating the shape expected by ``InfuseCommand`` +plugins without depending on project-specific behavior. +""" __author__ = "Jordan Yates" __copyright__ = "Copyright 2025, Embeint Holdings Pty Ltd" diff --git a/scripts/device_kv_update.py b/scripts/device_kv_update.py index 8729c0a5..d24c22bc 100755 --- a/scripts/device_kv_update.py +++ b/scripts/device_kv_update.py @@ -1,4 +1,11 @@ #!/usr/bin/env python3 +"""Schedule cloud-side key-value updates for selected Infuse-IoT devices. + +Edit the ``config`` block in this file with target device IDs, the KV key ID, +and the desired base64-encoded value. The script checks the current cloud KV +entry for each device and schedules an update only when the stored value does +not already match. +""" import base64 diff --git a/scripts/elf_task_schedules.py b/scripts/elf_task_schedules.py index 9639053a..f8224ea4 100755 --- a/scripts/elf_task_schedules.py +++ b/scripts/elf_task_schedules.py @@ -1,4 +1,12 @@ #!/usr/bin/env python3 +"""Extract initialized ``struct task_schedule`` arrays from a Zephyr ELF. + +The script walks DWARF variable/type metadata to find arrays whose element type +is ``struct task_schedule``, maps the selected variable back to initialized ELF +file bytes, and prints each array element as hex or base64. It exits with a +diagnostic when no initialized array is found or when multiple candidates need +to be disambiguated with ``--name``. +""" import argparse import base64 diff --git a/scripts/mqtt_read.py b/scripts/mqtt_read.py index ae0638e5..afb70055 100644 --- a/scripts/mqtt_read.py +++ b/scripts/mqtt_read.py @@ -1,6 +1,11 @@ #!/usr/bin/env python3 -"""Read device packets from the Infuse-IoT Cloud MQTT broker""" +"""Read device packets from the Infuse-IoT Cloud MQTT broker. + +The script subscribes to an organisation-wide MQTT topic, optionally narrowed +to one device, and prints incoming packets as raw JSON or formatted metadata, +route, and TDF tables. +""" __author__ = "Jace Galvin" __copyright__ = "Copyright 2025, Embeint Holdings Pty Ltd" diff --git a/scripts/reboot_count_reset.py b/scripts/reboot_count_reset.py index c989bc9f..dd326d99 100755 --- a/scripts/reboot_count_reset.py +++ b/scripts/reboot_count_reset.py @@ -1,4 +1,11 @@ #!/usr/bin/env python3 +"""Reset reboot counters for locally discoverable Infuse-IoT devices. + +The script watches local announce packets for one or more application IDs, +connects to devices whose reported reboot count differs from the requested +value, and writes the reboot-count KV slot through the standard KV RPC. A live +terminal table reports updated and already-matching devices. +""" import argparse diff --git a/scripts/regenerate_api_client.py b/scripts/regenerate_api_client.py index 2b00e3fa..8090067c 100755 --- a/scripts/regenerate_api_client.py +++ b/scripts/regenerate_api_client.py @@ -1,5 +1,10 @@ #!/usr/bin/env python3 -"""Regenerate the Infuse-IoT OpenAPI client.""" +"""Regenerate the checked-in Infuse-IoT OpenAPI client. + +The script runs ``openapi-python-client`` against a supplied OpenAPI YAML file, +locates the generated package in a temporary staging directory, and atomically +replaces ``src/infuse_iot/api_client`` while preserving its existing README. +""" from __future__ import annotations From e6dbc2f4855c618c2aaf0485a0341ee1c78a761b Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 2 Aug 2026 11:04:54 +1000 Subject: [PATCH 2/3] socket_comms: ensure multicast group exists on Windows Add the `LocalServer` output socket to the multicast group on Windows to ensure the group exists before we try to send to it. Signed-off-by: Jordan Yates --- src/infuse_iot/socket_comms.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/infuse_iot/socket_comms.py b/src/infuse_iot/socket_comms.py index 487214de..db02843d 100644 --- a/src/infuse_iot/socket_comms.py +++ b/src/infuse_iot/socket_comms.py @@ -275,6 +275,12 @@ def __init__(self, multicast_address): self._output_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) self._output_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton("127.0.0.1")) self._output_addr = multicast_address + if sys.platform == "win32": + # On Windows, trying to send to a multicast socket that has no receivers in the group will result in an + # error. To avoid this, we add the output socket to the group, even though we don't expect to receive + # anything on it. + mreq = struct.pack("4s4s", socket.inet_aton(multicast_address[0]), socket.inet_aton("127.0.0.1")) + self._output_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) # Single input socket unicast_address = ("localhost", multicast_address[1] + 1) self._input_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) From ef3f9797b16cd9872d50dc86809b495fb607f661 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 2 Aug 2026 10:45:47 +1000 Subject: [PATCH 3/3] tests: socket_comms: test broadcast without clients Ensure that the local server can broadcast to the multicast group even if there are no clients connected. This ensures the gateway doesn't crash before any client tools are connected. Signed-off-by: Jordan Yates --- tests/test_socket_comms.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_socket_comms.py b/tests/test_socket_comms.py index 5550d5cc..d50eadf3 100644 --- a/tests/test_socket_comms.py +++ b/tests/test_socket_comms.py @@ -12,8 +12,17 @@ def test_socket_comms(): multicast_addr = comms.default_multicast_address() # Increment port by 1 so we can run the tests in parallel with a real instance test_addr = (multicast_addr[0], multicast_addr[1] + 1) + + # Create the server first server = comms.LocalServer(test_addr) + + # Send a message before any client is connected + broadcast_msg = comms.ClientNotificationObservedDevices({}) + server.broadcast(broadcast_msg) + + # Create a client that receives from the server, shouldn't receive the broadcast message client = comms.LocalClient(test_addr) + assert client.receive() is None # Send request to server request = comms.GatewayRequestCommsCheck()