1 #include "stdafx.h"
2 #include "DenkoviDevices.h"
3 #include "../main/Helper.h"
4 #include "../main/Logger.h"
5 #include "../httpclient/HTTPClient.h"
6 #include "hardwaretypes.h"
7 #include "../main/localtime_r.h"
8 #include "../main/mainworker.h"
9 #include "../main/SQLHelper.h"
10 #include <sstream>
11 
12 #define MAX_POLL_INTERVAL 3600*1000
13 
14 #define DAE_DI_DEF		"DigitalInput"
15 #define DAE_AI_DEF		"AnalogInput"
16 #define DAE_TI_DEF		"TemperatureInput"
17 #define DAE_AO_DEF		"AnalogOutput"
18 #define DAE_PWM_DEF		"PWM"
19 #define DAE_OUT_DEF		"Output"
20 #define DAE_RELAY_DEF	"Relay"
21 #define DAE_CH_DEF		"Channel"
22 
23 
24 #define SDO_AI_DEF		"AI"
25 #define SDO_DI_DEF		"DI"
26 #define SDO_TI_DEF		"TI"
27 #define SDO_RELAY_DEF	"Relay"
28 #define SDO_MAIN_DEF	"Main"
29 
30 #define DAENETIP3_PORTA_MDO_DEF			"ASG"//portA multiple output state
31 #define DAENETIP3_PORTA_SDO_DEF			"AS"//portA single output state
32 #define DAENETIP3_PORTA_SNAME_DEF		"AC"//portA signle output name
33 
34 #define DAENETIP3_PORTB_MDI_DEF			"BVG"//portB multiple input state
35 #define DAENETIP3_PORTB_SDI_DEF			"BV"//portB single output state
36 #define DAENETIP3_PORTB_SNAME_DEF		"BC"//portB signle input name
37 
38 #define DAENETIP3_PORTC_SNAME_DEF		"CC"//portC signle analog input name
39 #define DAENETIP3_PORTC_SDIM_DEF		"CS"//portC signle analog input dimension
40 #define DAENETIP3_PORTC_SVAL_DEF		"CD"//portC signle analog input value + dimension
41 
42 
43 #define MIN_DAENETIP3_RESPOND_LENGTH	105
44 
45 #define DAE_VALUE_DEF		"Value"
46 #define DAE_STATE_DEF		"State"
47 #define DAE_RSTATE_DEF		"RelayState"
48 #define DAE_MEASURE_DEF		"Measure"
49 #define DAE_SCAL_VALUE_DEF	"Scaled_Value"
50 #define DAE_NAME_DEF		"Name"
51 #define DAE_LASTO_DEF		"LastOpened"
52 #define DAE_LASTC_DEF		"LastClosed"
53 #define DAE_COUNT_DEF		"Count"
54 
55 #define DAENETIP3_AI_VALUE				0
56 #define DAENETIP3_AI_DIMENSION			1
57 #define DAENETIP2_PORT_3_VAL			0
58 #define DAENETIP2_PORT_5_VAL			1
59 #define DAENETIP2_AI_VOLTAGE			0
60 #define DAENETIP2_AI_TEMPERATURE		1
61 
62 enum _eDenkoviIOType
63 {
64 	DIOType_DI = 0,		//0
65 	DIOType_DO,			//1
66 	DIOType_Relay,		//2
67 	DIOType_PWM,		//3
68 	DIOType_AO,			//4
69 	DIOType_AI,			//5
70 	DIOType_DIO,		//6
71 	DIOType_MCD,		//7
72 	DIOType_TXT			//8
73 };
74 
CDenkoviDevices(const int ID,const std::string & IPAddress,const unsigned short usIPPort,const std::string & password,const int pollInterval,const int model)75 CDenkoviDevices::CDenkoviDevices(const int ID, const std::string &IPAddress, const unsigned short usIPPort, const std::string &password, const int pollInterval, const int model) :
76 	m_szIPAddress(IPAddress),
77 	m_Password(CURLEncode::URLEncode(password)),
78 	m_pollInterval(pollInterval)
79 {
80 	m_HwdID = ID;
81 	m_usIPPort = usIPPort;
82 	m_bOutputLog = false;
83 	m_iModel = model;
84 	if (m_pollInterval < 500)
85 		m_pollInterval = 500;
86 	else if (m_pollInterval > MAX_POLL_INTERVAL)
87 		m_pollInterval = MAX_POLL_INTERVAL;
88 	Init();
89 }
90 
91 
~CDenkoviDevices()92 CDenkoviDevices::~CDenkoviDevices()
93 {
94 }
95 
Init()96 void CDenkoviDevices::Init()
97 {
98 }
99 
StartHardware()100 bool CDenkoviDevices::StartHardware()
101 {
102 	RequestStart();
103 
104 	Init();
105 
106 	//Start worker thread
107 	m_thread = std::make_shared<std::thread>(&CDenkoviDevices::Do_Work, this);
108 	SetThreadNameInt(m_thread->native_handle());
109 	m_bIsStarted = true;
110 	sOnConnected(this);
111 	switch (m_iModel) {
112 	case DDEV_DAEnet_IP4:
113 		_log.Log(LOG_STATUS, "DAEnetIP4: Started");
114 		break;
115 	case DDEV_SmartDEN_IP_16_Relays:
116 		_log.Log(LOG_STATUS, "SmartDEN IP-16R: Started");
117 		break;
118 	case DDEV_SmartDEN_IP_32_In:
119 		_log.Log(LOG_STATUS, "SmartDEN IP-32IN: Started");
120 		break;
121 	case DDEV_SmartDEN_IP_Maxi:
122 		_log.Log(LOG_STATUS, "SmartDEN IP-Maxi: Started");
123 		break;
124 	case DDEV_SmartDEN_IP_Watchdog:
125 		_log.Log(LOG_STATUS, "SmartDEN IP-Watchdog: Started");
126 		break;
127 	case DDEV_SmartDEN_Logger:
128 		_log.Log(LOG_STATUS, "SmartDEN Logger: Started");
129 		break;
130 	case DDEV_SmartDEN_Notifier:
131 		_log.Log(LOG_STATUS, "SmartDEN Notifier: Started");
132 		break;
133 	case DDEV_DAEnet_IP3:
134 		_log.Log(LOG_STATUS, "DAEnetIP3: Started");
135 		break;
136 	case DDEV_DAEnet_IP2:
137 		_log.Log(LOG_STATUS, "DAEnetIP2: Started");
138 		break;
139 	case DDEV_DAEnet_IP2_8_RELAYS:
140 		_log.Log(LOG_STATUS, "DAEnetIP2 8 Relay Module - LM35DZ: Started");
141 		break;
142 	case DDEV_SmartDEN_Opener:
143 		_log.Log(LOG_STATUS, "SmartDEN Opener: Started");
144 		break;
145 	case DDEV_SmartDEN_PLC:
146 		_log.Log(LOG_STATUS, "SmartDEN PLC: Started");
147 		break;
148 	}
149 	return (m_thread != NULL);
150 }
151 
StopHardware()152 bool CDenkoviDevices::StopHardware()
153 {
154 	if (m_thread != NULL)
155 	{
156 		RequestStop();
157 		m_thread->join();
158 		m_thread.reset();
159 	}
160 	m_bIsStarted = false;
161 	return true;
162 }
163 
Do_Work()164 void CDenkoviDevices::Do_Work()
165 {
166 	int poll_interval = m_pollInterval / 100;
167 	int poll_counter = poll_interval - 2;
168 
169 	while (!IsStopRequested(100))
170 	{
171 		poll_counter++;
172 
173 		if (poll_counter % 12 * 10 == 0) { //10 steps = 1 second (10 * 100)
174 			m_LastHeartbeat = mytime(NULL);
175 		}
176 
177 		if (poll_counter % poll_interval == 0)
178 		{
179 			GetMeterDetails();
180 		}
181 	}
182 	switch (m_iModel) {
183 	case DDEV_DAEnet_IP4:
184 		_log.Log(LOG_STATUS, "DAEnetIP4: Worker stopped...");
185 		break;
186 	case DDEV_SmartDEN_IP_16_Relays:
187 		_log.Log(LOG_STATUS, "SmartDEN IP-16R: Worker stopped...");
188 		break;
189 	case DDEV_SmartDEN_IP_32_In:
190 		_log.Log(LOG_STATUS, "SmartDEN IP-32IN: Worker stopped...");
191 		break;
192 	case DDEV_SmartDEN_IP_Maxi:
193 		_log.Log(LOG_STATUS, "SmartDEN IP-Maxi: Worker stopped...");
194 		break;
195 	case DDEV_SmartDEN_IP_Watchdog:
196 		_log.Log(LOG_STATUS, "SmartDEN IP-Watchdog: Worker stopped...");
197 		break;
198 	case DDEV_SmartDEN_Logger:
199 		_log.Log(LOG_STATUS, "SmartDEN Logger: Worker stopped...");
200 		break;
201 	case DDEV_SmartDEN_Notifier:
202 		_log.Log(LOG_STATUS, "SmartDEN Notifier: Worker stopped...");
203 		break;
204 	case DDEV_DAEnet_IP3:
205 		_log.Log(LOG_STATUS, "DAEnetIP3: Worker stopped...");
206 		break;
207 	case DDEV_DAEnet_IP2:
208 		_log.Log(LOG_STATUS, "DAEnetIP2: Worker stopped...");
209 		break;
210 	case DDEV_DAEnet_IP2_8_RELAYS:
211 		_log.Log(LOG_STATUS, "DAEnetIP2 8 Relay Module - LM35DZ: Worker stopped...");
212 		break;
213 	case DDEV_SmartDEN_Opener:
214 		_log.Log(LOG_STATUS, "SmartDEN Opener: Worker stopped...");
215 		break;
216 	case DDEV_SmartDEN_PLC:
217 		_log.Log(LOG_STATUS, "SmartDEN PLC: Worker stopped...");
218 		break;
219 	}
220 }
221 
WriteToHardware(const char * pdata,const unsigned char)222 bool CDenkoviDevices::WriteToHardware(const char *pdata, const unsigned char /*length*/)
223 {
224 	const _tGeneralSwitch *pSen1 = reinterpret_cast<const _tGeneralSwitch*>(pdata);
225 	const tRBUF *pSen = reinterpret_cast<const tRBUF*>(pdata);
226 
227 	int ioType = pSen->LIGHTING2.id4;
228 	int io;
229 	int Relay;
230 	uint8_t command;
231 	uint8_t level;
232 
233 	if (ioType!=DIOType_DO && ioType!=DIOType_Relay && ioType!= DIOType_DIO && ioType!= DIOType_MCD)
234 	{
235 		ioType = pSen1->id;
236 		io = pSen1->unitcode;
237 		Relay = pSen1->unitcode;
238 		command = pSen1->cmnd;
239 		level = pSen1->level;
240 	}
241 	else
242 	{
243 		ioType = pSen->LIGHTING2.id4;
244 		io = pSen->LIGHTING2.unitcode;
245 		Relay = pSen->LIGHTING2.unitcode;
246 		command = pSen->LIGHTING2.cmnd;
247 		level = pSen->LIGHTING2.level;
248 	}
249 
250 	if (m_Password.empty())
251 	{
252 		switch (m_iModel) {
253 		case DDEV_DAEnet_IP4:
254 			_log.Log(LOG_ERROR, "DAEnetIP4: Please enter a password.");
255 			break;
256 		case DDEV_SmartDEN_IP_16_Relays:
257 			_log.Log(LOG_ERROR, "SmartDEN IP-16R: Please enter a password.");
258 			break;
259 		case DDEV_SmartDEN_IP_32_In:
260 			_log.Log(LOG_ERROR, "SmartDEN IP-32IN: Please enter a password.");
261 			break;
262 		case DDEV_SmartDEN_IP_Maxi:
263 			_log.Log(LOG_ERROR, "SmartDEN IP-Maxi: Please enter a password.");
264 			break;
265 		case DDEV_SmartDEN_IP_Watchdog:
266 			_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Please enter a password.");
267 			break;
268 		case DDEV_SmartDEN_Logger:
269 			_log.Log(LOG_ERROR, "SmartDEN Logger: Please enter a password.");
270 			break;
271 		case DDEV_SmartDEN_Notifier:
272 			_log.Log(LOG_ERROR, "SmartDEN Notifier: Please enter a password.");
273 			break;
274 		case DDEV_DAEnet_IP3:
275 			_log.Log(LOG_ERROR, "DAEnetIP3: Please enter a password.");
276 			break;
277 		case DDEV_DAEnet_IP2:
278 			_log.Log(LOG_ERROR, "DAEnetIP2: Please enter a password.");
279 			break;
280 		case DDEV_DAEnet_IP2_8_RELAYS:
281 			_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Please enter a password.");
282 			break;
283 		case DDEV_SmartDEN_Opener:
284 			_log.Log(LOG_ERROR, "SmartDEN Opener: Please enter a password.");
285 			break;
286 		case DDEV_SmartDEN_PLC:
287 			_log.Log(LOG_ERROR, "SmartDEN PLC: Please enter a password.");
288 			break;
289 		}
290 		return false;
291 	}
292 
293 	switch (m_iModel) {
294 	case DDEV_SmartDEN_Opener: {
295 
296 		if ((ioType != DIOType_MCD) && (ioType != DIOType_Relay))
297 		{
298 			_log.Log(LOG_ERROR, "SmartDEN Opener: Not a valid Relay or Main Controlled Device!");
299 			return false;
300 		}
301 		//int io = pSen->unitcode;//Relay1, Relay2 and MCD
302 		if (io > 3)
303 			return false;
304 
305 		std::stringstream szURL;
306 
307 		szURL << "http://" << m_szIPAddress << ":" << m_usIPPort << "/current_state.xml";
308 		if (!m_Password.empty())
309 			szURL << "?pw=" << m_Password << "&";
310 		else
311 			szURL << "?";
312 
313 		if (ioType == DIOType_Relay)
314 			szURL << "R" << io << "=";
315 		else //DIOType_PWM:
316 			szURL << "MS=";
317 
318 		if (ioType == DIOType_Relay) {
319 			if (command== light2_sOff)
320 				szURL << "0";
321 			else if (command== light2_sOn)
322 				szURL << "1";
323 			else {
324 				_log.Log(LOG_ERROR, "SmartDEN Opener: Not a valid command for Relay!");
325 				return false;
326 			}
327 		}
328 		else if (ioType == DIOType_MCD) {
329 			if (command== blinds_sOpen)
330 				szURL << "1";
331 			else if (command== blinds_sClose)
332 				szURL << "0";
333 			else if (command== 0x11) //stop button
334 				szURL << "2";
335 			else {
336 				_log.Log(LOG_ERROR, "SmartDEN Opener: Not a valid command for MCD!");
337 				return false;
338 			}
339 		}
340 
341 		std::string sResult;
342 		if (!HTTPClient::GET(szURL.str(), sResult)) {
343 			_log.Log(LOG_ERROR, "SmartDEN Opener: Error sending command to: %s", m_szIPAddress.c_str());
344 			return false;
345 		}
346 		if (sResult.find("Message") != std::string::npos) {
347 			_log.Log(LOG_ERROR, "SmartDEN Opener: Error sending command to: %s", m_szIPAddress.c_str());
348 			return false;
349 		}
350 		return true;
351 	}
352 	case DDEV_DAEnet_IP2_8_RELAYS: {
353 		std::string sPass = m_Password;
354 		sPass.replace(sPass.find("%3A"), 3, ":");
355 		//int ioType = pSen->id;
356 		if (ioType != DIOType_DIO && ioType != DIOType_Relay)
357 		{
358 			_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Not a valid Digital Input/Output or Relay! ");
359 			return false;
360 		}
361 		//int io = pSen->unitcode;//DIO1 to DIO16
362 		if (io > 16)
363 			return false;
364 
365 		std::stringstream szURL;
366 		std::string sResult;
367 
368 		szURL << "http://" << sPass << "@" << m_szIPAddress << ":" << m_usIPPort << "/ioreg.js";
369 		if (!HTTPClient::GET(szURL.str(), sResult)) {
370 			_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Error sending command to: %s", m_szIPAddress.c_str());
371 			return false;
372 		}
373 		uint8_t port3 = DAEnetIP2GetIoPort(sResult, DAENETIP2_PORT_3_VAL);
374 		uint8_t port5 = DAEnetIP2GetIoPort(sResult, DAENETIP2_PORT_5_VAL);
375 		if (io < 9) { //DIO1 to DIO8 are from Port 3
376 			if (command== light2_sOff)
377 				port3 = port3 & (~(0x01 << (io - 1)));
378 			else if (command== light2_sOn)
379 				port3 = port3 | (0x01 << (io - 1));
380 			else {
381 				_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Not a valid command. Digital Input/Output could be On or Off.");
382 				return false;
383 			}
384 		}
385 		else { //DIO9 to DIO16 are from Port 5
386 			if (command== light2_sOff)
387 				port5 = port5 & (~(0x01 << (io - 8 - 1)));
388 			else if (command== light2_sOn)
389 				port5 = port5 | (0x01 << (io - 8 - 1));
390 			else {
391 				_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Not a valid command. Digital Input/Output could be On or Off.");
392 				return false;
393 			}
394 		}
395 		szURL.str("");
396 		char port3Val[3], port5Val[3];
397 		sprintf(port3Val, "%02X", port3);
398 		sprintf(port5Val, "%02X", port5);
399 		szURL << "http://" << sPass << "@" << m_szIPAddress << ":" << m_usIPPort << "/iochange.cgi?ref=re-io&01=" << port3Val << "&02=" << port5Val;
400 		if (!HTTPClient::GET(szURL.str(), sResult)) {
401 			_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Error sending command to: %s", m_szIPAddress.c_str());
402 			return false;
403 		}
404 		return true;
405 	}
406 	case DDEV_DAEnet_IP2: {
407 		std::string sPass = m_Password;
408 		sPass.replace(sPass.find("%3A"), 3, ":");
409 		//int ioType = pSen->id;
410 		if (ioType != DIOType_DIO)
411 		{
412 			_log.Log(LOG_ERROR, "DAEnetIP2: Not a valid Digital Input/Output! ");
413 			return false;
414 		}
415 		//int io = pSen->unitcode;//DIO1 to DIO16
416 		if (io > 16)
417 			return false;
418 
419 		std::stringstream szURL;
420 		std::string sResult;
421 
422 		szURL << "http://" << sPass << "@" << m_szIPAddress << ":" << m_usIPPort << "/ioreg.js";
423 		if (!HTTPClient::GET(szURL.str(), sResult)) {
424 			_log.Log(LOG_ERROR, "DAEnetIP2: Error sending command to: %s", m_szIPAddress.c_str());
425 			return false;
426 		}
427 		uint8_t port3 = DAEnetIP2GetIoPort(sResult, DAENETIP2_PORT_3_VAL);
428 		uint8_t port5 = DAEnetIP2GetIoPort(sResult, DAENETIP2_PORT_5_VAL);
429 		if (io < 9) { //DIO1 to DIO8 are from Port 3
430 			if (command== light2_sOff)
431 				port3 = port3 & (~(0x01 << (io - 1)));
432 			else if (command== light2_sOn)
433 				port3 = port3 | (0x01 << (io - 1));
434 			else {
435 				_log.Log(LOG_ERROR, "DAEnetIP2: Not a valid command. Digital Input/Output could be On or Off.");
436 				return false;
437 			}
438 		}
439 		else { //DIO9 to DIO16 are from Port 5
440 			if (command== light2_sOff)
441 				port5 = port5 & (~(0x01 << (io - 8 - 1)));
442 			else if (command== light2_sOn)
443 				port5 = port5 | (0x01 << (io - 8 - 1));
444 			else {
445 				_log.Log(LOG_ERROR, "DAEnetIP2: Not a valid command. Digital Input/Output could be On or Off.");
446 				return false;
447 			}
448 		}
449 		szURL.str("");
450 		char port3Val[3], port5Val[3];
451 		sprintf(port3Val, "%02X", port3);
452 		sprintf(port5Val, "%02X", port5);
453 		szURL << "http://" << sPass << "@" << m_szIPAddress << ":" << m_usIPPort << "/iochange.cgi?ref=re-io&01=" << port3Val << "&02=" << port5Val;
454 		if (!HTTPClient::GET(szURL.str(), sResult)) {
455 			_log.Log(LOG_ERROR, "DAEnetIP2: Error sending command to: %s", m_szIPAddress.c_str());
456 			return false;
457 		}
458 		return true;
459 	}
460 	case DDEV_DAEnet_IP3: {
461 		//int ioType = pSen->id;
462 		if (ioType != DIOType_DO)
463 		{
464 			_log.Log(LOG_ERROR, "DAEnetIP3: Not a valid Digital Output! ");
465 			return false;
466 		}
467 		//int io = pSen->unitcode;//DO1 to DO16
468 		if (io > 16)
469 			return false;
470 
471 		std::stringstream szURL;
472 
473 		szURL << "http://" << m_szIPAddress << ":" << m_usIPPort << "/command.html";
474 		if (!m_Password.empty())
475 			szURL << "?P=" << m_Password << "&";
476 		else
477 			szURL << "?";
478 
479 		szURL << DAENETIP3_PORTA_SDO_DEF << std::uppercase << std::hex << io - 1 << "=";
480 		if (command== light2_sOff)
481 			szURL << "0&";
482 		else if (command== light2_sOn) {
483 			szURL << "1&";
484 		}
485 		else {
486 			_log.Log(LOG_ERROR, "DAEnetIP3: Not a valid command. Digital Output could be On or Off.");
487 			return false;
488 		}
489 		std::string sResult;
490 		if (!HTTPClient::GET(szURL.str(), sResult)) {
491 			_log.Log(LOG_ERROR, "DAEnetIP3: Error sending command to: %s", m_szIPAddress.c_str());
492 			return false;
493 		}
494 		szURL.str("");
495 		szURL << DAENETIP3_PORTA_SDO_DEF << std::uppercase << std::hex << io - 1;
496 		if (sResult.find(szURL.str()) == std::string::npos) {
497 			_log.Log(LOG_ERROR, "DAEnetIP3: Error setting Digital Output %u", io);
498 			return false;
499 		}
500 		return true;
501 
502 	}
503 	case DDEV_SmartDEN_Notifier: {
504 		_log.Log(LOG_ERROR, "SmartDEN Notifier: This board does not have outputs! ");
505 		return false;
506 	}
507 	case DDEV_SmartDEN_Logger: {
508 		_log.Log(LOG_ERROR, "SmartDEN Logger: This board does not have outputs! ");
509 		return false;
510 	}
511 	case DDEV_SmartDEN_IP_32_In: {
512 		_log.Log(LOG_ERROR, "SmartDEN IP-32IN: This board does not have outputs! ");
513 		return false;
514 	}
515 	case DDEV_SmartDEN_PLC:
516 	case DDEV_SmartDEN_IP_Maxi: {
517 		//int ioType = pSen1->LIGHTING2.unitcode;//pSen->id;
518 		if ((ioType != DIOType_AO) && (ioType != DIOType_Relay))
519 		{
520 			_log.Log(LOG_ERROR, "SmartDEN IP-Maxi: Not a valid Relay or Analog Output!");
521 			return false;
522 		}
523 		//int io = pSen1->LIGHTING2.id4;//Relay1 to Relay8 and AO1 to AO2
524 		if (io > 8)
525 			return false;
526 
527 		std::stringstream szURL;
528 
529 		szURL << "http://" << m_szIPAddress << ":" << m_usIPPort << "/current_state.xml";
530 		if (!m_Password.empty())
531 			szURL << "?pw=" << m_Password << "&";
532 		else
533 			szURL << "?";
534 
535 		if (ioType == DIOType_Relay)
536 			szURL << "Relay" << io << "=";
537 		else //DIOType_PWM:
538 			szURL << "AnalogOutput" << io << "=";
539 
540 		if (command == light2_sOff)//pSen->cmnd
541 			szURL << "0";
542 		else if (command== light2_sSetLevel) {
543 			double lvl = level*10.34;
544 			int iLvl = (int)lvl;
545 			szURL << std::to_string(iLvl);
546 		}
547 		else
548 			szURL << "1";
549 		std::string sResult;
550 		if (!HTTPClient::GET(szURL.str(), sResult)) {
551 			_log.Log(LOG_ERROR, "SmartDEN IP-Maxi: Error sending command to: %s", m_szIPAddress.c_str());
552 			return false;
553 		}
554 		if (sResult.find("CurrentState") == std::string::npos) {
555 			_log.Log(LOG_ERROR, "SmartDEN IP-Maxi: Error sending command to: %s", m_szIPAddress.c_str());
556 			return false;
557 		}
558 		return true;
559 	}
560 	case DDEV_DAEnet_IP4: {
561 		//int ioType = pSen->id;
562 		if ((ioType != DIOType_DO) && (ioType != DIOType_PWM))
563 		{
564 			_log.Log(LOG_ERROR, "DAEnetIP4: Not a valid Digital or PWM output");
565 			return false;
566 		}
567 		//int io = pSen->unitcode;//Output1 to Output16 and PWM1 to PWM2
568 		if (io > 16)
569 			return false;
570 
571 		std::stringstream szURL;
572 
573 		szURL << "http://" << m_szIPAddress << ":" << m_usIPPort << "/current_state.xml";
574 		if (!m_Password.empty())
575 			szURL << "?pw=" << m_Password << "&";
576 		else
577 			szURL << "?";
578 
579 		if (ioType == DIOType_DO)
580 			szURL << "Output" << io << "=";
581 		else //DIOType_PWM:
582 			szURL << "PWM" << io << "=";
583 
584 		if (command== light2_sOff)
585 			szURL << "0";
586 		else if (command== light2_sSetLevel)
587 			szURL << std::to_string(level);
588 		else
589 			szURL << "1";
590 		std::string sResult;
591 		if (!HTTPClient::GET(szURL.str(), sResult)) {
592 			_log.Log(LOG_ERROR, "DAEnetIP4: Error sending command to: %s", m_szIPAddress.c_str());
593 			return false;
594 		}
595 		if (sResult.find("CurrentState") == std::string::npos) {
596 			_log.Log(LOG_ERROR, "DAEnetIP4: Error sending command to: %s", m_szIPAddress.c_str());
597 			return false;
598 		}
599 		return true;
600 	}
601 	case DDEV_SmartDEN_IP_Watchdog:
602 	case DDEV_SmartDEN_IP_16_Relays: {
603 		//int ioType = pSen->id;
604 		if (ioType != DIOType_Relay)
605 		{
606 			if (m_iModel == DDEV_SmartDEN_IP_Watchdog)
607 				_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Not a valid Relay switch.");
608 			else
609 				_log.Log(LOG_ERROR, "SmartDEN IP-16R: Not a valid Relay switch.");
610 			return false;
611 		}
612 		//int Relay = pSen->unitcode;
613 		if (Relay > 16)
614 			return false;
615 
616 		std::stringstream szURL;
617 
618 		szURL << "http://" << m_szIPAddress << ":" << m_usIPPort << "/current_state.xml";
619 		if (!m_Password.empty())
620 			szURL << "?pw=" << m_Password << "&Relay" << Relay << "=";
621 		else
622 			szURL << "?Relay" << Relay << "=";
623 
624 		if (command== light2_sOff)
625 			szURL << "0";
626 		else if (command== light2_sOn) {
627 			szURL << "1";
628 		}
629 		else {
630 			if (m_iModel == DDEV_SmartDEN_IP_Watchdog)
631 				_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Not a valid command. Relay could be On or Off.");
632 			else
633 				_log.Log(LOG_ERROR, "SmartDEN IP-16R: Not a valid command. Relay could be On or Off.");
634 			return false;
635 		}
636 		std::string sResult;
637 		if (!HTTPClient::GET(szURL.str(), sResult))
638 		{
639 			if (m_iModel == DDEV_SmartDEN_IP_Watchdog)
640 				_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Error sending relay command to: %s", m_szIPAddress.c_str());
641 			else
642 				_log.Log(LOG_ERROR, "SmartDEN IP-16R: Error sending relay command to: %s", m_szIPAddress.c_str());
643 			return false;
644 		}
645 		if (sResult.find("CurrentState") == std::string::npos)
646 		{
647 			if (m_iModel == DDEV_SmartDEN_IP_Watchdog)
648 				_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Error sending relay command to: %s", m_szIPAddress.c_str());
649 			else
650 				_log.Log(LOG_ERROR, "SmartDEN IP-16R: Error sending relay command to: %s", m_szIPAddress.c_str());
651 			return false;
652 		}
653 		return true;
654 	}
655 	}
656 	_log.Log(LOG_ERROR, "Denkovi: Unknown Device!");
657 	return false;
658 }
659 
DenkoviCheckForIO(std::string tmpstr,const std::string & tmpIoType)660 int CDenkoviDevices::DenkoviCheckForIO(std::string tmpstr, const std::string &tmpIoType) {
661 	int Idx = -1;
662 	std::string ioType = "<" + tmpIoType;
663 	size_t pos1 = tmpstr.find(ioType);
664 	if (pos1 != std::string::npos)
665 	{
666 		tmpstr = tmpstr.substr(pos1 + strlen(ioType.c_str()));
667 		pos1 = tmpstr.find(">");
668 		if (pos1 != std::string::npos)
669 			Idx = atoi(tmpstr.substr(0, pos1).c_str());
670 	}
671 	return Idx;
672 }
673 
DenkoviGetIntParameter(std::string tmpstr,const std::string & tmpParameter)674 int CDenkoviDevices::DenkoviGetIntParameter(std::string tmpstr, const std::string &tmpParameter) {
675 	int lValue = -1;
676 	std::string parameter = "<" + tmpParameter + ">";
677 	size_t pos1 = tmpstr.find(parameter);
678 	if (pos1 != std::string::npos)
679 	{
680 		tmpstr = tmpstr.substr(pos1 + strlen(parameter.c_str()));
681 		pos1 = tmpstr.find('<');
682 		if (pos1 != std::string::npos)
683 			lValue = atoi(tmpstr.substr(0, pos1).c_str());
684 	}
685 	return lValue;
686 }
687 
DenkoviGetStrParameter(std::string tmpstr,const std::string & tmpParameter)688 std::string CDenkoviDevices::DenkoviGetStrParameter(std::string tmpstr, const std::string &tmpParameter) {
689 	std::string sMeasure = "";
690 	std::string parameter = "<" + tmpParameter + ">";
691 
692 	size_t pos1 = tmpstr.find(parameter);
693 	if (pos1 != std::string::npos)
694 	{
695 		tmpstr = tmpstr.substr(pos1 + strlen(parameter.c_str()));
696 		pos1 = tmpstr.find('<');
697 		if (pos1 != std::string::npos)
698 			sMeasure = tmpstr.substr(0, pos1);
699 	}
700 	return sMeasure;
701 }
702 
DenkoviGetFloatParameter(std::string tmpstr,const std::string & tmpParameter)703 float CDenkoviDevices::DenkoviGetFloatParameter(std::string tmpstr, const std::string &tmpParameter) {
704 	float value = NAN;
705 	std::string parameter = "<" + tmpParameter + ">";
706 
707 	size_t pos1 = tmpstr.find(parameter);
708 	if (pos1 != std::string::npos)
709 	{
710 		tmpstr = tmpstr.substr(pos1 + strlen(parameter.c_str()));
711 		pos1 = tmpstr.find('<');
712 		if (pos1 != std::string::npos)
713 			value = static_cast<float>(atof(tmpstr.substr(0, pos1).c_str()));
714 	}
715 	return value;
716 }
717 
DAEnetIP3GetIo(std::string tmpstr,const std::string & tmpParameter)718 std::string CDenkoviDevices::DAEnetIP3GetIo(std::string tmpstr, const std::string &tmpParameter) {
719 	std::string parameter = tmpParameter + "=";
720 	size_t pos1 = tmpstr.find(parameter);
721 	size_t pos2 = tmpstr.find(";", pos1);
722 	return tmpstr.substr(pos1 + strlen(parameter.c_str()), pos2 - (pos1 + strlen(parameter.c_str()))).c_str();
723 }
724 
DAEnetIP3GetAi(std::string tmpstr,const std::string & tmpParameter,const int & ciType)725 std::string CDenkoviDevices::DAEnetIP3GetAi(std::string tmpstr, const std::string &tmpParameter, const int &ciType) {
726 	std::string parameter = tmpParameter + "=";
727 	size_t pos1 = tmpstr.find(parameter);
728 	size_t pos2;
729 	if (ciType == DAENETIP3_AI_VALUE) {
730 		pos2 = tmpstr.find("[", pos1);
731 		return tmpstr.substr(pos1 + strlen(parameter.c_str()), pos2 - (pos1 + strlen(parameter.c_str()))).c_str();
732 	}
733 	else if (ciType == DAENETIP3_AI_DIMENSION) {
734 		pos1 = tmpstr.find("[", pos1);
735 		pos2 = tmpstr.find("]", pos1);
736 		return tmpstr.substr(pos1 + 1, pos2 - (pos1 + 1)).c_str();
737 	}
738 	return "";// tmpstr.substr(pos1 + strlen(parameter.c_str()), pos2 - (pos1 + strlen(parameter.c_str()))).c_str();
739 }
740 
DAEnetIP2GetIoPort(std::string tmpstr,const int & port)741 uint8_t CDenkoviDevices::DAEnetIP2GetIoPort(std::string tmpstr, const int &port) {
742 	std::stringstream ss;
743 	size_t pos1, pos2;
744 	int b;
745 	if (port == DAENETIP2_PORT_3_VAL) {
746 		pos1 = tmpstr.find("(0x");
747 		pos2 = tmpstr.find(",", pos1);
748 		ss << std::hex << tmpstr.substr(pos1 + 3, pos2 - (pos1 + 3)).c_str();
749 		ss >> b;
750 		return (uint8_t)b;
751 	}
752 	else if (port == DAENETIP2_PORT_5_VAL) {
753 		pos1 = tmpstr.find(",0x");
754 		pos2 = tmpstr.find(",", pos1 + 3);
755 		ss << std::hex << tmpstr.substr(pos1 + 3, pos2 - (pos1 + 3)).c_str();
756 		ss >> b;
757 		return (uint8_t)b;
758 	}
759 	return 0;
760 }
761 
DAEnetIP2GetName(std::string tmpstr,const int & nmr)762 std::string CDenkoviDevices::DAEnetIP2GetName(std::string tmpstr, const int &nmr) {//nmr should be from 1 to 24
763 	size_t pos1 = 0, pos2 = 0;
764 	for (uint8_t ii = 0; ii < (((nmr - 1) * 2) + 1); ii++) {
765 		pos1 = tmpstr.find("\"", pos1 + 1);
766 	}
767 	pos2 = tmpstr.find("\"", pos1 + 1);
768 	return tmpstr.substr(pos1 + 1, pos2 - (pos1 + 1)).c_str();
769 }
770 
DAEnetIP2GetAiValue(std::string tmpstr,const int & aiNmr)771 uint16_t CDenkoviDevices::DAEnetIP2GetAiValue(std::string tmpstr, const int &aiNmr) {
772 	size_t pos1 = 0, pos2 = 0;
773 	std::stringstream ss;
774 	int b = 0;
775 	for (uint8_t ii = 0; ii < aiNmr + 3; ii++) {
776 		pos1 = tmpstr.find("0x", pos1 + 2);
777 	}
778 	pos2 = tmpstr.find(",", pos1 + 2);
779 	ss << std::hex << tmpstr.substr(pos1 + 2, pos2 - (pos1 + 2)).c_str();
780 	ss >> b;
781 	return (uint8_t)b;
782 }
783 
DAEnetIP2CalculateAi(int adc,const int & valType)784 float CDenkoviDevices::DAEnetIP2CalculateAi(int adc, const int &valType) {
785 	if (valType == DAENETIP2_AI_TEMPERATURE) {
786 		return static_cast<float>(10000 * ((1.2*204.8)*adc / (120 * 1024) + 0) / 100);
787 	}
788 	else if (valType == DAENETIP2_AI_VOLTAGE) {
789 		return static_cast<float>(10000 * ((1.2*0.377)*adc / (4.7 * 1024) + 0) / 100);
790 	}
791 	return 0.0f;
792 }
793 
SendDenkoviTextSensor(const int NodeID,const int ChildID,const int BatteryLevel,const std::string & textMessage,const std::string & defaultname)794 void CDenkoviDevices::SendDenkoviTextSensor(const int NodeID, const int ChildID, const int BatteryLevel, const std::string &textMessage, const std::string &defaultname)
795 {
796 	//check if we have a change, if not do not update it
797 	bool bExists;
798 	std::string oldvalue = GetTextSensorText(NodeID, ChildID, bExists);
799 	if (oldvalue.compare(textMessage)!=0)
800 		SendTextSensor(NodeID, ChildID, BatteryLevel, textMessage, defaultname);
801 }
802 
803 
804 
GetMeterDetails()805 void CDenkoviDevices::GetMeterDetails()
806 {
807 	std::string sResult, sResult2;
808 	std::stringstream szURL, szURL2;
809 
810 	if (m_Password.empty())
811 	{
812 		switch (m_iModel) {
813 		case DDEV_DAEnet_IP4:
814 			_log.Log(LOG_ERROR, "DAEnetIP4: Please enter a password.");
815 			break;
816 		case DDEV_SmartDEN_IP_16_Relays:
817 			_log.Log(LOG_ERROR, "SmartDEN IP-16R: Please enter a password.");
818 			break;
819 		case DDEV_SmartDEN_IP_32_In:
820 			_log.Log(LOG_ERROR, "SmartDEN IP-32IN: Please enter a password.");
821 			break;
822 		case DDEV_SmartDEN_IP_Maxi:
823 			_log.Log(LOG_ERROR, "SmartDEN IP-Maxi: Please enter a password.");
824 			break;
825 		case DDEV_SmartDEN_IP_Watchdog:
826 			_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Please enter a password.");
827 			break;
828 		case DDEV_SmartDEN_Logger:
829 			_log.Log(LOG_ERROR, "SmartDEN Logger: Please enter a password.");
830 			break;
831 		case DDEV_SmartDEN_Notifier:
832 			_log.Log(LOG_ERROR, "SmartDEN Notifier: Please enter a password.");
833 			break;
834 		case DDEV_DAEnet_IP3:
835 			_log.Log(LOG_ERROR, "DAEnetIP3: Please enter a password.");
836 			break;
837 		case DDEV_DAEnet_IP2:
838 			_log.Log(LOG_ERROR, "DAEnetIP2: Please enter a password.");
839 			break;
840 		case DDEV_DAEnet_IP2_8_RELAYS:
841 			_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Please enter a password.");
842 			break;
843 		case DDEV_SmartDEN_Opener:
844 			_log.Log(LOG_ERROR, "SmartDEN Opener: Please enter a password.");
845 			break;
846 		case DDEV_SmartDEN_PLC:
847 			_log.Log(LOG_ERROR, "SmartDEN PLC: Please enter a password.");
848 			break;
849 		}
850 		return;
851 	}
852 
853 	if (m_iModel == DDEV_DAEnet_IP2 || m_iModel == DDEV_DAEnet_IP2_8_RELAYS) {
854 		std::string sPass = m_Password;
855 		if (sPass.find("%3A") == std::string::npos) {
856 			if (m_iModel == DDEV_DAEnet_IP2)
857 				_log.Log(LOG_ERROR, "DAEnetIP2: Please enter username and password in format username:password. Example admin:admin.");
858 			else if (m_iModel == DDEV_DAEnet_IP2_8_RELAYS)
859 				_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Please enter username and password in format username:password. Example admin:admin.");
860 			return;
861 		}
862 		sPass.replace(sPass.find("%3A"), 3, ":");
863 		szURL << "http://" << sPass << "@" << m_szIPAddress << ":" << m_usIPPort << "/ioreg.js";
864 	}
865 	else if (m_iModel == DDEV_DAEnet_IP3) {
866 		szURL << "http://" << m_szIPAddress << ":" << m_usIPPort << "/command.html";
867 		szURL2 << "http://" << m_szIPAddress << ":" << m_usIPPort << "/command.html";
868 		if (!m_Password.empty()) {
869 			szURL << "?P=" << m_Password;
870 			szURL2 << "?P=" << m_Password;
871 		}
872 		szURL << "&ASG=?&BVG=?&CD0=?&CD1=?&CD2=?&CD3=?&CD4=?&CD5=?&CD6=?&CD7=?&AC0=?&AC1=?&AC2=?&AC3=?&AC4=?&AC5=?&AC6=?&AC7=?&AC8=?&AC9=?&ACA=?&ACB=?&ACC=?&ACD=?&ACE=?&ACF=?&";
873 		szURL2 << "&BC0=?&BC1=?&BC2=?&BC3=?&BC4=?&BC5=?&BC6=?&BC7=?&CC0=?&CC1=?&CC2=?&CC3=?&CC4=?&CC5=?&CC6=?&CC7=?&";
874 	}
875 	else {
876 		szURL << "http://" << m_szIPAddress << ":" << m_usIPPort << "/current_state.xml";
877 		if (!m_Password.empty())
878 			szURL << "?pw=" << m_Password;
879 	}
880 
881 	if (!HTTPClient::GET(szURL.str(), sResult) || (m_iModel == DDEV_DAEnet_IP3 && !HTTPClient::GET(szURL2.str(), sResult2)))
882 	{
883 		switch (m_iModel) {
884 		case DDEV_DAEnet_IP4:
885 			_log.Log(LOG_ERROR, "DAEnetIP4: Error connecting to: %s", m_szIPAddress.c_str());
886 			break;
887 		case DDEV_SmartDEN_IP_16_Relays:
888 			_log.Log(LOG_ERROR, "SmartDEN IP-16R: Error connecting to: %s", m_szIPAddress.c_str());
889 			break;
890 		case DDEV_SmartDEN_IP_32_In:
891 			_log.Log(LOG_ERROR, "SmartDEN IP-32IN: Error connecting to: %s", m_szIPAddress.c_str());
892 			break;
893 		case DDEV_SmartDEN_IP_Maxi:
894 			_log.Log(LOG_ERROR, "SmartDEN IP-Maxi: Error connecting to: %s", m_szIPAddress.c_str());
895 			break;
896 		case DDEV_SmartDEN_IP_Watchdog:
897 			_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Error connecting to: %s", m_szIPAddress.c_str());
898 			break;
899 		case DDEV_SmartDEN_Logger:
900 			_log.Log(LOG_ERROR, "SmartDEN Logger: Error connecting to: %s", m_szIPAddress.c_str());
901 			break;
902 		case DDEV_SmartDEN_Notifier:
903 			_log.Log(LOG_ERROR, "SmartDEN Notifier: Error connecting to: %s", m_szIPAddress.c_str());
904 			break;
905 		case DDEV_DAEnet_IP3:
906 			_log.Log(LOG_ERROR, "DAEnetIP3: Error connecting to: %s", m_szIPAddress.c_str());
907 			break;
908 		case DDEV_DAEnet_IP2:
909 			_log.Log(LOG_ERROR, "DAEnetIP2: Error connecting to: %s", m_szIPAddress.c_str());
910 			break;
911 		case DDEV_SmartDEN_Opener:
912 			_log.Log(LOG_ERROR, "SmartDEN Opener: Error connecting to: %s", m_szIPAddress.c_str());
913 			break;
914 		case DDEV_SmartDEN_PLC:
915 			_log.Log(LOG_ERROR, "SmartDEN PLC: Error connecting to: %s", m_szIPAddress.c_str());
916 			break;
917 		}
918 		return;
919 	}
920 	std::vector<std::string> results;
921 	if (m_iModel == DDEV_SmartDEN_Opener)
922 		StringSplit(sResult, "\n", results);
923 	else
924 		StringSplit(sResult, "\r\n", results);
925 	//int z = strlen(sResult.c_str());
926 	if (m_iModel != DDEV_DAEnet_IP3 && m_iModel != DDEV_DAEnet_IP2 && m_iModel != DDEV_DAEnet_IP2_8_RELAYS && results.size() < 8)
927 	{
928 		switch (m_iModel) {
929 		case DDEV_DAEnet_IP4:
930 			_log.Log(LOG_ERROR, "DAEnetIP4: Error connecting to: %s", m_szIPAddress.c_str());
931 			break;
932 		case DDEV_SmartDEN_IP_16_Relays:
933 			_log.Log(LOG_ERROR, "SmartDEN IP-16R: Error connecting to: %s", m_szIPAddress.c_str());
934 			break;
935 		case DDEV_SmartDEN_IP_32_In:
936 			_log.Log(LOG_ERROR, "SmartDEN IP-32IN: Error connecting to: %s", m_szIPAddress.c_str());
937 			break;
938 		case DDEV_SmartDEN_IP_Maxi:
939 			_log.Log(LOG_ERROR, "SmartDEN IP-Maxi: Error connecting to: %s", m_szIPAddress.c_str());
940 			break;
941 		case DDEV_SmartDEN_IP_Watchdog:
942 			_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Error connecting to: %s", m_szIPAddress.c_str());
943 			break;
944 		case DDEV_SmartDEN_Logger:
945 			_log.Log(LOG_ERROR, "SmartDEN Logger: Error connecting to: %s", m_szIPAddress.c_str());
946 			break;
947 		case DDEV_SmartDEN_Notifier:
948 			_log.Log(LOG_ERROR, "SmartDEN Notifier: Error connecting to: %s", m_szIPAddress.c_str());
949 			break;
950 		case DDEV_SmartDEN_Opener:
951 			_log.Log(LOG_ERROR, "SmartDEN Opener: Error connecting to: %s", m_szIPAddress.c_str());
952 			break;
953 		case DDEV_SmartDEN_PLC:
954 			_log.Log(LOG_ERROR, "SmartDEN PLC: Error connecting to: %s", m_szIPAddress.c_str());
955 			break;
956 		}
957 		return;
958 	}
959 	else if (m_iModel == DDEV_DAEnet_IP3 && (strlen(sResult.c_str()) < MIN_DAENETIP3_RESPOND_LENGTH)) {
960 		_log.Log(LOG_ERROR, "DAEnetIP3: Error connecting to: %s", m_szIPAddress.c_str());
961 		return;
962 	}
963 	else if (m_iModel == DDEV_DAEnet_IP2 && sResult.find("var IO=new Array") == std::string::npos) {
964 		_log.Log(LOG_ERROR, "DAEnetIP2: Error getting status from: %s", m_szIPAddress.c_str());
965 		return;
966 	}
967 	else if (m_iModel == DDEV_DAEnet_IP2_8_RELAYS && sResult.find("var IO=new Array") == std::string::npos) {
968 		_log.Log(LOG_ERROR, "DAEnetIP2 8 Relay Module - LM35DZ: Error getting status from: %s", m_szIPAddress.c_str());
969 		return;
970 	}
971 
972 	if (m_iModel != DDEV_DAEnet_IP3 && m_iModel != DDEV_DAEnet_IP2 && m_iModel != DDEV_DAEnet_IP2_8_RELAYS && results[0] != "<CurrentState>")
973 	{
974 		switch (m_iModel) {
975 		case DDEV_DAEnet_IP4:
976 			_log.Log(LOG_ERROR, "DAEnetIP4: Error getting status");
977 			break;
978 		case DDEV_SmartDEN_IP_16_Relays:
979 			_log.Log(LOG_ERROR, "SmartDEN IP-16R: Error getting status");
980 			break;
981 		case DDEV_SmartDEN_IP_32_In:
982 			_log.Log(LOG_ERROR, "SmartDEN IP-32IN: Error getting status");
983 		case DDEV_SmartDEN_IP_Maxi:
984 			_log.Log(LOG_ERROR, "SmartDEN IP-Maxi: Error getting status");
985 			break;
986 		case DDEV_SmartDEN_IP_Watchdog:
987 			_log.Log(LOG_ERROR, "SmartDEN IP-Watchdog: Error getting status");
988 		case DDEV_SmartDEN_Logger:
989 			_log.Log(LOG_ERROR, "SmartDEN Logger: Error getting status");
990 			break;
991 		case DDEV_SmartDEN_Notifier:
992 			_log.Log(LOG_ERROR, "SmartDEN Notifier: Error getting status");
993 			break;
994 		case DDEV_SmartDEN_Opener:
995 			_log.Log(LOG_ERROR, "SmartDEN Opener: Error getting status");
996 			break;
997 		case DDEV_SmartDEN_PLC:
998 			_log.Log(LOG_ERROR, "SmartDEN PLC: Error getting status");
999 			break;
1000 		}
1001 		return;
1002 	}
1003 	else if (m_iModel == DDEV_DAEnet_IP3 && ((sResult.find(DAENETIP3_PORTA_MDO_DEF) == std::string::npos) || (sResult2.find(DAENETIP3_PORTB_SNAME_DEF) == std::string::npos))) {
1004 		_log.Log(LOG_ERROR, "DAEnetIP3: Error getting status");
1005 		return;
1006 	}
1007 
1008 	int ii;
1009 	std::string tmpstr;
1010 	std::string tmp_counter;
1011 	std::string tmp_adc_raw_value;
1012 	int tmpState = 0;
1013 	int tmpValue = 0;
1014 	float tmpTiValue = NAN;
1015 	std::string tmpMeasure;
1016 
1017 	std::string tmpName;
1018 	std::string name;
1019 	int Idx = -1;
1020 
1021 	switch (m_iModel) {
1022 	case DDEV_SmartDEN_Opener: {//has DI, AI, TI, Relays, MCD
1023 		bool bHaveDigitalInput = false;
1024 		bool bHaveMCD = false;
1025 		bool bHaveAnalogInput = false;
1026 		bool bHaveTemperatureInput = false;
1027 		bool bHaveRelay = false;
1028 		for (ii = 1; ii < (int)results.size(); ii++)
1029 		{
1030 			tmpstr = stdstring_trim(results[ii]);
1031 
1032 			if (Idx == -1) {
1033 				if (!bHaveDigitalInput && ((Idx = DenkoviCheckForIO(tmpstr, SDO_DI_DEF)) != -1))
1034 				{
1035 					bHaveDigitalInput = true;
1036 					continue;
1037 				}
1038 
1039 				if (!bHaveAnalogInput && ((Idx = DenkoviCheckForIO(tmpstr, SDO_AI_DEF)) != -1))
1040 				{
1041 					bHaveAnalogInput = true;
1042 					continue;
1043 				}
1044 
1045 				if (!bHaveMCD && ((Idx = DenkoviCheckForIO(tmpstr, SDO_MAIN_DEF)) != -1))
1046 				{
1047 					bHaveMCD = true;
1048 					continue;
1049 				}
1050 
1051 				if (!bHaveTemperatureInput && ((Idx = DenkoviCheckForIO(tmpstr, SDO_TI_DEF)) != -1))
1052 				{
1053 					bHaveTemperatureInput = true;
1054 					continue;
1055 				}
1056 
1057 				if (!bHaveRelay && ((Idx = DenkoviCheckForIO(tmpstr, SDO_RELAY_DEF)) != -1))
1058 				{
1059 					bHaveRelay = true;
1060 					continue;
1061 				}
1062 			}
1063 
1064 			if ((tmpName = DenkoviGetStrParameter(tmpstr, DAE_NAME_DEF)) != "") {
1065 				name = tmpName;
1066 				continue;
1067 			}
1068 
1069 			if (bHaveDigitalInput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_STATE_DEF)) != -1))
1070 			{
1071 				name = "Digital Input " + std::to_string(Idx) + " (" + name + ")";
1072 				SendSwitch(DIOType_DI, (uint8_t)Idx, 255, (tmpValue == 1) ? true : false, 0, name);
1073 				Idx = -1;
1074 				bHaveDigitalInput = false;
1075 				continue;
1076 			}
1077 
1078 			if (bHaveAnalogInput && (Idx != -1) && ((tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_SCAL_VALUE_DEF)) != ""))
1079 			{
1080 				std::vector<std::string> vMeasure;
1081 				StringSplit(tmpMeasure, " ", vMeasure);
1082 				int len = tmpMeasure.length() - tmpMeasure.find_first_of('.', 0) - 2;
1083 				std::string units = tmpMeasure.substr(tmpMeasure.find_first_of('.',0)+2, len);
1084 				SendCustomSensor(Idx, 1, 255, static_cast<float>(atof(vMeasure[0].c_str())), "Analog Input Scaled (" + name + ")", units);
1085 
1086 				std::vector<std::string> vRaw;
1087 				tmpstr = results[ii - 1];
1088 				std::string tmpRawValue = DenkoviGetStrParameter(tmpstr, DAE_VALUE_DEF);
1089 				StringSplit(tmpRawValue, " ", vRaw);
1090 				SendCustomSensor(Idx+1, 1, 255, static_cast<float>(atof(vRaw[0].c_str())), "Analog Input (" + name + ")", "");
1091 
1092 				Idx = -1;
1093 				bHaveAnalogInput = false;
1094 				continue;
1095 			}
1096 
1097 			if (bHaveTemperatureInput && (Idx != -1) && ((tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_VALUE_DEF)) != ""))
1098 			{
1099 				name = "Temperature Input (" + name + ")";
1100 				std::vector<std::string> vMeasure;
1101 				StringSplit(tmpMeasure, " ", vMeasure);
1102 				tmpTiValue = static_cast<float>(atof(tmpMeasure.c_str()));
1103 				if (tmpMeasure.find("F") != std::string::npos)
1104 					tmpTiValue = (float)ConvertToCelsius((double)tmpTiValue);
1105 				SendTempSensor(Idx, 255, tmpTiValue, name);
1106 
1107 				Idx = -1;
1108 				bHaveTemperatureInput = false;
1109 				continue;
1110 			}
1111 
1112 			if (bHaveRelay && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_STATE_DEF)) != -1))
1113 			{
1114 				name = "Relay " + std::to_string(Idx) + " (" + name + ")";
1115 				SendSwitch(DIOType_Relay, (uint8_t)Idx, 255, (tmpValue == 1) ? true : false, 0, name);
1116 				Idx = -1;
1117 				bHaveRelay = false;
1118 				continue;
1119 			}
1120 
1121 			if (bHaveMCD && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_STATE_DEF)) != -1))
1122 			{
1123 				std::string tmpN = "";
1124 				tmpN = "MCD (" + name + ")";
1125 				if (tmpValue == 1 || tmpValue == 3)
1126 					tmpValue = blinds_sOpen;
1127 				else if (tmpValue == 0 || tmpValue == 4)
1128 					tmpValue = blinds_sClose;
1129 				else
1130 					tmpValue = 0x11;
1131 				SendSwitch(DIOType_MCD, (uint8_t)Idx, 255, tmpValue, 0, tmpN);
1132 				ii = ii + 4;
1133 				tmpstr = stdstring_trim(results[ii]);
1134 				tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_LASTO_DEF);
1135 				SendDenkoviTextSensor(DIOType_TXT, ++Idx, 255, tmpMeasure, name + " Last Opened");
1136 				ii = ii + 1;
1137 				tmpstr = stdstring_trim(results[ii]);
1138 				tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_LASTC_DEF);
1139 				SendDenkoviTextSensor(DIOType_TXT, ++Idx, 255, tmpMeasure, name + " Last Closed");
1140 				Idx = -1;
1141 				bHaveMCD = false;
1142 				continue;
1143 			}
1144 		}
1145 		break;
1146 	}
1147 	case DDEV_DAEnet_IP2_8_RELAYS: {
1148 		uint8_t port3 = DAEnetIP2GetIoPort(sResult, DAENETIP2_PORT_3_VAL);
1149 		uint8_t port5 = DAEnetIP2GetIoPort(sResult, DAENETIP2_PORT_5_VAL);
1150 		for (ii = 0; ii < 8; ii++)//8 digital inputs/outputs from port3
1151 		{
1152 			tmpName = DAEnetIP2GetName(sResult, ii + 1);
1153 			name = "Digital IO " + std::to_string(ii + 1) + " (" + tmpName + ")";
1154 			SendSwitch(DIOType_DIO, (uint8_t)(ii + 1), 255, ((port3&(0x01 << ii)) != 0) ? true : false, 0, name);
1155 		}
1156 		for (ii = 0; ii < 8; ii++)//8 digital inputs/outputs from port5
1157 		{
1158 			tmpName = DAEnetIP2GetName(sResult, ii + 8 + 1);
1159 			name = "Relay " + std::to_string(ii + 1) + " (" + tmpName + ")";
1160 			SendSwitch(DIOType_Relay, (uint8_t)(ii + 8 + 1), 255, ((port5&(0x01 << ii)) != 0) ? true : false, 0, name);
1161 		}
1162 		for (ii = 0; ii < 8; ii++)//8 analog inputs
1163 		{
1164 			tmpName = DAEnetIP2GetName(sResult, ii + 16 + 1);
1165 			tmpValue = DAEnetIP2GetAiValue(sResult, ii + 1);
1166 			name = "Analog Input " + std::to_string(ii + 1) + " (" + tmpName + ")";
1167 			SendCustomSensor(DIOType_AI, (uint8_t)(ii + 16 + 1), 255, static_cast<float>(tmpValue), name, "");
1168 			//float voltageValue = (float)(10.44*(tmpValue / 1024));
1169 			float voltageValue = DAEnetIP2CalculateAi(tmpValue, DAENETIP2_AI_VOLTAGE);
1170 			SendVoltageSensor(DIOType_AI, ii + 24 + 1, 255, voltageValue, name);
1171 			//float temperatureValue = (float)(2.05*(tmpValue / 1024));
1172 			float temperatureValue = DAEnetIP2CalculateAi(tmpValue, DAENETIP2_AI_TEMPERATURE);
1173 			SendTempSensor(ii + 1, 255, temperatureValue, name);
1174 		}
1175 		break;
1176 	}
1177 	case DDEV_DAEnet_IP2: {
1178 		uint8_t port3 = DAEnetIP2GetIoPort(sResult, DAENETIP2_PORT_3_VAL);
1179 		uint8_t port5 = DAEnetIP2GetIoPort(sResult, DAENETIP2_PORT_5_VAL);
1180 		for (ii = 0; ii < 8; ii++)//8 digital inputs/outputs from port3
1181 		{
1182 			tmpName = DAEnetIP2GetName(sResult, ii + 1);
1183 			name = "Digital IO " + std::to_string(ii + 1) + " (" + tmpName + ")";
1184 			SendSwitch(DIOType_DIO, (uint8_t)(ii + 1), 255, ((port3&(0x01 << ii)) != 0) ? true : false, 0, name);
1185 		}
1186 		for (ii = 0; ii < 8; ii++)//8 digital inputs/outputs from port5
1187 		{
1188 			tmpName = DAEnetIP2GetName(sResult, ii + 8 + 1);
1189 			name = "Digital IO " + std::to_string(ii + 8 + 1) + " (" + tmpName + ")";
1190 			SendSwitch(DIOType_DIO, (uint8_t)(ii + 8 + 1), 255, ((port5&(0x01 << ii)) != 0) ? true : false, 0, name);
1191 		}
1192 		for (ii = 0; ii < 8; ii++)//8 analog inputs
1193 		{
1194 			tmpName = DAEnetIP2GetName(sResult, ii + 16 + 1);
1195 			tmpValue = DAEnetIP2GetAiValue(sResult, ii + 1);
1196 			name = "Analog Input " + std::to_string(ii + 1) + " (" + tmpName + ")";
1197 			SendCustomSensor(DIOType_AI, (uint8_t)(ii + 16 + 1), 255, static_cast<float>(tmpValue), name, "");
1198 		}
1199 		break;
1200 	}
1201 	case DDEV_DAEnet_IP3: {
1202 		unsigned int pins = std::stoul(DAEnetIP3GetIo(sResult, DAENETIP3_PORTA_MDO_DEF), nullptr, 16);
1203 		for (ii = 0; ii < 16; ii++)//16 digital outputs
1204 		{
1205 			std::stringstream io;
1206 			io << std::uppercase << std::hex << ii;
1207 			tmpName = DAEnetIP3GetIo(sResult, DAENETIP3_PORTA_SNAME_DEF + io.str());
1208 			name = "Digital Output " + std::to_string(ii + 1) + " (" + tmpName + ")";
1209 			SendSwitch(DIOType_DO, (uint8_t)(ii + 1), 255, ((pins&(0x0001 << ii)) != 0) ? true : false, 0, name);
1210 		}
1211 
1212 		pins = std::stoul(DAEnetIP3GetIo(sResult, DAENETIP3_PORTB_MDI_DEF), nullptr, 16);
1213 		for (ii = 0; ii < 8; ii++)//8 digital inputs
1214 		{
1215 			std::stringstream io;
1216 			io << std::uppercase << std::hex << ii;
1217 			tmpName = DAEnetIP3GetIo(sResult2, DAENETIP3_PORTB_SNAME_DEF + io.str());
1218 			name = "Digital Input " + std::to_string(ii + 1) + " (" + tmpName + ")";
1219 			SendSwitch(DIOType_DI, (uint8_t)(ii + 1), 255, ((pins&(0x01 << ii)) != 0) ? true : false, 0, name);
1220 		}
1221 
1222 		for (ii = 0; ii < 8; ii++)//8 analog inputs
1223 		{
1224 			tmpMeasure = DAEnetIP3GetAi(sResult, (DAENETIP3_PORTC_SVAL_DEF + std::to_string(ii)), DAENETIP3_AI_VALUE);
1225 			tmpstr = DAEnetIP3GetAi(sResult, (DAENETIP3_PORTC_SVAL_DEF + std::to_string(ii)), DAENETIP3_AI_DIMENSION);
1226 			tmpName = DAEnetIP3GetIo(sResult2, DAENETIP3_PORTC_SNAME_DEF + std::to_string(ii));
1227 			SendCustomSensor(DIOType_AI, (uint8_t)(ii + 1), 255, static_cast<float>(atoi(tmpMeasure.c_str())), "Analog Input Scaled " + std::to_string(ii + 1) + " (" + tmpName + ")", tmpstr);
1228 		}
1229 	}
1230 	case DDEV_SmartDEN_IP_16_Relays: {//has only relays
1231 		bool bHaveRelays = false;
1232 		for (ii = 1; ii < (int)results.size(); ii++)
1233 		{
1234 			tmpstr = stdstring_trim(results[ii]);
1235 
1236 			if (!bHaveRelays && ((Idx = DenkoviCheckForIO(tmpstr, DAE_RELAY_DEF)) != -1))
1237 			{
1238 				bHaveRelays = true;
1239 				continue;
1240 			}
1241 
1242 			if ((tmpName = DenkoviGetStrParameter(tmpstr, DAE_NAME_DEF)) != "") {
1243 				name = tmpName;
1244 				continue;
1245 			}
1246 
1247 			if (bHaveRelays && (Idx != -1) && ((tmpState = DenkoviGetIntParameter(tmpstr, DAE_STATE_DEF)) != -1))
1248 			{
1249 				std::stringstream sstr;
1250 				sstr << "Relay " << Idx << " (" << name << ")";
1251 				SendSwitch(DIOType_Relay, (uint8_t)Idx, 255, (tmpState == 1) ? true : false, 0, sstr.str());
1252 				Idx = -1;
1253 				bHaveRelays = false;
1254 				continue;
1255 			}
1256 		}
1257 		break;
1258 	}
1259 	case DDEV_SmartDEN_IP_Watchdog: {//has only relays
1260 		bool bHaveRelays = false;
1261 		for (ii = 1; ii < (int)results.size(); ii++)
1262 		{
1263 			tmpstr = stdstring_trim(results[ii]);
1264 
1265 			if (!bHaveRelays && ((Idx = DenkoviCheckForIO(tmpstr, DAE_CH_DEF)) != -1))
1266 			{
1267 				bHaveRelays = true;
1268 				continue;
1269 			}
1270 
1271 			if ((tmpName = DenkoviGetStrParameter(tmpstr, DAE_NAME_DEF)) != "") {
1272 				name = tmpName;
1273 				continue;
1274 			}
1275 
1276 			if (bHaveRelays && (Idx != -1) && ((tmpState = DenkoviGetIntParameter(tmpstr, DAE_RSTATE_DEF)) != -1))
1277 			{
1278 				name = "Relay " + std::to_string(Idx) + "(" + name + ")";
1279 				SendSwitch(DIOType_Relay, (uint8_t)Idx, 255, (tmpState == 1) ? true : false, 0, name);
1280 				Idx = -1;
1281 				bHaveRelays = false;
1282 				continue;
1283 			}
1284 		}
1285 		break;
1286 	}
1287 	case DDEV_SmartDEN_Notifier:
1288 	case DDEV_SmartDEN_Logger: {
1289 		bool bHaveDigitalInput = false;
1290 		bool bHaveAnalogInput = false;
1291 		bool bHaveTemperatureInput = false;
1292 		for (ii = 1; ii < (int)results.size(); ii++)
1293 		{
1294 			tmpstr = stdstring_trim(results[ii]);
1295 
1296 			if (Idx == -1) {
1297 				if (!bHaveDigitalInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_DI_DEF)) != -1))
1298 				{
1299 					bHaveDigitalInput = true;
1300 					continue;
1301 				}
1302 
1303 				if (!bHaveAnalogInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_AI_DEF)) != -1))
1304 				{
1305 					bHaveAnalogInput = true;
1306 					continue;
1307 				}
1308 
1309 				if (!bHaveTemperatureInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_TI_DEF)) != -1))
1310 				{
1311 					bHaveTemperatureInput = true;
1312 					continue;
1313 				}
1314 			}
1315 
1316 			if ((tmpName = DenkoviGetStrParameter(tmpstr, DAE_NAME_DEF)) != "") {
1317 				name = tmpName;
1318 				continue;
1319 			}
1320 
1321 			if (bHaveDigitalInput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1322 			{
1323 				SendSwitch(DIOType_DI, (uint8_t)Idx, 255, (tmpValue == 1) ? true : false, 0, "Digital Input " + std::to_string(Idx) + " (" + name + ")");
1324 
1325 				//Check if there is counter
1326 				tmpstr = stdstring_trim(results[ii + 1]);
1327 				if ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_COUNT_DEF)) != -1)
1328 				{
1329 					SendDenkoviTextSensor(DIOType_TXT, Idx + 8, 255, DenkoviGetStrParameter(tmpstr, DAE_COUNT_DEF), "Digital Input Counter " + std::to_string(Idx) + " (" + name + ")");
1330 				}
1331 				Idx = -1;
1332 				bHaveDigitalInput = false;
1333 				continue;
1334 			}
1335 
1336 			if (bHaveAnalogInput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1337 			{
1338 				SendCustomSensor(Idx + 8, 1, 255, static_cast<float>(tmpValue), "Analog Input " + std::to_string(Idx) + " (" + name + ")", "");
1339 
1340 				//Check if there is sclaed value
1341 				tmpstr = stdstring_trim(results[ii + 1]);
1342 				if ((tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_MEASURE_DEF)) != "")
1343 				{
1344 					std::vector<std::string> vMeasure;
1345 					StringSplit(tmpMeasure, " ", vMeasure);
1346 					if (vMeasure.size() == 2)
1347 					{
1348 						SendCustomSensor(Idx, 1, 255, static_cast<float>(atof(vMeasure[0].c_str())), "Analog Input Scaled " + std::to_string(Idx) + " (" + name + ")", vMeasure[1]);
1349 					}
1350 				}
1351 				Idx = -1;
1352 				bHaveAnalogInput = false;
1353 				continue;
1354 			}
1355 
1356 			if (bHaveTemperatureInput && (Idx != -1) && ((tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_VALUE_DEF)) != ""))
1357 			{
1358 				name = "Temperature Input " + std::to_string(Idx) + " (" + name + ")";
1359 				std::vector<std::string> vMeasure;
1360 				StringSplit(tmpMeasure, " ", vMeasure);
1361 
1362 				if ((tmpMeasure.find("---") == std::string::npos))
1363 				{
1364 					tmpTiValue = static_cast<float>(atof(tmpMeasure.c_str()));
1365 
1366 					if (tmpMeasure[tmpMeasure.size() - 1] == -119)//Check if F is found
1367 						tmpTiValue = (float)ConvertToCelsius((double)tmpTiValue);
1368 				}
1369 				else
1370 					tmpTiValue = 0;
1371 
1372 				SendTempSensor(Idx, 255, tmpTiValue, name);
1373 				Idx = -1;
1374 				bHaveTemperatureInput = false;
1375 				continue;
1376 			}
1377 		}
1378 		break;
1379 	}
1380 	case DDEV_SmartDEN_IP_32_In: {
1381 		bool bHaveDigitalInput = false;
1382 		bool bHaveAnalogInput = false;
1383 		bool bHaveTemperatureInput = false;
1384 		for (ii = 1; ii < (int)results.size(); ii++)
1385 		{
1386 			tmpstr = stdstring_trim(results[ii]);
1387 
1388 			if (Idx == -1) {
1389 				if (!bHaveDigitalInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_DI_DEF)) != -1))
1390 				{
1391 					bHaveDigitalInput = true;
1392 					continue;
1393 				}
1394 
1395 				if (!bHaveAnalogInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_AI_DEF)) != -1))
1396 				{
1397 					bHaveAnalogInput = true;
1398 					continue;
1399 				}
1400 
1401 				if (!bHaveTemperatureInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_TI_DEF)) != -1))
1402 				{
1403 					bHaveTemperatureInput = true;
1404 					continue;
1405 				}
1406 			}
1407 
1408 			if ((tmpName = DenkoviGetStrParameter(tmpstr, DAE_NAME_DEF)) != "") {
1409 				name = tmpName;
1410 				continue;
1411 			}
1412 
1413 			if (bHaveDigitalInput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1414 			{
1415 				SendSwitch(DIOType_DI, (uint8_t)Idx, 255, (tmpValue == 1) ? true : false, 0, "Digital Input " + std::to_string(Idx) + " (" + name + ")");
1416 
1417 				//Check if there is counter
1418 				tmpstr = stdstring_trim(results[ii + 1]);
1419 				if ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_COUNT_DEF)) != -1)
1420 				{
1421 					SendDenkoviTextSensor(DIOType_TXT, Idx + 8, 255, DenkoviGetStrParameter(tmpstr, DAE_COUNT_DEF), "Digital Input Counter " + std::to_string(Idx) + " (" + name + ")");
1422 				}
1423 				Idx = -1;
1424 				bHaveDigitalInput = false;
1425 				continue;
1426 			}
1427 
1428 			if (bHaveAnalogInput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1429 			{
1430 				SendCustomSensor(Idx+8, 1, 255, static_cast<float>(tmpValue), "Analog Input " + std::to_string(Idx) + " (" + name + ")", "");
1431 
1432 				//Check if there is sclaed value
1433 				tmpstr = stdstring_trim(results[ii + 1]);
1434 				if ((tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_MEASURE_DEF)) != "")
1435 				{
1436 					std::vector<std::string> vMeasure;
1437 					StringSplit(tmpMeasure, " ", vMeasure);
1438 					if (vMeasure.size() == 2)
1439 					{
1440 						SendCustomSensor(Idx, 1, 255, static_cast<float>(atof(vMeasure[0].c_str())), "Analog Input Scaled " + std::to_string(Idx) + " (" + name + ")", vMeasure[1]);
1441 					}
1442 				}
1443 				Idx = -1;
1444 				bHaveAnalogInput = false;
1445 				continue;
1446 			}
1447 			if (bHaveTemperatureInput && (Idx != -1) && ((tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_VALUE_DEF)) != ""))
1448 			{
1449 				name = "Temperature Input " + std::to_string(Idx) + " (" + name + ")";
1450 				std::vector<std::string> vMeasure;
1451 				StringSplit(tmpMeasure, " ", vMeasure);
1452 
1453 				if ((tmpMeasure.find("---") == std::string::npos))
1454 				{
1455 					tmpTiValue = static_cast<float>(atof(tmpMeasure.c_str()));
1456 
1457 					if (tmpMeasure[tmpMeasure.size() - 1] == -119)//Check if F is found
1458 						tmpTiValue = (float)ConvertToCelsius((double)tmpTiValue);
1459 				}
1460 				else
1461 					tmpTiValue = 0;
1462 
1463 				SendTempSensor(Idx, 255, tmpTiValue, name);
1464 				Idx = -1;
1465 				bHaveTemperatureInput = false;
1466 				continue;
1467 			}
1468 		}
1469 		break;
1470 	}
1471 	case DDEV_SmartDEN_PLC:
1472 	case DDEV_SmartDEN_IP_Maxi: {//has DI, AO, AI, Relays
1473 		bool bHaveDigitalInput = false;
1474 		bool bHaveAnalogOutput = false;
1475 		bool bHaveAnalogInput = false;
1476 		bool bHaveRelay = false;
1477 		for (ii = 1; ii < (int)results.size(); ii++)
1478 		{
1479 			tmpstr = stdstring_trim(results[ii]);
1480 
1481 			if (Idx == -1) {
1482 				if (!bHaveDigitalInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_DI_DEF)) != -1))
1483 				{
1484 					bHaveDigitalInput = true;
1485 					continue;
1486 				}
1487 
1488 				if (!bHaveAnalogInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_AI_DEF)) != -1))
1489 				{
1490 					bHaveAnalogInput = true;
1491 					continue;
1492 				}
1493 
1494 				if (!bHaveAnalogOutput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_AO_DEF)) != -1))
1495 				{
1496 					bHaveAnalogOutput = true;
1497 					continue;
1498 				}
1499 
1500 				if (!bHaveRelay && ((Idx = DenkoviCheckForIO(tmpstr, DAE_RELAY_DEF)) != -1))
1501 				{
1502 					bHaveRelay = true;
1503 					continue;
1504 				}
1505 			}
1506 
1507 			if ((tmpName = DenkoviGetStrParameter(tmpstr, DAE_NAME_DEF)) != "") {
1508 				name = tmpName;
1509 				continue;
1510 			}
1511 
1512 			if (bHaveDigitalInput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1513 			{	//Value
1514 				name = "Digital Input " + std::to_string(Idx) + " (" + name + ")";
1515 				SendSwitch(DIOType_DI, (uint8_t)Idx, 255, (tmpValue == 1) ? true : false, 0, name);
1516 				//Counter
1517 				tmp_counter = stdstring_trim(results[ii+1]);
1518 				SendDenkoviTextSensor(DIOType_TXT, Idx + 8, 255, DenkoviGetStrParameter(tmp_counter, DAE_COUNT_DEF), name + " Counter");
1519 				Idx = -1;
1520 				bHaveDigitalInput = false;
1521 				continue;
1522 			}
1523 
1524 
1525 			if (bHaveAnalogInput && (Idx != -1) && ((tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_MEASURE_DEF)) != ""))
1526 			{
1527 				std::vector<std::string> vMeasure;
1528 				StringSplit(tmpMeasure, " ", vMeasure);
1529 				if (Idx <= 4)
1530 				{
1531 					//scaled value
1532 					SendCustomSensor(Idx, DIOType_AI, 255, static_cast<float>(atof(vMeasure[0].c_str())), "Analog Input Scaled " + std::to_string(Idx) + " (" + name + ")", vMeasure[1]);
1533 					//raw value
1534 					tmp_adc_raw_value = stdstring_trim(results[ii-1]);
1535 					SendCustomSensor(Idx+8, DIOType_AI, 255, DenkoviGetFloatParameter(tmp_adc_raw_value, DAE_VALUE_DEF), "Analog Input Raw " + std::to_string(Idx) + " (" + name + ")","");
1536 
1537 				}
1538 				else {
1539 					name = "Analog Input " + std::to_string(Idx) + " (" + name + ")";
1540 					if (vMeasure.size() == 2) {
1541 						tmpTiValue = static_cast<float>(atof(vMeasure[0].c_str()));
1542 						if (vMeasure[1] == "degF")
1543 							tmpTiValue = (float)ConvertToCelsius((double)tmpTiValue);
1544 						SendTempSensor(Idx, 255, tmpTiValue, name);
1545 					}
1546 					else
1547 						SendTempSensor(Idx, 255, NAN, name);
1548 				}
1549 				Idx = -1;
1550 				bHaveAnalogInput = false;
1551 				continue;
1552 			}
1553 
1554 			if (bHaveRelay && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1555 			{
1556 				name = "Relay " + std::to_string(Idx) + " (" + name + ")";
1557 				SendSwitch(DIOType_Relay, (uint8_t)Idx, 255, (tmpValue == 1) ? true : false, 0, name);
1558 				Idx = -1;
1559 				bHaveRelay = false;
1560 				continue;
1561 			}
1562 
1563 			if (bHaveAnalogOutput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1564 			{
1565 				name = "Analog Output " + std::to_string(Idx) + " (" + name + ")";
1566 				double val = (100 * tmpValue) / 1023;
1567 				SendGeneralSwitch(DIOType_AO, Idx, 255, (tmpValue > 0) ? true : false, (uint8_t)val, name);
1568 				Idx = -1;
1569 				bHaveAnalogOutput = false;
1570 				continue;
1571 			}
1572 		}
1573 		break;
1574 	}
1575 	case DDEV_DAEnet_IP4: {//has DI, DO, AI, PWM
1576 		bool bHaveDigitalInput = false;
1577 		bool bHaveDigitalOutput = false;
1578 		bool bHaveAnalogInput = false;
1579 		bool bHavePWM = false;
1580 		for (ii = 1; ii < (int)results.size(); ii++)
1581 		{
1582 			tmpstr = stdstring_trim(results[ii]);
1583 
1584 			if (Idx == -1) {
1585 				if (!bHaveDigitalInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_DI_DEF)) != -1))
1586 				{
1587 					bHaveDigitalInput = true;
1588 					continue;
1589 				}
1590 
1591 				if (!bHaveAnalogInput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_AI_DEF)) != -1))
1592 				{
1593 					bHaveAnalogInput = true;
1594 					continue;
1595 				}
1596 
1597 				if (!bHaveDigitalOutput && ((Idx = DenkoviCheckForIO(tmpstr, DAE_OUT_DEF)) != -1))
1598 				{
1599 					bHaveDigitalOutput = true;
1600 					continue;
1601 				}
1602 
1603 				if (!bHavePWM && ((Idx = DenkoviCheckForIO(tmpstr, DAE_PWM_DEF)) != -1))
1604 				{
1605 					bHavePWM = true;
1606 					continue;
1607 				}
1608 			}
1609 
1610 			if ((tmpName = DenkoviGetStrParameter(tmpstr, DAE_NAME_DEF)) != "") {
1611 				name = tmpName;
1612 				continue;
1613 			}
1614 
1615 
1616 			if (bHaveDigitalInput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1617 			{
1618 				SendSwitch(DIOType_DI, (uint8_t)Idx, 255, (tmpValue == 1) ? true : false, 0, "Digital Input " + std::to_string(Idx) + " (" + name + ")");
1619 
1620 				//Check if there is counter
1621 				tmpstr = stdstring_trim(results[ii + 1]);
1622 				if ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_COUNT_DEF)) != -1)
1623 				{
1624 					SendDenkoviTextSensor(DIOType_TXT, Idx + 8, 255, DenkoviGetStrParameter(tmpstr, DAE_COUNT_DEF), "Digital Input Counter " + std::to_string(Idx) + " (" + name + ")");
1625 				}
1626 				Idx = -1;
1627 				bHaveDigitalInput = false;
1628 				continue;
1629 			}
1630 
1631 			if (bHaveAnalogInput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1632 			{
1633 				SendCustomSensor(Idx + 8, 1, 255, static_cast<float>(tmpValue), "Analog Input " + std::to_string(Idx) + " (" + name + ")", "");
1634 
1635 				//Check if there is sclaed value
1636 				tmpstr = stdstring_trim(results[ii + 1]);
1637 				if ((tmpMeasure = DenkoviGetStrParameter(tmpstr, DAE_MEASURE_DEF)) != "")
1638 				{
1639 					std::vector<std::string> vMeasure;
1640 					StringSplit(tmpMeasure, " ", vMeasure);
1641 					if (vMeasure.size() == 2)
1642 					{
1643 						SendCustomSensor(Idx, 1, 255, static_cast<float>(atof(vMeasure[0].c_str())), "Analog Input Scaled " + std::to_string(Idx) + " (" + name + ")", vMeasure[1]);
1644 					}
1645 				}
1646 				Idx = -1;
1647 				bHaveAnalogInput = false;
1648 				continue;
1649 			}
1650 
1651 			if (bHaveDigitalOutput && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1652 			{
1653 				name = "Digital Output " + std::to_string(Idx) + " (" + name + ")";
1654 				SendSwitch(DIOType_DO, (uint8_t)Idx, 255, (tmpValue == 1) ? true : false, 0, name);
1655 				Idx = -1;
1656 				bHaveDigitalOutput = false;
1657 				continue;
1658 			}
1659 
1660 			if (bHavePWM && (Idx != -1) && ((tmpValue = DenkoviGetIntParameter(tmpstr, DAE_VALUE_DEF)) != -1))
1661 			{
1662 				name = "PWM " + std::to_string(Idx) + " (" + name + ")";
1663 				SendGeneralSwitch(DIOType_PWM, Idx, 255, (tmpValue > 0) ? true : false, (uint8_t)tmpValue, name);
1664 				Idx = -1;
1665 				bHavePWM = false;
1666 				continue;
1667 			}
1668 		}
1669 		break;
1670 	}
1671 	}
1672 }
1673