1 #include "stdafx.h"
2 #include "CurrentCostMeterTCP.h"
3 #include "../main/Logger.h"
4 #include "../main/Helper.h"
5 #include "../main/localtime_r.h"
6 #include <iostream>
7 
8 #define RETRY_DELAY 30
9 
CurrentCostMeterTCP(const int ID,const std::string & IPAddress,const unsigned short usIPPort)10 CurrentCostMeterTCP::CurrentCostMeterTCP(const int ID, const std::string &IPAddress, const unsigned short usIPPort):
11 	m_retrycntr(RETRY_DELAY),
12 	m_szIPAddress(IPAddress),
13 	m_usIPPort(usIPPort),
14 	m_socket(INVALID_SOCKET)
15 {
16 	m_HwdID=ID;
17 }
18 
~CurrentCostMeterTCP(void)19 CurrentCostMeterTCP::~CurrentCostMeterTCP(void)
20 {
21 }
22 
StartHardware()23 bool CurrentCostMeterTCP::StartHardware()
24 {
25 	RequestStart();
26 
27 	memset(&m_addr,0,sizeof(sockaddr_in));
28 	m_addr.sin_family = AF_INET;
29 	m_addr.sin_port = htons(m_usIPPort);
30 
31 	unsigned long ip;
32 	ip=inet_addr(m_szIPAddress.c_str());
33 
34 	// if we have a error in the ip, it means we have entered a string
35 	if(ip!=INADDR_NONE)
36 	{
37 		m_addr.sin_addr.s_addr=ip;
38 	}
39 	else
40 	{
41 		// change Hostname in serveraddr
42 		hostent *he=gethostbyname(m_szIPAddress.c_str());
43 		if(he==NULL)
44 		{
45 			return false;
46 		}
47 		else
48 		{
49 			memcpy(&(m_addr.sin_addr),he->h_addr_list[0],4);
50 		}
51 	}
52 
53 	//force connect the next first time
54 	m_retrycntr=RETRY_DELAY;
55 	m_bIsStarted=true;
56 
57 	//Start worker thread
58 	m_thread = std::make_shared<std::thread>(&CurrentCostMeterTCP::Do_Work, this);
59 	SetThreadNameInt(m_thread->native_handle());
60 	return (m_thread != nullptr);
61 }
62 
isConnected()63 bool CurrentCostMeterTCP::isConnected()
64 {
65 	return (m_socket != INVALID_SOCKET);
66 }
67 
StopHardware()68 bool CurrentCostMeterTCP::StopHardware()
69 {
70 	if (m_thread)
71 	{
72 		RequestStop();
73 		disconnect(); //force socket close to unblock the read request in the thread
74 		m_thread->join();
75 		m_thread.reset();
76 	}
77 	m_bIsStarted=false;
78 	return true;
79 }
80 
ConnectInternal()81 bool CurrentCostMeterTCP::ConnectInternal()
82 {
83 	m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
84 	if (m_socket == INVALID_SOCKET)
85 	{
86 		Log(LOG_ERROR,"could not create a TCP/IP socket!");
87 		return false;
88 	}
89 
90 	// connect to the server
91 	int nRet;
92 	nRet = connect(m_socket,(const sockaddr*)&m_addr, sizeof(m_addr));
93 	if (nRet == SOCKET_ERROR)
94 	{
95 		closesocket(m_socket);
96 		m_socket=INVALID_SOCKET;
97 		Log(LOG_ERROR,"could not connect to: %s:%d",m_szIPAddress.c_str(),m_usIPPort);
98 		return false;
99 	}
100 
101 	Log(LOG_STATUS,"connected to: %s:%d", m_szIPAddress.c_str(), m_usIPPort);
102 
103 	Init();
104 
105 	sOnConnected(this);
106 	return true;
107 }
108 
disconnect()109 void CurrentCostMeterTCP::disconnect()
110 {
111 	if (m_socket==INVALID_SOCKET)
112 		return;
113 	closesocket(m_socket);
114 	m_socket=INVALID_SOCKET;
115 }
116 
117 
Do_Work()118 void CurrentCostMeterTCP::Do_Work()
119 {
120 	int sec_counter = 0;
121 	while (!IsStopRequested(100))
122 	{
123 		if (m_socket == INVALID_SOCKET)
124 		{
125 			if (!IsStopRequested(900)) //+100 = 1000
126 			{
127 				sec_counter++;
128 
129 				if (sec_counter % 12 == 0) {
130 					m_LastHeartbeat = mytime(NULL);
131 				}
132 
133 				m_retrycntr++;
134 				if (m_retrycntr >= RETRY_DELAY)
135 				{
136 					m_retrycntr = 0;
137 					if (!ConnectInternal())
138 					{
139 						Log(LOG_STATUS, "retrying in %d seconds...", RETRY_DELAY);
140 						continue;
141 					}
142 				}
143 			}
144 		}
145 		else
146 		{
147 			char data[1028];
148 			int bread=recv(m_socket,data,sizeof(data),0);
149 			if (IsStopRequested(100))
150 				break;
151 			m_LastHeartbeat=mytime(NULL);
152 			if ((bread==0)||(bread<0))
153 			{
154 				disconnect();
155 				Log(LOG_ERROR, "TCP/IP connection closed!, retrying in %d seconds...", RETRY_DELAY);
156 				m_retrycntr = 0;
157 				continue;
158 			}
159 			ParseData(data, bread);
160 		}
161 	}
162 	Log(LOG_STATUS,"TCP/IP Worker stopped...");
163 }
164 
write(const char *,size_t)165 void CurrentCostMeterTCP::write(const char* /*data*/, size_t /*size*/)
166 {
167 }
168 
WriteToHardware(const char * pdata,const unsigned char length)169 bool CurrentCostMeterTCP::WriteToHardware(const char *pdata, const unsigned char length)
170 {
171 	if (!isConnected())
172 		return false;
173 	write(pdata,length);
174 	return true;
175 }
176