111 lines
3.0 KiB
Python
111 lines
3.0 KiB
Python
from .protocol import (
|
|
make_status_request,
|
|
make_set_relay,
|
|
is_status_response,
|
|
is_relay_response,
|
|
is_error,
|
|
)
|
|
|
|
|
|
class CommunicationService:
|
|
def __init__(
|
|
self,
|
|
uart_client,
|
|
app_state,
|
|
http_client=None,
|
|
clock=None,
|
|
timeout_seconds=5,
|
|
):
|
|
self.uart_client = uart_client
|
|
self.http_client = http_client
|
|
self.app_state = app_state
|
|
self.clock = clock
|
|
self.timeout_seconds = timeout_seconds
|
|
self.last_messages = []
|
|
self.use_http_fallback = False
|
|
self.last_status_received_at = None
|
|
|
|
def now(self):
|
|
if self.clock:
|
|
return self.clock()
|
|
|
|
try:
|
|
import time
|
|
return time.time()
|
|
except ImportError:
|
|
return 0
|
|
|
|
def request_status(self):
|
|
if self.use_http_fallback and self.http_client:
|
|
message = self.http_client.get_status()
|
|
self.handle_message(message)
|
|
return message
|
|
|
|
self.uart_client.send_message(make_status_request())
|
|
return None
|
|
|
|
def set_relay(self, relay, enabled):
|
|
if self.use_http_fallback and self.http_client:
|
|
message = self.http_client.set_relay(relay, enabled)
|
|
self.handle_message(message)
|
|
return message
|
|
|
|
self.uart_client.send_message(make_set_relay(relay, enabled))
|
|
return None
|
|
|
|
def poll(self):
|
|
messages = self.uart_client.read_available_messages()
|
|
self.last_messages = messages
|
|
|
|
for message in messages:
|
|
self.handle_message(message)
|
|
|
|
self.update_connection_state()
|
|
|
|
return messages
|
|
|
|
def update_connection_state(self):
|
|
if self.last_status_received_at is None:
|
|
self.app_state.network["uart_connected"] = False
|
|
return
|
|
|
|
age = self.now() - self.last_status_received_at
|
|
self.app_state.network["uart_connected"] = age <= self.timeout_seconds
|
|
|
|
def should_use_http_fallback(self):
|
|
return (
|
|
self.http_client is not None
|
|
and not self.app_state.network.get("uart_connected", False)
|
|
)
|
|
|
|
def auto_select_transport(self):
|
|
self.use_http_fallback = self.should_use_http_fallback()
|
|
return self.use_http_fallback
|
|
|
|
def enable_http_fallback(self):
|
|
self.use_http_fallback = True
|
|
|
|
def disable_http_fallback(self):
|
|
self.use_http_fallback = False
|
|
|
|
def handle_message(self, message):
|
|
if is_status_response(message):
|
|
self.last_status_received_at = self.now()
|
|
self.app_state.update_from_status(message)
|
|
self.app_state.network["uart_connected"] = True
|
|
return
|
|
|
|
if is_relay_response(message):
|
|
self.app_state.update_from_relay_response(message)
|
|
return
|
|
|
|
if is_error(message):
|
|
self.app_state.set_error(message)
|
|
return
|
|
|
|
self.app_state.set_error({
|
|
"type": "error",
|
|
"message": "unknown_message_type",
|
|
"raw": message,
|
|
})
|