1 //---------------------------------------------------------------------------
2 //
3 //	Notes for RELAY-NET-V5.7 LAN 8 channel relay and binary input card.
4 //
5 //	Hard reset: Hold reset button and power until, after about 10 seconds, one
6 //				of the green LEDS starts to flash to hard reset the relay card
7 //
8 //	After Hard Reset:
9 //	IpAddress 	= 192.168.1.166
10 //	Username	= admin
11 //	Password	= 12345678
12 //
13 //	Connect to it from a browser, type HTTP://192.168.1.166 in the bar.
14 //	Make sure you computer has access to the subnet.
15 //
16 //	Relay-Net-V5.7 card settings:
17 //
18 //	To use Inputs set scene settings to all "xxxxxxxx" for all inputs. This
19 //	give full control of the relays and inputs to domoticz.
20 //
21 //	Password does not matter when only TCP traffic is used.
22 //	When HTTP is used then username / password setting on the module and domoticz must match.
23 //	After init the is user:admin /password:12345678
24 //
25 //	Select power down save
26 //	Deselect Input output correlation
27 //	Deselect scene mode
28 //	Select touch input
29 //
30 //	Make sure TCP address and port match domoticz settings (example addr:192.168.2.241 port:17494)
31 //	Set HTTP port to 80 so you can access the module from your browser.
32 //	If you have multiple modules make sure mac address settings are unique.
33 //	Set Default Gateway, Primary & Secondary DNS server to 0.0.0.0 in most cases.
34 //
35 //	To test the card using Linux curl:
36 //	Turn  relay1 on:	curl --basic --user admin:12345678 --silent --data "saida1on=on"
37 //	Turn  relay1 off:	curl --basic --user admin:12345678 --silent --data "saida1off=off"
38 //	Pulse relay1 on:	curl --basic --user admin:12345678 --silent --data "saida1pluse=pluse"
39 //	(firmware pulse -> pluse)
40 //
41 //	Relays: saida1..saida8 ~ relay1..relay8
42 //			saida9 = ALL off, on or pluse
43 //
44 //	TCP command examples:
45 //	L1\r\n		Turn on relay 1
46 //	LA\r\n		Turn on all relays
47 //	D1\r\n		Turn off relay1
48 //	DA\r\n		Turn off all relays
49 //	P1\r\n		Pulse relay 1
50 //	R1\r\n		Read state relay1
51 //	DUMP\r\n	Read state of all relays and all inputs
52 //
53 //	setr00000001\r\n 	set all relays in one go
54 //	getr\r\n			get status of all relays in one go (result getr00000001)
55 //
56 //	Using scenes (we disable this by putting all xxxxxxxx)
57 //
58 //	INON=?\r\n
59 //	result:
60 //	INON1 = xxxxxxxx\r\n
61 //	INON2 = xxxxxxxx\r\n
62 //	INON3 = xxxxxxxx\r\n
63 //	INON4 = xxxxxxxx\r\n
64 //	INON5 = xxxxxxxx\r\n
65 //	INON6 = xxxxxxxx\r\n
66 //	INON7 = xxxxxxxx\r\n
67 //	INON8 = xxxxxxxx\r\n
68 //
69 //	INOFF=?\r\n
70 //	result:
71 //	INOFF1 = xxxxxxxx\r\n
72 //	INOFF2 = xxxxxxxx\r\n
73 //	INOFF3 = xxxxxxxx\r\n
74 //	INOFF4 = xxxxxxxx\r\n
75 //	INOFF5 = xxxxxxxx\r\n
76 //	INOFF6 = xxxxxxxx\r\n
77 //	INOFF7 = xxxxxxxx\r\n
78 //	INOFF8 = xxxxxxxx\r\n
79 //
80 //	INON1 = xxxxxxxx\r\n scene 1 ON part
81 //	result:
82 //	INON1 = xxxxxxxx\r\n
83 //
84 //	INOFF1 = xxxxxxxx\r\n scene 1 OFF part
85 //	result:
86 //	INOFF1 = xxxxxxxx\r\n
87 //
88 //	RESTART\r\n restart controller, takes 60 seconds before controller becomes responsive
89 //
90 //	Wifi ESP8266 Relay Module 10A Network Relay
91 //
92 //---------------------------------------------------------------------------
93 #include "stdafx.h"
94 #include "RelayNet.h"
95 #include "hardwaretypes.h"
96 #include "ASyncTCP.h"
97 #include "../main/Helper.h"
98 #include "../main/Logger.h"
99 #include "../main/localtime_r.h"
100 #include "../main/mainworker.h"
101 #include "../main/SQLHelper.h"
102 #include "../webserver/Base64.h"
103 #include "../httpclient/HTTPClient.h"
104 #include <sstream>
105 
106 //===========================================================================
107 
108 #define	RELAYNET_USE_HTTP 					false
109 #define RELAYNET_POLL_INPUTS				true
110 #define RELAYNET_POLL_RELAYS		 		true
111 #define RELAYNET_MIN_POLL_INTERVAL 			1
112 #define MAX_INPUT_COUNT						64
113 #define MAX_RELAY_COUNT						64
114 #define KEEP_ALIVE_INTERVAL					10
115 #define RETRY_DELAY 						30
116 
117 //===========================================================================
118 
RelayNet(const int ID,const std::string & IPAddress,const unsigned short usIPPort,const std::string & username,const std::string & password,const bool pollInputs,const bool pollRelays,const int pollInterval,const int inputCount,const int relayCount)119 RelayNet::RelayNet(const int ID, const std::string &IPAddress, const unsigned short usIPPort, const std::string &username, const std::string &password, const bool pollInputs, const bool pollRelays, const int pollInterval, const int inputCount, const int relayCount) :
120 	m_szIPAddress(IPAddress),
121 	m_username(CURLEncode::URLEncode(username)),
122 	m_password(CURLEncode::URLEncode(password))
123 {
124 	m_setup_devices = true;
125 	m_bOutputLog = false;
126 	m_bIsStarted = false;
127 	m_HwdID = ID;
128 	m_usIPPort = usIPPort;
129 	m_poll_inputs = pollInputs;
130 	m_poll_relays = pollRelays;
131 	m_input_count = inputCount;
132 	m_relay_count = relayCount;
133 	m_poll_interval = pollInterval;
134 	m_skip_relay_update	= 0;
135 	m_retrycntr = 0;
136 
137 	if (inputCount == 0)
138 	{
139 		m_poll_inputs = false;
140 	}
141 
142 	if (relayCount == 0)
143 	{
144 		m_poll_relays = false;
145 	}
146 
147 	if (pollInterval < RELAYNET_MIN_POLL_INTERVAL)
148 	{
149 		m_poll_interval = RELAYNET_MIN_POLL_INTERVAL;
150 	}
151 }
152 
153 //===========================================================================
154 
~RelayNet(void)155 RelayNet::~RelayNet(void)
156 {
157 }
158 
159 //===========================================================================
160 
StartHardware()161 bool RelayNet::StartHardware()
162 {
163 	RequestStart();
164 
165 	bool bOk = false;;
166 	m_bIsStarted = false;
167 	m_setup_devices = false;
168 	m_bIsStarted = false;
169 	m_retrycntr = RETRY_DELAY; //force connect the next first time
170 
171 	if (m_input_count || m_relay_count)
172 	{
173 		m_thread = std::make_shared<std::thread>(&RelayNet::Do_Work, this);
174 		SetThreadNameInt(m_thread->native_handle());
175 	}
176 
177 	if (m_thread)
178 	{
179 		bOk = true;
180 		m_bIsStarted=true;
181 	}
182 
183 	return bOk;
184 }
185 
186 //===========================================================================
187 
StopHardware()188 bool RelayNet::StopHardware()
189 {
190 	if (m_thread)
191 	{
192 		RequestStop();
193 		m_thread->join();
194 		m_thread.reset();
195 	}
196 	m_bIsStarted = false;
197 	_log.Log(LOG_STATUS, "RelayNet: Relay Module disconnected %s", m_szIPAddress.c_str());
198 
199 	return true;
200 }
201 
202 //===========================================================================
203 
WriteToHardware(const char * pdata,const unsigned char length)204 bool RelayNet::WriteToHardware(const char *pdata, const unsigned char length)
205 {
206 #if RELAYNET_USE_HTTP
207 	return WriteToHardwareHttp(pdata);
208 #else
209 	return WriteToHardwareTcp(pdata);
210 #endif
211 }
212 
213 //===========================================================================
214 
Do_Work()215 void RelayNet::Do_Work()
216 {
217 	int sec_counter = 0;
218 
219 	/*  Init  */
220 	Init();
221 
222 	if (m_poll_inputs || m_poll_relays)
223 	{
224 		_log.Log(LOG_STATUS, "RelayNet: %d-second poller started (%s)", m_poll_interval, m_szIPAddress.c_str());
225 	}
226 	connect(m_szIPAddress,m_usIPPort);
227 	/*  One second sleep  */
228 	while (!IsStopRequested(1000))
229 	{
230 		sec_counter++;
231 
232 		/*  Heartbeat maintenance  */
233 		if (sec_counter  % 10 == 0)
234 		{
235 			m_LastHeartbeat = mytime(NULL);
236 		}
237 
238 		/*  Prevent disconnect request by Relay Module  */
239 		if ((sec_counter % KEEP_ALIVE_INTERVAL == 0) &&
240 			((m_poll_interval > KEEP_ALIVE_INTERVAL) || (!m_poll_inputs && !m_poll_relays)))
241 		{
242 			KeepConnectionAlive();
243 		}
244 
245 		/*  Update relay module status when poll interval has expired  */
246 		if ((m_poll_inputs || m_poll_relays) && (sec_counter % m_poll_interval == 0))
247 		{
248 			TcpRequestRelaycardDump();
249 		}
250 	}
251 	terminate();
252 
253 	/*  Done  */
254 	if (m_poll_inputs || m_poll_relays)
255 	{
256 		_log.Log(LOG_STATUS, "RelayNet: %d-second poller stopped (%s)", m_poll_interval, m_szIPAddress.c_str());
257 	}
258 }
259 
260 //===========================================================================
261 
Init()262 void RelayNet::Init()
263 {
264 	BYTE id1 = 0x03;
265 	BYTE id2 = 0x0E;
266 	BYTE id3 = 0x0E;
267 	BYTE id4 = m_HwdID & 0xFF;
268 
269 	/* 	Prepare packet for LIGHTING2 relay status packet  */
270 	memset(&m_Packet, 0, sizeof(m_Packet));
271 
272 	if (m_HwdID > 0xFF)
273 	{
274 		id3 = (m_HwdID >> 8) & 0xFF;
275 	}
276 
277 	if (m_HwdID > 0xFFFF)
278 	{
279 		id3 = (m_HwdID >> 16) & 0xFF;
280 	}
281 
282 	m_Packet.LIGHTING2.packetlength = sizeof(m_Packet.LIGHTING2) - 1;
283 	m_Packet.LIGHTING2.packettype = pTypeLighting2;
284 	m_Packet.LIGHTING2.subtype = sTypeAC;
285 	m_Packet.LIGHTING2.unitcode = 0;
286 	m_Packet.LIGHTING2.id1 = id1;
287 	m_Packet.LIGHTING2.id2 = id2;
288 	m_Packet.LIGHTING2.id3 = id3;
289 	m_Packet.LIGHTING2.id4 = id4;
290 	m_Packet.LIGHTING2.cmnd = 0;
291 	m_Packet.LIGHTING2.level = 0;
292 	m_Packet.LIGHTING2.filler = 0;
293 	m_Packet.LIGHTING2.rssi = 12;
294 
295 	SetupDevices();
296 }
297 
298 //===========================================================================
299 
SetupDevices()300 void RelayNet::SetupDevices()
301 {
302 	std::vector<std::vector<std::string> > result;
303 	char szIdx[10];
304 
305 	sprintf(szIdx, "%X%02X%02X%02X",
306 		m_Packet.LIGHTING2.id1,
307 		m_Packet.LIGHTING2.id2,
308 		m_Packet.LIGHTING2.id3,
309 		m_Packet.LIGHTING2.id4);
310 
311 	if (m_relay_count)
312 	{
313 		for (int relayNumber = 1; relayNumber <= m_relay_count; relayNumber++)
314 		{
315 			result = m_sql.safe_query("SELECT Name,nValue,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit==%d)", m_HwdID, szIdx, relayNumber);
316 
317 			if (result.empty())
318 			{
319 				_log.Log(LOG_STATUS, "RelayNet: Create %s/Relay%i", m_szIPAddress.c_str(), relayNumber);
320 
321 				m_sql.InsertDevice(m_HwdID, szIdx, relayNumber, pTypeLighting2, sTypeAC, STYPE_OnOff, 0, " ", "Relay");
322 			}
323 		}
324 	}
325 
326 	if (m_input_count)
327 	{
328 		for (int inputNumber = 1; inputNumber <= m_input_count; inputNumber++)
329 		{
330 			result = m_sql.safe_query("SELECT Name,nValue,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit==%d)", m_HwdID, szIdx, 100 + inputNumber);
331 
332 			if (result.empty())
333 			{
334 				_log.Log(LOG_STATUS, "RelayNet: Create %s/Input%i", m_szIPAddress.c_str(), inputNumber);
335 
336 				m_sql.InsertDevice(m_HwdID, szIdx, 100 + inputNumber, pTypeLighting2, sTypeAC, int(STYPE_Contact), 0, " ", "Input");
337 			}
338 		}
339 	}
340 }
341 
342 //===========================================================================
343 
TcpRequestRelaycardDump()344 void RelayNet::TcpRequestRelaycardDump()
345 {
346 	std::string	sRequest = "DUMP\r\n";
347 
348 	write(sRequest);
349 }
350 
351 //===========================================================================
352 
KeepConnectionAlive()353 void RelayNet::KeepConnectionAlive()
354 {
355 	std::string	sRequest = "R1\r\n";
356 
357 	write(sRequest);
358 }
359 
360 //===========================================================================
361 
TcpGetSetRelay(int RelayNumber,bool SetRelay,bool State)362 void RelayNet::TcpGetSetRelay(int RelayNumber, bool SetRelay, bool State)
363 {
364 	char sndbuf[4];
365 
366 	if (SetRelay)
367 	{
368 		if (State)
369 		{
370 			sndbuf[0] = 'L'; 	//	Turn relay on & get status
371 		}
372 		else
373 		{
374 			sndbuf[0] = 'D'; 	//	Turn relay off & get status
375 		}
376 	}
377 	else
378 	{
379 		sndbuf[0] = 'R'; 		//	Get relay status
380 	}
381 
382 	sndbuf[1] = 0x30 + (char) RelayNumber;
383 	sndbuf[2] = '\r';
384 	sndbuf[3] = '\n';
385 
386 	write((const unsigned char*)&sndbuf[0], (size_t) sizeof(sndbuf));
387 }
388 
SetRelayState(int RelayNumber,bool State)389 void RelayNet::SetRelayState(int RelayNumber, bool State)
390 {
391 	TcpGetSetRelay(RelayNumber, true, State);
392 
393 	if (m_poll_relays)
394 	{
395 		m_skip_relay_update++;
396 	}
397 }
398 
399 //===========================================================================
400 
WriteToHardwareTcp(const char * pdata)401 bool RelayNet::WriteToHardwareTcp(const char *pdata)
402 {
403 	bool bOk = true;
404 
405 	const tRBUF *pSen = reinterpret_cast<const tRBUF*>(pdata);
406 	unsigned char packettype = pSen->ICMND.packettype;
407 
408 	if (packettype == pTypeLighting2)
409 	{
410 		int relay = pSen->LIGHTING2.unitcode;
411 
412 		if ((relay >= 1) && (relay <= m_relay_count))
413 		{
414 			if (pSen->LIGHTING2.cmnd == light2_sOn)
415 			{
416 				SetRelayState(relay, true);
417 			}
418 			else
419 			{
420 				SetRelayState(relay, false);
421 			}
422 		}
423 		else
424 		{
425 			bOk = false;
426 		}
427 	}
428 
429 	return bOk;
430 }
431 
432 //===========================================================================
433 
UpdateDomoticzInput(int InputNumber,bool State)434 void RelayNet::UpdateDomoticzInput(int InputNumber, bool State)
435 {
436 	bool updateDatabase = false;
437 	std::vector<std::vector<std::string> > result;
438 	char szIdx[10];
439 
440 	sprintf(szIdx, "%X%02X%02X%02X",
441 		m_Packet.LIGHTING2.id1,
442 		m_Packet.LIGHTING2.id2,
443 		m_Packet.LIGHTING2.id3,
444 		m_Packet.LIGHTING2.id4);
445 
446 	result = m_sql.safe_query("SELECT Name,nValue,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit==%d)", m_HwdID, szIdx, 100 + InputNumber);
447 
448 	if ((!result.empty()) && (result.size()>0))
449 	{
450 		std::vector<std::string> sd=result[0];
451 		bool dbState = true;
452 
453 		if (atoi(sd[1].c_str()) == 0)
454 		{
455 			dbState = false;
456 		}
457 
458 		if (dbState != State)
459 		{
460 			updateDatabase = true;
461 		}
462 	}
463 
464 	if (updateDatabase)
465 	{
466 		if (State)
467 		{
468 			m_Packet.LIGHTING2.cmnd = light2_sOn;
469 			m_Packet.LIGHTING2.level = 100;
470 		}
471 		else
472 		{
473 			m_Packet.LIGHTING2.cmnd = light2_sOff;
474 			m_Packet.LIGHTING2.level = 0;
475 		}
476 		m_Packet.LIGHTING2.unitcode = 100 + (char) InputNumber;
477 		m_Packet.LIGHTING2.seqnbr++;
478 
479 		/* send packet to Domoticz */
480 		sDecodeRXMessage(this, (const unsigned char *)&m_Packet.LIGHTING2, "Input", 255);
481 	}
482 }
483 
484 //===========================================================================
485 
UpdateDomoticzRelay(int RelayNumber,bool State)486 void RelayNet::UpdateDomoticzRelay(int RelayNumber, bool State)
487 {
488 	bool updateDatabase = false;
489 	std::vector<std::vector<std::string> > result;
490 	char szIdx[10];
491 
492 	sprintf(szIdx, "%X%02X%02X%02X",
493 		m_Packet.LIGHTING2.id1,
494 		m_Packet.LIGHTING2.id2,
495 		m_Packet.LIGHTING2.id3,
496 		m_Packet.LIGHTING2.id4);
497 
498 	result = m_sql.safe_query("SELECT Name,nValue,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit==%d)", m_HwdID, szIdx, RelayNumber);
499 
500 	if ((!result.empty()) && (result.size()>0))
501 	{
502 		std::vector<std::string> sd = result[0];
503 		bool dbState = true;
504 
505 		if (atoi(sd[1].c_str()) == 0)
506 		{
507 			dbState = false;
508 		}
509 
510 		if (dbState != State)
511 		{
512 			updateDatabase = true;
513 		}
514 	}
515 
516 	if (updateDatabase)
517 	{
518 		if (State)
519 		{
520 			m_Packet.LIGHTING2.cmnd = light2_sOn;
521 			m_Packet.LIGHTING2.level = 100;
522 		}
523 		else
524 		{
525 			m_Packet.LIGHTING2.cmnd = light2_sOff;
526 			m_Packet.LIGHTING2.level = 0;
527 		}
528 		m_Packet.LIGHTING2.unitcode = (char) RelayNumber;
529 		m_Packet.LIGHTING2.seqnbr++;
530 
531 		/* send packet to Domoticz */
532 		sDecodeRXMessage(this, (const unsigned char *)&m_Packet.LIGHTING2, "Relay", 255);
533 	}
534 }
535 
536 //===========================================================================
537 
ProcessRelaycardDump(char * Dump)538 void RelayNet::ProcessRelaycardDump(char* Dump)
539 {
540 	char	cTemp[16];
541 	std::string sDump;
542 	std::string sChkstr;
543 
544 	sDump = Dump;
545 	boost::to_upper(sDump);
546 
547 	if (!m_skip_relay_update && m_relay_count && (m_poll_relays || m_setup_devices))
548 	{
549 		for (uint16_t i=1; i <= m_relay_count ; i++)
550 		{
551 			snprintf(&cTemp[0], sizeof(cTemp), "RELAYON %d", i);
552 			sChkstr = cTemp;
553 
554 			if(sDump.find(sChkstr) != std::string::npos)
555 			{
556 				UpdateDomoticzRelay(i, true);
557 			}
558 
559 			snprintf(&cTemp[0], sizeof(cTemp), "RELAYOFF %d", i);
560 			sChkstr = cTemp;
561 
562 			if (sDump.find(sChkstr) != std::string::npos)
563 			{
564 				UpdateDomoticzRelay(i, false);
565 			}
566 		}
567 	}
568 
569 	if (m_input_count && (m_poll_inputs || m_setup_devices))
570 	{
571 		for (uint16_t i = 1; i <= m_input_count; i++)
572 		{
573 			snprintf(&cTemp[0], sizeof(cTemp), "IH %d", i);
574 			sChkstr = cTemp;
575 
576 			if (sDump.find(sChkstr) != std::string::npos)
577 			{
578 				UpdateDomoticzInput(i, true);
579 			}
580 
581 			snprintf(&cTemp[0], sizeof(cTemp), "IL %d", i);
582 			sChkstr = cTemp;
583 
584 			if (sDump.find(sChkstr) != std::string::npos)
585 			{
586 				UpdateDomoticzInput(i, false);
587 			}
588 		}
589 	}
590 
591 	/* housekeeping */
592 	m_setup_devices = false;
593 
594 	if (m_skip_relay_update)
595 	{
596 		m_skip_relay_update--;
597 	}
598 }
599 
600 //===========================================================================
601 
ParseData(const unsigned char * pData,int Len)602 void RelayNet::ParseData(const unsigned char *pData, int Len)
603 {
604 	char relayCardDump[512];
605 
606 	if ((Len > 64) && (Len <= sizeof(relayCardDump)))
607 	{
608 		/* Its a RelayCard dump message */
609 		memset(&relayCardDump[0], 0, Len);
610 		memcpy(&relayCardDump[0], pData, Len);
611 		ProcessRelaycardDump(&relayCardDump[0]);
612 	}
613 }
614 
615 //===========================================================================
616 //
617 //	Alternate way of turning relays on/off using HTTP.
618 //	Currently not used.
619 //
WriteToHardwareHttp(const char * pdata)620 bool RelayNet::WriteToHardwareHttp(const char *pdata)
621 {
622 	//-----------------------------------------------------------------------
623 	//
624 	//	Notes:
625 	//
626 	//	Use OpenSSL to manually create a base64 authorization string.
627 	//
628 	//	Example:
629 	//  echo -n "admin:ok" | openssl base64 -base64
630 	//	Output generated: WRtaW46b2s=
631 	//
632 	//	To use the string:
633 	//	std::string sAccessToken = "YWRtaW46b2s=";
634 	//
635 	//-----------------------------------------------------------------------
636 
637 	const tRBUF *pSen = reinterpret_cast<const tRBUF*>(pdata);
638 	unsigned char packettype = pSen->ICMND.packettype;
639 
640 	if (packettype == pTypeLighting2)
641 	{
642 		std::stringstream 			sRelayCommand;
643 		std::stringstream 			sLogin;
644 		std::string 				sAccessToken;
645 		std::stringstream			sURL;
646 		std::vector<std::string>	ExtraHeaders;
647 		std::string 				sResult;
648 		int 						relay = pSen->LIGHTING2.unitcode;
649 
650 		if ((relay >= 1) && (relay <= m_relay_count))
651 		{
652 			if (pSen->LIGHTING2.cmnd == light2_sOff)
653 			{
654 				sRelayCommand << "saida" << relay << "off=off";
655 			}
656 			else
657 			{
658 				sRelayCommand << "saida" << relay << "on=on";
659 			}
660 
661 			/*	Setup URL, relay-command and username/password */
662 			std::string sPostData = sRelayCommand.str();
663 			sURL << "http://" << m_szIPAddress << "/relay_en.cgi";
664 			sLogin << m_username << ":" << m_password;
665 
666 			/* Generate UnEncrypted base64 Basic Authorization for username/password and add result to ExtraHeaders */
667 			sAccessToken = base64_encode(sLogin.str());
668 			ExtraHeaders.push_back("Authorization: Basic " + sAccessToken);
669 
670 			/* Send URL to relay module and check return status */
671 			if (!HTTPClient::POST(sURL.str(), sPostData, ExtraHeaders, sResult))
672 			{
673 				_log.Log(LOG_ERROR, "RelayNet: [1] Error sending relay command to: %s", m_szIPAddress.c_str());
674 				return false;
675 			}
676 
677 			/* Look for "saida" in response, if present all should be ok */
678 			if (sResult.find("saida") == std::string::npos)
679 			{
680 				_log.Log(LOG_ERROR, "RelayNet: [2] Error sending relay command to: %s", m_szIPAddress.c_str());
681 				return false;
682 			}
683 
684 			return true;
685 		}
686 	}
687 
688 	return false;
689 }
690 
691 //===========================================================================
692 //
693 //							ASyncTCP support
694 //
OnConnect()695 void RelayNet::OnConnect()
696 {
697 	_log.Log(LOG_STATUS, "RelayNet: Connected to Relay Module %s", m_szIPAddress.c_str());
698 	m_bIsStarted = true;
699 }
700 
701 //===========================================================================
702 
OnDisconnect()703 void RelayNet::OnDisconnect()
704 {
705 	_log.Log(LOG_STATUS, "RelayNet: Relay Module disconnected %s, reconnect", m_szIPAddress.c_str());
706 }
707 
708 //===========================================================================
709 
OnData(const unsigned char * pData,size_t length)710 void RelayNet::OnData(const unsigned char *pData, size_t length)
711 {
712 	ParseData(pData, length);
713 }
714 
715 //===========================================================================
716 
OnError(const boost::system::error_code & error)717 void RelayNet::OnError(const boost::system::error_code& error)
718 {
719 	if ((error == boost::asio::error::address_in_use) ||
720 		(error == boost::asio::error::connection_refused) ||
721 		(error == boost::asio::error::access_denied) ||
722 		(error == boost::asio::error::host_unreachable) ||
723 		(error == boost::asio::error::timed_out))
724 	{
725 		_log.Log(LOG_ERROR, "RelayNet: OnError: Can not connect to: %s:%d", m_szIPAddress.c_str(), m_usIPPort);
726 	}
727 	else if ((error == boost::asio::error::eof) || (error == boost::asio::error::connection_reset))
728 	{
729 		_log.Log(LOG_STATUS, "RelayNet: OnError: Connection reset!");
730 	}
731 	else
732 	{
733 		_log.Log(LOG_ERROR, "RelayNet: OnError: %s", error.message().c_str());
734 	}
735 }
736 
737 //===========================================================================
738