152 lines
4.7 KiB
Python
152 lines
4.7 KiB
Python
# ------------------------------ BUTTON MAPPINGS ------------------------------------------
|
|
# BUTTON MATRIX: OK, VOL_UP, VOL_DOWN, SRC_UP, SRC_DOWN, PAUSE, WHEEL_UP, WHEEL_DOWN
|
|
# CD CHANGER: NEXT, PREV, FAST_FORW, PLAY, PAUSE, RESUME, STOP, FAST_BACK, CD_(1-6), STALK, RAND_ON, RAND_OFF
|
|
# RADIO: VOL_UP, VOL_DOWN, PAUSE
|
|
# ANDROID AUTO: ENTER, LEFT, RIGHT, UP, DOWN, BACK, HOME, PHONE, CALL_END, PLAY, PAUSE, PREV_TRACK, NEXT_TRACK, TOGGLE_PLAY, VOICE, WHEEL_LEFT, WHEEL_RIGHT
|
|
|
|
def send_to_radio(btn):
|
|
tunerlist.send_button(btn)
|
|
|
|
def send_to_aa(btn):
|
|
queue.put_nowait(dumps({"button": btn}))
|
|
|
|
BUTTON_MAPPINGS = {
|
|
"VOL_UP": (send_to_radio, "VOL_UP"),
|
|
"VOL_DOWN": (send_to_radio, "VOL_DOWN"),
|
|
"PAUSE": (send_to_radio, "PAUSE")
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------------------
|
|
|
|
from tunerlist import TunerList, TunerListState
|
|
from bluetooth import Bluetooth, BluetoothState
|
|
from buttondecoder import ButtonDecoder
|
|
|
|
from json import dumps
|
|
from fastapi import FastAPI, WebSocket, Request
|
|
from fastapi.responses import PlainTextResponse, JSONResponse, HTMLResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
from asyncio import create_task, CancelledError, Queue, sleep
|
|
from uvicorn import run
|
|
import os
|
|
|
|
app = FastAPI()
|
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
background_tasks = []
|
|
|
|
tunerlist = TunerList()
|
|
bluetooth = Bluetooth()
|
|
buttons = ButtonDecoder()
|
|
|
|
last_tunerlist_state: TunerListState = None
|
|
last_bluetooth_state: BluetoothState = None
|
|
state_to_send: dict = {}
|
|
queue = Queue()
|
|
|
|
def build_state_to_send():
|
|
if not last_tunerlist_state:
|
|
return
|
|
if not last_bluetooth_state:
|
|
state_to_send= {"radio": last_tunerlist_state.to_dict()}
|
|
elif last_tunerlist_state.is_temp_view and last_bluetooth_state.status == "playing":
|
|
state_to_send = {"bluetooth": last_bluetooth_state.to_dict()}
|
|
state_to_send["bluetooth"]["screen"] = last_tunerlist_state.text
|
|
elif last_tunerlist_state.is_playing_ext:
|
|
state_to_send = {"bluetooth": last_bluetooth_state.to_dict()}
|
|
else:
|
|
state_to_send = {"radio": last_tunerlist_state.to_dict()}
|
|
queue.put_nowait(state_to_send)
|
|
|
|
async def tunerlist_listener():
|
|
global last_tunerlist_state
|
|
try:
|
|
while True:
|
|
last_tunerlist_state = await tunerlist.queue.get()
|
|
build_state_to_send()
|
|
except CancelledError:
|
|
pass
|
|
|
|
async def bluetooth_listener():
|
|
global last_bluetooth_state
|
|
try:
|
|
while True:
|
|
last_bluetooth_state = await bluetooth.queue.get()
|
|
build_state_to_send()
|
|
except CancelledError:
|
|
pass
|
|
|
|
async def button_listener():
|
|
try:
|
|
while True:
|
|
button = await buttons.queue.get()
|
|
if button in BUTTON_MAPPINGS:
|
|
func, arg = BUTTON_MAPPINGS[button]
|
|
func(arg)
|
|
except CancelledError:
|
|
pass
|
|
|
|
@app.on_event("startup")
|
|
async def startup_event():
|
|
for i in [
|
|
tunerlist.run(),
|
|
# bluetooth.run(),
|
|
buttons.run(),
|
|
tunerlist_listener(),
|
|
bluetooth_listener()
|
|
]:
|
|
background_tasks.append(create_task(i))
|
|
|
|
@app.on_event("shutdown")
|
|
async def shutdown_event():
|
|
for task in background_tasks:
|
|
task.cancel()
|
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
async def root():
|
|
html_file_path = os.path.join(os.getcwd(), "static", "index.html")
|
|
with open(html_file_path, "r") as file:
|
|
return file.read()
|
|
|
|
@app.websocket("/ws")
|
|
async def websocket_endpoint(websocket: WebSocket):
|
|
global state_to_send
|
|
await websocket.accept()
|
|
try:
|
|
while True:
|
|
payload = await queue.get()
|
|
print(payload)
|
|
await websocket.send_text(dumps(payload))
|
|
except CancelledError:
|
|
return
|
|
|
|
@app.get("/state", response_class=JSONResponse)
|
|
async def state_endpoint():
|
|
return dumps(state_to_send)
|
|
|
|
@app.get("/btn", response_class=PlainTextResponse)
|
|
async def emulated_button(request: Request):
|
|
btn = request.query_params.get("btn")
|
|
print("CD Changer button: ", btn)
|
|
buttons.queue.put_nowait(btn)
|
|
|
|
@app.get("/settext", response_class=JSONResponse)
|
|
async def set_text(request: Request):
|
|
text = request.query_params.get("txt")
|
|
tunerlist.set_text(text)
|
|
return dumps(state_to_send)
|
|
|
|
@app.get("/connect", response_class=PlainTextResponse)
|
|
async def connect_aa(request: Request):
|
|
ip = request.query_params.get("ip")
|
|
queue.put_nowait({"wireless_aa_ip": ip})
|
|
return ip
|
|
|
|
@app.get("/aabtn", response_class=PlainTextResponse)
|
|
async def aabtn(request: Request):
|
|
btn = request.query_params.get("btn")
|
|
queue.put_nowait({"button": {"btn": btn, "state": 2}})
|
|
return btn
|
|
|
|
if __name__ == "__main__":
|
|
run(app=app, host="0.0.0.0", port=5959, log_level="info")
|