Blame view

src/devices/Device.py 5.95 KB
e8e6f017   Jeremy   Reworked devices ...
1
from django.conf import settings
ac26ad2b   haribo   Date: 22/07/2016
2
import socket
bb0fbab1   haribo   Fini de mettre la...
3
import configparser
e8e6f017   Jeremy   Reworked devices ...
4
5
import abc
import select
bca9a283   Jeremy   Reworked the sche...
6
import utils.Logger as L
bb0fbab1   haribo   Fini de mettre la...
7

257abe9b   Jeremy   Added comments
8
9
DEBUG_FILE = False

e8e6f017   Jeremy   Reworked devices ...
10
'''
257abe9b   Jeremy   Added comments
11
    Generic object for the communication with all the devices
e8e6f017   Jeremy   Reworked devices ...
12
'''
9774228b   haribo   Date: 22/06/2016
13

65149de7   Jeremy   Update
14

ddf59dd4   haribo   Remaniement :
15
class DeviceController():
e8e6f017   Jeremy   Reworked devices ...
16
17
18
19
20
21
22
23
24
    __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
9b5bad52   haribo   Commented all the...
25

bb0fbab1   haribo   Fini de mettre la...
26
    def __init__(self, device_name):
e8e6f017   Jeremy   Reworked devices ...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
        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

ce470283   Jeremy   Plc simulator fin...
44
45
46
47
    @abc.abstractmethod
    def getStatus(self):
        return

e8e6f017   Jeremy   Reworked devices ...
48
49
    def sendMessage(self, message: str) -> int:
        if (not self.isConnected()):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
50
51
52
            # (EP) NON, return 0 !!!
            #return (1)
            return False
c7583f6e   Etienne Pallier   Cleaner isolation...
53
        # (EP) Here we are still not sure that we are connected to the device (it may be down and we do not know)
e8e6f017   Jeremy   Reworked devices ...
54
        try:
f7dd3df1   Jeremy   Update simulators...
55
            readable, writable, exceptional = select.select([], [self.sock], [self.sock], 0)
e8e6f017   Jeremy   Reworked devices ...
56
57
58
            if not (writable or exceptional):
                raise (Exception("Socket not writable"))
            self.sock.send(bytes(message, "UTF-8"))
605b65e5   Jeremy   Update simulators
59
        except Exception as e:
e8e6f017   Jeremy   Reworked devices ...
60
            if (settings.DEBUG):
c7583f6e   Etienne Pallier   Cleaner isolation...
61
62
                print("(ENV) Could not send message (on socket) to "+self.name+" : " + message + " -> " + str(e))
                #EP TODO: bugfix: ce log ne fait rien du tout !!
605b65e5   Jeremy   Update simulators
63
                self.log(self.name, "Could not send message on socket : " + message + " -> " + str(e))
15e15006   Etienne Pallier   Nouvelles modifs ...
64
65
66
67
68
69
            # (EP) NON, 1 = true !!!
            #return (1)
            return False
        # (EP) NON, 0 = false !!!
        #return (0)
        return True
e8e6f017   Jeremy   Reworked devices ...
70
71

    def isError(self, message: str):
15e15006   Etienne Pallier   Nouvelles modifs ...
72
73
74
        #EP
        #if (message == "FAILED" or message == "NOT_SET" or message == "DISCONNECTED"):
        if (message == "FAILED" or message.startswith("NOT_SET") or message == "DISCONNECTED"):
e8e6f017   Jeremy   Reworked devices ...
75
76
77
            return (True)
        return (False)

c7583f6e   Etienne Pallier   Cleaner isolation...
78
    # MIND: Does not mean "is connected now" but "WAS connected once"
e8e6f017   Jeremy   Reworked devices ...
79
80
    def isConnected(self):
        if (not self.sock or not self.connected):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
81
82
            # (EP) NON, c'est totalement illisible !!! on n'est plus en 1970
            #if (self.connect()): return (False)
c7583f6e   Etienne Pallier   Cleaner isolation...
83
            print("something is wrong with this device, now trying to connect again...")
15e15006   Etienne Pallier   Nouvelles modifs ...
84
            if not self.connect(): return False
c7583f6e   Etienne Pallier   Cleaner isolation...
85
            #self.connected = True
15e15006   Etienne Pallier   Nouvelles modifs ...
86
        return True
e8e6f017   Jeremy   Reworked devices ...
87
88
89

    def readBytes(self, size) -> str:
        if (not self.isConnected()):
15e15006   Etienne Pallier   Nouvelles modifs ...
90
            return ("NOT_SET2")
65149de7   Jeremy   Update
91
        try:
f7dd3df1   Jeremy   Update simulators...
92
            readable, writable, exceptional = select.select([self.sock], [], [self.sock], 0)
e8e6f017   Jeremy   Reworked devices ...
93
94
95
96
97
98
99
100
            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")
605b65e5   Jeremy   Update simulators
101
        except Exception as e:
e8e6f017   Jeremy   Reworked devices ...
102
            if (settings.DEBUG):
605b65e5   Jeremy   Update simulators
103
                self.log(self.name, "Socket not readable : " + str(e))
e8e6f017   Jeremy   Reworked devices ...
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
            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):
c53a13e0   Jeremy   Updating a lot of...
135
136
        if DEBUG_FILE and settings.DEBUG:
            self.logger.info("From device : " + device_name + " -> " + message)
e8e6f017   Jeremy   Reworked devices ...
137
138
139
140
141
        return (0)

    def connect(self):
        if (self.ip is None or self.port is None):
            self.log(self.name, "Ip or Port not initialized")
1a2dc19f   Etienne Pallier   nombreux bugfixes...
142
143
            # (EP) It's a serious bug, so raise exception !!!
            #return (1)
c7583f6e   Etienne Pallier   Cleaner isolation...
144
            raise (Exception(self.name +"Controller has no ip or port to connect to"))
e8e6f017   Jeremy   Reworked devices ...
145
        try:
15e15006   Etienne Pallier   Nouvelles modifs ...
146
            # Create a TCP/IP socket
e8e6f017   Jeremy   Reworked devices ...
147
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
15e15006   Etienne Pallier   Nouvelles modifs ...
148
            # Connect the socket to the port on the server
65149de7   Jeremy   Update
149
            self.sock.connect((self.ip, self.port))
15e15006   Etienne Pallier   Nouvelles modifs ...
150
151
152
153
154
155
156
157
158
159
            '''
            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)
e8e6f017   Jeremy   Reworked devices ...
160
        except Exception as e:
c7583f6e   Etienne Pallier   Cleaner isolation...
161
            print("FAILED TO CONNECT TO DEVICE {}".format(self.name))
e8e6f017   Jeremy   Reworked devices ...
162
            if (settings.DEBUG):
15e15006   Etienne Pallier   Nouvelles modifs ...
163
                #TODO: Bugfix: Ce log ne fait rien !
605b65e5   Jeremy   Update simulators
164
                self.log(self.name, "Failed to connect to " + str(self.ip) + ":" + str(self.port) + " -> " + str(e))
1a2dc19f   Etienne Pallier   nombreux bugfixes...
165
166
167
            # (EP) return TRUE??? (for python, 1=true !!!)
            #return (1)
            return False
e8e6f017   Jeremy   Reworked devices ...
168
        self.connected = True
1a2dc19f   Etienne Pallier   nombreux bugfixes...
169
170
171
        # (EP) return FALSE ??? (for python, 0=false !!!)
        #return (0)
        return True