async def sendUDPMessage(self, message): """Send the UDP message to the bulb.""" connid = hex(int(time() * 10000000))[2:] data = None # overall 10 sec. for time out timeout = 10 send_interval = 0.5 max_send_datagrams = int(timeout / send_interval) try: _LOGGER.debug( "[wizlight {}, connid {}] connecting to UDP port with send_interval of {} sec.." .format(self.ip, connid, send_interval)) stream = await asyncio.wait_for( asyncio_dgram.connect((self.ip, self.port)), timeout) _LOGGER.debug( "[wizlight {}, connid {}] listening for response datagram". format(self.ip, connid)) receive_task = asyncio.create_task( self.receiveUDPwithTimeout(stream, timeout)) for i in range(max_send_datagrams): _LOGGER.debug( "[wizlight {}, connid {}] sending command datagram {}: {}". format(self.ip, connid, i, message)) asyncio.create_task(stream.send(bytes(message, "utf-8"))) done, pending = await asyncio.wait([receive_task], timeout=send_interval) if done: break await receive_task data = receive_task.result() except asyncio.TimeoutError: _LOGGER.debug( "[wizlight {}, connid {}] Failed to do UDP call(s) to wiz light - Timeout Error!" .format(self.ip, connid), exc_info=False, ) raise WizLightTimeOutError("The request to the bulb timed out") finally: try: stream.close() except UnboundLocalError: raise WizLightConnectionError( "Bulb is offline or IP address is not correct.") if data is not None and len(data) is not None: resp = json.loads(data.decode()) if "error" not in resp: _LOGGER.debug( "[wizlight {}, connid {}] response received: {}".format( self.ip, connid, resp)) return resp else: # exception should be created raise ValueError("Can't read response from the bulb. Debug:", resp)
async def send_udp(ip: str, message: str) -> str: """Send the UDP message to the bulb.""" # overall 10 sec. for time out timeout = 2 send_interval = 0.5 max_send_datagrams = 2 port = 38899 try: stream = await asyncio.wait_for(asyncio_dgram.connect((ip, port)), timeout) receive_task = asyncio.create_task(receive_udp( stream, timeout, )) i = 0 while not receive_task.done() and i < max_send_datagrams: asyncio.create_task(stream.send(bytes(message, "utf-8"))) await asyncio.sleep(send_interval) i += 1 await receive_task data = receive_task.result() finally: try: stream.close() except UnboundLocalError: raise ConnectionError( "Bulb is offline or IP address is not correct.") if data is not None and len(data) is not None: return data.decode()
async def sendUDPMessage(self, message, timeout=60, send_interval=0.5, max_send_datagrams=100): """Send the UDP message to the bulb.""" connid = hex(int(time() * 10000000))[2:] data = None try: _LOGGER.debug( "[wizlight {}, connid {}] connecting to UDP port".format( self.ip, connid)) stream = await asyncio.wait_for( asyncio_dgram.connect((self.ip, self.port)), timeout) _LOGGER.debug( "[wizlight {}, connid {}] listening for response datagram". format(self.ip, connid)) receive_task = asyncio.create_task( self.receiveUDPwithTimeout(stream, timeout)) i = 0 while not receive_task.done() and i < max_send_datagrams: _LOGGER.debug( "[wizlight {}, connid {}] sending command datagram {}: {}". format(self.ip, connid, i, message)) asyncio.create_task(stream.send(bytes(message, "utf-8"))) await asyncio.sleep(send_interval) i += 1 await receive_task data = receive_task.result() except asyncio.TimeoutError: _LOGGER.exception( "[wizlight {}, connid {}] Failed to do UDP call(s) to wiz light" .format(self.ip, connid), exc_info=False, ) finally: try: stream.close() except UnboundLocalError: raise WizLightConnectionError( "Bulb is offline or IP address is not correct") if data is not None and len(data) is not None: resp = json.loads(data.decode()) if "error" not in resp: _LOGGER.debug( "[wizlight {}, connid {}] response received: {}".format( self.ip, connid, resp)) return resp else: # exception should be created raise ValueError("Can't read response from the bulb. Debug:", resp)
async def raknet_status(host, port): # Should work on all BE servers if port is None: port = 19132 start = perf_counter() try: stream = await asyncio.wait_for(asyncio_dgram.connect((host, port)), TIMEOUT) #data = b'\x01' + struct.pack('>q', 0) + bytearray.fromhex('00 ff ff 00 fe fe fe fe fd fd fd fd 12 34 56 78') await asyncio.wait_for( stream.send( b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x124Vx' ), TIMEOUT) data, _ = await asyncio.wait_for(stream.recv(), TIMEOUT) except BaseException: return DEFAULT finally: try: stream.close() except BaseException: pass latency = round((perf_counter() - start) * 1000, 2) data = data[1:] name_length = struct.unpack('>H', data[32:34])[0] data = data[34:34 + name_length].decode().split(';') s_dict = DEFAULT.copy() s_dict['online'] = True s_dict['players_online'] = int(data[4]) s_dict['players_max'] = int(data[5]) s_dict['latency'] = latency s_dict['version'] = { 'brand': data[0], # string 'software': None, # string, assumes server is vanilla bc pocketmine + nukkit use query 'protocol': f'raknet {data[2]}', 'method': 'raknet' } s_dict['motd'] = data[1] try: s_dict['map'] = data[7] s_dict['gamemode'] = data[8] except IndexError: pass return s_dict
async def infoListener(self): print("Listening for info...") self.infoStream = await asyncio.wait_for( asyncio_dgram.connect((self.bulbIp, self.listenerPort)), self.timeout) infoData = asyncio.create_task(self.recData(self.infoStream)) await infoData resInfoData = infoData.result() self.infoStream.close if resInfoData and len(resInfoData): return resInfoData.decode()
async def async_update(self): logger.info("updating " + self._name) cypher = encrypt(self._getter + '\0', self._key) try: sock = await asyncio.wait_for(asyncio_dgram.connect((self._ip, 54321)), 5) await asyncio.wait_for(sock.send(cypher), 5) cypher, [host, port] = await asyncio.wait_for(sock.recv(), 5) message = decrypt(cypher, self._key) logger.info("%s -> %s:%s -> %s", self._getter, self._ip, 54321, message) self._state = float(message) except asyncio.TimeoutError: logger.error("Timeout error %s", self._getter) except: logger.error("Some other arror") finally: sock.close()
async def connect(self, name: str, host: str, port: int = 22023, gameVersion: tuple = None) -> None: """ Connects to the given server via UDP and starts listening for data on success Args: name (str): Name which will be displayed in Among Us host (str): Host/address of the server to connect to port (int): Port of the server to connect to, defaults to 22023 gameVersion (tuple): The version of the game running on the server Raises: Exception: Something went wrong, never happened while testing """ self._sequence_ids = {} self.net_ids = dotdict({}) self.host, self.port, self.name, self.gameVersion = host, port, name, gameVersion try: self.socket = await asyncio.wait_for( asyncio_dgram.connect((host, port)), timeout=self.connectTimeout / 1000 ) except asyncio.TimeoutError: logging.debug("Timeout when connecting to the server...") self.result = ConnectionException( f"Timeout connecting to {host}:{port}", DisconnectReason.Timeout ) await self.disconnect(True) except Exception as e: logger.exception(e) raise else: logger.info(f"Connected to {host}:{port} [{self.region}]") await self.send( HelloPacket.create(gameVersion=gameVersion, name=self.name) ) self.closed = False self._reader_task = asyncio.create_task(self._reader()) try: await asyncio.wait_for( self.wait_until_ready(), timeout=self.recvTimeout / 1000 ) except asyncio.TimeoutError: self.result = ConnectionException( "Timed out waiting for messages", DisconnectReason.Timeout ) await self.disconnect(True)
async def async_setup_platform(hass, config, add_entities, discovery_info=None): """Set up the sensor platform.""" entities = [] for k, v in config.items(): if k == 'hosts': for h in v: host = {} for p, r in h.items(): host[p] = r supported = [] try: key = unhexlify(host['key']) cypher = encrypt('(discovery)\0', key) sock = await asyncio.wait_for(asyncio_dgram.connect((host['ip'], 54321)), 5) await asyncio.wait_for(sock.send(cypher), 5) cypher, [source_host, port] = await asyncio.wait_for(sock.recv(), 5) message = decrypt(cypher, key) logger.info("discover -> %s:%s -> %s", host['ip'], 54321, message) supported = sexpdata.loads(message) except: logger.exception("Failed to init device %s", host['ip']) if 'temperature-read' in supported: entities.append(HHGSensor("hhg_" + host['ip'] + '_temperature', host['ip'], host['key'], '(temperature-read)', TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE)) if 'humidity-read' in supported: entities.append(HHGSensor("hhg_" + host['ip'] + '_humidity', host['ip'], host['key'], '(humidity-read)', UNIT_PERCENTAGE, DEVICE_CLASS_HUMIDITY)) if 'light-read' in supported: entities.append(HHGSensor("hhg_" + host['ip'] + '_light', host['ip'], host['key'], '(light-read)', 'lx', DEVICE_CLASS_ILLUMINANCE)) if 'co2-read' in supported: entities.append(HHGSensor("hhg_" + host['ip'] + '_co2', host['ip'], host['key'], '(co2-read)', CONCENTRATION_PARTS_PER_MILLION, 'air_quality')) if 'tvoc-read' in supported: entities.append(HHGSensor("hhg_" + host['ip'] + '_tvoc', host['ip'], host['key'], '(tvoc-read)', CONCENTRATION_PARTS_PER_MILLION, 'air_quality')) logger.info(entities) add_entities(entities)
async def sendCommand(self, message): # message = r'{"method":' + message + r',"params":{}}' maxTries = 100 sleepInterval = 0.5 dataStream = await asyncio.wait_for( asyncio_dgram.connect((self.bulbIp, self.bulbPort)), self.timeout) receive = asyncio.create_task(self.recData(dataStream)) i = 0 while not receive.done() and i < maxTries: asyncio.create_task(dataStream.send(bytes(message, "utf-8"))) await asyncio.sleep(0.5) i += 1 await receive resData = receive.result() dataStream.close if resData and len(resData): return resData.decode()
async def connect(self, addr, timeout=3): self.timeout = timeout conn = asyncio_dgram.connect((addr[0], addr[1])) self.stream = await asyncio.wait_for(conn, timeout=self.timeout)