Node-RED Tafy Nodes
A collection of Node-RED nodes for the Tafy Robot Distributed Operation System (RDOS).
Quick Start
Get your robot moving in 30 minutes! See our Quick Start Guide.
Documentation
Software Guides
- Quick Start Guide - Get up and running fast
- Flows Documentation - Detailed behavior documentation
- Examples - Import ready-to-use flows
Hardware Guides
- Hardware BOM - Parts list for building robots
- Wiring Diagrams - How to connect components
- Assembly Guide - Step-by-step build instructions
Available Nodes
Autonomous Behaviors
- obstacle-avoid - Autonomous obstacle avoidance with simple/advanced modes
- color-tracker - HSV-based color blob tracking
- color-follow - Follow colored objects with camera
- sensor-fusion - Combine multiple sensor readings
Control Components
- pid-controller - Generic PID controller with anti-windup
- motor-control - Differential drive motor control
- gamepad-input - Game controller input
- joystick-ui - Web-based joystick
- keyboard-input - Keyboard teleop control
Hardware Interface
- camera-stream - MJPEG/WebRTC camera streaming
- camera-snapshot - Capture still images
- camera-discovery - Auto-discover cameras
- camera-control - Camera settings control
- nats-pub - Publish to NATS/HAL
- nats-config - NATS connection config
Installation
cd ~/.node-red
npm install @tafystudio/node-red-contrib-tafy
Or install directly from the Node-RED palette manager.
Camera Nodes
tafy-camera-stream
Connects to a Tafy camera stream and outputs frame data or stream URLs.
Features:
- MJPEG HTTP streaming
- WebSocket frame-by-frame delivery
- WebRTC peer-to-peer streaming
- Auto-reconnection support
- Multiple output formats
Example Flow:
[{"id":"cam1","type":"tafy-camera-stream","cameraUrl":"http://camera:8080","streamType":"mjpeg"},
{"id":"template1","type":"template","template":"<img src='{{payload.url}}' />"},
{"id":"ui1","type":"ui_template"}]
tafy-camera-snapshot
Captures single frames from a Tafy camera.
Features:
- On-demand snapshot capture
- Multiple output formats (Buffer, Base64, URL)
- Metadata inclusion
- Error handling
Use Cases:
- Periodic image capture
- Motion-triggered snapshots
- Image analysis pipelines
tafy-camera-discovery
Discovers available cameras on the network.
Features:
- Automatic camera detection
- Periodic discovery updates
- Best camera selection
- Multiple output formats
Example - Auto-select best camera:
// In a function node after discovery
const cameras = msg.payload.cameras;
const mjpegCamera = cameras.find(cam =>
cam.formats.some(f => f.name.includes('MJPEG'))
);
return { payload: mjpegCamera };
tafy-camera-control
Controls and queries camera settings.
Current Commands:
status- Get camera status and statisticsinfo- Get camera information
Future Commands:
configure- Change camera settingsstart/stop- Control capture state- Exposure, white balance, focus control
Example Flows
1. Dashboard Camera Viewer
[
{
"id": "inject1",
"type": "inject",
"repeat": "",
"once": true,
"topic": "",
"payload": "true",
"x": 100,
"y": 100
},
{
"id": "discovery1",
"type": "tafy-camera-discovery",
"discoveryUrl": "http://hub:8080",
"outputFormat": "simple",
"x": 250,
"y": 100
},
{
"id": "function1",
"type": "function",
"func": "// Select first camera\nconst camera = msg.payload[0];\nif (camera) {\n flow.set('cameraUrl', `http://${camera.device}:8080`);\n return { payload: true };\n}\nreturn null;",
"x": 400,
"y": 100
},
{
"id": "stream1",
"type": "tafy-camera-stream",
"cameraUrl": "{{flow.cameraUrl}}",
"streamType": "mjpeg",
"x": 550,
"y": 100
},
{
"id": "dashboard1",
"type": "ui_template",
"template": "<img src='{{msg.payload.url}}' style='width:100%' />",
"x": 700,
"y": 100
}
]
2. Motion Detection Alert
[
{
"id": "motion1",
"type": "mqtt in",
"topic": "sensors/motion",
"x": 100,
"y": 200
},
{
"id": "filter1",
"type": "switch",
"property": "payload",
"rules": [{"t": "true"}],
"x": 250,
"y": 200
},
{
"id": "snapshot1",
"type": "tafy-camera-snapshot",
"cameraUrl": "http://camera:8080",
"outputType": "buffer",
"includeMetadata": true,
"x": 400,
"y": 200
},
{
"id": "notify1",
"type": "function",
"func": "// Send notification with image\nreturn {\n payload: {\n message: 'Motion detected!',\n image: msg.payload,\n timestamp: msg.metadata.timestamp\n }\n};",
"x": 550,
"y": 200
}
]
3. Multi-Camera Monitoring
[
{
"id": "timer1",
"type": "inject",
"repeat": "30",
"topic": "",
"payload": "discover",
"x": 100,
"y": 300
},
{
"id": "discover1",
"type": "tafy-camera-discovery",
"outputFormat": "full",
"x": 250,
"y": 300
},
{
"id": "split1",
"type": "function",
"func": "// Create snapshot request for each camera\nconst cameras = msg.payload.cameras || [];\nreturn cameras.map(cam => ({\n payload: 'snapshot',\n camera: cam.device,\n url: `http://${cam.device}:8080`\n}));",
"x": 400,
"y": 300
},
{
"id": "snapshot2",
"type": "tafy-camera-snapshot",
"cameraUrl": "{{msg.url}}",
"outputType": "base64",
"x": 550,
"y": 300
},
{
"id": "grid1",
"type": "ui_template",
"template": "<div class='camera-grid'>\n <img src='data:image/jpeg;base64,{{msg.payload}}' />\n <div>{{msg.camera}}</div>\n</div>",
"x": 700,
"y": 300
}
]
Integration with HAL
These nodes work with the Tafy HAL (Hardware Abstraction Layer) system:
- Camera nodes publish telemetry to
hal.v1.camera.*topics - Control commands follow HAL message format
- Discovery integrates with NATS-based service discovery
Troubleshooting
Camera not found
- Check camera driver is running:
curl http://camera:8080/health - Verify network connectivity
- Ensure discovery URL is correct
No stream displayed
- Check browser console for errors
- Verify CORS settings if accessing across origins
- Try different stream types (MJPEG vs WebSocket)
High latency
- Use WebRTC for lowest latency
- Check network bandwidth
- Reduce resolution/FPS in camera settings
Contributing
- Fork the repository
- Create your feature branch
- Add tests for new functionality
- Submit a pull request
License
Apache License 2.0