nixos-configuration/pkgs/myintercom-doorbell/myintercom_doorbell/myintercom_audiosocket.py
2023-11-08 23:49:46 +00:00

98 lines
2.8 KiB
Python

import os
import sys
import urllib3
from multiprocessing import Pipe, Process
from threading import Thread
from .audiosocket import Audiosocket
def open_url(direction, connection, username, password):
print(f"start {direction}", flush=True)
if direction not in ("transmit", "receive"):
raise NotImplementedError
method, headers = {
"receive": ("GET", {}),
"transmit": ("POST", {"Content-Type": "audio/basic", "Content-Length": "0"}),
}[direction]
url = f"http://192.168.0.74/axis-cgi/audio/{direction}.cgi"
http = urllib3.PoolManager()
print(f"start {direction} request", flush=True)
response = http.request(
method,
url,
headers={
**urllib3.make_headers(basic_auth=f"{username}:{password}"),
**headers,
},
preload_content=False,
body=(
None
if direction != "transmit"
else os.fdopen(connection.fileno(), "rb", buffering=0)
),
)
print(f"{direction} status is {response.status}", flush=True)
if direction == "receive":
for data in response.stream(amt=160):
connection.send_bytes(data)
def handle_connection(call, username, password):
print(f"Received connection from {call.peer_addr}")
pipe_transmit_in, pipe_transmit_out = Pipe()
doorbell_transmit_process = Process(
target=open_url, args=("transmit", pipe_transmit_out, username, password)
)
doorbell_transmit_process.start()
pipe_receive_in, pipe_receive_out = Pipe()
doorbell_receive_process = Process(
target=open_url, args=("receive", pipe_receive_in, username, password)
)
doorbell_receive_process.start()
with os.fdopen(os.dup(pipe_transmit_in.fileno()), "wb", buffering=0) as f_transmit:
while call.connected:
f_transmit.write(call.read())
call.write(pipe_receive_out.recv_bytes())
print(f"Connection with {call.peer_addr} is now over")
doorbell_transmit_process.terminate()
doorbell_receive_process.terminate()
doorbell_transmit_process.join()
doorbell_receive_process.join()
def main():
audiosocket = Audiosocket(
(os.environ["LISTEN_ADDRESS"], int(os.environ["LISTEN_PORT"]))
)
audiosocket.prepare_output(outrate=8000, channels=1, lin2ulaw=True)
audiosocket.prepare_input(inrate=8000, channels=1, ulaw2lin=True)
print("Listening for new connections " f"from Asterisk on port {audiosocket.port}")
username = os.environ["USERNAME"]
with open(os.environ["PASSWORD_FILE"], "r", encoding="utf-8") as f:
password = f.read()
while True:
call = audiosocket.listen()
call_thread = Thread(target=handle_connection, args=(call, username, password))
call_thread.start()
call_thread.join()
if __name__ == "__main__":
sys.exit(main())