Python OOCSI Client
The OOCSI Python client (oocsi-python) allows Python scripts to easily send and receive messages, subscribe to channels, synchronize variables, and participate in synchronous call-response services over the OOCSI network. It is ideal for data analysis, AI/machine learning prototyping, hardware interfacing (e.g., Raspberry Pi), and desktop automation.
Installation
Install the library using pip:
pip install oocsi
The source code and distribution details are available on GitHub: iddi/oocsi-python.
Connecting to OOCSI
To connect to an OOCSI server, import the OOCSI class and provide a client name and server address:
from oocsi import OOCSI
# Tip: Use '####' in the client name; the server will replace it with random numbers to guarantee a unique handle
oocsi = OOCSI('data_collector_####', 'localhost')
If connecting to a remote server on a custom port:
oocsi = OOCSI('data_collector_####', 'oocsi.example.com', 4444)
Sending Messages
You can send key-value data to a channel (for broadcasting) or directly to another client:
# Send data to a channel
oocsi.send('livingroom_lights', {
'power': True,
'brightness': 85,
'color': '#FFAA00'
})
# Send data directly to an individual client
oocsi.send('display_device_1', {
'notification': 'Doorbell rang!'
})
Receiving Messages
Using Decorators (Recommended)
You can register event handlers using the @oocsi.event decorator:
# Handle messages from a channel
@oocsi.event('livingroom_lights')
def handle_lights(sender, recipient, data):
print(f"Message from {sender}: {data}")
if 'brightness' in data:
print("Updated brightness to:", data['brightness'])
# Handle direct messages sent specifically to this client
@oocsi.event()
def handle_direct(sender, recipient, data):
print(f"Direct message from {sender}: {data}")
Using Subscription Functions
Alternatively, you can subscribe with a callback function:
def process_message(sender, recipient, data):
print(f"Received from {sender}: {data}")
oocsi.subscribe('livingroom_lights', process_message)
OOCSI Variables (State Synchronization)
OOCSI variables allow you to synchronize state automatically across multiple clients on a channel without manually drafting message payloads:
# Link a variable to the 'room_temperature' variable on channel 'home'
temp = oocsi.variable('home', 'room_temperature')
# Read current synchronized value
print("Current temperature:", temp.get())
# Update the value (automatically broadcasts the new state to all connected clients)
temp.set(22.5)
Synchronous Call-Response (RPC)
When you need an immediate answer from another client rather than fire-and-forget messaging, you can use the call-response pattern.
Providing a Service (Responder)
@oocsi.responder('weather_service', 'get_forecast')
def provide_forecast(data):
city = data.get('city', 'Eindhoven')
return {'city': city, 'forecast': 'Sunny', 'temp': 23}
Calling a Service
# Call service on channel 'weather_service' with operation 'get_forecast' (timeout in seconds)
response = oocsi.call('weather_service', 'get_forecast', {'city': 'Amsterdam'}, timeout=2.0)
if response:
print("Forecast response:", response)
else:
print("Service request timed out.")
Complete Example
import time
from oocsi import OOCSI
# Connect with a randomized handle
oocsi = OOCSI('weather_station_####', 'localhost')
# Subscribe to incoming sensor data
@oocsi.event('environment')
def on_environment(sender, recipient, data):
print(f"[{sender}] Temperature: {data.get('temp')} C, Humidity: {data.get('humidity')}%")
# Publish simulated readings
try:
while True:
oocsi.send('environment', {
'temp': 21.4,
'humidity': 55.0
})
time.sleep(5)
except KeyboardInterrupt:
print("Stopping OOCSI client...")
oocsi.stop()