Skip to main content

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).

FieldTypeDescription
type_string"output"
outputstringstdout 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.

FieldTypeDescription
type_string"message"
messagestringThe 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: true in 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.

FieldTypeDescription
type_string"unit_info"
wiringpi_versionstringWiringPi library version installed on the unit
boardio_versionstringboardio library version
firmware_versionstringFirmware version running on the MCU
unit_typestringRole of the unit (e.g. "light_array", "human_scanning")
mcu_typestringMCU model identifier
mac_addressstringMAC 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.

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']}")