Added server assisted roaming capability
This commit is contained in:
parent
e609411897
commit
46503b5d45
@ -5,8 +5,9 @@ import logging
|
||||
from datetime import datetime
|
||||
import requests
|
||||
from .abcsender import AbcSender
|
||||
from utils import config
|
||||
from utils import config, LoopingTimer
|
||||
from urllib.parse import urljoin
|
||||
import time
|
||||
|
||||
"""
|
||||
Send a sound sample
|
||||
@ -23,6 +24,87 @@ class SoundSender(AbcSender):
|
||||
SoundSender class, responsible for sending sound samples to the cloud.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self._feed_url = None
|
||||
self._reassign_timer = None
|
||||
if not config.NO_AUTODISCOVER:
|
||||
retry = 0
|
||||
timeout = 30
|
||||
while True:
|
||||
try:
|
||||
r = requests.post(
|
||||
urljoin(config.API_URL, "/assignment"),
|
||||
json={"device_id": config.DEVICE_ID},
|
||||
timeout=timeout
|
||||
)
|
||||
except requests.exceptions.Timeout:
|
||||
logging.warning(f"/assignment timed out after {timeout} sec! Retrying...")
|
||||
continue
|
||||
|
||||
if r.status_code not in [200, 404]:
|
||||
logging.warning(
|
||||
f"Unexpected status code while acquiring an assignment: {r.status_code}. Retrying..."
|
||||
)
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
if r.status_code == 404:
|
||||
logging.info(
|
||||
"/assignment returned 404 error. Assuming missing capability... Defaulting to use API_URL"
|
||||
)
|
||||
self._feed_url = config.API_URL
|
||||
break
|
||||
|
||||
if r.json()['hard_default']:
|
||||
retry += 1
|
||||
if retry < 10:
|
||||
logging.info(f"Still waiting for non hard-default url... Attempt {retry}/10")
|
||||
time.sleep(6)
|
||||
continue
|
||||
else:
|
||||
logging.info(f"Given up waiting for non hard-default url... accepting hard default.")
|
||||
|
||||
logging.info(f"Assigned to {r.json()['site']}")
|
||||
self._feed_url = r.json()['url']
|
||||
break
|
||||
|
||||
self._reassign_timer = LoopingTimer(config.REASSIGN_INTERVAL, lambda: self.reassign())
|
||||
self._reassign_timer.start()
|
||||
|
||||
# If the above block failed to assign a feed_url
|
||||
if not self._feed_url:
|
||||
logging.info("Using API_URL as feed url")
|
||||
self._feed_url = config.API_URL
|
||||
|
||||
def reassign(self):
|
||||
logging.debug("Asking for reassign...")
|
||||
timeout = 30
|
||||
try:
|
||||
r = requests.post(
|
||||
urljoin(config.API_URL, "/assignment"),
|
||||
json={"device_id": config.DEVICE_ID},
|
||||
timeout=timeout
|
||||
)
|
||||
except requests.exceptions.Timeout:
|
||||
logging.warning(f"/assignment timed out after {timeout} sec! Ignoring...")
|
||||
return
|
||||
|
||||
if r.status_code == 404:
|
||||
logging.debug("/assignment returned 404 status code. Assuming missing capability, and doing nothing...")
|
||||
return
|
||||
|
||||
if r.status_code != 200:
|
||||
logging.debug(f"/assignment returned {r.status_code} status code. Ignoring...")
|
||||
return
|
||||
|
||||
logging.debug(f"Received assignment to {r.json()['site']}")
|
||||
|
||||
if r.json()['url'] != self._feed_url:
|
||||
logging.info(f"Reassigned to {r.json()['site']}!")
|
||||
# Because of GIL and because this is a reference, we don't really have to be careful assigning this
|
||||
self._feed_url = r.json()['url']
|
||||
|
||||
def sendvalue(self, value: str, decision: bool) -> None:
|
||||
"""
|
||||
Send a sound sample to the cloud.
|
||||
@ -32,14 +114,24 @@ class SoundSender(AbcSender):
|
||||
"""
|
||||
if decision:
|
||||
files = {
|
||||
"file": (os.path.basename(value), open(value, 'rb').read(), 'audio/wave',
|
||||
{'Content-length': os.path.getsize(value)}),
|
||||
"file": (
|
||||
os.path.basename(value),
|
||||
open(value, 'rb').read(),
|
||||
'audio/wave',
|
||||
{'Content-length': os.path.getsize(value)}
|
||||
),
|
||||
"description": (
|
||||
None, json.dumps({'date': datetime.now().isoformat(), 'device_id': config.DEVICE_ID}),
|
||||
"application/json")
|
||||
None,
|
||||
json.dumps({'date': datetime.now().isoformat(), 'device_id': config.DEVICE_ID}),
|
||||
"application/json"
|
||||
)
|
||||
}
|
||||
|
||||
r = requests.post(urljoin(config.API_URL, config.FEED_TYPE), files=files)
|
||||
r = requests.post(urljoin(self._feed_url, config.FEED_TYPE), files=files)
|
||||
logging.debug(f"Content: {r.content.decode()}")
|
||||
logging.debug(f"Headers: {r.headers}")
|
||||
r.raise_for_status()
|
||||
|
||||
def __del__(self):
|
||||
if self._reassign_timer:
|
||||
self._reassign_timer.stop()
|
||||
|
@ -41,3 +41,8 @@ FEED_TYPE = os.environ.get("FEED_TYPE", "input") # probably the worst naming the
|
||||
|
||||
if FEED_TYPE not in ['input', 'filter']:
|
||||
raise ValueError("FEED_TYPE must be either input or filter")
|
||||
|
||||
# Skip fetching /assignment endpoint
|
||||
NO_AUTODISCOVER = os.environ.get("NO_AUTODISCOVER", 'no').lower() in ['yes', '1', 'true']
|
||||
|
||||
REASSIGN_INTERVAL = int(os.environ.get("REASSIGN_INTERVAL", 120))
|
||||
|
Loading…
Reference in New Issue
Block a user