2 Gateway Implementation. 4 This gateway reads a request from a TCP socket, 5 forwards it to a different network 6 and sends the answer to the requestor. 11 from connector
import Connector
12 from typesunisasa
import MessageTCP
13 from typesunisasadict
import dataTypeDictionary
17 DIC_TYPE_IO = dataTypeDictionary
21 """This class is an internal use only. 23 You could set: START_ID, SYMBOL_SENSOR and SYMBOL_ACTUATOR. 32 POS_SIZE_IO_DEVICE = 2
35 POS_DICTIONARY_SEN = 4
41 POS_DICTIONARY_ACT = 6
53 """Gateway implementation. 56 create/load/save/manage a routing table 57 routing between IP network and other networks 68 '''----- Setting stage -----''' 73 Since now the gateway can communicate with this device. 75 if isinstance(newConnector,Connector) ==
False :
80 """Remove all connectors.""" 84 """Load a table from a file. 87 :param filePath path ot the file 88 :type: fineConnector boolean 89 :param findConnector try to find the right device connector (see addConnector()) 92 file = open(filePath,
'r') 107 device = line.split(
";")
109 table[int(device[0])] = [int(device[1]), str(device[2]), int(device[3]), int(device[4]),sensors,int(device[5]),actuators]
110 for g
in range(6,len(device)-1,5):
111 if str(device[g]) == RouteTable.SYMBOL_SENSOR:
112 sensors[int(device[g+1])] = ( int(device[g+2]), int(device[g+3]), int(device[g+4]) )
114 actuators[int(device[g+1])] = ( int(device[g+2]), int(device[g+3]), int(device[g+4]) )
117 table[int(device[0])][RouteTable.POS_CONNECTOR] = self.
getConnector( int(device[1]),str(device[2]) )
125 """Internal use only. 127 Try to swap a 'Type Connector' field with an instanced Connector object (addConnector()) 137 """ Bind a device Address with a table ID.""" 141 """Verify table consistency.""" 144 connector = self.
_routeTable[deviceID][RouteTable.POS_CONNECTOR]
145 if isinstance(connector,Connector) ==
False or connector.verifyDevice(self.
_routeTable[deviceID][RouteTable.POS_ADDRESS]) ==
False:
146 delIDs.append(deviceID)
147 for currID
in range(len(delIDs)):
151 """Alias to verifyTable().""" 155 """Discovery Devices and create a new table.""" 160 """Discovery new devices and update currentTable.""" 165 """Discovery new devices. 167 This is the parent of all discovery function. 168 :return [ [ address, connector, sizeIODevice, 169 byteIDSen, {IDSen : (type S, Size Out, Type OUT)}, 170 byteIDAct, {IDAct : (type A, Size In, Type IN)} ] ] 176 devices += connector.discovery()
180 """Add new devices to the table 182 :type devices list [ [ address, connector, sizeIODevice, 183 byteIDSen, {IDSen : (type S, Size Out, Type OUT)}, 184 byteIDAct, {IDAct : (type A, Size In, Type IN)} ] ] 186 nextID = RouteTable.START_ID
187 for currDev
in range(len(devices)):
189 if (devices[currDev][0],devices[currDev][1])
in self.
_reservedID.values():
193 if devices[currDev]
not in self.
_routeTable.values() :
197 def _updateSizeIDDevice(self,newID):
198 """Internal use only. 200 Check and set max size device ID. 202 currSizeID = newID.bit_length() // 8 + (1
if newID.bit_length() % 8 != 0
else 0)
209 :param newNode [ address, connector, sizeIODevice, 210 byteIDSen, {IDSen : (type S, Size Out, Type OUT)}, 211 byteIDAct, {IDAct : (type A, Size In, Type IN)} ] 213 dev = [ [
None for x
in range(2)]
for x
in range(1)]
221 :param newNodes [ [ address, connector, sizeIODevice, 222 byteIDSen, {IDSen : (type S, Size Out, Type OUT)}, 223 byteIDAct, {IDAct : (type A, Size In, Type IN)} ] ] 228 """Romove a device from the table. 230 :type idDevice unsigned int 236 """Set current table to zero device.""" 241 """Return current table 243 :return {ID: [address, connector, sizeIODevice, 244 byteIDSen, { IDSen : (type S, Size Out, Type Out) }, 245 byteIDAct, { IDAct : (type A, Size In/, Type IN) } ] } 250 """Save current table. 254 :type verboseFile boolean 255 :param: verboseFile=True print a human readable file 258 file = open(path,
'w')
265 address = str(self.
_routeTable[IDs][RouteTable.POS_ADDRESS])
266 connector = self.
_routeTable[IDs][RouteTable.POS_CONNECTOR]
267 if isinstance(connector,Connector):
268 connector = self.
_routeTable[IDs][RouteTable.POS_CONNECTOR].__class__.__name__
269 size_io_device = str(self.
_routeTable[IDs][RouteTable.POS_SIZE_IO_DEVICE])
270 size_id_sen = str(self.
_routeTable[IDs][RouteTable.POS_SIZE_ID_SEN])
271 size_id_act = str(self.
_routeTable[IDs][RouteTable.POS_SIZE_ID_ACT])
274 verbose =
"#=======================================================================\n" 275 verbose +=
"# Device ID: "+ str(IDs) +
"\n" 276 verbose +=
"# address: " + address +
", Connector: "+ connector +
" (size data msg : "+ size_io_device +
"B)\n" 279 row = str(IDs) +
";" + address +
";"+ connector +
";"+ size_io_device +
";"+ size_id_sen +
";"+ size_id_act
281 verbose +=
"# (Size ID Sensor: "+ size_id_sen +
"B) Sensors:\n" 282 sensors = self.
_routeTable[IDs][RouteTable.POS_DICTIONARY_SEN]
283 for IDsen
in sensors:
285 type_sen = str(sensors[IDsen][RouteTable.POS_TYPE_SEN])
286 sensor =
"Sensor ID: " 288 size_out = str(sensors[IDsen][RouteTable.POS_SIZE_OUT])
289 type_out = str(sensors[IDsen][RouteTable.POS_TYPE_OUT])
291 verbose +=
"# {0:12s} {1:6s} (type: {2:6s} | size {3:6s}: {4:3s}B | type: {5:7s})\n".format(sensor,idsen,type_sen,output,size_out,DIC_TYPE_IO[int(type_out)])
293 row +=
";" + RouteTable.SYMBOL_SENSOR +
";" + idsen+
";"+ type_sen +
";"+ size_out +
";"+ type_out
295 verbose +=
"# (Size ID Actuator: "+ size_id_act +
"B) Actuators:\n" 296 actuators = self.
_routeTable[IDs][RouteTable.POS_DICTIONARY_ACT]
297 for IDact
in actuators:
299 type_act = str(actuators[IDact][RouteTable.POS_TYPE_ACT])
300 actuator =
"Actuator ID: " 302 size_in = str(actuators[IDact][RouteTable.POS_SIZE_IN])
303 type_in = str(actuators[IDact][RouteTable.POS_TYPE_IN])
305 verbose +=
"# {0:12s} {1:6s} (type: {2:6s} | size {3:6s}: {4:3s}B | type: {5:7s})\n".format(actuator,idact,type_act,inputStr,size_in,DIC_TYPE_IO[int(type_in)])
307 row +=
";" + RouteTable.SYMBOL_ACTUATOR +
";" + idact+
";"+ type_act +
";"+ size_in +
";"+ type_in
317 '''----- Communication Stage -----''' 320 """Create a socket to receive TCP request from UniSaSA library.""" 322 self.
_mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
325 server_address = (IP,port)
326 print(
'starting up on %s port %s' % server_address)
333 """Blocking to wait a 'UniSaSA library' client.""" 334 print(
'waiting for a connection')
335 connection, client_address = self.
_mySocket.accept()
336 connection.setblocking(
True)
337 connection.settimeout(
None)
338 print(
'connection from', client_address)
343 """Start to serve requests from an UniSaSA Library. 345 It is possible to use a multithread version.""" 347 print(
"Communication with: ", client)
350 data = client.recv(1)
355 elif data == MessageTCP.GET_DEVICES:
356 print(
"Request: GET DEVICES")
388 answer += deviceID.to_bytes(self.
_sizeByteID, byteorder=
'big')
390 answer += bytes([ listDevice[RouteTable.POS_SIZE_IO_DEVICE] ])
392 answer += bytes([ listDevice[RouteTable.POS_SIZE_ID_SEN] ])
393 sensorsDic = listDevice[RouteTable.POS_DICTIONARY_SEN]
394 answer += len(sensorsDic).to_bytes(listDevice[RouteTable.POS_SIZE_ID_SEN], byteorder=
'big')
396 for sensorID
in sensorsDic:
397 listSen = sensorsDic[sensorID]
398 answer += sensorID.to_bytes(listDevice[RouteTable.POS_SIZE_ID_SEN], byteorder=
'big')
399 answer += listSen[RouteTable.POS_TYPE_SEN].to_bytes(MessageTCP.SIZE_TYPE_SENSOR, byteorder=
'big')
400 answer += bytes( [ listSen[RouteTable.POS_SIZE_OUT] ] )
401 answer += bytes( [ listSen[RouteTable.POS_TYPE_OUT] ] )
403 answer += bytes([ listDevice[RouteTable.POS_SIZE_ID_ACT] ])
404 actuatorsDic = listDevice[RouteTable.POS_DICTIONARY_ACT]
405 answer += len(actuatorsDic).to_bytes(listDevice[RouteTable.POS_SIZE_ID_ACT], byteorder=
'big')
407 for actuatorID
in actuatorsDic:
408 listAct = actuatorsDic[actuatorID]
409 answer += actuatorID.to_bytes(listDevice[RouteTable.POS_SIZE_ID_ACT], byteorder=
'big')
410 answer += listAct[RouteTable.POS_TYPE_ACT].to_bytes(MessageTCP.SIZE_TYPE_ACTUATOR, byteorder=
'big')
411 answer += bytes( [ listAct[RouteTable.POS_SIZE_IN] ] )
412 answer += bytes( [ listAct[RouteTable.POS_TYPE_IN] ] )
416 client.send(bytearray(answer))
418 elif data == MessageTCP.GET_SENSOR_VALUE:
419 print(
"Request: GET SENSOR VALUE")
421 deviceIDInt = int.from_bytes(deviceID,byteorder=
'big')
422 address = self.
_routeTable[deviceIDInt][RouteTable.POS_ADDRESS]
423 sensorID = client.recv(self.
_routeTable[deviceIDInt][RouteTable.POS_SIZE_ID_SEN])
424 connector = self.
_routeTable[deviceIDInt][RouteTable.POS_CONNECTOR]
425 sensorValue = connector.getSensorValue(address,sensorID)
427 client.send(sensorValue)
429 elif data == MessageTCP.SET_ACTUATOR_VALUE:
430 print(
"Request: SET ACTUATOR VALUE")
432 deviceIDInt = int.from_bytes(deviceID,byteorder=
'big')
433 address = self.
_routeTable[deviceIDInt][RouteTable.POS_ADDRESS]
434 actuatorID = client.recv(self.
_routeTable[deviceIDInt][RouteTable.POS_SIZE_ID_ACT])
435 actuatorIDInt = int.from_bytes(actuatorID,byteorder=
'big')
436 value = client.recv(self.
_routeTable[deviceIDInt][RouteTable.POS_DICTIONARY_ACT][actuatorIDInt][RouteTable.POS_SIZE_IN])
438 connector = self.
_routeTable[deviceIDInt][RouteTable.POS_CONNECTOR]
439 connector.setActuatorValue(address,actuatorID,value)
441 elif data == MessageTCP.MSG_TO_DEVICE:
444 deviceIDInt = int.from_bytes(deviceID,byteorder=
'big')
445 address = self.
_routeTable[deviceIDInt][RouteTable.POS_ADDRESS]
446 value = client.recv(self.
_routeTable[deviceIDInt][RouteTable.POS_SIZE_IO_DEVICE])
448 connector = self.
_routeTable[deviceIDInt][RouteTable.POS_CONNECTOR]
449 connector.msgToDevice(address,value)
451 elif data == MessageTCP.MSG_AND_ANSWER_TO_DEVICE:
452 print(
"Request: MSG_AND_ANSWER_TO_DEVICE")
454 deviceIDInt = int.from_bytes(deviceID,byteorder=
'big')
455 address = self.
_routeTable[deviceIDInt][RouteTable.POS_ADDRESS]
456 value = client.recv(self.
_routeTable[deviceIDInt][RouteTable.POS_SIZE_IO_DEVICE])
457 connector = self.
_routeTable[deviceIDInt][RouteTable.POS_CONNECTOR]
459 answer = connector.msgAndAnswerToDevice(address,value)
460 client.send( answer )
462 elif data == MessageTCP.CLOSE_TCP_CONNECTION:
463 print(
"Request: CLOSE TCP CONNECTION")
468 print(
"TCP Message -Not implemented- ",data)
473 """MultiThread version of manageCommunication().""" 479 """Don't use directly, use: Gateway.manageCommunicationThread().""" 482 """Internal use only.""" 483 super(manageClientThread, self).
__init__()
488 """Internal use only.""" def removeConnectors(self)
def manageCommunicationThread(self, client)
def addDevices(self, newNodes)
def saveTable(self, path, verboseFile=True)
def addReservedID(self, ID, addr, connector)
def __init__(self, gateway, client)
def addConnector(self, newConnector)
def loadTable(self, filePath, findConnector=True)
def addDevice(self, newDev)
def managerCommunication(self, client)
def removeDevice(self, idDevice)
def _updateSizeIDDevice(self, newID)
def discoveryAndUpdateTable(self)
def updateTable(self, devices)
def discoveryAndCreateTable(self)
def getConnector(self, address, typeConnector)
def createTCPServer(self, IP, port)