Define a Device model #
We will now define a new Device model with the associated Decoder in order to receive raw payloads.
The device is a temperature and pressure sensor, we will use the standard temperature measurement but we need to define a custom co2 measurement.
Define a custom measurement #
To define a measure, it is necessary to declare an object indicating to the storage engine the names and types of the different values of the measure.
It is also advisable to create a type for this measure in order to take advantage of the strong typing in the rest of the project.
In this example, we will declare a CO2 measurement that will contain its value in a co2
property of type float
:
import { MeasureDefinition } from "@kuzzleio/iot-backend";
export type CO2Measurement = {
co2: number,
};
export const co2MeasureDefinition: MeasureDefinition = {
valueMappings: {
co2: { type: "float" },
},
};
Then the measure should be registered on the framework:
import { DeviceManagePlugin } from "kuzzle-device-manager";
import { co2MeasureDefinition } from "./CO2Measurement";
const deviceManager = app.plugin.get < DeviceManagerPlugin > "device-manager";
deviceManager.models.registerMeasure("co2", co2MeasureDefinition);
Decoder #
First, you need to create a Decoder that will transform the raw payload into standardized measures.
For this, you need to extends the Decoder
class and
- define measure decoded by the Decoder
- implements the
decode
method
The decode
method take 2 parameters:
decodedPayload
utility class to extract the measurespayload
the raw payload as a JSONObject
Each measure should be extracted with the following information:
- device reference which acts as device unique identifier (e.g.
ABC123
) - measure type (e.g.
temperature
) - measure name (e.g.
temperature
) - measure timestamp of the measurement (e.g.
1675959435515
) - measure values (e.g.
21.2
)
An example of the complete implementation can be found in the apps/api/lib/modules/devices/
directory
In this example, we will implements a Decoder to decode the following raw payload:
{
"deviceEUI": "ABC123",
"temp": 21.2
}
Our Decoder will define two measures, temperature
and co2
.
import {
DecodedPayload,
Decoder,
HumidityMeasurement,
TemperatureMeasurement,
} from "@kuzzleio/iot-backend";
import { JSONObject } from "kuzzle";
import { has } from "lodash";
import { CO2Measurement } from "./CO2Measurement";
export class ExampleDecoder extends Decoder {
/**
* Declare the measure extracted by this Decoder
*/
public measures = [
{ name: "temperature", type: "temperature" },
{ name: "co2", type: "co2" },
] as const;
constructor() {
super();
/**
* Register a custom mappings for the "payloads" collection
*/
this.payloadsMappings = {
deviceId: { type: "keyword" },
};
}
/**
* Ensure the payload contains the correct values
*/
async validate(payload: JSONObject): Promise<boolean> {
// This throw an exception if the property "deviceId" is not present
this.ensureProperties(payload, ["deviceId"]);
const properties = ["temperature", "co2"];
return properties.every((property) => has(payload, property));
}
async decode(
decodedPayload: DecodedPayload<ExampleDecoder>,
payload: JSONObject
): Promise<DecodedPayload<Decoder>> {
const deviceId = payload.deviceId;
const measuredAt = payload.timestamp || Date.now();
decodedPayload.addMeasurement<TemperatureMeasurement>(
deviceId, // device reference
"temperature", // measure name
{
measuredAt, // timestamp of the measure
type: "temperature", // measure type
values: {
temperature: payload.temperature,
},
}
);
decodedPayload.addMeasurement<CO2Measurement>(deviceId, "co2", {
measuredAt,
type: "co2",
values: {
co2: payload.co2,
},
});
return decodedPayload;
}
}
Then we can define a new Device model associated with the Decoder we just wrote.
For this, we will use the Device Manager plugin:
import { DeviceManagePlugin } from "kuzzle-device-manager";
const deviceManager = app.plugin.get < DeviceManagerPlugin > "device-manager";
deviceManager.models.registerDevice("Example", {
decoder: new ExampleDecoder(),
});
Once registered, the new device model automatically exposes a HTTP route to send raw payloads:
curl -X POST \
-H "Content-Type: application/json" \
"http://localhost:7512/_/devicemanager/payload/example"\
--data '{"deviceId": "ABC123", "co2": 123, "temperature": 21.2 }'
You can now open the Admin > Orphans
view of the IoT Console and see you newly created device.
By default, the IoT Platform automatically create new devices when a payload is received for the first time.