Core connection component of the bot controlling system, which provides the infrastructure for framework nodes to communicate via Redis.
- Nodes are Python scripts named
node_*.py, placed in the parent directory ofrobus-core/ - Each node communicates with others through a shared Redis instance using the
TelemetryBrokerlibrary (libs/lib_telemtrybroker.py) utils/detect_nodes.pyscans for nodes and writes their paths totmp/node_list.csvutils/starter.pydetects and launches all nodes, each in its own terminal window- To disable a node without deleting it, prefix its filename with
_(e.g._node_sensor.py)
robus-core/
├── libs/ # Shared libraries (TelemetryBroker, sensor drivers)
├── tmp/ # Runtime output (gitignored)
├── utils/ # Core python scripts (starter, stop, node detection)
└── various helper scripts
../ # Parent directory — place node_*.py files herebash setup_redis.shLinux:
bash configure_startup.shWindows:
configure_startup.batLinux:
bash start.shWindows:
start.batA '--debug' flag can be added to prevent nodes from closing automatically on error or process end.
This activates the virtual environment if one is found at venv/ or env/, then launches utils/starter.py.
Linux:
bash stop.shWindows:
stop.batThis activates the virtual environment if one is found at venv/ or env/, then launches utils/stop.py.
If a virtual environment exists at robus-core/venv/ or robus-core/env/, the start scripts activate it automatically. To create one:
python -m venv venv
venv/Scripts/activate # Windows
source venv/bin/activate # Linux
pip install redis psutilA node is a standalone Python script that communicates with other nodes via Redis.
- The filename must start with
node_: e.g.node_sensor.py - The file belongs in the parent directory of
robus-core/:
my-project/
├── robus-core/ ← framework
├── node_sensor.py ← your node
└── node_motor.py ← your nodePrefixing a filename with
_(e.g._node_sensor.py) excludes the node from autostart without deleting it.
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "robus-core"))
from libs.lib_telemtrybroker import TelemetryBroker
broker = TelemetryBroker() # connects to localhost:6379
# broker = TelemetryBroker(host="...", port=6379, db=0) # optionalThe broker automatically registers the node in Redis on startup. The key name is the filename without .py.
broker.set("motor_speed", 42)
broker.set("status", "running")
broker.set("armed", True) # bool is automatically cast to int (0/1)
broker.setmulti({
"x": 1.5,
"y": -3.0,
"z": 0.0,
})speed = broker.get("motor_speed") # single value
data = broker.getmulti(["x", "y", "z"]) # multiple values → dict
all = broker.getall() # entire Redis contents → dict
imu = broker.getallWith("imu_*") # all keys matching a prefix → dictValues are automatically cast to int, float, or str depending on their content.
def on_change(key, value):
print(f"{key} changed: {value}")
broker.setcallback(["motor_speed", "armed"], on_change)
broker.receiver_loop() # blocking — call at the end of main()receiver_loop() runs indefinitely and invokes the callback whenever a monitored value changes.
| Value | Meaning |
|---|---|
0 |
No access |
1 |
Read only |
2 |
Read, write, delete (default) |
broker.get_node_permission() # returns 0, 1, or 2The default is 2. Another node can restrict permissions via broker.set("node_sensor", 1).
import sys, os, time
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "robus-core"))
from libs.lib_telemtrybroker import TelemetryBroker
broker = TelemetryBroker()
while True:
broker.set("sensor_value", 42)
print(broker.getall())
time.sleep(0.1)The TelemetryBroker destructor calls close() automatically, which removes the node's key from Redis. To call it explicitly:
broker.close()