djfinnoy
djfinnoy

Reputation: 595

Processing incoming JSON messages from IoT Hub with Azure Functions

I'm receiving messages from IoT devices through IoT Hub, and storing them in a Cosmos database. Stream Analytics works fine, but I want to use Azure Functions.

I want to process the incoming message slightly before storing it in my Cosmos DB. The raw messages look something like this:

{
    "id": "12345",
    "time": "2019-12-05T07:21:37.000+0000",
    "sensors": [
        {
            "type": "TEMPERATURE",
            "value": 23.30286376953125,
            "unit": "C"
        },
        {
            "type": "HUMIDITY",
            "value": 29.686492919921875,
            "unit": "RH"
        },
        {
            "type": "CELL_ID",
            "value": 56789,
            "unit": ""
        },
        {
            "type": "RSSI_LEVEL",
            "value": -86,
            "unit": "dBm"
        }
    ]
}

What I would like to store in Cosmos should look something like this:

{
    id: "2019-12-05T07:21:37.000+0000",
    {
        "deviceId": "12345",
        "time": "2019-12-05T07:21:37.000+0000",
        "type": "TEMPERATURE",
        "value": "23.30286376953125",
        "unit": "C"
    },
    {
        "deviceId": "12345",
        "time": "2019-12-05T07:21:37.000+0000",
        "type": "HUMIDITY",
        "value": "29.686492919921875",
        "unit": "RH"
    },
    ...
}

The reason I'm setting id to equal time, is because I have not yet figured out how to replicate the Document Id functionality from Azure Stream Analytics. I'm trying to ensure that the writing operation to Cosmos doesn't overwrite existing files.

At the moment, my JavaScript code looks like this (I don't know JavaScript, I'm just adapting code I find on the internet):

module.exports = function (context, IoTHubMessages) {
    context.log(`JavaScript eventhub trigger function called for message array: ${IoTHubMessages}`);

    var payload = "";

    IoTHubMessages.forEach(message => {
        context.log(`Processed message: ${message}`);

        payload += { "id": message.time };
        message.sensors.forEach(observation => {
            if (observation.type != "CELL_ID" && observation.type != "RSSI_LEVEL") {
                payload += {
                    "deviceId": message.id,
                    "time": message.time,
                    "type": observation.type,
                    "value": observation.value,
                    "unit": observation.unit
                };
            };
        });
    });

    context.bindings.outputDocument = payload;
    context.done();
};

Debugging the above code takes a long time because I'm not in control of the IoT device's sample rate. I was wondering if someone could help me get the above code-chunk to produce the desired results.

Upvotes: 0

Views: 230

Answers (1)

Matias Quaranta
Matias Quaranta

Reputation: 15583

{
    id: "2019-12-05T07:21:37.000+0000",
    {
        "deviceId": "12345",
        "time": "2019-12-05T07:21:37.000+0000",
        "type": "TEMPERATURE",
        "value": "23.30286376953125",
        "unit": "C"
    },
    {
        "deviceId": "12345",
        "time": "2019-12-05T07:21:37.000+0000",
        "type": "HUMIDITY",
        "value": "29.686492919921875",
        "unit": "RH"
    },
    ...
}

Is not valid JSON, you are missing the property name for the device information. This could be changed to:

{
    id: "2019-12-05T07:21:37.000+0000",
    "deviceInformation": [
    {
        "deviceId": "12345",
        "time": "2019-12-05T07:21:37.000+0000",
        "type": "TEMPERATURE",
        "value": "23.30286376953125",
        "unit": "C"
    },
    {
        "deviceId": "12345",
        "time": "2019-12-05T07:21:37.000+0000",
        "type": "HUMIDITY",
        "value": "29.686492919921875",
        "unit": "RH"
    },
    ...
    ]
}

As for the code, it might be easier if you create an object instead of concatenating strings, something like:

module.exports = function (context, IoTHubMessages) {
    context.log(`JavaScript eventhub trigger function called for message array: ${IoTHubMessages}`);

    var payload = [];
    IoTHubMessages.forEach(message => {
        context.log(`Processed message: ${message}`);

        var messageToStore  = { id: message.time, deviceInformation: [] };
        message.sensors.forEach(observation => {
            if (observation.type != "CELL_ID" && observation.type != "RSSI_LEVEL") {
                messageToStore.deviceInformation.push({
                    "deviceId": message.id,
                    "time": message.time,
                    "type": observation.type,
                    "value": observation.value,
                    "unit": observation.unit
                });
            };
        });

        payload.push(messageToStore);
    });

    context.bindings.outputDocument = payload;
    context.done();
};

Upvotes: 1

Related Questions