JavaScript/TypeScript library for connecting to the Arduino IoT Cloud MQTT broker with support for both browser and Node.js applications.
SenML (Sensor Markup Language) utilities for IoT data encoding and processing. Handles CBOR encoding/decoding and data transformation for Arduino IoT Cloud communication.
Core CBOR functionality for SenML message processing. CBOR is directly exported from the Arduino CBOR package.
/** CBOR encoder/decoder from @arduino/cbor-js package */
const CBOR: {
/** Encode SenML array to CBOR binary format */
encode(value: SenML[], numericKeys?: boolean): ArrayBuffer;
/** Decode CBOR binary data to SenML array with optional tagger and simpleValue */
decode(data: ArrayBuffer, tagger?: (value: SenML) => SenML, simpleValue?: SenML): SenML[];
};Usage Examples:
import { SenML } from "arduino-iot-js";
// Encode SenML to CBOR
const senmlData: SenML.SenML[] = [{
n: "temperature",
v: 25.5,
t: Date.now()
}];
const cborBuffer = SenML.CBOR.encode(senmlData);
console.log("CBOR encoded:", cborBuffer);
// Decode CBOR back to SenML
const decodedData = SenML.CBOR.decode(cborBuffer);
console.log("Decoded SenML:", decodedData);
// Use numeric keys for compact encoding
const compactBuffer = SenML.CBOR.encode(senmlData, true);Convert property values to SenML format for transmission.
/**
* Parse property value to SenML format
* @param name - Property name
* @param value - Property value (string, number, boolean, or object)
* @param timestamp - Timestamp for the value
* @param useCloudProtocolV2 - Use cloud protocol v2 format
* @param deviceId - Device identifier
* @returns SenML record or array of records
* @throws Error if timestamp is not integer or name is invalid
*/
function parse(
name: string,
value: CloudMessageValue,
timestamp: number,
useCloudProtocolV2: boolean,
deviceId: string
): SenML | SenML[];Usage Examples:
import { SenML, type CloudMessageValue } from "arduino-iot-js";
// Parse simple values
const tempSenML = SenML.parse("temperature", 25.5, Date.now(), true, "device-123");
console.log("Temperature SenML:", tempSenML);
const statusSenML = SenML.parse("status", "active", Date.now(), true, "device-123");
console.log("Status SenML:", statusSenML);
const enabledSenML = SenML.parse("enabled", true, Date.now(), true, "device-123");
console.log("Enabled SenML:", enabledSenML);
// Parse object values (creates multiple SenML records)
const sensorData = {
temperature: 25.5,
humidity: 60,
pressure: 1013.25
};
const objectSenML = SenML.parse("sensors", sensorData, Date.now(), true, "device-123");
console.log("Object SenML:", objectSenML);
// Results in multiple SenML records: sensors:temperature, sensors:humidity, sensors:pressureFormat individual values as SenML records.
/**
* Format a single value as SenML record
* @param value - The value to format
* @param name - Property name
* @param timestamp - Timestamp (-1 to omit)
* @param deviceId - Device identifier
* @returns SenML record
*/
function format(
value: CloudMessageValue,
name: string,
timestamp: number,
deviceId: string
): SenML;Usage Examples:
import { SenML } from "arduino-iot-js";
// Format individual values
const tempRecord = SenML.format(25.5, "temperature", Date.now(), "device-123");
const humidityRecord = SenML.format(60, "humidity", -1, null); // No timestamp, no device ID
console.log("Temperature record:", tempRecord);
// Output: { bt: 1694123456789, n: "temperature", v: 25.5, bn: "urn:uuid:device-123" }
console.log("Humidity record:", humidityRecord);
// Output: { n: "humidity", v: 60 }Convert SenML arrays to base64 encoded strings.
/**
* Convert SenML array to base64 encoded CBOR string
* @param value - SenML array to encode
* @param numericKeys - Use numeric keys for compact encoding
* @returns Base64 encoded string
*/
function toString(value: SenML[], numericKeys?: boolean): string;Usage Examples:
import { SenML } from "arduino-iot-js";
const senmlData: SenML[] = [
{ n: "temperature", v: 25.5, t: Date.now() },
{ n: "humidity", v: 60, t: Date.now() }
];
// Convert to base64 string
const base64String = SenML.toString(senmlData);
console.log("Base64 encoded:", base64String);
// Use numeric keys for more compact encoding
const compactString = SenML.toString(senmlData, true);
console.log("Compact base64:", compactString);Convert SenML to Cloud Protocol V2 format.
/**
* Convert SenML record to Cloud Protocol V2 format (numeric keys)
* @param cborValue - SenML record to convert
* @returns SenML record with numeric keys
*/
function toCloudProtocolV2(cborValue: SenML): SenML;Usage Examples:
import { SenML } from "arduino-iot-js";
const originalSenML: SenML = {
bn: "urn:uuid:device-123",
n: "temperature",
v: 25.5,
t: Date.now()
};
const v2SenML = SenML.toCloudProtocolV2(originalSenML);
console.log("V2 format:", v2SenML);
// Output uses numeric keys: { -2: "urn:uuid:device-123", 0: "temperature", 2: 25.5, 6: 1694123456789 }Extract values and names from SenML records or string arrays.
/**
* Extract value from SenML record or string array
* @param message - SenML record or string array
* @returns The value (from v, vs, or vb fields)
*/
function valueFrom(message: SenML | string[]): CloudMessageValue;
/**
* Extract name from SenML record or string array
* @param property - SenML record or string array
* @returns The property name
*/
function nameFrom(property: SenML | string[]): string;
/**
* Type guard to check if message is SenML record
* @param message - Message to check
* @returns True if message is SenML record
*/
function isPropertyValue(message: SenML | string[]): message is SenML;
/**
* Check if value is null or undefined
* @param v - Value to check
* @returns True if value is null or undefined
*/
function isNil<T>(v: T): boolean;
/**
* Take the first non-nil value from provided values
* @param values - Values to check
* @returns First non-nil value
*/
function takeFrom(...values: CloudMessageValue[]): CloudMessageValue;Usage Examples:
import { SenML } from "arduino-iot-js";
// Extract from SenML record
const senmlRecord: SenML = { n: "temperature", v: 25.5 };
const value = SenML.valueFrom(senmlRecord);
const name = SenML.nameFrom(senmlRecord);
console.log(`${name}: ${value}`); // "temperature: 25.5"
// Extract from string array format
const stringArray = ["temperature", "unit", 25.5];
const arrayValue = SenML.valueFrom(stringArray);
const arrayName = SenML.nameFrom(stringArray);
console.log(`${arrayName}: ${arrayValue}`); // "temperature: 25.5"
// Type checking
if (SenML.isPropertyValue(senmlRecord)) {
console.log("This is a SenML record");
console.log("Name field:", senmlRecord.n);
}Helper functions for SenML processing.
/**
* Check if value is null or undefined
* @param v - Value to check
* @returns True if value is nil
*/
function isNil<T>(v: T): boolean;
/**
* Return first non-nil value from arguments
* @param values - Values to check
* @returns First non-nil value
*/
function takeFrom(...values: CloudMessageValue[]): CloudMessageValue;Usage Examples:
import { SenML } from "arduino-iot-js";
// Check for nil values
const temperature = undefined;
if (SenML.isNil(temperature)) {
console.log("Temperature value is missing");
}
// Take first valid value
const sensorValue = SenML.takeFrom(undefined, null, 25.5, 30.0);
console.log("Sensor value:", sensorValue); // 25.5interface SenML {
/** Base name for this record */
bn?: string;
/** Base time for this record */
bt?: number;
/** Base unit for this record */
bu?: string;
/** Base value for this record */
bv?: number;
/** Base sum for this record */
bs?: number;
/** Base version for this record */
bver?: number;
/** Name of this sensor */
n?: string;
/** Unit of this sensor reading */
u?: string;
/** Numeric value */
v?: number;
/** String value */
vs?: string;
/** Boolean value */
vb?: boolean;
/** Data value (blob) */
vd?: string;
/** Sum value */
s?: number;
/** Time when this reading was taken */
t?: number;
/** Update time for this reading */
ut?: number;
/** Allow additional properties */
[key: string]: any;
}import { SenML, type CloudMessageValue } from "arduino-iot-js";
// Process complex sensor data
function processSensorReading(
deviceId: string,
readings: Record<string, any>
): string {
const timestamp = Date.now();
const senmlRecords: SenML[] = [];
Object.entries(readings).forEach(([sensor, value]) => {
const senmlRecord = SenML.format(value, sensor, timestamp, deviceId);
const v2Record = SenML.toCloudProtocolV2(senmlRecord);
senmlRecords.push(v2Record);
});
return SenML.toString(senmlRecords, true);
}
// Usage
const sensorData = {
temperature: 25.5,
humidity: 60,
pressure: 1013.25,
light: 850
};
const encodedData = processSensorReading("device-123", sensorData);
console.log("Encoded sensor data:", encodedData);import { SenML } from "arduino-iot-js";
// Parse incoming CBOR messages
function parseIncomingMessage(buffer: ArrayBuffer): Array<{name: string, value: any}> {
try {
const senmlArray = SenML.CBOR.decode(buffer);
return senmlArray.map(record => ({
name: SenML.nameFrom(record),
value: SenML.valueFrom(record)
}));
} catch (error) {
console.error("Failed to parse CBOR message:", error);
return [];
}
}
// Create outgoing messages
function createMessage(
propertyName: string,
value: CloudMessageValue,
deviceId: string
): ArrayBuffer {
const senmlData = SenML.parse(propertyName, value, Date.now(), true, deviceId);
const senmlArray = Array.isArray(senmlData) ? senmlData : [senmlData];
return SenML.CBOR.encode(senmlArray, true);
}Install with Tessl CLI
npx tessl i tessl/npm-arduino-iot-js