1 #include "stdafx.h"
2 #include <iostream>
3 #include "DomoticzHardware.h"
4 #include "../main/Logger.h"
5 #include "../main/localtime_r.h"
6 #include "../main/Helper.h"
7 #include "../main/RFXtrx.h"
8 #include "../main/SQLHelper.h"
9 #include "../main/mainworker.h"
10 #include "hardwaretypes.h"
11 #include "HardwareCereal.h"
12
13 #define round(a) ( int ) ( a + .5 )
14
CDomoticzHardwareBase()15 CDomoticzHardwareBase::CDomoticzHardwareBase()
16 {
17 mytime(&m_LastHeartbeat);
18 mytime(&m_LastHeartbeatReceive);
19 };
20
~CDomoticzHardwareBase()21 CDomoticzHardwareBase::~CDomoticzHardwareBase()
22 {
23 }
24
CustomCommand(const uint64_t,const std::string &)25 bool CDomoticzHardwareBase::CustomCommand(const uint64_t /*idx*/, const std::string& /*sCommand*/)
26 {
27 return false;
28 }
29
Start()30 bool CDomoticzHardwareBase::Start()
31 {
32 m_iHBCounter = 0;
33 m_bIsStarted = StartHardware();
34 return m_bIsStarted;
35 }
36
Stop()37 bool CDomoticzHardwareBase::Stop()
38 {
39 m_bIsStarted = (!StopHardware());
40 return (!m_bIsStarted);
41 }
42
Restart()43 bool CDomoticzHardwareBase::Restart()
44 {
45 if (StopHardware())
46 {
47 m_bIsStarted = StartHardware();
48 return m_bIsStarted;
49 }
50 return false;
51 }
52
RestartWithDelay(const long seconds)53 bool CDomoticzHardwareBase::RestartWithDelay(const long seconds)
54 {
55 if (StopHardware())
56 {
57 sleep_seconds(seconds);
58 m_bIsStarted = StartHardware();
59 return m_bIsStarted;
60 }
61 return false;
62 }
63
EnableOutputLog(const bool bEnableLog)64 void CDomoticzHardwareBase::EnableOutputLog(const bool bEnableLog)
65 {
66 m_bOutputLog = bEnableLog;
67 }
68
StartHeartbeatThread()69 void CDomoticzHardwareBase::StartHeartbeatThread()
70 {
71 StartHeartbeatThread("Domoticz_HBWork");
72 }
73
StartHeartbeatThread(const char * ThreadName)74 void CDomoticzHardwareBase::StartHeartbeatThread(const char* ThreadName)
75 {
76 m_Heartbeatthread = std::make_shared<std::thread>(&CDomoticzHardwareBase::Do_Heartbeat_Work, this);
77 SetThreadName(m_Heartbeatthread->native_handle(), ThreadName);
78 }
79
80
StopHeartbeatThread()81 void CDomoticzHardwareBase::StopHeartbeatThread()
82 {
83 if (m_Heartbeatthread)
84 {
85 RequestStop();
86 m_Heartbeatthread->join();
87 // Wait a while. The read thread might be reading. Adding this prevents a pointer error in the async serial class.
88 sleep_milliseconds(10);
89 m_Heartbeatthread.reset();
90 }
91 }
92
Do_Heartbeat_Work()93 void CDomoticzHardwareBase::Do_Heartbeat_Work()
94 {
95 int secCounter = 0;
96 int hbCounter = 0;
97 while (!IsStopRequested(200))
98 {
99 secCounter++;
100 if (secCounter == 5)
101 {
102 secCounter = 0;
103 hbCounter++;
104 if (hbCounter % 12 == 0) {
105 mytime(&m_LastHeartbeat);
106 }
107 }
108 }
109 }
110
SetHeartbeatReceived()111 void CDomoticzHardwareBase::SetHeartbeatReceived()
112 {
113 mytime(&m_LastHeartbeatReceive);
114 }
115
HandleHBCounter(const int iInterval)116 void CDomoticzHardwareBase::HandleHBCounter(const int iInterval)
117 {
118 m_iHBCounter++;
119 if (m_iHBCounter % iInterval == 0)
120 {
121 SetHeartbeatReceived();
122 }
123 }
124
SetThreadNameInt(const std::thread::native_handle_type & thread)125 int CDomoticzHardwareBase::SetThreadNameInt(const std::thread::native_handle_type& thread)
126 {
127 return SetThreadName(thread, m_ShortName.c_str());
128 }
129
130 //Log Helper functions
131 #define MAX_LOG_LINE_LENGTH (2048*3)
Log(const _eLogLevel level,const std::string & sLogline)132 void CDomoticzHardwareBase::Log(const _eLogLevel level, const std::string& sLogline)
133 {
134 _log.Log(level, "%s: %s", m_ShortName.c_str(), sLogline.c_str());
135 }
136
Log(const _eLogLevel level,const char * logline,...)137 void CDomoticzHardwareBase::Log(const _eLogLevel level, const char* logline, ...)
138 {
139 va_list argList;
140 char cbuffer[MAX_LOG_LINE_LENGTH];
141 va_start(argList, logline);
142 vsnprintf(cbuffer, sizeof(cbuffer), logline, argList);
143 va_end(argList);
144 _log.Log(level, "%s: %s", m_ShortName.c_str(), cbuffer);
145 }
146
Debug(const _eDebugLevel level,const std::string & sLogline)147 void CDomoticzHardwareBase::Debug(const _eDebugLevel level, const std::string& sLogline)
148 {
149 _log.Debug(level, "%s: %s", m_ShortName.c_str(), sLogline.c_str());
150 }
151
Debug(const _eDebugLevel level,const char * logline,...)152 void CDomoticzHardwareBase::Debug(const _eDebugLevel level, const char* logline, ...)
153 {
154 va_list argList;
155 char cbuffer[MAX_LOG_LINE_LENGTH];
156 va_start(argList, logline);
157 vsnprintf(cbuffer, sizeof(cbuffer), logline, argList);
158 va_end(argList);
159 _log.Debug(level, "%s: %s", m_ShortName.c_str(), cbuffer);
160 }
161
162 //Sensor Helpers
SendTempSensor(const int NodeID,const int BatteryLevel,const float temperature,const std::string & defaultname,const int RssiLevel)163 void CDomoticzHardwareBase::SendTempSensor(const int NodeID, const int BatteryLevel, const float temperature, const std::string& defaultname, const int RssiLevel /* =12 */)
164 {
165 RBUF tsen;
166 memset(&tsen, 0, sizeof(RBUF));
167 tsen.TEMP.packetlength = sizeof(tsen.TEMP) - 1;
168 tsen.TEMP.packettype = pTypeTEMP;
169 tsen.TEMP.subtype = sTypeTEMP5;
170 tsen.TEMP.battery_level = BatteryLevel;
171 tsen.TEMP.rssi = RssiLevel;
172 tsen.TEMP.id1 = (NodeID & 0xFF00) >> 8;
173 tsen.TEMP.id2 = NodeID & 0xFF;
174 tsen.TEMP.tempsign = (temperature >= 0) ? 0 : 1;
175 int at10 = round(std::abs(temperature * 10.0f));
176 tsen.TEMP.temperatureh = (BYTE)(at10 / 256);
177 at10 -= (tsen.TEMP.temperatureh * 256);
178 tsen.TEMP.temperaturel = (BYTE)(at10);
179 sDecodeRXMessage(this, (const unsigned char*)& tsen.TEMP, defaultname.c_str(), BatteryLevel);
180 }
181
SendHumiditySensor(const int NodeID,const int BatteryLevel,const int humidity,const std::string & defaultname,const int RssiLevel)182 void CDomoticzHardwareBase::SendHumiditySensor(const int NodeID, const int BatteryLevel, const int humidity, const std::string& defaultname, const int RssiLevel /* =12 */)
183 {
184 RBUF tsen;
185 memset(&tsen, 0, sizeof(RBUF));
186 tsen.HUM.packetlength = sizeof(tsen.HUM) - 1;
187 tsen.HUM.packettype = pTypeHUM;
188 tsen.HUM.subtype = sTypeHUM1;
189 tsen.HUM.battery_level = BatteryLevel;
190 tsen.HUM.rssi = RssiLevel;
191 tsen.HUM.id1 = (NodeID & 0xFF00) >> 8;
192 tsen.HUM.id2 = NodeID & 0xFF;
193 tsen.HUM.humidity = (BYTE)humidity;
194 tsen.HUM.humidity_status = Get_Humidity_Level(tsen.HUM.humidity);
195 sDecodeRXMessage(this, (const unsigned char*)& tsen.HUM, defaultname.c_str(), BatteryLevel);
196 }
197
SendBaroSensor(const int NodeID,const int ChildID,const int BatteryLevel,const float pressure,const int forecast,const std::string & defaultname)198 void CDomoticzHardwareBase::SendBaroSensor(const int NodeID, const int ChildID, const int BatteryLevel, const float pressure, const int forecast, const std::string& defaultname)
199 {
200 _tGeneralDevice gdevice;
201 gdevice.subtype = sTypeBaro;
202 gdevice.intval1 = (NodeID << 8) | ChildID;
203 gdevice.intval2 = forecast;
204 gdevice.floatval1 = pressure;
205 sDecodeRXMessage(this, (const unsigned char*)& gdevice, defaultname.c_str(), BatteryLevel);
206 }
207
SendTempHumSensor(const int NodeID,const int BatteryLevel,const float temperature,const int humidity,const std::string & defaultname,const int RssiLevel)208 void CDomoticzHardwareBase::SendTempHumSensor(const int NodeID, const int BatteryLevel, const float temperature, const int humidity, const std::string& defaultname, const int RssiLevel /* =12 */)
209 {
210 RBUF tsen;
211 memset(&tsen, 0, sizeof(RBUF));
212 tsen.TEMP_HUM.packetlength = sizeof(tsen.TEMP_HUM) - 1;
213 tsen.TEMP_HUM.packettype = pTypeTEMP_HUM;
214 tsen.TEMP_HUM.subtype = sTypeTH5;
215 tsen.TEMP_HUM.battery_level = BatteryLevel;
216 tsen.TEMP_HUM.rssi = RssiLevel;
217 tsen.TEMP_HUM.id1 = (NodeID & 0xFF00) >> 8;
218 tsen.TEMP_HUM.id2 = NodeID & 0xFF;
219
220 tsen.TEMP_HUM.tempsign = (temperature >= 0) ? 0 : 1;
221 int at10 = round(std::abs(temperature * 10.0f));
222 tsen.TEMP_HUM.temperatureh = (BYTE)(at10 / 256);
223 at10 -= (tsen.TEMP_HUM.temperatureh * 256);
224 tsen.TEMP_HUM.temperaturel = (BYTE)(at10);
225 tsen.TEMP_HUM.humidity = (BYTE)humidity;
226 tsen.TEMP_HUM.humidity_status = Get_Humidity_Level(tsen.TEMP_HUM.humidity);
227
228 sDecodeRXMessage(this, (const unsigned char*)& tsen.TEMP_HUM, defaultname.c_str(), BatteryLevel);
229 }
230
SendTempHumBaroSensor(const int NodeID,const int BatteryLevel,const float temperature,const int humidity,const float pressure,int forecast,const std::string & defaultname,const int RssiLevel)231 void CDomoticzHardwareBase::SendTempHumBaroSensor(const int NodeID, const int BatteryLevel, const float temperature, const int humidity, const float pressure, int forecast, const std::string& defaultname, const int RssiLevel /* =12 */)
232 {
233 RBUF tsen;
234 memset(&tsen, 0, sizeof(RBUF));
235 tsen.TEMP_HUM_BARO.packetlength = sizeof(tsen.TEMP_HUM_BARO) - 1;
236 tsen.TEMP_HUM_BARO.packettype = pTypeTEMP_HUM_BARO;
237 tsen.TEMP_HUM_BARO.subtype = sTypeTHB1;
238 tsen.TEMP_HUM_BARO.battery_level = BatteryLevel;
239 tsen.TEMP_HUM_BARO.rssi = RssiLevel;
240 tsen.TEMP_HUM_BARO.id1 = (NodeID & 0xFF00) >> 8;
241 tsen.TEMP_HUM_BARO.id2 = NodeID & 0xFF;
242
243 tsen.TEMP_HUM_BARO.tempsign = (temperature >= 0) ? 0 : 1;
244 int at10 = round(std::abs(temperature * 10.0f));
245 tsen.TEMP_HUM_BARO.temperatureh = (BYTE)(at10 / 256);
246 at10 -= (tsen.TEMP_HUM_BARO.temperatureh * 256);
247 tsen.TEMP_HUM_BARO.temperaturel = (BYTE)(at10);
248 tsen.TEMP_HUM_BARO.humidity = (BYTE)humidity;
249 tsen.TEMP_HUM_BARO.humidity_status = Get_Humidity_Level(tsen.TEMP_HUM.humidity);
250
251 int ab10 = round(pressure);
252 tsen.TEMP_HUM_BARO.baroh = (BYTE)(ab10 / 256);
253 ab10 -= (tsen.TEMP_HUM_BARO.baroh * 256);
254 tsen.TEMP_HUM_BARO.barol = (BYTE)(ab10);
255
256 tsen.TEMP_HUM_BARO.forecast = (BYTE)forecast;
257
258 sDecodeRXMessage(this, (const unsigned char*)& tsen.TEMP_HUM_BARO, defaultname.c_str(), BatteryLevel);
259 }
260
SendTempHumBaroSensorFloat(const int NodeID,const int BatteryLevel,const float temperature,const int humidity,const float pressure,const uint8_t forecast,const std::string & defaultname,const int RssiLevel)261 void CDomoticzHardwareBase::SendTempHumBaroSensorFloat(const int NodeID, const int BatteryLevel, const float temperature, const int humidity, const float pressure, const uint8_t forecast, const std::string& defaultname, const int RssiLevel /* =12 */)
262 {
263 RBUF tsen;
264 memset(&tsen, 0, sizeof(RBUF));
265 tsen.TEMP_HUM_BARO.packetlength = sizeof(tsen.TEMP_HUM_BARO) - 1;
266 tsen.TEMP_HUM_BARO.packettype = pTypeTEMP_HUM_BARO;
267 tsen.TEMP_HUM_BARO.subtype = sTypeTHBFloat;
268 tsen.TEMP_HUM_BARO.battery_level = 9;
269 tsen.TEMP_HUM_BARO.rssi = RssiLevel;
270 tsen.TEMP_HUM_BARO.id1 = (NodeID & 0xFF00) >> 8;
271 tsen.TEMP_HUM_BARO.id2 = NodeID & 0xFF;
272
273 tsen.TEMP_HUM_BARO.tempsign = (temperature >= 0) ? 0 : 1;
274 int at10 = round(std::abs(temperature * 10.0f));
275 tsen.TEMP_HUM_BARO.temperatureh = (BYTE)(at10 / 256);
276 at10 -= (tsen.TEMP_HUM_BARO.temperatureh * 256);
277 tsen.TEMP_HUM_BARO.temperaturel = (BYTE)(at10);
278 tsen.TEMP_HUM_BARO.humidity = (BYTE)humidity;
279 tsen.TEMP_HUM_BARO.humidity_status = Get_Humidity_Level(tsen.TEMP_HUM.humidity);
280
281 int ab10 = round(pressure * 10.0f);
282 tsen.TEMP_HUM_BARO.baroh = (BYTE)(ab10 / 256);
283 ab10 -= (tsen.TEMP_HUM_BARO.baroh * 256);
284 tsen.TEMP_HUM_BARO.barol = (BYTE)(ab10);
285 tsen.TEMP_HUM_BARO.forecast = forecast;
286
287 sDecodeRXMessage(this, (const unsigned char*)& tsen.TEMP_HUM_BARO, defaultname.c_str(), BatteryLevel);
288 }
289
SendTempBaroSensor(const uint8_t NodeID,const int BatteryLevel,const float temperature,const float pressure,const std::string & defaultname)290 void CDomoticzHardwareBase::SendTempBaroSensor(const uint8_t NodeID, const int BatteryLevel, const float temperature, const float pressure, const std::string& defaultname)
291 {
292 _tTempBaro tsensor;
293 tsensor.id1 = NodeID;
294 tsensor.temp = temperature;
295 tsensor.baro = pressure;
296 tsensor.altitude = 188;
297
298 //this is probably not good, need to take the rising/falling of the pressure into account?
299 //any help would be welcome!
300
301 tsensor.forecast = baroForecastNoInfo;
302 if (tsensor.baro < 1000)
303 tsensor.forecast = baroForecastRain;
304 else if (tsensor.baro < 1020)
305 tsensor.forecast = baroForecastCloudy;
306 else if (tsensor.baro < 1030)
307 tsensor.forecast = baroForecastPartlyCloudy;
308 else
309 tsensor.forecast = baroForecastSunny;
310 sDecodeRXMessage(this, (const unsigned char*)& tsensor, defaultname.c_str(), BatteryLevel);
311 }
312
SendSetPointSensor(const uint8_t NodeID,const uint8_t ChildID,const unsigned char SensorID,const float Temp,const std::string & defaultname)313 void CDomoticzHardwareBase::SendSetPointSensor(const uint8_t NodeID, const uint8_t ChildID, const unsigned char SensorID, const float Temp, const std::string& defaultname)
314 {
315 _tThermostat thermos;
316 thermos.subtype = sTypeThermSetpoint;
317 thermos.id1 = 0;
318 thermos.id2 = NodeID;
319 thermos.id3 = ChildID;
320 thermos.id4 = SensorID;
321 thermos.dunit = 1;
322
323 thermos.temp = Temp;
324
325 sDecodeRXMessage(this, (const unsigned char*)& thermos, defaultname.c_str(), -1);
326 }
327
328
SendDistanceSensor(const int NodeID,const int ChildID,const int BatteryLevel,const float distance,const std::string & defaultname)329 void CDomoticzHardwareBase::SendDistanceSensor(const int NodeID, const int ChildID, const int BatteryLevel, const float distance, const std::string& defaultname)
330 {
331 _tGeneralDevice gdevice;
332 gdevice.subtype = sTypeDistance;
333 gdevice.intval1 = (NodeID << 8) | ChildID;
334 gdevice.floatval1 = distance;
335 sDecodeRXMessage(this, (const unsigned char*)& gdevice, defaultname.c_str(), BatteryLevel);
336 }
337
SendTextSensor(const int NodeID,const int ChildID,const int BatteryLevel,const std::string & textMessage,const std::string & defaultname)338 void CDomoticzHardwareBase::SendTextSensor(const int NodeID, const int ChildID, const int BatteryLevel, const std::string& textMessage, const std::string& defaultname)
339 {
340 _tGeneralDevice gdevice;
341 gdevice.subtype = sTypeTextStatus;
342 gdevice.intval1 = (NodeID << 8) | ChildID;
343 std::string sstatus = textMessage;
344 if (sstatus.size() > 63)
345 sstatus = sstatus.substr(0, 63);
346 strcpy(gdevice.text, sstatus.c_str());
347 sDecodeRXMessage(this, (const unsigned char*)& gdevice, defaultname.c_str(), BatteryLevel);
348 }
349
GetTextSensorText(const int NodeID,const int ChildID,bool & bExists)350 std::string CDomoticzHardwareBase::GetTextSensorText(const int NodeID, const int ChildID, bool& bExists)
351 {
352 bExists = false;
353 std::string ret = "";
354
355 std::vector<std::vector<std::string> > result;
356
357 char szTmp[30];
358 sprintf(szTmp, "%08X", (NodeID << 8) | ChildID);
359
360 result = m_sql.safe_query("SELECT sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Type==%d) AND (Subtype==%d)",
361 m_HwdID, szTmp, int(pTypeGeneral), int(sTypeTextStatus));
362 if (!result.empty())
363 {
364 bExists = true;
365 ret = result[0][0];
366 }
367 return ret;
368 }
369
SendRainSensor(const int NodeID,const int BatteryLevel,const float RainCounter,const std::string & defaultname,const int RssiLevel)370 void CDomoticzHardwareBase::SendRainSensor(const int NodeID, const int BatteryLevel, const float RainCounter, const std::string& defaultname, const int RssiLevel /* =12 */)
371 {
372 RBUF tsen;
373 memset(&tsen, 0, sizeof(RBUF));
374 tsen.RAIN.packetlength = sizeof(tsen.RAIN) - 1;
375 tsen.RAIN.packettype = pTypeRAIN;
376 tsen.RAIN.subtype = sTypeRAIN3;
377 tsen.RAIN.battery_level = BatteryLevel;
378 tsen.RAIN.rssi = RssiLevel;
379 tsen.RAIN.id1 = (NodeID & 0xFF00) >> 8;
380 tsen.RAIN.id2 = NodeID & 0xFF;
381
382 tsen.RAIN.rainrateh = 0;
383 tsen.RAIN.rainratel = 0;
384
385 uint64_t tr10 = int((float(RainCounter) * 10.0f));
386
387 tsen.RAIN.raintotal1 = (BYTE)(tr10 / 65535);
388 tr10 -= (tsen.RAIN.raintotal1 * 65535);
389 tsen.RAIN.raintotal2 = (BYTE)(tr10 / 256);
390 tr10 -= (tsen.RAIN.raintotal2 * 256);
391 tsen.RAIN.raintotal3 = (BYTE)(tr10);
392 sDecodeRXMessage(this, (const unsigned char*)& tsen.RAIN, defaultname.c_str(), BatteryLevel);
393 }
394
SendRainSensorWU(const int NodeID,const int BatteryLevel,const float RainCounter,const float LastHour,const std::string & defaultname,const int RssiLevel)395 void CDomoticzHardwareBase::SendRainSensorWU(const int NodeID, const int BatteryLevel, const float RainCounter, const float LastHour, const std::string& defaultname, const int RssiLevel)
396 {
397 RBUF tsen;
398 memset(&tsen, 0, sizeof(RBUF));
399 tsen.RAIN.packetlength = sizeof(tsen.RAIN) - 1;
400 tsen.RAIN.packettype = pTypeRAIN;
401 tsen.RAIN.subtype = sTypeRAINWU;
402 tsen.RAIN.battery_level = 9;
403 tsen.RAIN.rssi = 12;
404 tsen.RAIN.id1 = 0;
405 tsen.RAIN.id2 = 1;
406
407 tsen.RAIN.rainrateh = 0;
408 tsen.RAIN.rainratel = 0;
409
410 if (LastHour != 0)
411 {
412 uint64_t at10 = int((float(LastHour) * 10.0f));
413 tsen.RAIN.rainrateh = (BYTE)(at10 / 256);
414 at10 -= (tsen.RAIN.rainrateh * 256);
415 tsen.RAIN.rainratel = (BYTE)(at10);
416 }
417
418 int tr10 = int((float(RainCounter) * 10.0f));
419 tsen.RAIN.raintotal1 = 0;
420 tsen.RAIN.raintotal2 = (BYTE)(tr10 / 256);
421 tr10 -= (tsen.RAIN.raintotal2 * 256);
422 tsen.RAIN.raintotal3 = (BYTE)(tr10);
423
424 sDecodeRXMessage(this, (const unsigned char*)& tsen.RAIN, defaultname.c_str(), BatteryLevel);
425 }
426
SendRainRateSensor(const int NodeID,const int BatteryLevel,const float RainRate,const std::string & defaultname,const int RssiLevel)427 void CDomoticzHardwareBase::SendRainRateSensor(const int NodeID, const int BatteryLevel, const float RainRate, const std::string& defaultname, const int RssiLevel /* =12 */)
428 {
429 RBUF tsen;
430 memset(&tsen, 0, sizeof(RBUF));
431 tsen.RAIN.packetlength = sizeof(tsen.RAIN) - 1;
432 tsen.RAIN.packettype = pTypeRAIN;
433 tsen.RAIN.subtype = sTypeRAINByRate;
434 tsen.RAIN.battery_level = BatteryLevel;
435 tsen.RAIN.rssi = RssiLevel;
436 tsen.RAIN.id1 = (NodeID & 0xFF00) >> 8;
437 tsen.RAIN.id2 = NodeID & 0xFF;
438
439 int at10 = round(std::abs(RainRate * 10000.0f));
440 tsen.RAIN.rainrateh = (BYTE)(at10 / 256);
441 at10 -= (tsen.RAIN.rainrateh * 256);
442 tsen.RAIN.rainratel = (BYTE)(at10);
443
444 tsen.RAIN.raintotal1 = 0;
445 tsen.RAIN.raintotal2 = 0;
446 tsen.RAIN.raintotal3 = 0;
447
448 sDecodeRXMessage(this, (const unsigned char*)& tsen.RAIN, defaultname.c_str(), BatteryLevel);
449 }
450
GetRainSensorValue(const int NodeID,bool & bExists)451 float CDomoticzHardwareBase::GetRainSensorValue(const int NodeID, bool& bExists)
452 {
453 char szIdx[10];
454 sprintf(szIdx, "%d", NodeID & 0xFFFF);
455 int Unit = 0;
456
457 std::vector<std::vector<std::string> > results;
458 results = m_sql.safe_query("SELECT ID,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit == %d) AND (Type==%d) AND (Subtype==%d)", m_HwdID, szIdx, Unit, int(pTypeRAIN), int(sTypeRAIN3));
459 if (results.size() < 1)
460 {
461 bExists = false;
462 return 0.0f;
463 }
464 std::vector<std::string> splitresults;
465 StringSplit(results[0][1], ";", splitresults);
466 if (splitresults.size() != 2)
467 {
468 bExists = false;
469 return 0.0f;
470 }
471 bExists = true;
472 return (float)atof(splitresults[1].c_str());
473 }
474
GetWindSensorValue(const int NodeID,int & WindDir,float & WindSpeed,float & WindGust,float & WindTemp,float & WindChill,bool bHaveWindTemp,bool & bExists)475 bool CDomoticzHardwareBase::GetWindSensorValue(const int NodeID, int& WindDir, float& WindSpeed, float& WindGust, float& WindTemp, float& WindChill, bool bHaveWindTemp, bool& bExists)
476 {
477 char szIdx[10];
478 sprintf(szIdx, "%d", NodeID & 0xFFFF);
479 int Unit = 0;
480
481 std::vector<std::vector<std::string> > results;
482 if (!bHaveWindTemp)
483 results = m_sql.safe_query("SELECT ID,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit == %d) AND (Type==%d) AND (Subtype==%d)", m_HwdID, szIdx, Unit, int(pTypeWIND), int(sTypeWINDNoTemp));
484 else
485 results = m_sql.safe_query("SELECT ID,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit == %d) AND (Type==%d) AND (Subtype==%d)", m_HwdID, szIdx, Unit, int(pTypeWIND), int(sTypeWIND4));
486 if (results.size() < 1)
487 {
488 bExists = false;
489 return 0.0f;
490 }
491 std::vector<std::string> splitresults;
492 StringSplit(results[0][1], ";", splitresults);
493
494 if (splitresults.size() != 6)
495 {
496 bExists = false;
497 return 0.0f;
498 }
499 bExists = true;
500 WindDir = (int)atof(splitresults[0].c_str());
501 WindSpeed = (float)atof(splitresults[2].c_str());
502 WindGust = (float)atof(splitresults[3].c_str());
503 WindTemp = (float)atof(splitresults[4].c_str());
504 WindChill = (float)atof(splitresults[5].c_str());
505 return bExists;
506 }
507
SendWattMeter(const uint8_t NodeID,const uint8_t ChildID,const int BatteryLevel,const float musage,const std::string & defaultname)508 void CDomoticzHardwareBase::SendWattMeter(const uint8_t NodeID, const uint8_t ChildID, const int BatteryLevel, const float musage, const std::string& defaultname)
509 {
510 _tUsageMeter umeter;
511 umeter.id1 = 0;
512 umeter.id2 = 0;
513 umeter.id3 = 0;
514 umeter.id4 = NodeID;
515 umeter.dunit = ChildID;
516 umeter.fusage = musage;
517 sDecodeRXMessage(this, (const unsigned char*)& umeter, defaultname.c_str(), BatteryLevel);
518 }
519
520 //Obsolete, we should not call this anymore
521 //when all calls are removed, we should delete this function
SendKwhMeterOldWay(const int NodeID,const int ChildID,const int BatteryLevel,const double musage,const double mtotal,const std::string & defaultname)522 void CDomoticzHardwareBase::SendKwhMeterOldWay(const int NodeID, const int ChildID, const int BatteryLevel, const double musage, const double mtotal, const std::string& defaultname)
523 {
524 SendKwhMeter(NodeID, ChildID, BatteryLevel, musage * 1000, mtotal, defaultname);
525 }
526
SendKwhMeter(const int NodeID,const int ChildID,const int BatteryLevel,const double musage,const double mtotal,const std::string & defaultname)527 void CDomoticzHardwareBase::SendKwhMeter(const int NodeID, const int ChildID, const int BatteryLevel, const double musage, const double mtotal, const std::string& defaultname)
528 {
529 _tGeneralDevice gdevice;
530 gdevice.subtype = sTypeKwh;
531 gdevice.intval1 = (NodeID << 8) | ChildID;
532 gdevice.floatval1 = (float)musage;
533 gdevice.floatval2 = (float)(mtotal * 1000.0);
534 sDecodeRXMessage(this, (const unsigned char*)& gdevice, defaultname.c_str(), BatteryLevel);
535 }
536
GetKwhMeter(const int NodeID,const int ChildID,bool & bExists)537 double CDomoticzHardwareBase::GetKwhMeter(const int NodeID, const int ChildID, bool& bExists)
538 {
539 int dID = (NodeID << 8) | ChildID;
540 char szTmp[30];
541 sprintf(szTmp, "%08X", dID);
542
543 std::vector<std::vector<std::string> > result;
544 result = m_sql.safe_query("SELECT ID FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Type==%d) AND (Subtype==%d)",
545 m_HwdID, szTmp, int(pTypeGeneral), int(sTypeKwh));
546 if (result.empty())
547 {
548 bExists = false;
549 return 0;
550 }
551 result = m_sql.safe_query("SELECT MAX(Counter) FROM Meter_Calendar WHERE (DeviceRowID=='%q')", result[0][0].c_str());
552 if (result.empty())
553 {
554 bExists = false;
555 return 0.0f;
556 }
557 bExists = true;
558 return (float)atof(result[0][0].c_str());
559 }
560
SendMeterSensor(const int NodeID,const int ChildID,const int BatteryLevel,const float metervalue,const std::string & defaultname,const int RssiLevel)561 void CDomoticzHardwareBase::SendMeterSensor(const int NodeID, const int ChildID, const int BatteryLevel, const float metervalue, const std::string& defaultname, const int RssiLevel /* =12 */)
562 {
563 unsigned long counter = (unsigned long)(metervalue * 1000.0f);
564 RBUF tsen;
565 memset(&tsen, 0, sizeof(RBUF));
566 tsen.RFXMETER.packetlength = sizeof(tsen.RFXMETER) - 1;
567 tsen.RFXMETER.packettype = pTypeRFXMeter;
568 tsen.RFXMETER.subtype = sTypeRFXMeterCount;
569 tsen.RFXMETER.rssi = RssiLevel;
570 tsen.RFXMETER.id1 = (BYTE)NodeID;
571 tsen.RFXMETER.id2 = (BYTE)ChildID;
572
573 tsen.RFXMETER.count1 = (BYTE)((counter & 0xFF000000) >> 24);
574 tsen.RFXMETER.count2 = (BYTE)((counter & 0x00FF0000) >> 16);
575 tsen.RFXMETER.count3 = (BYTE)((counter & 0x0000FF00) >> 8);
576 tsen.RFXMETER.count4 = (BYTE)(counter & 0x000000FF);
577 sDecodeRXMessage(this, (const unsigned char*)& tsen.RFXMETER, defaultname.c_str(), BatteryLevel);
578 }
579
SendLuxSensor(const uint8_t NodeID,const uint8_t ChildID,const uint8_t BatteryLevel,const float Lux,const std::string & defaultname)580 void CDomoticzHardwareBase::SendLuxSensor(const uint8_t NodeID, const uint8_t ChildID, const uint8_t BatteryLevel, const float Lux, const std::string& defaultname)
581 {
582 _tLightMeter lmeter;
583 lmeter.id1 = 0;
584 lmeter.id2 = 0;
585 lmeter.id3 = 0;
586 lmeter.id4 = NodeID;
587 lmeter.dunit = ChildID;
588 lmeter.fLux = Lux;
589 lmeter.battery_level = BatteryLevel;
590 sDecodeRXMessage(this, (const unsigned char*)& lmeter, defaultname.c_str(), BatteryLevel);
591 }
592
SendAirQualitySensor(const uint8_t NodeID,const uint8_t ChildID,const int BatteryLevel,const int AirQuality,const std::string & defaultname)593 void CDomoticzHardwareBase::SendAirQualitySensor(const uint8_t NodeID, const uint8_t ChildID, const int BatteryLevel, const int AirQuality, const std::string& defaultname)
594 {
595 _tAirQualityMeter meter;
596 meter.len = sizeof(_tAirQualityMeter) - 1;
597 meter.type = pTypeAirQuality;
598 meter.subtype = sTypeVoltcraft;
599 meter.airquality = AirQuality;
600 meter.id1 = NodeID;
601 meter.id2 = ChildID;
602 sDecodeRXMessage(this, (const unsigned char*)& meter, defaultname.c_str(), BatteryLevel);
603 }
604
SendUsageSensor(const uint8_t NodeID,const uint8_t ChildID,const int BatteryLevel,const float Usage,const std::string & defaultname)605 void CDomoticzHardwareBase::SendUsageSensor(const uint8_t NodeID, const uint8_t ChildID, const int BatteryLevel, const float Usage, const std::string& defaultname)
606 {
607 _tUsageMeter umeter;
608 umeter.id1 = 0;
609 umeter.id2 = 0;
610 umeter.id3 = 0;
611 umeter.id4 = NodeID;
612 umeter.dunit = ChildID;
613 umeter.fusage = Usage;
614 sDecodeRXMessage(this, (const unsigned char*)& umeter, defaultname.c_str(), BatteryLevel);
615 }
616
SendSwitchIfNotExists(const int NodeID,const uint8_t ChildID,const int BatteryLevel,const bool bOn,const double Level,const std::string & defaultname)617 void CDomoticzHardwareBase::SendSwitchIfNotExists(const int NodeID, const uint8_t ChildID, const int BatteryLevel, const bool bOn, const double Level, const std::string& defaultname)
618 {
619 //make device ID
620 unsigned char ID1 = (unsigned char)((NodeID & 0xFF000000) >> 24);
621 unsigned char ID2 = (unsigned char)((NodeID & 0xFF0000) >> 16);
622 unsigned char ID3 = (unsigned char)((NodeID & 0xFF00) >> 8);
623 unsigned char ID4 = (unsigned char)NodeID & 0xFF;
624
625 char szIdx[10];
626 sprintf(szIdx, "%X%02X%02X%02X", ID1, ID2, ID3, ID4);
627 std::vector<std::vector<std::string> > result;
628 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)",
629 m_HwdID, szIdx, ChildID, int(pTypeLighting2), int(sTypeAC));
630 if (result.empty())
631 {
632 SendSwitch(NodeID, ChildID, BatteryLevel, bOn, Level, defaultname);
633 }
634 }
635
SendSwitchUnchecked(const int NodeID,const uint8_t ChildID,const int BatteryLevel,const bool bOn,const double Level,const std::string & defaultname,const int RssiLevel)636 void CDomoticzHardwareBase::SendSwitchUnchecked(const int NodeID, const uint8_t ChildID, const int BatteryLevel, const bool bOn, const double Level, const std::string& defaultname, const int RssiLevel /* =12 */)
637 {
638 double rlevel = (16.0 / 100.0) * Level;
639 uint8_t level = (uint8_t)(rlevel);
640
641 //make device ID
642 unsigned char ID1 = (unsigned char)((NodeID & 0xFF000000) >> 24);
643 unsigned char ID2 = (unsigned char)((NodeID & 0xFF0000) >> 16);
644 unsigned char ID3 = (unsigned char)((NodeID & 0xFF00) >> 8);
645 unsigned char ID4 = (unsigned char)NodeID & 0xFF;
646
647 //Send as Lighting 2
648 tRBUF lcmd;
649 memset(&lcmd, 0, sizeof(RBUF));
650 lcmd.LIGHTING2.packetlength = sizeof(lcmd.LIGHTING2) - 1;
651 lcmd.LIGHTING2.packettype = pTypeLighting2;
652 lcmd.LIGHTING2.subtype = sTypeAC;
653 lcmd.LIGHTING2.id1 = ID1;
654 lcmd.LIGHTING2.id2 = ID2;
655 lcmd.LIGHTING2.id3 = ID3;
656 lcmd.LIGHTING2.id4 = ID4;
657 lcmd.LIGHTING2.unitcode = ChildID;
658 if (!bOn)
659 {
660 lcmd.LIGHTING2.cmnd = light2_sOff;
661 }
662 else
663 {
664 if (level != 0)
665 lcmd.LIGHTING2.cmnd = light2_sSetLevel;
666 else
667 lcmd.LIGHTING2.cmnd = light2_sOn;
668 }
669 lcmd.LIGHTING2.level = level;
670 lcmd.LIGHTING2.filler = 0;
671 lcmd.LIGHTING2.rssi = RssiLevel;
672 sDecodeRXMessage(this, (const unsigned char*)& lcmd.LIGHTING2, defaultname.c_str(), BatteryLevel);
673 }
674
675
SendSwitch(const int NodeID,const uint8_t ChildID,const int BatteryLevel,const bool bOn,const double Level,const std::string & defaultname,const int RssiLevel)676 void CDomoticzHardwareBase::SendSwitch(const int NodeID, const uint8_t ChildID, const int BatteryLevel, const bool bOn, const double Level, const std::string& defaultname, const int RssiLevel /* =12 */)
677 {
678 double rlevel = (16.0 / 100.0) * Level;
679 int level = int(rlevel);
680
681 //make device ID
682 unsigned char ID1 = (unsigned char)((NodeID & 0xFF000000) >> 24);
683 unsigned char ID2 = (unsigned char)((NodeID & 0xFF0000) >> 16);
684 unsigned char ID3 = (unsigned char)((NodeID & 0xFF00) >> 8);
685 unsigned char ID4 = (unsigned char)NodeID & 0xFF;
686
687 char szIdx[10];
688 sprintf(szIdx, "%X%02X%02X%02X", ID1, ID2, ID3, ID4);
689 std::vector<std::vector<std::string> > result;
690 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)",
691 m_HwdID, szIdx, ChildID, int(pTypeLighting2), int(sTypeAC));
692 if (!result.empty())
693 {
694 //check if we have a change, if not do not update it
695 int nvalue = atoi(result[0][1].c_str());
696 if ((!bOn) && (nvalue == light2_sOff))
697 return;
698 if ((bOn && (nvalue != light2_sOff)))
699 {
700 //Check Level
701 int slevel = atoi(result[0][2].c_str());
702 if (slevel == level)
703 return;
704 }
705 }
706 SendSwitchUnchecked(NodeID, ChildID, BatteryLevel, bOn, Level, defaultname, RssiLevel);
707 }
708
SendBlindSensor(const uint8_t NodeID,const uint8_t ChildID,const int BatteryLevel,const uint8_t Command,const std::string & defaultname,const int RssiLevel)709 void CDomoticzHardwareBase::SendBlindSensor(const uint8_t NodeID, const uint8_t ChildID, const int BatteryLevel, const uint8_t Command, const std::string& defaultname, const int RssiLevel /* =12 */)
710 {
711 //Send as Blinds
712 tRBUF lcmd;
713 memset(&lcmd, 0, sizeof(RBUF));
714 lcmd.BLINDS1.packetlength = sizeof(lcmd.LIGHTING2) - 1;
715 lcmd.BLINDS1.packettype = pTypeBlinds;
716 lcmd.BLINDS1.subtype = sTypeBlindsT0;
717 lcmd.BLINDS1.id1 = 0;
718 lcmd.BLINDS1.id2 = 0;
719 lcmd.BLINDS1.id3 = NodeID;
720 lcmd.BLINDS1.id4 = 0;
721 lcmd.BLINDS1.unitcode = ChildID;
722 lcmd.BLINDS1.cmnd = Command;
723 lcmd.BLINDS1.filler = 0;
724 lcmd.BLINDS1.rssi = RssiLevel;
725 sDecodeRXMessage(this, (const unsigned char*)& lcmd.BLINDS1, defaultname.c_str(), BatteryLevel);
726 }
727
SendRGBWSwitch(const int NodeID,const uint8_t ChildID,const int BatteryLevel,const int Level,const bool bIsRGBW,const std::string & defaultname)728 void CDomoticzHardwareBase::SendRGBWSwitch(const int NodeID, const uint8_t ChildID, const int BatteryLevel, const int Level, const bool bIsRGBW, const std::string& defaultname)
729 {
730 int level = int(Level);
731 uint8_t subType = (bIsRGBW == true) ? sTypeColor_RGB_W : sTypeColor_RGB;
732 if (defaultname == "LIVCOL")
733 subType = sTypeColor_LivCol;
734 //Send as ColorSwitch
735 _tColorSwitch lcmd;
736 lcmd.id = NodeID;
737 lcmd.subtype = subType;
738 if (level == 0)
739 lcmd.command = Color_LedOff;
740 else
741 lcmd.command = Color_LedOn;
742 lcmd.dunit = ChildID;
743 lcmd.value = (uint32_t)level;
744 sDecodeRXMessage(this, (const unsigned char*)& lcmd, defaultname.c_str(), BatteryLevel);
745 }
746
SendVoltageSensor(const int NodeID,const uint32_t ChildID,const int BatteryLevel,const float Volt,const std::string & defaultname)747 void CDomoticzHardwareBase::SendVoltageSensor(const int NodeID, const uint32_t ChildID, const int BatteryLevel, const float Volt, const std::string& defaultname)
748 {
749 _tGeneralDevice gDevice;
750 gDevice.subtype = sTypeVoltage;
751 gDevice.id = ChildID;
752 gDevice.intval1 = (NodeID << 8) | ChildID;
753 gDevice.floatval1 = Volt;
754 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
755 }
756
SendCurrentSensor(const int NodeID,const int BatteryLevel,const float Current1,const float Current2,const float Current3,const std::string & defaultname,const int RssiLevel)757 void CDomoticzHardwareBase::SendCurrentSensor(const int NodeID, const int BatteryLevel, const float Current1, const float Current2, const float Current3, const std::string& defaultname, const int RssiLevel /* =12 */)
758 {
759 tRBUF tsen;
760 memset(&tsen, 0, sizeof(RBUF));
761 tsen.CURRENT.packetlength = sizeof(tsen.CURRENT) - 1;
762 tsen.CURRENT.packettype = pTypeCURRENT;
763 tsen.CURRENT.subtype = sTypeELEC1;
764 tsen.CURRENT.rssi = RssiLevel;
765 tsen.CURRENT.id1 = (NodeID & 0xFF00) >> 8;
766 tsen.CURRENT.id2 = NodeID & 0xFF;
767 tsen.CURRENT.battery_level = BatteryLevel;
768
769 int at10 = round(std::abs(Current1 * 10.0f));
770 tsen.CURRENT.ch1h = (BYTE)(at10 / 256);
771 at10 -= (tsen.TEMP.temperatureh * 256);
772 tsen.CURRENT.ch1l = (BYTE)(at10);
773
774 at10 = round(std::abs(Current2 * 10.0f));
775 tsen.CURRENT.ch2h = (BYTE)(at10 / 256);
776 at10 -= (tsen.TEMP.temperatureh * 256);
777 tsen.CURRENT.ch2l = (BYTE)(at10);
778
779 at10 = round(std::abs(Current3 * 10.0f));
780 tsen.CURRENT.ch3h = (BYTE)(at10 / 256);
781 at10 -= (tsen.TEMP.temperatureh * 256);
782 tsen.CURRENT.ch3l = (BYTE)(at10);
783
784 sDecodeRXMessage(this, (const unsigned char*)& tsen.CURRENT, defaultname.c_str(), BatteryLevel);
785 }
786
SendPercentageSensor(const int NodeID,const uint8_t ChildID,const int BatteryLevel,const float Percentage,const std::string & defaultname)787 void CDomoticzHardwareBase::SendPercentageSensor(const int NodeID, const uint8_t ChildID, const int BatteryLevel, const float Percentage, const std::string& defaultname)
788 {
789 _tGeneralDevice gDevice;
790 gDevice.subtype = sTypePercentage;
791 gDevice.id = ChildID;
792 gDevice.intval1 = NodeID;
793 gDevice.floatval1 = Percentage;
794 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
795 }
796
CheckPercentageSensorExists(const int NodeID,const int)797 bool CDomoticzHardwareBase::CheckPercentageSensorExists(const int NodeID, const int /*ChildID*/)
798 {
799 std::vector<std::vector<std::string> > result;
800 char szTmp[30];
801 sprintf(szTmp, "%08X", (unsigned int)NodeID);
802 result = m_sql.safe_query("SELECT Name FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Type==%d) AND (Subtype==%d)",
803 m_HwdID, szTmp, int(pTypeGeneral), int(sTypePercentage));
804 return (!result.empty());
805 }
806
SendWaterflowSensor(const int NodeID,const uint8_t ChildID,const int BatteryLevel,const float LPM,const std::string & defaultname)807 void CDomoticzHardwareBase::SendWaterflowSensor(const int NodeID, const uint8_t ChildID, const int BatteryLevel, const float LPM, const std::string& defaultname)
808 {
809 _tGeneralDevice gDevice;
810 gDevice.subtype = sTypeWaterflow;
811 gDevice.id = ChildID;
812 gDevice.intval1 = (NodeID << 8) | ChildID;
813 gDevice.floatval1 = LPM;
814 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
815 }
816
SendVisibilitySensor(const int NodeID,const int ChildID,const int BatteryLevel,const float Visibility,const std::string & defaultname)817 void CDomoticzHardwareBase::SendVisibilitySensor(const int NodeID, const int ChildID, const int BatteryLevel, const float Visibility, const std::string& defaultname)
818 {
819 _tGeneralDevice gDevice;
820 gDevice.subtype = sTypeVisibility;
821 gDevice.id = ChildID;
822 gDevice.intval1 = (NodeID << 8) | ChildID;
823 gDevice.floatval1 = Visibility;
824 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
825 }
826
SendCustomSensor(const int NodeID,const uint8_t ChildID,const int BatteryLevel,const float CustomValue,const std::string & defaultname,const std::string & defaultLabel)827 void CDomoticzHardwareBase::SendCustomSensor(const int NodeID, const uint8_t ChildID, const int BatteryLevel, const float CustomValue, const std::string& defaultname, const std::string& defaultLabel)
828 {
829
830 _tGeneralDevice gDevice;
831 gDevice.subtype = sTypeCustom;
832 gDevice.id = ChildID;
833 gDevice.intval1 = (NodeID << 8) | ChildID;
834 gDevice.floatval1 = CustomValue;
835
836 char szTmp[9];
837 sprintf(szTmp, "%08X", gDevice.intval1);
838 std::vector<std::vector<std::string> > result;
839 result = m_sql.safe_query("SELECT Name FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Type==%d) AND (Subtype==%d)",
840 m_HwdID, szTmp, int(pTypeGeneral), int(sTypeCustom));
841 bool bDoesExists = !result.empty();
842
843 if (bDoesExists)
844 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
845 else
846 {
847 m_mainworker.PushAndWaitRxMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
848 //Set the Label
849 std::string soptions = "1;" + defaultLabel;
850 m_sql.safe_query("UPDATE DeviceStatus SET Options='%q' WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Type==%d) AND (Subtype==%d)",
851 soptions.c_str(), m_HwdID, szTmp, int(pTypeGeneral), int(sTypeCustom));
852 }
853 }
854
855 //wind direction is in steps of 22.5 degrees (360/16)
SendWind(const int NodeID,const int BatteryLevel,const int WindDir,const float WindSpeed,const float WindGust,const float WindTemp,const float WindChill,const bool bHaveWindTemp,const bool bHaveWindChill,const std::string & defaultname,const int RssiLevel)856 void CDomoticzHardwareBase::SendWind(const int NodeID, const int BatteryLevel, const int WindDir, const float WindSpeed, const float WindGust, const float WindTemp, const float WindChill, const bool bHaveWindTemp, const bool bHaveWindChill, const std::string& defaultname, const int RssiLevel /* =12 */)
857 {
858 RBUF tsen;
859 memset(&tsen, 0, sizeof(RBUF));
860 tsen.WIND.packetlength = sizeof(tsen.WIND) - 1;
861 tsen.WIND.packettype = pTypeWIND;
862
863 if ((!bHaveWindTemp) && (!bHaveWindChill))
864 tsen.WIND.subtype = sTypeWINDNoTempNoChill;
865 else if (!bHaveWindTemp)
866 tsen.WIND.subtype = sTypeWINDNoTemp;
867 else
868 tsen.WIND.subtype = sTypeWIND4;
869
870 tsen.WIND.battery_level = BatteryLevel;
871 tsen.WIND.rssi = RssiLevel;
872 tsen.WIND.id1 = (NodeID & 0xFF00) >> 8;
873 tsen.WIND.id2 = NodeID & 0xFF;
874
875 int aw = WindDir;
876 tsen.WIND.directionh = (BYTE)(aw / 256);
877 aw -= (tsen.WIND.directionh * 256);
878 tsen.WIND.directionl = (BYTE)(aw);
879
880 int sw = round(WindSpeed * 10.0f);
881 tsen.WIND.av_speedh = (BYTE)(sw / 256);
882 sw -= (tsen.WIND.av_speedh * 256);
883 tsen.WIND.av_speedl = (BYTE)(sw);
884
885 int gw = round(WindGust * 10.0f);
886 tsen.WIND.gusth = (BYTE)(gw / 256);
887 gw -= (tsen.WIND.gusth * 256);
888 tsen.WIND.gustl = (BYTE)(gw);
889
890 if (!bHaveWindTemp)
891 {
892 //No temp, only chill
893 tsen.WIND.tempsign = (WindChill >= 0) ? 0 : 1;
894 tsen.WIND.chillsign = (WindChill >= 0) ? 0 : 1;
895 int at10 = round(std::abs(WindChill * 10.0f));
896 tsen.WIND.temperatureh = (BYTE)(at10 / 256);
897 tsen.WIND.chillh = (BYTE)(at10 / 256);
898 at10 -= (tsen.WIND.chillh * 256);
899 tsen.WIND.temperaturel = (BYTE)(at10);
900 tsen.WIND.chilll = (BYTE)(at10);
901 }
902 else
903 {
904 //temp+chill
905 tsen.WIND.tempsign = (WindTemp >= 0) ? 0 : 1;
906 int at10 = round(std::abs(WindTemp * 10.0f));
907 tsen.WIND.temperatureh = (BYTE)(at10 / 256);
908 at10 -= (tsen.WIND.temperatureh * 256);
909 tsen.WIND.temperaturel = (BYTE)(at10);
910
911 tsen.WIND.chillsign = (WindChill >= 0) ? 0 : 1;
912 at10 = round(std::abs(WindChill * 10.0f));
913 tsen.WIND.chillh = (BYTE)(at10 / 256);
914 at10 -= (tsen.WIND.chillh * 256);
915 tsen.WIND.chilll = (BYTE)(at10);
916 }
917
918 sDecodeRXMessage(this, (const unsigned char*)& tsen.WIND, defaultname.c_str(), BatteryLevel);
919 }
920
SendPressureSensor(const int NodeID,const int ChildID,const int BatteryLevel,const float pressure,const std::string & defaultname)921 void CDomoticzHardwareBase::SendPressureSensor(const int NodeID, const int ChildID, const int BatteryLevel, const float pressure, const std::string& defaultname)
922 {
923 _tGeneralDevice gdevice;
924 gdevice.subtype = sTypePressure;
925 gdevice.intval1 = (NodeID << 8) | ChildID;
926 gdevice.floatval1 = pressure;
927 sDecodeRXMessage(this, (const unsigned char*)& gdevice, defaultname.c_str(), BatteryLevel);
928 }
929
SendSolarRadiationSensor(const unsigned char NodeID,const int BatteryLevel,const float radiation,const std::string & defaultname)930 void CDomoticzHardwareBase::SendSolarRadiationSensor(const unsigned char NodeID, const int BatteryLevel, const float radiation, const std::string& defaultname)
931 {
932 _tGeneralDevice gdevice;
933 gdevice.subtype = sTypeSolarRadiation;
934 gdevice.id = NodeID;
935 gdevice.floatval1 = radiation;
936 sDecodeRXMessage(this, (const unsigned char*)& gdevice, defaultname.c_str(), BatteryLevel);
937 }
938
SendSoundSensor(const int NodeID,const int BatteryLevel,const int sLevel,const std::string & defaultname)939 void CDomoticzHardwareBase::SendSoundSensor(const int NodeID, const int BatteryLevel, const int sLevel, const std::string& defaultname)
940 {
941 _tGeneralDevice gDevice;
942 gDevice.subtype = sTypeSoundLevel;
943 gDevice.id = 1;
944 gDevice.intval1 = NodeID;
945 gDevice.intval2 = sLevel;
946 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
947 }
948
SendAlertSensor(const int NodeID,const int BatteryLevel,const int alertLevel,const std::string & message,const std::string & defaultname)949 void CDomoticzHardwareBase::SendAlertSensor(const int NodeID, const int BatteryLevel, const int alertLevel, const std::string& message, const std::string& defaultname)
950 {
951 _tGeneralDevice gDevice;
952 gDevice.subtype = sTypeAlert;
953 gDevice.id = (unsigned char)NodeID;
954 gDevice.intval1 = alertLevel;
955 sprintf(gDevice.text, "%.63s", message.c_str());
956 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
957 }
958
SendGeneralSwitch(const int NodeID,const int ChildID,const int BatteryLevel,const uint8_t SwitchState,const uint8_t Level,const std::string & defaultname,const int RssiLevel)959 void CDomoticzHardwareBase::SendGeneralSwitch(const int NodeID, const int ChildID, const int BatteryLevel, const uint8_t SwitchState, const uint8_t Level, const std::string& defaultname, const int RssiLevel)
960 {
961 _tGeneralSwitch gSwitch;
962 gSwitch.id = NodeID;
963 gSwitch.unitcode = ChildID;
964 gSwitch.cmnd = SwitchState;
965 gSwitch.level = Level;
966 gSwitch.rssi = (uint8_t)RssiLevel;
967 sDecodeRXMessage(this, (const unsigned char*)& gSwitch, defaultname.c_str(), BatteryLevel);
968 }
969
SendMoistureSensor(const int NodeID,const int BatteryLevel,const int mLevel,const std::string & defaultname)970 void CDomoticzHardwareBase::SendMoistureSensor(const int NodeID, const int BatteryLevel, const int mLevel, const std::string& defaultname)
971 {
972 _tGeneralDevice gDevice;
973 gDevice.subtype = sTypeSoilMoisture;
974 gDevice.id = 1;
975 gDevice.intval1 = NodeID;
976 gDevice.intval2 = mLevel;
977 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
978 }
979
SendUVSensor(const int NodeID,const int ChildID,const int BatteryLevel,const float UVI,const std::string & defaultname,const int RssiLevel)980 void CDomoticzHardwareBase::SendUVSensor(const int NodeID, const int ChildID, const int BatteryLevel, const float UVI, const std::string& defaultname, const int RssiLevel /* =12 */)
981 {
982 RBUF tsen;
983 memset(&tsen, 0, sizeof(RBUF));
984 tsen.UV.packetlength = sizeof(tsen.UV) - 1;
985 tsen.UV.packettype = pTypeUV;
986 tsen.UV.subtype = sTypeUV1;
987 tsen.UV.battery_level = BatteryLevel;
988 tsen.UV.rssi = RssiLevel;
989 tsen.UV.id1 = (unsigned char)NodeID;
990 tsen.UV.id2 = (unsigned char)ChildID;
991
992 tsen.UV.uv = (BYTE)round(UVI * 10);
993 sDecodeRXMessage(this, (const unsigned char*)& tsen.UV, defaultname.c_str(), BatteryLevel);
994 }
995
SendZWaveAlarmSensor(const int NodeID,const uint8_t InstanceID,const int BatteryLevel,const uint8_t aType,const int aValue,const std::string & alarmLabel,const std::string & defaultname)996 void CDomoticzHardwareBase::SendZWaveAlarmSensor(const int NodeID, const uint8_t InstanceID, const int BatteryLevel, const uint8_t aType, const int aValue, const std::string& alarmLabel, const std::string& defaultname)
997 {
998 uint8_t ID1 = 0;
999 uint8_t ID2 = (unsigned char)((NodeID & 0xFF00) >> 8);
1000 uint8_t ID3 = (unsigned char)NodeID & 0xFF;
1001 uint8_t ID4 = InstanceID;
1002
1003 unsigned long lID = (ID1 << 24) + (ID2 << 16) + (ID3 << 8) + ID4;
1004
1005 _tGeneralDevice gDevice;
1006 gDevice.subtype = sTypeZWaveAlarm;
1007 gDevice.id = aType;
1008 gDevice.intval1 = (int)(lID);
1009 gDevice.intval2 = aValue;
1010
1011 int maxChars = (alarmLabel.size() < sizeof(_tGeneralDevice::text) - 1) ? alarmLabel.size() : sizeof(_tGeneralDevice::text) - 1;
1012 strncpy(gDevice.text, alarmLabel.c_str(), maxChars);
1013 gDevice.text[maxChars] = 0;
1014
1015 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
1016 }
1017
SendFanSensor(const int Idx,const int BatteryLevel,const int FanSpeed,const std::string & defaultname)1018 void CDomoticzHardwareBase::SendFanSensor(const int Idx, const int BatteryLevel, const int FanSpeed, const std::string& defaultname)
1019 {
1020 _tGeneralDevice gDevice;
1021 gDevice.subtype = sTypeFan;
1022 gDevice.id = 1;
1023 gDevice.intval1 = Idx;
1024 gDevice.intval2 = FanSpeed;
1025 sDecodeRXMessage(this, (const unsigned char*)& gDevice, defaultname.c_str(), BatteryLevel);
1026 }
1027