mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 10:04:33 +02:00
ARQ WIP - session closing
This commit is contained in:
parent
2faf398e4b
commit
53955a8107
|
@ -20,7 +20,7 @@ import infoScreen from "./infoScreen.vue";
|
|||
import main_modem_healthcheck from "./main_modem_healthcheck.vue";
|
||||
import Dynamic_components2 from "./dynamic_components2.vue";
|
||||
|
||||
import { stopTransmission } from "../js/sock";
|
||||
import { stopTransmission } from "../js/api";
|
||||
|
||||
function stopAllTransmissions() {
|
||||
console.log("stopping transmissions");
|
||||
|
|
|
@ -97,6 +97,12 @@ export function sendModemARQRaw(mycall, dxcall, data, uuid) {
|
|||
});
|
||||
}
|
||||
|
||||
export function stopTransmission() {
|
||||
return apiPost("/modem/stop_transmission");
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function sendModemTestFrame() {
|
||||
return apiPost("/modem/send_test_frame");
|
||||
}
|
||||
|
|
|
@ -719,11 +719,6 @@ function sendResponseSharedFile(dxcallsign, sharedFile, sharedFileData) {
|
|||
sendResponse(dxcallsign, 255, 1, sharedFile + "/" + sharedFileData, "res-2");
|
||||
}
|
||||
*/
|
||||
//STOP TRANSMISSION
|
||||
export function stopTransmission() {
|
||||
var command = '{"type" : "arq", "command": "stop_transmission"}';
|
||||
writeTncCommand(command);
|
||||
}
|
||||
|
||||
// Get RX BUffer
|
||||
export function getRxBuffer() {
|
||||
|
|
|
@ -45,6 +45,8 @@ class ARQSession():
|
|||
|
||||
self.id = None
|
||||
|
||||
self.final = False # class wide final state for stopping transmissions on command
|
||||
|
||||
def log(self, message, isWarning = False):
|
||||
msg = f"[{type(self).__name__}]: {message}"
|
||||
logger = self.logger.warn if isWarning else self.logger.info
|
||||
|
@ -88,3 +90,4 @@ class ARQSession():
|
|||
return
|
||||
|
||||
self.log(f"Ignoring unknow transition from state {self.state.name} with frame {frame['frame_type']}")
|
||||
|
||||
|
|
|
@ -16,29 +16,39 @@ class IRS_State(Enum):
|
|||
|
||||
class ARQSessionIRS(arq_session.ARQSession):
|
||||
|
||||
TIMEOUT_CONNECT = 3
|
||||
TIMEOUT_CONNECT = 10
|
||||
TIMEOUT_DATA = 12
|
||||
|
||||
STATE_TRANSITION = {
|
||||
IRS_State.NEW: {
|
||||
FRAME_TYPE.ARQ_SESSION_OPEN.value : 'send_open_ack',
|
||||
FRAME_TYPE.ARQ_STOP.value: 'send_stop_ack'
|
||||
},
|
||||
IRS_State.OPEN_ACK_SENT: {
|
||||
FRAME_TYPE.ARQ_SESSION_OPEN.value: 'send_open_ack',
|
||||
FRAME_TYPE.ARQ_SESSION_INFO.value: 'send_info_ack',
|
||||
FRAME_TYPE.ARQ_STOP.value: 'send_stop_ack'
|
||||
|
||||
},
|
||||
IRS_State.INFO_ACK_SENT: {
|
||||
FRAME_TYPE.ARQ_SESSION_INFO.value: 'send_info_ack',
|
||||
FRAME_TYPE.ARQ_BURST_FRAME.value: 'receive_data',
|
||||
FRAME_TYPE.ARQ_STOP.value: 'send_stop_ack'
|
||||
|
||||
},
|
||||
IRS_State.BURST_REPLY_SENT: {
|
||||
FRAME_TYPE.ARQ_BURST_FRAME.value: 'receive_data',
|
||||
FRAME_TYPE.ARQ_STOP.value: 'send_stop_ack'
|
||||
|
||||
},
|
||||
IRS_State.ENDED: {
|
||||
FRAME_TYPE.ARQ_BURST_FRAME.value: 'receive_data',
|
||||
FRAME_TYPE.ARQ_STOP.value: 'send_stop_ack'
|
||||
|
||||
},
|
||||
IRS_State.FAILED: {
|
||||
FRAME_TYPE.ARQ_BURST_FRAME.value: 'receive_data',
|
||||
FRAME_TYPE.ARQ_STOP.value: 'send_stop_ack'
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -107,16 +117,10 @@ class ARQSessionIRS(arq_session.ARQSession):
|
|||
|
||||
info_ack = self.frame_factory.build_arq_session_info_ack(
|
||||
self.id, self.total_crc, self.snr[0],
|
||||
self.speed_level, self.frames_per_burst)
|
||||
self.speed_level, self.frames_per_burst, flag_final=self.final)
|
||||
self.launch_transmit_and_wait(info_ack, self.TIMEOUT_CONNECT, mode=FREEDV_MODE.signalling)
|
||||
self.set_state(IRS_State.INFO_ACK_SENT)
|
||||
|
||||
def send_burst_nack(self):
|
||||
self.calibrate_speed_settings()
|
||||
self.set_decode_mode()
|
||||
nack = self.frame_factory.build_arq_burst_ack(self.id, self.received_bytes, self.speed_level, self.frames_per_burst, self.snr[0])
|
||||
self.launch_transmit_and_wait(nack, self.TIMEOUT_DATA, mode=FREEDV_MODE.signalling)
|
||||
self.log("NACK sent")
|
||||
|
||||
def process_incoming_data(self, frame):
|
||||
if frame['offset'] != self.received_bytes:
|
||||
|
@ -148,7 +152,7 @@ class ARQSessionIRS(arq_session.ARQSession):
|
|||
if not self.all_data_received():
|
||||
ack = self.frame_factory.build_arq_burst_ack(
|
||||
self.id, self.received_bytes,
|
||||
self.speed_level, self.frames_per_burst, self.snr[0])
|
||||
self.speed_level, self.frames_per_burst, self.snr[0], flag_final=self.final)
|
||||
|
||||
# increase ack counter
|
||||
self.transmitted_acks += 1
|
||||
|
@ -199,3 +203,11 @@ class ARQSessionIRS(arq_session.ARQSession):
|
|||
if self.snr[0] >= self.SPEED_LEVEL_DICT[new_speed_level]["min_snr"]:
|
||||
self.speed_level = new_speed_level
|
||||
|
||||
def stop_transmission(self):
|
||||
self.log(f"Stopping transmission...., setting final flag")
|
||||
self.final = True
|
||||
|
||||
def send_stop_ack(self, stop_frame):
|
||||
stop_ack = self.frame_factory.build_arq_stop_ack(self.id)
|
||||
self.launch_transmit_and_wait(stop_ack, self.TIMEOUT_CONNECT, mode=FREEDV_MODE.signalling)
|
||||
self.set_state(IRS_State.FAILED)
|
|
@ -34,8 +34,10 @@ class ARQSessionISS(arq_session.ARQSession):
|
|||
ISS_State.BURST_SENT: {
|
||||
FRAME_TYPE.ARQ_SESSION_INFO_ACK.value: 'send_data',
|
||||
FRAME_TYPE.ARQ_BURST_ACK.value: 'send_data',
|
||||
FRAME_TYPE.ARQ_BURST_NACK.value: 'send_data',
|
||||
},
|
||||
ISS_State.FAILED:{
|
||||
FRAME_TYPE.ARQ_STOP_ACK.value: 'transmission_failed'
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, config: dict, modem, dxcall: str, data: bytearray):
|
||||
|
@ -54,7 +56,7 @@ class ARQSessionISS(arq_session.ARQSession):
|
|||
return random.randint(1,255)
|
||||
|
||||
def transmit_wait_and_retry(self, frame_or_burst, timeout, retries, mode):
|
||||
while retries > 0:
|
||||
while retries > 0 and not self.final:
|
||||
self.event_frame_received = threading.Event()
|
||||
if isinstance(frame_or_burst, list): burst = frame_or_burst
|
||||
else: burst = [frame_or_burst]
|
||||
|
@ -129,4 +131,10 @@ class ARQSessionISS(arq_session.ARQSession):
|
|||
def transmission_failed(self):
|
||||
self.set_state(ISS_State.FAILED)
|
||||
self.log("Transmission failed!")
|
||||
self.event_manager.send_arq_session_finished(True, self.id, self.dxcall, len(self.data),False)
|
||||
self.event_manager.send_arq_session_finished(True, self.id, self.dxcall, len(self.data),False)
|
||||
|
||||
def stop_transmission(self):
|
||||
self.log(f"Stopping transmission...")
|
||||
stop_frame = self.frame_factory.build_arq_stop(self.id)
|
||||
self.launch_twr(stop_frame, self.TIMEOUT_CONNECT_ACK, self.RETRIES_CONNECT, mode=FREEDV_MODE.signalling)
|
||||
self.set_state(ISS_State.FAILED)
|
||||
|
|
|
@ -4,6 +4,8 @@ import api_validations
|
|||
import base64
|
||||
from queue import Queue
|
||||
from arq_session_iss import ARQSessionISS
|
||||
|
||||
|
||||
class ARQRawCommand(TxCommand):
|
||||
|
||||
def set_params_from_api(self, apiParams):
|
||||
|
|
|
@ -127,6 +127,16 @@ class DataFrameFactory:
|
|||
"flag": 1,
|
||||
}
|
||||
|
||||
self.template_list[FR_TYPE.ARQ_STOP.value] = {
|
||||
"frame_length": self.LENGTH_SIG0_FRAME,
|
||||
"session_id": 1,
|
||||
}
|
||||
|
||||
self.template_list[FR_TYPE.ARQ_STOP_ACK.value] = {
|
||||
"frame_length": self.LENGTH_SIG0_FRAME,
|
||||
"session_id": 1,
|
||||
}
|
||||
|
||||
# arq burst frame
|
||||
self.template_list[FR_TYPE.ARQ_BURST_FRAME.value] = {
|
||||
"frame_length": None,
|
||||
|
@ -146,23 +156,6 @@ class DataFrameFactory:
|
|||
"flag": 1,
|
||||
}
|
||||
|
||||
# arq burst nack
|
||||
self.template_list[FR_TYPE.ARQ_BURST_NACK.value] = {
|
||||
"frame_length": self.LENGTH_SIG1_FRAME,
|
||||
"session_id": 1,
|
||||
"offset":4,
|
||||
"speed_level": 1,
|
||||
"frames_per_burst": 1,
|
||||
"snr": 1,
|
||||
}
|
||||
|
||||
# arq data ack nack
|
||||
self.template_list[FR_TYPE.ARQ_DATA_ACK_NACK.value] = {
|
||||
"frame_length": self.LENGTH_SIG1_FRAME,
|
||||
"session_id": 1,
|
||||
"state": 1,
|
||||
"snr": 1,
|
||||
}
|
||||
|
||||
def construct(self, frametype, content, frame_length = LENGTH_SIG1_FRAME):
|
||||
frame_template = self.template_list[frametype.value]
|
||||
|
@ -222,9 +215,12 @@ class DataFrameFactory:
|
|||
|
||||
elif key in ["session_id", "speed_level",
|
||||
"frames_per_burst", "version",
|
||||
"snr", "offset", "total_length", "state"]:
|
||||
"offset", "total_length", "state"]:
|
||||
extracted_data[key] = int.from_bytes(data, 'big')
|
||||
|
||||
elif key in ["snr"]:
|
||||
extracted_data[key] = helpers.snr_from_bytes(data)
|
||||
|
||||
elif key == "flag":
|
||||
|
||||
data = int.from_bytes(data, "big")
|
||||
|
@ -342,7 +338,8 @@ class DataFrameFactory:
|
|||
"origin": helpers.callsign_to_bytes(self.myfullcall),
|
||||
"destination_crc": helpers.get_crc_24(destination),
|
||||
"version": bytes([version]),
|
||||
"snr": snr.to_bytes(1, 'big'), }
|
||||
"snr": helpers.snr_to_bytes(1),
|
||||
}
|
||||
return self.construct(FR_TYPE.ARQ_SESSION_OPEN_ACK, payload)
|
||||
|
||||
def build_arq_session_info(self, session_id: int, total_length: int, total_crc: bytes, snr):
|
||||
|
@ -350,10 +347,23 @@ class DataFrameFactory:
|
|||
"session_id": session_id.to_bytes(1, 'big'),
|
||||
"total_length": total_length.to_bytes(4, 'big'),
|
||||
"total_crc": total_crc,
|
||||
"snr": snr.to_bytes(1, 'big'),
|
||||
"snr": helpers.snr_to_bytes(1),
|
||||
}
|
||||
return self.construct(FR_TYPE.ARQ_SESSION_INFO, payload)
|
||||
|
||||
def build_arq_stop(self, session_id: int):
|
||||
payload = {
|
||||
"session_id": session_id.to_bytes(1, 'big'),
|
||||
}
|
||||
return self.construct(FR_TYPE.ARQ_STOP, payload)
|
||||
|
||||
def build_arq_stop_ack(self, session_id: int):
|
||||
payload = {
|
||||
"session_id": session_id.to_bytes(1, 'big'),
|
||||
}
|
||||
return self.construct(FR_TYPE.ARQ_STOP_ACK, payload)
|
||||
|
||||
|
||||
def build_arq_session_info_ack(self, session_id, total_crc, snr, speed_level, frames_per_burst, flag_final=False):
|
||||
flag = 0b00000000
|
||||
if flag_final:
|
||||
|
@ -363,7 +373,7 @@ class DataFrameFactory:
|
|||
"frame_length": self.LENGTH_SIG0_FRAME,
|
||||
"session_id": session_id.to_bytes(1, 'big'),
|
||||
"total_crc": bytes.fromhex(total_crc),
|
||||
"snr": snr.to_bytes(1, 'big'),
|
||||
"snr": helpers.snr_to_bytes(1),
|
||||
"speed_level": speed_level.to_bytes(1, 'big'),
|
||||
"frames_per_burst": frames_per_burst.to_bytes(1, 'big'),
|
||||
"flag": flag.to_bytes(1, 'big'),
|
||||
|
|
|
@ -24,12 +24,11 @@ class DISPATCHER():
|
|||
FR_TYPE.ARQ_CONNECTION_CLOSE.value: {"class": ARQFrameHandler, "name": "ARQ CLOSE SESSION"},
|
||||
FR_TYPE.ARQ_CONNECTION_HB.value: {"class": ARQFrameHandler, "name": "ARQ HEARTBEAT"},
|
||||
FR_TYPE.ARQ_CONNECTION_OPEN.value: {"class": ARQFrameHandler, "name": "ARQ OPEN SESSION"},
|
||||
FR_TYPE.ARQ_STOP.value: {"class": ARQFrameHandler, "name": "ARQ STOP TX"},
|
||||
FR_TYPE.ARQ_STOP.value: {"class": ARQFrameHandler, "name": "ARQ STOP"},
|
||||
FR_TYPE.ARQ_STOP_ACK.value: {"class": ARQFrameHandler, "name": "ARQ STOP ACK"},
|
||||
FR_TYPE.BEACON.value: {"class": FrameHandler, "name": "BEACON"},
|
||||
FR_TYPE.ARQ_BURST_FRAME.value:{"class": ARQFrameHandler, "name": "BURST FRAME"},
|
||||
FR_TYPE.ARQ_BURST_ACK.value: {"class": ARQFrameHandler, "name": "BURST ACK"},
|
||||
FR_TYPE.ARQ_BURST_NACK.value: {"class": ARQFrameHandler, "name": "BURST NACK"},
|
||||
FR_TYPE.ARQ_DATA_ACK_NACK.value: {"class": ARQFrameHandler, "name": "DATA ACK NACK"},
|
||||
FR_TYPE.CQ.value: {"class": CQFrameHandler, "name": "CQ"},
|
||||
FR_TYPE.PING_ACK.value: {"class": FrameHandler, "name": "PING ACK"},
|
||||
FR_TYPE.PING.value: {"class": PingFrameHandler, "name": "PING"},
|
||||
|
|
|
@ -38,8 +38,9 @@ class ARQFrameHandler(frame_handler.FrameHandler):
|
|||
FR.ARQ_SESSION_OPEN_ACK.value,
|
||||
FR.ARQ_SESSION_INFO_ACK.value,
|
||||
FR.ARQ_BURST_ACK.value,
|
||||
FR.ARQ_DATA_ACK_NACK.value
|
||||
]:
|
||||
FR.ARQ_STOP.value,
|
||||
FR.ARQ_STOP_ACK.value
|
||||
]:
|
||||
session = self.states.get_arq_iss_session(session_id)
|
||||
|
||||
else:
|
||||
|
|
|
@ -10,14 +10,13 @@ class FRAME_TYPE(Enum):
|
|||
ARQ_CONNECTION_HB = 2
|
||||
ARQ_CONNECTION_CLOSE = 3
|
||||
ARQ_STOP = 10
|
||||
ARQ_SESSION_OPEN = 11
|
||||
ARQ_SESSION_OPEN_ACK = 12
|
||||
ARQ_SESSION_INFO = 13
|
||||
ARQ_SESSION_INFO_ACK = 14
|
||||
ARQ_STOP_ACK = 11
|
||||
ARQ_SESSION_OPEN = 12
|
||||
ARQ_SESSION_OPEN_ACK = 13
|
||||
ARQ_SESSION_INFO = 14
|
||||
ARQ_SESSION_INFO_ACK = 15
|
||||
ARQ_BURST_FRAME = 20
|
||||
ARQ_BURST_ACK = 21
|
||||
ARQ_BURST_NACK = 22
|
||||
ARQ_DATA_ACK_NACK = 23
|
||||
MESH_BROADCAST = 100
|
||||
MESH_SIGNALLING_PING = 101
|
||||
MESH_SIGNALLING_PING_ACK = 102
|
||||
|
|
|
@ -215,6 +215,19 @@ def post_modem_send_raw():
|
|||
# server_commands.modem_arq_send_raw(request.json)
|
||||
return "Not implemented yet"
|
||||
|
||||
@app.route('/modem/stop_transmission', methods=['POST'])
|
||||
def post_modem_send_raw_stop():
|
||||
|
||||
if request.method not in ['POST']:
|
||||
return api_response({"info": "endpoint for SENDING a STOP command via POST"})
|
||||
if not app.state_manager.is_modem_running:
|
||||
api_abort('Modem not running', 503)
|
||||
print("stop")
|
||||
app.state_manager.set_final_to_arq_transmissions()
|
||||
# server_commands.modem_arq_send_raw(request.json)
|
||||
return api_response(request.json)
|
||||
|
||||
|
||||
# @app.route('/modem/arq_connect', methods=['POST'])
|
||||
# @app.route('/modem/arq_disconnect', methods=['POST'])
|
||||
# @app.route('/modem/send_raw', methods=['POST'])
|
||||
|
|
|
@ -144,6 +144,12 @@ class StateManager:
|
|||
raise RuntimeError(f"ARQ ISS Session '{id}' not found!")
|
||||
del self.arq_irs_sessions[id]
|
||||
|
||||
def set_final_to_arq_transmissions(self):
|
||||
for id in self.arq_irs_sessions:
|
||||
self.arq_irs_sessions[id].stop_transmission()
|
||||
for id in self.arq_iss_sessions:
|
||||
self.arq_iss_sessions[id].stop_transmission()
|
||||
|
||||
def add_activity(self, activity_data):
|
||||
# Generate a random 8-byte string as hex
|
||||
activity_id = np.random.bytes(8).hex()
|
||||
|
|
Loading…
Reference in a new issue