Skip to main content

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

FeatureMQTTHTTP
BidirectionalYes (push from server)No (device must poll)
Real-time CommandsImmediatePolling delay
BandwidthVery lowLow
ComplexityModerate (pub/sub)Simple (request/response)
Industry SupportExcellent (Siemens, AB, Omron)Universal
Recommended ForPLCs, HMIs, IoT devicesSimple devices, testing

Table of Contents


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 NameData TypeDescriptionExampleNotes
machineIdStringUnique device identifier"press-001"Must match device configuration
runningBooleanDevice currently cyclingtrueTrue = running, False = stopped
mSecSinceBootIntegerMilliseconds since device boot1234567Must reset to 0 on reboot
cycleIntegerTotal cycle count since boot42Never decrease
goodPartIntegerGood parts count since boot100Never decrease
badPartIntegerScrap parts count since boot2Never decrease
overrideBooleanServer override mode activefalseSee 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 = true in 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)
  • When operator disables override:
    • Set override = false in status messages
    • Resume normal operation (respect server runEnabled response)

Optional Fields

Field NameData TypeDescriptionExampleNotes
machinePowerBooleanMachine power ON/OFFtrueControls server business rules
faultBooleanMachine in fault/warning statefalseTriggers attentionNeeded but does NOT block production
userIdStringOperator ID/badge number"OP-123"For operator tracking
partIdStringPart/geometry identifier"PART-5678"Future feature
partNameStringPart description"Bracket Assembly"Future feature
jobNumberStringJob/work order number"JOB-9012"Future feature

IMPORTANT - Fault Field Behavior:

The fault field is for informational purposes only:

  • When fault = true: Server sets attentionNeeded = 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 NameData TypeDescriptionNotes
runEnabledBooleanServer business rules allow production
attentionNeededBooleanOperator attention requiredTypically lights warning indicator
messageStringReason for runEnabled=false (optional)Human-readable explanation
timestampStringServer time of response (ISO 8601)Optional

IMPORTANT - Tracking vs Control:

Eclipse Pro provides guidance, not control:

  • runEnabled = false means "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 returns runEnabled = 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:

MessageMeaningResolution
"Machine power is off"machinePower = false in statusTurn machine power ON
"Part not selected"No part selected in Eclipse ProSelect part in UI or enable override
"Device not responding"Status updates stoppedCheck network, MQTT connection
"Downtime categorization required"Operator must classify delayCategorize downtime in UI or enable override
"Server error - grain unavailable"Internal server errorContact 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

ParameterValue
Default Port1883 (TCP)
Protocol VersionMQTT 3.1.1 or higher
AuthenticationNot required (currently)
TLS/SSLOptional
Clean Sessionfalse (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-001
  • factory/line1/saw-02
  • building3/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

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

ParameterValueNotes
Client ID{machineId}Use device's unique ID
Clean SessionfalseMaintain subscriptions across reconnects
Keep Alive60 secondsRecommended
QoS1 (At Least Once)For all production messages
Retainfalse for status/commands
true 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 (missing machineId, 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:

  1. Send status updates to server
  2. 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

ScenarioRecommended Handling
Network timeoutRetry with exponential backoff, enable override mode if >60s
HTTP 400 errorLog error, check JSON format, ensure machineId field present
HTTP 500 errorLog error, retry after 5s, enable override mode if persistent
Invalid responseLog error, assume runEnabled=false, attentionNeeded=true