Here is some code I have put together in order to receive basic info from the Viessmann boiler. I have used HTML and PHP.
<html>
<title>Viessmann boiler info</title>
<body>
<h1>Viessmann boiler info</h1>
<?php
$installationId = "Replace with your installation id";
$gatewaySerial = "Replace with your gateway serial";
$deviceId = "Replace with your device Id";
$getURL='https://api.viessmann.com/iot/v1/equipment/installations/'.$installationId.'/gateways/'.$gatewaySerial.'/devices/'.$deviceId.'/features';
$headerRequest = array(
"Content-Type: application/x-www-form-urlencoded",
"Authorization: Bearer $autorizationTOKEN"
);
$cURLConnection = curl_init();
curl_setopt($cURLConnection, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; MSIE 7.01; Windows NT 5.0)");
curl_setopt($cURLConnection, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($cURLConnection, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($cURLConnection, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($cURLConnection, CURLOPT_RETURNTRANSFER,true);
curl_setopt($cURLConnection, CURLOPT_HTTPHEADER, $headerRequest);
curl_setopt($cURLConnection, CURLOPT_CONNECTTIMEOUT, 130);
curl_setopt($cURLConnection, CURLOPT_TIMEOUT, 130);
curl_setopt($cURLConnection, CURLOPT_URL,$getURL);
$apiResponse = curl_exec($cURLConnection);
$apiErr = curl_error($cURLConnection);
curl_close($cURLConnection);
$jsonResponse = json_decode($apiResponse, true);
echo "<br><br><br>";
print_r($jsonResponse);
print_r($apiErr);
echo "<br><br><br>";
$BurnerHours = $jsonResponse['data']['29']['properties']['hours']['value'];
echo "BurnerHours: ".$BurnerHours."<br>";
$BurnerStarts = $jsonResponse['data']['29']['properties']['starts']['value'];
echo "BurnerStarts: ".$BurnerStarts."<br>";
$MeasureUnit = $jsonResponse['data']['15']['properties']['value']['unit'];
if ($MeasureUnit == "celsius") {
$MU = " °C ";
} else {
$MU = " °F ";
}
$TemperatureCommon = $jsonResponse['data']['15']['properties']['value']['value'];
echo "TemperaturaTur: ".$TemperatureCommon." ".$MU."<br>";
$HotWaterSet = $jsonResponse['data']['4']['properties']['value']['value'];
$HotWater = $jsonResponse['data']['20']['properties']['value']['value'];
echo "HotWater: ".$HotWaterSet." / ".$HotWater." ".$MU."<br>";
$RadiatorsSet = $jsonResponse['data']['1']['properties']['temperature']['value'];
$Radiators = $jsonResponse['data']['31']['properties']['value']['value'];
echo "Radiators: ".$RadiatorsSet ." / ".$Radiators." ".$MU."<br>";
?>
<div style="position:relative; ">
<img src="sistem_termic.png" alt="cetrala" style="display:block; margin-left:auto; margin-right:auto; ">
<div style="position:absolute; top: 12%; left:52%; font-size:150%; ">
<?php echo "Boiler<br>".
"TemperatureCommon: ".number_format($RadiatorsSet,0).$MU."<br>".
"BurnerHours: ".$BurnerHours."<br>".
"BurnerStarts: ".$BurnerStarts."<br>";?>
</div>
<div style="position:absolute; top: 53%; left:27%; font-size:150%; text-align:right; ">
<?php echo "Water heating<br>".
"Set: ".number_format($HotWaterSet,0).$MU."<br>".
"Current: ".number_format($HotWater,0).$MU."<br>";?>
</div>
<div style="position:absolute; top: 53%; left:50%; font-size:150%; ">
<?php echo "Radiators<br>".
"Set: ".number_format($RadiatorsSet,0).$MU."<br>".
"Current: ".number_format($Radiators,0).$MU."<br>";?>
</div>
</div>
<br><br><br><br><br><br>
</body>
</html>
And the result is presented in the attached screenshot.
Gelöst! Gehe zu Lösung.
Thank you for all questions and contributions. As a result I have updated the code and posted a new version here:
Regards,
@SorinB Thank you very much for sharing your code! This will definitely help others in start developing with the API.
Much appreciated!
@MichaelHanna, did you test the code?
@SorinB, your code is not functional as it is.
Where is the "$ autorizationTOKEN" variable?
Can you provide "sistem_termic.png"?
Best regards
The code is functional only after you get the following variables
$autorizationTOKEN
$installationId
$gatewaySerial
$deviceId
For this preliminary steps, documentation is available here:
https://developer.viessmann.com/en/doc/getting-started
and with more details, after you login, here
https://developer.viessmann.com/en/doc/authentication
Also you can take a lock at this post:
I have attached the background .PNG. Strongly encourage to design your own and share. Mine is not much.
All best,
S
Note that the returned JSON array order is not assured! Initially I used the array indices as well and had to change my code afterwards!
True,
it looks like from time to time the order of the data points is changing. I do not know yet what in causing this change. It can be a boiler restart, a restart of the boiler communication gateway or something else.
Regards
HI,
If we go data point to data point we will have about 7 queries to the server. If we query the entire list of features will have only one query. Is there any solution to simplify the process?
Regards,
You can call for one datapoint, several points or all!
See this example from my javascript rule which is requesting several datapoints:
url ="https://api.viessmann.com/iot/v1/equipment/installations/"+ installationID +"/gateways/" +gatewaySerial + "/devices/0/features?regex=heating.(sensors.temperature.outside%7Cdhw.(oneTimeCharge%7Csensors.temperature.hotWaterStorage%7Cpumps.circulation)%7Cburners.0.statistics%7Ccircuits.0.operating.modes.active)";
The "%7" is used instead of the "|" character.
Very good suggestion. I will publish an update of the code accordingly.
So the $getURL variable would be updated as follows. It will be registered as a single transaction, however it is not clear if the JSON order will preserve. For the moment the reply for each data point is not provided in the order stated in the URL. I will return in couple of days after I can test the code in the boiler premises,
$getURL='https://api.viessmann.com/iot/v1/equipment/installations/'.$installationId.'/gateways/'.$gatewaySeri...'
.'heating.burners'.'%7C'
.'heating.burners.0.statistics'.'%7C'
.'heating.boiler.sensors.temperature.commonSupply'.'%7C'
.'heating.dhw.temperature.main'.'%7C'
.'hotWaterStorage'.'%7C'
.'heating.circuits.0.operating.programs.normal'.'%7C'
.'heating.circuits.0.sensors.temperatue.room';
Quote: "however it is not clear if the JSON order will preserve."
That is assured, the order does change so you can't use the array index for parsing the results!
So, at the end of the day we remint with 7 queries to the server instead of one ...
Maybe would be good for the syntax to be reviewed and place al data points as elements in an array ([]) rather than displaying them as "objects" ({}). Just a thought ...
What makes you think so?
Try something like that:
var returnvalue = HTTP.sendHttpGetRequest(url, headers, 10*1000);
logger.info("returnvalue: {}", returnvalue);
//var arr=returnvalue;
returnvalue = JSON.parse(returnvalue);
var count = returnvalue.data.length;
logger.info("count: {}", count);
try {
for (var i = 0; i < count; i++) {
switch (returnvalue.data[i].feature) {
case "heating.sensors.temperature.outside":
var temp = returnvalue.data[i].properties.value.value;
events.postUpdate('OutsideTemperature', temp);
logger.info("DataIndex: {}, ExtTemp: {}", i,temp);
break;
case "heating.dhw.sensors.temperature.hotWaterStorage":
var temp = returnvalue.data[i].properties.value.value;
events.postUpdate('BoilerTemperature', temp);
logger.info("DataIndex: {}, HotWaterStorageTemp: {}", i, temp);
break;
case "heating.dhw.oneTimeCharge":
var temp = returnvalue.data[i].properties.active.value;
temp = (temp === true) ? 'on' : 'off';
events.postUpdate('IsOneTimeCharge', temp);
logger.info("DataIndex: {}, OneTimeCharge: {}",i, temp);
break;
case "heating.dhw.pumps.circulation":
temp = returnvalue.data[i].properties.status.value;
events.postUpdate('DhwPumpsCirculation', temp);
logger.info("DataIndex: {}, DhwPumpsCirculation: {}",i, temp);
break;
case "heating.burners.0.statistics":
temp = returnvalue.data[i].properties.hours.value;
events.postUpdate("HeatingBurnerStatistics_Hours",temp);
logger.info("DataIndex {}, Hours: {}", i, temp);
temp = returnvalue.data[i].properties.starts.value;
events.postUpdate("HeatingBurnerStatistics_Starts",temp)
logger.info("DataIndex: {}, Starts: {}", i, temp);
break;
case "heating.circuits.0.operating.modes.active":
temp= returnvalue.data[i].properties.value.value;
events.postUpdate("ActiveMode", temp);
logger.info("DataIndex: {}, ActiveMode: {}", i, temp);
break;
default:
logger.info("DataIndex: {}, Data not used: {}",i, returnvalue.data[i].feature);
}
I'm using those lines after the request posted above.
Sorry for no code tags, can't find them using my smartphone😎.
Thank you,
Solved. In PHP I have used ”usorit”. Just 3 lines after
$jsonResponse = json_decode($apiResponse, true);
include:
usort($jsonResponse['data'], function($a,$b){
return $a["feature"]>$b["feature"];
});
Thank you for all questions and contributions. As a result I have updated the code and posted a new version here:
Regards,
The usort will help, but this is also not the best solution. Since 13.12.2021 i have new values in the $jsonResponse and so the indexes of the array are misleading. The Code should be corrected to extract the values by the name of the feature and not by a hardcoded index of an (sorted) array.
Regards,
Bernhard
Hi @BernhardW1 ,
Thank you for comments. Indeed I have faced this problems and as result on 26.10.2021 I have published an updated version of the code. Check this link:
Regards,
Sorin
I have adopted the example to make it more robust if the number of items or the order of the items will change in the array:
$jsonResponse = json_decode($response, true);
function getEntryByFeatureName($resp, $feature)
{
for($i = 0; $i < sizeof($resp["data"]); $i++)
if ($resp["data"][$i]["feature"] == $feature)
return $resp["data"][$i];
}
echo getEntryByFeatureName($jsonResponse, "heating.sensors.temperature.outside")['properties']['value']['value'];
The reason for ( a lot of ) more datapoints being returned started on Dec 2nd for me. Actually the used Regex statement was not used and ALL datapoints were returned.
This misbehaviour was corrected today.
However the order of the returned datapoints is NOT fixed, for that reason the USORT function will not help!