Device Integration Guide
(preliminary)
Overview
Machine Buddy in Eclipse Pro helps track production for non-rollforming machines (XL200 controllers already track those). It monitors production equipment in real-time and provides operators with guidance, but the equipment retains full control over whether to run or stop.
Eclipse Pro supports integration via two transport protocols:
- MQTT: Recommended for real-time bidirectional communication
- HTTP: Alternative for simpler request/response scenarios
This guide provides the protocol specifications needed to integrate PLCs, HMIs, and other industrial devices.
Choosing a Transport
| Feature | MQTT | HTTP |
|---|---|---|
| Bidirectional | Yes (push from server) | No (device must poll) |
| Real-time Commands | Immediate | Polling delay |
| Bandwidth | Very low | Low |
| Complexity | Moderate (pub/sub) | Simple (request/response) |
| Industry Support | Excellent (Siemens, AB, Omron) | Universal |
| Recommended For | PLCs, HMIs, IoT devices | Simple devices, testing |
Table of Contents
- Core Concepts - Message formats and business rules (applies to both transports)
- MQTT Transport - MQTT-specific connection and topic details
- HTTP Transport - HTTP endpoint and polling details
Core Concepts
Device Identifier
Every device must have a unique Device ID (machineId):
Format: Alphanumeric string with hyphens/underscores allowed
Examples: press-001, saw-02, cnc_03
Restrictions:
- NO forward slashes
/or backslashes\ - Case-sensitive
- Must match device configuration in Eclipse Pro
Status Message
Devices send status updates to Eclipse Pro containing production data and device state.
Message Format (JSON)
{
"machineId": "press-001",
"running": true,
"mSecSinceBoot": 1234567,
"cycle": 42,
"goodPart": 100,
"badPart": 2,
"override": false
}
Required Fields
| Field Name | Data Type | Description | Example | Notes |
|---|---|---|---|---|
machineId | String | Unique device identifier | "press-001" | Must match device configuration |
running | Boolean | Device currently cycling | true | True = running, False = stopped |
mSecSinceBoot | Integer | Milliseconds since device boot | 1234567 | Must reset to 0 on reboot |
cycle | Integer | Total cycle count since boot | 42 | Never decrease |
goodPart | Integer | Good parts count since boot | 100 | Never decrease |
badPart | Integer | Scrap parts count since boot | 2 | Never decrease |
override | Boolean | Server override mode active | false | See important note below |
IMPORTANT - Server Override Mode:
Eclipse Pro is a tracking system, not a control system. Production should never stop because the tracking server's business rules aren't satisfied or the server is unavailable.
The override field allows devices to bypass server business rules when needed:
Common Scenarios:
- Server is offline (maintenance, updates, network issues)
- Part not selected in Eclipse Pro yet (new job starting)
- Downtime categorization pending (operator hasn't classified delay yet)
- Work order not synced from external system
Implementation Recommendation:
- Provide operator button/switch on HMI to control override mode
- When operator enables override:
- Set
override = truein status messages - Show "Override Active - Server Rules Bypassed" indicator on HMI
- Allow production to continue regardless of server response
- Continue publishing status (server tracks what actually happened)
- Set
- When operator disables override:
- Set
override = falsein status messages - Resume normal operation (respect server
runEnabledresponse)
- Set
Optional Fields
| Field Name | Data Type | Description | Example | Notes |
|---|---|---|---|---|
machinePower | Boolean | Machine power ON/OFF | true | Controls server business rules |
fault | Boolean | Machine in fault/warning state | false | Triggers attentionNeeded but does NOT block production |
userId | String | Operator ID/badge number | "OP-123" | For operator tracking |
partId | String | Part/geometry identifier | "PART-5678" | Future feature |
partName | String | Part description | "Bracket Assembly" | Future feature |
jobNumber | String | Job/work order number | "JOB-9012" | Future feature |
IMPORTANT - Fault Field Behavior:
The fault field is for informational purposes only:
- When
fault = true: Server setsattentionNeeded = true(alert operator/maintenance) - Does NOT affect
runEnabled(production can continue) - The PLC/device controls should decide if a fault is severe enough to halt production
- Eclipse Pro will track faulted time for maintenance metrics
Update Frequency
Recommended:
- Running: Every 500ms (0.5 seconds)
- Stopped: Every 1000ms (5 second)
Maximum: 10 updates per second
Command Message
Eclipse Pro sends command responses back to devices indicating whether business rules allow production and if operator attention is needed.
Message Format (JSON)
{
"runEnabled": true,
"attentionNeeded": false,
"message": "All checks passed",
"timestamp": "2025-10-18T14:30:00Z"
}
Fields
| Field Name | Data Type | Description | Notes |
|---|---|---|---|
runEnabled | Boolean | Server business rules allow production | |
attentionNeeded | Boolean | Operator attention required | Typically lights warning indicator |
message | String | Reason for runEnabled=false (optional) | Human-readable explanation |
timestamp | String | Server time of response (ISO 8601) | Optional |
IMPORTANT - Tracking vs Control:
Eclipse Pro provides guidance, not control:
runEnabled = falsemeans "server business rules not satisfied"- Device should typically prevent running when
runEnabled = false - BUT operator can use override mode to bypass server rules
- Device always has final authority over machine operation
RunEnabled Calculation Rules
The server calculates runEnabled based on business rules (priority order):
1. Machine Power Must Be ON
- If
machinePower = false(or not provided), server returnsrunEnabled = false - Message: "Machine power is off"
2. Part Must Be Selected
- Operator must have selected a part/geometry in Eclipse Pro UI
- If no part selected, server returns
runEnabled = false - Message: "Part not selected"
3. Device Must Not Be Timing Out
- Server expects status updates at least every 10 seconds
- If updates stop, server returns
runEnabled = false - Message: "Device not responding"
4. Downtime Must Be Categorized (If Applicable)
- When device stops while in "running" state, downtime reason must be categorized
- If categorization pending, server returns
runEnabled = false - Message: "Downtime categorization required"
Note: Fault state (fault = true) triggers attentionNeeded = true but does NOT affect runEnabled.
Device Implementation Guidance
Typical Logic:
IF override = true THEN
Allow running (ignore server response)
Show "Override Active" indicator
ELSE IF runEnabled = false THEN
Prevent running
Show message to operator
Light warning indicator if attentionNeeded = true
ELSE
Allow running
Clear warning indicator
END IF
Production Data Rules
Critical Rules
1. Counters Never Decrease
Rule: Once incremented, cycle, goodPart, and badPart must NEVER decrease (except on boot).
Why: Server detects production by comparing consecutive values. Decreasing values will cause:
- Missed parts (server thinks no production occurred)
- Negative cycle counts (database corruption)
- Incorrect OEE calculations
Example:
✓ CORRECT:
Update 1: cycle=10, goodPart=8, badPart=2
Update 2: cycle=11, goodPart=9, badPart=2 (cycle +1, goodPart +1)
Update 3: cycle=12, goodPart=9, badPart=3 (cycle +1, badPart +1)
✗ INCORRECT:
Update 1: cycle=10, goodPart=8, badPart=2
Update 2: cycle=9, goodPart=7, badPart=2 (COUNTERS DECREASED!)
2. Boot Time Reset Behavior
Rule: On device boot/restart, all counters and mSecSinceBoot MUST reset to 0.
Why: Server uses mSecSinceBoot to detect reboots and reset its tracking state.
Implementation:
On PLC/device startup:
mSecSinceBoot = 0
cycle = 0
goodPart = 0
badPart = 0
Detection: Server detects reboot when mSecSinceBoot decreases from previous update.
3. Accurate Boot Timer
Rule: mSecSinceBoot must accurately track milliseconds since boot (never reset except on actual boot).
Why: Server uses this to calculate:
- Device uptime
- Cycle times (time between cycles)
- Stopped duration
Common Mistake: Resetting timer during shift changes or maintenance stops (don't do this).
4. Running Flag Behavior
Rule: Set running = true ONLY when device is actively cycling (in automatic production mode).
When to set running = true:
- Device in automatic/cycle mode AND currently executing a cycle
When to set running = false:
- Manual mode
- Stopped (waiting for operator action, material, etc.)
- Fault/alarm condition (even if auto mode selected)
- Maintenance mode
Common Error Messages
When runEnabled = false, the message field explains why:
| Message | Meaning | Resolution |
|---|---|---|
"Machine power is off" | machinePower = false in status | Turn machine power ON |
"Part not selected" | No part selected in Eclipse Pro | Select part in UI or enable override |
"Device not responding" | Status updates stopped | Check network, MQTT connection |
"Downtime categorization required" | Operator must classify delay | Categorize downtime in UI or enable override |
"Server error - grain unavailable" | Internal server error | Contact support, use override mode |
MQTT Transport
MQTT Overview
MQTT is a lightweight publish/subscribe messaging protocol ideal for industrial automation:
- Industry Standard: Supported by Siemens, Allen-Bradley, Omron, Schneider Electric
- Bidirectional: Server can push commands to devices immediately
- Reliable: Built-in QoS guarantees message delivery
- Real-time: Millisecond-level latency
Broker Information
| Parameter | Value |
|---|---|
| Default Port | 1883 (TCP) |
| Protocol Version | MQTT 3.1.1 or higher |
| Authentication | Not required (currently) |
| TLS/SSL | Optional |
| Clean Session | false (maintain subscriptions across reconnects) |
Topic Structure
Each device uses a unique Topic Root configured in Eclipse Pro. The Topic Root serves as the namespace for all device MQTT topics.
Topic Root Format
Recommended: {location}/{machine-type}-{number}
Examples:
warehouse/press-001factory/line1/saw-02building3/cnc-03
Rules:
- Use forward slashes
/to separate levels - Allowed characters:
a-z,A-Z,0-9,-,_,/ - Case-sensitive
- Do NOT use wildcards (
#,+)
Complete Topic Namespace
Given Topic Root = warehouse/press-001:
Device Publishes (to server):
warehouse/press-001/status → Status updates (JSON)
warehouse/press-001/online → "true" or "false"
warehouse/press-001/lwt → "false" (Last Will)
Device Subscribes (from server):
warehouse/press-001/command → JSON format (recommended)
OR
warehouse/press-001/command/run-enabled → "0" or "1" (simple PLCs)
warehouse/press-001/command/attention-needed → "0" or "1" (simple PLCs)
Device to Server Topics
1. Status Updates
Topic: {TopicRoot}/status
Publish Frequency:
- Running: Every 500ms
- Stopped: Every 1000ms
QoS: 1 (At Least Once)
Retain: false (avoid stale data)
Payload: JSON string (see Status Message format above)
2. Online Status
Topic: {TopicRoot}/online
When to Publish:
- Immediately after connecting to broker:
"true" - Before gracefully disconnecting:
"false"
QoS: 1 (At Least Once)
Retain: true (persist connection state)
Payload: String "true" or "false"
3. Last Will and Testament (LWT)
Purpose: Automatically published by broker when device disconnects unexpectedly (power loss, network failure).
Topic: {TopicRoot}/lwt
Payload: "false"
QoS: 1 (At Least Once)
Retain: true
Configuration: Set LWT when connecting to broker (connection parameter).
Server to Device Topics
1. Command Messages (JSON Format - Recommended)
Topic: {TopicRoot}/command
Subscribe QoS: 1 (At Least Once)
Payload: JSON string (see Command Message format above)
Example:
{
"runEnabled": false,
"attentionNeeded": true,
"message": "Part not selected"
}
2. Command Messages (Simple Format - For Simple PLCs)
For PLCs that cannot easily parse JSON, the same information is published to individual topics:
Topic: {TopicRoot}/command/run-enabled
Payload: "0" (false) or "1" (true)
Topic: {TopicRoot}/command/attention-needed
Payload: "0" (false) or "1" (true)
Subscribe QoS: 1 (At Least Once)
Note: The message text is only available in JSON format.
MQTT Connection Parameters
| Parameter | Value | Notes |
|---|---|---|
| Client ID | {machineId} | Use device's unique ID |
| Clean Session | false | Maintain subscriptions across reconnects |
| Keep Alive | 60 seconds | Recommended |
| QoS | 1 (At Least Once) | For all production messages |
| Retain | false for status/commandstrue for config | Avoid stale data for dynamic state |
HTTP Transport
HTTP Overview
HTTP provides a simple request/response alternative to MQTT:
- Universal: Supported by all programming languages and platforms
- Simple: Standard POST request with JSON body
- Synchronous: Response contains command immediately
- Polling: Device must repeatedly poll for command updates (no push from server)
Limitation: Cannot receive immediate commands from server (device must poll).
Endpoint
POST /api/device/status
URL: http://{server}:8080/api/device/status
Method: POST
Content-Type: application/json
Authentication: None (currently)
Request Body: JSON status message (see Status Message format above)
Response Body: JSON command message (see Command Message format above)
Response Codes:
200 OK: Success (response body contains command)400 Bad Request: Invalid request (missingmachineId, invalid JSON, etc.)500 Internal Server Error: Server error
Example HTTP Request
Using curl
curl -X POST http://localhost:8080/api/device/status \
-H "Content-Type: application/json" \
-d '{
"machineId": "press-001",
"running": true,
"mSecSinceBoot": 1234567,
"cycle": 42,
"goodPart": 100,
"badPart": 2,
"override": false
}'
Example Response
{
"machineId": "press-001",
"runEnabled": true,
"attentionNeeded": false
}
Note: The HTTP response does NOT include the message or timestamp fields currently (MQTT provides more complete responses).
Polling Frequency
Since HTTP is request/response only, the device must poll repeatedly to:
- Send status updates to server
- Receive updated commands from server
Recommended Polling Frequency:
- Running: Every 500ms
- Stopped: Every 1000ms
Implementation:
Loop every 500ms (if running) or 1000ms (if stopped):
1. Build status JSON with current device state
2. POST to /api/device/status
3. Parse response JSON
4. Update local runEnabled and attentionNeeded state
5. Apply logic (see "Device Implementation Guidance" above)
Error Handling
| Scenario | Recommended Handling |
|---|---|
| Network timeout | Retry with exponential backoff, enable override mode if >60s |
| HTTP 400 error | Log error, check JSON format, ensure machineId field present |
| HTTP 500 error | Log error, retry after 5s, enable override mode if persistent |
| Invalid response | Log error, assume runEnabled=false, attentionNeeded=true |