In the world of IoT, “things” don’t always talk to each other.  Getting the Neurio Home Energy Monitor to speak with my front end home automation program, Imperihome proved to be quite the challenge.  Are there ways to solve this issue for everyone?

I’ve chosen a Vera Z-Wave controller and Nest Thermostat, with Nest Protect devices to expand its sensor network.  When complimented with ImperiHome as the front end device, all of these systems work great together, but I wanted a device that could monitor our power consumption, provide analytics, and maybe even alert the thermostat when to enter away mode based on our energy consumption.

ImperiHome
image-546

 Mismatched Data

Both the ImperiHome API and Neurio API documentation provide a great insight into accessing raw data for your applications; both use the standard OAuth 2.0 token system.  However, the first thing I immediately noticed was the different date stamps in use, Imperihome expected the data to arrive with a modified Unix epoch timestamp while Neurio sends data with ISO 8601 timestamps.

Second, Neurio sets a limit on how many API requests you can make in a short period.  Considering the ImperiHome app does not have any cookie functionality built in to store data temporarily between refreshes, thus requiring new tokens every time I quickly ran out of API requests before being locked out temporarily.

Time to spin up PHP and MySQL.

Centralisation

After spinning up a new Apache site and installing an SSL certificate, it was time to write an API server for ImperiHome.  The goal from the beginning was modularity.  I wanted to be able to use other APIs’ of future IoT devices without having to rewrite core components of the API server.

Caching the authorization token and various other device information that doesn’t frequently change, combined with now only having one device making requests instead of each end point, I was able to reduce being locked out of the Neurio API for making too many calls almost entirely.  Also, since the server was on the same local network as the Neurio unit, I was able to get “live” power information without it counting towards my API usage.

Neurio Output

Below is Neurio’s reply when making a request for energy consumption over the LAN.

{
    "sensorId": "[REDACTED]",
    "timestamp": "2017-04-01T20:22:06Z",
    "channels": [
        {
            "type": "PHASE_A_CONSUMPTION",
            "ch": 1,
            "eImp_Ws": 1779105434,
            "eExp_Ws": 499948,
            "p_W": 2687,
            "q_VAR": 373,
            "v_V": 120.494
        },
        {
            "type": "PHASE_B_CONSUMPTION",
            "ch": 2,
            "eImp_Ws": 1757055525,
            "eExp_Ws": 87583,
            "p_W": 2685,
            "q_VAR": 23,
            "v_V": 120.548
        },
        {
            "type": "CONSUMPTION",
            "ch": 3,
            "eImp_Ws": 3535802088,
            "eExp_Ws": 228658,
            "p_W": 5372,
            "q_VAR": 396,
            "v_V": 120.521
        }
    ],
    "cts": [
        {
            "ct": 1,
            "p_W": 2810,
            "q_VAR": 373,
            "v_V": 120.494
        },
        {
            "ct": 2,
            "p_W": 2811,
            "q_VAR": 23,
            "v_V": 120.548
        },
        {
            "ct": 3,
            "p_W": 0,
            "q_VAR": 0,
            "v_V": 0
        },
        {
            "ct": 4,
            "p_W": 0,
            "q_VAR": 0,
            "v_V": 120.494
        }
    ]
}

ImperiHome Input

Neurio Display
image-547
Now we take some of the Neurio data and put it into ImperiHome devices.  The following are the devices advertised to the ImperiHome app by my API server.

{
    "devices": [
        {
            "id": "dev1",
            "name": "Current Consumption",
            "type": "DevElectricity",
            "room": "1",
            "module": "neurio",
            "params": [
                {
                    "key": "Watts",
                    "value": 5385,
                    "unit": "W",
                    "graphable": true
                },
                {
                    "key": "ConsoTotal",
                    "value": 56,
                    "unit": "kWh",
                    "graphable": true
                },
                {
                    "key": "defaultIcon",
                    "value": "https://[REDACTED]/modules/neurio/assets/neurio.logo.png"
                }
            ]
        },
        {
            "id": "dev3",
            "name": "Always On",
            "type": "DevElectricity",
            "room": "1",
            "module": "neurio",
            "params": [
                {
                    "key": "Watts",
                    "value": 209,
                    "unit": "W",
                    "graphable": true
                },
                {
                    "key": "ConsoTotal",
                    "value": 56,
                    "unit": "kWh",
                    "graphable": true
                },
                {
                    "key": "defaultIcon",
                    "value": "https://[REDACTED]/modules/neurio/assets/neurio.logo.png"
                }
            ]
        },
        {
            "id": "dev5",
            "name": "Current Bill",
            "type": "DevGenericSensor",
            "room": "1",
            "module": "neurio",
            "params": [
                {
                    "key": "Value",
                    "value": "$35"
                },
                {
                    "key": "defaultIcon",
                    "value": "https://[REDACTED]/modules/neurio/assets/neurio.logo.png"
                }
            ]
        }
    ]
}

What About The Mismatch?

ImperiHome Charting
image-548
/devices/dev1/Watts/histo/1490906710538/1491079510538

The above is the GET parameters sent from the ImperiHome app encapsulated into an URL string when requesting data points for the chart on the left.  The last two numbers are the start and end date for which it is seeking power usage statistics.  You may notice those are Unix epoch timestamps in milliseconds.  Once converted to ISO 8601 format, they can be passed along to the Neurio API.  The following is an example of two chart points Neurio sends back.

[
    {
        "consumptionPower": 511,
        "consumptionEnergy": 3376751228,
        "generationPower": 0,
        "generationEnergy": 0,
        "netPower": 0,
        "netEnergy": 0,
        "timestamp": "2017-03-30T08:45:00.000Z"
    },
    {
        "consumptionPower": 310,
        "consumptionEnergy": 3378374989,
        "generationPower": 0,
        "generationEnergy": 0,
        "netPower": 0,
        "netEnergy": 0,
        "timestamp": "2017-03-30T09:45:00.000Z"
    }
]

Time Converter
image-549
Now we use my API server to send a correctly formatted list of points back to the app.

{
    "values": [
        {
            "date": 1490863521600,
            "value": 511
        },
        {
            "date": 1490867121600,
            "value": 310
        }
    ]
}

Conclusion

For IoT to be more widespread, it needs to be more affordable.  It’s time to step away from the standard practice of farming out entry-level programming work overseas.  Complete standardization of every device will never be a reality.  Therefore we are going to need people to stitch it all together, at least for the foreseeable future.  Services like IFTTT go a long way to bridge these gaps in communication, but how many different privately owned servers need access to your personal analytics?

During a local tradesperson shortage (circa 2006), the British Columbia public education system pushed the trades as an alternative to more traditional post-secondary education to fight off a housing shortage.  Impossible to say if it worked, but I sure know a lot of successful contracting entrepreneurs that might have otherwise unsuccessfully held out for the bar exam.

A hundred years ago, industrial manufacturing practically wiped out jobs without literacy requirements.  As a result, libraries became more common place to empower the average person with the skills to be productive in society.  It’s time we shift our focus one more time into digital literacy if we want technology to replace everyday tasks at prices the average person can afford; Particularly when the only road block are timestamps.

Leave a Reply

Your email address will not be published. Required fields are marked *