Auto-detect local IP address for pyVoIP binding (v2.1.1)

This commit is contained in:
2026-02-08 15:34:57 +01:00
parent 95ac41c1ed
commit b9122dcc5a
2 changed files with 38 additions and 11 deletions

View File

@@ -3,6 +3,7 @@
import json
import logging
import os
import socket
import tempfile
import time
from urllib.parse import urlparse
@@ -26,6 +27,21 @@ CONFIG = {}
DEFAULT_SAMPLE_RATE = 8000
def get_local_ip():
"""Get local IP address of the container."""
try:
# Create a socket to determine the local IP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Connect to an external address (doesn't actually send data)
s.connect(("8.8.8.8", 80))
local_ip = s.getsockname()[0]
s.close()
return local_ip
except Exception as e:
_LOGGER.warning(f"Could not auto-detect IP: {e}, using 0.0.0.0")
return "0.0.0.0"
def download_and_convert_audio(url: str) -> str:
"""Download and convert audio to WAV."""
parsed_url = urlparse(url)
@@ -98,7 +114,12 @@ def place_sip_call(destination: str, audio_file: str, duration: int):
sip_server = CONFIG['sip_server']
sip_password = CONFIG['sip_password']
_LOGGER.info(f"Connecting to SIP server: {sip_server}")
# Get local IP
local_ip = get_local_ip()
_LOGGER.info(f"Local IP: {local_ip}")
_LOGGER.info(f"SIP Server: {sip_server}")
_LOGGER.info(f"Calling: {destination}")
try:
# Create VoIP phone
@@ -108,48 +129,54 @@ def place_sip_call(destination: str, audio_file: str, duration: int):
sip_user,
sip_password,
callCallback=None,
myIP=None,
myIP=local_ip,
sipPort=5060,
rtpPortLow=10000,
rtpPortHigh=20000
)
phone.start()
time.sleep(2) # Wait for registration
_LOGGER.info("SIP phone started, waiting for registration...")
time.sleep(3) # Wait for registration
_LOGGER.info(f"Calling: {destination}")
_LOGGER.info(f"Making call to: {destination}")
# Make call
call = phone.call(destination)
# Wait for call to be answered
timeout = 10
timeout = 15
elapsed = 0
while call.state != CallState.ANSWERED and elapsed < timeout:
time.sleep(0.5)
elapsed += 0.5
if elapsed % 2 == 0:
_LOGGER.info(f"Waiting for answer... ({elapsed}s)")
if call.state != CallState.ANSWERED:
_LOGGER.warning("Call not answered within timeout")
_LOGGER.warning(f"Call not answered within {timeout}s timeout")
_LOGGER.info(f"Final call state: {call.state}")
call.hangup()
phone.stop()
return
_LOGGER.info("Call answered! Playing audio...")
_LOGGER.info("Call answered! Playing audio...")
# Transmit audio file
call.write_audio(audio_file)
# Keep call active
_LOGGER.info(f"Call active for {duration}s")
_LOGGER.info(f"Keeping call active for {duration}s...")
time.sleep(duration)
# Hangup
_LOGGER.info("Hanging up...")
call.hangup()
time.sleep(1)
# Cleanup
phone.stop()
_LOGGER.info("Call completed successfully")
except Exception as e:
_LOGGER.error(f"Call error: {e}", exc_info=True)
@@ -192,10 +219,9 @@ def handle_send_notification():
temp_files.append(audio_file)
# Place call
_LOGGER.info(f"Calling: {destination}")
place_sip_call(destination, audio_file, duration)
return jsonify({'status': 'success'}), 200
return jsonify({'status': 'success', 'message': 'Call completed'}), 200
finally:
# Cleanup
@@ -233,6 +259,7 @@ if __name__ == '__main__':
_LOGGER.info("Using pyVoIP from git (latest version)")
_LOGGER.info(f"SIP Server: {CONFIG.get('sip_server', 'not configured')}")
_LOGGER.info(f"SIP User: {CONFIG.get('sip_user', 'not configured')}")
_LOGGER.info(f"Local IP: {get_local_ip()}")
_LOGGER.info("")
_LOGGER.info("To use this add-on, add configuration to configuration.yaml")
_LOGGER.info("See add-on README for details")