feat: send connection message when starting up

issue: N25B-150
This commit is contained in:
Björn Otgaar
2025-10-08 12:11:24 +02:00
parent c634e4b516
commit ae60105b4d
5 changed files with 73 additions and 12 deletions

83
main.py
View File

@@ -1,18 +1,23 @@
import sys
import logging
logging.
import argparse
import zmq
import json
import logging
import hashlib
import socket
import time
from src.audio_streaming import AudioStreaming
from state import state
from urlparse import urlparse
def say(session, message):
tts = session.service("ALTextToSpeech")
tts.say(message)
def listen_for_messages(session):
context = zmq.Context()
socket = context.socket(zmq.SUB)
@@ -23,6 +28,25 @@ def listen_for_messages(session):
poller.register(socket, zmq.POLLIN)
logging.info("Listening for messages")
# Let the CB know we're connected.
pub = context.socket(zmq.PUB)
pub.bind("tcp://*:5555")
time.sleep(1)
print("Now attempting to send connection data to CB.")
connection_data = {
"event": "robot_connected",
"id": state.__getattribute__("id"),
"name": state.__getattribute__("name"),
"port": state.__getattribute__("port")
}
connection_json = json.dumps(connection_data)
pub.send_string(connection_json)
print("Send data: ", connection_json)
while not state.exit_event.is_set():
if not poller.poll(200): continue # At most 200 ms delay after CTRL+C
# We now know there's a message waiting for us
@@ -31,34 +55,71 @@ def listen_for_messages(session):
if session: say(session, message)
def get_session():
if "--qi-url" not in sys.argv:
logging.info("No Qi URL argument given. Running in stand-alone mode.")
return None
ip = resolve_local_ip()
port = -1
return None, ip, port
parser = argparse.ArgumentParser()
parser.add_argument("--qi-url", type=str, help="Qi URL argument")
parser.add_argument("--name", type=str, default="Robot without name", help="Optional robot name")
args = parser.parse_args()
name = args.name
parsed = urlparse(args.qi_url)
ip = parsed.hostname
port = parsed.port
# If URL uses localhost, get own ip instead
if ip in ("localhost", "127.0.0.1"):
ip = resolve_local_ip()
try:
import qi
except ImportError:
logging.info("Unable to import qi. Running in stand-alone mode.")
return None
return None, ip, port, name
try:
app = qi.Application()
app.start()
return app.session
return app.session, ip, port, name
except RuntimeError:
logging.info("Unable to connect to the robot. Running in stand-alone mode.")
return None
return None, ip, port, name
def resolve_local_ip():
"""Return the actual local IP, not 127.0.0.1."""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80)) # Use a public IP just to resolve interface
ip = s.getsockname()[0]
s.close()
return ip
except Exception as e:
logging.warning("Could not resolve local IP: {}".format(e))
return "127.0.0.1"
def main():
session = get_session()
session, ip, port, name = get_session()
audio_streamer = AudioStreaming()
audio_streamer.run()
# hash ip, port into id
id_source = "{}:{}".format(ip, port)
unique_id = hashlib.md5(id_source).hexdigest()
listen_for_messages(session) # Runs indefinitely, until CTRL+C
print("created unique id: ", unique_id)
state.id = unique_id
state.port = port
state.ip = ip
state.name = name
logging.info("Session ID: {} (from {})".format(unique_id, id_source))
listen_for_messages(session)
if __name__ == "__main__":

BIN
src/__init__.pyc Normal file

Binary file not shown.

BIN
src/audio_streaming.pyc Normal file

Binary file not shown.

View File

@@ -35,7 +35,7 @@ class State(object):
def __getattribute__(self, name):
# Enforce that the state is initialized before accessing any property (aside from the basic ones)
if name in ("initialize", "deinitialize", "is_initialized", "__dict__", "__class__"):
if name in ("initialize", "deinitialize", "is_initialized", "__dict__", "__class__", "id", "name", "ip", "port"):
return object.__getattribute__(self, name)
if not object.__getattribute__(self, "is_initialized"):

BIN
state.pyc Normal file

Binary file not shown.