wipdevice 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- WIPClient/WIPClient.py +280 -0
- WIPClient/WIPClientAbstractModel.py +61 -0
- WIPClient/WIPClient_advance.py +301 -0
- WIPClient/WIPClient_advance_original.py +363 -0
- WIPClient/WIPDevice.py +66 -0
- WIPClient/__init__.py +1 -0
- WIPClient/interface/HTTPSocketManager.py +323 -0
- WIPClient/interface/SocketManager.py +226 -0
- WIPClient/interface/SocketManagerV2.py +498 -0
- WIPClient/interface/WebSocketManager.py +97 -0
- WIPClient/interface/__init__.py +1 -0
- WIPClient/protocol/__init__.py +1 -0
- WIPClient/protocol/advanced/ConstantVar.py +89 -0
- WIPClient/protocol/advanced/JsonDataProtocol.py +87 -0
- WIPClient/protocol/advanced/ModelJsonData.py +17 -0
- WIPClient/protocol/advanced/__init__.py +1 -0
- WIPClient/protocol/advanced/aes256.py +42 -0
- WIPClient/protocol/advanced/commonFunction.py +17 -0
- wipdevice-0.0.1.dist-info/METADATA +20 -0
- wipdevice-0.0.1.dist-info/RECORD +22 -0
- wipdevice-0.0.1.dist-info/WHEEL +5 -0
- wipdevice-0.0.1.dist-info/top_level.txt +1 -0
WIPClient/WIPClient.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import socket
|
|
2
|
+
import time
|
|
3
|
+
import threading
|
|
4
|
+
from .interface import SocketManagerV2
|
|
5
|
+
from .WIPClientAbstractModel import WIPClientAbstractModel
|
|
6
|
+
|
|
7
|
+
class WIPClient(WIPClientAbstractModel, SocketManagerV2.SocketClient):
|
|
8
|
+
# ip : 연결할 서버의 IP
|
|
9
|
+
# port : 연결할 서버의 Port
|
|
10
|
+
# name : 연결할 서버를 구분하기 위한 용도 (ex: iotGateway, AutoVehicle, iotMakers .. 등등)
|
|
11
|
+
def __init__(self, ip="127.0.0.1", port=10008, device_id="device1", device_pw="00000000", isAutoConnect=True, live_receive=True, live_send=False, live_send_interval=1):
|
|
12
|
+
super().__init__(ip, port, "WOW Iot Platform", isAutoConnect=isAutoConnect, live_receive=live_receive)
|
|
13
|
+
self.device_id = str(device_id)
|
|
14
|
+
self.device_pw = str(device_pw)
|
|
15
|
+
self.isCertified = False
|
|
16
|
+
|
|
17
|
+
# 각 데이터가 노드 ID로 구분되기 때문에 WIP Client에서만 사용한다.
|
|
18
|
+
self.live_send = live_send
|
|
19
|
+
self.live_send_run = False
|
|
20
|
+
self.live_send_interval = live_send_interval
|
|
21
|
+
self.socketSendThread = None
|
|
22
|
+
self.sendDataQueues = {}
|
|
23
|
+
|
|
24
|
+
# 서버 자동 접속 쓰레드 호출 시 사용되는 함수 (필요 시 사용자 정의)
|
|
25
|
+
def _connectToServer(self):
|
|
26
|
+
certify_check_time = time.time()
|
|
27
|
+
print("[" + self.log_title + "] Connecting to {0}:{1}...".format(self.ip, self.port))
|
|
28
|
+
while(self.socketConnectThread_Enable):
|
|
29
|
+
try:
|
|
30
|
+
# 한 번 서버에 연결되면 연결이 끊어지기 전까지 더 이상 접속을 시도하지 않도록 함
|
|
31
|
+
if(not self.ser_socket_connect_status):
|
|
32
|
+
self.ser_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
33
|
+
self.ser_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
34
|
+
self.ser_socket.connect((self.ip, self.port))
|
|
35
|
+
self.ser_socket_connect_status = True
|
|
36
|
+
|
|
37
|
+
self.ser_socket.send("{0},{1},{2}\n".format(self.device_id, self.device_pw, "S100").encode("utf-8"))
|
|
38
|
+
|
|
39
|
+
# URL로부터 이미지를 읽어들일 경우 (영상 지연 문제로 쓰레드를 별도로 만들어 아래와 같이 비동기로 읽어들임)
|
|
40
|
+
if(self.live_receive):
|
|
41
|
+
self.live_receive_run = True
|
|
42
|
+
self.receiveDataQueue.clear()
|
|
43
|
+
self.socketReceiveThread = threading.Thread(target=self._receiveThread)
|
|
44
|
+
self.socketReceiveThread.setDaemon(True)
|
|
45
|
+
self.socketReceiveThread.start()
|
|
46
|
+
|
|
47
|
+
if(self.live_send):
|
|
48
|
+
self.live_send_run = True
|
|
49
|
+
self.socketSendThread = threading.Thread(target=self._sendThread)
|
|
50
|
+
self.socketSendThread.setDaemon(True)
|
|
51
|
+
self.socketSendThread.start()
|
|
52
|
+
|
|
53
|
+
print("[" + self.log_title + "] Server connection was successful.")
|
|
54
|
+
certify_check_time = time.time() # 인증 체크 시간 초기화
|
|
55
|
+
|
|
56
|
+
# 접속 후 5초 넘게 인증이 완료되지 않았을 경우 재요청
|
|
57
|
+
elif (time.time() - certify_check_time >= 5) and not self.isCertified:
|
|
58
|
+
certify_check_time = time.time()
|
|
59
|
+
print("[" + self.log_title + "] Not certified long time. retry")
|
|
60
|
+
self.ser_socket.send("{0},{1},{2}\n".format(self.device_id, self.device_pw, "S100").encode("utf-8"))
|
|
61
|
+
|
|
62
|
+
except socket.error as e:
|
|
63
|
+
print("[" + self.log_title + "] Connect to server process error " + str(e))
|
|
64
|
+
self.close()
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
finally:
|
|
68
|
+
time.sleep(1)
|
|
69
|
+
|
|
70
|
+
# 소켓 서버에 IoT 데이터 전송. live_send에 따라 전송 방식이 달라짐
|
|
71
|
+
def sendData(self, values):
|
|
72
|
+
try:
|
|
73
|
+
if(type(values) != list):
|
|
74
|
+
print("[" + self.log_title + "] Invalid data format ({0})".format(value))
|
|
75
|
+
return
|
|
76
|
+
if(type(values[0]) != list):
|
|
77
|
+
values = [values] # to 2d array
|
|
78
|
+
|
|
79
|
+
for value in values:
|
|
80
|
+
if(type(value) != list or len(value) != 3):
|
|
81
|
+
print("[" + self.log_title + "] Invalid data format ({0})".format(value))
|
|
82
|
+
continue
|
|
83
|
+
if(value[1] not in ["CS", "CN", "SS", "SN"]):
|
|
84
|
+
print("[" + self.log_title + "] Invalid data type. ({0})".format(value[1]))
|
|
85
|
+
continue
|
|
86
|
+
value_final = [self.device_id, self.device_pw] + value
|
|
87
|
+
tagData = ','.join(map(str, value_final)) + "\n"
|
|
88
|
+
tagPacket = tagData.encode('utf-8')
|
|
89
|
+
|
|
90
|
+
if(self.live_send):
|
|
91
|
+
if(self.live_send_run and self.socketSendThread.is_alive()):
|
|
92
|
+
self.sendDataQueues[value[0]] = tagPacket
|
|
93
|
+
# else:
|
|
94
|
+
# print("[" + self.log_title + "] {0}:{1} The connection with the socket has been terminated or closed. Data cannot be sent.".format(self.ip, self.port))
|
|
95
|
+
else:
|
|
96
|
+
self.ser_socket.send(tagPacket)
|
|
97
|
+
|
|
98
|
+
except ConnectionResetError:
|
|
99
|
+
self.close()
|
|
100
|
+
print("[" + self.log_title + "] {0}:{1} The connection to the server has been lost.".format(self.ip, self.port))
|
|
101
|
+
pass
|
|
102
|
+
except socket.error as e:
|
|
103
|
+
self.close()
|
|
104
|
+
print("[" + self.log_title + "] {0}:{1} The connection to the server has been lost.".format(self.ip, self.port))
|
|
105
|
+
pass
|
|
106
|
+
finally:
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
# 소켓 서버에 IoT 데이터 즉시 전송
|
|
110
|
+
def sendDataDirect(self, values):
|
|
111
|
+
try:
|
|
112
|
+
if(type(values) != list):
|
|
113
|
+
print("[" + self.log_title + "] Invalid data format ({0})".format(value))
|
|
114
|
+
return
|
|
115
|
+
if(type(values[0]) != list):
|
|
116
|
+
values = [values] # to 2d array
|
|
117
|
+
|
|
118
|
+
for value in values:
|
|
119
|
+
if(type(value) != list or len(value) != 3):
|
|
120
|
+
print("[" + self.log_title + "] Invalid data format ({0})".format(value))
|
|
121
|
+
continue
|
|
122
|
+
if(value[1] not in ["CS", "CN", "SS", "SN"]):
|
|
123
|
+
print("[" + self.log_title + "] Invalid data type. ({0})".format(value[1]))
|
|
124
|
+
continue
|
|
125
|
+
value_final = [self.device_id, self.device_pw] + value
|
|
126
|
+
tagData = ','.join(map(str, value_final)) + "\n"
|
|
127
|
+
tagPacket = tagData.encode('utf-8')
|
|
128
|
+
|
|
129
|
+
self.ser_socket.send(tagPacket)
|
|
130
|
+
|
|
131
|
+
except ConnectionResetError:
|
|
132
|
+
self.close()
|
|
133
|
+
print("[" + self.log_title + "] {0}:{1} The connection to the server has been lost.".format(self.ip, self.port))
|
|
134
|
+
pass
|
|
135
|
+
except socket.error as e:
|
|
136
|
+
self.close()
|
|
137
|
+
print("[" + self.log_title + "] {0}:{1} The connection to the server has been lost.".format(self.ip, self.port))
|
|
138
|
+
pass
|
|
139
|
+
finally:
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
def _sendThread(self):
|
|
143
|
+
send_interval_time = 0
|
|
144
|
+
self_break = False
|
|
145
|
+
|
|
146
|
+
while(self.live_send_run):
|
|
147
|
+
try:
|
|
148
|
+
if time.time() - send_interval_time >= self.live_send_interval:
|
|
149
|
+
send_interval_time = time.time()
|
|
150
|
+
# 인증 된 상태인지 확인한다.
|
|
151
|
+
if self.checkCertified() and len(self.sendDataQueues) > 0:
|
|
152
|
+
for key, value in self.sendDataQueues.items():
|
|
153
|
+
self.ser_socket.send(value)
|
|
154
|
+
time.sleep(0.05)
|
|
155
|
+
|
|
156
|
+
except Exception as e:
|
|
157
|
+
self.live_send_run = False
|
|
158
|
+
print("[" + self.log_title + "] Problem processing data in _sendThread. => ", e)
|
|
159
|
+
break
|
|
160
|
+
|
|
161
|
+
finally:
|
|
162
|
+
time.sleep(0.01)
|
|
163
|
+
|
|
164
|
+
# 데이터 자동 수신 쓰레드 호출 시 사용되는 함수 (사용자 정의)
|
|
165
|
+
def _receiveThread(self):
|
|
166
|
+
data = ""
|
|
167
|
+
while(self.live_receive_run):
|
|
168
|
+
try:
|
|
169
|
+
data += self.ser_socket.recv(self.receiveBuffer).decode('utf-8')
|
|
170
|
+
|
|
171
|
+
if data is not None:
|
|
172
|
+
if not (len(data) == 0):
|
|
173
|
+
packets = data.split('\n')
|
|
174
|
+
# 마지막 항목은 제외
|
|
175
|
+
for i in range(len(packets) - 1):
|
|
176
|
+
if len(packets[i]) > 5: # 못해도 5는 넘어야 정상적인 데이터 "A,B,C"
|
|
177
|
+
data_str = packets[i].strip()
|
|
178
|
+
data_list = data_str.split(',')
|
|
179
|
+
if(len(data_list) == 3):
|
|
180
|
+
device_id = data_list[0]
|
|
181
|
+
device_pw = data_list[1]
|
|
182
|
+
status = data_list[2]
|
|
183
|
+
self.isCertified = (device_id == self.device_id and device_pw == self.device_pw and status == "S001")
|
|
184
|
+
if(not self.isCertified):
|
|
185
|
+
print("[" + self.log_title + "] Device not certified. Please check your ID and password again.")
|
|
186
|
+
elif(len(data_list) == 5):
|
|
187
|
+
device_id = data_list[0]
|
|
188
|
+
device_pw = data_list[1]
|
|
189
|
+
tag_id = data_list[2]
|
|
190
|
+
tag_type = data_list[3]
|
|
191
|
+
tag_value = data_list[4]
|
|
192
|
+
self.receiveDataQueue.append([tag_id, tag_type, tag_value])
|
|
193
|
+
else:
|
|
194
|
+
continue
|
|
195
|
+
|
|
196
|
+
# for문을 다 돌았으면, 마지막 하나는 '' 또는 '남은데이터' 이다.
|
|
197
|
+
# data를 packets의 마지막 데이터로 적용하고, 뒤에 데이터 수신 시 쌓을 수 있도록 한다.
|
|
198
|
+
data = packets[-1]
|
|
199
|
+
|
|
200
|
+
else:
|
|
201
|
+
print("[" + self.log_title + "] Disconnect from", str(self.getServerIP()))
|
|
202
|
+
self.close()
|
|
203
|
+
break
|
|
204
|
+
|
|
205
|
+
except ConnectionResetError:
|
|
206
|
+
self.close()
|
|
207
|
+
break
|
|
208
|
+
except socket.timeout as e:
|
|
209
|
+
pass
|
|
210
|
+
except socket.error as e:
|
|
211
|
+
self.close()
|
|
212
|
+
break
|
|
213
|
+
finally:
|
|
214
|
+
time.sleep(0.01)
|
|
215
|
+
|
|
216
|
+
# 소켓 서버로부터 데이터 수신 (사용자 정의)
|
|
217
|
+
def receiveData(self):
|
|
218
|
+
data = ""
|
|
219
|
+
try:
|
|
220
|
+
if(self.live_receive):
|
|
221
|
+
if(self.live_receive_run and self.socketReceiveThread.is_alive()):
|
|
222
|
+
data = self.receiveDataQueue.popleft() if self.receiveDataQueue else None
|
|
223
|
+
else:
|
|
224
|
+
print("The connection with the socket has been terminated. A value of None is returned.")
|
|
225
|
+
data = None
|
|
226
|
+
else:
|
|
227
|
+
data += self.ser_socket.recv(self.receiveBuffer).decode('utf-8')
|
|
228
|
+
if data is not None:
|
|
229
|
+
if not (len(data) == 0):
|
|
230
|
+
packets = data.split('\n')
|
|
231
|
+
# 마지막 항목은 제외
|
|
232
|
+
for i in range(len(packets) - 1):
|
|
233
|
+
if len(packets[i]) > 5: # 못해도 5는 넘어야 정상적인 데이터 "A,B,C"
|
|
234
|
+
data_str = packets[i].strip()
|
|
235
|
+
data_list = data_str.split(',')
|
|
236
|
+
if(len(data_list) == 3):
|
|
237
|
+
device_id = data_list[0]
|
|
238
|
+
device_pw = data_list[1]
|
|
239
|
+
status = data_list[2]
|
|
240
|
+
self.isCertified = (device_id == self.device_id and device_pw == self.device_pw and status == "S001")
|
|
241
|
+
if(not self.isCertified):
|
|
242
|
+
print("[" + self.log_title + "] Device not certified. Please check your ID and password again.")
|
|
243
|
+
elif(len(data_list) == 5):
|
|
244
|
+
device_id = data_list[0]
|
|
245
|
+
device_pw = data_list[1]
|
|
246
|
+
tag_id = data_list[2]
|
|
247
|
+
tag_type = data_list[3]
|
|
248
|
+
tag_value = data_list[4]
|
|
249
|
+
self.receiveDataQueue.append([tag_id, tag_type, tag_value])
|
|
250
|
+
else:
|
|
251
|
+
continue
|
|
252
|
+
|
|
253
|
+
# for문을 다 돌았으면, 마지막 하나는 '' 또는 '남은데이터' 이다.
|
|
254
|
+
# data를 packets의 마지막 데이터로 적용하고, 뒤에 데이터 수신 시 쌓을 수 있도록 한다.
|
|
255
|
+
data = packets[-1]
|
|
256
|
+
|
|
257
|
+
else:
|
|
258
|
+
print("[" + self.log_title + "] Disconnect from", str(self.getServerIP()))
|
|
259
|
+
self.close()
|
|
260
|
+
|
|
261
|
+
return data
|
|
262
|
+
|
|
263
|
+
except ConnectionResetError:
|
|
264
|
+
self.close()
|
|
265
|
+
return None
|
|
266
|
+
except socket.error as e:
|
|
267
|
+
self.close()
|
|
268
|
+
return None
|
|
269
|
+
except Exception as e:
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
def checkCertified(self):
|
|
273
|
+
return self.isCertified
|
|
274
|
+
|
|
275
|
+
def isExistReceiveData(self):
|
|
276
|
+
return len(self.receiveDataQueue) > 0
|
|
277
|
+
|
|
278
|
+
def waitForConnect(self):
|
|
279
|
+
while(self.socketConnectThread_Enable and not self.checkConnected()):
|
|
280
|
+
time.sleep(0.5)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from abc import ABC, ABCMeta, abstractmethod
|
|
2
|
+
|
|
3
|
+
class WIPClientAbstractModel(metaclass=ABCMeta):
|
|
4
|
+
"""
|
|
5
|
+
@brief 생성자
|
|
6
|
+
@param ip Server IP
|
|
7
|
+
@param port Server Port
|
|
8
|
+
@param device_id Device ID
|
|
9
|
+
@param device_pw Device PW
|
|
10
|
+
@param isAutoConnect 자동 접속 관련 boolean. True일 경우 연결이 끊길 시 자동으로 접속한다.
|
|
11
|
+
@param live_receive 자동으로 수신관련 처리를 수행할지 여부
|
|
12
|
+
@param live_send 데이터를 자동으로 전송할지 여부
|
|
13
|
+
@param live_send_interval live_send가 True일 경우 전송할 주기
|
|
14
|
+
"""
|
|
15
|
+
# @abstractmethod
|
|
16
|
+
# def __init__(self, ip="127.0.0.1", port=10008, device_id="device1", device_pw="00000000", isAutoConnect=True, live_receive=True, live_send=False, live_send_interval=1):
|
|
17
|
+
# print("AbstractModel Initialize")
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
@brief 노드 데이터를 전송하는 메소드
|
|
21
|
+
"""
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def sendData(self, values):
|
|
24
|
+
print("AbstractModel sendData")
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
@vbrief
|
|
28
|
+
"""
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def sendDataDirect(self, values):
|
|
31
|
+
print("AbstractModel sendDataDirect")
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
@brief 수신받은 데이터를 받는 메소드
|
|
35
|
+
live_receive가 True일 경우 백그라운드에서 수신한 노드 데이터를 리턴한다.
|
|
36
|
+
advanced protocol에서 live_receive가 False일 경우 None 리턴
|
|
37
|
+
"""
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def receiveData(self):
|
|
40
|
+
print("AbstractModel receiveData")
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
@brief 인증이 완료되었는지 확인하는 메소드
|
|
44
|
+
"""
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def checkCertified(self):
|
|
47
|
+
print("AbstractModel checkCertified")
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
live_receive가 True일 경우 Queue에 받은 데이터가 존재하는지 확인
|
|
51
|
+
"""
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def isExistReceiveData(self):
|
|
54
|
+
print("AbstractModel isExistReceiveData")
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
서버 접속이 완료될 때 까지 대기한다.
|
|
58
|
+
"""
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def waitForConnect(self):
|
|
61
|
+
print("AbstractModel waitForConnect")
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import json
|
|
3
|
+
import socket
|
|
4
|
+
import logging
|
|
5
|
+
import threading
|
|
6
|
+
from .interface import SocketManagerV2
|
|
7
|
+
# from .protocol.advanced import commonFunction as cf
|
|
8
|
+
from .protocol.advanced import JsonDataProtocol as api
|
|
9
|
+
from .WIPClientAbstractModel import WIPClientAbstractModel
|
|
10
|
+
|
|
11
|
+
class WIPClient(WIPClientAbstractModel, SocketManagerV2.SocketClient):
|
|
12
|
+
# ip : 연결할 서버의 IP
|
|
13
|
+
# port : 연결할 서버의 Port
|
|
14
|
+
# name : 연결할 서버를 구분하기 위한 용도 (ex: iotGateway, AutoVehicle, iotMakers .. 등등)
|
|
15
|
+
def __init__(self, ip="127.0.0.1", port=10008, device_id="device1", device_pw="00000000", isAutoConnect=True, live_receive=True, live_send=False, live_send_interval=1):
|
|
16
|
+
super().__init__(ip, port, "WOW Iot Platform", isAutoConnect=isAutoConnect, live_receive=live_receive)
|
|
17
|
+
self.device_id = str(device_id)
|
|
18
|
+
self.device_pw = str(device_pw)
|
|
19
|
+
self.token = ""
|
|
20
|
+
self.isCertified = False
|
|
21
|
+
|
|
22
|
+
# 각 데이터가 노드 ID로 구분되기 때문에 WIP Client에서만 사용한다.
|
|
23
|
+
self.live_send = live_send
|
|
24
|
+
self.live_send_run = False
|
|
25
|
+
self.live_send_interval = live_send_interval
|
|
26
|
+
self.socketSendThread = None
|
|
27
|
+
self.sendDataQueues = {}
|
|
28
|
+
|
|
29
|
+
self.is_wait_response = False
|
|
30
|
+
|
|
31
|
+
# 서버 자동 접속 쓰레드 호출 시 사용되는 함수 (필요 시 사용자 정의)
|
|
32
|
+
def _connectToServer(self):
|
|
33
|
+
certify_check_time = time.time()
|
|
34
|
+
print("[" + self.log_title + "] Connecting to {0}:{1}...".format(self.ip, self.port))
|
|
35
|
+
while(self.socketConnectThread_Enable):
|
|
36
|
+
try:
|
|
37
|
+
# 한 번 서버에 연결되면 연결이 끊어지기 전까지 더 이상 접속을 시도하지 않도록 함
|
|
38
|
+
if(not self.ser_socket_connect_status):
|
|
39
|
+
self.ser_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
40
|
+
self.ser_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
41
|
+
self.ser_socket.connect((self.ip, self.port))
|
|
42
|
+
self.ser_socket_connect_status = True
|
|
43
|
+
|
|
44
|
+
# 서버 로그인 진행
|
|
45
|
+
login_json, cmd = api.dev_login_001(self.device_id, self.device_pw)
|
|
46
|
+
# print("[" + self.log_title + "] Authentication Request => {0}\n".format(login_json))
|
|
47
|
+
self.ser_socket.send(login_json.encode("utf-8"))
|
|
48
|
+
self.is_wait_response = True
|
|
49
|
+
|
|
50
|
+
# self.ser_socket.send("{0},{1},{2}\n".format(self.device_id, self.device_pw, "S100").encode("utf-8"))
|
|
51
|
+
|
|
52
|
+
# URL로부터 이미지를 읽어들일 경우 (영상 지연 문제로 쓰레드를 별도로 만들어 아래와 같이 비동기로 읽어들임)
|
|
53
|
+
if(self.live_receive):
|
|
54
|
+
self.live_receive_run = True
|
|
55
|
+
self.receiveDataQueue.clear()
|
|
56
|
+
self.socketReceiveThread = threading.Thread(target=self._receiveThread)
|
|
57
|
+
self.socketReceiveThread.setDaemon(True)
|
|
58
|
+
self.socketReceiveThread.start()
|
|
59
|
+
|
|
60
|
+
if(self.live_send):
|
|
61
|
+
self.live_send_run = True
|
|
62
|
+
self.socketSendThread = threading.Thread(target=self._sendThread)
|
|
63
|
+
self.socketSendThread.setDaemon(True)
|
|
64
|
+
self.socketSendThread.start()
|
|
65
|
+
|
|
66
|
+
print("[" + self.log_title + "] Server connection was successful.")
|
|
67
|
+
certify_check_time = time.time() # 인증 체크 시간 초기화
|
|
68
|
+
|
|
69
|
+
# 접속 후 5초 넘게 인증이 완료되지 않았을 경우 재요청
|
|
70
|
+
elif (time.time() - certify_check_time >= 5) and not self.isCertified:
|
|
71
|
+
certify_check_time = time.time()
|
|
72
|
+
print("[" + self.log_title + "] Not certified long time. retry")
|
|
73
|
+
login_json, cmd = api.dev_login_001(self.device_id, self.device_pw)
|
|
74
|
+
print("[" + self.log_title + "] Authentication Request => {0}\n".format(login_json))
|
|
75
|
+
self.ser_socket.send(login_json.encode("utf-8"))
|
|
76
|
+
self.is_wait_response = True
|
|
77
|
+
# self.ser_socket.send("{0},{1},{2}\n".format(self.device_id, self.device_pw, "S100").encode("utf-8"))
|
|
78
|
+
|
|
79
|
+
except socket.error as e:
|
|
80
|
+
print("[" + self.log_title + "] Connect to server process error " + str(e))
|
|
81
|
+
self.close()
|
|
82
|
+
continue
|
|
83
|
+
|
|
84
|
+
finally:
|
|
85
|
+
time.sleep(1.5)
|
|
86
|
+
|
|
87
|
+
# 소켓 서버에 IoT 데이터 전송
|
|
88
|
+
def sendData(self, values):
|
|
89
|
+
try:
|
|
90
|
+
if(type(values) != list):
|
|
91
|
+
print("[" + self.log_title + "] Invalid data format ({0})".format(value))
|
|
92
|
+
return
|
|
93
|
+
if(type(values[0]) != list):
|
|
94
|
+
values = [values] # to 2d array
|
|
95
|
+
|
|
96
|
+
dataList = []
|
|
97
|
+
for value in values:
|
|
98
|
+
if(type(value) != list or len(value) != 3):
|
|
99
|
+
print("[" + self.log_title + "] Invalid data format ({0})".format(value))
|
|
100
|
+
continue
|
|
101
|
+
if(value[1] not in ["CS", "CN", "SS", "SN"]):
|
|
102
|
+
print("[" + self.log_title + "] Invalid data type. ({0})".format(value[1]))
|
|
103
|
+
continue
|
|
104
|
+
value_final = api.node_data(value[0], value[1], value[2])
|
|
105
|
+
dataList.append(value_final)
|
|
106
|
+
|
|
107
|
+
if(self.live_send):
|
|
108
|
+
if(self.live_send_run and self.socketSendThread.is_alive()):
|
|
109
|
+
self.sendDataQueues[value[0]] = value_final
|
|
110
|
+
# else:
|
|
111
|
+
# print("[" + self.log_title + "] {0}:{1} The connection with the socket has been terminated or closed. Data cannot be sent.".format(self.ip, self.port))
|
|
112
|
+
if(not self.live_send):
|
|
113
|
+
data_json, cmd = api.dev_data_001(self.token, dataList)
|
|
114
|
+
self.ser_socket.send(data_json.encode('utf-8'))
|
|
115
|
+
self.is_wait_response = True
|
|
116
|
+
|
|
117
|
+
except ConnectionResetError:
|
|
118
|
+
self.close()
|
|
119
|
+
print("[" + self.log_title + "] {0}:{1} The connection to the server has been lost.".format(self.ip, self.port))
|
|
120
|
+
pass
|
|
121
|
+
except socket.error as e:
|
|
122
|
+
self.close()
|
|
123
|
+
print("[" + self.log_title + "] {0}:{1} The connection to the server has been lost.".format(self.ip, self.port))
|
|
124
|
+
pass
|
|
125
|
+
finally:
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
# 소켓 서버에 IoT 데이터 전송
|
|
129
|
+
def sendDataDirect(self, values):
|
|
130
|
+
try:
|
|
131
|
+
if(type(values) != list):
|
|
132
|
+
print("[" + self.log_title + "] Invalid data format ({0})".format(value))
|
|
133
|
+
return
|
|
134
|
+
if(type(values[0]) != list):
|
|
135
|
+
values = [values] # to 2d array
|
|
136
|
+
|
|
137
|
+
dataList = []
|
|
138
|
+
for value in values:
|
|
139
|
+
if(type(value) != list or len(value) != 3):
|
|
140
|
+
print("[" + self.log_title + "] Invalid data format ({0})".format(value))
|
|
141
|
+
continue
|
|
142
|
+
if(value[1] not in ["CS", "CN", "SS", "SN"]):
|
|
143
|
+
print("[" + self.log_title + "] Invalid data type. ({0})".format(value[1]))
|
|
144
|
+
continue
|
|
145
|
+
value_final = api.node_data(value[0], value[1], value[2])
|
|
146
|
+
dataList.append(value_final)
|
|
147
|
+
|
|
148
|
+
data_json, cmd = api.dev_data_001(self.token, dataList)
|
|
149
|
+
self.ser_socket.send(data_json.encode('utf-8'))
|
|
150
|
+
self.is_wait_response = True
|
|
151
|
+
|
|
152
|
+
except ConnectionResetError:
|
|
153
|
+
self.close()
|
|
154
|
+
print("[" + self.log_title + "] {0}:{1} The connection to the server has been lost.".format(self.ip, self.port))
|
|
155
|
+
pass
|
|
156
|
+
except socket.error as e:
|
|
157
|
+
self.close()
|
|
158
|
+
print("[" + self.log_title + "] {0}:{1} The connection to the server has been lost.".format(self.ip, self.port))
|
|
159
|
+
pass
|
|
160
|
+
finally:
|
|
161
|
+
pass
|
|
162
|
+
|
|
163
|
+
def _sendThread(self):
|
|
164
|
+
send_interval_time = 0
|
|
165
|
+
self_break = False
|
|
166
|
+
|
|
167
|
+
while(self.live_send_run):
|
|
168
|
+
try:
|
|
169
|
+
if time.time() - send_interval_time >= self.live_send_interval:
|
|
170
|
+
send_interval_time = time.time()
|
|
171
|
+
# 인증 된 상태인지 확인한다.
|
|
172
|
+
if self.checkCertified() and len(self.sendDataQueues) > 0:
|
|
173
|
+
data_json, cmd = api.dev_data_001(self.token, list(self.sendDataQueues.values()))
|
|
174
|
+
self.ser_socket.send(data_json.encode('utf-8'))
|
|
175
|
+
self.is_wait_response = True
|
|
176
|
+
time.sleep(0.05)
|
|
177
|
+
|
|
178
|
+
except Exception as e:
|
|
179
|
+
self.live_send_run = False
|
|
180
|
+
print("[" + self.log_title + "] Problem processing data in _sendThread. => ", e)
|
|
181
|
+
break
|
|
182
|
+
|
|
183
|
+
finally:
|
|
184
|
+
time.sleep(0.01)
|
|
185
|
+
|
|
186
|
+
# 데이터 자동 수신 쓰레드 호출 시 사용되는 함수 (사용자 정의)
|
|
187
|
+
def _receiveThread(self):
|
|
188
|
+
data = ""
|
|
189
|
+
while(self.live_receive_run):
|
|
190
|
+
try:
|
|
191
|
+
data += self.ser_socket.recv(self.receiveBuffer).decode('utf-8')
|
|
192
|
+
if data is not None:
|
|
193
|
+
if not (len(data) == 0):
|
|
194
|
+
packets = data.split('\n')
|
|
195
|
+
# 마지막 항목은 제외
|
|
196
|
+
for i in range(len(packets) - 1):
|
|
197
|
+
if len(packets[i]) > 5: # 못해도 5는 넘어야 정상적인 데이터 "A,B,C"
|
|
198
|
+
data_str = packets[i].strip()
|
|
199
|
+
try:
|
|
200
|
+
self.json_data = json.loads(data_str)
|
|
201
|
+
except Exception as e: # JSON Load FAIL
|
|
202
|
+
continue
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
# 받은 JSON 데이터의 cmd 항목 가져오기
|
|
206
|
+
cmd = self.json_data["cmd"]
|
|
207
|
+
|
|
208
|
+
if (
|
|
209
|
+
self.is_wait_response and
|
|
210
|
+
(
|
|
211
|
+
cmd == api.CMD_LOGIN01 or
|
|
212
|
+
cmd == api.CMD_DDATA01
|
|
213
|
+
)
|
|
214
|
+
):
|
|
215
|
+
self.is_wait_response = False
|
|
216
|
+
# LOGIN
|
|
217
|
+
if(cmd == api.CMD_LOGIN01):
|
|
218
|
+
if(
|
|
219
|
+
(self.json_data['result'] == api.RESULT_CODE_SUCCESS) and
|
|
220
|
+
(self.json_data['device_id'] == self.device_id)
|
|
221
|
+
):
|
|
222
|
+
self.token = self.json_data['token']
|
|
223
|
+
self.isCertified = True
|
|
224
|
+
|
|
225
|
+
elif (
|
|
226
|
+
cmd == api.CMD_HB or
|
|
227
|
+
cmd == api.CMD_CONTROL01
|
|
228
|
+
):
|
|
229
|
+
# HB
|
|
230
|
+
if cmd == api.CMD_HB:
|
|
231
|
+
j, cmd = api.sv_hb_001(self.token, api.RESULT_CODE_SUCCESS)
|
|
232
|
+
self.ser_socket.send(j.encode('utf-8'))
|
|
233
|
+
|
|
234
|
+
# Control
|
|
235
|
+
elif cmd == api.CMD_CONTROL01:
|
|
236
|
+
j, cmd = api.sv_ctrl_001(self.token, api.RESULT_CODE_SUCCESS)
|
|
237
|
+
self.ser_socket.send(j.encode('utf-8'))
|
|
238
|
+
if(self.token == self.json_data['token']):
|
|
239
|
+
nodes = self.json_data['data']
|
|
240
|
+
for node in nodes:
|
|
241
|
+
self.receiveDataQueue.append([node['node_id'], node['node_type'], node['node_data']])
|
|
242
|
+
|
|
243
|
+
except Exception as e:
|
|
244
|
+
# cf.gLog.info("json process error =? %s", e)
|
|
245
|
+
pass
|
|
246
|
+
finally:
|
|
247
|
+
pass
|
|
248
|
+
|
|
249
|
+
# for문을 다 돌았으면, 마지막 하나는 '' 또는 '남은데이터' 이다.
|
|
250
|
+
# data를 packets의 마지막 데이터로 적용하고, 뒤에 데이터 수신 시 쌓을 수 있도록 한다.
|
|
251
|
+
data = packets[-1]
|
|
252
|
+
|
|
253
|
+
else:
|
|
254
|
+
print("[" + self.log_title + "] Disconnect from", str(self.getServerIP()))
|
|
255
|
+
self.close()
|
|
256
|
+
break
|
|
257
|
+
|
|
258
|
+
except ConnectionResetError:
|
|
259
|
+
self.close()
|
|
260
|
+
break
|
|
261
|
+
except socket.timeout as e:
|
|
262
|
+
pass
|
|
263
|
+
except socket.error as e:
|
|
264
|
+
self.close()
|
|
265
|
+
break
|
|
266
|
+
finally:
|
|
267
|
+
time.sleep(0.01)
|
|
268
|
+
|
|
269
|
+
# 소켓 서버로부터 데이터 수신 (사용자 정의)
|
|
270
|
+
# 만약 live_receive가 true인 경우 백그라운드에서 실행된 수신 쓰레드에서 넣은 큐를 접근
|
|
271
|
+
# 만약 live_receive가 false인 경우 None 리턴
|
|
272
|
+
def receiveData(self):
|
|
273
|
+
data = ""
|
|
274
|
+
try:
|
|
275
|
+
if(self.live_receive):
|
|
276
|
+
if(self.live_receive_run and self.socketReceiveThread.is_alive()):
|
|
277
|
+
data = self.receiveDataQueue.popleft() if self.receiveDataQueue else None
|
|
278
|
+
else:
|
|
279
|
+
print("The connection with the socket has been terminated. A value of None is returned.")
|
|
280
|
+
data = None
|
|
281
|
+
return data
|
|
282
|
+
else:
|
|
283
|
+
return None
|
|
284
|
+
except ConnectionResetError:
|
|
285
|
+
self.close()
|
|
286
|
+
return None
|
|
287
|
+
except socket.error as e:
|
|
288
|
+
self.close()
|
|
289
|
+
return None
|
|
290
|
+
except Exception as e:
|
|
291
|
+
return None
|
|
292
|
+
|
|
293
|
+
def checkCertified(self):
|
|
294
|
+
return self.isCertified
|
|
295
|
+
|
|
296
|
+
def isExistReceiveData(self):
|
|
297
|
+
return len(self.receiveDataQueue) > 0
|
|
298
|
+
|
|
299
|
+
def waitForConnect(self):
|
|
300
|
+
while(self.socketConnectThread_Enable and not self.checkConnected()):
|
|
301
|
+
time.sleep(0.5)
|