diff --git a/scripts/apn_set.py b/scripts/apn_set.py index 4de53d2..3769e6e 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 406549d..e6a814b 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 8729c0a..d24c22b 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 9639053..f8224ea 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 ae0638e..afb7005 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 c989bc9..dd326d9 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 2b00e3f..8090067 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 diff --git a/src/infuse_iot/socket_comms.py b/src/infuse_iot/socket_comms.py index 487214d..db02843 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) diff --git a/tests/test_socket_comms.py b/tests/test_socket_comms.py index 5550d5c..d50eadf 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()