Blame view

src/device_controller/channels/client_channel_socket.py 7.24 KB
ac0e5c70   Etienne Pallier   nouveau devices_c...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python3

"""Socket Client implementation (TCP or UDP)

"""


# Standard library imports
import socket

# Third party imports
# None

# Local application imports
ef335590   Etienne Pallier   Agent v2 asynchro...
15
from src.device_controller.channels.client_channel import *
ac0e5c70   Etienne Pallier   nouveau devices_c...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35




##class SocketClientAbstract():
class ClientChannelSocket(ClientChannel):
    
    # Select protocol here (udp or tcp)
    buf = 1024
    mysock = None
    
    # STAMP : 
    # 00 00 00 00 00 00 00' (8 bytes from '00' to 'FF', 1st one is LOW BYTE)
    # ex: 01 + STAMP = 01 00 00 00 00 00 00 00' (8 bytes from '00' to 'FF', 1st one is LOW BYTE)
    #STAMP_FILLER = '00000000000000'
    ''' 
    STAMP_FILLER = '000000' 
    MYSTAMP = '01'
    MY_FULL_STAMP = MYSTAMP + STAMP_FILLER
    '''
ce74dbbb   Etienne Pallier   LOGGER unique : p...
36
37
38
39


    #def __init__(self, server_host:str="localhost", server_port:int=11110, PROTOCOL:str="SOCKET-TCP", buffer_size=1024, DEBUG=False):
    def __init__(self, server_host:str="localhost", server_port:int=11110, PROTOCOL:str="SOCKET-TCP", buffer_size=1024):
ac0e5c70   Etienne Pallier   nouveau devices_c...
40
41
42
43
44
45
46
        '''
        :param server_host: server IP or hostname
        :param server_port: server port
        :param PROTOCOL: "SOCKET-UDP" or "SOCKET-TCP"
        '''        
        myprotocol = socket.SOCK_DGRAM if PROTOCOL=="SOCKET-UDP" else socket.SOCK_STREAM
        self.mysock = socket.socket(socket.AF_INET, myprotocol)
ce74dbbb   Etienne Pallier   LOGGER unique : p...
47
48
        #super().__init__(server_host, server_port, PROTOCOL, buffer_size, DEBUG)
        super().__init__(server_host, server_port, PROTOCOL, buffer_size)
ac0e5c70   Etienne Pallier   nouveau devices_c...
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
        # Logger configuration
        #self.set_logger()
        '''
        log_d("\n**************************")
        log_d("Logger configured")
        log_d("Client instanciated")
        '''
           
        
    '''
    def _send_data(self, data_to_send:str):
        #data_to_send = bytes(data_to_send + "\n", "utf-8")
        #data_to_send = bytes(data_to_send + "\x00", "utf-8")
        ##data_to_send = bytes(data_to_send, "utf-8")
        #print("before sending", data_to_send)
        data_to_send_bytes = data_to_send.encode("utf-8")
        #data_to_send_bytes = data_to_send.encode()
        #print("before sending", data_to_send_bytes)
        if self.PROTOCOL=="SOCKET-TCP": 
            # Unlike send(), this method sendall() continues to send data from bytes until either all data has been sent or an error occurs. 
            # None is returned on success. 
            # On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent
            nb_bytes_sent = self.mysock.sendall(data_to_send_bytes)
        else:
            nb_bytes_sent = self.mysock.sendto(data_to_send_bytes, (self.HOST, self.PORT))
        log_i(f'Sent: {data_to_send_bytes}')
        log_i(f"Sent {nb_bytes_sent} bytes")
    '''
    '''
    def _receive_data(self)->bytes:
        data_received = self.mysock.recv(self.buf)
        #log_d("data type is "+str(type(data_received)))
        log_i(f"RECEIVED (ALL BYTES): {data_received}") 
        #return str(data_received, "utf-8")
        return data_received
    '''

    # Only for TCP ; does nothing for UDP
    #@override
    def _connect_to_server(self):
        if self.PROTOCOL=="SOCKET-TCP": self.mysock.connect((self.HOST, self.PORT))
ce74dbbb   Etienne Pallier   LOGGER unique : p...
90
        self.printd(f"Ready to send commands to HOST {self.HOST} on PORT {self.PORT} \n")
ac0e5c70   Etienne Pallier   nouveau devices_c...
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

    
    # Close socket
    def close(self):
        self.mysock.close()

    #@override
    def _send_data(self, data_to_send:str):
        #data_to_send = bytes(data_to_send + "\n", "utf-8")
        #data_to_send = bytes(data_to_send + "\x00", "utf-8")
        ##data_to_send = bytes(data_to_send, "utf-8")
        data_to_send_bytes = data_to_send.encode("utf-8")
        #data_to_send_bytes = data_to_send.encode()
        if self.PROTOCOL=="SOCKET-TCP": 
            # Unlike send(), this method sendall() continues to send data from bytes until either all data has been sent or an error occurs. 
            # None is returned on success. 
            # On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent
            nb_bytes_sent = self.mysock.sendall(data_to_send_bytes)
        else: 
            # SOCKET-UDP
            nb_bytes_sent = self.mysock.sendto(data_to_send_bytes, (self.HOST, self.PORT))
1cf4a67f   Etienne Pallier   Affichage console...
112
113
114
115
        ##log_i(f'(channel sock) Sent: {data_to_send_bytes}')
        ##log_i(f"(channel sock) Sent {nb_bytes_sent} bytes")
        ##log_i(f"(channel sock) Sent {nb_bytes_sent} bytes ; mesg sent is: ", data_to_send_bytes)
        ##log_i("(channel sock) Sent ",nb_bytes_sent, "bytes ; mesg sent is: ", data_to_send_bytes)
ce74dbbb   Etienne Pallier   LOGGER unique : p...
116
        self.printd("(channel sock) Sent ",nb_bytes_sent, "bytes ; mesg sent is: ", data_to_send_bytes)
ac0e5c70   Etienne Pallier   nouveau devices_c...
117
118
119
120
121
122
123
124
125

    #@override
    def _receive_data(self)->str:
        data_received_bytes = self.mysock.recv(self.buf)
        #TODO: resoudre ce pb plus proprement (utiliser unicode au lieu de utf-8 codec ???
        # BUGFIX: b'\xdf' (should correspond to "°" symbol) generates a UnicodeDecodeError,
        # so, replace it by ':' (b'\x3A')
        if b'\xdf' in data_received_bytes:
            data_received_bytes = data_received_bytes.replace(b'\xdf', b'\x3A')
ce74dbbb   Etienne Pallier   LOGGER unique : p...
126
        self.printd(f"(channel sock) RECEIVED (ALL BYTES...): {data_received_bytes}") 
1cf4a67f   Etienne Pallier   Affichage console...
127
        ##log_i(f"(channel sock) ({self}) RECEIVED (ALL BYTES...): {data_received_bytes}") 
ce74dbbb   Etienne Pallier   LOGGER unique : p...
128
        self.printd(f"(channel sock) ({self}) RECEIVED (ALL BYTES...): {data_received_bytes}") 
ac0e5c70   Etienne Pallier   nouveau devices_c...
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

        data_received = data_received_bytes.decode()
        #log_d("data type is "+str(type(data_received)))
        #return str(data_received, "utf-8")
        return data_received

    '''
    # Encapsulate useful data to be ready for sending
    #@override    
    def encapsulate_data_to_send(self, data:str):
        #return bytes(data, "utf-8")
        return data.encode("utf-8")
    # Extract data from received raw data
    #@override    
    def uncap_received_data(self, data_received_bytes:bytes):
        #return data_received.decode("utf-8)
        return data_received_bytes.decode()
    '''
        

# TODO: empecher de creer une instance de cette classe abstraite
# Avec ABC ?

'''
if __name__ == "__main__":
    
    #HOST, PORT = "localhost", 9999
    #HOST, PORT = "localhost", 20001
    HOST, PORT = "localhost", 11110

    # Classic usage:
    #tsock = SocketClient_UDP_TCP(HOST, PORT, "UDP")
    # More elegant usage, using "with":
    with SocketClient_ABSTRACT(HOST, PORT, "UDP") as tsock:
        
        # 0) CONNECT to server (only for TCP, does nothing for UDP)
        tsock._connect_to_server()
        
        while True:
            
            # 1) SEND REQUEST data to server
            # saisie de la requête au clavier et suppression des espaces des 2 côtés
            data = input("REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: ").strip()
            # test d'arrêt
            if data=="": break
            #data_to_send = bytes(data + "\n", "utf-8")
            tsock.send_data(data)
            #mysock.sendto("%s" % data, (HOST, PORT))
            #print("Sent: {}".format(data))
    
            # 2) RECEIVE REPLY data from server
            data_received = tsock.receive_data()
            #reponse, adr = mysock.recvfrom(buf)
            #print("Received: {}".format(data_received))
            #print("Useful data received: {}".format(data_useful))
            print('\n')

        #tsock.close()
'''