2023-11-09 21:11:53 +00:00
|
|
|
import threading
|
2023-11-23 09:14:11 +00:00
|
|
|
import frame_dispatcher
|
2023-11-09 21:11:53 +00:00
|
|
|
import modem
|
|
|
|
import structlog
|
2023-11-10 15:02:38 +00:00
|
|
|
import audio
|
2024-02-02 18:37:02 +00:00
|
|
|
|
2024-01-12 14:51:23 +00:00
|
|
|
import radio_manager
|
2023-11-12 21:35:10 +00:00
|
|
|
|
2023-11-09 21:11:53 +00:00
|
|
|
|
|
|
|
class SM:
|
|
|
|
def __init__(self, app):
|
|
|
|
self.log = structlog.get_logger("service")
|
2024-01-12 15:29:22 +00:00
|
|
|
self.app = app
|
2023-11-09 21:11:53 +00:00
|
|
|
self.modem = False
|
2024-01-12 15:29:22 +00:00
|
|
|
self.app.radio_manager = False
|
2023-11-19 08:56:00 +00:00
|
|
|
self.config = self.app.config_manager.read()
|
2023-11-09 21:11:53 +00:00
|
|
|
self.modem_fft = app.modem_fft
|
|
|
|
self.modem_service = app.modem_service
|
2024-01-12 14:51:23 +00:00
|
|
|
self.state_manager = app.state_manager
|
2024-01-04 14:46:58 +00:00
|
|
|
self.event_manager = app.event_manager
|
2024-02-02 18:37:02 +00:00
|
|
|
self.schedule_manager = app.schedule_manager
|
2024-01-04 14:46:58 +00:00
|
|
|
|
2023-11-10 15:02:38 +00:00
|
|
|
|
2023-11-09 21:11:53 +00:00
|
|
|
runner_thread = threading.Thread(
|
|
|
|
target=self.runner, name="runner thread", daemon=True
|
|
|
|
)
|
|
|
|
runner_thread.start()
|
|
|
|
|
|
|
|
def runner(self):
|
|
|
|
while True:
|
|
|
|
cmd = self.modem_service.get()
|
|
|
|
if cmd in ['start'] and not self.modem:
|
2024-01-12 14:51:23 +00:00
|
|
|
self.config = self.app.config_manager.read()
|
|
|
|
self.start_radio_manager()
|
2023-11-12 21:35:10 +00:00
|
|
|
self.start_modem()
|
2023-11-23 06:02:56 +00:00
|
|
|
|
2023-11-12 21:35:10 +00:00
|
|
|
elif cmd in ['stop'] and self.modem:
|
|
|
|
self.stop_modem()
|
2024-01-12 14:51:23 +00:00
|
|
|
self.stop_radio_manager()
|
2023-11-12 21:35:10 +00:00
|
|
|
# we need to wait a bit for avoiding a portaudio crash
|
|
|
|
threading.Event().wait(0.5)
|
2023-11-12 18:56:15 +00:00
|
|
|
|
2023-11-12 21:35:10 +00:00
|
|
|
elif cmd in ['restart']:
|
|
|
|
self.stop_modem()
|
2024-01-12 14:51:23 +00:00
|
|
|
self.stop_radio_manager()
|
2023-11-12 21:35:10 +00:00
|
|
|
# we need to wait a bit for avoiding a portaudio crash
|
|
|
|
threading.Event().wait(0.5)
|
2024-01-12 14:51:23 +00:00
|
|
|
|
|
|
|
self.config = self.app.config_manager.read()
|
|
|
|
self.start_radio_manager()
|
|
|
|
|
2023-11-12 21:35:10 +00:00
|
|
|
if self.start_modem():
|
2024-01-04 14:46:58 +00:00
|
|
|
self.event_manager.modem_restarted()
|
2023-12-21 16:47:48 +00:00
|
|
|
|
2023-11-09 21:11:53 +00:00
|
|
|
else:
|
2024-01-12 14:51:23 +00:00
|
|
|
self.log.warning("[SVC] modem command processing failed", cmd=cmd, state=self.state_manager.is_modem_running)
|
2023-11-12 21:35:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
def start_modem(self):
|
2024-02-02 18:37:02 +00:00
|
|
|
|
|
|
|
if self.config['STATION']['mycall'] in ['XX1XXX']:
|
|
|
|
self.log.warning("wrong callsign in config! interrupting startup")
|
|
|
|
return False
|
|
|
|
|
2024-01-12 14:51:23 +00:00
|
|
|
if self.state_manager.is_modem_running:
|
2023-11-26 13:51:58 +00:00
|
|
|
self.log.warning("modem already running")
|
|
|
|
return False
|
|
|
|
|
2024-02-02 18:37:02 +00:00
|
|
|
|
2023-11-19 08:56:00 +00:00
|
|
|
# test audio devices
|
2023-11-12 21:35:10 +00:00
|
|
|
audio_test = self.test_audio()
|
2023-11-19 08:56:00 +00:00
|
|
|
|
2024-01-12 14:51:23 +00:00
|
|
|
if False in audio_test or None in audio_test or self.state_manager.is_modem_running:
|
2023-11-12 21:35:10 +00:00
|
|
|
self.log.warning("starting modem failed", input_test=audio_test[0], output_test=audio_test[1])
|
2024-01-12 14:51:23 +00:00
|
|
|
self.state_manager.set("is_modem_running", False)
|
2024-01-04 14:46:58 +00:00
|
|
|
self.event_manager.modem_failed()
|
2023-11-12 21:35:10 +00:00
|
|
|
return False
|
|
|
|
|
2023-11-26 13:51:58 +00:00
|
|
|
self.log.info("starting modem....")
|
2024-01-12 15:29:22 +00:00
|
|
|
self.modem = modem.RF(self.config, self.event_manager, self.modem_fft, self.modem_service, self.state_manager, self.app.radio_manager)
|
2023-11-26 13:51:58 +00:00
|
|
|
|
2023-11-29 16:35:23 +00:00
|
|
|
self.frame_dispatcher = frame_dispatcher.DISPATCHER(self.config,
|
2024-01-04 14:46:58 +00:00
|
|
|
self.event_manager,
|
2024-01-12 14:51:23 +00:00
|
|
|
self.state_manager,
|
2023-12-15 23:51:57 +00:00
|
|
|
self.modem)
|
2023-11-26 13:51:58 +00:00
|
|
|
self.frame_dispatcher.start()
|
|
|
|
|
2024-01-04 14:46:58 +00:00
|
|
|
self.event_manager.modem_started()
|
2024-01-12 14:51:23 +00:00
|
|
|
self.state_manager.set("is_modem_running", True)
|
2023-11-29 16:35:23 +00:00
|
|
|
self.modem.start_modem()
|
2024-02-02 18:37:02 +00:00
|
|
|
self.schedule_manager.start(self.modem)
|
2023-11-26 13:51:58 +00:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
2023-11-12 21:35:10 +00:00
|
|
|
def stop_modem(self):
|
|
|
|
self.log.info("stopping modem....")
|
|
|
|
del self.modem
|
|
|
|
self.modem = False
|
2024-01-12 14:51:23 +00:00
|
|
|
self.state_manager.set("is_modem_running", False)
|
2024-02-02 18:37:02 +00:00
|
|
|
self.schedule_manager.stop()
|
2024-01-04 14:46:58 +00:00
|
|
|
self.event_manager.modem_stopped()
|
2023-11-12 21:35:10 +00:00
|
|
|
|
|
|
|
def test_audio(self):
|
2024-01-05 14:10:46 +00:00
|
|
|
try:
|
|
|
|
audio_test = audio.test_audio_devices(self.config['AUDIO']['input_device'],
|
|
|
|
self.config['AUDIO']['output_device'])
|
|
|
|
self.log.info("tested audio devices", result=audio_test)
|
2023-12-21 16:47:48 +00:00
|
|
|
|
2024-01-05 14:10:46 +00:00
|
|
|
return audio_test
|
|
|
|
except Exception as e:
|
|
|
|
self.log.error("Error testing audio devices", e=e)
|
|
|
|
return [False, False]
|
2023-12-21 16:47:48 +00:00
|
|
|
|
2024-01-12 14:51:23 +00:00
|
|
|
def start_radio_manager(self):
|
2024-01-12 15:29:22 +00:00
|
|
|
self.app.radio_manager = radio_manager.RadioManager(self.config, self.state_manager, self.event_manager)
|
2024-01-12 14:51:23 +00:00
|
|
|
|
|
|
|
def stop_radio_manager(self):
|
2024-01-12 15:29:22 +00:00
|
|
|
self.app.radio_manager.stop()
|
|
|
|
del self.app.radio_manager
|