Skip to content

Commit 12f944b

Browse files
committed
Added Evohome zone temperature sensor device linking
1 parent b7a1cf3 commit 12f944b

File tree

4 files changed

+154
-9
lines changed

4 files changed

+154
-9
lines changed

hardware/evohome.cpp

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ CEvohome::CEvohome(const int ID, const std::string &szSerialPort) :
8888
m_nSendFail=0;
8989
m_nZoneCount=0;
9090
m_nControllerMode=0;
91+
m_MaxDeviceID = 0;
9192

9293
m_iBaudRate=115200;
9394
if(!szSerialPort.empty())
@@ -497,6 +498,7 @@ void CEvohome::RequestZoneState()
497498
//Trying this linked to DHW heat demand instead...that won't be adequate do it here too!
498499
RequestDHWState();
499500
SendExternalSensor();
501+
SendZoneSensor();
500502
}
501503

502504
void CEvohome::RequestZoneNames()
@@ -577,6 +579,57 @@ void CEvohome::SendExternalSensor()
577579
AddSendQueue(CEvohomeMsg(CEvohomeMsg::pktinf,0,GetGatewayID(),cmdExternalSensor).Add((uint8_t)0).Add(static_cast<uint16_t>(dbUV*39)).Add((uint8_t)2).Add((uint8_t)2).Add(static_cast<int16_t>(dbTemp*100.0)).Add((uint8_t)1));
578580
}
579581

582+
void CEvohome::SendZoneSensor()
583+
{
584+
unsigned int ID;
585+
586+
if (GetGatewayID() == 0)
587+
return;
588+
double dbTemp = 0.0;
589+
std::vector<std::vector<std::string> > result;
590+
result = m_sql.safe_query("SELECT Max(Unit) FROM DeviceStatus WHERE (HardwareID==%d) AND (Type==%d) AND (Unit>=40) AND (Unit<52)", m_HwdID, (int)pTypeEvohomeZone);
591+
592+
int nDevCount = 0;
593+
if (result.size() > 0)
594+
{
595+
nDevCount = atoi(result[0][0].c_str());
596+
}
597+
else return;
598+
for (int i = 40; i <= nDevCount; ++i)
599+
{
600+
result = m_sql.safe_query("SELECT DeviceID, Name FROM DeviceStatus WHERE (HardwareID==%d) AND (Type==%d) AND (Unit==%d)", m_HwdID, (int)pTypeEvohomeZone, i); // Get Zone Name and DeviceID
601+
if (result.size() > 0) //Check that sensor number exists - this allows for deletion
602+
{
603+
//std::vector<std::string> sd = result[0];
604+
std::stringstream s_strid;
605+
std::string SensorName = result[0][1].c_str();
606+
//s_strid << std::hex << sd[0].c_str();
607+
s_strid << std::hex << result[0][0].c_str();
608+
s_strid >> ID;
609+
result = m_sql.safe_query("SELECT sValue FROM DeviceStatus WHERE (Type !=%d) AND (Name=='%q')", (int)pTypeEvohomeZone, SensorName.c_str()); // Get temperature from external sensor with matching Name
610+
if (result.size() == 1)
611+
{
612+
std::vector<std::string> strarray;
613+
StringSplit(result[0][0], ";", strarray);
614+
if (strarray.size() >= 1)
615+
dbTemp = atof(strarray[0].c_str());
616+
Log(true, LOG_STATUS, "evohome: Send Temp Zone msg Zone: %d DeviceID: 0x%x Name:%s Temp:%f ", i, ID, SensorName.c_str(), dbTemp);
617+
AddSendQueue(CEvohomeMsg(CEvohomeMsg::pktinf, 0, ID, cmdZoneTemp).Add((uint8_t)0).Add(static_cast<int16_t>(dbTemp*100.0)));
618+
// Update the dummy Temp Zone device with the new temperature
619+
REVOBUF tsen;
620+
memset(&tsen, 0, sizeof(REVOBUF));
621+
tsen.EVOHOME2.len = sizeof(tsen.EVOHOME2) - 1;
622+
tsen.EVOHOME2.type = pTypeEvohomeZone;
623+
tsen.EVOHOME2.subtype = sTypeEvohomeZone;
624+
tsen.EVOHOME2.zone = i;
625+
tsen.EVOHOME2.temperature = dbTemp * 100;
626+
RFX_SETID3(ID, tsen.EVOHOME2.id1, tsen.EVOHOME2.id2, tsen.EVOHOME2.id3);
627+
sDecodeRXMessage(this, (const unsigned char *)&tsen.EVOHOME2, "Zone Temp", 255);
628+
}
629+
}
630+
}
631+
}
632+
580633
void CEvohome::ReadCallback(const char *data, size_t len)
581634
{
582635
boost::lock_guard<boost::mutex> l(readQueueMutex);
@@ -804,7 +857,10 @@ int CEvohome::Bind(uint8_t nDevNo, unsigned char nDevType)//use CEvohomeID::devT
804857
int nGatewayID=GetGatewayID();
805858
if(nGatewayID==0)
806859
return 0;
807-
860+
uint8_t ID1;
861+
uint8_t ID2;
862+
uint8_t ID3;
863+
808864
if(nDevType==CEvohomeID::devRelay)//Binding a relay to the HGI80
809865
{
810866
boost::unique_lock<boost::mutex> lock(m_mtxBindNotify);
@@ -835,16 +891,48 @@ int CEvohome::Bind(uint8_t nDevNo, unsigned char nDevType)//use CEvohomeID::devT
835891

836892
boost::system_time const timeout=boost::get_system_time() + boost::posix_time::seconds(60);//monotonic?
837893
while(m_nBindID==0)
838-
{
839-
AddSendQueue(CEvohomeMsg(CEvohomeMsg::pktinf,0,nGatewayID,cmdBinding).Add((uint8_t)0).Add((uint16_t)cmdExternalSensor).Add(CEvohomeID(nGatewayID)).Add((uint8_t)2).Add((uint16_t)cmdExternalSensor).Add(CEvohomeID(nGatewayID)).Add((uint8_t)0).Add((uint16_t)cmdBinding).Add(CEvohomeID(nGatewayID)));
894+
{
895+
AddSendQueue(CEvohomeMsg(CEvohomeMsg::pktinf,0,nGatewayID,cmdBinding).Add((uint8_t)0).Add((uint16_t)cmdExternalSensor).Add(CEvohomeID(nGatewayID)).Add((uint8_t)2).Add((uint16_t)cmdExternalSensor).Add(CEvohomeID(nGatewayID)).Add((uint8_t)0).Add((uint16_t)cmdBinding).Add(CEvohomeID(nGatewayID)));
840896
boost::system_time const wait=boost::get_system_time() + boost::posix_time::seconds(5);//monotonic?
841897
if(!m_cndBindNotify.timed_wait(lock,wait) && boost::get_system_time()>timeout)
842898
return 0;
843899
}
844900
AddSendQueue(CEvohomeMsg(CEvohomeMsg::pktinf,m_nBindID,cmdBinding).Add((uint8_t)0).Add((uint16_t)0xFFFF).Add(CEvohomeID(nGatewayID)));
845901
return m_nBindID;
846902
}
847-
903+
else if (nDevType == CEvohomeID::devZone)//Binding the HGI80 to the evohome controller as a zone temperature sensor
904+
{
905+
// Check that the max Device ID includes the zone temperature sensors
906+
std::vector<std::vector<std::string> > result;
907+
908+
result = m_sql.safe_query("SELECT MAX(DeviceID) FROM DeviceStatus WHERE (HardwareID==%d) AND (Type==%d) AND (Unit>=40) AND (Unit<52)", m_HwdID, (int)pTypeEvohomeZone);
909+
unsigned int ID = 0;
910+
if (result.size() > 0)
911+
{
912+
std::stringstream s_strid;
913+
s_strid << std::hex << result[0][0].c_str();
914+
s_strid >> ID;
915+
}
916+
if (ID > m_MaxDeviceID)
917+
m_MaxDeviceID = ID + 1;
918+
else
919+
m_MaxDeviceID++;
920+
boost::unique_lock<boost::mutex> lock(m_mtxBindNotify);
921+
m_nBindID = 0;
922+
m_nBindIDType = CEvohomeID::devController;
923+
RFX_SETID3(m_MaxDeviceID, ID1, ID2, ID3);
924+
925+
boost::system_time const timeout = boost::get_system_time() + boost::posix_time::seconds(60);//monotonic?
926+
while (m_nBindID == 0)
927+
{
928+
AddSendQueue(CEvohomeMsg(CEvohomeMsg::pktinf, 0, nGatewayID, cmdBinding).Add((uint8_t)0).Add((uint16_t)cmdZoneTemp).Add(ID1).Add(ID2).Add(ID3).Add((uint8_t)2).Add((uint16_t)cmdZoneTemp).Add(ID1).Add(ID2).Add(ID3).Add((uint8_t)0).Add((uint16_t)cmdBinding).Add(CEvohomeID(nGatewayID)));
929+
boost::system_time const wait = boost::get_system_time() + boost::posix_time::seconds(5);//monotonic?
930+
if (!m_cndBindNotify.timed_wait(lock, wait) && boost::get_system_time()>timeout)
931+
return 0;
932+
}
933+
AddSendQueue(CEvohomeMsg(CEvohomeMsg::pktinf, m_nBindID, cmdBinding).Add((uint8_t)0).Add((uint16_t)0x30C9).Add(ID1).Add(ID2).Add(ID3));
934+
return m_MaxDeviceID;
935+
}
848936
return 0;
849937
}
850938

@@ -1016,6 +1104,8 @@ bool CEvohome::DecodeZoneTemp(CEvohomeMsg &msg)//0x30C9
10161104
Log(true,LOG_STATUS,"evohome: %s: WARNING: sensor reading with zone != 0: 0x%x - %d", tag, msg.GetID(0), msg.payload[0]);
10171105
}
10181106
}
1107+
if ((msg.GetID(0) > m_MaxDeviceID))
1108+
m_MaxDeviceID = msg.GetID(0);
10191109

10201110
return true;
10211111
}
@@ -1812,6 +1902,27 @@ namespace http {
18121902
}
18131903
else if (type == "OutdoorSensor")
18141904
nID = pEvoHW->Bind(0, CEvohomeID::devSensor);
1905+
else if (type == "ZoneSensor")
1906+
{
1907+
//get dev count
1908+
std::vector<std::vector<std::string> > result;
1909+
result = m_sql.safe_query("SELECT MAX(Unit) FROM DeviceStatus WHERE (HardwareID==%d) AND (Type==%d) AND (Unit>=40) AND (Unit<52)", HwdID,(int)pTypeEvohomeZone);
1910+
int nDevCount = 0;
1911+
if (result.size() > 0)
1912+
{
1913+
nDevCount = atoi(result[0][0].c_str());
1914+
}
1915+
1916+
if (nDevCount == 51)// Allow a maximum of 12 sensors
1917+
{
1918+
root["status"] = "ERR";
1919+
root["message"] = "Maximum number of Zone sensors reached";
1920+
return;
1921+
}
1922+
1923+
nDevNo = nDevCount + 1;
1924+
nID = pEvoHW->Bind(nDevNo, CEvohomeID::devZone);
1925+
}
18151926
if (nID == 0)
18161927
{
18171928
root["status"] = "ERR";
@@ -1838,6 +1949,25 @@ namespace http {
18381949
m_sql.UpdateValue(HwdID, devid.c_str(), nDevNo, pTypeEvohomeRelay, sTypeEvohomeRelay, 10, 255, 0, "Off", devname);
18391950
pEvoHW->SetRelayHeatDemand(nDevNo, 0);//initialize heat demand
18401951
}
1952+
else if (type == "ZoneSensor")
1953+
{
1954+
char ID[40];
1955+
sprintf(ID, "%x", nID);
1956+
1957+
std::vector<std::vector<std::string> > result;
1958+
result = m_sql.safe_query("SELECT ID,DeviceID,Name FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q')", HwdID, ID);
1959+
if (result.size() > 0)
1960+
{
1961+
root["status"] = "ERR";
1962+
root["message"] = "Device already exists";
1963+
root["Used"] = true;
1964+
root["Name"] = result[0][2];
1965+
return;
1966+
}
1967+
1968+
std::string devname; // = "Zone Temp";
1969+
m_sql.UpdateValue(HwdID, ID, nDevNo, pTypeEvohomeZone, sTypeEvohomeZone, 10, 255, 0, "0.0;0.0;Auto", devname);
1970+
}
18411971
root["status"] = "OK";
18421972
root["title"] = "BindEvohome";
18431973
root["Used"] = false;

hardware/evohome.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ class CEvohome : public AsyncSerial, public CDomoticzHardwareBase
534534
void RequestDeviceInfo(uint8_t nAddr);
535535

536536
void SendExternalSensor();
537+
void SendZoneSensor();
537538

538539
void RXRelay(uint8_t nDevNo, uint8_t nDemand, int nID=0);
539540
void SendRelayHeatDemand(uint8_t nDevNo, uint8_t nDemand);
@@ -603,6 +604,8 @@ class CEvohome : public AsyncSerial, public CDomoticzHardwareBase
603604
unsigned char m_nBindIDType;//what type of device to bind
604605
boost::mutex m_mtxBindNotify;
605606
boost::condition_variable m_cndBindNotify;
607+
608+
unsigned int m_MaxDeviceID;
606609

607610
struct _tRelayCheck
608611
{

main/mainworker.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5904,7 +5904,14 @@ void MainWorker::decode_evohome2(const int HwdID, const _eHardwareTypes HwdType,
59045904

59055905
//Get Device details
59065906
std::vector<std::vector<std::string> > result;
5907-
if(pEvo->EVOHOME2.zone)//if unit number is available the id3 will be the controller device id
5907+
if (pEvo->EVOHOME2.type == pTypeEvohomeZone && pEvo->EVOHOME2.zone > 12) //Allow for additional Zone Temp devices which require DeviceID
5908+
{
5909+
result = m_sql.safe_query(
5910+
"SELECT HardwareID, DeviceID,Unit,Type,SubType,sValue,BatteryLevel "
5911+
"FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID == '%x') AND (Type==%d)",
5912+
HwdID, (int)RFX_GETID3(pEvo->EVOHOME2.id1, pEvo->EVOHOME2.id2, pEvo->EVOHOME2.id3), (int)pEvo->EVOHOME2.type);
5913+
}
5914+
else if (pEvo->EVOHOME2.zone)//if unit number is available the id3 will be the controller device id
59085915
{
59095916
result = m_sql.safe_query(
59105917
"SELECT HardwareID, DeviceID,Unit,Type,SubType,sValue,BatteryLevel "

www/app/HardwareController.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3377,9 +3377,11 @@ define(['app'], function (app) {
33773377
{
33783378
$.devIdx=idx;
33793379
if(devtype=="Relay")
3380-
ShowNotify($.t('Hold bind button on relay...'));
3380+
ShowNotify($.t('Hold bind button on relay...'),2500);
3381+
else if (devtype == "ZoneSensor")
3382+
ShowNotify($.t('Binding Domoticz zone temperature sensor to controller...'),2500);
33813383
else
3382-
ShowNotify($.t('Binding Domoticz outdoor temperature device to evohome controller...'));
3384+
ShowNotify($.t('Binding Domoticz outdoor temperature device to evohome controller...'),2500);
33833385

33843386
setTimeout(function() {
33853387
var bNewDevice = false;
@@ -3406,9 +3408,11 @@ define(['app'], function (app) {
34063408
if ((bNewDevice == true) && (bIsUsed == false))
34073409
{
34083410
if(devtype=="Relay")
3409-
ShowNotify($.t('Relay bound, and can be found in the devices tab!'));
3411+
ShowNotify($.t('Relay bound, and can be found in the devices tab!'),2500);
3412+
else if (devtype == "ZoneSensor")
3413+
ShowNotify($.t('Sensor bound, and can be found in the devices tab!'),2500);
34103414
else
3411-
ShowNotify($.t('Domoticz outdoor temperature device has been bound to evohome controller'));
3415+
ShowNotify($.t('Domoticz outdoor temperature device has been bound to evohome controller'),2500);
34123416
}
34133417
else {
34143418
if (bIsUsed == true)
@@ -3751,6 +3755,7 @@ define(['app'], function (app) {
37513755
{
37523756
HwTypeStr+=' <span class="label label-info lcursor" onclick="BindEvohome(' + item.idx + ',\'' + item.Name + '\',\'Relay\');">Bind Relay</span>';
37533757
HwTypeStr+=' <span class="label label-info lcursor" onclick="BindEvohome(' + item.idx + ',\'' + item.Name + '\',\'OutdoorSensor\');">Outdoor Sensor</span>';
3758+
HwTypeStr += ' <span class="label label-info lcursor" onclick="BindEvohome(' + item.idx + ',\'' + item.Name + '\',\'ZoneSensor\');">Bind Temp Sensor</span>';
37543759
}
37553760
}
37563761
else if (HwTypeStr.indexOf("Rego 6XX") >= 0)

0 commit comments

Comments
 (0)