or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

connection-management.mdindex.mdproperty-operations.mdsenml-processing.md

senml-processing.mddocs/

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

```