#!/usr/bin/env python3 """Socket Client GEMINI Telescope implementation 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 #sys.path.append('../..') from src.client.socket_client_telescope_abstract import Position, UnknownCommandException, SocketClientTelescopeAbstract TERMINATOR = '\x00' class SocketClientTelescopeGEMINI(SocketClientTelescopeAbstract): ''' 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' #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) #data = " ".join(sys.argv[1:]) #data_to_send = bytes(data + "\n", "utf-8") # @override # GEMINI is using UDP def __init__(self, server_host:str="localhost", server_port:int=11110, DEBUG=False): super().__init__(server_host, server_port, "UDP", 1024, DEBUG) ''' 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") ''' sep_pos = data.find(':') # no ":" if sep_pos == -1: stamp = '' command = data else: # has ":" stamp,command = data.split(':',1) if stamp == '': stamp = self.MY_FULL_STAMP #if command.find('#')>-1: command,_ = command.split('#',1) #command = ':' + command + '#' #command = command + '#' ''' command = data 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 #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): #useful_data = data_received.split(self.MY_FULL_STAMP)[1][:-1] useful_data = data_received.split(self.last_stamp)[1][:-1] # 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: res.append(self.put_read(':'+c+'#')) if len(res) == 1: return res[0] return res ''' 2) SET methods ''' # @override def set(self): pass ''' 3) DO methods ''' # @override def do(self): pass ''' SPECIFIC methods # @override def get_coord_sys(self): pass # @override def get_position(self)->Position: pass # @override def set_coord_sys(self): 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 ''' if __name__ == "__main__": # Classic usage: #tsock = SocketClient_GEMINI(HOST, PORT) # More elegant usage, using "with": with SocketClientTelescopeGEMINI("localhost", 11110, DEBUG=False) as tsock: # 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 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()