11#if PC_ENABLE_MTCONNECT
17void put(pc_mtc_streams *s,
const char *text)
28 size_t tl = strnlen(text, s->cap + 1);
29 if (s->len + tl >= s->cap)
34 memcpy(s->buf + s->len, text, tl);
38void put_escaped(pc_mtc_streams *s,
const char *text)
49 for (
const char *p = text; *p; p++)
51 const char *rep =
nullptr;
75 if (s->len + 1 >= s->cap)
80 s->buf[s->len++] = *p;
86void put_u64(pc_mtc_streams *s, uint64_t v)
92 tmp[n++] = (char)(
'0' + (
int)(v % 10));
96 for (
int i = 0; i < n; i++)
98 out[i] = tmp[n - 1 - i];
104const char *mtc_cat_str(pc_mtc_category cat)
106 if (cat == pc_mtc_category::PC_MTC_SAMPLE)
110 if (cat == pc_mtc_category::PC_MTC_EVENT)
118void pc_mtc_streams_begin(pc_mtc_streams *s,
char *buf,
size_t cap, uint64_t instance_id, uint64_t next_seq,
119 const char *device_name)
124 s->ok = (buf !=
nullptr && cap > 0);
126 put(s,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
127 put(s,
"<MTConnectStreams xmlns=\"urn:mtconnect.org:MTConnectStreams:1.4\">");
128 put(s,
"<Header instanceId=\"");
129 put_u64(s, instance_id);
130 put(s,
"\" version=\"1.4\" nextSequence=\"");
131 put_u64(s, next_seq);
133 put(s,
"<Streams><DeviceStream name=\"");
134 put_escaped(s, device_name ? device_name :
"");
138void pc_mtc_streams_add(pc_mtc_streams *s, pc_mtc_category cat,
const char *type,
const char *data_id, uint64_t seq,
139 const char *timestamp,
const char *value)
147 put(s,
"<ComponentStream component=\"Device\">");
150 const char *wrap =
"Condition";
151 if (cat == pc_mtc_category::PC_MTC_SAMPLE)
155 else if (cat == pc_mtc_category::PC_MTC_EVENT)
162 if (cat == pc_mtc_category::PC_MTC_CONDITION)
165 const char *sub = value ? value :
"Normal";
169 put_escaped(s, type ? type :
"");
170 put(s,
"\" dataItemId=\"");
171 put_escaped(s, data_id ? data_id :
"");
172 put(s,
"\" sequence=\"");
174 put(s,
"\" timestamp=\"");
175 put_escaped(s, timestamp ? timestamp :
"");
182 put(s, type ? type :
"");
183 put(s,
" dataItemId=\"");
184 put_escaped(s, data_id ? data_id :
"");
185 put(s,
"\" sequence=\"");
187 put(s,
"\" timestamp=\"");
188 put_escaped(s, timestamp ? timestamp :
"");
190 put_escaped(s, value ? value :
"");
192 put(s, type ? type :
"");
200size_t pc_mtc_streams_end(pc_mtc_streams *s)
204 put(s,
"</ComponentStream>");
206 put(s,
"</DeviceStream></Streams></MTConnectStreams>");
211 s->buf[s->len] =
'\0';
215size_t pc_mtc_error(uint64_t instance_id,
const char *error_code,
const char *message,
char *out,
size_t cap)
221 s.ok = (out !=
nullptr && cap > 0);
223 put(&s,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
224 put(&s,
"<MTConnectError xmlns=\"urn:mtconnect.org:MTConnectError:1.4\">");
225 put(&s,
"<Header instanceId=\"");
226 put_u64(&s, instance_id);
227 put(&s,
"\" version=\"1.4\"/>");
228 put(&s,
"<Errors><Error errorCode=\"");
229 put_escaped(&s, error_code ? error_code :
"");
231 put_escaped(&s, message ? message :
"");
232 put(&s,
"</Error></Errors></MTConnectError>");
235 if (!s.ok || out ==
nullptr)
247void pc_mtc_devices_begin(pc_mtc_streams *s,
char *buf,
size_t cap, uint64_t instance_id,
const char *device_id,
248 const char *device_name,
const char *uuid)
253 s->ok = (buf !=
nullptr && cap > 0);
255 put(s,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
256 put(s,
"<MTConnectDevices xmlns=\"urn:mtconnect.org:MTConnectDevices:1.4\">");
257 put(s,
"<Header instanceId=\"");
258 put_u64(s, instance_id);
259 put(s,
"\" version=\"1.4\"/>");
260 put(s,
"<Devices><Device id=\"");
261 put_escaped(s, device_id ? device_id :
"");
262 put(s,
"\" name=\"");
263 put_escaped(s, device_name ? device_name :
"");
264 put(s,
"\" uuid=\"");
265 put_escaped(s, uuid ? uuid :
"");
266 put(s,
"\"><DataItems>");
269void pc_mtc_devices_add_item(pc_mtc_streams *s, pc_mtc_category cat,
const char *
id,
const char *type,
const char *name,
276 put(s,
"<DataItem category=\"");
277 put(s, mtc_cat_str(cat));
279 put_escaped(s,
id ?
id :
"");
280 put(s,
"\" type=\"");
281 put_escaped(s, type ? type :
"");
286 put_escaped(s, name);
289 if (units && units[0])
292 put_escaped(s, units);
298size_t pc_mtc_devices_end(pc_mtc_streams *s)
300 put(s,
"</DataItems></Device></Devices></MTConnectDevices>");
305 s->buf[s->len] =
'\0';
311void pc_mtc_assets_begin(pc_mtc_streams *s,
char *buf,
size_t cap, uint64_t instance_id, uint32_t asset_count,
312 uint32_t asset_buffer_size)
317 s->ok = (buf !=
nullptr && cap > 0);
319 put(s,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
320 put(s,
"<MTConnectAssets xmlns=\"urn:mtconnect.org:MTConnectAssets:1.4\">");
321 put(s,
"<Header instanceId=\"");
322 put_u64(s, instance_id);
323 put(s,
"\" version=\"1.4\" assetBufferSize=\"");
324 put_u64(s, asset_buffer_size);
325 put(s,
"\" assetCount=\"");
326 put_u64(s, asset_count);
331void pc_mtc_assets_cutting_tool_begin(pc_mtc_streams *s,
const char *asset_id,
const char *serial_number,
332 const char *tool_id,
const char *device_uuid,
const char *timestamp)
334 put(s,
"<CuttingTool assetId=\"");
335 put_escaped(s, asset_id ? asset_id :
"");
337 if (serial_number && serial_number[0])
339 put(s,
" serialNumber=\"");
340 put_escaped(s, serial_number);
343 if (tool_id && tool_id[0])
345 put(s,
" toolId=\"");
346 put_escaped(s, tool_id);
349 if (device_uuid && device_uuid[0])
351 put(s,
" deviceUuid=\"");
352 put_escaped(s, device_uuid);
355 if (timestamp && timestamp[0])
357 put(s,
" timestamp=\"");
358 put_escaped(s, timestamp);
361 put(s,
"><CuttingToolLifeCycle>");
364void pc_mtc_assets_tool_life(pc_mtc_streams *s,
const char *type,
const char *count_direction,
const char *limit,
368 put(s,
"<ToolLife type=\"");
369 put_escaped(s, type ? type :
"");
370 put(s,
"\" countDirection=\"");
371 put_escaped(s, count_direction ? count_direction :
"");
373 if (limit && limit[0])
376 put_escaped(s, limit);
380 put_escaped(s, value ? value :
"");
381 put(s,
"</ToolLife>");
384void pc_mtc_assets_cutting_tool_end(pc_mtc_streams *s)
386 put(s,
"</CuttingToolLifeCycle></CuttingTool>");
389size_t pc_mtc_assets_end(pc_mtc_streams *s)
391 put(s,
"</Assets></MTConnectAssets>");
396 s->buf[s->len] =
'\0';
405void mtc_copy_str(
char *dst,
size_t cap,
const char *src)
417 for (; i < cap - 1 && src[i] !=
'\0'; i++)
426void mtc_streams_begin_windowed(pc_mtc_streams *s,
char *buf,
size_t cap, uint64_t instance_id, uint64_t first_seq,
427 uint64_t last_seq, uint64_t next_seq, uint32_t buffer_size,
const char *device_name)
432 s->ok = (buf !=
nullptr && cap > 0);
434 put(s,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
435 put(s,
"<MTConnectStreams xmlns=\"urn:mtconnect.org:MTConnectStreams:1.4\">");
436 put(s,
"<Header instanceId=\"");
437 put_u64(s, instance_id);
438 put(s,
"\" version=\"1.4\" bufferSize=\"");
439 put_u64(s, buffer_size);
440 put(s,
"\" firstSequence=\"");
441 put_u64(s, first_seq);
442 put(s,
"\" lastSequence=\"");
443 put_u64(s, last_seq);
444 put(s,
"\" nextSequence=\"");
445 put_u64(s, next_seq);
447 put(s,
"<Streams><DeviceStream name=\"");
448 put_escaped(s, device_name ? device_name :
"");
453void pc_mtc_sample_buffer_init(pc_mtc_sample_buffer *b, uint64_t start_seq)
457 b->next_seq = start_seq ? start_seq : 1;
458 b->first_seq = b->next_seq;
461uint64_t pc_mtc_sample_buffer_add(pc_mtc_sample_buffer *b, pc_mtc_category cat,
const char *type,
const char *data_id,
462 const char *timestamp,
const char *value)
464 pc_mtc_observation *o = &b->obs[b->head];
466 o->seq = b->next_seq;
467 mtc_copy_str(o->type,
sizeof(o->type), type);
468 mtc_copy_str(o->data_id,
sizeof(o->data_id), data_id);
469 mtc_copy_str(o->timestamp,
sizeof(o->timestamp), timestamp);
470 mtc_copy_str(o->value,
sizeof(o->value), value);
480 return b->next_seq++;
483size_t pc_mtc_sample_query(
const pc_mtc_sample_buffer *b,
char *buf,
size_t cap, uint64_t instance_id,
484 const char *device_name, uint64_t from, uint32_t count)
486 uint64_t first = b->first_seq;
487 uint64_t next = b->next_seq;
488 uint64_t last = next - 1;
489 uint64_t start = from < first ? first : from;
491 uint32_t avail = (start < next) ? (uint32_t)(next - start) : 0;
492 uint32_t to_emit = (count < avail) ? count : avail;
494 uint64_t next_report = (start >= next) ? next : start + to_emit;
497 mtc_streams_begin_windowed(&s, buf, cap, instance_id, first, last, next_report,
PC_MTC_SAMPLE_BUFFER, device_name);
502 for (uint32_t e = 0; e < to_emit; e++)
504 uint32_t k = (uint32_t)((start - first) + e);
506 pc_mtc_streams_add(&s, o->cat, o->type, o->data_id, o->seq, o->timestamp, o->value);
508 return pc_mtc_streams_end(&s);
MTConnect agent response codec (PC_ENABLE_MTCONNECT).
#define PC_MTC_SAMPLE_BUFFER
MTConnect rolling sample buffer sizing (PC_ENABLE_MTCONNECT).