ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
euromap77.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file euromap77.h
6 * @brief EUROMAP 77 / OPC 40077 - OPC UA for injection moulding machines (IMM <-> MES), the
7 * IMM_MES_Interface information model (PC_ENABLE_EUROMAP77).
8 *
9 * EUROMAP 77 (published as OPC 40077, namespace `http://www.euromap.org/euromap77/`) standardizes how an
10 * injection molding machine (IMM) reports its identity, status, and the active job's live production
11 * counters to a MES, so any OPC UA client reads the same structure across machine vendors. It builds on
12 * EUROMAP 83 (OPC 40083, `http://www.euromap.org/euromap83/`), the shared plastics/rubber type + enum
13 * library (MachineModeEnumeration, JobStatusEnumeration, ...).
14 *
15 * This module builds the IMM_MES_Interface address space on top of the OPC UA Binary server
16 * (`services/opcua`, PC_ENABLE_OPCUA): it registers a Browse + Read resolver that answers for the
17 * IMM_MES_Interface node hierarchy and serves live values out of a caller-owned @ref EmImm struct you
18 * refresh in your loop. Same pattern as `services/umati` / `services/robotics`; no heap, no stdlib - the
19 * model is a fixed node table, the values are pointers/scalars in your struct.
20 *
21 * Model exposed (BrowseNames per the EUROMAP 77 NodeSet), under the Objects folder:
22 *
23 * IMM_MES_Interface
24 * MachineInformation Manufacturer, Model, SerialNumber, ProductCode, HardwareRevision,
25 * SoftwareRevision, DeviceRevision, ManufacturerUri
26 * MachineStatus IsPresent, MachineMode
27 * Jobs
28 * ActiveJob JobName, JobDescription, Material, ProductName, MouldId, ExpectedCycleTime,
29 * NumCavities, NominalParts
30 * ActiveJobValues JobCycleCounter, MachineCycleCounter, LastCycleTime, AverageCycleTime,
31 * JobPartsCounter, JobGoodPartsCounter, JobBadPartsCounter, JobStatus
32 *
33 * The production counters are faithful UInt64 (EUROMAP 77 defines them 64-bit), served through the OPC UA
34 * Variant's UInt64 encoding. The model is read-only (a monitoring model - the machine reports, the MES
35 * observes). Scope note: one IMM with its active job is exposed (the common single-machine MES feed); the
36 * companion-spec TypeDefinitions, methods, file/dataset transfer, and the multi-cardinality arrays
37 * (InjectionUnits, Moulds, MachineConfiguration detail) are a documented follow-on - a generic OPC UA
38 * client still browses the structure and reads every value by BrowseName today.
39 *
40 * Like umati / robotics, this installs the single OPC UA read + browse handler, so one companion model is
41 * active per server build (EUROMAP 77, umati, and robotics are mutually exclusive per OPC UA endpoint).
42 *
43 * @author Douglas Quigg (dstroy0)
44 * @date 2026
45 */
46
47#ifndef PROTOCORE_EUROMAP77_H
48#define PROTOCORE_EUROMAP77_H
49
50#include "protocore_config.h"
51
52#if PC_ENABLE_EUROMAP77
53
54#include "services/fieldbus/opcua/opcua.h" // OpcUaVariant / OpcUaReference / handler typedefs (shares the OPC UA codec)
55#include <stdint.h>
56
57/** @brief The EUROMAP 77 companion-spec namespace URI (OPC 40077). */
58#define EUROMAP77_NS_URI "http://www.euromap.org/euromap77/"
59/** @brief The EUROMAP 83 shared type/enum library namespace URI (OPC 40083). */
60#define EUROMAP83_NS_URI "http://www.euromap.org/euromap83/"
61
62/**
63 * @brief Machine mode (EUROMAP 83 MachineModeEnumeration, em83 i=3011). Exposed as Int32; the numeric
64 * values are the companion-spec enumeration.
65 */
66enum class EmMachineMode : int32_t
67{
68 EM_MODE_OTHER = 0, ///< a mode outside the ones below.
69 EM_MODE_AUTOMATIC = 1, ///< automatic production.
70 EM_MODE_SEMI_AUTOMATIC = 2, ///< semi-automatic (operator-triggered cycles).
71 EM_MODE_MANUAL = 3, ///< manual / hand operation.
72 EM_MODE_SETUP = 4, ///< set-up / preparation.
73 EM_MODE_SLEEP = 5, ///< energy-saving sleep.
74};
75
76/**
77 * @brief Active-job status (EUROMAP 83 JobStatusEnumeration, em83 i=3017). Exposed as Int32; the numeric
78 * values are the companion-spec enumeration.
79 */
80enum class EmJobStatus : int32_t
81{
82 EM_JOB_OTHER = 0, ///< a status outside the ones below.
83 EM_JOB_TRANSFERRED_ASSIGNED = 1, ///< transferred / assigned to the machine.
84 EM_JOB_SET_UP_ACTIVE = 2, ///< set-up in progress.
85 EM_JOB_SET_UP_INTERRUPTED = 3, ///< set-up interrupted.
86 EM_JOB_SET_UP_FINISHED = 4, ///< set-up finished.
87 EM_JOB_START_UP_ACTIVE = 5, ///< start-up in progress.
88 EM_JOB_IN_PRODUCTION = 6, ///< running production.
89 EM_JOB_INTERRUPTED = 7, ///< production interrupted.
90 EM_JOB_FINISHED = 8, ///< job finished.
91 EM_JOB_TEAR_DOWN_ACTIVE = 9, ///< tear-down in progress.
92 EM_JOB_TEAR_DOWN_INTERRUPTED = 10, ///< tear-down interrupted.
93 EM_JOB_TEAR_DOWN_FINISHED = 11, ///< tear-down finished.
94};
95
96/** @brief IMM identity (EUROMAP 77 MachineInformation, common subset; all String). */
97struct EmMachineInformation
98{
99 const char *manufacturer; ///< Manufacturer.
100 const char *model; ///< Model.
101 const char *serial_number; ///< SerialNumber.
102 const char *product_code; ///< ProductCode.
103 const char *hardware_revision; ///< HardwareRevision.
104 const char *software_revision; ///< SoftwareRevision.
105 const char *device_revision; ///< DeviceRevision.
106 const char *manufacturer_uri; ///< ManufacturerUri.
107};
108
109/** @brief IMM live status (EUROMAP 77 MachineStatus, common subset). */
110struct EmMachineStatus
111{
112 bool is_present; ///< IsPresent.
113 EmMachineMode machine_mode; ///< MachineMode.
114};
115
116/** @brief The active job's static parameters (EUROMAP 77 Jobs.ActiveJob, common subset). */
117struct EmActiveJob
118{
119 const char *job_name; ///< JobName.
120 const char *job_description; ///< JobDescription.
121 const char *material; ///< Material.
122 const char *product_name; ///< ProductName.
123 const char *mould_id; ///< MouldId.
124 double expected_cycle_time; ///< ExpectedCycleTime (Duration, seconds -> Double).
125 uint32_t num_cavities; ///< NumCavities.
126 uint64_t nominal_parts; ///< NominalParts.
127};
128
129/** @brief The active job's live production counters (EUROMAP 77 Jobs.ActiveJobValues; counters UInt64). */
130struct EmActiveJobValues
131{
132 uint64_t job_cycle_counter; ///< JobCycleCounter.
133 uint64_t machine_cycle_counter; ///< MachineCycleCounter.
134 double last_cycle_time; ///< LastCycleTime (Duration -> Double).
135 double average_cycle_time; ///< AverageCycleTime (Duration -> Double).
136 uint64_t job_parts_counter; ///< JobPartsCounter.
137 uint64_t job_good_parts_counter; ///< JobGoodPartsCounter.
138 uint64_t job_bad_parts_counter; ///< JobBadPartsCounter.
139 EmJobStatus job_status; ///< JobStatus.
140};
141
142/**
143 * @brief The whole IMM_MES_Interface the server exposes. Own it in your sketch and refresh its fields
144 * each loop from your machine I/O; the resolvers read straight out of it (no copy). String fields
145 * may be null (served as an empty String).
146 */
147struct EmImm
148{
149 const char *name; ///< IMM_MES_Interface BrowseName / DisplayName.
150 EmMachineInformation info; ///< MachineInformation.
151 EmMachineStatus status; ///< MachineStatus.
152 EmActiveJob active_job; ///< Jobs.ActiveJob.
153 EmActiveJobValues active_job_values; ///< Jobs.ActiveJobValues.
154};
155
156/**
157 * @brief Bind the IMM the resolvers serve. @p imm must outlive the server (own it statically). Refresh
158 * its fields any time; each Read returns the current values.
159 */
160void pc_em77_bind(const EmImm *imm);
161
162/**
163 * @brief Read resolver for the IMM_MES_Interface model (an @ref OpcUaReadHandler): fills @p out for an
164 * EUROMAP 77 node's Value attribute. Returns false for a node outside the model (the server
165 * answers BadNodeIdUnknown). Install with `pc_opcua_set_read_handler(pc_em77_read)`.
166 */
167bool pc_em77_read(uint16_t ns, uint32_t id, uint32_t attribute, OpcUaVariant *out);
168
169/**
170 * @brief Browse resolver for the IMM_MES_Interface model (an @ref OpcUaBrowseHandler): writes the child
171 * references of an EUROMAP 77 node (and of the Objects folder, which organizes the
172 * IMM_MES_Interface) into @p out. Returns the count, or -1 for a node outside the model. Install
173 * with `pc_opcua_set_browse_handler(pc_em77_browse)`.
174 */
175int32_t pc_em77_browse(uint16_t ns, uint32_t id, OpcUaReference *out, uint32_t max);
176
177/**
178 * @brief Convenience: bind @p imm and register both resolvers on the OPC UA server in one call
179 * (`pc_opcua_set_read_handler` + `pc_opcua_set_browse_handler`). Call before `server.begin()`.
180 */
181void pc_em77_install(const EmImm *imm);
182
183#endif // PC_ENABLE_EUROMAP77
184#endif // PROTOCORE_EUROMAP77_H
OPC UA Binary server: handshake + SecureChannel + Session + Read/Write + Browse (PC_ENABLE_OPCUA).
User-facing configuration for ProtoCore.