Messaggistica APRS#
Il componente message (components/message/) implementa la messaggistica
APRS con conferma e ritentativo, e instradamento in RF e/o APRS-IS.
L’amministrazione web espone due pagine distinte: la pagina Message
configura il motore (abilitazione RF/INET, ritentativo, GPIO di allarme),
mentre la pagina Snd/Rcv Msg (/msgchat) è l’interfaccia di
casella/composizione vera e propria.
Il motore dei messaggi#
Coda in RAM.
s_queue[]contiene fino aMSG_QUEUE_SIZE(10) voci, condivise dai messaggi ricevuti e in uscita allo stesso modo — ogni voce porta un flagrxtxche dice quale sia. La coda è la conversazione: un messaggio inviato e uno ricevuto occupano ciascuno una propria casella e la mantengono finché traffico più recente non li spinge fuori, e una volta occupate tutte e dieci le caselle, memorizzare il messaggio successivo scarta la voce più vecchia del filo, RX o TX che sia.MSG_TEXT_MAX(200) è il tetto di memorizzazione in memoria del testo di una voce; il limite di protocollo in onda è il separatoAPRS_MSG_TEXT_STD_MAX(67 caratteri), contro cui validano la casella di composizione e il risponditore di query, così che un campo informativo":ADDRESSEE:testo{id"completo resti entro il classico budget TNC2 di 256 byte.Ordine della conversazione. Ogni messaggio memorizzato porta un contatore di inserimento (
msg_entry_t::seq) assegnato una sola volta e mai modificato, ed è quel contatore — non l’orologio di sistema — a ordinare il filo e a scegliere la voce da scartare. Un messaggio in uscita mantiene quindi il posto in cui è stato scritto per tutto il tempo in cui viene ritentato (last_txporta la pianificazione dei ritentativi,timeresta il momento della creazione), e l’ordine sopravvive a un salto dell’orologio di sistema come la prima sincronizzazione NTP dopo l’avvio.Invia / ack / ritentativo.
sendAPRSMessage()accoda un messaggio,sendAPRSAck()risponde a uno ricevuto, esendAPRSMessageRetry()— invocata a 1 Hz dal task di tick del servizio APRS — reinvia qualsiasi messaggio la cui conferma non è ancora arrivata, fino amsg_retryvolte ognimsg_intervalsecondi.Risposta a ``?APRSM``.
message_send_pending_to()ritrasmette ciò che questa stazione trattiene per l’operatore che interroga, senza consumare nessuno dei ritentativi propri del messaggio né spostarne il successivo, e si ferma dopoMSG_QUERY_BURST_MAX(3) trame: una query diretta vale una manciata di trame, non un’intera coda con il trasmettitore attivo. Ciò che il limite lascia fuori resta pendente, quindi la passata di ritentativi qui sopra continua a consegnarlo a distanza di unmsg_interval.Analisi degli entranti.
handleIncomingAPRS()analizza qualsiasi riga TNC2 — da RF o da APRS-IS. Un messaggio viene riconosciuto dal campo informazioni della riga, tutto ciò che segue il primo:(nessun indirizzo di un’intestazione TNC2 può contenerne uno), che deve portare per intero l’inquadratura":DESTINATARIO:"del capitolo 14: l’identificatore di tipo dato:, un destinatario di nove caratteri e un:di chiusura. È la stessa prova applicata dal classificatore di pacchetti, così un testo libero che sembra soltanto un messaggio — dentro un rapporto di stato, un commento di posizione o un oggetto — resta dove gli compete, e nessuna trama mai indirizzata qui può far scattare l’Allarme Messaggi né una trasmissione di ack. Da una riga che invece passa, riconosce i messaggi diretti a questa stazione o a un gruppo di messaggi che essa legge, risponde con un ack quando è un messaggio diretto, e riconosce gli ack entranti (ackNNN) per pulire il messaggio accodato corrispondente. Ogni messaggio accettato è una nuova riga della conversazione e riceve una propria casella, compresi quelli che non portano alcun{ide quelli il cui numero la stazione mittente ha già usato in precedenza (la numerazione riparte quando quella stazione si riavvia). L’unica riga che non occupa una casella è una ritrasmissione che la coda già contiene — stesso mittente, stesso numero di messaggio, testo identico, stesso carattere diretto/di gruppo — a cui si risponde con un ack nuovo quando era un messaggio diretto, perché un ripetuto significa che il mittente non ha mai sentito il primo, senza comparire due volte nella cronologia. Gli indicativi di origine sono normalizzati in maiuscolo durante l’analisi, così una stazione occupa un solo nome nel filo e un ack si abbina al messaggio in uscita che conferma.
Gruppi di messaggi#
Secondo il capitolo 14 di APRS101, «Message Groups», una stazione ricevente
legge ogni messaggio indirizzato a ALL, QST o CQ — l’insieme di
gruppi incorporato — oltre che al proprio indicativo, più qualsiasi nome di
gruppo configurato localmente, come il destinatario che un net o una tavola
rotonda APRS usa al posto dell’indicativo proprio di ciascun partecipante.
ALL, QST e CQ non richiedono configurazione e sono sempre letti;
fino a MSG_USER_GROUPS (3) nomi definiti dall’operatore si impostano nel
riquadro «Message Groups» della pagina Message, un campo di testo per
casella, lo stesso schema a caselle ripetute usato dalla pagina Bollettini. Un
nome di gruppo è confrontato per intero e senza distinguere maiuscole/
minuscole, senza rimozione del -SSID (un gruppo non è un indicativo).
Si legge, non si conferma mai. Un messaggio indirizzato a un gruppo viene salvato nella coda e mostrato nel pannello
/msgchatesattamente come un messaggio diretto. Tuttavia non viene mai confermato, mai ritrasmesso e mai a cui si risponde automaticamente, che porti o meno un suffisso{id: un gruppo non ha un unico proprietario che rimandi unackNN, e ogni membro che lo legga risponderebbe altrimenti al mittente contemporaneamente.handleIncomingAPRS()decide ogni scelta «invia un ack» / «ricorda un Reply-ACK dovuto» / «attiva l’Allarme Messaggio» in base al fatto che il destinatario abbia corrisposto esattamente all’indicativo proprio di questa stazione, mai solo per essere stato accettato — anche una rigaack/rejdiretta a un gruppo viene ignorata, poiché questa stazione non invia mai un messaggio in uscita a un gruppo perché qualcosa lo confermi.Caselle di cronologia separate. Un messaggio di gruppo e uno diretto restano separati nella coda anche quando condividono lo stesso mittente e lo stesso numero di messaggio APRS: il rilevamento dei duplicati e il salvataggio usano l’indicativo del mittente e il numero di messaggio insieme al carattere diretto/di gruppo, così i due non collidono mai in un’unica casella né si sovrascrivono a vicenda.
Instradamento#
Ogni messaggio è instradato tramite una maschera di bit di canale via un gestore TX registrato:
MSG_CHANNEL_RF(1 << 0) →aprs_service_send_tnc2()(ramo RF).MSG_CHANNEL_INET(1 << 1) →igate_send_raw()(ramo APRS-IS).
g_config.msg_rf e g_config.msg_inet decidono quali rami sono attivi.
C’è un terzo ramo facoltativo che non raggiunge alcuna radio: con
l’interruttore «Inoltra messaggi della stazione» della pagina Telegram
acceso, un messaggio indirizzato a un nominativo elencato lì viene consegnato
anche alla chat Telegram di quell’utente, che sia ricevuto dalla rete o
inviato dalla pagina /msgchat. Vedi Bot Telegram.
L’interfaccia di chat messaggi (/msgchat)#
La pagina /msgchat presenta un pannello scorrevole di messaggi inviati e
ricevuti da questa stazione, un campo di indicativo di destinazione, una casella
di testo del messaggio (limitata alla lunghezza del messaggio APRS) e un pulsante
di invio. Aggiorna la sua lista di messaggi tramite /msgchat/list (un
frammento JSON), che restituisce l’intero filo memorizzato, dal più vecchio al
più recente. È condizionata dall’interruttore di compilazione
ENABLE_MSG_CHAT.
Il pannello si legge come una sola conversazione, con i messaggi inviati e
ricevuti alternati nell’ordine in cui sono avvenuti e il più recente in basso.
Il suo script misura le bolle dei messaggi una volta impaginate e dimensiona il
pannello sulle MSGCHAT_VISIBLE_MESSAGES (5) più recenti, così cinque
messaggi sono visibili senza scorrere e il resto del filo memorizzato — fino a
MSG_QUEUE_SIZE (10) messaggi — dista uno scorrimento. La misura viene
ripetuta quando la finestra cambia dimensione, perché un testo più stretto va a
capo su più righe e rende le bolle più alte. Lo scorrimento segue la
conversazione solo finché l’operatore è già in fondo ad essa, così un messaggio
in arrivo non strappa mai il pannello dalle righe più vecchie che si stanno
leggendo.
Entrambi i numeri sono costanti di compilazione: MSGCHAT_VISIBLE_MESSAGES in
page_msgchat.c decide soltanto quanto è alto il pannello, mentre
MSG_QUEUE_SIZE in message.h decide quanta conversazione conserva il
firmware.
Vedi anche
Risponditore di query APRS — il risponditore di query condivide il gestore di TX di questo
componente ed è raggiunto da handleIncomingAPRS() quando il testo di un
messaggio indirizzato inizia con ?.
GPIO di allarme messaggio#
Opzionalmente (msg_alarm_enable), un messaggio entrante può attivare un GPIO
(msg_alarm_gpio; -1 = disabilitato), validato da
message_alarm_gpio_is_valid() — utile per accendere un LED o far suonare un
cicalino alla ricezione di un messaggio.