diff --git a/mrobot_controller/app.py b/mrobot_controller/app.py index a65016a..2609d0a 100644 --- a/mrobot_controller/app.py +++ b/mrobot_controller/app.py @@ -33,7 +33,7 @@ def main(): logger.info("Starting controller...") asyncio.run(controller.run()) except Exception as e: - logger.critical(f"Failed to start video streaming: {e}") + logger.critical(f"Failed to start controller: {e}") controller.stop() exit(1) diff --git a/mrobot_controller/controller.py b/mrobot_controller/controller.py index 357bd31..df22088 100644 --- a/mrobot_controller/controller.py +++ b/mrobot_controller/controller.py @@ -3,6 +3,7 @@ from .websocket import WebSocketServer, WebSocketMessageHandler from .serdes import deserialize, DeserializationError, serialize from .video_streamer import VideoStreamer +from .dns_sd import ServicePublisher class ControllerException(Exception): @@ -20,6 +21,7 @@ def __init__(self, port: int, video_config: dict): 'localhost', video_config['port'], video_config['test']) + self.service_publisher = ServicePublisher('mrobot-server', video_config['port']) self.event_loop = None self.tasks = None @@ -49,6 +51,8 @@ def handle_message(self, message): async def run(self): self.logger.debug('Starting server') + self.service_publisher.publish() + self.event_loop = asyncio.get_running_loop() self.tasks = await asyncio.gather( asyncio.to_thread(self.video_streamer.start), @@ -56,8 +60,12 @@ async def run(self): ) def stop(self): - self.video_streamer.stop() - self.tasks.cancel() + if self.service_publisher: + self.service_publisher.unpublish() + if self.video_streamer: + self.video_streamer.stop() + if self.tasks: + self.tasks.cancel() def video_start(self, parameters): self.logger.info(f'Starting video') diff --git a/mrobot_controller/dns_sd/__init__.py b/mrobot_controller/dns_sd/__init__.py new file mode 100644 index 0000000..1fb1061 --- /dev/null +++ b/mrobot_controller/dns_sd/__init__.py @@ -0,0 +1 @@ +from .snd_sd import ServicePublisher diff --git a/mrobot_controller/dns_sd/snd_sd.py b/mrobot_controller/dns_sd/snd_sd.py new file mode 100644 index 0000000..a5a0743 --- /dev/null +++ b/mrobot_controller/dns_sd/snd_sd.py @@ -0,0 +1,32 @@ +import socket +from zeroconf import ServiceInfo, Zeroconf +import logging + + +class ServicePublisher: + + def __init__(self, service_name: str, port: int): + self.logger = logging.getLogger(f'{self.__class__.__name__}-{service_name}') + self.zeroconf = Zeroconf() + self.service_name = f'_{service_name}._websocket._tcp.local.' + self.port = port + + local_ip = socket.gethostbyname(socket.gethostname()) + + self.info = ServiceInfo( + '_websocket._tcp.local.', + name=self.service_name, + addresses=[socket.inet_aton(local_ip)], + port=port, + properties={'path': '/ws'}, + server="websocket-server.local." + ) + + def publish(self): + self.zeroconf.register_service(self.info) + self.logger.info(f"WebSocket service '{self.service_name}' published on port {self.port}") + + def unpublish(self): + self.zeroconf.unregister_service(self.info) + self.zeroconf.close() + self.logger.info(f"WebSocket service '{self.service_name}' removed") diff --git a/mrobot_controller/video_streamer/video_streamer.py b/mrobot_controller/video_streamer/video_streamer.py index ce6db74..02669d4 100644 --- a/mrobot_controller/video_streamer/video_streamer.py +++ b/mrobot_controller/video_streamer/video_streamer.py @@ -181,7 +181,7 @@ def pause(self): self.logger.info('Pipeline state: PAUSED') self.pipeline.set_state(Gst.State.PAUSED) - async def stop(self): + def stop(self): # Clean up self.pipeline.set_state(Gst.State.NULL) self.logger.info('Pipeline stopped') diff --git a/requirements.txt b/requirements.txt index 49f8eb2..52c1f91 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ websockets json asyncio msgpack +zeroconf