@@ -20,12 +20,16 @@ const std::string HONEYWELL_LOCATIONS_PATH = "https://api.honeywell.com/v2/locat
20
20
const std::string HONEYWELL_UPDATE_THERMOSTAT = " https://api.honeywell.com/v2/devices/thermostats/[deviceid]?apikey=[apikey]&locationId=[locationid]" ;
21
21
const std::string HONEYWELL_TOKEN_PATH = " https://api.honeywell.com/oauth2/token" ;
22
22
23
- const std::string kHeatSetPointDesc = " Target temperature ([devicename])" ;
24
- const std::string kHeatingDesc = " Heating ([devicename])" ;
25
- const std::string kOperationStatusDesc = " Heating state ([devicename])" ;
23
+ const std::string kSetPointDesc = " Target temperature ([devicename])" ;
24
+ const std::string kHeatingDesc = " Heating Mode([devicename])" ;
25
+ const std::string kCoolingDesc = " Cooling Mome([devicename])" ;
26
+ const std::string kHeatingStatusDesc = " Heating State ([devicename])" ;
27
+ const std::string kCoolingStatusDesc = " Cooling State ([devicename])" ;
26
28
const std::string kOutdoorTempDesc = " Outdoor temperature ([devicename])" ;
27
29
const std::string kRoomTempDesc = " Room temperature ([devicename])" ;
28
30
const std::string kAwayDesc = " Away ([name])" ;
31
+ const std::string kfanRequest = " Fan Request ([devicename])" ;
32
+ const std::string kcirculationFanRequest = " Circulation Fan Request ([devicename])" ;
29
33
30
34
extern http::server::CWebServerHelper m_webservers;
31
35
@@ -123,19 +127,19 @@ void CHoneywell::Do_Work()
123
127
//
124
128
bool CHoneywell::WriteToHardware (const char *pdata, const unsigned char /* length*/ )
125
129
{
130
+
126
131
const tRBUF *pCmd = reinterpret_cast <const tRBUF *>(pdata);
132
+
127
133
if (pCmd->LIGHTING2 .packettype == pTypeLighting2)
128
134
{
129
135
// Light command
130
-
131
- int nodeID = pCmd->LIGHTING2 .id3 ;
136
+
137
+ int nodeID = pCmd->LIGHTING2 .id4 ;
132
138
int devID = nodeID / 10 ;
133
139
std::string deviceName = mDeviceList [devID][" name" ].asString ();
134
-
135
-
136
140
bool bIsOn = (pCmd->LIGHTING2 .cmnd == light2_sOn);
137
- if ((nodeID % 10 ) == 3 ) {
138
- // heating on or off
141
+ if ((nodeID % 10 ) == 3 | (nodeID % 10 ) == 7 ) {
142
+ // heating cooling on or off
139
143
SetPauseStatus (devID, bIsOn, nodeID);
140
144
return true ;
141
145
}
@@ -248,40 +252,83 @@ void CHoneywell::GetThermostatData()
248
252
Json::Value devices = location[" devices" ];
249
253
for (int devCnt = 0 ; devCnt < (int )devices.size (); devCnt++)
250
254
{
255
+
251
256
Json::Value device = devices[devCnt];
252
257
std::string deviceName = device[" name" ].asString ();
253
258
mDeviceList [devNr] = device;
254
259
mLocationList [devNr] = location[" locationID" ].asString ();
255
260
261
+ std::string units = device[" units" ].asString (); // :"Fahrenheit"
262
+
256
263
float temperature;
257
264
temperature = (float )device[" indoorTemperature" ].asFloat ();
258
265
std::string desc = kRoomTempDesc ;
259
266
stdreplace (desc, " [devicename]" , deviceName);
260
- SendTempSensor (10 * devNr + 1 , 255 , temperature, desc);
267
+ if (units == " Fahrenheit" ) {
268
+ SendTempSensor (10 * devNr + 1 , 255 , (float )ConvertToCelsius (temperature), desc);
269
+ }else {
270
+ SendTempSensor (10 * devNr + 1 , 255 , temperature, desc);
271
+ }
261
272
262
273
temperature = (float )device[" outdoorTemperature" ].asFloat ();
263
274
desc = kOutdoorTempDesc ;
264
275
stdreplace (desc, " [devicename]" , deviceName);
265
- SendTempSensor (10 * devNr + 2 , 255 , temperature, desc);
276
+ if (units == " Fahrenheit" ) {
277
+ SendTempSensor (10 * devNr + 2 , 255 , (float )ConvertToCelsius (temperature), desc);
278
+ }else {
279
+ SendTempSensor (10 * devNr + 2 , 255 , temperature, desc);
280
+ }
266
281
267
282
std::string mode = device[" changeableValues" ][" mode" ].asString ();
268
283
bool bHeating = (mode == " Heat" );
269
284
desc = kHeatingDesc ;
270
285
stdreplace (desc, " [devicename]" , deviceName);
271
286
SendSwitch (10 * devNr + 3 , 1 , 255 , bHeating, 0 , desc);
272
287
273
- temperature = (float )device[" changeableValues" ][" heatSetpoint" ].asFloat ();
274
- desc = kHeatSetPointDesc ;
288
+ if (bHeating){
289
+ temperature = (float )device[" changeableValues" ][" heatSetpoint" ].asFloat ();
290
+ }else {
291
+ temperature = (float )device[" changeableValues" ][" coolSetpoint" ].asFloat ();
292
+ }
293
+ desc = kSetPointDesc ;
275
294
stdreplace (desc, " [devicename]" , deviceName);
276
- SendSetPointSensor ((uint8_t )(10 * devNr + 4 ), temperature, desc);
277
- devNr++;
295
+ if (units == " Fahrenheit" ) {
296
+ SendSetPointSensor ((uint8_t )(10 * devNr + 4 ), (float )ConvertToCelsius (temperature), desc);
297
+ }else {
298
+ SendSetPointSensor ((uint8_t )(10 * devNr + 4 ), temperature, desc);
299
+ }
278
300
279
301
std::string operationstatus = device[" operationStatus" ][" mode" ].asString ();
280
- bool bStatus = (operationstatus != " EquipmentOff " );
281
- desc = kOperationStatusDesc ;
302
+ bool bStatus = (operationstatus == " Heat " );
303
+ desc = kHeatingStatusDesc ;
282
304
stdreplace (desc, " [devicename]" , deviceName);
283
305
SendSwitch (10 * devNr + 5 , 1 , 255 , bStatus, 0 , desc);
284
- }
306
+
307
+ // std::string operationstatus = device["operationStatus"]["mode"].asString();
308
+ bool bCStatus = (operationstatus == " Cool" );
309
+ desc = kCoolingStatusDesc ;
310
+ stdreplace (desc, " [devicename]" , deviceName);
311
+ SendSwitch (10 * devNr + 6 , 1 , 255 , bCStatus, 0 , desc);
312
+
313
+ // std::string mode = device["changeableValues"]["mode"].asString();
314
+ bool bCooling = (mode == " Cool" );
315
+ desc = kCoolingDesc ;
316
+ stdreplace (desc, " [devicename]" , deviceName);
317
+ SendSwitch (10 * devNr + 7 , 1 , 255 , bCooling, 0 , desc);
318
+
319
+ bool fanRequest = device[" operationStatus" ][" fanRequest" ].asBool ();
320
+ desc = kfanRequest;
321
+ stdreplace (desc, " [devicename]" , deviceName);
322
+ SendSwitch (10 * devNr + 8 , 1 , 255 , fanRequest, 0 , desc);
323
+
324
+ bool circulationFanRequest = device[" operationStatus" ][" circulationFanRequest" ].asBool ();
325
+ desc = kcirculationFanRequest;
326
+ stdreplace (desc, " [devicename]" , deviceName);
327
+ SendSwitch (10 * devNr + 9 , 1 , 255 , circulationFanRequest, 0 , desc);
328
+
329
+ devNr++;
330
+
331
+ }
285
332
286
333
bool geoFenceEnabled = location[" geoFenceEnabled" ].asBool ();
287
334
if (geoFenceEnabled) {
@@ -324,13 +371,35 @@ void CHoneywell::SendSetPointSensor(const unsigned char Idx, const float Temp, c
324
371
//
325
372
// transfer pause status to Honeywell api
326
373
//
327
- void CHoneywell::SetPauseStatus (const int idx, bool bHeating , const int /* nodeid */ )
374
+ void CHoneywell::SetPauseStatus (const int idx, bool bCommand , const int nodeID )
328
375
{
329
376
if (!refreshToken ()) {
330
377
_log.Log (LOG_ERROR," Honeywell: No token available. Failed setting thermostat data" );
331
378
return ;
332
379
}
333
380
381
+ std::string currentMode = mDeviceList [idx][" changeableValues" ][" mode" ].asString ();
382
+
383
+ bool bHeating = currentMode == " Heat" ;
384
+ bool nHeat = currentMode == " Heat" ;
385
+ bool nCool = currentMode == " Cool" ;
386
+
387
+ if ((nodeID % 10 ) == 3 ){
388
+ nHeat = bCommand;
389
+ bHeating = true ;
390
+ if (bCommand){
391
+ nCool = false ;
392
+ }
393
+ }
394
+ if ((nodeID % 10 ) == 7 ){
395
+ nCool = bCommand;
396
+ bHeating = false ;
397
+ if (bCommand){
398
+ nHeat = false ;
399
+ }
400
+ }
401
+
402
+
334
403
std::string url = HONEYWELL_UPDATE_THERMOSTAT;
335
404
std::string deviceID = mDeviceList [idx][" deviceID" ].asString ();
336
405
@@ -339,8 +408,9 @@ void CHoneywell::SetPauseStatus(const int idx, bool bHeating, const int /*nodeid
339
408
stdreplace (url, " [locationid]" , mLocationList [idx]);
340
409
341
410
Json::Value reqRoot;
342
- reqRoot[" mode" ] = bHeating ? " Heat" : " Off" ;
343
- reqRoot[" heatSetpoint" ] = mDeviceList [idx][" changeableValues" ][" coolHeatpoint" ].asInt ();
411
+ reqRoot[" mode" ] = nHeat ? " Heat" : (nCool ? " Cool" : " Off" );
412
+ reqRoot[" autoChangeoverActive" ] = " true" ;
413
+ reqRoot[" heatSetpoint" ] = mDeviceList [idx][" changeableValues" ][" heatSetpoint" ].asInt ();
344
414
reqRoot[" coolSetpoint" ] = mDeviceList [idx][" changeableValues" ][" coolSetpoint" ].asInt ();
345
415
reqRoot[" thermostatSetpointStatus" ] = " TemporaryHold" ;
346
416
@@ -351,16 +421,38 @@ void CHoneywell::SetPauseStatus(const int idx, bool bHeating, const int /*nodeid
351
421
_log.Log (LOG_ERROR, " Honeywell: Error setting thermostat data!" );
352
422
return ;
353
423
}
354
-
355
424
std::string desc = kHeatingDesc ;
356
425
stdreplace (desc, " [devicename]" , mDeviceList [idx][" name" ].asString ());
357
- SendSwitch (10 * idx + 3 , 1 , 255 , bHeating, 0 , desc);
426
+ SendSwitch (10 * idx + 3 , 1 , 255 , nHeat, 0 , desc);
427
+
428
+ desc = kCoolingDesc ;
429
+ stdreplace (desc, " [devicename]" , mDeviceList [idx][" name" ].asString ());
430
+ SendSwitch (10 * idx + 7 , 1 , 255 , nCool, 0 , desc);
431
+
432
+ if (bCommand){
433
+ std::string units = mDeviceList [idx][" units" ].asString ();
434
+ float temperature;
435
+ if (nHeat){
436
+ temperature = (float )mDeviceList [idx][" changeableValues" ][" heatSetpoint" ].asFloat ();
437
+ }else {
438
+ temperature = (float )mDeviceList [idx][" changeableValues" ][" coolSetpoint" ].asFloat ();
439
+ }
440
+ desc = kSetPointDesc ;
441
+ stdreplace (desc, " [devicename]" , mDeviceList [idx][" name" ].asString ());
442
+ if (units == " Fahrenheit" ) {
443
+ SendSetPointSensor ((uint8_t )(10 * idx + 4 ), (float )ConvertToCelsius (temperature), desc);
444
+ }else {
445
+ SendSetPointSensor ((uint8_t )(10 * idx + 4 ), temperature, desc);
446
+ }
447
+ }
448
+
449
+
358
450
}
359
451
360
452
//
361
453
// transfer the updated temperature to Honeywell API
362
454
//
363
- void CHoneywell::SetSetpoint (const int idx, const float temp, const int /* nodeid*/ )
455
+ void CHoneywell::SetSetpoint (const int idx, const float temp, const int nodeid)
364
456
{
365
457
if (!refreshToken ()) {
366
458
_log.Log (LOG_ERROR, " Honeywell: No token available. Error setting thermostat data!" );
@@ -375,24 +467,69 @@ void CHoneywell::SetSetpoint(const int idx, const float temp, const int /*nodeid
375
467
stdreplace (url, " [locationid]" , mLocationList [idx]);
376
468
377
469
Json::Value reqRoot;
378
- reqRoot[" mode" ] = " Heat" ;
379
- reqRoot[" heatSetpoint" ] = temp;
380
- reqRoot[" coolSetpoint" ] = mDeviceList [idx][" changeableValues" ][" coolSetpoint" ].asInt ();
470
+ std::string units = mDeviceList [idx][" units" ].asString ();
471
+
472
+ if (GetSwitchValue ((uint8_t )(10 * idx + 7 )) /* mode set for cooling*/ ){
473
+ reqRoot[" mode" ] = " Cool" ;
474
+ reqRoot[" autoChangeoverActive" ] = " true" ;
475
+ reqRoot[" heatSetpoint" ] = mDeviceList [idx][" changeableValues" ][" heatSetpoint" ].asInt ();
476
+
477
+ if (units == " Fahrenheit" ) {
478
+ reqRoot[" coolSetpoint" ] = (float )ConvertToFahrenheit (temp);
479
+ }else {
480
+ reqRoot[" coolSetpoint" ] = temp;
481
+ }
482
+ }else {
483
+ reqRoot[" mode" ] = " Heat" ;
484
+ reqRoot[" autoChangeoverActive" ] = " true" ;
485
+ if (units == " Fahrenheit" ) {
486
+ reqRoot[" heatSetpoint" ] = (float )ConvertToFahrenheit (temp);
487
+ }else {
488
+ reqRoot[" heatSetpoint" ] = temp;
489
+ }
490
+ reqRoot[" coolSetpoint" ] = mDeviceList [idx][" changeableValues" ][" coolSetpoint" ].asInt ();
491
+ }
492
+
493
+ // reqRoot["thermostatSetpointStatus"] = "PermanentHold";
381
494
reqRoot[" thermostatSetpointStatus" ] = " TemporaryHold" ;
382
-
383
495
std::string sResult ;
384
- HTTPClient::SetConnectionTimeout (HWAPITIMEOUT);
385
- HTTPClient::SetTimeout (HWAPITIMEOUT);
386
- if (!HTTPClient::POST (url, JSonToRawString (reqRoot), mSessionHeaders , sResult , true , true )) {
387
- _log.Log (LOG_ERROR, " Honeywell: Error setting thermostat data!" );
388
- return ;
389
- }
496
+ if (GetSwitchValue ((uint8_t )(10 * idx + 7 )) | GetSwitchValue ((uint8_t )(10 * idx + 3 ))){
497
+ HTTPClient::SetConnectionTimeout (HWAPITIMEOUT);
498
+ HTTPClient::SetTimeout (HWAPITIMEOUT);
499
+ if (!HTTPClient::POST (url, JSonToRawString (reqRoot), mSessionHeaders , sResult , true , true )) {
500
+ _log.Log (LOG_ERROR, " Honeywell: Error setting thermostat data!" );
501
+ return ;
502
+ }
390
503
391
- std::string desc = kHeatSetPointDesc ;
392
- stdreplace (desc, " [devicename]" , mDeviceList [idx][" name" ].asString ());
393
- SendSetPointSensor ((uint8_t )(10 * idx + 4 ), temp, desc);
504
+ std::string desc = kSetPointDesc ;
505
+ stdreplace (desc, " [devicename]" , mDeviceList [idx][" name" ].asString ());
506
+ SendSetPointSensor ((uint8_t )(10 * idx + 4 ), temp, desc);
507
+ }
508
+ // desc = kHeatingDesc;
509
+ // stdreplace(desc, "[devicename]", mDeviceList[idx]["name"].asString());
510
+ // SendSwitch(10 * idx + 3, 1, 255, true, 0, desc);
511
+ }
394
512
395
- desc = kHeatingDesc ;
396
- stdreplace (desc, " [devicename]" , mDeviceList [idx][" name" ].asString ());
397
- SendSwitch (10 * idx + 3 , 1 , 255 , true , 0 , desc);
513
+ bool CHoneywell::GetSwitchValue (const int NodeID)
514
+ {
515
+ uint8_t ChildID = 1 ;
516
+ // make device ID
517
+ unsigned char ID1 = (unsigned char )((NodeID & 0xFF000000 ) >> 24 );
518
+ unsigned char ID2 = (unsigned char )((NodeID & 0xFF0000 ) >> 16 );
519
+ unsigned char ID3 = (unsigned char )((NodeID & 0xFF00 ) >> 8 );
520
+ unsigned char ID4 = (unsigned char )NodeID & 0xFF ;
521
+
522
+ char szIdx[10 ];
523
+ sprintf (szIdx, " %X%02X%02X%02X" , ID1, ID2, ID3, ID4);
524
+ std::vector<std::vector<std::string> > result;
525
+ result = m_sql.safe_query (" SELECT Name,nValue,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit == %d) AND (Type==%d) AND (Subtype==%d)" ,
526
+ m_HwdID, szIdx, ChildID, int (pTypeLighting2), int (sTypeAC ));
527
+ if (!result.empty ())
528
+ {
529
+ int nvalue = atoi (result[0 ][1 ].c_str ());
530
+ return (nvalue != light2_sOff);
531
+ }else {
532
+ return false ;
533
+ _log.Log (LOG_ERROR, " Honeywell: Error reading switch data!" );
534
+ }
398
535
}
0 commit comments