@springfield/ham-radio-utils 3.2.5 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/schemas/radio-protocol-schema.json +129 -295
- package/dist/utils/ui-logger.d.ts +0 -14
- package/dist/utils/ui-logger.d.ts.map +1 -1
- package/dist/utils/ui-logger.js +19 -65
- package/dist/utils/ui-logger.js.map +1 -1
- package/package.json +7 -7
- package/src/schemas/radio-protocol-schema.json +129 -295
- package/src/utils/ui-logger.ts +19 -85
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-logger.js","sourceRoot":"","sources":["../../src/utils/ui-logger.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ILogLayer } from 'loglayer';\n\n/**\n * UI Logger: Command-Level Logging for UI Display\n *\n * This module provides a specialized logger for capturing command-level information\n * that can be easily parsed and displayed in a UI. It captures details about\n * commands, data sent, data expected, and data received in a structured format.\n *\n * Purpose:\n * - Captures command-level information for UI display\n * - Provides structured JSON logging for easy parsing\n * - Tracks command execution details including timing\n * - Supports protocol debugging in UI environments\n * - Maintains separation from debug logging\n *\n * Design Rationale:\n * - Single log entry per command provides clean UI display\n * - JSON structure enables easy parsing and filtering\n * - Command-level granularity is appropriate for UI debugging\n * - Structured data supports rich UI representations\n * - Separate from debug logging avoids UI noise\n */\n\ninterface ProtocolContext {\n variables?: Map<string, unknown>;\n}\n\n/**\n * Generic protocol step interface for UI logging\n */\nexport type UIProtocolStep = Record<string, unknown>;\n\n/**\n * Type guards for protocol step properties\n */\nconst hasDescription = (obj: unknown): obj is { description: string } =>\n typeof obj === 'object' && obj !== null && 'description' in obj && typeof (obj as Record<string, unknown>).description === 'string';\n\nconst hasReceive = (obj: unknown): obj is { receive: unknown } => typeof obj === 'object' && obj !== null && 'receive' in obj;\n\nconst hasEndChunk = (obj: unknown): obj is { endChunk: { receive: unknown } } =>\n typeof obj === 'object' &&\n obj !== null &&\n 'endChunk' in obj &&\n typeof (obj as Record<string, unknown>).endChunk === 'object' &&\n (obj as Record<string, unknown>).endChunk !== null &&\n 'receive' in ((obj as Record<string, unknown>).endChunk as Record<string, unknown>);\n\nconst hasStartChunk = (obj: unknown): obj is { startChunk: { receive: unknown } } =>\n typeof obj === 'object' &&\n obj !== null &&\n 'startChunk' in obj &&\n typeof (obj as Record<string, unknown>).startChunk === 'object' &&\n (obj as Record<string, unknown>).startChunk !== null &&\n 'receive' in ((obj as Record<string, unknown>).startChunk as Record<string, unknown>);\n\n/**\n * UI Logger for capturing command-level information for UI display\n */\nexport class UILogger {\n private logger: ILogLayer;\n private commandStartTimes = new Map<string, number>();\n\n constructor(logger: ILogLayer) {\n this.logger = logger;\n }\n\n // eslint-disable-next-line max-params\n startCommand(stepIndex: number, totalSteps: number, operation: string, step: UIProtocolStep): void {\n const commandId = `${operation}-${stepIndex}`;\n const startTime = Date.now();\n this.commandStartTimes.set(commandId, startTime);\n\n const commandType = this.getCommandType(step);\n const description = this.getStepDescription(step);\n\n this.logger\n .withMetadata({\n commandId,\n commandType,\n description,\n operation,\n startTime,\n stepIndex,\n totalSteps,\n })\n .info('Command started');\n }\n\n // eslint-disable-next-line max-params\n logCommandSuccess(stepIndex: number, totalSteps: number, operation: string, step: UIProtocolStep, context: ProtocolContext): void {\n const commandId = `${operation}-${stepIndex}`;\n const startTime = this.commandStartTimes.get(commandId) || Date.now();\n const endTime = Date.now();\n const duration = endTime - startTime;\n\n const commandType = this.getCommandType(step);\n const description = this.getStepDescription(step);\n\n // Extract sent and received data from context\n const dataSent = context.variables && context.variables.get('lastSentData');\n const dataReceived = context.variables && context.variables.get('lastReceivedData');\n const dataExpected = this.getExpectedData(step);\n\n // For readSegment, also extract chunk logs if present\n const dataChunks = commandType === 'readSegment' && context.variables && context.variables.get('lastReadSegmentChunks');\n\n // Convert dataSent and dataReceived to byte array format if they exist\n // eslint-disable-next-line unicorn/prefer-spread\n const dataSentArray = dataSent && Array.from(dataSent as Uint8Array);\n // eslint-disable-next-line unicorn/prefer-spread\n const dataReceivedArray = dataReceived && Array.from(dataReceived as Uint8Array);\n\n this.logger\n .withMetadata({\n commandType,\n dataChunks,\n dataExpected,\n dataReceived: dataReceivedArray,\n dataSent: dataSentArray,\n description,\n duration,\n endTime,\n operation,\n startTime,\n stepIndex,\n success: true,\n totalSteps,\n })\n .info('Command completed successfully');\n }\n\n // eslint-disable-next-line max-params\n logCommandFailure(stepIndex: number, totalSteps: number, operation: string, step: UIProtocolStep, error: Error, context: ProtocolContext): void {\n const commandId = `${operation}-${stepIndex}`;\n const startTime = this.commandStartTimes.get(commandId) || Date.now();\n const endTime = Date.now();\n const duration = endTime - startTime;\n\n const commandType = this.getCommandType(step);\n const description = this.getStepDescription(step);\n\n // Extract sent data from context\n const dataSent = context.variables && context.variables.get('lastSentData');\n const dataExpected = this.getExpectedData(step);\n\n // Convert dataSent to byte array format if it exists\n // eslint-disable-next-line unicorn/prefer-spread\n const dataSentArray = dataSent && Array.from(dataSent as Uint8Array);\n\n this.logger\n .withMetadata({\n commandType,\n dataExpected,\n dataSent: dataSentArray,\n description,\n duration,\n endTime,\n error: error.message,\n operation,\n startTime,\n stepIndex,\n success: false,\n totalSteps,\n })\n .info('Command failed');\n }\n\n private getCommandType(step: UIProtocolStep): string {\n if ('sendReceive' in step) {\n return 'sendReceive';\n }\n if ('send' in step) {\n return 'send';\n }\n if ('receive' in step) {\n return 'receive';\n }\n if ('readSegment' in step) {\n return 'readSegment';\n }\n if ('writeSegment' in step) {\n return 'writeSegment';\n }\n if ('setVariable' in step) {\n return 'setVariable';\n }\n return 'unknown';\n }\n\n private getStepDescription(step: UIProtocolStep): string {\n if ('sendReceive' in step && hasDescription(step.sendReceive)) {\n return step.sendReceive.description;\n }\n if ('send' in step && hasDescription(step.send)) {\n return step.send.description;\n }\n if ('receive' in step && hasDescription(step.receive)) {\n return step.receive.description;\n }\n if ('readSegment' in step && hasDescription(step.readSegment)) {\n return step.readSegment.description;\n }\n if ('writeSegment' in step && hasDescription(step.writeSegment)) {\n return step.writeSegment.description;\n }\n return 'No description';\n }\n\n private getExpectedData(step: UIProtocolStep): unknown {\n if ('sendReceive' in step && hasReceive(step.sendReceive)) {\n return step.sendReceive.receive;\n }\n if ('receive' in step) {\n return step.receive;\n }\n if ('readSegment' in step) {\n // For readSegment, return both start and end chunk receive patterns\n const { readSegment } = step;\n if (hasEndChunk(readSegment) && hasStartChunk(readSegment)) {\n return {\n endChunk: readSegment.endChunk.receive,\n startChunk: readSegment.startChunk.receive,\n type: 'readSegment',\n };\n }\n }\n return {};\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ui-logger.js","sourceRoot":"","sources":["../../src/utils/ui-logger.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ILogLayer } from 'loglayer';\n\n/**\n * UI Logger: Command-Level Logging for UI Display\n *\n * This module provides a specialized logger for capturing command-level information\n * that can be easily parsed and displayed in a UI. It captures details about\n * commands, data sent, data expected, and data received in a structured format.\n */\n\ninterface ProtocolContext {\n variables?: Map<string, unknown>;\n}\n\n/**\n * Generic protocol step interface for UI logging\n */\nexport type UIProtocolStep = Record<string, unknown>;\n\nconst hasDescription = (obj: unknown): obj is { description: string } =>\n typeof obj === 'object' && obj !== null && 'description' in obj && typeof (obj as Record<string, unknown>).description === 'string';\n\n/**\n * UI Logger for capturing command-level information for UI display\n */\nexport class UILogger {\n private logger: ILogLayer;\n private commandStartTimes = new Map<string, number>();\n\n constructor(logger: ILogLayer) {\n this.logger = logger;\n }\n\n // eslint-disable-next-line max-params\n startCommand(stepIndex: number, totalSteps: number, operation: string, step: UIProtocolStep): void {\n const commandId = `${operation}-${stepIndex}`;\n const startTime = Date.now();\n this.commandStartTimes.set(commandId, startTime);\n\n const commandType = this.getCommandType(step);\n const description = this.getStepDescription(step);\n\n this.logger\n .withMetadata({\n commandId,\n commandType,\n description,\n operation,\n startTime,\n stepIndex,\n totalSteps,\n })\n .info('Command started');\n }\n\n // eslint-disable-next-line max-params\n logCommandSuccess(stepIndex: number, totalSteps: number, operation: string, step: UIProtocolStep, context: ProtocolContext): void {\n const commandId = `${operation}-${stepIndex}`;\n const startTime = this.commandStartTimes.get(commandId) || Date.now();\n const endTime = Date.now();\n const duration = endTime - startTime;\n\n const commandType = this.getCommandType(step);\n const description = this.getStepDescription(step);\n\n const dataSent = context.variables && context.variables.get('lastSentData');\n const dataReceived = context.variables && context.variables.get('lastReceivedData');\n const dataExpected = this.getExpectedData(step);\n const dataChunks = commandType === 'read' && context.variables && context.variables.get('lastReadSegmentChunks');\n\n // eslint-disable-next-line unicorn/prefer-spread\n const dataSentArray = dataSent && Array.from(dataSent as Uint8Array);\n // eslint-disable-next-line unicorn/prefer-spread\n const dataReceivedArray = dataReceived && Array.from(dataReceived as Uint8Array);\n\n this.logger\n .withMetadata({\n commandType,\n dataChunks,\n dataExpected,\n dataReceived: dataReceivedArray,\n dataSent: dataSentArray,\n description,\n duration,\n endTime,\n operation,\n startTime,\n stepIndex,\n success: true,\n totalSteps,\n })\n .info('Command completed successfully');\n }\n\n // eslint-disable-next-line max-params\n logCommandFailure(stepIndex: number, totalSteps: number, operation: string, step: UIProtocolStep, error: Error, context: ProtocolContext): void {\n const commandId = `${operation}-${stepIndex}`;\n const startTime = this.commandStartTimes.get(commandId) || Date.now();\n const endTime = Date.now();\n const duration = endTime - startTime;\n\n const commandType = this.getCommandType(step);\n const description = this.getStepDescription(step);\n\n const dataSent = context.variables && context.variables.get('lastSentData');\n const dataExpected = this.getExpectedData(step);\n\n // eslint-disable-next-line unicorn/prefer-spread\n const dataSentArray = dataSent && Array.from(dataSent as Uint8Array);\n\n this.logger\n .withMetadata({\n commandType,\n dataExpected,\n dataSent: dataSentArray,\n description,\n duration,\n endTime,\n error: error.message,\n operation,\n startTime,\n stepIndex,\n success: false,\n totalSteps,\n })\n .info('Command failed');\n }\n\n private getCommandType(step: UIProtocolStep): string {\n if ('read' in step) {\n return 'read';\n }\n if ('write' in step) {\n return 'write';\n }\n if ('send' in step || 'expect' in step) {\n return 'exchange';\n }\n return 'unknown';\n }\n\n private getStepDescription(step: UIProtocolStep): string {\n if (hasDescription(step)) {\n return step.description;\n }\n return 'No description';\n }\n\n private getExpectedData(step: UIProtocolStep): unknown {\n if ('read' in step && typeof step.read === 'object' && step.read !== null && 'expect' in step.read) {\n const read = step.read as { expect: unknown; ack?: { expect?: unknown } };\n return {\n expect: read.expect,\n ack: read.ack?.expect,\n };\n }\n if ('write' in step && typeof step.write === 'object' && step.write !== null && 'expect' in step.write) {\n return (step.write as { expect: unknown }).expect;\n }\n if ('expect' in step) {\n return step.expect;\n }\n return {};\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@springfield/ham-radio-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"author": "Bryan Hunt",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"readme": "README.md",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"prepare": "husky"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@springfield/ham-radio-api": "^
|
|
32
|
-
"ajv": "^8.
|
|
31
|
+
"@springfield/ham-radio-api": "^17.0.0",
|
|
32
|
+
"ajv": "^8.20.0",
|
|
33
33
|
"ajv-formats": "^3.0.1",
|
|
34
34
|
"fishery": "^2.4.0",
|
|
35
|
-
"loglayer": "^
|
|
35
|
+
"loglayer": "^9.4.0",
|
|
36
36
|
"sprintf-js": "^1.1.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
"@commitlint/config-conventional": "21.2.2",
|
|
41
41
|
"@semantic-release/changelog": "7.0.0",
|
|
42
42
|
"@semantic-release/git": "11.0.1",
|
|
43
|
-
"@semantic-release/github": "12.0.
|
|
43
|
+
"@semantic-release/github": "12.0.9",
|
|
44
44
|
"@semantic-release/npm": "13.1.5",
|
|
45
45
|
"@types/chai": "5.2.3",
|
|
46
|
-
"@types/node": "
|
|
46
|
+
"@types/node": "26.2.0",
|
|
47
47
|
"@types/sprintf-js": "1.1.4",
|
|
48
|
-
"chai": "6.2.
|
|
48
|
+
"chai": "6.2.2",
|
|
49
49
|
"husky": "9.1.7",
|
|
50
50
|
"oxfmt": "^0.64.0",
|
|
51
51
|
"oxlint": "1.79.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"title": "Radio Protocol DSL Schema",
|
|
4
|
-
"description": "Schema for defining radio communication protocols
|
|
4
|
+
"description": "Schema for defining radio communication protocols as send/expect exchanges",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": [
|
|
7
7
|
"id",
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
},
|
|
170
170
|
"endAddress": {
|
|
171
171
|
"type": "integer",
|
|
172
|
-
"description": "
|
|
172
|
+
"description": "Inclusive ending address of the memory segment",
|
|
173
173
|
"minimum": 0
|
|
174
174
|
}
|
|
175
175
|
}
|
|
@@ -194,358 +194,192 @@
|
|
|
194
194
|
},
|
|
195
195
|
"definitions": {
|
|
196
196
|
"protocolStep": {
|
|
197
|
-
"
|
|
198
|
-
"description": "A single protocol step",
|
|
197
|
+
"description": "A single protocol step: an exchange, a chunked read, or a chunked write",
|
|
199
198
|
"oneOf": [
|
|
200
199
|
{
|
|
201
|
-
"
|
|
202
|
-
"required": [
|
|
203
|
-
"sendReceive"
|
|
204
|
-
],
|
|
205
|
-
"properties": {
|
|
206
|
-
"sendReceive": {
|
|
207
|
-
"$ref": "#/definitions/sendReceiveStep"
|
|
208
|
-
}
|
|
209
|
-
}
|
|
200
|
+
"$ref": "#/definitions/readStep"
|
|
210
201
|
},
|
|
211
202
|
{
|
|
212
|
-
"
|
|
213
|
-
"required": [
|
|
214
|
-
"send"
|
|
215
|
-
],
|
|
216
|
-
"properties": {
|
|
217
|
-
"send": {
|
|
218
|
-
"$ref": "#/definitions/sendStep"
|
|
219
|
-
}
|
|
220
|
-
}
|
|
203
|
+
"$ref": "#/definitions/writeStep"
|
|
221
204
|
},
|
|
222
205
|
{
|
|
223
|
-
"
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
206
|
+
"$ref": "#/definitions/exchangeStep"
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
},
|
|
210
|
+
"byteToken": {
|
|
211
|
+
"description": "A send/expect token: a byte, hex string (0x50), ASCII opcode (S), or placeholder ($address)",
|
|
212
|
+
"oneOf": [
|
|
213
|
+
{
|
|
214
|
+
"type": "integer",
|
|
215
|
+
"minimum": 0,
|
|
216
|
+
"maximum": 255
|
|
232
217
|
},
|
|
233
218
|
{
|
|
234
|
-
"type": "
|
|
235
|
-
"
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
219
|
+
"type": "string",
|
|
220
|
+
"minLength": 1
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
},
|
|
224
|
+
"sendData": {
|
|
225
|
+
"type": "array",
|
|
226
|
+
"description": "Bytes and placeholders to send",
|
|
227
|
+
"items": {
|
|
228
|
+
"$ref": "#/definitions/byteToken"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
"expect": {
|
|
232
|
+
"description": "Expected serial reply: exact byte(s), opaque length, or a framed pattern",
|
|
233
|
+
"oneOf": [
|
|
234
|
+
{
|
|
235
|
+
"$ref": "#/definitions/byteToken"
|
|
243
236
|
},
|
|
244
237
|
{
|
|
245
|
-
"type": "
|
|
246
|
-
"
|
|
247
|
-
"
|
|
248
|
-
|
|
249
|
-
"
|
|
250
|
-
"writeSegment": {
|
|
251
|
-
"$ref": "#/definitions/writeSegmentStep"
|
|
252
|
-
}
|
|
253
|
-
}
|
|
238
|
+
"type": "array",
|
|
239
|
+
"items": {
|
|
240
|
+
"$ref": "#/definitions/byteToken"
|
|
241
|
+
},
|
|
242
|
+
"minItems": 1
|
|
254
243
|
},
|
|
255
244
|
{
|
|
256
245
|
"type": "object",
|
|
257
246
|
"required": [
|
|
258
|
-
"
|
|
247
|
+
"bytes"
|
|
259
248
|
],
|
|
249
|
+
"additionalProperties": false,
|
|
260
250
|
"properties": {
|
|
261
|
-
"
|
|
262
|
-
"
|
|
251
|
+
"bytes": {
|
|
252
|
+
"type": "integer",
|
|
253
|
+
"description": "Accept any content of this many bytes",
|
|
254
|
+
"minimum": 1
|
|
263
255
|
}
|
|
264
256
|
}
|
|
265
257
|
}
|
|
266
258
|
]
|
|
267
259
|
},
|
|
268
|
-
"
|
|
260
|
+
"exchangeStep": {
|
|
269
261
|
"type": "object",
|
|
270
|
-
"description": "Send
|
|
271
|
-
"
|
|
272
|
-
|
|
273
|
-
|
|
262
|
+
"description": "Send bytes and/or wait for a reply",
|
|
263
|
+
"anyOf": [
|
|
264
|
+
{
|
|
265
|
+
"required": [
|
|
266
|
+
"send"
|
|
267
|
+
]
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"required": [
|
|
271
|
+
"expect"
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
274
|
],
|
|
275
|
+
"additionalProperties": false,
|
|
275
276
|
"properties": {
|
|
277
|
+
"description": {
|
|
278
|
+
"type": "string",
|
|
279
|
+
"description": "Human-readable description of the step"
|
|
280
|
+
},
|
|
276
281
|
"send": {
|
|
277
282
|
"$ref": "#/definitions/sendData"
|
|
278
283
|
},
|
|
279
|
-
"
|
|
280
|
-
"$ref": "#/definitions/
|
|
284
|
+
"expect": {
|
|
285
|
+
"$ref": "#/definitions/expect"
|
|
281
286
|
},
|
|
282
287
|
"timeout": {
|
|
283
288
|
"type": "integer",
|
|
284
289
|
"description": "Timeout in milliseconds",
|
|
285
290
|
"minimum": 1,
|
|
286
291
|
"default": 5000
|
|
287
|
-
},
|
|
288
|
-
"description": {
|
|
289
|
-
"type": "string",
|
|
290
|
-
"description": "Human-readable description of the step"
|
|
291
292
|
}
|
|
292
293
|
}
|
|
293
294
|
},
|
|
294
|
-
"
|
|
295
|
+
"readStep": {
|
|
295
296
|
"type": "object",
|
|
296
|
-
"description": "
|
|
297
|
+
"description": "Chunked memory read",
|
|
297
298
|
"required": [
|
|
298
|
-
"
|
|
299
|
+
"read"
|
|
299
300
|
],
|
|
301
|
+
"additionalProperties": false,
|
|
300
302
|
"properties": {
|
|
301
|
-
"data": {
|
|
302
|
-
"$ref": "#/definitions/sendData"
|
|
303
|
-
},
|
|
304
303
|
"description": {
|
|
305
304
|
"type": "string",
|
|
306
305
|
"description": "Human-readable description of the step"
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
"receiveStep": {
|
|
311
|
-
"type": "object",
|
|
312
|
-
"description": "Receive data only",
|
|
313
|
-
"required": [
|
|
314
|
-
"type",
|
|
315
|
-
"length"
|
|
316
|
-
],
|
|
317
|
-
"properties": {
|
|
318
|
-
"type": {
|
|
319
|
-
"type": "string",
|
|
320
|
-
"enum": [
|
|
321
|
-
"exact",
|
|
322
|
-
"variable",
|
|
323
|
-
"pattern",
|
|
324
|
-
"any"
|
|
325
|
-
],
|
|
326
|
-
"description": "Type of receive operation"
|
|
327
|
-
},
|
|
328
|
-
"value": {
|
|
329
|
-
"type": "integer",
|
|
330
|
-
"description": "Expected value for exact match",
|
|
331
|
-
"minimum": 0,
|
|
332
|
-
"maximum": 255
|
|
333
|
-
},
|
|
334
|
-
"length": {
|
|
335
|
-
"type": "integer",
|
|
336
|
-
"description": "Expected length in bytes",
|
|
337
|
-
"minimum": 1
|
|
338
306
|
},
|
|
339
|
-
"
|
|
340
|
-
"type": "
|
|
341
|
-
"
|
|
342
|
-
|
|
343
|
-
"
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
307
|
+
"read": {
|
|
308
|
+
"type": "object",
|
|
309
|
+
"required": [
|
|
310
|
+
"segments",
|
|
311
|
+
"send",
|
|
312
|
+
"expect"
|
|
313
|
+
],
|
|
314
|
+
"additionalProperties": false,
|
|
315
|
+
"properties": {
|
|
316
|
+
"segments": {
|
|
317
|
+
"type": "array",
|
|
318
|
+
"description": "Memory segment names to read",
|
|
319
|
+
"items": {
|
|
320
|
+
"type": "string"
|
|
351
321
|
},
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
]
|
|
371
|
-
}
|
|
372
|
-
},
|
|
373
|
-
"description": {
|
|
374
|
-
"type": "string",
|
|
375
|
-
"description": "Human-readable description of the step"
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
},
|
|
379
|
-
"readSegmentStep": {
|
|
380
|
-
"type": "object",
|
|
381
|
-
"description": "Read memory segments",
|
|
382
|
-
"required": [
|
|
383
|
-
"segments",
|
|
384
|
-
"startChunk",
|
|
385
|
-
"endChunk"
|
|
386
|
-
],
|
|
387
|
-
"properties": {
|
|
388
|
-
"segments": {
|
|
389
|
-
"type": "array",
|
|
390
|
-
"description": "List of segment names to read",
|
|
391
|
-
"items": {
|
|
392
|
-
"type": "string"
|
|
322
|
+
"minItems": 1
|
|
323
|
+
},
|
|
324
|
+
"send": {
|
|
325
|
+
"$ref": "#/definitions/sendData"
|
|
326
|
+
},
|
|
327
|
+
"expect": {
|
|
328
|
+
"$ref": "#/definitions/expect"
|
|
329
|
+
},
|
|
330
|
+
"ack": {
|
|
331
|
+
"$ref": "#/definitions/exchangeStep",
|
|
332
|
+
"description": "Optional exchange after each chunk"
|
|
333
|
+
},
|
|
334
|
+
"timeout": {
|
|
335
|
+
"type": "integer",
|
|
336
|
+
"description": "Timeout in milliseconds for each chunk exchange",
|
|
337
|
+
"minimum": 1
|
|
338
|
+
}
|
|
393
339
|
}
|
|
394
|
-
},
|
|
395
|
-
"startChunk": {
|
|
396
|
-
"$ref": "#/definitions/sendReceiveStep",
|
|
397
|
-
"description": "Protocol for starting a chunk read"
|
|
398
|
-
},
|
|
399
|
-
"endChunk": {
|
|
400
|
-
"$ref": "#/definitions/sendReceiveStep",
|
|
401
|
-
"description": "Protocol for ending a chunk read"
|
|
402
|
-
},
|
|
403
|
-
"description": {
|
|
404
|
-
"type": "string",
|
|
405
|
-
"description": "Human-readable description of the step"
|
|
406
340
|
}
|
|
407
341
|
}
|
|
408
342
|
},
|
|
409
|
-
"
|
|
343
|
+
"writeStep": {
|
|
410
344
|
"type": "object",
|
|
411
|
-
"description": "
|
|
345
|
+
"description": "Chunked memory write",
|
|
412
346
|
"required": [
|
|
413
|
-
"
|
|
414
|
-
"send",
|
|
415
|
-
"data",
|
|
416
|
-
"receive"
|
|
347
|
+
"write"
|
|
417
348
|
],
|
|
349
|
+
"additionalProperties": false,
|
|
418
350
|
"properties": {
|
|
419
|
-
"segments": {
|
|
420
|
-
"type": "array",
|
|
421
|
-
"description": "List of segment names to write",
|
|
422
|
-
"items": {
|
|
423
|
-
"type": "string"
|
|
424
|
-
}
|
|
425
|
-
},
|
|
426
|
-
"send": {
|
|
427
|
-
"$ref": "#/definitions/sendData",
|
|
428
|
-
"description": "Data to send for write command"
|
|
429
|
-
},
|
|
430
|
-
"data": {
|
|
431
|
-
"type": "string",
|
|
432
|
-
"description": "Expression for segment data to write"
|
|
433
|
-
},
|
|
434
|
-
"receive": {
|
|
435
|
-
"$ref": "#/definitions/receiveConfig",
|
|
436
|
-
"description": "Expected response for write command"
|
|
437
|
-
},
|
|
438
351
|
"description": {
|
|
439
352
|
"type": "string",
|
|
440
353
|
"description": "Human-readable description of the step"
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
},
|
|
444
|
-
"setVariableStep": {
|
|
445
|
-
"type": "object",
|
|
446
|
-
"description": "Set a variable value",
|
|
447
|
-
"required": [
|
|
448
|
-
"name",
|
|
449
|
-
"value"
|
|
450
|
-
],
|
|
451
|
-
"properties": {
|
|
452
|
-
"name": {
|
|
453
|
-
"type": "string",
|
|
454
|
-
"description": "Variable name"
|
|
455
354
|
},
|
|
456
|
-
"
|
|
457
|
-
"
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
{
|
|
463
|
-
"type": "number",
|
|
464
|
-
"description": "Numeric value"
|
|
465
|
-
}
|
|
466
|
-
],
|
|
467
|
-
"description": "Value to assign to the variable"
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
},
|
|
471
|
-
"sendData": {
|
|
472
|
-
"type": "array",
|
|
473
|
-
"description": "Array of data to send",
|
|
474
|
-
"items": {
|
|
475
|
-
"oneOf": [
|
|
476
|
-
{
|
|
477
|
-
"type": "string",
|
|
478
|
-
"description": "String literal or expression"
|
|
479
|
-
},
|
|
480
|
-
{
|
|
481
|
-
"type": "number",
|
|
482
|
-
"description": "Numeric literal or expression",
|
|
483
|
-
"minimum": 0,
|
|
484
|
-
"maximum": 255
|
|
485
|
-
}
|
|
486
|
-
]
|
|
487
|
-
}
|
|
488
|
-
},
|
|
489
|
-
"receiveConfig": {
|
|
490
|
-
"type": "object",
|
|
491
|
-
"description": "Configuration for receiving data",
|
|
492
|
-
"required": [
|
|
493
|
-
"type"
|
|
494
|
-
],
|
|
495
|
-
"properties": {
|
|
496
|
-
"type": {
|
|
497
|
-
"type": "string",
|
|
498
|
-
"enum": [
|
|
499
|
-
"exact",
|
|
500
|
-
"variable",
|
|
501
|
-
"pattern",
|
|
502
|
-
"any"
|
|
355
|
+
"write": {
|
|
356
|
+
"type": "object",
|
|
357
|
+
"required": [
|
|
358
|
+
"segments",
|
|
359
|
+
"send",
|
|
360
|
+
"expect"
|
|
503
361
|
],
|
|
504
|
-
"
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
},
|
|
512
|
-
"length": {
|
|
513
|
-
"type": "integer",
|
|
514
|
-
"description": "Expected length in bytes",
|
|
515
|
-
"minimum": 1
|
|
516
|
-
},
|
|
517
|
-
"pattern": {
|
|
518
|
-
"type": "array",
|
|
519
|
-
"description": "Pattern for structured responses",
|
|
520
|
-
"items": {
|
|
521
|
-
"oneOf": [
|
|
522
|
-
{
|
|
523
|
-
"type": "string",
|
|
524
|
-
"description": "Literal value (1 byte)"
|
|
525
|
-
},
|
|
526
|
-
{
|
|
527
|
-
"type": "number",
|
|
528
|
-
"description": "Literal value (1 byte)"
|
|
362
|
+
"additionalProperties": false,
|
|
363
|
+
"properties": {
|
|
364
|
+
"segments": {
|
|
365
|
+
"type": "array",
|
|
366
|
+
"description": "Memory segment names to write",
|
|
367
|
+
"items": {
|
|
368
|
+
"type": "string"
|
|
529
369
|
},
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
"description": "Size in bytes (0 for variable length)",
|
|
544
|
-
"minimum": 0
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
]
|
|
370
|
+
"minItems": 1
|
|
371
|
+
},
|
|
372
|
+
"send": {
|
|
373
|
+
"$ref": "#/definitions/sendData"
|
|
374
|
+
},
|
|
375
|
+
"expect": {
|
|
376
|
+
"$ref": "#/definitions/expect"
|
|
377
|
+
},
|
|
378
|
+
"timeout": {
|
|
379
|
+
"type": "integer",
|
|
380
|
+
"description": "Timeout in milliseconds for each chunk exchange",
|
|
381
|
+
"minimum": 1
|
|
382
|
+
}
|
|
549
383
|
}
|
|
550
384
|
}
|
|
551
385
|
}
|