Script for API for energy consumption smart meter.

Hi Symcon experts,

First of all thanks for a great forum, even if I have to use Google Translate to understand anything :slight_smile:

I am a new user of the Symcon software and have next to no programming experience so it has been a steep learning curve.
Mostly I have copy/pasted PHP scripts for my setup from the forum and other places.

I would really appriciate some help with integrating my automatic smart meter into Symcon.
In Norway we last year got smart home energy meters with automatic reading and a HAN interface for extracting data.
I have selected the Norwegian company Tibber for getting the data to the cloud since they supplied an API. Tibber Developer
It is possible to get all energy consumption data, energy prices etc.

I have found a basic PHP script for sending queries to the API but I do not know how I can write the values I get into variables for use in Symcon.
Could anyone please help with this?

This script is just for getting the hourly energy price:

$json = '{"query":"{viewer {homes {currentSubscription {priceInfo {current {total energy tax startsAt }}}}}}"}';

# Create a connection
$ch = curl_init('https://api.tibber.com/v1-beta/gql');
# Setting our options
curl_setopt($ch, CURLOPT_URL, 'https://api.tibber.com/v1-beta/gql');
curl_setopt($ch, CURLOPT_HTTPHEADER, 
   array('Content-Type: application/json',  
   'Authorization: Bearer d1007ead2dc84a2b82f0de19451c5fb22112f7ae11d19bf2bedb224a003ff74a')); // Demo token
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

# Get the response
$response = curl_exec($ch);
curl_close($ch);

echo '<pre>';
echo $json.'<br>';
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
?>

Best regards
Andreas

If you send a curl request to Tibber what is the output of


var_export($response);

You get data in JSON. First you have to create the variable in Symcon for the value you want to save.
After that you can get the data as described How can I … 2.0.

If you post the content here from $response (var_export) you can get help, if you have problems to read out individual values.

For this example, you get the values with


$data = json_decode($response);

$current = $data->data->viewer->homes[0];

$total = $current->currentSubscription->priceInfo->current->total;
var_dump($total);

$energy = $current->currentSubscription->priceInfo->current->energy;
var_dump($energy);

$tax = $current->currentSubscription->priceInfo->current->tax;
var_dump($tax);

Then write the values to a variable with SetValue.

Thank you so much for your quick reply.
That worked perfect :slight_smile:

Later this week I will get access to my full energy consumption with value updates every 2 seconds as well.
I might come back and ask a few more questions then.

Thanks again.

Hi again,

I do now have access to a „subscription“ with live consumption from the Tibber API over a websocket.
The address apparently is: wss://api.tibber.com/v1-beta/gql/subscriptions

This is from the Tibber developer page:

[i]"
While queries and mutations are typically handled over HTTP some data are better suited to handled as streams over a persistent connection (web socket). Subscriptions follows the same semantics as queries and mutations - the shape of what is returned/sent from the server is determined by the client when invoking the api:

subscription{
liveMeasurement(homeId:„195f75d5-9d10-472b-b78b-3976904a01fb“){
timestamp
power
accumulatedConsumption
accumulatedCost
currency
minPower
averagePower
maxPower
}
}

"[/i]

Could anyone explain how I can set that up? Do I use the Webhook module? Also how the script should look for getting live data from the API?

This is not so easy because Websockets are not natively supported by Symcon at the moment, so you have to use a PHP Module like WebSocketClient for IP-Symcon.

No, Webhook would only work if the device would send activity data to an URL.

This depends on what the data exactly looks like. Perhaps you can try first to set up a web socket and then see what data is sent to Symcon. If you know what data is received in Symcon then you could get help in what the script should look like.

Another possibility would be to get the data from the device via a timer and a curl request (see above). It depends on if you need the data in realtime or if it is enough to get the data in a defined interval…

I don’t quite see where in the Websocket client a script goes?
In the Tibber API developer webpage there is an API explorer where queries can be made.
The „live subscription“ is entered like this:

subscription{
  liveMeasurement(homeId:"195f75d5-9d10-472b-b78b-397690******"){
    timestamp
    power
    accumulatedConsumption
    accumulatedCost
    currency
    minPower
    averagePower
    maxPower
  }
}

And the data received looks like this:

{
  "liveMeasurement": {
    "timestamp": "2019-06-25T22:24:00.000+02:00",
    "power": 6882,
    "accumulatedConsumption": 38.304167,
    "accumulatedCost": 14.621026,
    "currency": "NOK",
    "minPower": 313,
    "averagePower": 1709.8,
    "maxPower": 11329
  }
}

The Client seems to connect OK as I see in the debug that I receive data in HEX format.
But I am not sure how I use this client correctly.

Hi,

I still have not been able to use the websocket client to read live data from the server.
Have anyone else used this module before and could assist in making a script to use it?
Or have a demo script that could point me in the right direction?

The module is setup to the server but keeps losing connection once a minute.
Will Symcon come out with native support for Websocket in the near future?

Br
Andreas

Good morning people,

I’ll give my Websocket issue another try.
I still struggle to setup my connection towards the Tibber API Tibber Developer.

When opening the websocket it keeps reconnecting all the time creating fault messages.
Could anyone help and see my logs what could be wrong? I have attached the debug from the websocket and the client socket and also message log.

Just as a side note, I had never even heard of a websocket before starting this so please in small words :slight_smile:

Message log.txt (1.35 KB)

ClientSocket.txt (136 KB)

Websocket.txt (195 KB)

Hi,

I recently got Pulse device from Tibber.
Hope there is a solution to get real time data over at Symcon.
Have you found a solution?

Best regards
Håvard

Hi and happy new year,

No I have not been able to figure out the websocket yet. I will just try to buy some „premium support“ at Symcon and see if they can help me setting up a websocket.

As it is now I’m getting the current last hour energy price with this code and writing it to a variable:


$json = '{"query":"{viewer {homes {currentSubscription {priceInfo {current {total energy tax startsAt }}}}}}"}';

# Create a connection
$ch = curl_init('https://api.tibber.com/v1-beta/gql');
# Setting our options
curl_setopt($ch, CURLOPT_URL, 'https://api.tibber.com/v1-beta/gql');
curl_setopt($ch, CURLOPT_HTTPHEADER, 
   array('Content-Type: application/json',  
   'Authorization: Bearer 41121d0cdb9d4d2592c2c0c3395add82166e9e3a160d6abf0b70cd8******')); 
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

# Get the response
$response = curl_exec($ch);
curl_close($ch);

//Decoding of the JSON data
$data = json_decode($response); 
$current = $data->data->viewer->homes[0]; 

$total = $current->currentSubscription->priceInfo->current->total; 
//var_dump($total); 

//Convert KR to Øre
$pris = floatval($total) * floatval(100);

//Write Energy price Incl Tax to Float 
setvalue  (35230, $pris) ;

What I want to try now is to get the whole 24 hour day price in one query and get this into a variable for a nice graph so I can adjust my power consumption after this.
According to Tibber I just change my query by changing „current“ to „today“:

$json = '{"query":"{viewer {homes {currentSubscription {priceInfo {today {total energy tax startsAt }}}}}}"}';

But I am not able to get the data in the same way in the code.
When I try it in the Tibber API explorer I get:

{
  "data": {
    "viewer": {
      "homes": [
        {
          "currentSubscription": {
            "priceInfo": {
              "today": [
                {
                  "total": 0.2319,
                  "energy": 0.22,
                  "tax": 0.0119,
                  "startsAt": "2020-01-14T00:00:00+01:00"
                },
                {
                  "total": 0.1957,
                  "energy": 0.1838,
                  "tax": 0.0119,
                  "startsAt": "2020-01-14T01:00:00+01:00"
                },
                {
                  "total": 0.1941,
                  "energy": 0.1822,
                  "tax": 0.0119,
                  "startsAt": "2020-01-14T02:00:00+01:00"
                },

Here I get the price for every hour.
I see there is an [ before and after all the data. Is this an array?

Could anyone please assist in how I can change my script to be able to decode the data and write it to a variable so I can display the whole 24Hour energy price?

Yes this is an array you get multiple values per day.


$prices_today = $data->data->viewer->homes[0]->currentSubscription->priceInfo->today;
foreach($prices_today as $price)
{
    var_dump($price);
}

What do you want to do exactly, there are several values, do you want a special value e.g. looking for the lowest or do you want to write each value individually in a separate variable?
how to write the 24 values in a single variable so that the archive also records them over the last 24 hours, I am questioned myself, maybe this can answer IP-Symcon or someone else who has done this before.

Thank you Fonzo.
Now I believe I can write all 24 values to its own variable :slight_smile:

But then the problem is exactly as you mention, how can I write these 24 variables to one with different timestamps to generate a 24 hour trend over the energy price?

If you want to write this to one variable you have to add this to the archive. So you need three variables, total, energy, tax and activate archive setting. Then you need a script that runs exactly every 24 hours with a cyclic event in IP-Symcon.

The skript should be as followed:


$json = '{"query":"{viewer {homes {currentSubscription {priceInfo {today {total energy tax startsAt }}}}}}"}'; 
$response = SendCommand($json);
function SendCommand($json)
{
    # Create a connection
$ch = curl_init('https://api.tibber.com/v1-beta/gql');
# Setting our options
curl_setopt($ch, CURLOPT_URL, 'https://api.tibber.com/v1-beta/gql');
curl_setopt($ch, CURLOPT_HTTPHEADER, 
   array('Content-Type: application/json',  
   'Authorization: Bearer d1007ead2dc84a2b82f0de19451c5fb22112f7ae11d19bf2bedb224a003ff74a')); // Demo token
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

# Get the response
$response = curl_exec($ch);
curl_close($ch);
    return $response;
}

$data = json_decode($response);
$prices_today = $data->data->viewer->homes[0]->currentSubscription->priceInfo->today;

    $total_arr = [];
    $energy_arr = [];
    $tax_arr = [];
foreach($prices_today as $key => $price)
{
    $timestamp = strtotime($price->startsAt);
    $total = $price->total;
    $energy = $price->energy;
    $tax = $price->tax;
    $total_arr[$key] = [
        'TimeStamp' => $timestamp,
        'Value' => $total
    ];
    $energy_arr[$key] = [
        'TimeStamp' => $timestamp,
        'Value' => $energy
        ];
    $tax_arr[$key] = [
        'TimeStamp' => $timestamp,
        'Value' => $tax
        ];
}
$archive_id = 11380;
$total_id = 21856;
$energy_id = 19802;
$tax_id = 40813;

AddArchiveValues($archive_id, $total_id, $total_arr);
AddArchiveValues($archive_id, $energy_id, $energy_arr);
AddArchiveValues($archive_id, $tax_id, $tax_arr);

function AddArchiveValues($archive_id, $variable_id, $values_array)
{
AC_AddLoggedValues($archive_id, $variable_id, $values_array);
AC_ReAggregateVariable($archive_id, $variable_id);
}

.

Learning alot here now, great.

Now the script stops at:

AC_AddLoggedValues($archive_id, $variable_id, $values_array);

With the message:
Warning: Cannot add data with timestamps after logged data that is not yet written to file in /var/lib/symcon/scripts/13063.ips.php on line 49

$archive_id I set to my archive and $total_id is a new variable.
The „tax“ and the „energy“ I actually don’t need as this „Total“ is the sum of these.

According to the message, you try to add values that occur before data that is not yet written to the file, i.e., the newest data, up to a couple of minutes old. To keep consitency, this is blocked. Maybe you want to write the data for 0:00 at 0:00? In such a case, you could either wait and add the values at 0:05 instead or you could just use SetValue.

Have you run the script multiple times in the past 24 hours? What is the current number of measurements in the archive?
Otherwise, you would have to add a query that first checks whether the last timestamp is older than the data that you want to add in case the script is accidentally executed more than every 24 hours.

Not sure I follow you guys exactly.

   $total_arr[$key] = [
        'TimeStamp' => $timestamp,
        'Value' => $total
    ];
}
 var_dump($total_arr);

Doing the vardump above I get 24 arrays of:

 [0]=>
  array(2) {
    ["TimeStamp"]=>
    int(1579042800)
    ["Value"]=>
    float(0,2021)

This is the energy price from 00:00 - 01:00 at night.
I see the unix timestamp translates to 23:00 - 00:00 as I guess this is UTC time.
The string value for the same array was:
string(25) „2020-01-15T00:00:00+01:00“.
So I guess that is one hour wrong.

Just to conclude what I want to do. Just after midnight every day I want to get the upcoming 24 hour energy price and write to a variable and display the trend. So I can adjust my power consumption after the price that day. So yes the timestamps will be up to 24 hours into the future :slight_smile:

When running the below script it does not write any values at all to the $total_id variable.
It just gives the error mentioned in my previous post.

<?php

$json = '{"query":"{viewer {homes {currentSubscription {priceInfo {today {total energy tax startsAt }}}}}}"}'; 
$response = SendCommand($json);
function SendCommand($json)
{
    # Create a connection
$ch = curl_init('https://api.tibber.com/v1-beta/gql');
# Setting our options
curl_setopt($ch, CURLOPT_URL, 'https://api.tibber.com/v1-beta/gql');
curl_setopt($ch, CURLOPT_HTTPHEADER, 
   array('Content-Type: application/json',  
   'Authorization: Bearer 41121d0cdb9d4d2592c2c0c3395add82166e9e3a160d6abf0b70cd85efb2****')); // Demo token
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

# Get the response
$response = curl_exec($ch);
curl_close($ch);
    return $response;
}

$data = json_decode($response);
$prices_today = $data->data->viewer->homes[0]->currentSubscription->priceInfo->today;
//var_dump($prices_today);

    $total_arr = [];

foreach($prices_today as $key => $price)
{
    $timestamp = strtotime($price->startsAt);
    $total = $price->total;

    $total_arr[$key] = [
        'TimeStamp' => $timestamp,
        'Value' => $total
    ];
}
 //var_dump($total_arr);

$archive_id = 30456;
$total_id = 26429;

AddArchiveValues($archive_id, $total_id, $total_arr);

function AddArchiveValues($archive_id, $variable_id, $values_array)
{
AC_AddLoggedValues($archive_id, $variable_id, $values_array);
AC_ReAggregateVariable($archive_id, $variable_id);
} 

I did a test with the command AC_AddLoggedValues and could add data with timestamp in the past just fine, but if I try to add data forward in time I get the same error message.

Is it not possible to enter future data in the archive?

You are correct, adding future data is not possible. You could write the future data into a String variable as array, extract the current value at every full hour and write it into your variable.Thus, you would add the trend over the day.