0
# SenML Processing
1
2
SenML (Sensor Markup Language) utilities for IoT data encoding and processing. Handles CBOR encoding/decoding and data transformation for Arduino IoT Cloud communication.
3
4
## Capabilities
5
6
### CBOR Encoding/Decoding
7
8
Core CBOR functionality for SenML message processing. CBOR is directly exported from the Arduino CBOR package.
9
10
```typescript { .api }
11
/** CBOR encoder/decoder from @arduino/cbor-js package */
12
const CBOR: {
13
/** Encode SenML array to CBOR binary format */
14
encode(value: SenML[], numericKeys?: boolean): ArrayBuffer;
15
/** Decode CBOR binary data to SenML array with optional tagger and simpleValue */
16
decode(data: ArrayBuffer, tagger?: (value: SenML) => SenML, simpleValue?: SenML): SenML[];
17
};
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
import { SenML } from "arduino-iot-js";
24
25
// Encode SenML to CBOR
26
const senmlData: SenML.SenML[] = [{
27
n: "temperature",
28
v: 25.5,
29
t: Date.now()
30
}];
31
32
const cborBuffer = SenML.CBOR.encode(senmlData);
33
console.log("CBOR encoded:", cborBuffer);
34
35
// Decode CBOR back to SenML
36
const decodedData = SenML.CBOR.decode(cborBuffer);
37
console.log("Decoded SenML:", decodedData);
38
39
// Use numeric keys for compact encoding
40
const compactBuffer = SenML.CBOR.encode(senmlData, true);
41
```
42
43
### SenML Data Parsing
44
45
Convert property values to SenML format for transmission.
46
47
```typescript { .api }
48
/**
49
* Parse property value to SenML format
50
* @param name - Property name
51
* @param value - Property value (string, number, boolean, or object)
52
* @param timestamp - Timestamp for the value
53
* @param useCloudProtocolV2 - Use cloud protocol v2 format
54
* @param deviceId - Device identifier
55
* @returns SenML record or array of records
56
* @throws Error if timestamp is not integer or name is invalid
57
*/
58
function parse(
59
name: string,
60
value: CloudMessageValue,
61
timestamp: number,
62
useCloudProtocolV2: boolean,
63
deviceId: string
64
): SenML | SenML[];
65
```
66
67
**Usage Examples:**
68
69
```typescript
70
import { SenML, type CloudMessageValue } from "arduino-iot-js";
71
72
// Parse simple values
73
const tempSenML = SenML.parse("temperature", 25.5, Date.now(), true, "device-123");
74
console.log("Temperature SenML:", tempSenML);
75
76
const statusSenML = SenML.parse("status", "active", Date.now(), true, "device-123");
77
console.log("Status SenML:", statusSenML);
78
79
const enabledSenML = SenML.parse("enabled", true, Date.now(), true, "device-123");
80
console.log("Enabled SenML:", enabledSenML);
81
82
// Parse object values (creates multiple SenML records)
83
const sensorData = {
84
temperature: 25.5,
85
humidity: 60,
86
pressure: 1013.25
87
};
88
89
const objectSenML = SenML.parse("sensors", sensorData, Date.now(), true, "device-123");
90
console.log("Object SenML:", objectSenML);
91
// Results in multiple SenML records: sensors:temperature, sensors:humidity, sensors:pressure
92
```
93
94
### SenML Data Formatting
95
96
Format individual values as SenML records.
97
98
```typescript { .api }
99
/**
100
* Format a single value as SenML record
101
* @param value - The value to format
102
* @param name - Property name
103
* @param timestamp - Timestamp (-1 to omit)
104
* @param deviceId - Device identifier
105
* @returns SenML record
106
*/
107
function format(
108
value: CloudMessageValue,
109
name: string,
110
timestamp: number,
111
deviceId: string
112
): SenML;
113
```
114
115
**Usage Examples:**
116
117
```typescript
118
import { SenML } from "arduino-iot-js";
119
120
// Format individual values
121
const tempRecord = SenML.format(25.5, "temperature", Date.now(), "device-123");
122
const humidityRecord = SenML.format(60, "humidity", -1, null); // No timestamp, no device ID
123
124
console.log("Temperature record:", tempRecord);
125
// Output: { bt: 1694123456789, n: "temperature", v: 25.5, bn: "urn:uuid:device-123" }
126
127
console.log("Humidity record:", humidityRecord);
128
// Output: { n: "humidity", v: 60 }
129
```
130
131
### SenML String Encoding
132
133
Convert SenML arrays to base64 encoded strings.
134
135
```typescript { .api }
136
/**
137
* Convert SenML array to base64 encoded CBOR string
138
* @param value - SenML array to encode
139
* @param numericKeys - Use numeric keys for compact encoding
140
* @returns Base64 encoded string
141
*/
142
function toString(value: SenML[], numericKeys?: boolean): string;
143
```
144
145
**Usage Examples:**
146
147
```typescript
148
import { SenML } from "arduino-iot-js";
149
150
const senmlData: SenML[] = [
151
{ n: "temperature", v: 25.5, t: Date.now() },
152
{ n: "humidity", v: 60, t: Date.now() }
153
];
154
155
// Convert to base64 string
156
const base64String = SenML.toString(senmlData);
157
console.log("Base64 encoded:", base64String);
158
159
// Use numeric keys for more compact encoding
160
const compactString = SenML.toString(senmlData, true);
161
console.log("Compact base64:", compactString);
162
```
163
164
### Cloud Protocol V2 Conversion
165
166
Convert SenML to Cloud Protocol V2 format.
167
168
```typescript { .api }
169
/**
170
* Convert SenML record to Cloud Protocol V2 format (numeric keys)
171
* @param cborValue - SenML record to convert
172
* @returns SenML record with numeric keys
173
*/
174
function toCloudProtocolV2(cborValue: SenML): SenML;
175
```
176
177
**Usage Examples:**
178
179
```typescript
180
import { SenML } from "arduino-iot-js";
181
182
const originalSenML: SenML = {
183
bn: "urn:uuid:device-123",
184
n: "temperature",
185
v: 25.5,
186
t: Date.now()
187
};
188
189
const v2SenML = SenML.toCloudProtocolV2(originalSenML);
190
console.log("V2 format:", v2SenML);
191
// Output uses numeric keys: { -2: "urn:uuid:device-123", 0: "temperature", 2: 25.5, 6: 1694123456789 }
192
```
193
194
### Value and Name Extraction
195
196
Extract values and names from SenML records or string arrays.
197
198
```typescript { .api }
199
/**
200
* Extract value from SenML record or string array
201
* @param message - SenML record or string array
202
* @returns The value (from v, vs, or vb fields)
203
*/
204
function valueFrom(message: SenML | string[]): CloudMessageValue;
205
206
/**
207
* Extract name from SenML record or string array
208
* @param property - SenML record or string array
209
* @returns The property name
210
*/
211
function nameFrom(property: SenML | string[]): string;
212
213
/**
214
* Type guard to check if message is SenML record
215
* @param message - Message to check
216
* @returns True if message is SenML record
217
*/
218
function isPropertyValue(message: SenML | string[]): message is SenML;
219
220
/**
221
* Check if value is null or undefined
222
* @param v - Value to check
223
* @returns True if value is null or undefined
224
*/
225
function isNil<T>(v: T): boolean;
226
227
/**
228
* Take the first non-nil value from provided values
229
* @param values - Values to check
230
* @returns First non-nil value
231
*/
232
function takeFrom(...values: CloudMessageValue[]): CloudMessageValue;
233
```
234
235
**Usage Examples:**
236
237
```typescript
238
import { SenML } from "arduino-iot-js";
239
240
// Extract from SenML record
241
const senmlRecord: SenML = { n: "temperature", v: 25.5 };
242
const value = SenML.valueFrom(senmlRecord);
243
const name = SenML.nameFrom(senmlRecord);
244
245
console.log(`${name}: ${value}`); // "temperature: 25.5"
246
247
// Extract from string array format
248
const stringArray = ["temperature", "unit", 25.5];
249
const arrayValue = SenML.valueFrom(stringArray);
250
const arrayName = SenML.nameFrom(stringArray);
251
252
console.log(`${arrayName}: ${arrayValue}`); // "temperature: 25.5"
253
254
// Type checking
255
if (SenML.isPropertyValue(senmlRecord)) {
256
console.log("This is a SenML record");
257
console.log("Name field:", senmlRecord.n);
258
}
259
```
260
261
### Utility Functions
262
263
Helper functions for SenML processing.
264
265
```typescript { .api }
266
/**
267
* Check if value is null or undefined
268
* @param v - Value to check
269
* @returns True if value is nil
270
*/
271
function isNil<T>(v: T): boolean;
272
273
/**
274
* Return first non-nil value from arguments
275
* @param values - Values to check
276
* @returns First non-nil value
277
*/
278
function takeFrom(...values: CloudMessageValue[]): CloudMessageValue;
279
```
280
281
**Usage Examples:**
282
283
```typescript
284
import { SenML } from "arduino-iot-js";
285
286
// Check for nil values
287
const temperature = undefined;
288
if (SenML.isNil(temperature)) {
289
console.log("Temperature value is missing");
290
}
291
292
// Take first valid value
293
const sensorValue = SenML.takeFrom(undefined, null, 25.5, 30.0);
294
console.log("Sensor value:", sensorValue); // 25.5
295
```
296
297
## SenML Type Definitions
298
299
```typescript { .api }
300
interface SenML {
301
/** Base name for this record */
302
bn?: string;
303
/** Base time for this record */
304
bt?: number;
305
/** Base unit for this record */
306
bu?: string;
307
/** Base value for this record */
308
bv?: number;
309
/** Base sum for this record */
310
bs?: number;
311
/** Base version for this record */
312
bver?: number;
313
/** Name of this sensor */
314
n?: string;
315
/** Unit of this sensor reading */
316
u?: string;
317
/** Numeric value */
318
v?: number;
319
/** String value */
320
vs?: string;
321
/** Boolean value */
322
vb?: boolean;
323
/** Data value (blob) */
324
vd?: string;
325
/** Sum value */
326
s?: number;
327
/** Time when this reading was taken */
328
t?: number;
329
/** Update time for this reading */
330
ut?: number;
331
/** Allow additional properties */
332
[key: string]: any;
333
}
334
```
335
336
## Advanced Usage
337
338
### Custom SenML Processing
339
340
```typescript
341
import { SenML, type CloudMessageValue } from "arduino-iot-js";
342
343
// Process complex sensor data
344
function processSensorReading(
345
deviceId: string,
346
readings: Record<string, any>
347
): string {
348
const timestamp = Date.now();
349
const senmlRecords: SenML[] = [];
350
351
Object.entries(readings).forEach(([sensor, value]) => {
352
const senmlRecord = SenML.format(value, sensor, timestamp, deviceId);
353
const v2Record = SenML.toCloudProtocolV2(senmlRecord);
354
senmlRecords.push(v2Record);
355
});
356
357
return SenML.toString(senmlRecords, true);
358
}
359
360
// Usage
361
const sensorData = {
362
temperature: 25.5,
363
humidity: 60,
364
pressure: 1013.25,
365
light: 850
366
};
367
368
const encodedData = processSensorReading("device-123", sensorData);
369
console.log("Encoded sensor data:", encodedData);
370
```
371
372
### Message Parsing Pipeline
373
374
```typescript
375
import { SenML } from "arduino-iot-js";
376
377
// Parse incoming CBOR messages
378
function parseIncomingMessage(buffer: ArrayBuffer): Array<{name: string, value: any}> {
379
try {
380
const senmlArray = SenML.CBOR.decode(buffer);
381
382
return senmlArray.map(record => ({
383
name: SenML.nameFrom(record),
384
value: SenML.valueFrom(record)
385
}));
386
} catch (error) {
387
console.error("Failed to parse CBOR message:", error);
388
return [];
389
}
390
}
391
392
// Create outgoing messages
393
function createMessage(
394
propertyName: string,
395
value: CloudMessageValue,
396
deviceId: string
397
): ArrayBuffer {
398
const senmlData = SenML.parse(propertyName, value, Date.now(), true, deviceId);
399
const senmlArray = Array.isArray(senmlData) ? senmlData : [senmlData];
400
401
return SenML.CBOR.encode(senmlArray, true);
402
}
403
```