2023-11-15 22:34:26 +00:00
|
|
|
import time
|
2023-11-12 18:56:15 +00:00
|
|
|
import ujson as json
|
2023-11-22 20:54:50 +00:00
|
|
|
import threading
|
2023-11-22 17:05:31 +00:00
|
|
|
class StateManager:
|
2023-11-11 19:01:15 +00:00
|
|
|
def __init__(self, statequeue):
|
2023-11-17 09:22:45 +00:00
|
|
|
|
|
|
|
# state related settings
|
2023-11-11 19:01:15 +00:00
|
|
|
self.statequeue = statequeue
|
2023-11-14 18:26:11 +00:00
|
|
|
self.newstate = None
|
2023-11-17 09:22:45 +00:00
|
|
|
self.last = time.time()
|
|
|
|
|
|
|
|
# modem related states
|
|
|
|
# not every state is needed to publish, yet
|
|
|
|
# TODO can we reduce them?
|
2023-11-11 19:01:15 +00:00
|
|
|
self.channel_busy = False
|
|
|
|
self.channel_busy_slot = [False, False, False, False, False]
|
|
|
|
self.is_codec2_traffic = False
|
2023-11-12 18:56:15 +00:00
|
|
|
self.is_modem_running = False
|
2023-11-17 10:07:29 +00:00
|
|
|
self.is_modem_busy = False
|
2023-11-12 22:22:53 +00:00
|
|
|
self.is_beacon_running = False
|
2023-11-13 19:26:27 +00:00
|
|
|
self.is_arq_state = False
|
|
|
|
self.is_arq_session = False
|
2023-11-22 20:54:50 +00:00
|
|
|
|
|
|
|
# If true, any wait() call is blocking
|
|
|
|
self.transmitting_event = threading.Event()
|
|
|
|
self.setTransmitting(False)
|
|
|
|
|
2023-11-13 17:11:55 +00:00
|
|
|
self.audio_dbfs = 0
|
2023-11-17 09:58:07 +00:00
|
|
|
self.dxcallsign: bytes = b"ZZ9YY-0"
|
|
|
|
self.dxgrid: bytes = b"------"
|
2023-11-17 22:05:41 +00:00
|
|
|
self.heard_stations = []
|
2023-11-12 22:22:53 +00:00
|
|
|
|
2023-11-23 22:10:53 +00:00
|
|
|
self.arq_instance_table = {}
|
2023-11-17 21:45:10 +00:00
|
|
|
self.arq_session_state = 'disconnected'
|
|
|
|
self.arq_speed_level = 0
|
|
|
|
self.arq_total_bytes = 0
|
|
|
|
self.arq_bits_per_second = 0
|
|
|
|
self.arq_bytes_per_minute = 0
|
|
|
|
self.arq_transmission_percent = 0
|
|
|
|
self.arq_compression_factor = 0
|
|
|
|
self.arq_speed_list = []
|
|
|
|
self.arq_seconds_until_timeout = 0
|
|
|
|
|
2023-11-17 22:33:30 +00:00
|
|
|
self.mesh_routing_table = []
|
|
|
|
|
2023-11-17 09:37:50 +00:00
|
|
|
self.radio_frequency = 0
|
|
|
|
self.radio_mode = None
|
|
|
|
self.radio_bandwidth = 0
|
|
|
|
self.radio_rf_power = 0
|
2023-11-17 22:33:30 +00:00
|
|
|
self.radio_strength = 0
|
2023-11-18 22:50:40 +00:00
|
|
|
# Set rig control status regardless or rig control method
|
|
|
|
self.radio_status = False
|
2023-11-17 09:37:50 +00:00
|
|
|
|
2023-11-23 22:10:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-17 21:35:52 +00:00
|
|
|
def sendState (self):
|
|
|
|
currentState = self.getAsJSON(False)
|
|
|
|
self.statequeue.put(currentState)
|
|
|
|
return currentState
|
|
|
|
|
2023-11-17 01:39:04 +00:00
|
|
|
def sendStateUpdate (self):
|
2023-11-17 11:54:26 +00:00
|
|
|
self.statequeue.put(self.newstate)
|
2023-11-12 22:22:53 +00:00
|
|
|
|
2023-11-11 19:01:15 +00:00
|
|
|
def set(self, key, value):
|
|
|
|
setattr(self, key, value)
|
2023-11-18 22:50:40 +00:00
|
|
|
#print(f"State ==> Setting {key} to value {value}")
|
2023-11-14 18:26:11 +00:00
|
|
|
# only process data if changed
|
2023-11-17 21:35:52 +00:00
|
|
|
new_state = self.getAsJSON(True)
|
2023-11-17 01:39:04 +00:00
|
|
|
if new_state != self.newstate:
|
2023-11-14 18:26:11 +00:00
|
|
|
self.newstate = new_state
|
2023-11-17 01:39:04 +00:00
|
|
|
self.sendStateUpdate()
|
|
|
|
|
2023-11-17 21:35:52 +00:00
|
|
|
def getAsJSON(self, isChangedState):
|
|
|
|
msgtype = "state-change"
|
|
|
|
if (not isChangedState):
|
|
|
|
msgtype = "state"
|
2023-11-11 19:01:15 +00:00
|
|
|
|
2023-11-12 18:56:15 +00:00
|
|
|
return json.dumps({
|
2023-11-17 21:35:52 +00:00
|
|
|
"freedata-message": msgtype,
|
2023-11-11 19:01:15 +00:00
|
|
|
"channel_busy": self.channel_busy,
|
2023-11-12 18:56:15 +00:00
|
|
|
"is_codec2_traffic": self.is_codec2_traffic,
|
|
|
|
"is_modem_running": self.is_modem_running,
|
2023-11-12 22:22:53 +00:00
|
|
|
"is_beacon_running": self.is_beacon_running,
|
2023-11-18 22:50:40 +00:00
|
|
|
"radio_status": self.radio_status,
|
|
|
|
"radio_frequency": self.radio_frequency,
|
2023-11-22 20:54:50 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
# .wait() blocks until the event is set
|
|
|
|
def isTransmitting(self):
|
|
|
|
return not self.transmitting_event.is_set()
|
|
|
|
|
|
|
|
# .wait() blocks until the event is set
|
|
|
|
def setTransmitting(self, transmitting: bool):
|
|
|
|
if transmitting:
|
|
|
|
self.transmitting_event.clear()
|
|
|
|
else:
|
|
|
|
self.transmitting_event.set()
|
|
|
|
|
|
|
|
def waitForTransmission(self):
|
|
|
|
self.transmitting_event.wait()
|
2023-11-23 22:10:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def register_arq_instance_by_id(self, id, instance):
|
|
|
|
self.arq_instance_table[id] = instance
|
|
|
|
|
|
|
|
def get_arq_instance_by_id(self, id):
|
|
|
|
return self.arq_instance_table.get(id)
|
|
|
|
|
|
|
|
def delete_arq_instance_by_id(self, id):
|
|
|
|
instances = self.arq_instance_table.pop(id, None)
|
|
|
|
if None not in instances:
|
|
|
|
for key in instances:
|
|
|
|
del instances[key]
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|