30 MOTIONDEVICESYSTEM = 6000,
35 MD_MANUFACTURER = 6201,
37 MD_PRODUCTCODE = 6203,
43 MDP_SPEEDOVERRIDE = 6213,
51 CT_MANUFACTURER = 6611,
53 CT_PRODUCTCODE = 6613,
56 SW_MANUFACTURER = 6621,
84 const RoboticsMotionDeviceSystem *mds;
87RoboticsCtx s_robotics = {
nullptr, {{0}}};
90void build_axis_names(RoboticsCtx *c)
94 char *b = c->axis_name[k];
104 b[o++] = (char)(
'0' + (idx / 10));
106 b[o++] = (char)(
'0' + (idx % 10));
114bool decode_axis(uint32_t
id, uint32_t axis_count, uint32_t *k_out, uint32_t *sub_out)
120 uint32_t rel =
id - AXIS_BASE;
121 uint32_t k = rel / 10;
122 uint32_t sub = rel % 10;
123 if (k < 1 || k > axis_count)
133void set_str(OpcUaVariant *o,
const char *s)
135 o->type = OpcUaVariantType::OPCUA_VAR_STRING;
137 o->str_len = (int32_t)strnlen(o->str, 0xFFFF);
139void set_i32(OpcUaVariant *o, int32_t v)
141 o->type = OpcUaVariantType::OPCUA_VAR_INT32;
144void set_f64(OpcUaVariant *o,
double v)
146 o->type = OpcUaVariantType::OPCUA_VAR_DOUBLE;
149void set_bool(OpcUaVariant *o,
bool v)
151 o->type = OpcUaVariantType::OPCUA_VAR_BOOL;
159int32_t add_ref(OpcUaReference *out, int32_t n, uint32_t max, uint32_t target_id,
const char *name, uint32_t node_class,
162 if ((uint32_t)n >= max)
166 OpcUaReference *r = &out[n];
167 r->ref_type_id = organizes ? OPCUA_REFTYPE_ORGANIZES : OPCUA_REFTYPE_HAS_COMPONENT;
168 r->is_forward =
true;
170 r->target_id = target_id;
172 r->browse_name = name;
173 r->display_name = name;
174 r->node_class = node_class;
176 (node_class == OPCUA_NODECLASS_VARIABLE) ? OPCUA_TYPEDEF_BASE_DATA_VARIABLE : OPCUA_TYPEDEF_BASE_OBJECT;
179int32_t add_obj(OpcUaReference *out, int32_t n, uint32_t max, uint32_t
id,
const char *name)
181 return add_ref(out, n, max,
id, name, OPCUA_NODECLASS_OBJECT,
false);
183int32_t add_folder_member(OpcUaReference *out, int32_t n, uint32_t max, uint32_t
id,
const char *name)
185 return add_ref(out, n, max,
id, name, OPCUA_NODECLASS_OBJECT,
true);
187int32_t add_var(OpcUaReference *out, int32_t n, uint32_t max, uint32_t
id,
const char *name)
189 return add_ref(out, n, max,
id, name, OPCUA_NODECLASS_VARIABLE,
false);
196void pc_robotics_bind(
const RoboticsMotionDeviceSystem *mds)
198 s_robotics.mds = mds;
199 build_axis_names(&s_robotics);
202bool pc_robotics_read(uint16_t ns, uint32_t
id, uint32_t attribute, OpcUaVariant *out)
204 const RoboticsMotionDeviceSystem *mds = s_robotics.mds;
205 if (!mds || ns !=
PC_ROBOTICS_NS || attribute != OPCUA_ATTR_VALUE)
213 if (decode_axis(
id, mds->device.axis_count, &k, &sub) && sub >= AXVAR_POSITION && sub <= AXVAR_PROFILE)
215 const RoboticsAxis *ax = &mds->device.axes[k - 1];
221 set_f64(out, ax->actual_position);
224 set_f64(out, ax->actual_speed);
227 set_f64(out, ax->actual_acceleration);
230 set_i32(out, (int32_t)ax->motion_profile);
240 case MD_MANUFACTURER:
241 set_str(out, mds->device.manufacturer);
244 set_str(out, mds->device.model);
247 set_str(out, mds->device.product_code);
250 set_str(out, mds->device.serial_number);
253 set_i32(out, (int32_t)mds->device.category);
257 set_bool(out, mds->device.on_path);
260 set_bool(out, mds->device.in_control);
262 case MDP_SPEEDOVERRIDE:
263 set_f64(out, mds->device.speed_override);
266 case CT_MANUFACTURER:
267 set_str(out, mds->controller.manufacturer);
270 set_str(out, mds->controller.model);
273 set_str(out, mds->controller.product_code);
276 set_str(out, mds->controller.serial_number);
278 case SW_MANUFACTURER:
279 set_str(out, mds->controller.sw_manufacturer);
282 set_str(out, mds->controller.sw_model);
285 set_str(out, mds->controller.sw_revision);
289 set_i32(out, (int32_t)mds->safety.operational_mode);
292 set_bool(out, mds->safety.emergency_stop);
295 set_bool(out, mds->safety.protective_stop);
302int32_t pc_robotics_browse(uint16_t ns, uint32_t
id, OpcUaReference *out, uint32_t max)
304 const RoboticsMotionDeviceSystem *mds = s_robotics.mds;
311 if (ns == 0 &&
id == 85)
313 return add_folder_member(out, 0, max, MOTIONDEVICESYSTEM, mds->name ? mds->name :
"MotionDeviceSystem");
324 if (decode_axis(
id, mds->device.axis_count, &k, &sub) && sub == 0)
326 uint32_t base = AXIS_BASE + k * 10;
328 n = add_var(out, n, max, base + AXVAR_POSITION,
"ActualPosition");
329 n = add_var(out, n, max, base + AXVAR_SPEED,
"ActualSpeed");
330 n = add_var(out, n, max, base + AXVAR_ACCEL,
"ActualAcceleration");
331 n = add_var(out, n, max, base + AXVAR_PROFILE,
"MotionProfile");
338 case MOTIONDEVICESYSTEM:
339 n = add_obj(out, n, max, MOTIONDEVICES,
"MotionDevices");
340 n = add_obj(out, n, max, CONTROLLERS,
"Controllers");
341 n = add_obj(out, n, max, SAFETYSTATES,
"SafetyStates");
344 return add_folder_member(out, 0, max, MOTIONDEVICE,
"MotionDevice");
346 n = add_var(out, n, max, MD_MANUFACTURER,
"Manufacturer");
347 n = add_var(out, n, max, MD_MODEL,
"Model");
348 n = add_var(out, n, max, MD_PRODUCTCODE,
"ProductCode");
349 n = add_var(out, n, max, MD_SERIAL,
"SerialNumber");
350 n = add_var(out, n, max, MD_CATEGORY,
"MotionDeviceCategory");
351 n = add_obj(out, n, max, MD_PARAMSET,
"ParameterSet");
352 n = add_obj(out, n, max, MD_AXES,
"Axes");
355 n = add_var(out, n, max, MDP_ONPATH,
"OnPath");
356 n = add_var(out, n, max, MDP_INCONTROL,
"InControl");
357 n = add_var(out, n, max, MDP_SPEEDOVERRIDE,
"SpeedOverride");
360 for (uint32_t a = 1; a <= mds->device.axis_count && a <=
PC_ROBOTICS_AXES; a++)
362 n = add_folder_member(out, n, max, AXIS_BASE + a * 10, s_robotics.axis_name[a - 1]);
366 return add_folder_member(out, 0, max, CONTROLLER,
"Controller");
368 n = add_var(out, n, max, CT_MANUFACTURER,
"Manufacturer");
369 n = add_var(out, n, max, CT_MODEL,
"Model");
370 n = add_var(out, n, max, CT_PRODUCTCODE,
"ProductCode");
371 n = add_var(out, n, max, CT_SERIAL,
"SerialNumber");
372 n = add_obj(out, n, max, CT_SOFTWARE,
"Software");
375 n = add_var(out, n, max, SW_MANUFACTURER,
"Manufacturer");
376 n = add_var(out, n, max, SW_MODEL,
"Model");
377 n = add_var(out, n, max, SW_REVISION,
"SoftwareRevision");
380 return add_folder_member(out, 0, max, SAFETYSTATE,
"SafetyState");
382 return add_obj(out, 0, max, SS_PARAMSET,
"ParameterSet");
384 n = add_var(out, n, max, SSP_OPMODE,
"OperationalMode");
385 n = add_var(out, n, max, SSP_ESTOP,
"EmergencyStop");
386 n = add_var(out, n, max, SSP_PSTOP,
"ProtectiveStop");
393void pc_robotics_install(
const RoboticsMotionDeviceSystem *mds)
395 pc_robotics_bind(mds);
396 pc_opcua_set_read_handler(pc_robotics_read);
397 pc_opcua_set_browse_handler(pc_robotics_browse);
#define PC_ROBOTICS_AXES
Number of Axes the robotics MotionDevice exposes (default 6; must fit PC_OPCUA_REF_MAX).
#define PC_ROBOTICS_NS
NamespaceIndex the robotics MotionDeviceSystem nodes live at (default 1).
OPC UA for Robotics (OPC 40010-1) MotionDevice information model (PC_ENABLE_ROBOTICS).