class Websocket_Server(): def __init__(self, host, port): self.client_id_username_map = {} self.server = WebsocketServer(port, host = host, loglevel = logging.DEBUG) def new_client(self, client, server): print("new client connected and was given id {}".format(client['id'])) self.server.send_message(client,"make connection : success!!") def client_left(self, client, server): print("client({}) disconnected".format(client['id'])) def message_received(self, client, server, message): if message.startswith("init:username:"******"init:username:"******"") print(username) self.client_id_username_map[client["id"]] = username self.server.send_message_to_all(message) else: self.server.send_message_to_all(message) def run(self): self.server.set_fn_new_client(self.new_client) self.server.set_fn_client_left(self.client_left) self.server.set_fn_message_received(self.message_received) self.server.run_forever()
class RpiServerWS(): """docstring for WebsocketServer""" server = None def __init__(self, parent): self.parent = parent self.server = WebsocketServer(8050, host=hosthome, loglevel=logging.INFO) self.server.set_fn_new_client(self.new_client) self.server.set_fn_message_received(self.message_received) self.server.set_fn_client_left(self.client_left) print('Websocket Server started, waiting for clients to connect') self.server.run_forever() def new_client(self, client, server): #print('Connected by ', client) self.parent.clientSockets.append(client) greeting = '{"functionName":"connected", "args":{} }' self.server.send_message(client, greeting) def message_received(self, client, server, message): item = (message, self.server, client) #print('putting ', item, 'in the queue') self.parent.callbackQueue.put(item) #self.server.send_message(client, 'WS: Message put in queue') def client_left(self, client, server): self.parent.clientSockets.remove(client)
class Environment: """Clase de ambiente""" actions = {Action.HIT: 'HIT', Action.STAND: 'STAND'} duration = 0.01 def __init__(self, host, port): print("host:" + host + " port:" + str(port)) self.queue = multiprocessing.Queue() self.server = WebsocketServer(port, host=host) self.server.set_fn_new_client(self.new_client) self.server.set_fn_message_received(self.new_message) self.game_client = None thread = threading.Thread(target=self.server.run_forever) thread.daemon = True thread.start() def new_client(self, client, server): self.game_client = client self.server.send_message(self.game_client, "Connected! :)") def new_message(self, client, server, message): #Por lo general se envia la accion que se quiera tomar data = json.loads(message) state, score, finished = data['state'], data['reward'], data[ 'finished'] # print(state, score, finished) self.queue.put((state, score, finished)) def start_game(self): # game can not be started as long as the browser is not ready while self.game_client is None: time.sleep(self.duration) #Empezar el juego! self.server.send_message(self.game_client, "START") time.sleep(self.duration) return self.get_state() def refresh_game(self): #Empezar el juego! print("Refreshing") self.server.send_message(self.game_client, "START") time.sleep(self.duration) def do_action(self, action): print(self.actions[action]) self.server.send_message(self.game_client, self.actions[action]) time.sleep(self.duration) return self.get_state() def get_state(self): self.server.send_message(self.game_client, "STATE") time.sleep(self.duration) state, score, finished = self.queue.get() print("Actual hand(state):", state, "Score:", score, "Finished:", finished) return state, score, finished
def on_export_data(self, client, server: WebsocketServer, file_name: str, json_data: str): excel_data = self.converter.json_to_excel(json_data) ext = file_name.split('.')[1] excel: Any if ext == 'xls': excel = excel_data.xls if ext == 'xlsx': excel = excel_data.xlsx try: open('output/%s' % file_name, 'wb').write(excel) server.send_message(client, 'res|info|io') except: print('Error occured while trying to write file.') server.send_message(client, 'res|error|io')
def message_received(client, server, message): if len(message) > 200: message = message[:200]+'..' print("Client(%d) said: %s" % (client['id'], message)) try: msg = json.loads(message) if msg['type'] == "GET": response = json.dumps({"port":1081}) WebsocketServer.send_message(server, client, response) print('config sent') if msg['type'] == "SET": config = msg["conf"] print(config) print('config updated!') except Exception as e: pass
class Server(object): def __init__(self, ip, port): self.__ip = ip self.__port = port self.__server = None def __new_client(self, client, server): logging.info(client) logging.info(server.clients) def __client_left(self, client, server): logging.info(client) logging.info(server.clients) def __recv_ping(self, client, data=''): self.__send_msg_client(client, str({'timestamp' : int(1000 * time.time())})) def __message_received(self, client, server, message): if not message: self.__recv_ping(client, message) logging.info(client) logging.info(message) self.__send_msg(message) def __run(self): try: self.__server = WebsocketServer(self.__ip, self.__port) self.__server.set_fn_new_client(self.__new_client) self.__server.set_fn_client_left(self.__client_left) self.__server.set_fn_message_received(self.__message_received) self.__server.run_forever() except Exception as e: logging.exception(e) self.__server = None def __send_msg_client(self, client, message): if self.__server: self.__server.send_message(client, message) def __send_msg(self, message): if self.__server: self.__server.send_message_to_all(message) def start(self): #while True: self.__run()
class ParentMain(Parent): def new_client(self, client, server): values["clients"] = server.clients def client_left(self, client, server): values["clients"] = server.clients def message_received(self, client, server, message): values["messages"].append({client["id"]: message}) values["newest"][client["id"]] = message def __init__(self, config: dict): super().__init__(config) __port = config['port'] self.__server = WebsocketServer(port=__port, host='0.0.0.0') self.__server.set_fn_new_client(self.new_client) self.__server.set_fn_client_left(self.client_left) self.__server.set_fn_message_received(self.message_received) th = threading.Thread(target=self.__server.run_forever) th.setDaemon(True) th.start() def read(self, params): super().read(params) __tag = params["tag"] if __tag in values: return values[__tag] else: return None def write(self, value, params): super().write(value, params) __tag = params["tag"] __client = params["client"] if __tag == "send_to_client": if "client" in params: __client = params["client"] self.__server.send_message(__client, value) elif __tag == "send_to_all": self.__server.send_message_to_all(value) def __del__(self): super().__del__() del self.__server
class IPCWebSocket(object): def __init__(self, ipc): self.ipc = ipc self.server = WebsocketServer(9000) self._set_callbacks(self.server) self.clients = [] def start(self): from threading import Thread def run(): self.server.run_forever() t = Thread(target=run) t.daemon = True t.start() def _set_callbacks(self, server): server.set_fn_new_client(self.on_connect) server.set_fn_client_left(self.on_disconnect) server.set_fn_message_received(self.on_message) def on_connect(self, client, server): print("New client connected") self.clients.append(client) def on_disconnect(self, client, server): print("Client disconnected") self.clients = [c for c in self.clients if c['id'] != client['id']] def on_message(self, client, server, message): message = json.loads(message) self.ipc.on_message(client, message) def broadcast(self, message): message = json.dumps(message) for c in self.clients: self.server.send_message(c, message) print("broadcasted message to {} clients".format(len(self.clients))) def send(self, client, message): self.server.send_message(client, json.dumps(message))
class IPCWebSocket(object): def __init__(self, ipc, port): self.ipc = ipc self.server = WebsocketServer(port) self._set_callbacks(self.server) self.clients = [] def start(self): from threading import Thread def run(): self.server.run_forever() t = Thread(target=run) t.daemon = True t.start() def _set_callbacks(self, server): server.set_fn_new_client(self.on_connect) server.set_fn_client_left(self.on_disconnect) server.set_fn_message_received(self.on_message) def on_connect(self, client, server): self.clients.append(client) def on_disconnect(self, client, server): self.clients = [c for c in self.clients if c['id'] != client['id']] def on_message(self, client, server, message): message = json.loads(message) self.ipc.on_message(client, message) def broadcast(self, message): message = json.dumps(message) for c in self.clients: self.server.send_message(c, message) def send(self, client, message): self.server.send_message(client, json.dumps(message))
class OrderingHub(): def __init__(self, host='localhost', port=7777, isdebug=True): self.server = WebsocketServer(port, host) self.server.set_fn_new_client(self.new_client) self.server.set_fn_client_left(self.client_left) self.clients = {} self.clientId = 0 self.orderId = 0; return def run(self): self.server.run_forever() return def set_callback(self, callback): # self.server.set_fn_message_received(lambda client, server,message: callback(json.loads(message), self.send_all)) self.server.set_fn_message_received(lambda client, server,message: callback(self, json.loads(message), self.send_all)) return def send_all(self, message): for c in self.clients.values(): self.server.send_message(c, json.dumps(message)) return def new_client(self, client, server): print('hello clinet') client['id'] = self.clientId self.clients[self.clientId] = client print('add client(id={})'.format(self.clientId)) self.clientId = self.clientId+1 return def client_left(self, client, server): print('closing clientid={}'.format(client['id'])) del self.clients[client['id']] return
def on_get_version(self, client, server: WebsocketServer): version = self.database.get_version() server.send_message(client, 'res|version|%s' % version[0])
class WebSocket(Agent): autostart = True def __init__(self): super(WebSocket, self).__init__() self.target = self.identifier self.server = WebsocketServer(5601, "0.0.0.0") self.wsThread = threading.Thread(target=self.server.run_forever) self.clients = self.server.clients self.subscriptions = [] @self.server.set_fn_new_client def new_client(client, server): client["subscriptions"] = [] @self.server.set_fn_client_left def client_left(client, server): logging.info("Client(%d) disconnected" % client['id']) @self.server.set_fn_message_received def message_received(client, server, msg): if msg: try: event = json.loads(msg) event_type = event["type"] event_data = event["data"] if event_type == "subscribe": self._subscribe(client, event_data) elif event_type == "unsubscribe": self._unsubscribe(client, msg) else: Dispatcher().put_event(Event(type=event_type, data=event_data)) except json.decoder.JSONDecodeError as e: pass def run(self): self.wsThread.start() self._listener() def _listener(self): while self.wsThread.isAlive(): event = self.next_event() event_type = event["type"] event_data = event["data"] for client in self.clients: if event_type in client["subscriptions"]: self.server.send_message(client, json.dumps(event)) def _subscribe(self, client, event_data): client["subscriptions"].append(str(event_data)) if not str(event_data) in self.subscriptions: self.subscriptions.append(str(event_data)) Dispatcher().bind(self, event_data) logging.info("Client subscribed to " + event_data) def _unsubscribe(self, client, event_data): if str(event_data) in client["subscriptions"]: client["subscriptions"].remove(event_data) othersubscriber = False for otherclient in self.clients: if str(event_data) in otherclient["subscriptions"]: othersubscriber = True if not othersubscriber: self.subscriptions.remove(str(event_data)) logging.info("Client unsubscribed from " + event_data) else: # Client wasn't found in subscribers list pass
class SerialServer(object): ''' 串口硬件 ==> 串口服务器(ws server) ==> 电脑浏览器(ws client) 电脑浏览器(ws client) ==> 串口服务器(ws server) ==> 串口硬件 ''' def __init__(self, websocket_server_port): super(SerialServer, self).__init__() self.ser = Serial() self.ws_client = None self.ws = WebsocketServer(port=websocket_server_port) self.ws.set_fn_new_client( lambda client, server: self.ws_new_client(client)) self.ws.set_fn_message_received( lambda client, server, message: self.ws_message_received(message)) threading.Thread(target=self.ws.run_forever).start() threading.Thread(target=self.ser_receive).start() def ws_new_client(self, client): self.ws_client = client def ws_message_received(self, message): msg = json.loads(message) if 'cmd' in msg: if msg['cmd'] == 'open serial': print(msg['port']) print(msg['baud']) if not self.ser.is_open: try: self.ser.port = msg['port'] self.ser.baudrate = msg['baud'] self.ser.open() except Exception as e: print(e) self.ws.send_message( self.ws_client, json.dumps({'cmd': 'serial closed'})) else: self.ws.send_message( self.ws_client, json.dumps({'cmd': 'serial opened'})) elif msg['cmd'] == 'close serial': print('close') if self.ser.is_open: self.ser.close() self.ws.send_message(self.ws_client, json.dumps({'cmd': 'serial closed'})) elif 'data' in msg: print(msg['data']) if self.ser.is_open: self.ser.write(msg['data'].encode()) def ser_receive(self): while True: if self.ser.is_open: num = self.ser.in_waiting if num > 0: bytes = self.ser.read(num) print(bytes) if self.ws_client: self.ws.send_message( self.ws_client, json.dumps({'data': bytes.decode()})) time.sleep(0.1)
class SyncPlayerServer(): clients = {} log = [] player_filenum = '1' player_time = 0.0 player_start_time = 0.0 player_is_playing = False def __init__(self, host, port): self.server = WebsocketServer(port, host=host, loglevel=logging.DEBUG) # on new client def new_client(self, client, server): self.clients[client['id']] = { 'name': 'id' + str(client['id']), 'is_ready': False } self.send_client_list() self.send_text('[SERVER]', self.clients[client['id']]['name'] + 'が参加しました') obj = { \ 'message_kind': 'player_load', \ 'filenum': self.player_filenum} self.server.send_message(client, json.dumps(obj)) # on client left def client_left(self, client, server): print("client({}) disconnected".format(client['id'])) self.server.clients.remove(client) if (len(self.server.clients) > 0): self.send_client_list() self.send_text('[SERVER]', self.clients[client['id']]['name'] + 'が退出しました') self.clients.pop(client['id']) # on message received def message_received(self, client, server, message_raw): print("client({}) said: {}".format(client['id'], message_raw)) message = json.loads(message_raw) # クライアントの名前を設定する if message['message_kind'] in 'set_name': self.send_text( '[SERVER]', '名前変更 ' + self.clients[client['id']]['name'] + ' → ' + message['name']) self.clients[client['id']]['name'] = message['name'] self.send_client_list() elif message['message_kind'] in 'text': self.send_text(self.clients[client['id']]['name'], message['content']) # ファイルを読み込む elif message['message_kind'] in 'player_load': self.player_filenum = message['filenum'] self.player_time = 0.0 self.player_start_time = 0.0 self.player_is_playing = False obj = { \ 'message_kind': 'player_load', \ 'filenum': self.player_filenum} self.send_message_exclude_a_client(client, json.dumps(obj)) self.send_text( '[SERVER]', self.clients[client['id']]['name'] + 'が' + self.player_filenum + 'をロードしました') for key in self.clients: self.clients[key]['is_ready'] = False self.send_client_list() # 再生したりポーズしたり elif message['message_kind'] in 'player_play_pause': self.player_time = message['time'] self.player_start_time = time.time() self.player_is_playing = message['is_playing'] obj = { \ 'message_kind': 'player_play_pause', \ 'time': self.player_time,\ 'is_playing': self.player_is_playing} self.send_message_exclude_a_client(client, json.dumps(obj)) if self.player_is_playing: self.send_text('[SERVER]', self.clients[client['id']]['name'] + 'によって再生') else: self.send_text('[SERVER]', self.clients[client['id']]['name'] + 'によって一時停止') # 時間を取得(遅れて来た人向け) # elif message['message_kind'] in 'get_player_time' : # if self.player_is_playing: # diff = time.time() - self.player_start_time # ptime = self.player_time + diff # else: # ptime = self.player_time # # obj = { \ # 'message_kind': 'player_time', \ # 'time': ptime, \ # 'is_playing': self.player_is_playing} # self.server.send_message(client,json.dumps(obj)) # 準備完了 elif message['message_kind'] in 'set_ready': self.clients[client['id']]['is_ready'] = message['is_ready'] if self.player_is_playing: diff = time.time() - self.player_start_time ptime = self.player_time + diff else: ptime = self.player_time obj = { \ 'message_kind': 'player_play_pause', \ 'time': ptime, \ 'is_playing': self.player_is_playing} self.server.send_message(client, json.dumps(obj)) # obj = { \ # 'message_kind': 'set_ready', \ # 'id' : client['id'],\ # 'is_ready': self.clients[client['id']]['is_ready']} # self.server.send_message_to_all(json.dumps(obj)) self.send_client_list() # クライアント一覧を送信 def send_client_list(self): self.server.send_message_to_all( json.dumps({ 'message_kind': 'clients_list', 'clients': self.clients })) # テキストメッセージを送信すると同時にログに貯める def send_text(self, name, content): obj = { \ 'message_kind': 'text', \ 'name': name, \ 'content': content} self.server.send_message_to_all(json.dumps(obj)) self.log.append(obj) # あるクライアント以外に送信 def send_message_exclude_a_client(self, client, message): for item in self.server.clients: if item == client: continue self.server.send_message(item, message) # run server def run(self): self.server.set_fn_new_client(self.new_client) self.server.set_fn_client_left(self.client_left) self.server.set_fn_message_received(self.message_received) self.server.run_forever()
class WebSocketServer: def __init__(self): self.server = WebsocketServer(8082, host='0.0.0.0') self.server.set_fn_new_client(self.onClient) self.server.set_fn_message_received(self.onMessage) self.openCvService = OpenCvService() def onClient(self, client, server): print("new client", client) def onMessage(self, client, server, message): print("new message", message) messageParsed = json.loads(message) command = messageParsed['command'] args = messageParsed['args'] if command == "ping": print('PONG!') if command == "photo": print('TAKE PHOTO') self.send(client, "PIC#" + self.openCvService.takePicture()) if command == "begin_calibration": # will clean the calib_tmp folder self.openCvService.beginCalibration(self, client) if command == "calibration_snapshot": self.openCvService.calibrationSnapshot(self, client, args['calibrationId']) if command == "calibration_process": self.openCvService.processCalibrationData(self, client, args['calibrationId']) if command == "calibration_fetch_saves": self.openCvService.fetchSaves(self, client) if command == "calibration_fetch_save": self.openCvService.fetchSave(self, client, args['calibrationId']) if command == "enable_markers": # enable marker for this specific client self.openCvService.enableMarkers() if command == "disable_markers": # enable marker for this specific client self.openCvService.disableMarkers() if command == "enable_position": # enable marker for this specific client self.openCvService.enablePosition() if command == "disable_position": # enable marker for this specific client self.openCvService.disablePosition() if command == "live": # create a new thread self.openCvService.startLiveVideo(self, client) if command == "stop_live": self.stopClientLiveThread(client) # if command == "calibration_get_input_data": # with open(args['path'], "rb") as imageFile: # sent = "data:image/jpeg;base64," + base64.b64encode(imageFile.read()).decode("utf-8") # self.send(client, "calibrationData", sent) if command == "calibration_delete_input_data": frameId = str(int(args['calibrationFrameId'])) calibrationId = args['calibrationId'] if not re.compile('^[a-z0-9\-]+$').match(calibrationId): print('ERR: Calibration id not match') return self.openCvService.deleteInputData(calibrationId, frameId) def send(self, client, responseType, data = None): if not client['handler'].keep_alive: return False toSend = json.dumps({'responseType': responseType, 'data': data}) # if responseType != 'frame': # print(toSend) self.server.send_message(client, toSend) return True def start(self): self.server.run_forever()
class WebSocket: def __init__(self): self.server = None self.rooms = None self.clientSelectedRoom = dict() self.debugMode = False # Called for every client connecting (after handshake) def new_client(self,client, server): print("New client connected and was given id %d" % client['id']) self.clientSelectedRoom[client['id']]=-1 if self.rooms == None or len(self.rooms) == 0: server.send_message(client,"0") else: messageStr = self.getRoomInfo(self.rooms) server.send_message(client,"R:"+messageStr) # Called for every client disconnecting def client_left(self,client, server): # print("Client(%d) disconnected" % client['id']) self.clientSelectedRoom.pop(client['id']) print("Client disconnected") pass # Called when a client sends a message def message_received(self,client, server, message): if len(message) > 200: message = message[:200]+'..' print("Client(%d) said: %s" % (client['id'], message)) if message == "debug": self.debugMode = True elif message == "normal": self.debugMode = False else: roomIndex=int(message) self.clientSelectedRoom[client['id']]=roomIndex if roomIndex < len(self.rooms): room = self.rooms[roomIndex] messageStr = self.getUpdateInfo(self.rooms[roomIndex]) server.send_message(client,messageStr) def start(self): port=3344 self.server = WebsocketServer(port,host='0.0.0.0') self.server.set_fn_new_client(self.new_client) self.server.set_fn_client_left(self.client_left) self.server.set_fn_message_received(self.message_received) server_thread = threading.Thread(target=self.server.run_forever) server_thread.daemon = True server_thread.start() def stop(self): self.server.server_close() def findClientFromId(self,clientId): for client in self.server.clients: if client['id'] == clientId: return client return None def updateRooms(self,Rooms,removeIndex): self.rooms=Rooms messageStr = "" if len(self.rooms) != 0: messageStr = self.getRoomInfo(self.rooms) self.server.send_message_to_all("R:"+messageStr) if removeIndex != -1: for key in self.clientSelectedRoom: if self.clientSelectedRoom[key] > removeIndex: self.clientSelectedRoom[key]-=1 elif self.clientSelectedRoom[key] == removeIndex: self.clientSelectedRoom[key]=-1 def updateContent(self,Rooms,roomIndex): self.rooms=Rooms for clientId,selectedIndex in self.clientSelectedRoom.iteritems(): client = self.findClientFromId(clientId) if client == None: continue if selectedIndex == roomIndex: messageStr = self.getUpdateInfo(Rooms[roomIndex]) self.server.send_message(client,messageStr) def getRoomInfo(self,rooms): content = "" for room in rooms: names = "" for index in range(4): name = room.users[index].name names += name if index != 3: names += "、" content += names + "|" content = content[:-1] return content def getUpdateInfo(self,room): # trump^{info}^{Name}^{call}^{three}^{play}^{card} info = "" if room.attackTeam!="": info = room.attackTeam + "|" + ("%d / %d")%(room.attackScore,room.attackWinNumber) + "|" + room.defenseTeam + "|" + ("%d / %d")%(room.defenseScore,14-room.attackWinNumber) name = "" for user in room.users: name += user.name + "|" name = name[:-1] call = "" subCalls = [[],[],[],[]] for index in range(4): subCalls[index] = room.callsRaw[index].split('^') count=0;index=0;length=0 while 1: subCall = subCalls[index] str = "" if length < len(subCall) and subCall[length]!="": str = subCall[length] elif(subCalls[index]!=""): count+=1 subCalls[index]="" if count == 4: break call += str + "," if index+1 == 4: index = 0 length += 1 call = call[:-1] call += "|" else: index += 1 call = call[:-1] three = "" for player in room.threeModeUsers: three += player + "|" three = three[:-1] play = "" subPlays = [[],[],[],[]] for index in range(4): subPlays[index] = room.playsRaw[index].split('^') count=0;index=0;length=0 while 1: subPlay = subPlays[index] str = "" if length < len(subPlay): str = subPlay[length] if count == 13: break play += str + "," if index+1 == 4: index = 0 length += 1 count += 1 play = play[:-1] play += "|" else: index += 1 play = play[:-1] winBount = room.boutsWinRecord[:-1] flower = "" for index in range(4): flower += ("%d|")%room.flowerCountRecord[index] flower = flower[:-1] card = "" if room.users[0].name!="": for index in range(4): str = "" for poker in room.playsPokerHand[index]: str += ("%d,")%poker card += str[:-1] + "|" card = card[:-1] return ("%d")%room.getTrump() + "^" + info + "^" + name + "^" + call + "^" + three + "^" + play + "^" + winBount + "^"+ flower + "^" +card
class FakeGWServer(threading.Thread): """ Creates an FakeGWServer. Arguments: port -- port of WebSocket connection. config -- configuration of behaviour, could contain following parameters: 'autoRegister' -- automatic registration accepting 'autoResponse' -- automatic response for requests 'autoData' -- automatic data messages processing 'prePaired' -- list of paired devices for device_list requests. 'autoNewDevice' -- automatic new device reqests handling """ def __init__(self, port, config, host='127.0.0.1'): self.autoRegister = config['autoRegister'] self.autoResponse = config['autoResponse'] self.autoData = config['autoData'] self.prePaired = config['prePaired'] self.autoNewDevice = config['autoNewDevice'] self.WSServer = WebsocketServer(port, host, loglevel=logging.DEBUG) self.WSServer.set_fn_message_received(self.message_received) self.WSServer.set_fn_client_left(self.client_left) self.WSServer.set_fn_new_client(self.new_client) self.messages = [] self.dataMessages = [] self.responseMessages = [] self.newDevices = [] self.client = None self.clientLock = threading.Lock() self.newConnection = threading.Condition(self.clientLock) self.disconnect = threading.Condition(self.clientLock) self.newMessage = threading.Condition(self.clientLock) self.newDataMessage = threading.Condition(self.clientLock) self.newResponseMessage = threading.Condition(self.clientLock) self.newDeviceMessage = threading.Condition(self.clientLock) self.connected = False self.resetEnable = False super().__init__() def run(self): self.WSServer.run_forever() self.WSServer.socket.close() def stop(self): self.WSServer.shutdown() def enableReset(self): with self.clientLock: self.resetEnable = True def new_client(self, client, server): with self.clientLock: if self.connected: logging.debug("Unknown client refused") client['handler'].send_text("", websocket_server.OPCODE_CLOSE_CONN) elif self.client is None or self.resetEnable: self.client = client if not self.autoRegister: self.connected = True self.newConnection.notify_all() self.resetEnable = False logging.debug("connection established") else: logging.debug("dropping completely") client['handler'].send_text("", websocket_server.OPCODE_CLOSE_CONN) def client_left(self, client, server): with self.clientLock: if client == self.client: logging.debug("client disconnected") self.connected = False self.messages = [] self.disconnect.notify_all() else: logging.debug("unknown client disconnected") def message_received(self, client, server, message): logging.debug("received: " + message) with self.clientLock: if self.client != client: logging.debug("dropping message from unknown client") return try: jsonMessage = json.loads(message) if self.autoRegister: if jsonMessage['message_type'] == "gateway_register": self.WSServer.send_message( self.client, '{ "message_type" : "gateway_accepted" }') self.connected = True self.newConnection.notify_all() return if self.autoData: if jsonMessage['message_type'] == "sensor_data_export": sensorData = SensorData.SensorData() sensorData.fromJSON(jsonMessage['data'][0]) self.dataMessages.append(sensorData) self.newDataMessage.notify_all() response = {} response['message_type'] = "sensor_data_confirm" response['id'] = jsonMessage['id'] logging.debug("sending message: " + json.dumps(response)) self.WSServer.send_message(self.client, json.dumps(response)) return if self.prePaired is not None: if jsonMessage['message_type'] == "device_list_request": if jsonMessage['device_prefix'] in self.prePaired: response = {} response['message_type'] = "device_list_response" response['id'] = jsonMessage['id'] response['status'] = 1 response['devices'] = self.prePaired[ jsonMessage['device_prefix']] logging.debug("sending message: " + json.dumps(response)) self.WSServer.send_message(self.client, json.dumps(response)) return if self.autoResponse: if jsonMessage['message_type'] == "response_with_ack": self.responseMessages.append(jsonMessage) self.newResponseMessage.notify_all() response = {} response['message_type'] = "generic_ack" response['id'] = jsonMessage['id'] response['status'] = jsonMessage['status'] logging.debug("sending message: " + json.dumps(response)) self.WSServer.send_message(self.client, json.dumps(response)) return if jsonMessage['message_type'] == "generic_response": self.responseMessages.append(jsonMessage) self.newResponseMessage.notify_all() return if self.autoNewDevice: if jsonMessage['message_type'] == "new_device_request": device = Device.Device(jsonMessage) self.newDevices.append(device) self.newDeviceMessage.notify_all() response = {} response['message_type'] = "generic_ack" response['id'] = jsonMessage['id'] response['status'] = 1 logging.debug("sending message: " + json.dumps(response)) self.WSServer.send_message(self.client, json.dumps(response)) return except Exception as ex: logging.error("Exception: " + str(ex)) pass self.messages.append(message) self.newMessage.notify_all() def nextNewDevice(self, timeout=10): with self.clientLock: if not self.newDevices: self.newDeviceMessage.wait(timeout) if self.newDevices: return self.newDevices.pop(0) def nextResponse(self, timeout=10): with self.clientLock: if not self.responseMessages: self.newResponseMessage.wait(timeout) if self.responseMessages: return self.responseMessages.pop(0) def nextData(self, timeout=10): with self.clientLock: if not self.dataMessages: self.newDataMessage.wait(timeout) if self.dataMessages: return self.dataMessages.pop(0) def clearData(self): with self.clientLock: self.dataMessages = [] def nextMessage(self, timeout=10): with self.clientLock: if not self.messages: self.newMessage.wait(timeout) if self.messages: return self.messages.pop(0) def waitForDisconnect(self, timeout=10): with self.clientLock: if not self.connected: return True self.disconnect.wait(timeout) return not self.connected def waitForConnection(self, timeout=10): with self.clientLock: if self.connected: return True self.newConnection.wait(timeout) return self.connected def sendMessage(self, message): with self.clientLock: if self.connected: logging.debug("sending message: " + message) self.WSServer.send_message(self.client, message) else: raise Exception("client is not connected")
class SwarmNode: def __init__(self, host): self.logger = logger.get_logger(__name__, 'swarm_node') self.assets_paths = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'assets')) self.assets = {} self.load_assets() Thread(target=self.maintain_assets).start() self.host = host self.api_port = 8721 self.api = WebsocketServer(self.api_port, host=self.host) self.api.set_fn_message_received(self.api_on_message) self.api_thread = Thread(target=self.api.run_forever) self.api_thread.start() self.logger.info('Swarm API server started, listening on {}:{}'.format(self.host, self.api_port)) self.report_queue = queue.Queue() self.reports_thread = Thread(target=self.reports_listener) self.reports_thread.start() self.cartography = { 'messages': {}, 'authorized_clients': [] } def load_assets(self): start = time.time() assets_downloader.update_assets() files_packs = {} self.logger.info('Mapping static assets') for file in os.listdir(self.assets_paths): if file.endswith('.json'): if file.replace('.json', '').split('_')[-1].isdigit(): if '_'.join(file.replace('.json', '').split('_')[:-1]) not in files_packs.keys(): files_packs['_'.join(file.replace('.json', '').split('_')[:-1])] = [file] else: files_packs['_'.join(file.replace('.json', '').split('_')[:-1])].append(file) else: files_packs[file.replace('.json', '')] = [file] self.logger.info('Loading static assets...') self.load_assets_list(files_packs) self.logger.info('Done loading assets in {}s'.format(round(time.time() - start, 2))) def build_files_packs_from_assets_names(self, assets_names): files_packs = {} for assset_name in assets_names: for file in os.listdir(self.assets_paths): if file.endswith('.json') and assset_name in file: if file.replace('.json', '').split('_')[-1].isdigit(): if '_'.join(file.replace('.json', '').split('_')[:-1]) not in files_packs.keys(): files_packs['_'.join(file.replace('.json', '').split('_')[:-1])] = [file] else: files_packs['_'.join(file.replace('.json', '').split('_')[:-1])].append(file) else: files_packs[file.replace('.json', '')] = [file] return files_packs def load_assets_list(self, files_packs): for asset_name, file_pack in files_packs.items(): self.logger.info('Loading asset: {}'.format(asset_name)) if len(file_pack) <= 20: for file in file_pack: with open(self.assets_paths + '/' + file, 'r', encoding='utf8') as f: data = json.load(f) if asset_name not in self.assets.keys(): self.assets[asset_name] = data else: if type(data) is list: self.assets[asset_name] += data elif type(data) is dict: self.assets[asset_name].update(data) else: with Pool(cpu_count() - 1) as p: results_list = p.map(self.load_asset_chunk, [self.assets_paths + '/' + file_name for file_name in file_pack]) for asset_chunk in results_list: if asset_name not in self.assets.keys(): self.assets[asset_name] = asset_chunk else: if type(asset_chunk) is list: self.assets[asset_name] += asset_chunk elif type(asset_chunk) is dict: self.assets[asset_name].update(asset_chunk) def maintain_assets(self): self.logger.info('Assets maintainer starting') try: while 1: time.sleep(60) updated_files = assets_downloader.update_assets() updated_assets = set() for file in updated_files: if file.split('_')[-1].isdigit(): updated_assets.add('_'.join(file.split('_')[:-1])) else: updated_assets.add(file) if len(updated_assets): start = time.time() self.logger.info('Updating assets: '.format(updated_assets)) files_packs = self.build_files_packs_from_assets_names(updated_assets) self.load_assets_list(files_packs) self.logger.info('Done updating assets in {}s'.format(round(time.time() - start, 2))) except: self.logger.error('Assets maintainer crashed') self.logger.error(traceback.format_exc()) send_discord_message("Assets maintainer crashed") send_discord_message("`{}`".format(traceback.format_exc())) time.sleep(1) def load_asset_chunk(self, file_path): with open(file_path, 'r', encoding='utf8') as f: chunk = json.load(f) return chunk def api_on_message(self, client, server, message): if message == '': return try: self.logger.info('Recieved from {}: {}'.format(client['address'], message)) message = json.loads(message) if 'id' not in message.keys(): message['id'] = str(uuid.uuid4()) if 'command' in message.keys() and message['command'] != 'login': new_authorized_clients = [] found = False for authorized_client, valid_until in self.cartography['authorized_clients']: if valid_until > time.time(): new_authorized_clients.append((authorized_client, valid_until)) if authorized_client == client: found = True self.cartography['authorized_clients'] = new_authorized_clients if not found: self.logger.warning('Unauthorized client tried to connect') message['success'] = False message['details'] = {'reason': 'Unauthorized client'} self.api.send_message(client, json.dumps(message)) return self.cartography['messages'][message['id']] = client intercept_command = False if 'command' in message.keys() and message['command'] == 'new_bot': self.logger.info('Creating new bot : ' + str(message['parameters'])) try: strategies.support_functions.create_profile( id=message['parameters']['id'], bot_name=message['bot'], password=message['parameters']['password'], username=message['parameters']['username'], server=message['parameters']['server'] ) self.logger.info('Created : ' + str(message['bot'])) message['success'] = True message['details'] = {} self.api.send_message(client, json.dumps(message)) return except Exception as e: if e.args[0] == 'Bot already exists. Delete it using the \'delete_bot\' command first.': self.logger.warn('Failed creating : ' + str(message['bot'])) message['success'] = False message['details'] = {'reason': e.args[0]} self.api.send_message(client, json.dumps(message)) else: raise return if 'command' in message.keys() and message['command'] == 'delete_bot': strategies.support_functions.delete_profile(message['bot']) message['success'] = True message['details'] = {} if message['bot'] in self.cartography.keys(): self.kill_commander(message['bot']) self.api.send_message(client, json.dumps(message)) return if 'command' in message.keys() and message['command'] == 'login': if 'parameters' in message.keys() and 'token' in message['parameters'].keys(): valid_until = support_functions.token_is_authorized(message['parameters']['token']) if valid_until: for authorized_client, _ in self.cartography['authorized_clients']: message['success'] = True if client == authorized_client: self.api.send_message(client, json.dumps(message)) return self.cartography['authorized_clients'].append((client, valid_until)) message['success'] = True self.api.send_message(client, json.dumps(message)) return else: message['success'] = False self.api.send_message(client, json.dumps(message)) return if 'command' in message.keys() and message['command'] == 'test': self.api.send_message(client, json.dumps({'success': True})) return if 'bot' in message.keys() and message['bot'] not in self.cartography.keys(): self.logger.info('Bot is not running. Starting commander for {}'.format(message['bot'])) try: self.spawn_commander(json.loads(json.dumps(message['bot'])), client) except Exception as e: if e.args[0] == 'Bot does not exist. Create a profile using the \'new_bot\' command first.': message['report'] = {} message['report']['success'] = False message['report']['details'] = {'reason': e.args[0]} self.api.send_message(client, json.dumps(message)) else: raise return if not intercept_command: self.logger.info('Adding strategy to {}: {}'.format(message['bot'], message)) self.cartography[message['bot']]['strategies_queue'].put(message) except Exception: self.logger.warning('Received badly formatted strategy') self.logger.warning(traceback.format_exc()) def reports_listener(self): while 1: try: report = self.report_queue.get() self.logger.info('New report from {}: {}'.format(report['bot'], report)) if 'exception_notif' in report.keys(): # A component of a bot died, kill the rest of it client = self.cartography[report['bot']]['client'] self.kill_commander(report['bot']) else: # Business as usual client = self.cartography['messages'].pop(report['id']) self.api.send_message(client, json.dumps(report)) except BrokenPipeError: self.logger.warning('Client closed connection') self.logger.warning(traceback.format_exc()) except Exception: self.logger.warning('Received badly formatted report') self.logger.warning(traceback.format_exc()) def spawn_commander(self, bot_name, client): if bot_name in self.cartography.keys(): raise Exception('{} is already used elsewhere'.format(bot_name)) bot_profile = strategies.support_functions.get_profile(bot_name) self.cartography[bot_name] = {} self.cartography[bot_name].update({'strategies_queue': queue.Queue()}) self.cartography[bot_name].update({'thread': Thread(target=Commander, args=(bot_profile, self.cartography[bot_name]['strategies_queue'], self.report_queue, self.assets))}) self.cartography[bot_name]['thread'].start() self.cartography[bot_name]['client'] = client def kill_commander(self, bot_name): self.cartography[bot_name]['strategies_queue'].put({'stop': 'die'}) del self.cartography[bot_name]
class GUI: # Initialization function # The actual initialization def __init__(self, host, console, hal): t = threading.Thread(target=self.run_server) self.payload = {'image1': '', 'shape1': [], 'image2': '', 'shape2': [], 'text_buffer': '', 'point': '', 'matching': '', 'paint_matching':''} self.server = None self.client = None self.host = host # Image variables self.image1_to_be_shown = None self.image2_to_be_shown = None self.image_to_be_shown_updated = False self.image_show_lock = threading.Lock() self.acknowledge = False self.acknowledge_lock = threading.Lock() self.point_to_save = [] self.point_to_send = [] self.matching_to_save = [] self.duplicate_matching = False self.matching_to_send = [] self.paint_matching = False # Take the console object to set the same websocket and client self.console = console self.hal = hal t.start() # Explicit initialization function # Class method, so user can call it without instantiation @classmethod def initGUI(cls, host, console): # self.payload = {'image': '', 'shape': []} new_instance = cls(host, console) return new_instance # Function to prepare image payload # Encodes the image as a JSON string and sends through the WS def payloadImage(self): self.image_show_lock.acquire() image_to_be_shown_updated = self.image_to_be_shown_updated image1_to_be_shown = self.image1_to_be_shown image2_to_be_shown = self.image2_to_be_shown self.image_show_lock.release() image1 = image1_to_be_shown payload1 = {'image1': '', 'shape1': ''} image2 = image2_to_be_shown payload2 = {'image2': '', 'shape2': ''} if(image_to_be_shown_updated == False): return payload1,payload2 shape1 = image1.shape image1 = cv2.cvtColor(image1, cv2.COLOR_RGB2BGR) frame1 = cv2.imencode('.JPEG', image1)[1] encoded_image1 = base64.b64encode(frame1) payload1['image1'] = encoded_image1.decode('utf-8') payload1['shape1'] = shape1 shape2 = image2.shape image2 = cv2.cvtColor(image2, cv2.COLOR_RGB2BGR) frame2 = cv2.imencode('.JPEG', image2)[1] encoded_image2 = base64.b64encode(frame2) payload2['image2'] = encoded_image2.decode('utf-8') payload2['shape2'] = shape2 self.image_show_lock.acquire() self.image_to_be_shown_updated = False self.image_show_lock.release() return payload1,payload2 # Function for student to call def showImages(self, image1, image2, paint_matching): self.paint_matching = paint_matching if (np.all(self.image1_to_be_shown == image1) == False or np.all(self.image2_to_be_shown == image2) == False): self.image_show_lock.acquire() self.image1_to_be_shown = image1 self.image2_to_be_shown = image2 self.image_to_be_shown_updated = True self.image_show_lock.release() # Function to get the client # Called when a new client is received def get_client(self, client, server): self.client = client self.console.set_websocket(self.server, self.client) # Function to get value of Acknowledge def get_acknowledge(self): self.acknowledge_lock.acquire() acknowledge = self.acknowledge self.acknowledge_lock.release() return acknowledge # Function to get value of Acknowledge def get_frequency(self): frequency = self.time_frequency return frequency # Function to get value of Acknowledge def set_acknowledge(self, value): self.acknowledge_lock.acquire() self.acknowledge = value self.acknowledge_lock.release() # Update the gui def update_gui(self): # Payload Image Message payload1, payload2 = self.payloadImage() self.payload["image1"] = json.dumps(payload1) self.payload["image2"] = json.dumps(payload2) # Payload Point Message length_point_send = len(self.point_to_send) if (length_point_send != 0): if (length_point_send > 20): self.payload["point"] = json.dumps(self.point_to_send[0:20]) del self.point_to_send[0:20] else: self.payload["point"] = json.dumps(self.point_to_send) del self.point_to_send[0:length_point_send] else: self.payload["point"] = json.dumps([]) length_matching_send = len(self.matching_to_send) self.payload["matching"] = json.dumps(self.matching_to_send) del self.matching_to_send[0:length_matching_send] self.payload["paint_matching"] = self.paint_matching # Payload Console Messages message_buffer = self.console.get_text_to_be_displayed() self.payload["text_buffer"] = json.dumps(message_buffer) message = "#gui" + json.dumps(self.payload) self.server.send_message(self.client, message) # Function to read the message from websocket # Gets called when there is an incoming message from the client def get_message(self, client, server, message): # Acknowledge Message for GUI Thread if(message[:4] == "#ack"): self.set_acknowledge(True) # Message for Console elif(message[:4] == "#con"): self.console.prompt(message) # Activate the server def run_server(self): self.server = WebsocketServer(port=2303, host=self.host) self.server.set_fn_new_client(self.get_client) self.server.set_fn_message_received(self.get_message) self.server.run_forever() # Show new points def ShowNewPoints(self, points): duplicate_point = False for i in range(0, len(points)): for j in range (0, len(self.point_to_save)): if (self.point_to_save[j] == points[i]): duplicate_point = True if (duplicate_point == False): self.point_to_save.append(points[i]) self.point_to_send.append(points[i]) else: duplicate_point = False # Show all points def ShowAllPoints(self, points): number_equal_points = 0 for i in range(0, len(points)): for j in range (0, len(self.point_to_save)): if (self.point_to_save[j] == points[i]): number_equal_points += 1 if (number_equal_points != len(points)): self.ClearAllPoints() for i in range(0, len(points)): self.point_to_save.append(points[i]) self.point_to_send.append(points[i]) # Show image matching def showImageMatching(self, x1, y1, x2, y2): matching = [x1, y1, x2, y2] for i in range(0, len(self.matching_to_save)): if ((self.matching_to_save[i] == matching) == True): self.duplicate_matching = True if (self.duplicate_matching == False): self.matching_to_save.append(matching) self.matching_to_send.append(matching) else: self.duplicate_matching = False # Function to reset def ClearAllPoints(self): self.point_to_save =[] self.point_to_send = [] self.matching_to_save = [] self.matching_to_send = [] self.server.send_message(self.client, "#res")
class WSServer: def __init__(self, port=9007): self.port = port self.server = WebsocketServer(self.port, host='0.0.0.0') self.server.set_fn_new_client(self.on_connect) self.server.set_fn_message_received(self.on_msg) self.server.set_fn_client_left(self.on_disconnect) self.msg_lock = Lock() def ping(self): self.server.send_message_to_all(json.dumps({'action': 'ping'})) # pinging every 50 seconds to avoid disconnection t = Timer(50, self.ping) t.start() def on_connect(self, client, server): #server.send_message_to_all("Hey all, a new client has joined us") pass def on_disconnect(self, client, server): #server.send_message_to_all("Hey all, a new client has joined us") pass def on_msg(self, client, server, message): self.msg_lock.acquire() try: args = message.split(' ') command = args[0] args = args[1:] internal = 'internal_ws_' + command if hasattr(self, internal): getattr(self, internal)(client, *args) else: data = {'action': 'cmd', 'msg': 'not found'} self.server.send_message(client, json.dumps(data)) except Exception as e: print("Error: ", e) connection.close() self.msg_lock.release() def run(self): self.ping() self.server.run_forever() def drop_seat(self, hold): session = hold.session layout = hold.layout row, col = hold.seat.split('-') data = { 'action': 'drop', 'session': session.id, 'layout': layout.id, 'row': row, 'col': col, } hold.delete() confirmed = not session.is_seat_available(layout, row, col) if confirmed: data['action'] = 'confirm' self.server.send_message_to_all(json.dumps(data)) def notify_confirmed(self): d = timezone.now() d = d - datetime.timedelta(seconds=80) holds = TicketSeatHold.objects.filter(date__gt=d, type="R") for h in holds: row, col = h.seat.split('-') data = { 'action': 'confirm', 'session': h.session.id, 'layout': h.layout.id, 'row': row, 'col': col, } self.server.send_message_to_all(json.dumps(data)) # Protocol definitions def internal_ws_autoseats(self, client, session, amount, user): session = Session.objects.get(id=session) seats = search_seats(session, int(amount)) data = { 'action': 'autoseat', 'session': session.id, 'seats': seats, } for s in seats: layout = SeatLayout.objects.get(id=s['layout']) seat = '{}-{}'.format(s['row'], s['col']) d2 = { 'action': 'hold', 'session': session.id, 'layout': layout.id, 'row': s['row'], 'col': s['col'], } sh = TicketSeatHold(client=user, layout=layout, seat=seat, session=session) sh.save() self.server.send_message_to_all(json.dumps(d2)) if not seats: data['error'] = _('Not found contiguous seats, please, select manually using the green button') self.server.send_message(client, json.dumps(data)) def internal_ws_get_events(self, client): events = serializers.serialize("json", Event.objects.all()) self.server.send_message(client, events) def internal_ws_get_spaces(self, client, event): event = Event.objects.get(slug=event) spaces = serializers.serialize("json", event.spaces.all()) self.server.send_message(client, spaces) def internal_ws_get_sessions(self, client, event, space): event = Event.objects.get(slug=event) space = event.spaces.get(slug=space) sessions = serializers.serialize("json", space.sessions.all()) self.server.send_message(client, sessions) def internal_ws_hold_seat(self, client, session, layout, row, col, user): session = Session.objects.get(id=session) layout = SeatLayout.objects.get(id=layout) data = { 'action': 'hold', 'session': session.id, 'layout': layout.id, 'row': row, 'col': col, } if not session.is_seat_holded(layout, row, col): seat = row + '-' + col sh = TicketSeatHold(client=user, layout=layout, seat=seat, session=session) sh.save() self.server.send_message_to_all(json.dumps(data)) else: data['action'] = 'holded' self.server.send_message(client, json.dumps(data)) def internal_ws_drop_seat(self, client, session, layout, row, col, user): try: seat = row + '-' + col sh = TicketSeatHold.objects.get(client=user, type='H', layout=layout, seat=seat, session=session) self.drop_seat(sh) except: pass def internal_ws_add_ac(self, client, control, date, st): data = { 'action': 'add_ac', 'control': control, 'date': date, 'st': st, } log = LogAccessControl(access_control=AccessControl.objects.get(slug=control), status=st) log.save() self.server.send_message_to_all(json.dumps(data)) def internal_ws_add_sale(self, client, window, date, payment, amount, price): data = { 'action': 'add_sale', 'window': window, 'date': date, 'payment': payment, 'amount': amount, 'price': price } self.server.send_message_to_all(json.dumps(data)) def internal_ws_add_change(self, client, window, date, payment, amount, price): data = { 'action': 'add_change', 'window': window, 'date': date, 'payment': payment, 'amount': amount, 'price': price } self.server.send_message_to_all(json.dumps(data))
class WebTunnel(threading.Thread): def __init__(self, controller, port): threading.Thread.__init__(self) self.port = port self.outboundPackets = { "SET_VALUE_BOUNDS": "svb", "FEEDBACK_VALUE": "fv" #aka true value } self.inboundPackets = {"USER_VALUE": "uv"} self.positionSuffix = "0" self.maxVelocitySuffix = "1" self.stiffnessSuffix = "2" self.jointNoToWidgetPrefix = ["joint0_", "joint1_"] self.controller = controller self.queue = [] self.server = WebsocketServer(self.port) self.server.set_fn_new_client(self.new_client) self.server.set_fn_client_left(self.client_left) self.server.set_fn_message_received(self.message_received) self.positionFeedback = {} self.stiffnessFeedback = {} self.positionBounds = {} self.stiffnessBounds = {} self.maxVelocityBounds = {} def run(self): print("Tunnel now running!") self.server.run_forever() def shutdown(self): print("Shutting down") try: self.server.shutdown() except: exit(1) # Called for every client connecting (after handshake) def new_client(self, client, server): print("New client connected and was given id %d" % client['id']) print("Filling in client with latest data") #send latest position bounds for k in self.positionBounds: self.server.send_message( client, self.getPositionBoundsPacket(k, str(self.positionBounds[k][0]), self.positionBounds[k][1])) #send latest position feedbacks for k in self.positionFeedback: self.server.send_message( client, self.getPositionFeedbackPacket(k, self.positionFeedback[k])) #send latest max velocity bounds for k in self.maxVelocityBounds: self.server.send_message( client, self.getMaxVelocityBoundsPacket( k, str(self.maxVelocityBounds[k][0]), self.maxVelocityBounds[k][1])) #send latest stiffness bounds for k in self.stiffnessBounds: self.server.send_message( client, self.getStiffnessBoundsPacket(k, str(self.stiffnessBounds[k][0]), self.stiffnessBounds[k][1])) #send latest applied force feedbacks #for k in self.stiffnessFeedback: # self.server.send_message(client, self.getStiffnessFeedbackPacket(k, # self.stiffnessFeedback[k])) def client_left(self, client, server): print("Client(%d) disconnected" % client['id']) def message_received(self, client, server, message): print("Client %d said: %s", client['id'], message) if '%' in message: tokens = message.split('%') if tokens[0] == self.inboundPackets['USER_VALUE']: if tokens[1] and tokens[2]: jointType = tokens[1].split("_") jointType = jointType[len(jointType) - 1] jointPrefix = tokens[1].split("_")[0] + "_" #jointNo = jointPrefix.split("joint") #jointNo = jointNo[len(jointNo) - 1] print "jointPrefix: " + jointPrefix + "\n" print "joint type: " + jointType + "\n" if jointPrefix in self.jointNoToWidgetPrefix: index = self.jointNoToWidgetPrefix.index(jointPrefix) if self.controller: if jointType == self.positionSuffix: self.controller.setPosition(index, tokens[2]) elif jointType == self.maxVelocitySuffix: self.controller.setMaxVelocity( index, tokens[2]) elif jointType == self.stiffnessSuffix: self.controller.setStiffness(index, tokens[2]) else: print( 'Undefined controller -- tried calling setPosition(' + str(index) + ', ' + str(tokens[2]) + ')') else: print('Could not find target with prefix: ' + jointPrefix) else: print('Corrupt USER_VALUE packet') else: print('Unhandled packet: ' + tokens[0]) elif message == 'PING': self.server.send_message_to_all('PONG') else: print('Invalid packet') def sendPositionBoundsPacket(self, no, lower, upper): self.server.send_message_to_all( self.getPositionBoundsPacket(no, lower, upper)) self.positionBounds[no] = [lower, upper] def sendPositionFeedbackPacket(self, no, val): self.server.send_message_to_all(self.getPositionFeedbackPacket( no, val)) self.positionFeedback[no] = val def sendStiffnessBoundsPacket(self, no, lower, upper): print "SENDING STIFFNESS BOUNDS: " + str(no) + " " + str( lower) + " " + str(upper) self.server.send_message_to_all( self.getStiffnessBoundsPacket(no, lower, upper)) self.stiffnessBounds[no] = [lower, upper] def sendStiffnessFeedbackPacket(self, no, val): self.server.send_message_to_all( self.getStiffnessFeedbackPacket(no, val)) self.stiffnessFeedback[no] = val def sendMaxVelocityBoundsPacket(self, no, lower, upper): self.server.send_message_to_all( self.getMaxVelocityBoundsPacket(no, lower, upper)) self.maxVelocityBounds[no] = [lower, upper] def getPositionBoundsPacket(self, no, lower, upper): if self.jointNoToWidgetPrefix[no]: return (self.outboundPackets["SET_VALUE_BOUNDS"] + "%" + self.jointNoToWidgetPrefix[no] + self.positionSuffix + "%" + str(lower) + "%" + str(upper)) else: print("Could not find widget prefix for no = " + no) return None def getStiffnessBoundsPacket(self, no, lower, upper): if self.jointNoToWidgetPrefix[no]: return (self.outboundPackets["SET_VALUE_BOUNDS"] + "%" + self.jointNoToWidgetPrefix[no] + self.stiffnessSuffix + "%" + str(lower) + "%" + str(upper)) else: print("Could not find widget prefix for no = " + no) return None def getPositionFeedbackPacket(self, no, val): if self.jointNoToWidgetPrefix[no]: return (self.outboundPackets["FEEDBACK_VALUE"] + "%" + self.jointNoToWidgetPrefix[no] + str(self.positionSuffix) + "%" + str(val)) else: print("Could not find widget prefix for no = " + no) return None def getStiffnessFeedbackPacket(self, no, val): if self.jointNoToWidgetPrefix[no]: return (self.outboundPackets["FEEDBACK_VALUE"] + "%" + self.jointNoToWidgetPrefix[no] + str(self.stiffnessSuffix) + "%" + str(val)) else: print("Could not find widget prefix for no = " + no) return None def getMaxVelocityBoundsPacket(self, no, lower, upper): if self.jointNoToWidgetPrefix[no]: return (self.outboundPackets["SET_VALUE_BOUNDS"] + "%" + self.jointNoToWidgetPrefix[no] + self.maxVelocitySuffix + "%" + str(lower) + "%" + str(upper)) else: print("Could not find widget prefix for no = " + no) return None
class Million: _port = 9001 _server = None def __init__(self): self._server = WebsocketServer(self._port, "0.0.0.0") self._server.set_fn_new_client(self.new_client) #用户加入 self._server.set_fn_client_left(self.client_left) #用户断开 self._server.set_fn_message_received(self.message_received) #接收消息 self._server.run_forever() # 验证发送或接收到的数据包是否合法 def verifyData(self, data, stype='receive'): if (type(data) is not dict): data = json.loads(data) if 'type' not in data: raise Exception('Data type error type:' + data['type']) if 'receive' == stype: if 'UUID' not in data: raise Exception('UUID can not empty {}'.format(data)) return data # 向客户端发送 def sendTo(self, clientId, data): try: data = self.verifyData(data, 'send') except Exception as e: return common.ex(e) # 全员发送 if 'all' == clientId: # data['receiver'] = 'all' self._server.send_message_to_all( json.dumps(data, ensure_ascii=False)) else: self._server.send_message(clientId, json.dumps(data, ensure_ascii=False)) print("发送: {} to client {}".format(data, clientId)) # 发送聊天消息 def sendChat(self, fromName, toId, msg): return self.sendTo(toId, { 'from': fromName, 'type': 'chat', 'msg': msg.strip() }) # 当新的客户端连接时会提示 # Called for every client connecting (after handshake) def new_client(self, client, server): print("New client connected and was given id {}".format(client['id'])) # self.sendTo('all', {'type': 'newplayer', 'msg': '进入了房间'}) # 当旧的客户端离开 # Called for every client disconnecting def client_left(self, client, server): print("Client({}) disconnected".format(client['id'])) # UUID: clientHandler _clients = {} # 接收客户端的信息。 # Called when a client sends a message def message_received(self, client, server, data): try: data = self.verifyData(data) except Exception as e: return common.ex(e) print("Client({}) 接收: {}".format(client['id'], data)) self._clients[data['UUID']] = client # data['_clientId'] = client name = data['type'] try: getattr(self, name)(data) except AttributeError as e: return common.ex('接收消息处理失败', e) # 给客户端显示错误 def errorShow(self, to, msg): self.sendTo(to, {'type': 'errorShow', 'msg': msg}) return False # 用户信息 _userList = {} # 新用户加入 def newplayer(self, data): print('do newplayer') if not data['name'].strip(): return self.errorShow(self._clients[data['UUID']], '名字不能为空') # 添加人员信息 self._userList[data['UUID']] = { 'UUID': data['UUID'], 'name': data['name'], 'jointime': int(time.time()), # 'joinip': data["ip"], # '_clientId': data["_clientId"], } # 发送消息 self.sendChat('系统', 'all', '欢迎 {} 加入海岛争夺'.format(data['name'])) return self.getMyInfo({"UUID": data['UUID']}) # 获取用户信息 def getMyInfo(self, data): print('do get my info') if data['UUID'] not in self._userList: print('notlogin') return self.sendTo(self._clients[data['UUID']], { 'type': 'getMyInfo', 'status': 'notlogin', }) else: print('login') userInfo = self._userList[data['UUID']] return self.sendTo(self._clients[data['UUID']], { 'type': 'getMyInfo', 'status': 'success', 'userInfo': userInfo }) # 聊天 def chat(self, data): print('do chat') self.sendChat(data['from'], data['to'], data['msg']) # 获取已创建房间列表 def getRoomList(self, data, refresh=False): print('do get room list') # 还没有房间 if len(self._roomList) <= 0: return False to = self._clients[data['UUID']] # 即刷新所有人的列表 if True == refresh: to = 'all' self.sendTo( to, { 'type': "getRoomList", 'status': 'success', 'roomList': self._roomList, }) # 房间缓存 _roomList = {} # 最后的 room _lastRoomId = 5000 # 创建新房间 def newRoom(self, data): print('do get newRoom') self._lastRoomId = self._lastRoomId + 1 roomId = self._lastRoomId self._roomList[roomId] = { 'roomId': roomId, 'name': data['name'], 'min_per': data['min_per'], 'map_size': data['map_size'], 'created_at': int(time.time()), 'userList': [data['UUID']] } # 通知创建人创建成功 self.sendTo(self._clients[data['UUID']], { 'type': 'newRoom', 'status': 'success', 'roomId': roomId, }) # 通知大厅 重新加载 return self.getRoomList(data, True) # 加入一个房间 def join2Room(self, data): print('do join to room') if data['roomId'] not in self._roomList: self.getRoomList(data) # 刷新他的房间列表 return common.ex('房间已被解散,请重新进入') self.sendTo( self._clients[data['UUID']], { 'type': "getRoomList", 'status': 'success', 'roomInfo': self._roomList[data['roomId']], })
class Environment: """ Environment class is responsible for passing the actions to the game. It is also responsible for retrieving the game status and the reward. """ actions = {Action.UP: 'UP', Action.FORWARD: 'FORTH', Action.DOWN: 'DOWN'} def __init__(self, host, port, debug=False): self.debug = debug self.queue = multiprocessing.Queue() self.game_client = None self.server = WebsocketServer(port, host=host) self.server.set_fn_new_client(self.new_client) self.server.set_fn_message_received(self.new_message) print("\nGame can be connected (press F5 in Browser)") thread = threading.Thread(target=self.server.run_forever) thread.daemon = True thread.start() def new_client(self, client, server): if self.debug: print("GameAgent: Game just connected") self.game_client = client self.server.send_message(self.game_client, "Connection to Game Agent Established") def new_message(self, client, server, message): if self.debug: print("GameAgent: Incoming data from game") data = json.loads(message) image, crashed = data['world'], data['crashed'] # remove data-info at the beginning of the image image = re.sub('data:image/png;base64,', '', image) # convert image from base64 decoding to np array image = np.array(Image.open(BytesIO(base64.b64decode(image)))) # cast to bool crashed = True if crashed in ['True', 'true'] else False self.queue.put((image, crashed)) def start_game(self): """ Starts the game and lets the TRex run for half a second and then returns the initial state. :return: the initial state of the game (np.array, reward, crashed). """ # game can not be started as long as the browser is not ready while self.game_client is None: time.sleep(1) self.server.send_message(self.game_client, "START") time.sleep(4) return self.get_state(Action.FORWARD) def refresh_game(self): time.sleep(0.5) print("...refreshing game...") self.server.send_message(self.game_client, "REFRESH") time.sleep(1) def do_action(self, action): """ Performs action and returns the updated status :param action: Must come from the class Action. The only allowed actions are Action.UP, Action.Down and Action.FORWARD. :return: return the image of the game after performing the action, the reward (after the action) and whether the TRex crashed or not. """ if action != Action.FORWARD: # noting needs to be send when the action is going forward self.server.send_message(self.game_client, self.actions[action]) time.sleep(.05) return self.get_state(action) def get_state(self, action): self.server.send_message(self.game_client, "STATE") image, crashed = self.queue.get() if crashed: reward = -100. else: if action == Action.UP: reward = -5. elif action == Action.DOWN: reward = -3. else: reward = 1. return image, reward, crashed
def on_get_batches(self, client, server: WebsocketServer): batches = self.database.get_batches() json_data = self.converter.batches_to_json(batches) server.send_message(client, 'res|batches|%s' % json_data)
def on_get_paths_dta(self, client, server: WebsocketServer): paths = self.database.get_paths_dta() json_data = self.converter.paths_dta_to_json(paths) server.send_message(client, 'res|pathsDta|%s' % json_data)
class DataDriver: # 客户端信息 class ClientInfo: def __init__(self, client, address): # 客户端对象 self.client = client # 客户端地址 self.address = address # 客户端订阅主题 self.topic = '' def __init__(self): # 本地ip地址 self.__host = '' # 本地端口号 self.__port = 0 # 数据模式:sensor(传感类数据);event(事件类数据) self.__model = '' # websocket服务器对象 self.__web_server = None # 客户端字典 self.__client_dict = {} # 组装数据函数字典 self.__package = { 'sensor': self.__package_sensor_data, 'event': self.__package_event_data } # 获取版本信息 def get_version(self): return json.dumps({ 'code': 0, 'data': { 'version': driver_version, 'name': driver_name, 'desc': driver_desc } }) # 设置基础配置 def set_basic_config(self, cfg_name, cfg_msg): # 解析配置 try: cfg = json.loads(cfg_msg, encoding='utf-8') self.__host, self.__port, self.__model = cfg['host'], cfg[ 'port'], cfg['model'] except Exception as err: LOG.error('解析基础配置失败:%s' % (str(err), )) return RET_FAIL_PARAM # 校验配置 if self.__model not in ('sensor', 'event'): LOG.error('校验基础配置失败:%s' % self.__model) return RET_FAIL_PARAM LOG.info('设置基础配置成功') return RET_OK # 设置运行时配置 def set_run_config(self, cfg_name, cfg_msg): # 无运行时配置,直接返回 return RET_OK # 初始化 def init(self): try: # 启动WebSocket服务 self.__web_server = WebsocketServer(self.__port, self.__host) # 注册回调函数 self.__web_server.set_fn_new_client(self.__new_client) self.__web_server.set_fn_client_left(self.__client_left) self.__web_server.set_fn_message_received(self.__msg_receive) # 创建WebSocket服务线程 t1 = threading.Thread(target=self.__web_server.run_forever) t1.start() except Exception as err: LOG.error('初始化失败:%s' % (str(err), )) return RET_FAIL_EXEC LOG.info('驱动初始化成功。创建websocket服务端:%s:%d' % (self.__host, self.__port)) return RET_OK # 设置回调函数 def set_fun(self, fun): # 无需回调,直接返回 return RET_OK # 写入数据(对外发布数据) def write_data(self, data_info, data_list): try: # 解析data_info里的topic data_info = json.loads(data_info, encoding='utf-8') topic = data_info['topic'] for info in self.__client_dict.values(): if topic == info.topic: self.__web_server.send_message( info.client, self.__package_data(data_list)) except Exception as err: LOG.error('发布数据失败:%s' % str(err)) return RET_FAIL_EXEC return RET_OK # 启动运行 def run(self): # 无需启动,直接返回 return RET_OK # 停止运行 def stop(self): # 无需停止,直接返回 return RET_OK # 获取状态 def get_state(self): state = 0x00000000 return json.dumps({'code': 0, 'data': state}) # ---------------------------------------内部实现--------------------------------------------- # 新客户端连接 def __new_client(self, client, server): if client: LOG.info("新的页面客户端连接: %d, %s" % (client['id'], str(client['address']))) self.__client_dict[client['id']] = self.ClientInfo( client, client['address']) # 接收到页面请求 def __msg_receive(self, client, server, message): if client: LOG.info("接收到页面%d请求:%s..." % (client['id'], message[:100])) try: msg_dict = json.loads(message) topic = msg_dict['topic'] self.__client_dict[client['id']].topic = topic except Exception: server.send_message(client, 'pong') # 页面离开 def __client_left(self, client, server): if client: LOG.info('页面断开连接:%d, %s' % (client['id'], str(client['address']))) if client['id'] in self.__client_dict: self.__client_dict.pop(client['id']) # 组装数据 def __package_data(self, data_list): return self.__package[self.__model](data_list) # 组装传感类数据 def __package_sensor_data(self, data_list): datas = [] for data in data_list: datas.append(sensor2dict(data)) return json.dumps(datas) def __package_event_data(self, data_list): datas = [] for data in data_list: datas.append(event2dict(data)) return json.dumps(datas)
class WBmessenger(object): def __init__(self, viewerparent): self.parent = viewerparent self.ProcessMessage = self.parent.ProcessMessage self.websockport = self.parent.websockport self.sleeptime = self.parent.sleeptime self.mprint = self.parent.mprint self.parent.lastviewmtrx self.browserisopen = False self.msgqueue = [] self.msgdelim = ":\n" self.ishandling = False self.websockclient = None self.isterminating = False self.was_disconnected = None self.mywebsock = None self.websockeventloop = None def Sleep(self, t): time.sleep(t) def OnWebsocketClientMessage(self, client, server, message): self.ProcessMessage(message) def StartWebsocket(self): self.server = WebsocketServer(self.websockport, host='127.0.0.1') if not self.server: raise Sorry("Could not connect to web browser") self.server.set_fn_new_client(self.OnConnectWebsocketClient) self.server.set_fn_client_left(self.OnDisconnectWebsocketClient) self.server.set_fn_message_received(self.OnWebsocketClientMessage) self.wst = threading.Thread(target=self.server.run_forever) self.wst.daemon = True self.wst.start() self.msgqueuethrd = threading.Thread(target=self.WebBrowserMsgQueue) self.msgqueuethrd.daemon = True self.msgqueuethrd.start() def StopWebsocket(self): try: if self.websockclient: # might not have been created if program is closed before a data set is shown self.websockclient['handler'].send_text(u"", opcode=0x8) except Exception as e: self.mprint(to_str(e) + "\n" + traceback.format_exc(limit=10), verbose=0) self.mprint("Shutting down Websocket listening thread", verbose=1) self.server.shutdown() self.parent.javascriptcleaned = True self.msgqueuethrd.join() self.mprint("Shutting down WebsocketServer", verbose=1) self.wst.join() self.isterminating = True def AddToBrowserMsgQueue(self, msgtype, msg=""): self.msgqueue.append((msgtype, msg)) def WebBrowserMsgQueue(self): try: while True: nwait = 0.0 time.sleep(self.sleeptime) if self.parent.javascriptcleaned: self.mprint("Shutting down WebBrowser message queue", verbose=1) return if len(self.msgqueue): pendingmessagetype, pendingmessage = self.msgqueue[0] gotsent = self.send_msg_to_browser(pendingmessagetype, pendingmessage) while not self.browserisopen: #self.websockclient: time.sleep(self.sleeptime) nwait += self.sleeptime if nwait > self.parent.handshakewait or self.parent.javascriptcleaned or not self.viewerparams.scene_id is not None: return if gotsent: self.msgqueue.remove(self.msgqueue[0]) #if self.was_disconnected: # nwait2 = 0.0 # while nwait2 < self.parent.handshakewait: # nwait2 += self.sleeptime # self.ReloadNGL() # if the html content is huge the browser will be unresponsive until it has finished # reading the html content. This may crash this thread. So try restarting this thread until # browser is ready except Exception as e: self.mprint( str(e) + ", Restarting WebBrowserMsgQueue\n" \ + traceback.format_exc(limit=10), verbose=2) self.websockclient = None self.WebBrowserMsgQueue() def OnConnectWebsocketClient(self, client, server): self.websockclient = client self.mprint("Browser connected:" + str(self.websockclient), verbose=1) if self.was_disconnected: self.was_disconnected = False if self.parent.lastviewmtrx and self.parent.viewerparams.scene_id is not None: self.parent.set_volatile_params() self.mprint("Reorienting client after refresh:" + str(self.websockclient), verbose=2) self.AddToBrowserMsgQueue("ReOrient", self.parent.lastviewmtrx) else: self.parent.SetAutoView() def OnDisconnectWebsocketClient(self, client, server): self.mprint("Browser disconnected:" + str(client), verbose=1) self.was_disconnected = True def send_msg_to_browser(self, msgtype, msg=""): message = u"" + msgtype + self.msgdelim + str(msg) if self.websockclient: nwait = 0.0 while not ("Ready" in self.parent.lastmsg or "tooltip_id" in self.parent.lastmsg \ or "CurrentViewOrientation" in self.parent.lastmsg or "AutoViewSet" in self.parent.lastmsg \ or "ReOrient" in self.parent.lastmsg or "JavaScriptCleanUp" in self.parent.lastmsg or self.websockclient is None): time.sleep(self.sleeptime) nwait += self.sleeptime if nwait > 2.0 and self.browserisopen: self.mprint("ERROR: No handshake from browser!", verbose=0) self.mprint("failed sending " + msgtype, verbose=1) self.mprint("Reopening webpage again", verbose=0) break if self.browserisopen and self.websockclient is not None: try: self.server.send_message(self.websockclient, message) return True except Exception as e: self.mprint(str(e) + "\n" + traceback.format_exc(limit=10), verbose=1) self.websockclient = None return False else: return self.parent.OpenBrowser()
class hklview_3d: def __init__(self, *args, **kwds): self.settings = kwds.get("settings") self.miller_array = None self.d_min = None self.scene = None self.NGLscriptstr = "" self.cameratype = "orthographic" self.url = "" self.binarray = "Resolution" self.icolourcol = None self.iradiicol = None self.iarray = None self.isnewfile = False self.binvals = [] self.workingbinvals = [] self.proc_arrays = [] self.otherscenes = [] self.othermaxdata = [] self.othermindata = [] self.othermaxsigmas = [] self.otherminsigmas = [] self.sceneisdirty = False self.matchingarrayinfo = [] self.match_valarrays = [] self.binstrs = [] self.mapcoef_fom_dict = {} self.verbose = True if kwds.has_key('verbose'): self.verbose = kwds['verbose'] self.mprint = sys.stdout.write if kwds.has_key('mprint'): self.mprint = kwds['mprint'] self.nbin = 0 self.websockclient = None self.lastmsg = "" self.StartWebsocket() tempdir = tempfile.gettempdir() self.hklfname = os.path.join(tempdir, "hkl.htm") if os.path.isfile(self.hklfname): os.remove(self.hklfname) if kwds.has_key('htmlfname'): self.hklfname = kwds['htmlfname'] self.hklfname = os.path.abspath(self.hklfname) self.jscriptfname = os.path.join(tempdir, "hkljstr.js") if os.path.isfile(self.jscriptfname): os.remove(self.jscriptfname) if kwds.has_key('jscriptfname'): self.jscriptfname = kwds['jscriptfname'] self.mprint('Output will be written to \"%s\"\n' \ 'including reference to NGL JavaScript \"%s\"' %(self.hklfname, self.jscriptfname)) self.hklhtml = r""" <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <meta charset="utf-8" /> </head> <body> <script src="%s" type="text/javascript"></script> <script src="%s" type="text/javascript"></script> """ self.htmldiv = """ <div id="viewport" style="width:100%; height:100%;"></div> </body></html> """ self.colourgradientvalues = [] self.UseOSBrowser = True if kwds.has_key('UseOSBrowser'): self.UseOSBrowser = kwds['UseOSBrowser'] self.viewmtrxelms = None self.pendingmessage = None def __exit__(self, exc_type, exc_value, traceback): # not called unless instantiated with a "with hklview_3d ... " statement self.server.shutdown() if os.path.isfile(self.hklfname): os.remove(self.hklfname) def set_miller_array(self, col, merge=None, details="", proc_arrays=[]): self.iarray = col if col: self.miller_array = proc_arrays[col] self.proc_arrays = proc_arrays self.merge = merge if (self.miller_array is None): return self.d_min = self.miller_array.d_min() array_info = self.miller_array.info() self.binvals = [ 1.0 / self.miller_array.d_max_min()[0], 1.0 / self.miller_array.d_max_min()[1] ] #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) uc = "a=%g b=%g c=%g angles=%g,%g,%g" % self.miller_array.unit_cell( ).parameters() self.mprint( "Data: %s %s, %d reflections in space group: %s, unit Cell: %s" \ % (array_info.label_string(), details, self.miller_array.indices().size(), \ self.miller_array.space_group_info(), uc) ) #self.construct_reciprocal_space(merge=merge) def ExtendMillerArraysUnionHKLs(self): #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) self.match_valarrays = [] # loop over all miller arrays to find the subsets of hkls common between currently selected # miler array and the other arrays. hkls found in the currently selected miller array but # missing in the subsets are populated populated with NaN values # create miller indices being a superset of available indices in all arrays self.mprint("Gathering superset of miller indices") superset_array = self.proc_arrays[0] for i, validarray in enumerate(self.proc_arrays): if i == 0: continue # first match indices in currently selected miller array with indices in the other miller arrays matchindices = miller.match_indices(superset_array.indices(), validarray.indices()) #print validarray.info().label_string() valarray = validarray.select(matchindices.pairs().column(1)) #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) if valarray.anomalous_flag( ) and not superset_array.anomalous_flag(): # valarray gets its anomalous_flag from validarray. But it cannot have more HKLs than self.miller_array # so set its anomalous_flag to False if self.miller_array is not anomalous data valarray._anomalous_flag = False if not valarray.anomalous_flag() and superset_array.anomalous_flag( ): # temporarily expand other arrays to anomalous if self.miller_array is anomalous valarray = valarray.generate_bijvoet_mates() missing = superset_array.lone_set(valarray) # insert NAN values for reflections in self.miller_array not found in validarray valarray = display.ExtendMillerArray(valarray, missing.size(), missing.indices()) match_valindices = miller.match_indices(superset_array.indices(), valarray.indices()) #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) match_valarray = valarray.select( match_valindices.pairs().column(1)) match_valarray.sort(by_value="packed_indices") #match_valarray.set_info(validarray.info() ) superset_array = match_valarray #print "supersetsize:", superset_array.size() # now extend each miller array to contain any missing indices from the superset miller array for i, validarray in enumerate(self.proc_arrays): # first match indices in currently selected miller array with indices in the other miller arrays matchindices = miller.match_indices(superset_array.indices(), validarray.indices()) #print validarray.info().label_string() valarray = validarray.select(matchindices.pairs().column(1)) #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) if valarray.anomalous_flag( ) and not superset_array.anomalous_flag(): # valarray gets its anomalous_flag from validarray. But it cannot have more HKLs than self.miller_array # so set its anomalous_flag to False if self.miller_array is not anomalous data valarray._anomalous_flag = False if not valarray.anomalous_flag() and superset_array.anomalous_flag( ): # temporarily expand other arrays to anomalous if self.miller_array is anomalous valarray = valarray.generate_bijvoet_mates() missing = superset_array.lone_set(valarray) # insert NAN values for reflections in self.miller_array not found in validarray valarray = display.ExtendMillerArray(valarray, missing.size(), missing.indices()) match_valindices = miller.match_indices(superset_array.indices(), valarray.indices()) #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) match_valarray = valarray.select( match_valindices.pairs().column(1)) match_valarray.sort(by_value="packed_indices") match_valarray.set_info(validarray.info()) self.match_valarrays.append(match_valarray) def construct_reciprocal_space(self, merge=None): self.mprint("Constructing HKL scenes") #if len(self.match_valarrays)==0: # self.ExtendMillerArraysUnionHKLs() self.miller_array = self.match_valarrays[self.iarray] if not self.sceneisdirty: return self.otherscenes = [] self.othermaxdata = [] self.othermindata = [] self.othermaxsigmas = [] self.otherminsigmas = [] self.matchingarrayinfo = [] #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) foms_array = None if self.miller_array.is_complex_array(): fomcolm = self.mapcoef_fom_dict.get( self.miller_array.info().label_string()) if fomcolm: foms_array = self.proc_arrays[fomcolm].deep_copy() #self.scene = display.scene(miller_array=self.miller_array, merge=merge, # settings=self.settings, foms_array=foms_array) # compute scenes for each of the miller arrays for i, match_valarray in enumerate(self.match_valarrays): foms = None if match_valarray.is_complex_array(): fomcolm = self.mapcoef_fom_dict.get( match_valarray.info().label_string()) #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) if fomcolm: foms = self.match_valarrays[fomcolm] #commonarray = match_valarray commonarray = match_valarray.common_set( self.proc_arrays[self.iarray]) commonarray.set_info(match_valarray.info()) if i == self.iradiicol or i == self.icolourcol or i == self.iarray: bfullprocess = True else: bfullprocess = False otherscene = display.scene(miller_array=commonarray, merge=merge, settings=self.settings, foms_array=foms, fullprocessarray=True) #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) if not otherscene.SceneCreated: self.mprint("The " + commonarray.info().label_string() + " array was not processed") continue #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) # cast any NAN values to 1 of the colours and radii to 0.2 before writing javascript b = flex.bool([ bool(math.isnan(e[0]) + math.isnan(e[1]) + math.isnan(e[2])) for e in otherscene.colors ]) otherscene.colors = otherscene.colors.set_selected( b, (1.0, 1.0, 1.0)) b = flex.bool([bool(math.isnan(e)) for e in otherscene.radii]) otherscene.radii = otherscene.radii.set_selected(b, 0.2) self.otherscenes.append(otherscene) ainf = ArrayInfo(otherscene.work_array, self.mprint) self.othermaxdata.append(ainf.maxdata) self.othermindata.append(ainf.mindata) self.othermaxsigmas.append(ainf.maxsigmas) self.otherminsigmas.append(ainf.minsigmas) infostr = ainf.infostr self.mprint("%d, %s" % (i, infostr)) self.matchingarrayinfo.append(infostr) #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) self.sceneisdirty = False def update_settings(self, diffphil): if hasattr(diffphil, "filename"): self.ExtendMillerArraysUnionHKLs() self.sceneisdirty = True if hasattr(diffphil, "spacegroupchoice") or \ hasattr(diffphil, "mergedata") or \ hasattr(diffphil, "column") or \ hasattr(diffphil, "fomcolumn") or \ hasattr(diffphil, "viewer") and ( hasattr(diffphil.viewer, "show_anomalous_pairs") \ or hasattr(diffphil.viewer, "show_data_over_sigma") \ or hasattr(diffphil.viewer, "show_missing") \ or hasattr(diffphil.viewer, "show_only_missing") \ or hasattr(diffphil.viewer, "show_systematic_absences") \ or hasattr(diffphil.viewer, "slice_axis") \ or hasattr(diffphil.viewer, "slice_mode") \ or hasattr(diffphil.viewer, "scale") \ or hasattr(diffphil.viewer, "nth_power_scale_radii") \ or hasattr(diffphil.viewer, "expand_anomalous") \ or hasattr(diffphil.viewer, "expand_to_p1") ): self.sceneisdirty = True self.construct_reciprocal_space(merge=self.merge) if self.miller_array is None or self.iarray < 0: return self.scene = self.otherscenes[self.iarray] self.DrawNGLJavaScript() msg = "Rendered %d reflections\n" % self.scene.points.size() return msg def UpdateBinValues(self, binvals=[]): if binvals: self.binvals = binvals else: self.binvals = [ 1.0 / self.miller_array.d_max_min()[0], 1.0 / self.miller_array.d_max_min()[1] ] def DrawNGLJavaScript(self): if self.miller_array is None: self.mprint("A miller array must be selected for drawing") return self.mprint("Composing NGL JavaScript...") h_axis = self.scene.axes[0] k_axis = self.scene.axes[1] l_axis = self.scene.axes[2] nrefls = self.scene.points.size() Hstararrowstart = roundoff( [-h_axis[0] * 100, -h_axis[1] * 100, -h_axis[2] * 100]) Hstararrowend = roundoff( [h_axis[0] * 100, h_axis[1] * 100, h_axis[2] * 100]) Hstararrowtxt = roundoff( [h_axis[0] * 102, h_axis[1] * 102, h_axis[2] * 102]) Kstararrowstart = roundoff( [-k_axis[0] * 100, -k_axis[1] * 100, -k_axis[2] * 100]) Kstararrowend = roundoff( [k_axis[0] * 100, k_axis[1] * 100, k_axis[2] * 100]) Kstararrowtxt = roundoff( [k_axis[0] * 102, k_axis[1] * 102, k_axis[2] * 102]) Lstararrowstart = roundoff( [-l_axis[0] * 100, -l_axis[1] * 100, -l_axis[2] * 100]) Lstararrowend = roundoff( [l_axis[0] * 100, l_axis[1] * 100, l_axis[2] * 100]) Lstararrowtxt = roundoff( [l_axis[0] * 102, l_axis[1] * 102, l_axis[2] * 102]) # make arrow font size roughly proportional to radius of highest resolution shell fontsize = str(1.0 + roundoff( math.pow(max(self.miller_array.index_span().max()), 1.0 / 3.0))) arrowstr = """ // xyz arrows shape.addSphere( [0,0,0] , [ 1, 1, 1 ], 0.3, 'Origo'); //blue-x shape.addArrow( %s, %s , [ 0, 0, 1 ], 0.1); //green-y shape.addArrow( %s, %s , [ 0, 1, 0 ], 0.1); //red-z shape.addArrow( %s, %s , [ 1, 0, 0 ], 0.1); shape.addText( %s, [ 0, 0, 1 ], %s, 'h'); shape.addText( %s, [ 0, 1, 0 ], %s, 'k'); shape.addText( %s, [ 1, 0, 0 ], %s, 'l'); """ % (str(Hstararrowstart), str(Hstararrowend), str(Kstararrowstart), str(Kstararrowend), str(Lstararrowstart), str(Lstararrowend), Hstararrowtxt, fontsize, Kstararrowtxt, fontsize, Lstararrowtxt, fontsize) # Make colour gradient array used for drawing a bar of colours next to associated values on the rendered html mincolourscalar = self.othermindata[self.icolourcol] maxcolourscalar = self.othermaxdata[self.icolourcol] if self.settings.sigma_color: mincolourscalar = self.otherminsigmas[self.icolourcol] maxcolourscalar = self.othermaxsigmas[self.icolourcol] span = maxcolourscalar - mincolourscalar ln = 60 incr = span / ln colourgradarrays = [] val = mincolourscalar colourscalararray = flex.double() colourscalararray.append(val) for j, sc in enumerate(range(ln)): val += incr colourscalararray.append(val) if self.otherscenes[self.icolourcol].miller_array.is_complex_array(): # When displaying phases from map coefficients together with fom values # compute colour map chart as a function of fom and phase values (x,y axis) incr = 360.0 / ln val = 0.0 colourscalararray = flex.double() colourscalararray.append(val) for j in enumerate(range(ln)): val += incr colourscalararray.append(val) fomarrays = [] if self.otherscenes[self.icolourcol].isUsingFOMs(): fomln = 50 fom = 1.0 fomdecr = 1.0 / (fomln - 1.0) # make fomln fom arrays of size len(colourscalararray) when calling colour_by_phi_FOM for j in range(fomln): fomarrays.append(flex.double(len(colourscalararray), fom)) fom -= fomdecr for j in range(fomln): colourgradarrays.append( graphics_utils.colour_by_phi_FOM( colourscalararray * (math.pi / 180.0), fomarrays[j]) * 255.0) else: fomln = 1 fomarrays = [1.0] colourgradarrays.append( graphics_utils.colour_by_phi_FOM(colourscalararray * (math.pi / 180.0)) * 255.0) else: fomln = 1 fomarrays = [1.0] colourgradarrays.append( graphics_utils.color_by_property( properties=flex.double(colourscalararray), selection=flex.bool(len(colourscalararray), True), color_all=False, gradient_type=self.settings.color_scheme) * 255.0) colors = self.otherscenes[self.icolourcol].colors radii = self.otherscenes[self.iradiicol].radii points = self.scene.points hkls = self.scene.indices dres = self.scene.dres colstr = self.scene.miller_array.info().label_string() data = self.scene.data colourlabel = self.otherscenes[self.icolourcol].colourlabel fomlabel = self.otherscenes[self.icolourcol].fomlabel #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) assert (colors.size() == radii.size() == nrefls) colours = [] positions = [] radii2 = [] spbufttips = [] self.workingbinvals = [] if not self.binarray == "Resolution": ibinarray = int(self.binarray) self.workingbinvals = [ self.othermindata[ibinarray] - 0.1, self.othermaxdata[ibinarray] + 0.1 ] self.workingbinvals.extend(self.binvals) self.workingbinvals.sort() if self.workingbinvals[0] < 0.0: self.workingbinvals.append(0.0) self.workingbinvals.sort() bindata = self.otherscenes[ibinarray].data if self.otherscenes[ibinarray].work_array.is_complex_array(): bindata = self.otherscenes[ibinarray].ampl else: self.workingbinvals = self.binvals colstr = "dres" bindata = 1.0 / dres self.nbin = len(self.workingbinvals) for ibin in range(self.nbin): colours.append([]) # colours and positions are 3 x size of data() positions.append([]) radii2.append([]) spbufttips.append([]) def data2bin(d): for ibin, binval in enumerate(self.workingbinvals): if (ibin + 1) == self.nbin: return ibin if d > binval and d <= self.workingbinvals[ibin + 1]: return ibin #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) raise Sorry("Should never get here") #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) for i, hklstars in enumerate(points): # bin currently displayed data according to the values of another miller array ibin = data2bin(bindata[i]) spbufttip = 'H,K,L: %s, %s, %s' % (hkls[i][0], hkls[i][1], hkls[i][2]) spbufttip += '\ndres: %s ' % str(roundoff(dres[i])) spbufttip += '\' + AA + \'' for j, otherscene in enumerate(self.otherscenes): ocolstr = self.proc_arrays[j].info().label_string() odata = otherscene.data od = "" if self.proc_arrays[j].is_complex_array(): if not math.isnan(otherscene.foms[i]): od = str(roundoff(otherscene.ampl[i])) + ", " + str(roundoff(otherscene.phases[i]) ) + \ "\' + DGR + \'" + ", " + str(roundoff(otherscene.foms[i]) ) else: od = str(roundoff(otherscene.ampl[i])) + ", " + str(roundoff(otherscene.phases[i]) ) + \ "\' + DGR + \'" elif self.proc_arrays[j].sigmas() is not None: od = str(roundoff(odata[i])) + ", " + str( roundoff(otherscene.sigmas[i])) else: od = str(roundoff(odata[i])) if not (math.isnan(abs(odata[i])) or odata[i] == display.inanval): spbufttip += "\n%s: %s" % (ocolstr, od) positions[ibin].extend(roundoff(list(hklstars))) colours[ibin].extend(roundoff(list(colors[i]), 2)) radii2[ibin].append(roundoff(radii[i], 2)) spbufttips[ibin].append(spbufttip) spherebufferstr = """ ttips = new Array(%d) positions = new Array(%d) colours = new Array(%d) radii = new Array(%d) spherebufs = new Array(%d) """ % (self.nbin, self.nbin, self.nbin, self.nbin, self.nbin) negativeradiistr = "" cntbin = 0 self.binstrs = [] for ibin in range(self.nbin): mstr = "" nreflsinbin = len(radii2[ibin]) if (ibin + 1) < self.nbin and nreflsinbin > 0: bin1 = self.workingbinvals[ibin] bin2 = self.workingbinvals[ibin + 1] if colstr == "dres": bin1 = 1.0 / self.workingbinvals[ibin] bin2 = 1.0 / self.workingbinvals[ibin + 1] mstr= "bin:%d, %d reflections with %s in ]%2.2f; %2.2f]" %(cntbin, nreflsinbin, \ colstr, bin1, bin2) self.binstrs.append(mstr) self.mprint(mstr, verbose=True) spherebufferstr += """ // %s ttips[%d] = %s positions[%d] = new Float32Array( %s ) colours[%d] = new Float32Array( %s ) radii[%d] = new Float32Array( %s ) spherebufs[%d] = new NGL.SphereBuffer({ position: positions[%d], color: colours[%d], radius: radii[%d], picking: ttips[%d], }) //}, { disableImpostor: true }) // if true allows wireframe spheres but does not allow resizing spheres shape.addBuffer(spherebufs[%d]) """ %(mstr, cntbin, str(spbufttips[ibin]).replace('\"', '\''), \ cntbin, str(positions[ibin]), cntbin, str(colours[ibin]), \ cntbin, str(radii2[ibin]), cntbin, cntbin, cntbin, cntbin, cntbin, cntbin ) if self.workingbinvals[ibin] < 0.0: negativeradiistr += "spherebufs[%d].setParameters({metalness: 1})\n" % cntbin cntbin += 1 spherebufferstr += """ // create tooltip element and add to the viewer canvas tooltip = document.createElement("div"); Object.assign(tooltip.style, { display: "none", position: "absolute", zIndex: 10, pointerEvents: "none", backgroundColor: "rgba(255, 255, 255, 0.75)", color: "black", padding: "0.1em", fontFamily: "sans-serif" }); stage.viewer.container.appendChild(tooltip); // listen to `hovered` signal to move tooltip around and change its text stage.signals.hovered.add(function (pickingProxy) { if (pickingProxy && (Object.prototype.toString.call(pickingProxy.picker) === '[object Array]' )){ var sphere = pickingProxy.sphere; var cp = pickingProxy.canvasPosition; tooltip.innerText = pickingProxy.picker[pickingProxy.pid]; tooltip.style.bottom = cp.y + 7 + "px"; tooltip.style.left = cp.x + 8 + "px"; tooltip.style.fontSize = "smaller"; tooltip.style.display = "block"; }else{ tooltip.style.display = "none"; } }); stage.signals.clicked.add(function (pickingProxy) { if (pickingProxy && (Object.prototype.toString.call(pickingProxy.picker) === '[object Array]' )){ var innerText = pickingProxy.picker[pickingProxy.pid]; mysocket.send( innerText); } }); """ colourgradstrs = "colourgradvalarray = new Array(%s)\n" % fomln # if displaying phases from map coefficients together with fom values then for g, colourgradarray in enumerate(colourgradarrays): self.colourgradientvalues = [] for j, e in enumerate(colourgradarray): self.colourgradientvalues.append([colourscalararray[j], e]) self.colourgradientvalues = roundoff(self.colourgradientvalues) fom = fomarrays[g] colourgradstr = [] for j, val in enumerate(self.colourgradientvalues): vstr = "" alpha = 1.0 gradval = "rgba(%s, %s, %s, %s)" % (val[1][0], val[1][1], val[1][2], alpha) if j % 10 == 0 or j == len(self.colourgradientvalues) - 1: vstr = str(roundoff(val[0], 2)) colourgradstr.append([vstr, gradval]) colourgradstrs += " colourgradvalarray[%s] = %s\n" % ( g, str(colourgradstr)) #negativeradiistr = "" #for ibin in range(self.nbin): # if self.workingbinvals[ibin] < 0.0: # negativeradiistr += "spherebufs[%d].setParameters({metalness: 1})\n" %ibin self.NGLscriptstr = """ // Microsoft Edge users follow instructions on // https://stackoverflow.com/questions/31772564/websocket-to-localhost-not-working-on-microsoft-edge // to enable websocket connection var pagename = location.pathname.substring(1); var mysocket = new WebSocket('ws://127.0.0.1:7894/'); mysocket.onopen = function (e) { mysocket.send('%s now connected via websocket to ' + pagename + '\\n'); }; mysocket.onclose = function (e) { mysocket.send('%s now disconnecting from websocket ' + pagename + '\\n'); }; // Log errors to debugger of your browser mysocket.onerror = function (error) { console.log('WebSocket Error ' + error); }; window.addEventListener( 'resize', function( event ){ stage.handleResize(); }, false ); var stage; var shape; var shapeComp; var repr; var AA = String.fromCharCode(197); // short for angstrom var DGR = String.fromCharCode(176); // short for degree symbol function createElement (name, properties, style) { // utility function used in for loop over colourgradvalarray var el = document.createElement(name) Object.assign(el, properties) Object.assign(el.style, style) Object.assign(el.style, { display: "block", position: "absolute", color: "black", fontFamily: "sans-serif", fontSize: "smaller", } ) return el } function addElement (el) { // utility function used in for loop over colourgradvalarray Object.assign(el.style, { position: "absolute", zIndex: 10 }) stage.viewer.container.appendChild(el) } function addDivBox(txt, t, l, w, h, bgcolour='rgba(255.0, 255.0, 255.0, 0.0)') { divbox = createElement("div", { innerText: txt }, { backgroundColor: bgcolour, color: 'rgba(0.0, 0.0, 0.0, 1.0)', top: t.toString() + "px", left: l.toString() + "px", width: w.toString() + "px", height: h.toString() + "px", } ); addElement(divbox) } var hklscene = function () { shape = new NGL.Shape('shape'); stage = new NGL.Stage('viewport', { backgroundColor: "grey", tooltip:false, fogNear: 100, fogFar: 100 }); stage.setParameters( { cameraType: "%s" } ); %s %s shapeComp = stage.addComponentFromObject(shape); repr = shapeComp.addRepresentation('buffer'); shapeComp.autoView(); repr.update() // if some radii are negative draw them with wireframe %s //colourgradvalarrays %s var ih = 3; var topr = 35 var topr2 = 10 var lp = 10 var wp = 40 var lp2 = lp + wp var gl = 3 var wp2 = gl var fomlabelheight = 25 if (colourgradvalarray.length === 1) { wp2 = 15 fomlabelheight = 0 } var wp3 = wp + colourgradvalarray.length * wp2 + 2 totalheight = ih*colourgradvalarray[0].length + 35 + fomlabelheight // make a white box on top of which boxes with transparent background are placed // containing the colour values at regular intervals as well as label legend of // the displayed miller array addDivBox("", topr2, lp, wp3, totalheight, 'rgba(255.0, 255.0, 255.0, 1.0)'); // print label of the miller array used for colouring addDivBox("%s", topr2, lp, wp, 20); if (colourgradvalarray.length > 1) { // print FOM label, 1, 0.5 and 0.0 values below colour chart fomtop = topr2 + totalheight - 18 fomlp = lp + wp fomwp = wp3 fomtop2 = fomtop - 13 // print the 1 number addDivBox("1", fomtop2, fomlp, fomwp, 20) // print the 0.5 number leftp = fomlp + 0.48 * gl * colourgradvalarray.length addDivBox("0.5", fomtop2, leftp, fomwp, 20) // print the FOM label addDivBox("%s", fomtop, leftp, fomwp, 20); // print the 0 number leftp = fomlp + 0.96 * gl * colourgradvalarray.length addDivBox("0", fomtop2, leftp, fomwp, 20) } for (j = 0; j < colourgradvalarray[0].length; j++) { rgbcol = colourgradvalarray[0][j][1]; val = colourgradvalarray[0][j][0] topv = j*ih + topr toptxt = topv - 5 // print value of miller array if present in colourgradvalarray[0][j][0] addDivBox(val, toptxt, lp, wp, ih); } // draw the colour gradient for (g = 0; g < colourgradvalarray.length; g++) { leftp = g*gl + lp + wp // if FOM values are supplied draw colour gradients with decreasing // saturation values as stored in the colourgradvalarray[g] arrays for (j = 0; j < colourgradvalarray[g].length; j++) { rgbcol = colourgradvalarray[g][j][1]; val = colourgradvalarray[g][j][0] topv = j*ih + topr addDivBox("", topv, leftp, wp2, ih, rgbcol); } } } document.addEventListener('DOMContentLoaded', function() { hklscene() }, false ); mysocket.onmessage = function (e) { //alert('Server: ' + e.data); var c var alpha var si mysocket.send('got ' + e.data ); // tell server what it sent us try { val = e.data.split(",") if (val[0] === "alpha") { ibin = parseInt(val[1]) alpha = parseFloat(val[2]) spherebufs[ibin].setParameters({opacity: alpha}) stage.viewer.requestRender() } if (val[0] === "colour") { ibin = parseInt(val[1]) si = parseInt(val[2]) colours[ibin][3*si] = parseFloat(val[3]) colours[ibin][3*si+1] = parseFloat(val[4]) colours[ibin][3*si+2] = parseFloat(val[5]) spherebufs[ibin].setAttributes({ color: colours[ibin] }) stage.viewer.requestRender() } if (val[0] === "Redraw") { stage.viewer.requestRender() } if (val[0] === "ReOrient") { mysocket.send( 'Reorienting ' + pagename ); sm = new Float32Array(16); for (j=0; j<16; j++) sm[j] = parseFloat(val[j + 2]) // first 2 are "ReOrient", "NGL\\n" var m = new NGL.Matrix4(); m.fromArray(sm); stage.viewerControls.orient(m); stage.viewer.requestRender(); } if (val[0] === "Reload") { // refresh browser with the javascript file cvorient = stage.viewerControls.getOrientation().elements msg = String(cvorient) mysocket.send('Current vieworientation:\\n, ' + msg ); mysocket.send( 'Refreshing ' + pagename ); window.location.reload(true); } if (val[0] === "Testing") { // test something new mysocket.send( 'Testing something new ' + pagename ); var newradii = radii[0].map(function(element) { return element*1.5; }); spherebufs[0].setAttributes({ radius: newradii }) stage.viewer.requestRender() } } catch(err) { mysocket.send('error: ' + err ); } }; """ % (self.__module__, self.__module__, self.cameratype, arrowstr, spherebufferstr, \ negativeradiistr, colourgradstrs, colourlabel, fomlabel) if self.jscriptfname: with open(self.jscriptfname, "w") as f: f.write(self.NGLscriptstr) self.ReloadNGL() def OnConnectWebsocketClient(self, client, server): #if not self.websockclient: self.websockclient = client self.mprint("Browser connected:" + str(self.websockclient), self.verbose) #else: # self.mprint( "Unexpected browser connection was rejected" ) def OnWebsocketClientMessage(self, client, server, message): if message != "": self.mprint(message, verbose=False) self.lastmsg = message if "Current vieworientation:" in message: # The NGL.Matrix4 with the orientation is a list of floats. self.viewmtrxelms = message[message.find("\n"):] sleep(0.2) self.mprint("Reorienting client after refresh:" + str(self.websockclient)) if not self.isnewfile: self.pendingmessage = u"ReOrient, NGL" + self.viewmtrxelms self.isnewfile = False def WebBrowserMsgQueue(self): while True: sleep(1) if hasattr(self, "pendingmessage") and self.pendingmessage: self.SendWebSockMsg(self.pendingmessage) self.pendingmessage = None def StartWebsocket(self): self.server = WebsocketServer(7894, host='127.0.0.1') if not self.server: raise Sorry("Could not connect socket to web browser") self.server.set_fn_new_client(self.OnConnectWebsocketClient) self.server.set_fn_message_received(self.OnWebsocketClientMessage) self.wst = threading.Thread(target=self.server.run_forever) self.wst.daemon = True self.wst.start() self.msgqueuethrd = threading.Thread(target=self.WebBrowserMsgQueue) self.msgqueuethrd.daemon = True self.msgqueuethrd.start() def SendWebSockMsg(self, msg): #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) ) #print "self.server.clients: ", self.server.clients #print "self.websockclient: ", if self.websockclient: while "Refreshing" in self.lastmsg: sleep(0.5) self.lastmsg = "" self.server.send_message(self.websockclient, msg) else: self.OpenBrowser() def SetOpacity(self, bin, alpha): if bin > self.nbin: self.mprint("There are only %d bins of data present" % self.nbin) return msg = u"alpha, %d, %f" % (bin, alpha) self.SendWebSockMsg(msg) def RedrawNGL(self): self.SendWebSockMsg(u"Redraw, NGL\n") def ReloadNGL(self): # expensive as javascript may be several Mbytes large self.mprint("Rendering NGL JavaScript...") self.SendWebSockMsg(u"Reload, NGL\n") def OpenBrowser(self): NGLlibpath = libtbx.env.under_root( os.path.join("modules", "cctbx_project", "crys3d", "hklview", "ngl.js")) htmlstr = self.hklhtml % (NGLlibpath, os.path.abspath( self.jscriptfname)) htmlstr += self.htmldiv with open(self.hklfname, "w") as f: f.write(htmlstr) self.url = "file://" + os.path.abspath(self.hklfname) self.mprint( "Writing %s and connecting to its websocket client" % self.hklfname, self.verbose) if self.UseOSBrowser: webbrowser.open(self.url, new=1) self.isnewfile = False def TestNewFunction(self): self.SendWebSockMsg(u"Testing, NGL\n")
class websocketserver: cameras = {} tags = {} users = {} calibration = {} port = 8001 # Called for every client connecting (after handshake) def new_client_connection(self, client, server): print("New client connected and was given id %d" % client['id'] + " and address " + str(client['address'])) server.send_message(client, "Client connected succesfully") # Called for every client disconnecting def client_left(self, client, server): print("Client(%d) disconnected" % client['id']) # Remove client from its list # TODO better delete (remove points etc...) if (str(client['address']) in self.cameras): print "Camera disconnected : " + str(client['address']) del self.cameras[str(client['address'])] elif (str(client['address']) in self.users): # Remove Tag assignement because User left print "User disconnected : " + str(client['address']) self.users[str(client['address'])].removeTag() del self.users[str(client['address'])] elif (str(client['address']) in self.calibration): print "Calibration disconnected : " + str(client['address']) del self.calibration[str(client['address'])] elif (str(client['address']) in self.tags): print "Tag disconnected : " + str(client['address']) # Remove Tag assignement to User because Tag left AND kill 3D point for key in self.users: if self.users[key].tag == self.tags[str(client['address'])]: self.users[key].removeTag() del self.tags[str(client['address'])] # Called when a client sends a message def message_received(self, client, server, message): self.parseMessage(client, message) def __init__(self, host='127.0.0.1'): self.server = WebsocketServer(self.port, host) self.server.set_fn_new_client(self.new_client_connection) self.server.set_fn_client_left(self.client_left) self.server.set_fn_message_received(self.message_received) self.server.run_forever() def parseMessage(self, client, message): """ Check who is the message from to redirect it to User / Tag / Camera / Calibration or create a new instance of User / Tag / Camera / Calibration :param client: :param message: :return: """ if self.cameras.has_key(str(client['address'])): #print "Message from Camera" self.cameras[str(client['address'])].push(message) # Update all cameras counters #Todo: Change this method for checking all cameras for lost point (auto check inside point2D ?) for key in self.cameras.keys(): self.cameras[key].update() elif self.users.has_key(str(client['address'])): print "Message from User" elif self.tags.has_key(str(client['address'])): print "Message from Tag" elif self.calibration.has_key(str(client['address'])): self.calibration[str(client['address'])].push(message) print "Message from Calibration" # This message is coming from an unknown client else: if message.split("-")[0] == "camera": self.cameras[str(client['address'])] = Camera( client, message.split("-")[1]) # Add Observers linking every user to every camera's update for key in self.users: if isinstance(self.users[key], User): self.cameras[str( client['address'])].new2DPointNotifier.addObserver( self.users[key].position.newPoint2DObserver) self.cameras[str( client['address'] )].point2DdeletedNotifier.addObserver( self.users[key].position.point2DDeletedObserver) elif message.split("-")[0] == "tag": self.tags[str(client['address'])] = Tag( self.server, client, message.split("-")[1]) for key in self.users: if isinstance(self.users[key], User): # Assign a Tag to User with no Tag if self.users[key].tag == None: self.users[key].setTag(self.tags[str( client['address'])]) elif message.split("-")[0] == "user": user = User(self.server, client, message.split("-")[1]) self.users[str(client['address'])] = user # Add Observers linking every user to every camera's update for key in self.cameras: if isinstance(self.cameras[key], Camera): self.cameras[key].new2DPointNotifier.addObserver( user.position.newPoint2DObserver) self.cameras[key].point2DdeletedNotifier.addObserver( user.position.point2DDeletedObserver) for key in self.tags: if isinstance(self.tags[key], Tag): # Assign a Tag to new User if self.tags[key].isAssigned() == False: user.setTag(self.tags[key]) elif message == "calibration": if (len(self.tags) > 0): self.calibration[str(client['address'])] = Calibration( self.server, client, self.cameras, self.tags.values()[0]) else: self.server.send_message( client, "Please connect a Tag first, and start Calibration again." )
class WUI(): def __init__(self, theme_path, browser_path, log_lv=logging.DEBUG, exit_time=10, host='0.0.0.0', port=6688): logging.basicConfig(level=log_lv) self.port = port self.CREATE_NO_WINDOW = 0x08000000 self.exit_time = exit_time self.theme_path = theme_path self.browser_path = browser_path self.User_List = [] self.host = host self.init_stat = 0 self.Recv_Message_Hook = list() self.Join_Hook = list() self.Leave_Hook = list() self.init_ws() def init_ws(self): self.ws = WebsocketServer(self.port, host=self.host) self.ws.set_fn_message_received(self.message_received) self.ws.set_fn_client_left(self.user_leave) self.ws.set_fn_new_client(self.user_join) t = Thread(target=self.Exit_Check) t.start() def Send_Order(self, client, order, detail): temp = dict() temp['order'] = order temp['detail'] = detail temp = json.dumps(temp) self.ws.send_message(client, temp) def Broadcast(self, order, detail): temp = dict() temp['order'] = order temp['detail'] = detail temp = json.dumps(temp) self.ws.send_message_to_all(temp) def Add_Recv_Msg_Hook(self, msg_txt, callback, send_msg_to_fn=1): self.Add_WS_Hook('rec', msg_txt, callback, send_msg_to_fn) def Add_Join_Hook(self, callback='', msg_txt='', send_msg_to_fn=1): self.Add_WS_Hook('join', msg_txt, callback, send_msg_to_fn) def Add_Leave_Hook(self, msg_txt, callback, send_msg_to_fn=1): self.Add_WS_Hook('leave', msg_txt, callback, send_msg_to_fn) def Add_WS_Hook(self, hook_type, msg_txt, callback, send_msg_to_fn=1): try: mb = dict() mb['txt'] = msg_txt mb['callback'] = callback mb['send_msg_to_fn'] = send_msg_to_fn if hook_type == 'rec': self.Recv_Message_Hook.append(mb) if hook_type == 'join': self.Join_Hook.append(mb) if hook_type == 'leave': self.Leave_Hook.append(mb) except: print("Add_Hook_Error:" + format(msg_txt)) def Run_Hook(self, hook_type, client, message): hook_list = list() if hook_type == 'rec': hook_list = self.Recv_Message_Hook if hook_type == 'join': hook_list = self.Join_Hook if hook_type == 'leave': hook_list = self.Leave_Hook for mb in hook_list: try: if hook_type == 'rec': if mb['send_msg_to_fn'] == 1: try: msg_o = json.loads(message) order = msg_o['order'] detail = msg_o['detail'] if order == mb['txt']: mb['callback'](client, detail) except Exception as e: print(e) logging.info("Message:" + format(message) + "JSON_Decode_Error") else: if message == mb['txt']: mb['callback']() else: if mb['send_msg_to_fn'] == 1: mb['callback'](client) else: mb['callback']() except: print('Hook_Error:' + mb) def message_received(self, client, server, message): logging.debug("WS_Rec_Msg:" + format(message)) self.Run_Hook(hook_type='rec', client=client, message=message) def user_leave(self, client, server): uid = client['id'] del self.User_List[self.User_List.index(uid)] self.Run_Hook(hook_type='leave', client=client, message='') def user_join(self, client, server): logging.debug("User_Join:" + format(client)) uid = client['id'] self.User_List.append(uid) self.Run_Hook(hook_type='join', client=client, message=client) def Start_WS(self, start_browser=1): logging.info("Start_WS_Server:" + self.host + ":" + format(self.port)) t = Thread(target=self.ws.run_forever) t.start() if start_browser == 1: self.Start_Chrome() def Start_Chrome(self): chrome_path = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' Self_chrome_path = self.browser_path if os.path.isfile(chrome_path) == True: order = [chrome_path, '%s', self.theme_path] subprocess.Popen(order) else: order = [Self_chrome_path, '%s', self.theme_path] subprocess.Popen(order) def Quit(self): pid = os.getpid() subprocess.Popen(args=['taskkill', '/f', '/PID', str(pid)], creationflags=self.CREATE_NO_WINDOW) def Exit_Check(self): zero_time = time.time() while 1: if len(self.User_List) != 0: zero_time = time.time() if zero_time != 0: af_time = time.time() - zero_time if af_time > self.exit_time: self.Quit() time.sleep(0.3)
class RosConsumer: # Initialization function # The actual initialization def __init__(self, host): t = threading.Thread(target=self.run_server) self.reload = False self.server = None self.client = None self.host = host t.start() # Explicit initialization functions # Class method, so user can call it without instantiation @classmethod def initWeb(cls, host): new_instance = cls(host) return new_instance # Gets called when there is an incoming message from the client def handle(self, client, server, message): if (message == "#pong"): self.server.send_message(self.client, "#ping") return try: # Once received turn the reload flag up and send it to execute_thread function message_array = np.fromstring(message, dtype=int, sep=',') message_array.resize(240, 320, 3) frame_int64 = message_array frame_bgr = np.uint8(frame_int64) self.frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB) self.server.send_message(self.client, "#ack") self.reload = True except: pass # Function that gets called when the connected closes def getImage(self): return self.frame_rgb def connected(self, client, server): self.client = client # Initialize the ping message self.server.send_message(self.client, "#ping") print(client, 'connected') # Function that gets called when the connected closes def handle_close(self, client, server): print(client, 'closed') def run_server(self): self.server = WebsocketServer(port=60002, host=self.host) self.server.set_fn_new_client(self.connected) self.server.set_fn_client_left(self.handle_close) self.server.set_fn_message_received(self.handle) self.server.run_forever() def callback(self, data): # Used to convert between ROS and OpenCV images br = CvBridge() # Output debugging information to the terminal rospy.loginfo("receiving video frame") # Convert ROS Image message to OpenCV image current_frame = br.imgmsg_to_cv2(data) _, im_arr = cv2.imencode( '.jpg', current_frame) # im_arr: image in Numpy one-dim array format. im_bytes = im_arr.tobytes() im_b64 = base64.b64encode(im_bytes) try: self.server.send_message(self.client, im_b64) except: pass def receive_message(self): # Tells rospy the name of the node. # Anonymous = True makes sure the node has a unique name. Random # numbers are added to the end of the name. rospy.init_node('video_sub_py', anonymous=True) # Node is subscribing to the video_frames topic rospy.Subscriber('video_frames', Image, self.callback) # spin() simply keeps python from exiting until this node is stopped rospy.spin()
class IgorServer: def __init__(self, api=None, config=CONFIG): """ :param api: api dictionary containing handler functions :param config: config object """ if not isinstance(api, dict): raise Exception("API config object must be dictionary object") else: self.paths = api self.config = config self.file_server_threat = None self.streams = {} self.clients = {} self.timeouts = {} self.sessions = {} self.processes = {} self.scope = {} self.loop = asyncio.get_event_loop() self.server = WebsocketServer(config['port'], host=config['host'], loglevel=config['logging']['level']) self.server.set_fn_new_client(self.__register_new_client) self.server.set_fn_client_left(self.__unregister_client) self.server.set_fn_message_received(self.__main_handler) self.session_delete_timeout = 10.0 self.logger = None self.__configure(config) def __configure(self, config): if config['file_server_config']['enable']: self.file_server_threat = run_file_server( config['file_server_config']['port'], config['file_server_config']['root_directory']) logger = logging.getLogger(__name__) log_handler = None if config['logging']['file_name']: log_handler = logging.FileHandler(config['logging']['file_name']) else: log_handler = logging.StreamHandler() log_handler.setFormatter( logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')) logger.addHandler(log_handler) logger.setLevel(level=config['logging']['level']) self.logger = logger def run_forever(self): self.logger.debug("Starting server") for process_id, process in self.processes.items(): thread = process['thread'] thread.daemon = True print('Starting thread') thread.start() self.server.run_forever() def __register_new_client(self, client, server): if client.get('id', None) is None: raise Exception('Trying to register client without id') if self.clients.get(client['id'], None) is not None: raise Exception('Client with id: "' + client['id'] + '" already connected') self.logger.debug('New client: "' + str(client['id']) + '" registered') self.clients[client['id']] = client self.sessions[client['id']] = {} def __unregister_client(self, client, server): self.logger.debug('Client: "' + str(client['id']) + '" unregistered') del self.clients[client['id']] def delete_session(client_id, igor_server): _client = igor_server.clients.get(client_id, None) if _client is None: del self.sessions[client_id] timeout = Timer(self.session_delete_timeout, delete_session, [client['id'], self]) self.timeouts[client['id']] = timeout timeout.start() def __add_new_stream(self, stream_id, client): self.logger.debug('Stream added') stream = Stream(self, client, stream_id, self.__remove_stream) self.streams[stream_id] = stream return stream def __remove_stream(self, real_self, stream_id): self.logger.debug('Stream removed') del real_self.streams[stream_id] def add_process(self, process_id, thread): """ Adds new process to server - it won't be started immediately, to start it run: run_forever method :process_id: id of the process :thread: thread object of the process """ output = ProcessOutput(process_id, self, self._IgorServer__remove_process) thread.process_id = process_id thread.output = output thread.scope = self.scope thread.sessions = self.sessions self.processes[process_id] = {'thread': thread, 'output': output} def __remove_process(self, real_self, process_id): self.logger.debug('Process with id: "' + process_id + '" finished and is removed') real_self.processes[process_id]['thread'].kill() del real_self.processes[process_id] def __send_erorr(self, client, message, code=500): self.logger.error(message) self.server.send_message(client, json.dumps({ 'error': message, 'code': code })) def __introduce_self(self, client, stream_data): client_id = stream_data.get('client_id', None) if client_id is None: self.__send_erorr(client, 'No client_id for introduce_self action', code=400) return else: client_session = self.sessions.get(client_id, None) if client_session is not None: timeout = self.timeouts.get(client['id'], None) if timeout is not None: timeout.cancel() else: client_session = self.sessions[client['id']] del self.sessions[client['id']] del self.clients[client['id']] self.clients[stream_data['client_id']] = client self.sessions[stream_data['client_id']] = client_session client['id'] = stream_data['client_id'] def __main_handler(self, client, server, message): try: message = json.loads(message) stream_id = message.get('streamId', None) if stream_id is None: self.__send_erorr(client, 'No streamId specified', code=400) else: stream_data = message.get('data', None) action = message.get('action', None) if action is None: self.__send_erorr(client, 'No action specified', code=400) return if action == 'introduce_self': self.__introduce_self(client, stream_data) return handler_function = self.paths.get(action, None) if handler_function is None: self.__send_erorr(client, 'No handler for action: "' + action + '"', code=400) return stream = self.streams.get(stream_id, None) if stream is None: stream = self.__add_new_stream(stream_id, client) session = self.sessions.get(client['id'], None) self.loop.run_until_complete( handler_wrapper(handler_function, stream, stream_data, session, self.scope)) except SystemExit: loggself.loggering.debug('System exit exception shutting down') if self.file_server_threat is not None: self.file_server_threat.kill() _thread.interrupt_main() except Exception as error: self.logger.error(str(error)) self.__send_erorr(client, 'Undefined error occured while handling message', code=503) raise error
class websocket_server_impl(server_parent): def __init__(self, port, name): super().__init__(name) self.server = WebsocketServer(port) self.server.set_fn_client_left(self.client_left) self.server.set_fn_message_received(self.get_message) self.server.run_forever() def get_message(self, client, server, message): """ get message in some way,child need implement it """ # client = args[0] # server = args[1] # message = args[2] self.filter(json.loads(message), client) def login(self, data: dict, *args, **kwargs): """ when a client send login to server,check client and name :param data : { CODE: LOGIN, LOGIN_ID: id, INFO :{ LOGIN_NAME: name } TIMESTAMP: int(time.time() / 1000) } :return: """ # load data from info client = args[0][0] id = data[LOGIN_ID] name = data[INFO][LOGIN_NAME] # if id exist,it means client want to login again and get its data before. # TODO password is nessary if id != None and id in self.user_dict: # switch to login self.user_dict[id].switch_type_login() # set client self.user_dict[id].set_client(client) # send response to client self.send_to_client( id, generate_json.generate_login_response( self.user_dict[id].get_user_id(), self.user_dict[id].get_name())) # if not exist,give it a new one else: # new websocket user user = websocket_user_impl(id, name) # set client user.set_client(client) # input to user id, name = self.input_user(user) # send to client self.send_to_client( id, generate_json.generate_login_response(id, name)) def client_left(self, client, server): """ when clinet left there are two situation 1.left natural, server need delete its data 2.left by unknown problem, server need keep its data :param client: the client which left :param server: self.server :return: """ # TODO rewrite # close connection # id = self.get_number_by_client(client) if id != -1: self.close_client(id) print(f"client:{id} close") # charge if it is left natural room_number = self.get_room_by_number(id) if room_number == -1 and id != -1: self.delete_client(id) print(f"client:{id} delete") def send_to_client(self, user_id: str, msg: str): """ :param user_id: user's id :param msg: message :return: """ self.server.send_message(self.user_dict[user_id].get_client(), msg)
class websocketserver: cameras = {} tags = {} users = {} calibration = {} port=8001 # Called for every client connecting (after handshake) def new_client_connection(self, client, server): print("New client connected and was given id %d" % client['id'] +" and address " + str(client['address'])) server.send_message(client, "Client connected succesfully") # Called for every client disconnecting def client_left(self, client, server): print("Client(%d) disconnected" % client['id']) # Remove client from its list # TODO better delete (remove points etc...) if(str(client['address']) in self.cameras): print "Camera disconnected : " + str(client['address']) del self.cameras[str(client['address'])] elif(str(client['address']) in self.users): # Remove Tag assignement because User left print "User disconnected : " + str(client['address']) self.users[str(client['address'])].removeTag() del self.users[str(client['address'])] elif(str(client['address']) in self.calibration): print "Calibration disconnected : " + str(client['address']) del self.calibration[str(client['address'])] elif(str(client['address']) in self.tags): print "Tag disconnected : " + str(client['address']) # Remove Tag assignement to User because Tag left AND kill 3D point for key in self.users: if self.users[key].tag == self.tags[str(client['address'])]: self.users[key].removeTag() del self.tags[str(client['address'])] # Called when a client sends a message def message_received(self, client, server, message): self.parseMessage(client, message) def __init__(self, host='127.0.0.1'): self.server = WebsocketServer(self.port, host) self.server.set_fn_new_client(self.new_client_connection) self.server.set_fn_client_left(self.client_left) self.server.set_fn_message_received(self.message_received) self.server.run_forever() def parseMessage(self, client, message): """ Check who is the message from to redirect it to User / Tag / Camera / Calibration or create a new instance of User / Tag / Camera / Calibration :param client: :param message: :return: """ if self.cameras.has_key(str(client['address'])): #print "Message from Camera" self.cameras[str(client['address'])].push(message) # Update all cameras counters #Todo: Change this method for checking all cameras for lost point (auto check inside point2D ?) for key in self.cameras.keys(): self.cameras[key].update() elif self.users.has_key(str(client['address'])): print "Message from User" elif self.tags.has_key(str(client['address'])): print "Message from Tag" elif self.calibration.has_key(str(client['address'])): self.calibration[str(client['address'])].push(message) print "Message from Calibration" # This message is coming from an unknown client else: if message.split("-")[0] == "camera": self.cameras[str(client['address'])] = Camera(client, message.split("-")[1]) # Add Observers linking every user to every camera's update for key in self.users: if isinstance(self.users[key], User): self.cameras[str(client['address'])].new2DPointNotifier.addObserver(self.users[key].position.newPoint2DObserver) self.cameras[str(client['address'])].point2DdeletedNotifier.addObserver(self.users[key].position.point2DDeletedObserver) elif message.split("-")[0] == "tag": self.tags[str(client['address'])] = Tag(self.server, client, message.split("-")[1]) for key in self.users: if isinstance(self.users[key], User): # Assign a Tag to User with no Tag if self.users[key].tag == None: self.users[key].setTag(self.tags[str(client['address'])]) elif message.split("-")[0] == "user": user = User(self.server, client, message.split("-")[1]) self.users[str(client['address'])] = user # Add Observers linking every user to every camera's update for key in self.cameras: if isinstance(self.cameras[key], Camera): self.cameras[key].new2DPointNotifier.addObserver(user.position.newPoint2DObserver) self.cameras[key].point2DdeletedNotifier.addObserver(user.position.point2DDeletedObserver) for key in self.tags: if isinstance(self.tags[key], Tag): # Assign a Tag to new User if self.tags[key].isAssigned() == False: user.setTag(self.tags[key]) elif message == "calibration": if(len(self.tags)>0): self.calibration[str(client['address'])] = Calibration(self.server, client, self.cameras, self.tags.values()[0]) else: self.server.send_message(client, "Please connect a Tag first, and start Calibration again.")