Blame view

sockets_tele/src/client/socket_client_telescope_gemini.py 7.43 KB
fc6ea9bc   Etienne Pallier   socket client pou...
1
2
#!/usr/bin/env python3

c252db76   Etienne Pallier   Test maintenant s...
3
"""Socket Client GEMINI Telescope implementation
fc6ea9bc   Etienne Pallier   socket client pou...
4

c252db76   Etienne Pallier   Test maintenant s...
5
6
7
8
9
10
11
12
13
14
15
16
17
To be used as a concrete class to system control a GEMINI telescope
"""


# Standard library imports
#import socket
#import logging
#import sys

# Third party imports
# None

# Local application imports
ca2504aa   Etienne Pallier   Nouvelle version ...
18
19
#sys.path.append('../..')
from src.client.socket_client_telescope_abstract import Position, UnknownCommandException, SocketClientTelescopeAbstract
fc6ea9bc   Etienne Pallier   socket client pou...
20

fc6ea9bc   Etienne Pallier   socket client pou...
21

c252db76   Etienne Pallier   Test maintenant s...
22
23
24
25

TERMINATOR = '\x00'


ca2504aa   Etienne Pallier   Nouvelle version ...
26
class SocketClientTelescopeGEMINI(SocketClientTelescopeAbstract):
fc6ea9bc   Etienne Pallier   socket client pou...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    
    '''
    http://82.64.28.71:8083/L5V1serial.html
    
    ACK = 0x06
    => 06 00 (le 00 à la fin signifie que la commande s’est bien passée)
    Réponse:
    - B#
    - b#
    - G#
    
    Ce qui marche:
    
    - REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: 01000000:GD#
    Received (all data): 01000000+90:00:00#
    
    - REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: 01000000:GR#
    Received (all data): 0100000015:01:48#
    - REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: 01000000:GR#
    Received (all data): 0100000016:04:17#
    
    - Get Software Level l(one digit) and Version vv(two digits)
    REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: 01000000:GV#
    Received (all data): 01000000510#
    
    - REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: 01000000:GG#
    Received (all data): 01000000+00#
    
    - Get Maximum Velocity of both axes (N = No mvmt)
    REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: 01000000:Gv#
    Received (all data): 01000000N

    '''

    # 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' 
ca2504aa   Etienne Pallier   Nouvelle version ...
65
66
67
68
69
70
71
72
73
74
    #MY_FULL_STAMP = MYSTAMP + STAMP_FILLER

    # Initialize request number (will be increased at each request)
    request_num = 0
    # Request number stands on 4 digits (from 0001 to 9999)
    request_num_nb_digits = 4
    # For 4 digits, we should get the format '{:04d}':
    request_num_format = '{:0'+str(request_num_nb_digits)+'d}'
    # Stamp filler with 0
    STAMP_FILLER = '0' * (8 - request_num_nb_digits)
fc6ea9bc   Etienne Pallier   socket client pou...
75
76
77
78
79
80
    
    #data = " ".join(sys.argv[1:])
    #data_to_send = bytes(data + "\n", "utf-8")

    # @override
    # GEMINI is using UDP
ca2504aa   Etienne Pallier   Nouvelle version ...
81
82
83
    def __init__(self, server_host:str="localhost", server_port:int=11110, DEBUG=False):
        super().__init__(server_host, server_port, "UDP", 1024, DEBUG)

fc6ea9bc   Etienne Pallier   socket client pou...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
        
        
    '''
    Encapsulate useful data to be ready for sending
    If data is "complete" (with stamp, and well formatted), send it as is
    Otherwise, add stamp and format it
    Examples:
    '01000000:GD#' => complete, so send it as is
    ':GD#' => add stamp in order to send '01000000:GD#'
    'GD' => add stamp + format in order to send '01000000:GD#'
    '''
    # @override
    def _encapsulate_data_to_send(self, data:str):
        ####return bytes(self.MYSTAMP + self.STAMP_FILLER + data + "\n", "utf-8")
de0a0210   Etienne Pallier   modifs
98
        '''
fc6ea9bc   Etienne Pallier   socket client pou...
99
        sep_pos = data.find(':')
de0a0210   Etienne Pallier   modifs
100
        # no ":"
fc6ea9bc   Etienne Pallier   socket client pou...
101
102
103
104
105
        if sep_pos == -1:
            stamp = ''
            command = data
        else:
        # has ":"
b6165668   Etienne Pallier   bugfix
106
            stamp,command = data.split(':',1)
fc6ea9bc   Etienne Pallier   socket client pou...
107
        if stamp == '': stamp = self.MY_FULL_STAMP
de0a0210   Etienne Pallier   modifs
108
109
110
111
112
        #if command.find('#')>-1: command,_ = command.split('#',1)
        #command = ':' + command + '#'
        #command = command + '#'
        '''
        command = data
ca2504aa   Etienne Pallier   Nouvelle version ...
113
114
115
116
117
        self.request_num += 1
        # Format to request_num_nb_digits (4) digits
        request_num_str = self.request_num_format.format(self.request_num)
        self.last_stamp = request_num_str + self.STAMP_FILLER 
        return self.last_stamp + command
fc6ea9bc   Etienne Pallier   socket client pou...
118
119
120
121
122
123
124
        #return bytes(data + "\n", "utf-8")
        ####return bytes(self.MYSTAMP + self.STAMP_FILLER + data + "\n", "utf-8")

    # Extract useful data from received raw data    
    # @override
    def _uncap_data(self, data_received:str):
        # Remove STAMP (and \n at the end):
ca2504aa   Etienne Pallier   Nouvelle version ...
125
126
        #useful_data = data_received.split(self.MY_FULL_STAMP)[1][:-1]
        useful_data = data_received.split(self.last_stamp)[1][:-1]
fc6ea9bc   Etienne Pallier   socket client pou...
127
128
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
        # Remove '#' at the end, if exists
        if useful_data[-1] == '#': useful_data = useful_data[:-1]
        return useful_data


    '''
    TELESCOPE COMMANDS implementation
    '''
       
    ''' 
    The 3 main generic commands : get(), set(), do()
    '''

    ''' 1) GET methods '''
    # @override
    def get(self, what:str):
        cmd = None
        
        if what == "ALT": cmd = ('GA',)
        if what == "AZ": cmd = ('GZ',)
        if what == "ALT-AZ": cmd = ('GA','GZ')
        
        if what == "DEC": cmd = ('GD',)
        if what == "RA": cmd = ('GR',)
        if what == "RA-DEC": cmd = ('GR','GD')

        if what == "LONG": cmd = ('Gg',)
        if what == "LAT": cmd = ('Gt',)
        if what == "LONG-LAT": cmd = ('Gg','Gt')
        
        if what == "hour-angle": cmd = ('GH',)

        if what == "max-vel": cmd = ('Gv',)

        if not cmd: raise UnknownCommandException()
                
        res = []
        for c in cmd:
de0a0210   Etienne Pallier   modifs
165
            res.append(self.put_read(':'+c+'#'))
fc6ea9bc   Etienne Pallier   socket client pou...
166
167
168
        if len(res) == 1: return res[0]
        return res

ca2504aa   Etienne Pallier   Nouvelle version ...
169
170
171


    ''' 2) SET methods '''
fc6ea9bc   Etienne Pallier   socket client pou...
172
    # @override
ca2504aa   Etienne Pallier   Nouvelle version ...
173
    def set(self):
fc6ea9bc   Etienne Pallier   socket client pou...
174
175
        pass

ca2504aa   Etienne Pallier   Nouvelle version ...
176
177

    ''' 3) DO methods '''
fc6ea9bc   Etienne Pallier   socket client pou...
178
    # @override
ca2504aa   Etienne Pallier   Nouvelle version ...
179
    def do(self):
fc6ea9bc   Etienne Pallier   socket client pou...
180
181
182
        pass


ca2504aa   Etienne Pallier   Nouvelle version ...
183
184
185
186
187



    ''' SPECIFIC methods

fc6ea9bc   Etienne Pallier   socket client pou...
188
    # @override
ca2504aa   Etienne Pallier   Nouvelle version ...
189
    def get_coord_sys(self):
fc6ea9bc   Etienne Pallier   socket client pou...
190
        pass
ca2504aa   Etienne Pallier   Nouvelle version ...
191

fc6ea9bc   Etienne Pallier   socket client pou...
192
    # @override
ca2504aa   Etienne Pallier   Nouvelle version ...
193
    def get_position(self)->Position: 
fc6ea9bc   Etienne Pallier   socket client pou...
194
195
        pass

fc6ea9bc   Etienne Pallier   socket client pou...
196
    # @override
ca2504aa   Etienne Pallier   Nouvelle version ...
197
    def set_coord_sys(self):
fc6ea9bc   Etienne Pallier   socket client pou...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
        pass

    # @override
    def start(self):
        pass

    # @override
    def park(self):
        pass

    # @override
    def goto(self, position:Position):
        pass

    # Move to Home Position. The Home Position defaults to the celestial pole visible at the given hemisphere (north or south)
    # :hP#
    # Move to the Startup Position. This position is the position required for a Cold or Warm Start, pointing to the celestial pole of the given hemisphere (north or south), with the counterweight pointing downwards (CWD position)
    # :hC# 
    # @override
    def move(self, position:Position):
        pass
ca2504aa   Etienne Pallier   Nouvelle version ...
219
    '''
fc6ea9bc   Etienne Pallier   socket client pou...
220
221
222
223
224
225
226
227
228
229
230
231
232

    
    
    




if __name__ == "__main__":
    
    # Classic usage:
    #tsock = SocketClient_GEMINI(HOST, PORT)
    # More elegant usage, using "with":
ca2504aa   Etienne Pallier   Nouvelle version ...
233
    with SocketClientTelescopeGEMINI("localhost", 11110, DEBUG=False) as tsock:
fc6ea9bc   Etienne Pallier   socket client pou...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
        
        # 0) CONNECT to server (only for TCP, does nothing for UDP)
        tsock._connect_to_server()
        
        # Send some commands to the Telescope
        pos = tsock.get_position()
        
        # Do EXPERT mode execution
        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("(EXPERT MODE) REQUEST TO SERVER [ex: ':GD#' (Get Dec), ':GR#' (Get RA)']: ").strip()
            # test d'arrêt
ca2504aa   Etienne Pallier   Nouvelle version ...
248
            if data == "": break
fc6ea9bc   Etienne Pallier   socket client pou...
249
250
251
252
253
254
255
256
257
258
259
260
261
            #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()