31. Device Integration
MALDA supports interaction with physical devices through serial communication (USB) and HTTP/REST APIs (WiFi). This enables control of Arduino, ESP32, Raspberry Pi, smart home devices, and other IoT equipment.
31.1 Overview
Why Device Integration?
Device integration allows MALDA programs to:
- Control physical hardware (robots, sensors, actuators)
- Build IoT applications and smart home automation
- Create multi-device systems coordinated by actors
- Combine AI agents with physical world interaction
Communication Methods
MALDA supports two primary communication methods:
- Serial Communication: Direct USB connection to devices (Arduino, microcontrollers)
- HTTP/REST: Network-based communication for WiFi-enabled devices (ESP32, Raspberry Pi, smart home devices)
When to Use Each Method
| Method | Best For | Advantages | Limitations |
|---|---|---|---|
| Serial | USB-connected devices, simple projects | Low latency, simple setup, no network required | Requires physical connection, limited range |
| HTTP/REST | WiFi devices, multiple devices, remote control | Wireless, scalable, works over network/internet | Requires network setup, slightly higher latency |
31.2 Serial Communication
The SerialConnection class provides low-level serial port communication for USB-connected devices.
Constructor
var serial = new SerialConnection();
Creates a new serial connection instance. The connection is established via the connect() method.
Methods
connect(portName, baudRate)→bool: Open serial connection to specified portdisconnect(): Close the serial connectionwrite(data): Send data string to deviceread()→string: Read all available data from deviceread(byteCount)→string: Read specified number of bytesreadLine()→string: Read a line (until newline character)
Properties
isConnected(bool): Check if connection is active
Example
var serial = new SerialConnection();
var connected = serial.connect("COM3", 9600);
if (connected) {
serial.write("Hello Arduino\n");
var response = serial.readLine();
print("Response: " + response);
serial.disconnect();
}
Port Names
Port names vary by operating system:
- Windows:
"COM3","COM4", etc. - Linux:
"/dev/ttyUSB0","/dev/ttyACM0", etc. - macOS:
"/dev/cu.usbserial-*","/dev/cu.usbmodem*", etc.
31.3 HTTP/REST Devices
For WiFi-enabled devices, use the RestClient class (see 28. REST Web Client for full documentation). This works with any device that exposes HTTP/REST APIs.
Example: ESP32 Device
var device = new RestClient("http://192.168.1.100");
// Read sensor value
var response = device.get("/sensor/temperature");
if (response.ok) {
var data = parseJSON(response.body);
print("Temperature: " + data.value);
}
// Control actuator
device.post("/relay/1", {"state": "on"});
Authentication
Many devices require authentication:
var device = new RestClient("http://192.168.1.100");
device.setAuth("Bearer", "your-api-token");
31.4 Arduino Integration
The ArduinoConnection class provides a high-level interface for controlling Arduino devices, supporting both serial and HTTP communication modes.
Constructor
ArduinoConnection supports two modes:
// HTTP mode (WiFi-enabled devices like ESP32)
var arduino = new ArduinoConnection("http://192.168.1.100");
// Serial mode (USB connection)
var arduino = new ArduinoConnection("COM3", 9600);
Connection
connect()→bool: Establish connection to Arduinodisconnect(): Close connectionisConnected(bool): Check connection status
Digital I/O
digitalWrite(pin, value): Set digital pin HIGH (true) or LOW (false)digitalRead(pin)→bool: Read digital pin value
Analog I/O
analogRead(pin)→int: Read analog pin (0-1023)analogWrite(pin, value): Write PWM value (0-255) to pin
Pin Configuration
pinMode(pin, mode): Configure pin mode.modemust be:"INPUT": Digital input"OUTPUT": Digital output"INPUT_PULLUP": Digital input with internal pull-up resistor
Example: Basic Arduino Control
// Connect via serial
var arduino = new ArduinoConnection("COM3", 9600);
arduino.connect();
// Configure pin 13 as OUTPUT (LED)
arduino.pinMode(13, "OUTPUT");
// Blink LED
for (var i = 0; i < 5; i = i + 1) {
arduino.digitalWrite(13, true);
sleep(500);
arduino.digitalWrite(13, false);
sleep(500);
}
// Read analog sensor
var sensorValue = arduino.analogRead(0);
print("Sensor value: " + sensorValue);
arduino.disconnect();
Arduino Sketch Setup
To use Arduino with MALDA, upload the bridge sketch to your Arduino board. The sketch listens for commands and executes them.
See Examples/Arduino/arduino_bridge.ino for the complete sketch.
Protocol:
- Commands:
DIGITAL_WRITE:pin:value\n - Responses:
OK:value\norERROR:message\n
31.5 ESP32/ESP8266
ESP32 and ESP8266 devices can be controlled via HTTP/REST after uploading the bridge sketch.
WiFi Setup
Edit the ESP32 sketch to configure WiFi credentials:
const char* ssid = "YourWiFiSSID";
const char* password = "YourWiFiPassword";
REST API Endpoints
The ESP32 bridge exposes the following endpoints:
GET /ping: Health checkPOST /digital/write:{"pin": 5, "value": 1}GET /digital/read?pin=5: Returns{"value": 1}GET /analog/read?pin=0: Returns{"value": 512}POST /analog/write:{"pin": 3, "value": 128}POST /pin/mode:{"pin": 5, "mode": "OUTPUT"}
Example: ESP32 Control
// Connect to ESP32 via WiFi
var esp32 = new ArduinoConnection("http://192.168.1.100");
esp32.connect();
// Control LED
esp32.pinMode(2, "OUTPUT");
esp32.digitalWrite(2, true);
// Read sensor
var distance = esp32.analogRead(0);
print("Distance: " + distance);
31.6 Raspberry Pi
Raspberry Pi can be controlled via HTTP API or serial connection.
HTTP API Control
If Raspberry Pi runs a web server exposing REST API:
var pi = new RestClient("http://raspberrypi.local:8080");
var status = pi.get("/status");
Serial Communication
For direct serial communication:
var pi = new SerialConnection();
pi.connect("/dev/ttyUSB0", 115200);
pi.write("command\n");
var response = pi.readLine();
31.7 Smart Home Devices
Many smart home devices expose REST APIs that can be controlled with RestClient.
Philips Hue Example
var hue = new RestClient("http://192.168.1.50");
hue.setAuth("Bearer", "your-api-key");
// Turn on light
hue.put("/api/username/lights/1/state", {
"on": true,
"bri": 254,
"hue": 10000
});
// Dim light
hue.put("/api/username/lights/1/state", {
"bri": 128
});
// Turn off
hue.put("/api/username/lights/1/state", {
"on": false
});
SmartThings Example
var smartThings = new RestClient("https://api.smartthings.com");
smartThings.setAuth("Bearer", "your-token");
// Get devices
var devices = smartThings.get("/devices");
// Control device
smartThings.post("/devices/device-id/commands", {
"commands": [{
"component": "main",
"capability": "switch",
"command": "on"
}]
});
Home Assistant Example
var homeAssistant = new RestClient("http://homeassistant.local:8123");
homeAssistant.setHeader("Authorization", "Bearer your-token");
// Get states
var states = homeAssistant.get("/api/states");
// Control entity
homeAssistant.post("/api/services/light/turn_on", {
"entity_id": "light.living_room"
});
31.8 Multi-Device Coordination
MALDA's actor model is ideal for coordinating multiple devices. Each device can be controlled by its own actor, enabling concurrent, coordinated operations.
Using Actors for Device Control
actor DeviceController {
var device;
var deviceId;
function DeviceController(id, url) {
deviceId = id;
device = new ArduinoConnection(url);
}
on connect() {
device.connect();
print("Device " + deviceId + " connected");
}
on control(value) {
device.digitalWrite(5, value);
}
}
// Create multiple device controllers
var devices = [];
for (var i = 0; i < 5; i = i + 1) {
devices.append(spawn DeviceController(i, "http://192.168.1." + (100 + i)));
}
// Connect all devices concurrently
for (var i = 0; i < devices.length; i = i + 1) {
send devices[i].connect();
}
Coordination Patterns
Common patterns for multi-device systems:
- Coordinator Actor: Central actor that coordinates all devices
- Device Actors: One actor per device for isolated control
- Message Passing: Devices communicate via actor messages
- State Management: Each device actor maintains its own state
Example: Multi-Robot System
actor Robot {
var robotId;
var arduino;
var coordinator;
function Robot(id, url, coord) {
robotId = id;
arduino = new ArduinoConnection(url);
coordinator = coord;
}
on move(direction) {
if (direction == "forward") {
arduino.digitalWrite(5, true);
arduino.digitalWrite(6, true);
}
send coordinator.robotMoved(robotId, direction);
}
}
actor Coordinator {
var robots = [];
on registerRobot(robot) {
robots.append(robot);
}
on startAll() {
for (var i = 0; i < robots.length; i = i + 1) {
send robots[i].move("forward");
}
}
}
var coordinator = spawn Coordinator();
var robot1 = spawn Robot(1, "http://192.168.1.100", coordinator);
var robot2 = spawn Robot(2, "http://192.168.1.101", coordinator);
send coordinator.registerRobot(robot1);
send coordinator.registerRobot(robot2);
send coordinator.startAll();
31.9 Examples
Complete examples are available in the Examples/Devices/ directory:
- basic_arduino.malda: Simple Arduino control (LED blink, sensor reading)
- multi_robot_soccer.malda: Multi-robot coordination game using actors
- smart_home.malda: Smart home device control examples
Step-by-Step Tutorial: First Arduino Project
- Upload Bridge Sketch: Upload
arduino_bridge.inoto your Arduino - Find Port Name: Identify your Arduino's serial port (COM3, /dev/ttyUSB0, etc.)
- Connect in MALDA:
var arduino = new ArduinoConnection("COM3", 9600); arduino.connect(); - Control Hardware:
arduino.pinMode(13, "OUTPUT"); arduino.digitalWrite(13, true);
31.10 Troubleshooting
Serial Connection Issues
- Port not found: Verify port name and that device is connected
- Permission denied (Linux/macOS): Add user to dialout group:
sudo usermod -a -G dialout $USER - Connection timeout: Check baud rate matches device configuration
HTTP Connection Issues
- Connection refused: Verify device IP address and that it's on the same network
- Timeout: Check device is powered on and WiFi is connected
- Authentication errors: Verify API keys and tokens are correct
Common Errors
"Arduino not connected": Callconnect()before using device"Invalid pin": Verify pin numbers are valid for your device"Arduino error: ...": Check device sketch is uploaded and running