Device.py
7.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
from django.conf import settings
import socket
import configparser
import abc
import select
import utils.Logger as L
import time
import os
from common.models import Log
DEBUG_FILE = True
RECONNECT_TIMEOUT_SECONDS = 20
'''
Generic object for the communication with all the devices
'''
class DeviceController():
__metaclass__ = abc.ABCMeta
logger = L.setupLogger("DeviceLogger", "Devices")
name = ""
config_file = "../config/socket_config.ini"
config = None
connected = False
sock = None
ip = None
port = None
def __init__(self, device_name):
self.name = device_name
self.getConfig()
self.getConnection(device_name)
self.connect()
@abc.abstractmethod
def set(self, command: str, *args):
return
@abc.abstractmethod
def do(self, command: str, *args):
return
@abc.abstractmethod
def get(self, command: str, *args):
return
@abc.abstractmethod
def getStatus(self):
return
def sendMessage(self, message: str):
if (not self.isConnected()):
# (EP) NON, return 0 !!!
#return (1)
return False
# (EP) Here we are still not sure that we are connected to the device (it may be down and we do not know)
try:
readable, writable, exceptional = select.select([], [self.sock], [self.sock], 0)
if not (writable or exceptional):
raise (Exception("Socket not writable"))
self.sock.send(bytes(message, "UTF-8"))
except Exception as e:
if (settings.DEBUG):
print("(ENV) Could not send message (on socket) to "+self.name+" : " + message + " -> " + str(e))
#EP TODO: bugfix: ce log ne fait rien du tout !!
self.log(self.name, "Could not send message on socket : " + message + " -> " + str(e))
i = 0
while self.reconnect() is False and i < RECONNECT_TIMEOUT_SECONDS:
i += 1
if i == RECONNECT_TIMEOUT_SECONDS:
self.device_is_dead()
# (EP) NON, 1 = true !!!
#return (1)
return False
# (EP) NON, 0 = false !!!
#return (0)
Log.objects.create(agent=self.name, message='Message send : ' + message)
return True
def isError(self, message: str):
#EP
#if (message == "FAILED" or message == "NOT_SET" or message == "DISCONNECTED"):
if (message == "FAILED" or message.startswith("NOT_SET") or message == "DISCONNECTED"):
return (True)
return (False)
# MIND: Does not mean "is connected now" but "WAS connected once"
def isConnected(self):
if (not self.sock or not self.connected):
# (EP) NON, c'est totalement illisible !!! on n'est plus en 1970
#if (self.connect()): return (False)
print("something is wrong with this device, now trying to connect again...")
if not self.connect(): return False
#self.connected = True
return True
def readBytes(self, size) -> str:
if (not self.isConnected()):
return ("NOT_SET2")
try:
readable, writable, exceptional = select.select([self.sock], [], [self.sock], 0)
if not (readable or exceptional):
raise (Exception("Socket not readable"))
ret = self.sock.recv(size).decode()
if (not ret):
if (settings.DEBUG):
self.log(self.name, "Connection has been killed")
self.connected = False
return ("DISCONNECTED")
except Exception as e:
if (settings.DEBUG):
self.log(self.name, "Socket not readable : " + str(e))
return ("FAILED")
return (ret)
def blockAndReadBytes(self, size) -> str:
self.sock.setblocking(1)
return (self.readBytes(size))
def blockAndReadMessage(self) -> str:
return (self.blockAndReadBytes(1024))
def setBlocking(self, flag):
if (not self.sock):
return (1)
self.sock.setblocking(flag)
return (0)
# TODO maybe read more than 1024 bytes ?????
def readMessage(self) -> str:
return self.readBytes(1024)
def getConnection(self, device_name):
self.ip = self.config.get(device_name, "ip")
self.port = int(self.config.get(device_name, "port"))
return (0)
def getConfig(self):
self.config = configparser.ConfigParser()
self.config.read(self.config_file)
return (0)
def log(self, device_name: str, message: str):
Log.objects.create(agent=self.name, message=message)
if DEBUG_FILE and settings.DEBUG:
self.logger.info("From device : " + device_name + " -> " + message)
return (0)
def connect(self):
if (self.ip is None or self.port is None):
self.log(self.name, "Ip or Port not initialized")
# (EP) It's a serious bug, so raise exception !!!
#return (1)
raise (Exception(self.name +"Controller has no ip or port to connect to"))
try:
# Create a TCP/IP socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port on the server
r = self.sock.connect_ex((self.ip, self.port))
if (r != 0):
raise Exception("sock.connect_ex failed : " + os.strerror(r))
'''
Socket set to non blocking (by default, it is blocking)
In non-blocking mode, if a recv() call doesn’t find any data,
or if a send() call can’t immediately dispose of the data,
an error exception is raised.
(In blocking mode, the calls block until they can proceed)
s.setblocking(0) is equivalent to s.settimeout(0.0);
s.setblocking(1) is equivalent to s.settimeout(None).
'''
self.sock.setblocking(0)
except Exception as e:
print(e)
print("FAILED TO CONNECT TO DEVICE {}".format(self.name))
if (settings.DEBUG):
#TODO: Bugfix: Ce log ne fait rien !
self.log(self.name, "Failed to connect to " + str(self.ip) + ":" + str(self.port) + " -> " + str(e))
# (EP) return TRUE??? (for python, 1=true !!!)
#return (1)
return False
self.connected = True
# (EP) return FALSE ??? (for python, 0=false !!!)
#return (0)
return True
def reconnect(self):
self.getConfig()
self.getConnection(self.name)
try:
print("\nTrying to reconnect to " + str(self.name) + "...")
self.log(self.name, "Trying to reconnect to " + self.name)
if not self.connect():
raise Exception("Reconnect to " + self.name + " failed")
return True
except Exception as e:
print(str(e))
time.sleep(1)
return False
'''
Function called when the connection with the device is lost for too lon time and the max timeout for reconnection
RECONNECT_TIMEOUT_SECONDS is reached
'''
def device_is_dead(self):
print("\nCan't establish connection with the " + self.name + ", timeout expired")