Integrate OpexMX with Your Machines
How OpexMX connects to industrial machines via the OpexMX Edge Connector and FOCAS Agent.
Overview
OpexMX provides a complete edge-to-cloud machine integration using two open-source components:
- OpexMX Connector — A Rust binary running on a Raspberry Pi that reads Modbus TCP, OPC-UA, and MQTT data from your machines and pushes it to the OpexMX cloud.
- OpexMX FOCAS Agent — A companion Windows agent for Fanuc CNC machines that reads data via the FOCAS2 library and publishes it via MQTT to the connector.
No custom gateway code is needed. Configure YAML, deploy, and your machines are online.
Architecture
Factory Floor Cloud
┌───────────────────────────┐ ┌──────────────────┐
│ OpexMX Edge Connector │ │ OpexMX Platform │
│ (Raspberry Pi) │ HMAC-signed │ (Cloudflare) │
│ │ HTTP push │ │
│ Modbus TCP ◄──── PLCs │─────────────────►│ REST API │
│ OPC-UA ◄──── SCADA │ │ CMMS │
│ MQTT ◄──── Sensors │ │ Dashboards │
│ │ │ Analytics │
│ SQLite (local buffer) │ │ Alerts │
│ React Dashboard (local) │ │ │
└───────────┬───────────────┘ └──────────────────┘
│ MQTT
│
┌───────────┴───────────────┐
│ Windows PC (optional) │
│ OpexMX FOCAS Agent │
│ fwlib30.dll ◄── Fanuc CNC
└───────────────────────────┘
Supported Protocols
| Protocol | Adapter | Machines | How It Works |
|---|---|---|---|
| Modbus TCP | Built-in | PLCs, VFDs, energy meters, sensors | Reads holding registers (uint16/int16/uint32/int32/float) with configurable mapping |
| OPC-UA | Built-in | SCADA systems, Siemens, Allen-Bradley, generic OPC servers | Reads nodes by NodeId with anonymous or username/password auth |
| MQTT | Built-in | IoT sensors, custom devices, other agents | Subscribes to topics, parses JSON/number/string payloads |
| FOCAS2 | Companion agent | Fanuc CNC (0i, 30i, 31i, 32i, 35i) | Windows agent reads status/axes/spindle/alarms, publishes via MQTT |
Quick Start: Edge Connector
1. Flash Raspberry Pi
# Standard Raspberry Pi OS Lite (64-bit)
# SSH into the Pi
2. Deploy the Connector
# From your development machine (macOS/Linux)
git clone https://github.com/dzulfikar08/opexmx-connector-v2.git
cd opexmx-connector-v2
# Cross-compile for ARM64
rustup target add aarch64-unknown-linux-musl
cargo zigbuild --release --target aarch64-unknown-linux-musl --all-features
# Deploy to Pi
./deploy.sh pi@192.168.1.100
The deploy script copies the binary, dashboard, and config, then installs a systemd service.
3. Configure Machines
Edit /opt/opexmx-connector/config.yaml:
connector:
name: factory-floor-1
poll_interval_ms: 5000
push_endpoint: https://your-opexmx-instance.com/api/machine-parameter-values
hmac_secret: ${HMAC_SECRET}
adapters:
modbus:
enabled: true
devices:
- id: plc-line-1
host: 192.168.1.10
port: 502
unit_id: 1
registers:
- address: 0
name: spindle_speed
type: uint16
mapping: spindleSpeed
- address: 1
name: axis_x_position
type: float
mapping: position
axis_name: X
- address: 10
name: machine_state
type: uint16
mapping: state
mqtt:
enabled: true
external:
enabled: true
url: 0.0.0.0
devices:
- id: fanuc-mill-1
topic: opexmx/focas/fanuc-mill-1
data_type: json
4. Start
sudo systemctl start opexmx-connector
sudo systemctl enable opexmx-connector # auto-start on boot
Open http://192.168.1.100:3000 for the local dashboard showing live machine data.
Quick Start: Fanuc CNC (FOCAS Agent)
For Fanuc CNC machines with FOCAS2 support:
1. Build the Windows Agent
# From macOS/Linux
git clone https://github.com/dzulfikar08/opexmx-focas-agent.git
cd opexmx-focas-agent
./build.sh
# Output: target/x86_64-pc-windows-gnu/release/opexmx-focas-agent.exe
2. Deploy to Windows PC
Copy to the Windows PC near the CNC:
opexmx-focas-agent.execonfig.yaml(fromconfig.example.yaml)fwlib30i64.dll(from Fanuc FOCAS2 SDK)
3. Configure
agent:
poll_interval_ms: 5000
dll_path: fwlib30i64.dll
mqtt:
broker: 192.168.1.100 # RPi connector's IP
port: 1883
topic_prefix: opexmx/focas
machines:
- id: fanuc-mill-1
name: Fanuc VF-2SS
host: 192.168.1.10 # CNC IP address
port: 8193 # FOCAS port
max_axes: 3
4. Run
opexmx-focas-agent.exe
The agent reads CNC status, axis positions, spindle speed, and alarms, then publishes to MQTT. The RPi connector picks it up automatically.
Data Format
All adapters output the same CanonicalMachineData JSON:
{
"source": "modbus",
"timestamp": "2025-05-12T09:30:00.000Z",
"machine": { "id": "plc-line-1", "name": "Line 1 PLC" },
"status": { "state": "running" },
"axes": [
{ "name": "X", "position": 125.450, "unit": "mm" },
{ "name": "Y", "position": 50.200, "unit": "mm" }
],
"spindle": { "speed": 4500 },
"metadata": {
"spindle_speed": 4500,
"machine_state": 1
}
}
Machine states: running, idle, alarm, offline.
Modbus Register Mapping
Map any Modbus register to a semantic field:
| Mapping | What It Does |
|---|---|
state | Maps value to machine state (0=idle, 1=running, ≥2=alarm) |
position | Creates an axis data point (use axis_name to label it) |
spindleSpeed | Sets spindle speed |
| (no mapping) | Stored in metadata as a raw value |
Register types: uint16, int16, uint32, int32, float. Apply scaling with the scale field.
Local Features
The connector works even without cloud connectivity:
- SQLite storage — All data stored locally with 7-day retention
- React dashboard — Live WebSocket view, status, device list, history browser
- REST API — Health checks, device status, history queries, config reload
- Retry buffer — 1000-entry FIFO buffer for failed pushes, auto-flushes on reconnect
Security
- HMAC-SHA256 signatures on all cloud push requests
- Environment variable substitution in config (
${SECRET}syntax) - Local network only — connector runs inside your factory LAN
- No inbound connections required — the connector pushes outbound to your OpexMX instance
Monitoring
| Endpoint | Purpose |
|---|---|
GET /api/health | Basic health check |
GET /api/ready | Readiness (adapters started) |
GET /api/status | Full status with adapter details |
GET /api/devices | Per-device connection status |
GET /api/ws/live | WebSocket real-time data stream |
Direct API Integration
If you prefer to build your own gateway, you can POST directly to the OpexMX API:
POST /api/machine-parameter-values
{
"machineParameterId": "SPINDLE_SPEED",
"value": "1500",
"createdAt": "2025-12-04T07:24:20.069Z"
}
This is what the connector's pusher calls internally. Use this approach for custom integrations or when the connector doesn't support your protocol yet.
Summary
- Deploy the OpexMX Connector on a Raspberry Pi in your factory network
- Configure YAML with your machine protocols (Modbus, OPC-UA, MQTT)
- For Fanuc CNC, deploy the FOCAS Agent on a nearby Windows PC
- Data flows automatically from machines → connector → OpexMX cloud
- Monitor locally via the built-in React dashboard at
http://pi-ip:3000
No custom code. No vendor lock-in. Open-source connectors you can modify for your needs.