async def open_tunnel(self, port: int) -> Tuple[Status, Optional[int]]: """Open tunnel to the specified 'port'. Return (sessionId, None) on success, otherwise return (None, error)""" request = api.Message() request.commutator.open_tunnel = port self.send(request) # it shouldn't take much time response, _ = await self.wait_message(timeout=0.1) if not response: return CommutatorI.Status.RESPONSE_TIMEOUT, None # Note: once 'open_tunnel_report' is passed through 'sessions_mux', # it creates a new related session object, that can be retreived by # 'get_channel_for_session()' tunnel_id = get_message_field(response, ["commutator", "open_tunnel_report"]) if tunnel_id is None: error = get_message_field(response, ["commutator", "open_tunnel_failed"]) if not error: return CommutatorI.Status.UNEXPECTED_RESPONSE, None self._logger.warning( f"Failed to open tunnel to port #{port}: {error}") return CommutatorI.Status.convert(error), None return CommutatorI.Status.SUCCESS, tunnel_id
async def get_total_slots(self) -> (bool, int): """Return total number of devices, attached to this commutator""" request = api.Message() request.commutator.total_slots_req = True self.send(request) response, _ = await self.wait_message() if not response: return False, 0 total_slots = get_message_field(response, ["commutator", "total_slots"]) return total_slots is not None, total_slots
async def login(self, login: str, password: str) -> (bool, Optional[int]): """Try to open privileged session as user with the specified 'login' and 'password'. Return tuple (status, token)""" message = api.admin.Message() login_req = message.access.login login_req.login = login login_req.password = password self.send(message) response, _ = await self.wait_message() token: Optional[int] = get_message_field(response, ["access", "success"]) return token is not None, token
async def login(self, login: str, password: str) -> (int, int, Optional[str]): """Try to open privileged session as user with the specified 'login' and 'password'. Return tuple (port, session_id, error_string)""" message = api.Message() login_req = message.accessPanel.login login_req.login = login login_req.password = password self.socket.send(message) response, _ = await self.socket.wait_message() if not response: return 0, 0, "response timeout" access_granted = get_message_field(response, ["accessPanel", "access_granted"]) if access_granted: return access_granted.port, access_granted.session_id, None error: Optional[str] = get_message_field( response, ["accessPanel", "access_rejected"]) return 0, 0, error if error is not None else "Unexpected response"
async def close_tunnel(self, tunnel_id: int) -> Status: request = api.Message() request.commutator.close_tunnel = tunnel_id self.send(request) # it shouldn't take much time response, _ = await self.wait_message(timeout=0.2) if not response: return CommutatorI.Status.RESPONSE_TIMEOUT status = get_message_field(response, ["commutator", "close_tunnel_status"]) if status is None: return CommutatorI.Status.UNEXPECTED_RESPONSE return CommutatorI.Status.convert(status)
async def get_module_info(self, slot_id: int)\ -> Optional[ModuleInfo]: """Return information about module, installed into the specified 'slot_id'. """ request = api.Message() request.commutator.module_info_req = slot_id self.send(request) response, _ = await self.wait_message() if not response: return None module_info = get_message_field(response, ["commutator", "module_info"]) if not module_info: return None info = ModuleInfo.from_protubuf(module_info) return info
async def get_all_modules(self) -> Optional[List[ModuleInfo]]: """Return all modules, attached to commutator. Modules received will be stored to a local cache""" success, total_slots = await self.get_total_slots() if not success: return None request = api.Message() request.commutator.all_modules_info_req = True self.send(request) result: List[ModuleInfo] = [] for i in range(total_slots): response, _ = await self.wait_message() module_info = get_message_field(response, ["commutator", "module_info"]) if not module_info: return None result.append(ModuleInfo.from_protubuf(module_info)) return result
async def _await_status(self, timeout_sec: float = 0.1) -> Optional[Status]: response, _ = await self.wait_message(timeout=timeout_sec) status = get_message_field(response, ["system_clock", "status"]) return Status.from_protobuf(mode=status) if status is not None else None
async def _await_time(self, timeout_sec: float = 0.1) -> Optional[int]: response, _ = await self.wait_message(timeout=timeout_sec) time = get_message_field(response, ["system_clock", "now"]) if time is None: return None return time