mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Implement more commands and remove old code
This commit is contained in:
parent
dea132203b
commit
8670646ca7
|
@ -1,5 +1,5 @@
|
||||||
from data_frame_factory import DataFrameFactory
|
from data_frame_factory import DataFrameFactory
|
||||||
from modem.modem import RF
|
from modem import RF
|
||||||
import queue
|
import queue
|
||||||
from codec2 import FREEDV_MODE
|
from codec2 import FREEDV_MODE
|
||||||
|
|
||||||
|
@ -26,18 +26,22 @@ class TxCommand():
|
||||||
def build_frame(self):
|
def build_frame(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_c2_mode(self):
|
def get_tx_mode(self):
|
||||||
c2_mode = FREEDV_MODE.fsk_ldpc_0.value if self.config.enable_fsk else FREEDV_MODE.sig0.value
|
c2_mode = FREEDV_MODE.fsk_ldpc_0.value if self.config.enable_fsk else FREEDV_MODE.sig0.value
|
||||||
return c2_mode
|
return c2_mode
|
||||||
|
|
||||||
def transmit(self, tx_frame_queue):
|
def make_modem_queue_item(self, mode, repeat, repeat_delay, frame):
|
||||||
frame = self.build_frame()
|
item = {
|
||||||
tx_queue_item = {
|
|
||||||
'mode': self.get_c2_mode(),
|
'mode': self.get_c2_mode(),
|
||||||
'repeat': 1,
|
'repeat': 1,
|
||||||
'repeat_delay': 0,
|
'repeat_delay': 0,
|
||||||
'frame': frame
|
'frame': frame
|
||||||
}
|
}
|
||||||
|
return item
|
||||||
|
|
||||||
|
def transmit(self, tx_frame_queue):
|
||||||
|
frame = self.build_frame()
|
||||||
|
tx_queue_item = self.make_modem_queue_item(self.get_tx_mode(), 1, 0, frame)
|
||||||
tx_frame_queue.put(tx_queue_item)
|
tx_frame_queue.put(tx_queue_item)
|
||||||
|
|
||||||
def run(self, event_queue: queue.Queue, tx_frame_queue: queue.Queue):
|
def run(self, event_queue: queue.Queue, tx_frame_queue: queue.Queue):
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
from command import TxCommand
|
from command import TxCommand
|
||||||
|
|
||||||
class CQCommand(TxCommand):
|
class CQCommand(TxCommand):
|
||||||
|
|
||||||
|
def build_frame(self):
|
||||||
|
return self.frame_factory.build_cq()
|
||||||
|
|
|
@ -22,8 +22,8 @@ class FecCommand(TxCommand):
|
||||||
|
|
||||||
def transmit(self, tx_frame_queue):
|
def transmit(self, tx_frame_queue):
|
||||||
if self.wakeup:
|
if self.wakeup:
|
||||||
tx_queue_item = [self.get_c2_mode(), 1, 0, self.build_wakeup_frame()]
|
tx_queue_item = self.make_modem_queue_item(self.get_c2_mode(), 1, 0, self.build_wakeup_frame())
|
||||||
tx_frame_queue.put(tx_queue_item)
|
tx_frame_queue.put(tx_queue_item)
|
||||||
|
|
||||||
tx_queue_item = [self.get_c2_mode(), 1, 0, self.build_frame()]
|
tx_queue_item = self.make_modem_queue_item(self.get_c2_mode(), 1, 0, self.build_frame())
|
||||||
tx_frame_queue.put(tx_queue_item)
|
tx_frame_queue.put(tx_queue_item)
|
||||||
|
|
|
@ -6,10 +6,5 @@ class PingCommand(TxCommand):
|
||||||
self.dxcall = apiParams['dxcall']
|
self.dxcall = apiParams['dxcall']
|
||||||
return super().setParamsFromApi()
|
return super().setParamsFromApi()
|
||||||
|
|
||||||
def run(self, modem_state, tx_frame_queue):
|
def build_frame(self):
|
||||||
frame = self.frame_factory.build_ping(self.dxcall)
|
return self.frame_factory.build_ping(self.dxcall)
|
||||||
|
|
||||||
|
|
||||||
return super().execute(modem_state, tx_frame_queue)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
10
modem/command_test.py
Normal file
10
modem/command_test.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from command import TxCommand
|
||||||
|
import codec2
|
||||||
|
|
||||||
|
class TestCommand(TxCommand):
|
||||||
|
|
||||||
|
def build_frame(self):
|
||||||
|
return self.frame_factory.build_test()
|
||||||
|
|
||||||
|
def get_tx_mode(self):
|
||||||
|
return codec2.FREEDV_MODE.datac13.value
|
|
@ -76,3 +76,7 @@ class DataFrameFactory:
|
||||||
fec_frame[:1] = bytes([FR_TYPE.FEC.value])
|
fec_frame[:1] = bytes([FR_TYPE.FEC.value])
|
||||||
fec_frame[1:payload_per_frame] = bytes(payload[:fec_payload_length])
|
fec_frame[1:payload_per_frame] = bytes(payload[:fec_payload_length])
|
||||||
return fec_frame
|
return fec_frame
|
||||||
|
|
||||||
|
def build_test(self):
|
||||||
|
test_frame = bytearray(126)
|
||||||
|
test_frame[:1] = bytes([FR_TYPE.TEST_FRAME.value])
|
||||||
|
|
|
@ -95,13 +95,6 @@ class DISPATCHER():
|
||||||
FR_TYPE.FEC_WAKEUP.value: (self.data_broadcasts.received_fec_wakeup, "FEC WAKEUP"),
|
FR_TYPE.FEC_WAKEUP.value: (self.data_broadcasts.received_fec_wakeup, "FEC WAKEUP"),
|
||||||
|
|
||||||
}
|
}
|
||||||
self.command_dispatcher = {
|
|
||||||
# "CONNECT": (self.arq_session_handler, "CONNECT"),
|
|
||||||
"CQ": (self.broadcasts.transmit_cq, "CQ"),
|
|
||||||
"DISCONNECT": (self.arq_session.close_session, "DISCONNECT"),
|
|
||||||
"SEND_TEST_FRAME": (self.broadcasts.send_test_frame, "TEST"),
|
|
||||||
"STOP": (self.arq.stop_transmission, "STOP"),
|
|
||||||
}
|
|
||||||
|
|
||||||
def _initialize_queues(self):
|
def _initialize_queues(self):
|
||||||
"""Initializes data queues."""
|
"""Initializes data queues."""
|
||||||
|
@ -121,47 +114,6 @@ class DISPATCHER():
|
||||||
while True:
|
while True:
|
||||||
command = self.data_queue_transmit.get()
|
command = self.data_queue_transmit.get()
|
||||||
command.execute(self.event_queue, MODEM_TRANSMIT_QUEUE)
|
command.execute(self.event_queue, MODEM_TRANSMIT_QUEUE)
|
||||||
continue
|
|
||||||
|
|
||||||
# Dispatch commands known to command_dispatcher
|
|
||||||
if data[0] in self.command_dispatcher:
|
|
||||||
self.log.debug(f"[Modem] TX {self.command_dispatcher[data[0]][1]}...")
|
|
||||||
self.command_dispatcher[data[0]][0]()
|
|
||||||
|
|
||||||
# Dispatch commands that need more arguments.
|
|
||||||
elif data[0] == "CONNECT":
|
|
||||||
# [1] mycallsign
|
|
||||||
# [2] dxcallsign
|
|
||||||
self.arq.arq_session_handler(data[1], data[2])
|
|
||||||
|
|
||||||
elif data[0] == "PING":
|
|
||||||
# [1] mycallsign // this is being injected as None
|
|
||||||
# [2] dxcallsign
|
|
||||||
mycallsign = f"{self.config['STATION']['mycall']}-{self.config['STATION']['myssid']}"
|
|
||||||
self.ping.transmit_ping(mycallsign, data[2])
|
|
||||||
|
|
||||||
elif data[0] == "ARQ_RAW":
|
|
||||||
# [1] DATA_OUT bytes
|
|
||||||
# [2] self.transmission_uuid str
|
|
||||||
# [3] mycallsign with ssid str
|
|
||||||
# [4] dxcallsign with ssid str
|
|
||||||
self.arq_iss.open_dc_and_transmit(data[1], data[2], data[3], data[4])
|
|
||||||
|
|
||||||
elif data[0] == "FEC_IS_WRITING":
|
|
||||||
# [1] DATA_OUT bytes
|
|
||||||
# [2] MODE str datac0/1/3...
|
|
||||||
self.broadcasts.send_fec_is_writing(data[1])
|
|
||||||
|
|
||||||
elif data[0] == "FEC":
|
|
||||||
# [1] WAKEUP bool
|
|
||||||
# [2] MODE str datac0/1/3...
|
|
||||||
# [3] PAYLOAD
|
|
||||||
# [4] MYCALLSIGN
|
|
||||||
self.broadcasts.send_fec(data[1], data[2], data[3], data[4])
|
|
||||||
else:
|
|
||||||
self.log.error(
|
|
||||||
"[Modem] worker_transmit: received invalid command:", data=data
|
|
||||||
)
|
|
||||||
|
|
||||||
def worker_receive(self) -> None:
|
def worker_receive(self) -> None:
|
||||||
"""Queue received data for processing"""
|
"""Queue received data for processing"""
|
||||||
|
|
|
@ -6,14 +6,16 @@ import serial_ports
|
||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
import audio
|
import audio
|
||||||
import queue
|
import queue
|
||||||
import server_commands
|
|
||||||
import service_manager
|
import service_manager
|
||||||
import state_manager
|
import state_manager
|
||||||
import ujson as json
|
import ujson as json
|
||||||
import websocket_manager as wsm
|
import websocket_manager as wsm
|
||||||
import api_validations as validations
|
import api_validations as validations
|
||||||
from command import TxCommand
|
import command_ping
|
||||||
from command_ping import PingCommand
|
import command_cq
|
||||||
|
import command_ping
|
||||||
|
import command_feq
|
||||||
|
import command_test
|
||||||
from queues import DATA_QUEUE_TRANSMIT as tx_cmd_queue
|
from queues import DATA_QUEUE_TRANSMIT as tx_cmd_queue
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
@ -125,9 +127,10 @@ def get_modem_state():
|
||||||
def post_cqcqcq():
|
def post_cqcqcq():
|
||||||
if request.method not in ['POST']:
|
if request.method not in ['POST']:
|
||||||
return api_response({"info": "endpoint for triggering a CQ via POST"})
|
return api_response({"info": "endpoint for triggering a CQ via POST"})
|
||||||
if app.state_manager.is_modem_running:
|
if not app.state_manager.is_modem_running:
|
||||||
server_commands.cqcqcq()
|
api_abort('Modem not running', 503)
|
||||||
return api_response({"cmd": "cqcqcq"})
|
enqueue_tx_command(command_cq.CQCommand)
|
||||||
|
return "ok"
|
||||||
|
|
||||||
@app.route('/modem/beacon', methods=['POST'])
|
@app.route('/modem/beacon', methods=['POST'])
|
||||||
def post_beacon():
|
def post_beacon():
|
||||||
|
@ -147,32 +150,35 @@ def post_ping():
|
||||||
if not app.state_manager.is_modem_running:
|
if not app.state_manager.is_modem_running:
|
||||||
api_abort('Modem not running', 503)
|
api_abort('Modem not running', 503)
|
||||||
validate(request.json, 'dxcall', validations.validate_freedata_callsign)
|
validate(request.json, 'dxcall', validations.validate_freedata_callsign)
|
||||||
enqueue_tx_command(PingCommand, request.json)
|
enqueue_tx_command(command_ping.PingCommand, request.json)
|
||||||
return 'ok'
|
return 'ok'
|
||||||
|
|
||||||
@app.route('/modem/send_test_frame', methods=['POST'])
|
@app.route('/modem/send_test_frame', methods=['POST'])
|
||||||
def post_send_test_frame():
|
def post_send_test_frame():
|
||||||
if request.method not in ['POST']:
|
if request.method not in ['POST']:
|
||||||
return api_response({"info": "endpoint for triggering a TEST_FRAME via POST"})
|
return api_response({"info": "endpoint for triggering a TEST_FRAME via POST"})
|
||||||
if app.state_manager.is_modem_running:
|
if not app.state_manager.is_modem_running:
|
||||||
server_commands.modem_send_test_frame()
|
api_abort('Modem not running', 503)
|
||||||
return api_response({"cmd": "test_frame"})
|
enqueue_tx_command(command_test.TestCommand)
|
||||||
|
return "ok"
|
||||||
|
|
||||||
@app.route('/modem/fec_transmit', methods=['POST'])
|
@app.route('/modem/fec_transmit', methods=['POST'])
|
||||||
def post_send_fec_frame():
|
def post_send_fec_frame():
|
||||||
if request.method not in ['POST']:
|
if request.method not in ['POST']:
|
||||||
return api_response({"info": "endpoint for triggering a FEC frame via POST"})
|
return api_response({"info": "endpoint for triggering a FEC frame via POST"})
|
||||||
if app.state_manager.is_modem_running:
|
if not app.state_manager.is_modem_running:
|
||||||
server_commands.modem_fec_transmit(request.json)
|
api_abort('Modem not running', 503)
|
||||||
return api_response(request.json)
|
enqueue_tx_command(command_feq.FecCommand, request.json)
|
||||||
|
return "ok"
|
||||||
|
|
||||||
@app.route('/modem/fec_is_writing', methods=['POST'])
|
@app.route('/modem/fec_is_writing', methods=['POST'])
|
||||||
def post_send_fec_is_writing():
|
def post_send_fec_is_writing():
|
||||||
if request.method not in ['POST']:
|
if request.method not in ['POST']:
|
||||||
return api_response({"info": "endpoint for triggering a IS WRITING frame via POST"})
|
return api_response({"info": "endpoint for triggering a IS WRITING frame via POST"})
|
||||||
if app.state_manager.is_modem_running:
|
if not app.state_manager.is_modem_running:
|
||||||
server_commands.modem_fec_is_writing(request.json)
|
api_abort('Modem not running', 503)
|
||||||
return api_response(request.json)
|
#server_commands.modem_fec_is_writing(request.json)
|
||||||
|
return 'Not implemented yet'
|
||||||
|
|
||||||
@app.route('/modem/start', methods=['POST'])
|
@app.route('/modem/start', methods=['POST'])
|
||||||
def post_modem_start():
|
def post_modem_start():
|
||||||
|
@ -199,8 +205,11 @@ def get_modem_version():
|
||||||
def post_modem_send_raw():
|
def post_modem_send_raw():
|
||||||
if request.method not in ['POST']:
|
if request.method not in ['POST']:
|
||||||
return api_response({"info": "endpoint for SENDING RAW DATA via POST"})
|
return api_response({"info": "endpoint for SENDING RAW DATA via POST"})
|
||||||
server_commands.modem_arq_send_raw(request.json)
|
if not app.state_manager.is_modem_running:
|
||||||
return api_response(request.json)
|
api_abort('Modem not running', 503)
|
||||||
|
|
||||||
|
# server_commands.modem_arq_send_raw(request.json)
|
||||||
|
return "Not implemented yet"
|
||||||
|
|
||||||
# @app.route('/modem/arq_connect', methods=['POST'])
|
# @app.route('/modem/arq_connect', methods=['POST'])
|
||||||
# @app.route('/modem/arq_disconnect', methods=['POST'])
|
# @app.route('/modem/arq_disconnect', methods=['POST'])
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
from queues import DATA_QUEUE_TRANSMIT
|
|
||||||
import base64
|
|
||||||
import structlog
|
|
||||||
import threading
|
|
||||||
from random import randrange
|
|
||||||
log = structlog.get_logger("COMMANDS")
|
|
||||||
|
|
||||||
def cqcqcq():
|
|
||||||
try:
|
|
||||||
DATA_QUEUE_TRANSMIT.put(["CQ"])
|
|
||||||
return
|
|
||||||
except Exception as err:
|
|
||||||
log.warning("[CMD] error while transmiting CQ", e=err)
|
|
||||||
|
|
||||||
def ping_ping(dxcall):
|
|
||||||
try:
|
|
||||||
DATA_QUEUE_TRANSMIT.put(["PING", None, dxcall])
|
|
||||||
|
|
||||||
except Exception as err:
|
|
||||||
log.warning(
|
|
||||||
"[CMD] PING command execution error", e=err
|
|
||||||
)
|
|
||||||
|
|
||||||
def modem_send_test_frame():
|
|
||||||
|
|
||||||
log.info(
|
|
||||||
"[CMD] Send test frame"
|
|
||||||
)
|
|
||||||
DATA_QUEUE_TRANSMIT.put(["SEND_TEST_FRAME"])
|
|
||||||
|
|
||||||
def modem_arq_send_raw(mycallsign, dxcallsign, payload, arq_uuid = "no-uuid"):
|
|
||||||
|
|
||||||
# wait some random time
|
|
||||||
threading.Event().wait(randrange(5, 25, 5) / 10.0)
|
|
||||||
|
|
||||||
base64data = payload
|
|
||||||
|
|
||||||
if len(base64data) % 4:
|
|
||||||
raise TypeError
|
|
||||||
|
|
||||||
binarydata = base64.b64decode(base64data)
|
|
||||||
|
|
||||||
DATA_QUEUE_TRANSMIT.put(
|
|
||||||
["ARQ_RAW", binarydata, arq_uuid, mycallsign, dxcallsign]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def modem_fec_transmit(mode, wakeup, base64data, mycallsign = None):
|
|
||||||
log.info(
|
|
||||||
"[CMD] Send fec frame"
|
|
||||||
)
|
|
||||||
if len(base64data) % 4:
|
|
||||||
raise TypeError
|
|
||||||
payload = base64.b64decode(base64data)
|
|
||||||
|
|
||||||
DATA_QUEUE_TRANSMIT.put(["FEC", mode, wakeup, payload, mycallsign])
|
|
||||||
|
|
||||||
def modem_fec_is_writing(mycallsign):
|
|
||||||
try:
|
|
||||||
DATA_QUEUE_TRANSMIT.put(["FEC_IS_WRITING", mycallsign])
|
|
||||||
except Exception as err:
|
|
||||||
log.warning(
|
|
||||||
"[SCK] Send fec frame command execution error",
|
|
||||||
e=err,
|
|
||||||
)
|
|
||||||
|
|
Loading…
Reference in a new issue