Commit 54cb16da28f8a8885f1a32fa0c57b332389983fa
1 parent
e519f61d
Exists in
dev
implementation du do_MOVE()
et renommage du dossier sockets_tele/src en src_socket pour eviter conflit avec pyros/src (les imports fonctionnent mieux ainsi...) mais git aime pas trop quand on renomme un dossier...
Showing
12 changed files
with
447 additions
and
88 deletions
Show diff stats
sockets_tele/README.txt
... | ... | @@ -63,6 +63,8 @@ Pour lancer le client sur le "simulateur" de telescope (localhost, port 11110): |
63 | 63 | ******************************************************************************************** |
64 | 64 | 4) DONE |
65 | 65 | |
66 | + - doctests | |
67 | + | |
66 | 68 | - GOTO |
67 | 69 | - finalize do_init() |
68 | 70 | |
... | ... | @@ -96,11 +98,15 @@ Pour lancer le client sur le "simulateur" de telescope (localhost, port 11110): |
96 | 98 | ******************************************************************************************** |
97 | 99 | 5) WORK CURRENTLY IN PROGRESS... |
98 | 100 | |
99 | - - doctests | |
100 | 101 | |
101 | - - tele au lieu de tsock | |
102 | + - move do_GOTO dans abstract | |
102 | 103 | |
104 | + - main updated | |
103 | 105 | - tests updated |
106 | + | |
107 | + - comment functions args | |
108 | + | |
109 | + - clean code | |
104 | 110 | |
105 | 111 | |
106 | 112 | ******************************************************************************************** |
... | ... | @@ -114,7 +120,8 @@ Pour lancer le client sur le "simulateur" de telescope (localhost, port 11110): |
114 | 120 | - doc page 1 : x=implémenté, p=partial, - = pas implémenté |
115 | 121 | |
116 | 122 | - POSITION (p103): |
117 | - - (100) MOVE() en altaz ou radec | |
123 | + - (100) MOVE() (p104-105) | |
124 | + => en altaz ou radec | |
118 | 125 | => préférer "haut, bas, gauche, droite" plutôt que North, South, west, east (surtout sur altaz ça n'a aucun sens) |
119 | 126 | => sur equatorial, h,b = DEC et g,d = RA |
120 | 127 | - set_speed() | ... | ... |
sockets_tele/client_gemini_run.py
1 | 1 | #!/usr/bin/env python3 |
2 | 2 | |
3 | -from src.client.socket_client_telescope_gemini import SocketClientTelescopeGEMINI | |
3 | +from src_socket.client.socket_client_telescope_gemini import SocketClientTelescopeGEMINI | |
4 | 4 | |
5 | 5 | import sys |
6 | 6 | |
... | ... | @@ -19,18 +19,18 @@ else: |
19 | 19 | #if sys.argv[1] == "local": |
20 | 20 | HOST, PORT = "localhost", 11110 |
21 | 21 | |
22 | -#tsock = SocketClient_UDP_TCP(HOST, PORT) | |
23 | -with SocketClientTelescopeGEMINI(HOST, PORT, DEBUG) as tsock: | |
24 | - #tsock.connect_to_server() | |
22 | +#tele_client = SocketClient_UDP_TCP(HOST, PORT) | |
23 | +with SocketClientTelescopeGEMINI(HOST, PORT, DEBUG) as tele_client: | |
24 | + #tele_client.connect_to_server() | |
25 | 25 | # Only useful for TCP (does nothing for UDP) |
26 | - tsock._connect_to_server() | |
26 | + tele_client._connect_to_server() | |
27 | 27 | |
28 | - print("RA is", tsock.get_RA()) | |
29 | - print("ack is", tsock.get_ACK()) | |
28 | + print("RA is", tele_client.get_RA()) | |
29 | + print("ack is", tele_client.get_ACK()) | |
30 | 30 | |
31 | 31 | # Initialize telescope config (ack, date, time) |
32 | - #tsock.do("INIT") | |
33 | - tsock.do_INIT() | |
32 | + #tele_client.do("INIT") | |
33 | + tele_client.do_INIT() | |
34 | 34 | |
35 | 35 | ''' |
36 | 36 | TEST ENVOI DIRECT: |
... | ... | @@ -42,29 +42,29 @@ with SocketClientTelescopeGEMINI(HOST, PORT, DEBUG) as tsock: |
42 | 42 | #data = 0x010000003a474423 |
43 | 43 | #data = b'010000003a474423' |
44 | 44 | |
45 | - #data_to_send = tsock._format_data_to_send(data) | |
46 | - tsock._send_data(data) | |
47 | - #data_received = tsock.receive_data() | |
48 | - data_received = tsock.mysock.recv(1024) | |
45 | + #data_to_send = tele_client._format_data_to_send(data) | |
46 | + tele_client._send_data(data) | |
47 | + #data_received = tele_client.receive_data() | |
48 | + data_received = tele_client.mysock.recv(1024) | |
49 | 49 | print("data rec = ", data_received) |
50 | 50 | ''' |
51 | 51 | |
52 | 52 | # Send some commands to the Telescope |
53 | - #pos = tsock.get_position() | |
54 | - #dec = tsock.get("DEC") | |
55 | - #ra = tsock.get("RA") | |
53 | + #pos = tele_client.get_position() | |
54 | + #dec = tele_client.get("DEC") | |
55 | + #ra = tele_client.get("RA") | |
56 | 56 | ''' |
57 | - tsock.get("NONE") | |
58 | - tsock.set("NONE", 1) | |
59 | - tsock.do("NONE") | |
57 | + tele_client.get("NONE") | |
58 | + tele_client.set("NONE", 1) | |
59 | + tele_client.do("NONE") | |
60 | 60 | ''' |
61 | 61 | |
62 | - #radec = tsock.get("RA-DEC") | |
63 | - radec = tsock.get_RADEC() | |
62 | + #radec = tele_client.get("RA-DEC") | |
63 | + radec = tele_client.get_RADEC() | |
64 | 64 | print("RA-DEC is", radec) |
65 | 65 | |
66 | - #ack = tsock.put_read("6") | |
67 | - ack = tsock.get_ACK() | |
66 | + #ack = tele_client.put_read("6") | |
67 | + ack = tele_client.get_ACK() | |
68 | 68 | print("ACK is", ack) |
69 | 69 | |
70 | 70 | # TEST BAS NIVEAU POUR ACK 06: |
... | ... | @@ -92,7 +92,7 @@ with SocketClientTelescopeGEMINI(HOST, PORT, DEBUG) as tsock: |
92 | 92 | b'#' |
93 | 93 | >>> a.decode() |
94 | 94 | '#' |
95 | - >>> tsock.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x3A\x47\x44\x23\x00', (HOST, PORT)) | |
95 | + >>> tele_client.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x3A\x47\x44\x23\x00', (HOST, PORT)) | |
96 | 96 | RECEIVED (ALL BYTES): b'\x00\x00\x00\x01\x00\x00\x00\x00+90.000000#\x00' |
97 | 97 | |
98 | 98 | >>> a=b'\x52' |
... | ... | @@ -100,73 +100,74 @@ with SocketClientTelescopeGEMINI(HOST, PORT, DEBUG) as tsock: |
100 | 100 | b'R' |
101 | 101 | >>> a.decode() |
102 | 102 | 'R' |
103 | - >>> tsock.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x3A\x47\x52\x23\x00', (HOST, PORT)) | |
103 | + >>> tele_client.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x3A\x47\x52\x23\x00', (HOST, PORT)) | |
104 | 104 | RECEIVED (ALL BYTES): b'\x00\x00\x00\x01\x00\x00\x00\x008.911844#\x00' |
105 | 105 | |
106 | - >>> tsock.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06\x00\x00', (HOST, PORT)) | |
106 | + >>> tele_client.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06\x00\x00', (HOST, PORT)) | |
107 | 107 | RECEIVED (ALL BYTES): b'\x00\x00\x00\x01\x00\x00\x00\x00G#\x00' |
108 | 108 | |
109 | 109 | ''' |
110 | - #tsock.mysock.sendto(b'00030000:GD#\x00', (HOST, PORT)) | |
111 | - #tsock.mysock.sendto(b'00030000\x06\x00', (HOST, PORT)) | |
112 | - #tsock.mysock.sendto(b'00030000\x00\x06\x00', (HOST, PORT)) | |
113 | - #tsock.mysock.sendto(b'00030000\0x06\x00', (HOST, PORT)) | |
114 | - #tsock.mysock.sendto(b'00010000\0x06\x00', (HOST, PORT)) | |
110 | + #tele_client.mysock.sendto(b'00030000:GD#\x00', (HOST, PORT)) | |
111 | + #tele_client.mysock.sendto(b'00030000\x06\x00', (HOST, PORT)) | |
112 | + #tele_client.mysock.sendto(b'00030000\x00\x06\x00', (HOST, PORT)) | |
113 | + #tele_client.mysock.sendto(b'00030000\0x06\x00', (HOST, PORT)) | |
114 | + #tele_client.mysock.sendto(b'00010000\0x06\x00', (HOST, PORT)) | |
115 | 115 | ''' |
116 | 116 | # :GD# |
117 | - ###tsock.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x3A\x47\x44\x23\x00', (HOST, PORT)) | |
117 | + ###tele_client.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x3A\x47\x44\x23\x00', (HOST, PORT)) | |
118 | 118 | |
119 | 119 | # :GR# |
120 | - ###tsock.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x3A\x47\x52\x23\x00', (HOST, PORT)) | |
120 | + ###tele_client.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x3A\x47\x52\x23\x00', (HOST, PORT)) | |
121 | 121 | |
122 | 122 | # ACK 06 OK !!! : |
123 | 123 | |
124 | - tsock.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06\x00\x00', (HOST, PORT)) | |
124 | + tele_client.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x00\x06\x00\x00', (HOST, PORT)) | |
125 | 125 | RECEIVED (ALL BYTES): b'\x00\x00\x00\x01\x00\x00\x00\x00G#\x00' |
126 | 126 | |
127 | - tsock.mysock.sendto(b'00010000\x00\x06\x00\x00', (HOST, PORT)) | |
127 | + tele_client.mysock.sendto(b'00010000\x00\x06\x00\x00', (HOST, PORT)) | |
128 | 128 | RECEIVED (ALL BYTES): b'00010000G#\x00' |
129 | 129 | ''' |
130 | 130 | ''' |
131 | 131 | # wrong: b'00010000\\x00\\x06\\x00\x00' |
132 | 132 | # ok: |
133 | 133 | \x05\x00\x00\ |
134 | - #tsock.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00', (HOST, PORT)) | |
135 | - #tsock.mysock.sendto(b'00010000\x00\x05\x00\x00', (HOST, PORT)) | |
136 | - tsock.mysock.sendto(b'00010000\x00\x06\x00\x00', (HOST, PORT)) | |
137 | - data_received = tsock.receive_data() | |
134 | + #tele_client.mysock.sendto(b'\x00\x00\x00\x01\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00', (HOST, PORT)) | |
135 | + #tele_client.mysock.sendto(b'00010000\x00\x05\x00\x00', (HOST, PORT)) | |
136 | + tele_client.mysock.sendto(b'00010000\x00\x06\x00\x00', (HOST, PORT)) | |
137 | + data_received = tele_client.receive_data() | |
138 | 138 | ''' |
139 | 139 | |
140 | - #tsock.do_GOTO(ra='22:00:00',dec='+30:00:00') | |
141 | - #tsock.do_GOTO(ra='21:00:00',dec='+20:00:00') | |
140 | + #tele_client.do_GOTO(ra='22:00:00',dec='+30:00:00') | |
141 | + #tele_client.do_GOTO(ra='21:00:00',dec='+20:00:00') | |
142 | + #tele_client.do_MOVE_DIR('EAST','4', 'slew') | |
142 | 143 | |
143 | 144 | # Do EXPERT mode execution |
144 | 145 | while True: |
145 | 146 | |
146 | - #print("Available commands:", tsock.available_commands()) | |
147 | - tsock.print_available_commands() | |
147 | + #print("Available commands:", tele_client.available_commands()) | |
148 | + tele_client.print_available_commands() | |
148 | 149 | #data = input("\n(EXPERT MODE) REQUEST TO SERVER [ex: '6' (ACK), ':GD#' (Get Dec), ':GR#' (Get RA)'], (ENTER to quit): ").strip() |
149 | 150 | req = input("REQUEST TO SERVER (ENTER to quit): >>> ").strip() |
150 | 151 | # test d'arrêt |
151 | 152 | #if data=="": break |
152 | 153 | if not req: break |
153 | - result = tsock.execute(req) | |
154 | + result = tele_client.execute(req) | |
154 | 155 | |
155 | 156 | ''' |
156 | 157 | #data_to_send = bytes(data + "\n", "utf-8")` |
157 | - tsock.send_request(req) | |
158 | + tele_client.send_request(req) | |
158 | 159 | |
159 | 160 | #mysock.sendto("%s" % data, (HOST, PORT)) |
160 | 161 | #print("Sent: {}".format(data)) |
161 | 162 | |
162 | 163 | # 2) RECEIVE REPLY data from server |
163 | - data_received = tsock.receive_data() | |
164 | + data_received = tele_client.receive_data() | |
164 | 165 | #reponse, adr = mysock.recvfrom(buf) |
165 | 166 | #print("Received: {}".format(data_received)) |
166 | 167 | #print("Useful data received: {}".format(data_useful)) |
167 | 168 | ''' |
168 | 169 | |
169 | - ###tsock.do_PARK() | |
170 | + tele_client.do_PARK() | |
170 | 171 | |
171 | - #tsock.close() | |
172 | + #tele_client.close() | |
172 | 173 | ... | ... |
sockets_tele/src/__init__.py renamed to sockets_tele/src_socket/__init__.py
sockets_tele/src/client/__init__.py renamed to sockets_tele/src_socket/client/__init__.py
sockets_tele/src/client/socket_client_abstract.py renamed to sockets_tele/src_socket/client/socket_client_abstract.py
... | ... | @@ -139,7 +139,7 @@ class SocketClientAbstract(): |
139 | 139 | |
140 | 140 | # Extract useful data from received raw data |
141 | 141 | # By default, do nothing |
142 | - def _uncap_data(self, data_received:bytes): | |
142 | + def _uncap_received_data(self, data_received:bytes): | |
143 | 143 | return data_received.decode() |
144 | 144 | |
145 | 145 | |
... | ... | @@ -187,7 +187,7 @@ class SocketClientAbstract(): |
187 | 187 | data_received_bytes = self._receive_data() |
188 | 188 | #log_d("Received (all data): {}".format(data_received)) |
189 | 189 | #log_d("data in bytes: "+str(bytes(data_received, "utf-8"))) |
190 | - data = self._uncap_data(data_received_bytes) | |
190 | + data = self._uncap_received_data(data_received_bytes) | |
191 | 191 | log_i("RECEIVED (useful data): {}".format(data)) |
192 | 192 | return data |
193 | 193 | ... | ... |
sockets_tele/src_socket/client/socket_client_plc_abstract.py
0 → 100755
... | ... | @@ -0,0 +1,282 @@ |
1 | +#!/usr/bin/env python3 | |
2 | + | |
3 | +import socket | |
4 | +import logging | |
5 | + | |
6 | +DEBUG = False | |
7 | +#DEBUG = True | |
8 | + | |
9 | +logger = None | |
10 | +# Aliases for logger: | |
11 | +def log_d(msg:str): logger.debug(msg) | |
12 | +def log_i(msg:str): logger.info(msg) | |
13 | +def log_w(msg:str): logger.warning(msg) | |
14 | +def log_e(msg:str): logger.error(msg) | |
15 | +def log_c(msg:str): logger.critical(msg) | |
16 | + | |
17 | +class Position(): | |
18 | + x = 0 | |
19 | + y = 0 | |
20 | + def __init__(self, x,y): | |
21 | + self.x = x | |
22 | + self.y = y | |
23 | + def get_values(self): | |
24 | + return self.x, self.y | |
25 | + | |
26 | + | |
27 | +class UnknownCommandException(Exception): | |
28 | + pass | |
29 | + ''' | |
30 | + def __init__(self,*args,**kwargs): | |
31 | + super().__init__(self,*args,**kwargs) | |
32 | + ''' | |
33 | + | |
34 | + | |
35 | +class SocketClient_ABSTRACT(): | |
36 | + | |
37 | + # Select protocol here (udp or tcp) | |
38 | + buf = 1024 | |
39 | + | |
40 | + # STAMP : | |
41 | + # 00 00 00 00 00 00 00' (8 bytes from '00' to 'FF', 1st one is LOW BYTE) | |
42 | + # ex: 01 + STAMP = 01 00 00 00 00 00 00 00' (8 bytes from '00' to 'FF', 1st one is LOW BYTE) | |
43 | + #STAMP_FILLER = '00000000000000' | |
44 | + ''' | |
45 | + STAMP_FILLER = '000000' | |
46 | + MYSTAMP = '01' | |
47 | + MY_FULL_STAMP = MYSTAMP + STAMP_FILLER | |
48 | + ''' | |
49 | + | |
50 | + #data = " ".join(sys.argv[1:]) | |
51 | + #data_to_send = bytes(data + "\n", "utf-8") | |
52 | + | |
53 | + | |
54 | + def __init__(self, server_host:str="localhost", server_port:int=11110, PROTOCOL:str="TCP", buffer_size=1024): | |
55 | + ''' | |
56 | + :param server_host: server IP or hostname | |
57 | + :param server_port: server port | |
58 | + :param PROTOCOL: "UDP" or "TCP" | |
59 | + ''' | |
60 | + self.HOST = server_host | |
61 | + self.PORT = server_port | |
62 | + self.PROTOCOL = PROTOCOL | |
63 | + self.buf = buffer_size | |
64 | + | |
65 | + self.protocol = socket.SOCK_DGRAM if PROTOCOL=="UDP" else socket.SOCK_STREAM | |
66 | + self.mysock = socket.socket(socket.AF_INET, self.protocol) | |
67 | + # Logger configuration | |
68 | + self.set_logger() | |
69 | + log_d("\n**************************") | |
70 | + log_d("Logger configured") | |
71 | + log_d("Client instanciated") | |
72 | + ''' | |
73 | + log_d("coucou") | |
74 | + ''' | |
75 | + | |
76 | + def set_logger(self): | |
77 | + global logger | |
78 | + ''' | |
79 | + # Logger configuration | |
80 | + # Log all events, starting from DEBUG level | |
81 | + # Above DEBUG, there is INFO, WARNING, ERROR, and then CRITICAL | |
82 | + ''' | |
83 | + | |
84 | + # Basic configuration | |
85 | + ''' | |
86 | + #logging.basicConfig(level=logging.DEBUG) | |
87 | + logging.basicConfig(level=logging.DEBUG, filename='client.log', filemode='a', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') | |
88 | + logging.debug("Client instanciated") | |
89 | + ''' | |
90 | + | |
91 | + # Advanced configuration | |
92 | + logger = logging.getLogger(__name__) | |
93 | + # Absolument necessaire, sinon rien ne marche !!! | |
94 | + logger.setLevel(logging.DEBUG) | |
95 | + | |
96 | + # Create handlers for writing to console and file | |
97 | + c_handler = logging.StreamHandler() | |
98 | + f_handler = logging.FileHandler('client.log') | |
99 | + | |
100 | + # Set level for each handler | |
101 | + if DEBUG: | |
102 | + c_handler.setLevel(logging.DEBUG) | |
103 | + f_handler.setLevel(logging.DEBUG) | |
104 | + else: | |
105 | + c_handler.setLevel(logging.INFO) | |
106 | + f_handler.setLevel(logging.INFO) | |
107 | + | |
108 | + # Set format for each handler | |
109 | + c_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s') | |
110 | + f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') | |
111 | + c_handler.setFormatter(c_format) | |
112 | + f_handler.setFormatter(f_format) | |
113 | + | |
114 | + # Set handlers (for console and file) | |
115 | + logger.addHandler(c_handler) | |
116 | + logger.addHandler(f_handler) | |
117 | + | |
118 | + | |
119 | + # So that we can use this with the "with" statement (context manager) | |
120 | + def __enter__(self): | |
121 | + return self | |
122 | + def __exit__(self, type, value, traceback): | |
123 | + self.close() | |
124 | + log_d("Client socket killed") | |
125 | + | |
126 | + | |
127 | + # Encapsulate useful data to be ready for sending | |
128 | + # By default, do nothing | |
129 | + def _encapsulate_data_to_send(self, data:str): | |
130 | + return data | |
131 | + | |
132 | + # Extract useful data from received raw data | |
133 | + # By default, do nothing | |
134 | + def _uncap_received_data(self, data_received:str): | |
135 | + return data_received | |
136 | + | |
137 | + | |
138 | + def send_data(self, data:str): | |
139 | + encapsulated_data = self._encapsulate_data_to_send(data) | |
140 | + self._send_data(encapsulated_data) | |
141 | + log_i(f'Sent: {encapsulated_data}') | |
142 | + | |
143 | + def _send_data(self, data_to_send:bytes): | |
144 | + #data_to_send = bytes(data_to_send + "\n", "utf-8") | |
145 | + data_to_send = bytes(data_to_send + "\x00", "utf-8") | |
146 | + if self.PROTOCOL=="TCP": | |
147 | + # Unlike send(), this method sendall() continues to send data from bytes until either all data has been sent or an error occurs. | |
148 | + # None is returned on success. | |
149 | + # On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent | |
150 | + nb_bytes_sent = self.mysock.sendall(data_to_send) | |
151 | + else: | |
152 | + nb_bytes_sent = self.mysock.sendto(data_to_send, (self.HOST, self.PORT)) | |
153 | + log_d(f"Sent {nb_bytes_sent} bytes") | |
154 | + | |
155 | + def receive_data(self): | |
156 | + data_received = self._receive_data() | |
157 | + log_d("Received (all data): {}".format(data_received)) | |
158 | + log_d("data in bytes: "+str(bytes(data_received, "utf-8"))) | |
159 | + data = self._uncap_received_data(data_received) | |
160 | + log_i("RECEIVED (useful data): {}".format(data)) | |
161 | + return data | |
162 | + | |
163 | + def _receive_data(self): | |
164 | + data_received = self.mysock.recv(self.buf) | |
165 | + log_d("data type is "+str(type(data_received))) | |
166 | + log_i(f"RECEIVED (ALL BYTES): {data_received}") | |
167 | + return str(data_received, "utf-8") | |
168 | + | |
169 | + # Only for TCP ; does nothing for UDP | |
170 | + def _connect_to_server(self): | |
171 | + if self.PROTOCOL=="TCP": self.mysock.connect((self.HOST, self.PORT)) | |
172 | + print(f"Ready to send commands to HOST {self.HOST} on PORT {self.PORT} \n") | |
173 | + | |
174 | + | |
175 | + # Close socket | |
176 | + def close(self): | |
177 | + self.mysock.close() | |
178 | + | |
179 | + ''' | |
180 | + TELESCOPE COMMANDS (abstract methods) | |
181 | + These methods must be overriden by the child classes, | |
182 | + otherwise they raise a NotImplementedError exception | |
183 | + ''' | |
184 | + | |
185 | + ''' | |
186 | + put(), read(), put_read() commands | |
187 | + ''' | |
188 | + def put(self, data:str): | |
189 | + self.send_data(data) | |
190 | + def read(self)->str: | |
191 | + return self.receive_data() | |
192 | + def put_read(self, data:str)->str: | |
193 | + # send command | |
194 | + self.put(data) | |
195 | + # receive answer (or ack) | |
196 | + return self.read() | |
197 | + | |
198 | + | |
199 | + ''' | |
200 | + The 3 main generic commands : get(), do(), set() | |
201 | + ''' | |
202 | + def get(self, what:str): | |
203 | + pass | |
204 | + def do(self): | |
205 | + pass | |
206 | + def set(self): | |
207 | + pass | |
208 | + | |
209 | + | |
210 | + ''' | |
211 | + Specific commands | |
212 | + ''' | |
213 | + | |
214 | + # @abstract | |
215 | + def start(self): | |
216 | + raise NotImplementedError | |
217 | + | |
218 | + # @abstract | |
219 | + def park(self): | |
220 | + raise NotImplementedError | |
221 | + | |
222 | + # @abstract | |
223 | + def goto(self, position:Position): | |
224 | + raise NotImplementedError | |
225 | + | |
226 | + # @abstract | |
227 | + def move(self, ): | |
228 | + raise NotImplementedError | |
229 | + | |
230 | + # @abstract | |
231 | + def get_coord_sys(self): | |
232 | + raise NotImplementedError | |
233 | + | |
234 | + # @abstract | |
235 | + def set_coord_sys(self): | |
236 | + raise NotImplementedError | |
237 | + | |
238 | + # @abstract | |
239 | + def get_position(self)->Position: | |
240 | + raise NotImplementedError | |
241 | + | |
242 | + | |
243 | + | |
244 | +# TODO: empecher de creer une instance de cette classe abstraite | |
245 | +# Avec ABC ? | |
246 | + | |
247 | +''' | |
248 | +if __name__ == "__main__": | |
249 | + | |
250 | + #HOST, PORT = "localhost", 9999 | |
251 | + #HOST, PORT = "localhost", 20001 | |
252 | + HOST, PORT = "localhost", 11110 | |
253 | + | |
254 | + # Classic usage: | |
255 | + #tsock = SocketClient_UDP_TCP(HOST, PORT, "UDP") | |
256 | + # More elegant usage, using "with": | |
257 | + with SocketClient_ABSTRACT(HOST, PORT, "UDP") as tsock: | |
258 | + | |
259 | + # 0) CONNECT to server (only for TCP, does nothing for UDP) | |
260 | + tsock._connect_to_server() | |
261 | + | |
262 | + while True: | |
263 | + | |
264 | + # 1) SEND REQUEST data to server | |
265 | + # saisie de la requête au clavier et suppression des espaces des 2 côtés | |
266 | + data = input("REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: ").strip() | |
267 | + # test d'arrêt | |
268 | + if data=="": break | |
269 | + #data_to_send = bytes(data + "\n", "utf-8") | |
270 | + tsock.send_data(data) | |
271 | + #mysock.sendto("%s" % data, (HOST, PORT)) | |
272 | + #print("Sent: {}".format(data)) | |
273 | + | |
274 | + # 2) RECEIVE REPLY data from server | |
275 | + data_received = tsock.receive_data() | |
276 | + #reponse, adr = mysock.recvfrom(buf) | |
277 | + #print("Received: {}".format(data_received)) | |
278 | + #print("Useful data received: {}".format(data_useful)) | |
279 | + print('\n') | |
280 | + | |
281 | + #tsock.close() | |
282 | +''' | |
0 | 283 | \ No newline at end of file | ... | ... |
sockets_tele/src/client/socket_client_telescope_abstract.py renamed to sockets_tele/src_socket/client/socket_client_telescope_abstract.py
... | ... | @@ -11,16 +11,21 @@ To be used as a base class (interface) for any concrete socket client telescope |
11 | 11 | import logging |
12 | 12 | import socket |
13 | 13 | import sys |
14 | +import time | |
14 | 15 | |
15 | 16 | # Third party imports |
16 | -sys.path.append("../src/") | |
17 | -import utils.celme as celme | |
17 | + | |
18 | +# from sockets_tele/ | |
19 | +sys.path.append("..") | |
20 | +# from src_socket/client/ | |
21 | +sys.path.append("../../..") | |
22 | +import src.utils.celme as celme | |
18 | 23 | |
19 | 24 | |
20 | 25 | # Local application imports |
21 | 26 | #sys.path.append('../..') |
22 | 27 | #from src.client.socket_client_abstract import UnknownCommandException, SocketClientAbstract |
23 | -from src.client.socket_client_abstract import * | |
28 | +from src_socket.client.socket_client_abstract import * | |
24 | 29 | |
25 | 30 | |
26 | 31 | |
... | ... | @@ -134,6 +139,10 @@ class SocketClientTelescopeAbstract(SocketClientAbstract): |
134 | 139 | def execute_native_cmd(self, request:str)->str: |
135 | 140 | self.send_request(request) |
136 | 141 | return self.receive_data() |
142 | + def execute_unformated_native_cmd(self, request:str)->str: | |
143 | + request = self.formated_cmd(request) | |
144 | + self.send_request(request) | |
145 | + return self.receive_data() | |
137 | 146 | |
138 | 147 | def send_request(self, request:str)->str: |
139 | 148 | return self.send_data(request) |
... | ... | @@ -208,6 +217,13 @@ class SocketClientTelescopeAbstract(SocketClientAbstract): |
208 | 217 | if len(res) == 1: return res[0] |
209 | 218 | return res |
210 | 219 | |
220 | + def set_SPEED(self, speed_rate): | |
221 | + pass | |
222 | + def do_MOVE_NORTH(self): pass | |
223 | + def do_MOVE_SOUTH(self): pass | |
224 | + def do_MOVE_WEST(self): pass | |
225 | + def do_MOVE_EAST(self): pass | |
226 | + | |
211 | 227 | ''' |
212 | 228 | def do(self, generic_cmd:str): |
213 | 229 | return NotImplementedError |
... | ... | @@ -286,6 +302,8 @@ class SocketClientTelescopeAbstract(SocketClientAbstract): |
286 | 302 | # @abstract |
287 | 303 | def do_PARK(self): return self._do("PARK") |
288 | 304 | def do_MOVE(self): return self._do("MOVE") |
305 | + def do_STOP(self): return self._do("STOP") | |
306 | + | |
289 | 307 | # @abstract |
290 | 308 | #def do_GOTO(self, pos:Position): return self._do("GOTO") |
291 | 309 | def do_WARM_START(self): return self._do("WARM_START") | ... | ... |
sockets_tele/src/client/socket_client_telescope_gemini.py renamed to sockets_tele/src_socket/client/socket_client_telescope_gemini.py
... | ... | @@ -9,16 +9,16 @@ To be used as a concrete class to system control a GEMINI telescope |
9 | 9 | # Standard library imports |
10 | 10 | #import socket |
11 | 11 | #import logging |
12 | -#import sys | |
12 | +import sys | |
13 | 13 | import time |
14 | 14 | |
15 | 15 | # Third party imports |
16 | 16 | # None |
17 | 17 | |
18 | 18 | # Local application imports |
19 | -#sys.path.append('../..') | |
19 | +sys.path.append('../..') | |
20 | 20 | #from src.client.socket_client_telescope_abstract import Position, UnknownCommandException, TimeoutException, SocketClientTelescopeAbstract |
21 | -from src.client.socket_client_telescope_abstract import * | |
21 | +from src_socket.client.socket_client_telescope_abstract import * | |
22 | 22 | |
23 | 23 | |
24 | 24 | # Default timeout set to 10s |
... | ... | @@ -102,9 +102,14 @@ class SocketClientTelescopeGEMINI(SocketClientTelescopeAbstract): |
102 | 102 | _cmd_do = { |
103 | 103 | #'INIT': [], |
104 | 104 | 'PARK': ['hP'], |
105 | - 'MOVE': ['MS'], | |
106 | 105 | 'WARM_START': ['bW'], |
107 | 106 | 'PREC_REFR': ['p3'], |
107 | + 'MOVE': ['MS'], | |
108 | + 'MOVE_NORTH': ['Mn'], | |
109 | + 'MOVE_SOUTH': ['Ms'], | |
110 | + 'MOVE_WEST': ['Mw'], | |
111 | + 'MOVE_EAST': ['Me'], | |
112 | + 'STOP': ['Q'], | |
108 | 113 | } |
109 | 114 | |
110 | 115 | |
... | ... | @@ -125,24 +130,30 @@ class SocketClientTelescopeGEMINI(SocketClientTelescopeAbstract): |
125 | 130 | return cmd |
126 | 131 | |
127 | 132 | |
128 | - ''' | |
129 | - Encapsulate useful data to be ready for sending | |
130 | - If data is "complete" (with stamp, and well formatted), send it as is | |
131 | - Otherwise, add stamp and format it | |
132 | - Examples: | |
133 | - '01000000:GD#' => complete, so send it as is | |
134 | - ':GD#' => add stamp in order to send '01000000:GD#' | |
135 | - 'GD' => add stamp + format in order to send '01000000:GD#' | |
136 | - ''' | |
137 | 133 | # @override |
138 | 134 | def _encapsulate_data_to_send(self, command:str): |
139 | - ####return bytes(self.MYSTAMP + self.STAMP_FILLER + data + "\n", "utf-8") | |
140 | - ''' | |
135 | + ''' Encapsulate useful data to be ready for sending | |
136 | + | |
137 | + If data is "complete" (with stamp, and well formatted), send it as is | |
138 | + Otherwise, add stamp and format it | |
139 | + | |
141 | 140 | 3 types of commands: |
142 | 141 | - TYPE1: '06' or '050000' |
143 | 142 | - TYPE2: ':cde#' (mainly ':??#' - i.e : ':GD#', ':GR#', ...) |
144 | 143 | - TYPE3: 'b?#' (bC# = Cold Start, bW# = selecting Warm Start, bR# = selecting Warm Restart) |
144 | + | |
145 | + :Examples: | |
146 | + >>> tele = SocketClientTelescopeGEMINI("localhost", 11110, DEBUG=False) | |
147 | + >>> tele._encapsulate_data_to_send(':GD#') | |
148 | + '00010000:GD#\\x00' | |
149 | + >>> tele._encapsulate_data_to_send(':GR#') | |
150 | + '00020000:GR#\\x00' | |
151 | + >>> tele.close() | |
152 | + | |
153 | + # ne marche pas => '00010000:GD#\x00' | |
145 | 154 | ''' |
155 | + | |
156 | + ####return bytes(self.MYSTAMP + self.STAMP_FILLER + data + "\n", "utf-8") | |
146 | 157 | |
147 | 158 | # TYPE1 |
148 | 159 | #print("command to encapsulate is", repr(command)) |
... | ... | @@ -168,9 +179,17 @@ class SocketClientTelescopeGEMINI(SocketClientTelescopeAbstract): |
168 | 179 | #return bytes(data + "\n", "utf-8") |
169 | 180 | ####return bytes(self.MYSTAMP + self.STAMP_FILLER + data + "\n", "utf-8") |
170 | 181 | |
171 | - # Extract useful data from received raw data | |
172 | 182 | # @override |
173 | - def _uncap_data(self, data_received_bytes:bytes): | |
183 | + def _uncap_received_data(self, data_received_bytes:bytes)->str: | |
184 | + ''' Extract useful data from received raw data | |
185 | + | |
186 | + >>> tele = SocketClientTelescopeGEMINI("localhost", 11110, DEBUG=False) | |
187 | + >>> tele.last_stamp = '00170000' | |
188 | + >>> tele._uncap_received_data(b'001700001\\x00') | |
189 | + '1' | |
190 | + >>> tele.close() | |
191 | + ''' | |
192 | + | |
174 | 193 | #print("data_received_bytes type is", type(data_received_bytes)) |
175 | 194 | #print("data received is", data_received_bytes) |
176 | 195 | |
... | ... | @@ -192,6 +211,7 @@ class SocketClientTelescopeGEMINI(SocketClientTelescopeAbstract): |
192 | 211 | |
193 | 212 | # @override |
194 | 213 | def do_INIT(self): |
214 | + | |
195 | 215 | ''' |
196 | 216 | 1) Send cde ACK ('06') and check answer to see if telescope is ready (see doc page 100) |
197 | 217 | (utile pour savoir si tout est ok ; par ex, si une raquette est branchée sur le tele, ça peut bloquer le protocole) |
... | ... | @@ -354,6 +374,33 @@ class SocketClientTelescopeGEMINI(SocketClientTelescopeAbstract): |
354 | 374 | ''' |
355 | 375 | self.do_PREC_REFR() |
356 | 376 | |
377 | + | |
378 | + def set_SPEED(self, speed_rate): | |
379 | + native_cmd = None | |
380 | + # quick | |
381 | + if speed_rate == "slew": native_cmd = 'RS' | |
382 | + # average | |
383 | + if speed_rate == "average": native_cmd = 'RM' | |
384 | + # slow | |
385 | + if speed_rate == "center": native_cmd = 'RC' | |
386 | + # very slow | |
387 | + if speed_rate == "guide": native_cmd = 'RG' | |
388 | + if not native_cmd: raise UnknownCommandException(speed_rate) | |
389 | + return self.execute_unformated_native_cmd(native_cmd) | |
390 | + | |
391 | + def do_MOVE_NORTH(self): return self.execute_unformated_native_cmd('Mn') | |
392 | + def do_MOVE_SOUTH(self): return self.execute_unformated_native_cmd('Ms') | |
393 | + def do_MOVE_WEST(self): return self.execute_unformated_native_cmd('Mw') | |
394 | + def do_MOVE_EAST(self): return self.execute_unformated_native_cmd('Me') | |
395 | + | |
396 | + def do_MOVE_DIR(self, dir, nbsec, speed_rate=None): | |
397 | + if speed_rate: self.set_SPEED(speed_rate) | |
398 | + if dir=="NORTH": self.do_MOVE_NORTH() | |
399 | + if dir=="SOUTH": self.do_MOVE_SOUTH() | |
400 | + if dir=="WEST": self.do_MOVE_WEST() | |
401 | + if dir=="EAST": self.do_MOVE_EAST() | |
402 | + time.sleep(int(nbsec)) | |
403 | + self.do_STOP() | |
357 | 404 | |
358 | 405 | ''' GOTO (p105) |
359 | 406 | - GOTO(position, blocking=Y/N): |
... | ... | @@ -540,18 +587,22 @@ class SocketClientTelescopeGEMINI(SocketClientTelescopeAbstract): |
540 | 587 | |
541 | 588 | if __name__ == "__main__": |
542 | 589 | |
590 | + import doctest | |
591 | + doctest.testmod() | |
592 | + exit() | |
593 | + | |
543 | 594 | # Classic usage: |
544 | - #tsock = SocketClient_GEMINI(HOST, PORT) | |
595 | + #tele_client = SocketClient_GEMINI(HOST, PORT) | |
545 | 596 | # More elegant usage, using "with": |
546 | - with SocketClientTelescopeGEMINI("localhost", 11110, DEBUG=False) as tsock: | |
597 | + with SocketClientTelescopeGEMINI("localhost", 11110, DEBUG=False) as tele_client: | |
547 | 598 | |
548 | 599 | # 0) CONNECT to server (only for TCP, does nothing for UDP) |
549 | - tsock._connect_to_server() | |
600 | + tele_client._connect_to_server() | |
550 | 601 | |
551 | - #tsock.config() | |
602 | + #tele_client.config() | |
552 | 603 | |
553 | 604 | # Send some commands to the Telescope |
554 | - #pos = tsock.get_position() | |
605 | + #pos = tele_client.get_position() | |
555 | 606 | |
556 | 607 | # Do EXPERT mode execution |
557 | 608 | while True: |
... | ... | @@ -562,16 +613,16 @@ if __name__ == "__main__": |
562 | 613 | # test d'arrêt |
563 | 614 | if data == "": break |
564 | 615 | #data_to_send = bytes(data + "\n", "utf-8") |
565 | - tsock.send_data(data) | |
616 | + tele_client.send_data(data) | |
566 | 617 | #mysock.sendto("%s" % data, (HOST, PORT)) |
567 | 618 | #print("Sent: {}".format(data)) |
568 | 619 | |
569 | 620 | # 2) RECEIVE REPLY data from server |
570 | - data_received = tsock.receive_data() | |
621 | + data_received = tele_client.receive_data() | |
571 | 622 | #reponse, adr = mysock.recvfrom(buf) |
572 | 623 | #print("Received: {}".format(data_received)) |
573 | 624 | #print("Useful data received: {}".format(data_useful)) |
574 | 625 | print('\n') |
575 | 626 | |
576 | - #tsock.close() | |
627 | + #tele_client.close() | |
577 | 628 | ... | ... |
sockets_tele/src/server/__init__.py renamed to sockets_tele/src_socket/server/__init__.py
sockets_tele/src/server/server_udp_or_tcp.py renamed to sockets_tele/src_socket/server/server_udp_or_tcp.py
sockets_tele/test/test_client_gemini.py
... | ... | @@ -39,26 +39,26 @@ class TestClient(unittest.TestCase): |
39 | 39 | #time.sleep(3) |
40 | 40 | |
41 | 41 | # RUN CLIENT to connect to server |
42 | - #tsock = SocketClient_UDP_TCP(HOST, PORT, "UDP") | |
43 | - with SocketClientTelescopeGEMINI(HOST, PORT) as tsock: | |
42 | + #tele_client = SocketClient_UDP_TCP(HOST, PORT, "UDP") | |
43 | + with SocketClientTelescopeGEMINI(HOST, PORT) as tele_client: | |
44 | 44 | # Only useful for TCP (does nothing for UDP) |
45 | - tsock._connect_to_server() | |
45 | + tele_client._connect_to_server() | |
46 | 46 | |
47 | 47 | # 1) SEND REQUEST data to server |
48 | 48 | |
49 | 49 | for data in q_a: |
50 | 50 | question,answer = data |
51 | - tsock.send_data(question) | |
51 | + tele_client.send_data(question) | |
52 | 52 | |
53 | 53 | # 2) RECEIVE REPLY data from server |
54 | - data_received = tsock.receive_data() | |
54 | + data_received = tele_client.receive_data() | |
55 | 55 | self.assertEqual(data_received, answer) |
56 | 56 | |
57 | - radec = tsock.get("RA-DEC") | |
57 | + radec = tele_client.get("RA-DEC") | |
58 | 58 | print("ra-dec is", radec) |
59 | 59 | self.assertEqual(radec, ['15:01:48', '+12:28']) |
60 | 60 | |
61 | - #tsock.close() | |
61 | + #tele_client.close() | |
62 | 62 | |
63 | 63 | #TODO: Stop the server thread (t_server), how can we do that ? |
64 | 64 | # cf https://www.oreilly.com/library/view/python-cookbook-2nd/0596007973/ch09s03.html | ... | ... |