1 #include "stdafx.h"
2 #include "DavisLoggerSerial.h"
3 #include "../main/Logger.h"
4 #include "hardwaretypes.h"
5 #include "../main/RFXtrx.h"
6 #include "../main/Helper.h"
7
8 #include <string>
9 #include <algorithm>
10 #include <iostream>
11 #include <boost/bind.hpp>
12
13 #include "../main/localtime_r.h"
14 #include "../main/mainworker.h"
15
16 #include <ctime>
17
18 #ifdef _DEBUG
19 //#define DEBUG_DAVIS
20 #endif
21
22 #define RETRY_DELAY 30
23 #define DAVIS_READ_INTERVAL 30
24
25 #define round(a) ( int ) ( a + .5 )
26
CDavisLoggerSerial(const int ID,const std::string & devname,unsigned int baud_rate)27 CDavisLoggerSerial::CDavisLoggerSerial(const int ID, const std::string& devname, unsigned int baud_rate) :
28 m_szSerialPort(devname)
29 {
30 m_HwdID = ID;
31 m_iBaudRate = baud_rate;
32 m_retrycntr = RETRY_DELAY;
33 m_statecounter = 0;
34 m_state = DSTATE_WAKEUP;
35 }
36
~CDavisLoggerSerial(void)37 CDavisLoggerSerial::~CDavisLoggerSerial(void)
38 {
39
40 }
41
StartHardware()42 bool CDavisLoggerSerial::StartHardware()
43 {
44 StopHardware();
45
46 RequestStart();
47
48 m_retrycntr = RETRY_DELAY; //will force reconnect first thing
49 //Start worker thread
50 m_thread = std::make_shared<std::thread>(&CDavisLoggerSerial::Do_Work, this);
51 SetThreadNameInt(m_thread->native_handle());
52 return (m_thread != nullptr);
53
54 }
55
StopHardware()56 bool CDavisLoggerSerial::StopHardware()
57 {
58 if (m_thread)
59 {
60 RequestStop();
61 m_thread->join();
62 m_thread.reset();
63 }
64 m_bIsStarted = false;
65 return true;
66 }
67
OpenSerialDevice()68 bool CDavisLoggerSerial::OpenSerialDevice()
69 {
70 //Try to open the Serial Port
71 try
72 {
73 open(m_szSerialPort, m_iBaudRate);
74 Log(LOG_STATUS, "Using serial port: %s", m_szSerialPort.c_str());
75 m_statecounter = 0;
76 m_state = DSTATE_WAKEUP;
77 }
78 catch (boost::exception & e)
79 {
80 Log(LOG_ERROR, "Error opening serial port!");
81 #ifdef _DEBUG
82 Log(LOG_ERROR, "-----------------\n%s\n----------------", boost::diagnostic_information(e).c_str());
83 #else
84 (void)e;
85 #endif
86 return false;
87 }
88 catch (...)
89 {
90 Log(LOG_ERROR, "Error opening serial port!!!");
91 return false;
92 }
93 m_bIsStarted = true;
94 setReadCallback(boost::bind(&CDavisLoggerSerial::readCallback, this, _1, _2));
95 sOnConnected(this);
96 return true;
97 }
98
WriteToHardware(const char *,const unsigned char)99 bool CDavisLoggerSerial::WriteToHardware(const char* /*pdata*/, const unsigned char /*length*/)
100 {
101 return false;
102 }
103
Do_Work()104 void CDavisLoggerSerial::Do_Work()
105 {
106 Log(LOG_STATUS, "Worker started...");
107
108 int sec_counter = 0;
109 while (!IsStopRequested(1000))
110 {
111 sec_counter++;
112 if (sec_counter % 12 == 0) {
113 mytime(&m_LastHeartbeat);
114 }
115 if (!isOpen())
116 {
117 if (m_retrycntr == 0)
118 {
119 Log(LOG_STATUS, "serial setup retry in %d seconds...", RETRY_DELAY);
120 }
121 m_retrycntr++;
122 if (m_retrycntr >= RETRY_DELAY)
123 {
124 m_retrycntr = 0;
125 OpenSerialDevice();
126 }
127 }
128 else
129 {
130 switch (m_state)
131 {
132 case DSTATE_WAKEUP:
133 m_statecounter++;
134 if (m_statecounter < 5) {
135 write("\n", 1);
136 }
137 else {
138 m_retrycntr = 0;
139 //still did not receive a wakeup, lets try again
140 terminate();
141 }
142 break;
143 case DSTATE_LOOP:
144 m_statecounter++;
145 if (m_statecounter >= DAVIS_READ_INTERVAL)
146 {
147 m_statecounter = 0;
148 write("LOOP 1\n", 7);
149 }
150 break;
151 }
152 }
153 }
154 terminate();
155
156 Log(LOG_STATUS, "Worker stopped...");
157 }
158
readCallback(const char * data,size_t len)159 void CDavisLoggerSerial::readCallback(const char *data, size_t len)
160 {
161 try
162 {
163 //Log(LOG_NORM,"received %ld bytes",len);
164
165 switch (m_state)
166 {
167 case DSTATE_WAKEUP:
168 if (len == 2) {
169 Log(LOG_NORM, "System is Awake...");
170 m_state = DSTATE_LOOP;
171 m_statecounter = DAVIS_READ_INTERVAL - 1;
172 }
173 break;
174 case DSTATE_LOOP:
175 if (len == 2)
176 break; //could be a left over from the awake
177 if (len != 100) {
178 Log(LOG_ERROR, "Invalid bytes received!...");
179 //lets try again
180 terminate();
181 }
182 else {
183 if (!HandleLoopData((const unsigned char*)data, len))
184 {
185 //error in data, try again...
186 terminate();
187 }
188 }
189 break;
190 }
191 }
192 catch (...)
193 {
194
195 }
196 }
197
HandleLoopData(const unsigned char * data,size_t len)198 bool CDavisLoggerSerial::HandleLoopData(const unsigned char *data, size_t len)
199 {
200 const uint8_t *pData = data + 1;
201
202 #ifndef DEBUG_DAVIS
203 if (len != 100)
204 return false;
205
206 if (
207 (data[1] != 'L') ||
208 (data[2] != 'O') ||
209 (data[3] != 'O') ||
210 (data[96] != 0x0a) ||
211 (data[97] != 0x0d)
212 )
213 return false;
214 //bool bIsRevA = (data[4]=='P');
215 #else
216 // FILE *fOut=fopen("davisrob.bin","wb+");
217 // fwrite(data,1,len,fOut);
218 // fclose(fOut);
219 unsigned char szBuffer[200];
220 FILE *fIn = fopen("E:\\davis2.bin", "rb+");
221 //FILE *fIn=fopen("davisrob.bin","rb+");
222 fread(&szBuffer, 1, 100, fIn);
223 fclose(fIn);
224 pData = szBuffer + 1;
225 //bool bIsRevA(szBuffer[4]=='P');
226 #endif
227
228 RBUF tsen;
229 memset(&tsen, 0, sizeof(RBUF));
230
231
232 unsigned char tempIdx = 1;
233
234 bool bBaroValid = false;
235 float BaroMeter = 0;
236 bool bInsideTemperatureValid = false;
237 float InsideTemperature = 0;
238 bool bInsideHumidityValid = false;
239 int InsideHumidity = 0;
240 bool bOutsideTemperatureValid = false;
241 float OutsideTemperature = 0;
242 bool bOutsideHumidityValid = false;
243 int OutsideHumidity = 0;
244
245 bool bWindDirectionValid = false;
246 int WindDirection = 0;
247
248 bool bWindSpeedValid = false;
249 float WindSpeed = 0;
250 //bool bWindSpeedAVR10Valid=false;
251 //float WindSpeedAVR10=0;
252
253 bool bUVValid = false;
254 float UV = 0;
255
256 //Barometer
257 if ((pData[7] != 0xFF) && (pData[8] != 0xFF))
258 {
259 bBaroValid = true;
260 BaroMeter = ((unsigned int)((pData[8] << 8) | pData[7])) / 29.53f; //in hPa
261 }
262 //Inside Temperature
263 if ((pData[9] != 0xFF) || (pData[10] != 0x7F))
264 {
265 bInsideTemperatureValid = true;
266 InsideTemperature = ((unsigned int)((pData[10] << 8) | pData[9])) / 10.f;
267 InsideTemperature = (InsideTemperature - 32.0f) * 5.0f / 9.0f;
268 }
269 //Inside Humidity
270 if (pData[11] != 0xFF)
271 {
272 InsideHumidity = pData[11];
273 if (InsideHumidity < 101)
274 bInsideHumidityValid = true;
275 }
276
277 if (bBaroValid&&bInsideTemperatureValid&&bInsideHumidityValid)
278 {
279 uint8_t forecastitem = pData[89];
280 uint8_t forecast = 0;
281
282 if ((forecastitem & 0x01) == 0x01)
283 forecast = wsbaroforecast_rain;
284 else if ((forecastitem & 0x02) == 0x02)
285 forecast = wsbaroforecast_cloudy;
286 else if ((forecastitem & 0x04) == 0x04)
287 forecast = wsbaroforecast_some_clouds;
288 else if ((forecastitem & 0x08) == 0x08)
289 forecast = wsbaroforecast_sunny;
290 else if ((forecastitem & 0x10) == 0x10)
291 forecast = wsbaroforecast_snow;
292
293 SendTempHumBaroSensorFloat(tempIdx++, 255, InsideTemperature, InsideHumidity, BaroMeter, forecast, "THB");
294 }
295
296 //Outside Temperature
297 if ((pData[12] != 0xFF) || (pData[13] != 0x7F))
298 {
299 bOutsideTemperatureValid = true;
300 //OutsideTemperature=((unsigned int)((pData[13] << 8) | pData[12])) / 10.f;
301 //OutsideTemperature = (OutsideTemperature - 32.0f) * 5.0f / 9.0f;
302
303 uint8_t msb = pData[13];
304 uint8_t lsb = pData[12];
305
306 uint16_t temp16 = ((msb << 8) | lsb);
307 if (temp16 > 0x800) {
308 // Negative values, convert to float from two complements int
309 int temp_int = (temp16 | ~((1 << 16) - 1));
310 OutsideTemperature = (float)temp_int / 10.0f;
311 }
312 else {
313 OutsideTemperature = (float)temp16 / 10.0f;
314 }
315
316 // Convert to celsius
317 OutsideTemperature = (OutsideTemperature - 32.0f) * 5.0f / 9.0f;
318 }
319 //Outside Humidity
320 if (pData[33] != 0xFF)
321 {
322 OutsideHumidity = pData[33];
323 if (OutsideHumidity < 101)
324 bOutsideHumidityValid = true;
325 }
326 if (bOutsideTemperatureValid || bOutsideHumidityValid)
327 {
328 if ((bOutsideTemperatureValid) && (bOutsideHumidityValid))
329 {
330 //Temp+hum
331 SendTempHumSensor(tempIdx++, 255, OutsideTemperature, OutsideHumidity, "Outside TempHum");
332 }
333 else if (bOutsideTemperatureValid)
334 {
335 //Temp
336 SendTempSensor(tempIdx++, 255, OutsideTemperature, "Outside Temp");
337 }
338 else if (bOutsideHumidityValid)
339 {
340 //hum
341 SendHumiditySensor(tempIdx++, 255, OutsideHumidity, "Outside Humidity");
342 }
343 }
344
345 tempIdx = 10;
346 //Add Extra Temp/Hum Sensors
347 int iTmp;
348 for (iTmp = 0; iTmp < 7; iTmp++)
349 {
350 bool bTempValid = false;
351 bool bHumValid = false;
352 float temp = 0;
353 uint8_t hum = 0;
354
355 if (pData[18 + iTmp] != 0xFF)
356 {
357 bTempValid = true;
358 temp = pData[18 + iTmp] - 90.0f;
359 temp = (temp - 32.0f) * 5.0f / 9.0f;
360 }
361 if (pData[34 + iTmp] != 0xFF)
362 {
363 bHumValid = true;
364 hum = pData[34 + iTmp];
365 }
366 if ((bTempValid) && (bHumValid))
367 {
368 //Temp+hum
369 SendTempHumSensor(tempIdx++, 255, temp, hum, "Extra TempHum");
370 }
371 else if (bTempValid)
372 {
373 //Temp
374 SendTempSensor(tempIdx++, 255, temp, "Extra Temp");
375 }
376 else if (bHumValid)
377 {
378 //hum
379 SendHumiditySensor(tempIdx++, 255, hum, "Extra Humidity");
380 }
381 }
382
383 tempIdx = 20;
384 //Add Extra Soil Temp Sensors
385 for (iTmp = 0; iTmp < 4; iTmp++)
386 {
387 bool bTempValid = false;
388 float temp = 0;
389
390 if (pData[25 + iTmp] != 0xFF)
391 {
392 bTempValid = true;
393 temp = pData[25 + iTmp] - 90.0f;
394 temp = (temp - 32.0f) * 5.0f / 9.0f;
395 }
396 if (bTempValid)
397 {
398 SendTempSensor(tempIdx++, 255, temp, "Soil Temp");
399 }
400 }
401
402 tempIdx = 30;
403 //Add Extra Leaf Temp Sensors
404 for (iTmp = 0; iTmp < 4; iTmp++)
405 {
406 bool bTempValid = false;
407 float temp = 0;
408
409 if (pData[29 + iTmp] != 0xFF)
410 {
411 bTempValid = true;
412 temp = pData[29 + iTmp] - 90.0f;
413 temp = (temp - 32.0f) * 5.0f / 9.0f;
414 }
415 if (bTempValid)
416 {
417 SendTempSensor(tempIdx++, 255, temp, "Leaf Temp");
418 }
419 }
420
421 //Wind Speed
422 if (pData[14] != 0xFF)
423 {
424 bWindSpeedValid = true;
425 WindSpeed = (pData[14])*(4.0f / 9.0f);
426 }
427 //Wind Speed AVR 10 minutes
428 if (pData[15] != 0xFF)
429 {
430 //bWindSpeedAVR10Valid=true;
431 //WindSpeedAVR10=(pData[15])*(4.0f/9.0f);
432 }
433 //Wind Direction
434 if ((pData[16] != 0xFF) && (pData[17] != 0x7F))
435 {
436 bWindDirectionValid = true;
437 WindDirection = ((unsigned int)((pData[17] << 8) | pData[16]));
438 }
439
440 if ((bWindSpeedValid) && (bWindDirectionValid))
441 {
442 memset(&tsen, 0, sizeof(RBUF));
443 tsen.WIND.packetlength = sizeof(tsen.WIND) - 1;
444 tsen.WIND.packettype = pTypeWIND;
445 tsen.WIND.subtype = sTypeWINDNoTemp;
446 tsen.WIND.battery_level = 9;
447 tsen.WIND.rssi = 12;
448 tsen.WIND.id1 = 0;
449 tsen.WIND.id2 = 1;
450
451 int aw = round(WindDirection);
452 tsen.WIND.directionh = (BYTE)(aw / 256);
453 aw -= (tsen.WIND.directionh * 256);
454 tsen.WIND.directionl = (BYTE)(aw);
455
456 tsen.WIND.av_speedh = 0;
457 tsen.WIND.av_speedl = 0;
458 int sw = round(WindSpeed*10.0f);
459 tsen.WIND.av_speedh = (BYTE)(sw / 256);
460 sw -= (tsen.WIND.av_speedh * 256);
461 tsen.WIND.av_speedl = (BYTE)(sw);
462
463 tsen.WIND.gusth = 0;
464 tsen.WIND.gustl = 0;
465
466 //this is not correct, why no wind temperature? and only chill?
467 tsen.WIND.chillh = 0;
468 tsen.WIND.chilll = 0;
469 tsen.WIND.temperatureh = 0;
470 tsen.WIND.temperaturel = 0;
471 if (bOutsideTemperatureValid)
472 {
473 tsen.WIND.tempsign = (OutsideTemperature >= 0) ? 0 : 1;
474 tsen.WIND.chillsign = (OutsideTemperature >= 0) ? 0 : 1;
475 int at10 = round(std::abs(OutsideTemperature*10.0f));
476 tsen.WIND.temperatureh = (BYTE)(at10 / 256);
477 tsen.WIND.chillh = (BYTE)(at10 / 256);
478 at10 -= (tsen.WIND.chillh * 256);
479 tsen.WIND.temperaturel = (BYTE)(at10);
480 tsen.WIND.chilll = (BYTE)(at10);
481 }
482
483 sDecodeRXMessage(this, (const unsigned char *)&tsen.WIND, NULL, 255);
484 }
485
486 //UV
487 if (pData[43] != 0xFF)
488 {
489 UV = (pData[43]) / 10.0f;
490 if (UV < 100)
491 bUVValid = true;
492 }
493 if (bUVValid)
494 {
495 SendUVSensor(0, 1, 255, UV, "UV");
496 }
497
498 //Rain Rate
499 if ((pData[41] != 0xFF) && (pData[42] != 0xFF))
500 {
501 //float rainRate=((unsigned int)((pData[42] << 8) | pData[41])) / 100.0f; //inches
502 //rainRate*=25.4f; //mm
503 }
504 //Rain Day
505 if ((pData[50] != 0xFF) && (pData[51] != 0xFF))
506 {
507 //float rainDay=((unsigned int)((pData[51] << 8) | pData[50])) / 100.0f; //inches
508 //rainDay*=25.4f; //mm
509 }
510 //Rain Year
511 if ((pData[54] != 0xFF) && (pData[55] != 0xFF))
512 {
513 float rainYear = ((unsigned int)((pData[55] << 8) | pData[54])) / 100.0f; //inches
514 rainYear *= 25.4f; //mm
515
516 SendRainSensor(1, 255, rainYear, "Rain");
517 }
518
519 //Solar Radiation
520 if ((pData[44] != 0xFF) && (pData[45] != 0x7F))
521 {
522 unsigned int solarRadiation = ((unsigned int)((pData[45] << 8) | pData[44]));//Watt/M2
523 _tGeneralDevice gdevice;
524 gdevice.subtype = sTypeSolarRadiation;
525 gdevice.floatval1 = float(solarRadiation);
526 sDecodeRXMessage(this, (const unsigned char *)&gdevice, NULL, 255);
527
528 }
529
530 //Soil Moistures
531 for (int iMoister = 0; iMoister < 4; iMoister++)
532 {
533 if (pData[62 + iMoister] != 0xFF)
534 {
535 int moister = pData[62 + iMoister];
536 SendMoistureSensor(1 + iMoister, 255, moister, "Moisture");
537 }
538 }
539
540 //Leaf Wetness
541 for (int iLeaf = 0; iLeaf < 4; iLeaf++)
542 {
543 if (pData[66 + iLeaf] != 0xFF)
544 {
545 int leaf_wetness = pData[66 + iLeaf];
546
547 _tGeneralDevice gdevice;
548 gdevice.subtype = sTypeLeafWetness;
549 gdevice.intval1 = leaf_wetness;
550 gdevice.id = (uint8_t)(1 + iLeaf);
551 sDecodeRXMessage(this, (const unsigned char *)&gdevice, NULL, 255);
552 }
553 }
554
555 return true;
556 }
557
558