System Architecture
This chapter provides a deeper look at how AutoCore works internally. You don’t need to understand all of this to use AutoCore, but it will help you debug issues and make better design decisions.
Architecture Diagram
┌─────────────────────────────────────────────────────────────────┐
│ AutoCore Server │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ System │ │ GM │ │ Datastore │ │ Module IPC │ │
│ │ Servelet │ │ Servelet │ │ Servelet │ │ Server │ │
│ └─────┬─────┘ └─────┬────┘ └──────┬─────┘ └────────┬─────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Shared Memory (autocore_cyclic) │ │
│ │ ┌──────────┐ ┌───────────┐ ┌─────────────┐ ┌─────────┐ │ │
│ │ │ Variables │ │ Signals │ │ Direct │ │ Events │ │ │
│ │ │ (I/O) │ │ (Tick) │ │ Mapping │ │ (Sync) │ │ │
│ │ └──────────┘ └───────────┘ └─────────────┘ └─────────┘ │ │
│ └──────────▲─────────────────────────────▲────────────────────┘ │
│ │ Zero-Copy R/W │ Zero-Copy R/W │
│ │ (every cycle) │ (every cycle) │
└─────────────┼─────────────────────────────┼──────────────────────┘
│ │
┌──────────┴──────────┐ ┌─────────────┴──────────────┐
│ Control Program │ │ External Modules │
│ (your program.rs) │ │ (EtherCAT, Modbus, etc.) │
│ │ │ │
│ autocore-std │ │ mechutil IPC client │
└──────────────────────┘ └──────────────────────────────┘
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────────────┐
│ Web Console / HMI │ │ Field Devices │
│ (Browser, ws://) │ │ (Drives, Sensors, I/O) │
└──────────────────────┘ └──────────────────────────────┘
Shared Memory Model
Shared memory is the heart of AutoCore’s performance. Instead of sending data through network protocols or message queues, all processes access the same memory region directly.
- Allocation: When the server starts, it creates a shared memory segment called
autocore_cyclicbased on the variables inproject.json. - Mapping: The control program and all enabled modules map this segment into their own address space.
- Synchronization: The server generates a tick event. The control program waits for this event, reads the memory, processes one cycle, and writes back.
This zero-copy architecture means that I/O data exchange takes nanoseconds, not milliseconds.
The Module System
External modules extend AutoCore’s hardware capabilities. Each module:
- Is spawned as a child process by the server on startup
- Receives three CLI arguments:
--ipc-address,--module-name, and--config - Connects to the server’s IPC port (default 9100)
- Receives lifecycle commands:
initialize,configure_shm,finalize - Maps shared memory variables to exchange cyclic data
- Handles commands routed by the server based on the module’s domain name
Built-in modules:
- autocore-ethercat: EtherCAT fieldbus master
- autocore-modbus: Modbus TCP client
- autocore-labelit: Camera and label inspection
Configuration: config.ini
The config.ini file contains machine-specific settings that stay the same across projects. It is located at:
- Linux:
/opt/autocore/config/config.ini - Development: specified with
--configflag when running the server
[console]
port = 11969 # WebSocket port for CLI and web clients
www_root = /srv/autocore/console/dist # Path to web console static files
[general]
projects_directory = /srv/autocore/projects # Root directory for all projects
module_base_directory = /opt/autocore/bin/modules # Directory containing module executables
port = 8080 # HTTP port for the web server
autocore_std_directory = /srv/autocore/lib/autocore-std # Path to the autocore-std library
disable_ads = 1 # Disable TwinCAT ADS compatibility
ipc_port = 9100 # TCP port for module IPC
project_name = default # Project to load on startup
[modules]
modbus = ${general.module_base_directory}/autocore-modbus
ethercat = ${general.module_base_directory}/autocore-ethercat
labelit = ${general.module_base_directory}/autocore-labelit
The [modules] section maps module names to executable paths. This keeps project.json portable — the same project file works on different machines where modules may be installed in different locations.
The CommandMessage Protocol
All communication in AutoCore — between web clients and the server, between the CLI and the server, and between modules and the server — uses the CommandMessage protocol. Understanding this protocol helps you debug communication issues and write effective HMI code.
A CommandMessage is a JSON object with the following fields:
{
"transaction_id": 101,
"timecode": 1768960000000,
"topic": "gm.motor_speed",
"message_type": 2,
"data": null,
"crc": 0,
"success": false,
"error_message": ""
}
| Field | Type | Description |
|---|---|---|
transaction_id | number | Unique ID for matching responses to requests. The server echoes this back. For broadcasts, this is 0. |
timecode | number | Timestamp in milliseconds since UNIX epoch. |
topic | string | The FQDN (Fully Qualified Domain Name) of the resource. The first segment routes to the appropriate module or servelet (e.g., gm, modbus, ethercat, datastore). |
message_type | number | The operation to perform (see table below). |
data | any | The payload. For a Write, this is the value to set. For a Read Response, this is the value retrieved. |
crc | number | Optional CRC32 checksum for message integrity verification. Defaults to 0. |
success | boolean | true if the operation succeeded, false if it failed. Only meaningful in responses. |
error_message | string | Human-readable error description if success is false. Otherwise empty. |
Message Types
| Name | Value | Description |
|---|---|---|
| NoOp | 0 | No operation. Used for connection testing / ping. |
| Response | 1 | Reply to a previous request. The transaction_id matches the original. |
| Read | 2 | Request to read the current value of topic. |
| Write | 3 | Request to update the value of topic. |
| Subscribe | 4 | Request to receive updates whenever topic changes. |
| Unsubscribe | 5 | Stop receiving updates for topic. |
| Broadcast | 6 | Unsolicited push from server to client (live variable update). |
| Heartbeat | 7 | Keepalive signal. |
| Control | 8 | System control message (initialize, finalize, configure). |
| Request | 10 | Generic RPC call. The topic implies the action, data contains arguments. |
The protocol follows a REST-like pattern: the topic is the resource (like a URL path), and the message_type is the verb (like an HTTP method).
Common Workflows
Reading a variable:
// Request (Client → Server)
{ "transaction_id": 101, "topic": "gm.motor_speed", "message_type": 2, "data": null }
// Response (Server → Client)
{ "transaction_id": 101, "topic": "gm.motor_speed", "message_type": 1, "data": 1500, "success": true }
Writing a variable:
// Request
{ "transaction_id": 102, "topic": "gm.motor_speed_setpoint", "message_type": 3, "data": 1200 }
// Response
{ "transaction_id": 102, "topic": "gm.motor_speed_setpoint", "message_type": 1, "success": true }
Subscribing to live updates:
// Subscribe request
{ "transaction_id": 103, "topic": "gm.motor_speed", "message_type": 4, "data": {} }
// Confirmation
{ "transaction_id": 103, "topic": "gm.motor_speed", "message_type": 1, "success": true }
// Subsequent broadcasts (sent automatically when value changes)
{ "transaction_id": 0, "topic": "gm.motor_speed", "message_type": 6, "data": 1485, "success": true }
FQDN Routing
The topic string determines where a message is routed. The first segment (before the first .) is the domain, which maps to a servelet or module:
| Domain | Routes To | Example Topics |
|---|---|---|
gm | Global Memory servelet | gm.motor_speed, gm.cycle_counter |
system | System servelet | system.get_domains, system.new_project, system.full_shutdown |
datastore | Datastore servelet | datastore.calibration.offset |
modbus | Modbus module | modbus.vfd_01.speed_setpoint |
ethercat | EtherCAT module | ethercat.clearpath_0.rxpdo_5.controlword |
python | Python servelet | python.run_script |
Glossary
| Term | Definition |
|---|---|
| FQDN | Fully Qualified Domain Name. A dot-separated hierarchical address for any resource in the system. Example: ethercat.servo_drive.rxpdo_1.controlword |
| PDO | Process Data Object. The cyclic data image exchanged with fieldbus devices every scan cycle. |
| SDO | Service Data Object. A request/response protocol for reading or writing individual configuration parameters from a device. Used for acyclic (on-demand) access. |
| Cyclic data | Data exchanged at a fixed interval (every tick). PDO data from EtherCAT slaves is cyclic. Requires deterministic timing. |
| Acyclic data | Data exchanged on demand or at variable intervals. Modbus register reads, SDO access, and CommandMessage requests are acyclic. |
| Process image | The complete set of input and output data for all devices on a fieldbus, updated each scan cycle. |
| Scan cycle | One complete exchange of process data with all fieldbus devices. At a 1 ms cycle time, there are 1,000 scan cycles per second. |
| Servelet | An internal module within autocore-server that handles a specific domain of messages (e.g., GM servelet, Datastore servelet, System servelet). |