Listening to Events
pycom does not reply on the same TCP connection you used to send a request. Because commands can take a variable amount of time to complete, keeping that connection open would block your application until the node finishes. Instead, pycom closes the connection immediately after receiving your request and, once ready, opens a new outbound connection back to the IP it observed from your connection and the port you specified in the request payload, delivering the payload as a JSON string encoded in UTF-8.
Your application must therefore run its own TCP server on that port, ready to accept incoming connections from the node. Each event arrives as a separate, short-lived TCP connection — the node connects, sends the JSON, and closes the connection.
Event types
All incoming events share the same base fields that identify the sender, plus a type_ field that indicates what kind of event it is.
Output
Sent by pycom after executing a command. The output field contains the stdout of the command (or stderr if the command failed).
| Field | Type | Description |
|---|---|---|
type_ | string | "output" |
output | string | stdout of the executed command, or stderr on failure |
{
"id": "81639cd4",
"name": "rigsters-controller",
"ip": "192.168.0.22",
"port": 5000,
"version": "0.14.0",
"coordinator": false,
"type_": "output",
"output": "BOARDIO_CLI: Sent: \"uSeq\" to FIFO file\nBOARDIO_CLI: Sent: \"runSeq\" to FIFO file\n"
}
Message
A text message sent by pycom to your application.
| Field | Type | Description |
|---|---|---|
type_ | string | "message" |
message | string | The message content |
{
"id": "81639cd4",
"name": "rigsters-controller",
"ip": "192.168.0.22",
"port": 5000,
"version": "0.14.0",
"coordinator": false,
"type_": "message",
"message": "Sequence complete"
}
Unit info
Sent once by the LA4 node to your integration when both of the following are true:
- Your application has set
coordinator: truein its payloads. - The node's hardware information is available (boardio has finished initialising).
Whichever condition is met last triggers the send. If your application is already known as a coordinator when hardware info becomes available, the event is sent at that point. If hardware info is already available when your application is first detected as a coordinator, the event is sent immediately on that first detection.
It is not re-sent on subsequent heartbeats or reconnections from the same coordinator.
| Field | Type | Description |
|---|---|---|
type_ | string | "unit_info" |
wiringpi_version | string | WiringPi library version installed on the unit |
boardio_version | string | boardio library version |
firmware_version | string | Firmware version running on the MCU |
unit_type | string | Role of the unit (e.g. "light_array", "human_scanning") |
mcu_type | string | MCU model identifier |
mac_address | string | MAC address of the unit's network interface |
{
"id": "81639cd4",
"name": "rigsters-controller",
"ip": "192.168.0.22",
"port": 5000,
"version": "0.14.0",
"coordinator": false,
"type_": "unit_info",
"wiringpi_version": "2.61",
"boardio_version": "1.3.0",
"firmware_version": "2.0.4",
"unit_type": "light_array",
"mcu_type": "RP2040",
"mac_address": "dc:a6:32:1b:4e:f0"
}
Setting up a listener
Bind a TCP server to the same port you include in your request payloads. In the examples on the previous page that port is 5000.
- Python
- C#
import socket
import json
HOST = "0.0.0.0"
PORT = 5000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((HOST, PORT))
server.listen()
print(f"Listening on port {PORT}...")
while True:
conn, addr = server.accept()
with conn:
data = b""
while chunk := conn.recv(4096):
data += chunk
payload = json.loads(data.decode("utf-8"))
type_ = payload.get("type_")
if type_ == "output":
print(f"[{payload['name']}] output: {payload['output']}")
elif type_ == "message":
print(f"[{payload['name']}] message: {payload['message']}")
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
var listener = new TcpListener(IPAddress.Any, 5000);
listener.Start();
Console.WriteLine("Listening on port 5000...");
while (true)
{
using var client = await listener.AcceptTcpClientAsync();
using var stream = client.GetStream();
using var reader = new StreamReader(stream, Encoding.UTF8);
var json = await reader.ReadToEndAsync();
var payload = JsonDocument.Parse(json).RootElement;
var name = payload.GetProperty("name").GetString();
switch (payload.GetProperty("type_").GetString())
{
case "output":
Console.WriteLine($"[{name}] output: {payload.GetProperty("output").GetString()}");
break;
case "message":
Console.WriteLine($"[{name}] message: {payload.GetProperty("message").GetString()}");
break;
}
}