Blame view

src/devices/Device.py 5.44 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
e8e6f017   Jeremy   Reworked devices ...
53
        try:
f7dd3df1   Jeremy   Update simulators...
54
            readable, writable, exceptional = select.select([], [self.sock], [self.sock], 0)
e8e6f017   Jeremy   Reworked devices ...
55
56
57
            if not (writable or exceptional):
                raise (Exception("Socket not writable"))
            self.sock.send(bytes(message, "UTF-8"))
605b65e5   Jeremy   Update simulators
58
        except Exception as e:
e8e6f017   Jeremy   Reworked devices ...
59
            if (settings.DEBUG):
605b65e5   Jeremy   Update simulators
60
                self.log(self.name, "Could not send message on socket : " + message + " -> " + str(e))
15e15006   Etienne Pallier   Nouvelles modifs ...
61
62
63
64
65
66
            # (EP) NON, 1 = true !!!
            #return (1)
            return False
        # (EP) NON, 0 = false !!!
        #return (0)
        return True
e8e6f017   Jeremy   Reworked devices ...
67
68

    def isError(self, message: str):
15e15006   Etienne Pallier   Nouvelles modifs ...
69
70
71
        #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 ...
72
73
74
75
76
            return (True)
        return (False)

    def isConnected(self):
        if (not self.sock or not self.connected):
1a2dc19f   Etienne Pallier   nombreux bugfixes...
77
78
            # (EP) NON, c'est totalement illisible !!! on n'est plus en 1970
            #if (self.connect()): return (False)
15e15006   Etienne Pallier   Nouvelles modifs ...
79
80
81
            if not self.connect(): return False
        self.connected = True
        return True
e8e6f017   Jeremy   Reworked devices ...
82
83
84

    def readBytes(self, size) -> str:
        if (not self.isConnected()):
15e15006   Etienne Pallier   Nouvelles modifs ...
85
            return ("NOT_SET2")
65149de7   Jeremy   Update
86
        try:
f7dd3df1   Jeremy   Update simulators...
87
            readable, writable, exceptional = select.select([self.sock], [], [self.sock], 0)
e8e6f017   Jeremy   Reworked devices ...
88
89
90
91
92
93
94
95
            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
96
        except Exception as e:
e8e6f017   Jeremy   Reworked devices ...
97
            if (settings.DEBUG):
605b65e5   Jeremy   Update simulators
98
                self.log(self.name, "Socket not readable : " + str(e))
e8e6f017   Jeremy   Reworked devices ...
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
            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...
130
131
        if DEBUG_FILE and settings.DEBUG:
            self.logger.info("From device : " + device_name + " -> " + message)
e8e6f017   Jeremy   Reworked devices ...
132
133
134
135
136
        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...
137
138
139
            # (EP) It's a serious bug, so raise exception !!!
            #return (1)
            raise (Exception("PLC has no ip or port"))
e8e6f017   Jeremy   Reworked devices ...
140
        try:
15e15006   Etienne Pallier   Nouvelles modifs ...
141
            # Create a TCP/IP socket
e8e6f017   Jeremy   Reworked devices ...
142
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
15e15006   Etienne Pallier   Nouvelles modifs ...
143
            # Connect the socket to the port on the server
65149de7   Jeremy   Update
144
            self.sock.connect((self.ip, self.port))
15e15006   Etienne Pallier   Nouvelles modifs ...
145
146
147
148
149
150
151
152
153
154
            '''
            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 ...
155
        except Exception as e:
1a2dc19f   Etienne Pallier   nombreux bugfixes...
156
            print("FAILED TO CONNECT")
e8e6f017   Jeremy   Reworked devices ...
157
            if (settings.DEBUG):
15e15006   Etienne Pallier   Nouvelles modifs ...
158
                #TODO: Bugfix: Ce log ne fait rien !
605b65e5   Jeremy   Update simulators
159
                self.log(self.name, "Failed to connect to " + str(self.ip) + ":" + str(self.port) + " -> " + str(e))
1a2dc19f   Etienne Pallier   nombreux bugfixes...
160
161
162
            # (EP) return TRUE??? (for python, 1=true !!!)
            #return (1)
            return False
e8e6f017   Jeremy   Reworked devices ...
163
        self.connected = True
1a2dc19f   Etienne Pallier   nombreux bugfixes...
164
165
166
        # (EP) return FALSE ??? (for python, 0=false !!!)
        #return (0)
        return True