1 #include "stdafx.h"
2 #include "Sterbox.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 //http://sterbox.eu/index.php/sterbox
13 
14 #define STERBOX_POLL_INTERVAL 8
15 
CSterbox(const int ID,const std::string & IPAddress,const unsigned short usIPPort,const std::string & username,const std::string & password)16 CSterbox::CSterbox(const int ID, const std::string &IPAddress, const unsigned short usIPPort, const std::string &username, const std::string &password) :
17 m_szIPAddress(IPAddress),
18 m_Username(username),
19 m_Password(password)
20 {
21 	m_HwdID=ID;
22 	m_usIPPort=usIPPort;
23 	m_bOutputLog = false;
24 	Init();
25 }
26 
~CSterbox(void)27 CSterbox::~CSterbox(void)
28 {
29 }
30 
Init()31 void CSterbox::Init()
32 {
33 }
34 
StartHardware()35 bool CSterbox::StartHardware()
36 {
37 	RequestStart();
38 
39 	Init();
40 	//Start worker thread
41 	m_thread = std::make_shared<std::thread>(&CSterbox::Do_Work, this);
42 	SetThreadNameInt(m_thread->native_handle());
43 	m_bIsStarted=true;
44 	sOnConnected(this);
45 	_log.Log(LOG_STATUS, "Sterbox: Started");
46 	return (m_thread != nullptr);
47 }
48 
StopHardware()49 bool CSterbox::StopHardware()
50 {
51 	if (m_thread)
52 	{
53 		RequestStop();
54 		m_thread->join();
55 		m_thread.reset();
56 	}
57     m_bIsStarted=false;
58     return true;
59 }
60 
Do_Work()61 void CSterbox::Do_Work()
62 {
63 	int sec_counter = STERBOX_POLL_INTERVAL - 2;
64 
65 	while (!IsStopRequested(1000))
66 	{
67 		sec_counter++;
68 
69 		if (sec_counter % 12 == 0) {
70 			m_LastHeartbeat=mytime(NULL);
71 		}
72 
73 		if (sec_counter % STERBOX_POLL_INTERVAL == 0)
74 		{
75 			GetMeterDetails();
76 		}
77 	}
78 	_log.Log(LOG_STATUS,"Sterbox: Worker stopped...");
79 }
80 
WriteToHardware(const char * pdata,const unsigned char length)81 bool CSterbox::WriteToHardware(const char *pdata, const unsigned char length)
82 {
83 	const tRBUF *pSen = reinterpret_cast<const tRBUF*>(pdata);
84 
85 	unsigned char packettype = pSen->ICMND.packettype;
86 	//unsigned char subtype = pSen->ICMND.subtype;
87 
88 	if (packettype == pTypeLighting2)
89 	{
90 		//light command
91 
92 		int Relay = pSen->LIGHTING2.unitcode;
93 		if (Relay > 20)
94 			return false;
95 
96 		std::stringstream szURL;
97 		//std::stringstream szhex;
98 		//szhex << std::hex << Relay;
99 		//std::string strhex = szhex.str();
100 		//_log.Log(LOG_ERROR, "Sterbox: Size od szhex: %s", strhex.c_str());
101 
102 
103 		//if (m_Password.empty())
104 		//{
105 			szURL << "http://" << m_szIPAddress << ":" << m_usIPPort;
106 		//}
107 		//else
108 		//{
109 		//	szURL << "http://" << m_Username << ":" << m_Password << "@" << m_szIPAddress << ":" << m_usIPPort;
110 		//}
111 
112 		szURL << "/x?x00" << std::uppercase << std::hex << Relay;
113 
114 		if (pSen->LIGHTING2.cmnd == light2_sOff)
115 		{
116 			szURL << "=0";
117 		}
118 		else
119 		{
120 			szURL << "=0";
121 		}
122 		std::string sResult;
123 		if (!HTTPClient::GET(szURL.str(), sResult))
124 		{
125 			_log.Log(LOG_ERROR, "Sterbox: Protocol Error sending relay command to: %s", m_szIPAddress.c_str());
126 			return false;
127 		}
128 		std::string strhex = szURL.str();
129 		_log.Log(LOG_STATUS, "Sterbox: sending relay command to: %s", strhex.c_str());
130 
131 		return true;
132 	}
133 	return false;
134 }
135 
UpdateSwitch(const unsigned char Idx,const int SubUnit,const bool bOn,const double Level,const std::string & defaultname)136 void CSterbox::UpdateSwitch(const unsigned char Idx, const int SubUnit, const bool bOn, const double Level, const std::string &defaultname)
137 {
138 	double rlevel = (15.0 / 100)*Level;
139 	int level = int(rlevel);
140 
141 	char szIdx[10];
142 	sprintf(szIdx, "%X%02X%02X%02X", 0, 0, 0, Idx);
143 	std::vector<std::vector<std::string> > result;
144 	result = m_sql.safe_query("SELECT Name,nValue,sValue FROM DeviceStatus WHERE (HardwareID==%d) AND (DeviceID=='%q') AND (Unit==%d)", m_HwdID, szIdx, SubUnit);
145 	if (!result.empty())
146 	{
147 		//check if we have a change, if not do not update it
148 		int nvalue = atoi(result[0][1].c_str());
149 		if ((!bOn) && (nvalue == 0))
150 			return;
151 		if ((bOn && (nvalue != 0)))
152 		{
153 			//Check Level
154 			int slevel = atoi(result[0][2].c_str());
155 			if (slevel == level)
156 				return;
157 		}
158 	}
159 
160 	//Send as Lighting 2
161 	tRBUF lcmd;
162 	memset(&lcmd, 0, sizeof(RBUF));
163 	lcmd.LIGHTING2.packetlength = sizeof(lcmd.LIGHTING2) - 1;
164 	lcmd.LIGHTING2.packettype = pTypeLighting2;
165 	lcmd.LIGHTING2.subtype = sTypeAC;
166 	lcmd.LIGHTING2.id1 = 0;
167 	lcmd.LIGHTING2.id2 = 0;
168 	lcmd.LIGHTING2.id3 = 0;
169 	lcmd.LIGHTING2.id4 = Idx;
170 	lcmd.LIGHTING2.unitcode = SubUnit;
171 	if (!bOn)
172 	{
173 		lcmd.LIGHTING2.cmnd = light2_sOff;
174 	}
175 	else
176 	{
177 		lcmd.LIGHTING2.cmnd = light2_sOn;
178 	}
179 	lcmd.LIGHTING2.level = level;
180 	lcmd.LIGHTING2.filler = 0;
181 	lcmd.LIGHTING2.rssi = 12;
182 	sDecodeRXMessage(this, (const unsigned char *)&lcmd.LIGHTING2, defaultname.c_str(), 255);
183 }
184 
GetMeterDetails()185 void CSterbox::GetMeterDetails()
186 {
187 	std::string sResult;
188 	std::stringstream szURL;
189 
190 	//if(m_Password.empty())
191 	//{
192 		szURL << "http://" << m_szIPAddress << ":" << m_usIPPort;
193 	//}
194 	//else
195 	//{
196 	//	szURL << "http://" << m_Username << ":" << m_Password << "@" << m_szIPAddress << ":" << m_usIPPort;
197 	//}
198 
199 	szURL << "/x.cgi";
200 
201 	if (!HTTPClient::GET(szURL.str(),sResult))
202 	{
203 		_log.Log(LOG_ERROR,"Sterbox: Error connecting to: %s", m_szIPAddress.c_str());
204 		return;
205 	}
206 	std::vector<std::string> results;
207 	std::vector<std::string> outputs;
208 	std::vector<std::string> inputs;
209 	std::vector<std::string> analog;
210 	StringSplit(sResult, "<br>", results);
211 	if (results.size()<8)
212 	{
213 		_log.Log(LOG_ERROR,"Sterbox: Result 8 Error connecting to: %s", m_szIPAddress.c_str());
214 		return;
215 	}
216 	//if (results[0] != "<body>")
217 	std::string tmpstr;
218 	std::string tmpstr2;
219 	std::string tmpinp;
220 	tmpstr = results[0];
221 	size_t ii;
222 	size_t jj;
223 	int pos1;
224 
225 	if (m_Username.empty())
226 	{
227 		StringSplit("o,o,o,o,i,i,i,i", ",", inputs);
228 	}
229 	else
230 	{
231 		StringSplit(m_Username, ",", inputs);
232 		//_log.Log(LOG_ERROR,"Sterbox: Username : %s , IP: %s", m_Username.c_str(), m_szIPAddress.c_str());
233 	}
234 
235 	for (ii = 1; ii < results.size(); ii++)
236 	{
237 		tmpstr = results[ii];
238 		if (tmpstr.find("OU") != std::string::npos)
239 		{
240 			tmpstr = tmpstr.substr(strlen("OU"));
241 			pos1 = tmpstr.find("=");
242 			if (pos1 != std::string::npos)
243 			{
244 				tmpstr = tmpstr.substr(pos1+1);
245 				//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr.c_str());
246 				StringSplit(tmpstr, ",", outputs);
247 				for (jj = 0; jj < inputs.size(); jj++)
248 				{
249 					tmpinp = inputs[jj];
250 					//if (( jj < 4 || jj > 7  ))
251 					pos1 = tmpinp.find("o");
252 					if (pos1 != std::string::npos)
253 					{
254 					int lValue = 0;
255 					//tmpstr = tmpstr.substr(pos1+1);
256 					tmpstr2 = outputs[jj];
257 					//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr2.c_str());
258 					pos1 = tmpstr2.find("s");
259 					if (pos1 != std::string::npos)
260 					{
261 						lValue = 1;
262 					}
263 					else
264 					{
265 						lValue = 0;
266 					}
267 					std::stringstream sstr;
268 					sstr << "Relay " << jj;
269 					UpdateSwitch(1, jj, (lValue == 1) ? true : false, 100, sstr.str());
270 					}
271 				}
272 			}
273 		}
274 		else if (tmpstr.find("IN") != std::string::npos)
275 		{
276 			tmpstr = tmpstr.substr(strlen("IN"));
277 			pos1 = tmpstr.find("=");
278 			if (pos1 != std::string::npos)
279 			{
280 				tmpstr = tmpstr.substr(pos1+1);
281 				//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr.c_str());
282 				StringSplit(tmpstr, ",", outputs);
283 				for (jj = 0; jj < inputs.size(); jj++)
284 				{
285 					tmpinp = inputs[jj];
286 					//if (( jj > 3 && jj < 8  ))
287 					pos1 = tmpinp.find("i");
288 					if (pos1 != std::string::npos)
289 					{
290 					int lValue = 0;
291 					//tmpstr = tmpstr.substr(pos1+1);
292 					tmpstr2 = outputs[jj];
293 					//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr2.c_str());
294 					pos1 = tmpstr2.find("S");
295 					if (pos1 != std::string::npos)
296 					{
297 						lValue = 1;
298 					}
299 					else
300 					{
301 						lValue = 0;
302 					}
303 					std::stringstream sstr;
304 					sstr << "Relay " << jj;
305 					UpdateSwitch(1, jj, (lValue == 1) ? true : false, 100, sstr.str());
306 					}
307 				}
308 			}
309 		}
310 		else if (tmpstr.find("AN") != std::string::npos)
311 		{
312 			tmpstr = tmpstr.substr(strlen("AN"));
313 			pos1 = tmpstr.find("=");
314 			if (pos1 != std::string::npos)
315 			{
316 				tmpstr = tmpstr.substr(pos1+1);
317 				StringSplit(tmpstr, ",", outputs);
318 				if (m_Password.empty())
319 				{
320 					StringSplit("t,t,t", ",", analog);
321 				}
322 				else
323 				{
324 					//StringSplit("t,t,t", ",", inputs);
325 					StringSplit(m_Password, ",", analog);
326 				//_log.Log(LOG_ERROR,"Sterbox: Pass : %s", m_Password.c_str());
327 
328 				}
329 				for (jj = 0; jj < 3; jj++)
330 				{
331 					tmpstr2 = outputs[jj];
332 					tmpinp = analog[jj];
333 					tmpstr2 = tmpstr2.substr(1, 10);
334 
335 					float lValue = (float)atof(tmpstr2.c_str());
336 					std::stringstream sstr;
337 					sstr << "Analog " << jj;
338 					pos1 = tmpinp.find("t");
339 					if (pos1 != std::string::npos)
340 					{
341 						SendTempSensor(jj,255,lValue, sstr.str());
342 					}
343 					pos1 = tmpinp.find("v");
344 					if (pos1 != std::string::npos)
345 					{
346 						SendVoltageSensor(0, (uint8_t)jj, 255, lValue, sstr.str());
347 					}
348 					pos1 = tmpinp.find("l");
349 					if (pos1 != std::string::npos)
350 					{
351 						SendLuxSensor(0, (uint8_t)jj, 255,lValue, sstr.str());
352 					}
353 					pos1 = tmpinp.find("h");
354 					if (pos1 != std::string::npos)
355 					{
356 						SendHumiditySensor(jj,255,int(lValue), sstr.str());
357 					}
358 
359 					//SendTempSensor(jj,255,lValue, sstr.str());
360 					//_log.Log(LOG_ERROR,"Sterbox: OU Status: %s", tmpstr2.c_str());
361 
362 				}
363 				//int Idx = atoi(tmpstr.substr(0, pos1).c_str());
364 				//tmpstr = tmpstr.substr(pos1 + 1);
365 				//pos1 = tmpstr.find("<");
366 				//if (pos1 != std::string::npos)
367 				//{
368 				//	int lValue = atoi(tmpstr.substr(0, pos1).c_str());
369 				//	float voltage = (float)(5.0f / 1023.0f)*lValue;
370 				//	if (voltage > 5.0f)
371 				//		voltage = 5.0f;
372 				//	std::stringstream sstr;
373 				//	sstr << "Voltage " << Idx;
374 				//	SendVoltageSensor(0, Idx, 255, voltage, sstr.str());
375 				//}
376 			}
377 		}
378 	}
379 }
380