kopia lustrzana https://github.com/SP8EBC/ParaTNC
aprs message decoding
rodzic
15829704be
commit
428f6a2360
|
@ -12,6 +12,7 @@ C_SRCS += \
|
||||||
../system/src/aprs/crc.c \
|
../system/src/aprs/crc.c \
|
||||||
../system/src/aprs/dac.c \
|
../system/src/aprs/dac.c \
|
||||||
../system/src/aprs/digi.c \
|
../system/src/aprs/digi.c \
|
||||||
|
../system/src/aprs/message.c \
|
||||||
../system/src/aprs/status.c \
|
../system/src/aprs/status.c \
|
||||||
../system/src/aprs/telemetry.c \
|
../system/src/aprs/telemetry.c \
|
||||||
../system/src/aprs/wx.c
|
../system/src/aprs/wx.c
|
||||||
|
@ -25,6 +26,7 @@ OBJS += \
|
||||||
./system/src/aprs/crc.o \
|
./system/src/aprs/crc.o \
|
||||||
./system/src/aprs/dac.o \
|
./system/src/aprs/dac.o \
|
||||||
./system/src/aprs/digi.o \
|
./system/src/aprs/digi.o \
|
||||||
|
./system/src/aprs/message.o \
|
||||||
./system/src/aprs/status.o \
|
./system/src/aprs/status.o \
|
||||||
./system/src/aprs/telemetry.o \
|
./system/src/aprs/telemetry.o \
|
||||||
./system/src/aprs/wx.o
|
./system/src/aprs/wx.o
|
||||||
|
@ -38,6 +40,7 @@ C_DEPS += \
|
||||||
./system/src/aprs/crc.d \
|
./system/src/aprs/crc.d \
|
||||||
./system/src/aprs/dac.d \
|
./system/src/aprs/dac.d \
|
||||||
./system/src/aprs/digi.d \
|
./system/src/aprs/digi.d \
|
||||||
|
./system/src/aprs/message.d \
|
||||||
./system/src/aprs/status.d \
|
./system/src/aprs/status.d \
|
||||||
./system/src/aprs/telemetry.d \
|
./system/src/aprs/telemetry.d \
|
||||||
./system/src/aprs/wx.d
|
./system/src/aprs/wx.d
|
||||||
|
|
|
@ -50,7 +50,7 @@ void aprsis_init(
|
||||||
aprsis_return_t aprsis_connect_and_login(const char * address, uint8_t address_ln, uint16_t port, uint8_t auto_send_beacon);
|
aprsis_return_t aprsis_connect_and_login(const char * address, uint8_t address_ln, uint16_t port, uint8_t auto_send_beacon);
|
||||||
aprsis_return_t aprsis_connect_and_login_default(uint8_t auto_send_beacon);
|
aprsis_return_t aprsis_connect_and_login_default(uint8_t auto_send_beacon);
|
||||||
sim800_return_t aprsis_disconnect(void);
|
sim800_return_t aprsis_disconnect(void);
|
||||||
void aprsis_receive_callback(srl_context_t* srl_context);
|
//void aprsis_receive_callback(srl_context_t* srl_context);
|
||||||
void aprsis_check_alive(void);
|
void aprsis_check_alive(void);
|
||||||
int aprsis_check_connection_attempt_alive(void);
|
int aprsis_check_connection_attempt_alive(void);
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,6 @@
|
||||||
* $WIZ$ type = "int"
|
* $WIZ$ type = "int"
|
||||||
* $WIZ$ min = 1
|
* $WIZ$ min = 1
|
||||||
*/
|
*/
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
//extern uint8_t kiss_txdelay;
|
|
||||||
//#define CONFIG_AFSK_PREAMBLE_LEN (kiss_txdelay*10UL)
|
|
||||||
#define CONFIG_AFSK_PREAMBLE_LEN 400UL /// 300
|
#define CONFIG_AFSK_PREAMBLE_LEN 400UL /// 300
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,8 +32,6 @@
|
||||||
* $WIZ$ type = "int"
|
* $WIZ$ type = "int"
|
||||||
* $WIZ$ min = 1
|
* $WIZ$ min = 1
|
||||||
*/
|
*/
|
||||||
//extern uint8_t kiss_txtail;
|
|
||||||
//#define CONFIG_AFSK_TRAILER_LEN (kiss_txtail*10UL)
|
|
||||||
#define CONFIG_AFSK_TRAILER_LEN 50UL
|
#define CONFIG_AFSK_TRAILER_LEN 50UL
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
/**
|
/**
|
||||||
* Do not uncomment this on production devices
|
* Do not uncomment this on production devices
|
||||||
*/
|
*/
|
||||||
//#define INHIBIT_CUTOFF
|
#define INHIBIT_CUTOFF
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intermediate STOP2 cycle lenght within L7 or L6 mode.
|
* Intermediate STOP2 cycle lenght within L7 or L6 mode.
|
||||||
|
|
96
src/aprsis.c
96
src/aprsis.c
|
@ -9,6 +9,7 @@
|
||||||
#include "etc/aprsis_config.h"
|
#include "etc/aprsis_config.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "aprs/status.h"
|
#include "aprs/status.h"
|
||||||
|
#include "aprs/message.h"
|
||||||
|
|
||||||
#include "gsm/sim800c.h"
|
#include "gsm/sim800c.h"
|
||||||
#include "gsm/sim800c_poolers.h"
|
#include "gsm/sim800c_poolers.h"
|
||||||
|
@ -19,6 +20,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
#define STATIC
|
||||||
|
#else
|
||||||
|
#define STATIC static
|
||||||
|
#endif
|
||||||
|
|
||||||
srl_context_t * aprsis_serial_port;
|
srl_context_t * aprsis_serial_port;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -180,6 +187,72 @@ char aprsis_login_string_reveived[APRSIS_LOGIN_STRING_RECEIVED_LN];
|
||||||
*/
|
*/
|
||||||
#define MAXIMUM_CALL_SSID_DASH_LN 10
|
#define MAXIMUM_CALL_SSID_DASH_LN 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if data in a buffer contains APRS message
|
||||||
|
* @param message
|
||||||
|
* @param message_ln
|
||||||
|
* @return position at which content of message starts
|
||||||
|
*/
|
||||||
|
STATIC int aprsis_check_is_message(const uint8_t * const message, const uint16_t message_ln) {
|
||||||
|
// example message
|
||||||
|
// Details:"SP8EBC>APX216,TCPIP*,qAC,NINTH::SR9WXZ :tedt{0s}\r\n", '\0' <repeats 715 times>
|
||||||
|
|
||||||
|
// go through a buffer and look for double ':'
|
||||||
|
|
||||||
|
int message_start_position = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < message_ln; i++) {
|
||||||
|
const uint8_t * this_character = message + i;
|
||||||
|
|
||||||
|
const uint8_t * next_character = message + i + 1;
|
||||||
|
|
||||||
|
if (*this_character == 0x00) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*this_character == ':') && (*next_character == ':')) {
|
||||||
|
message_start_position = i + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return message_start_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param srl_context
|
||||||
|
*/
|
||||||
|
STATIC void aprsis_receive_callback(srl_context_t* srl_context) {
|
||||||
|
|
||||||
|
const uint8_t * buffer = srl_get_rx_buffer(srl_context);
|
||||||
|
|
||||||
|
const uint16_t message_ln = srl_context->srl_rx_bytes_counter;
|
||||||
|
|
||||||
|
// if something was actually received
|
||||||
|
if (srl_context->srl_rx_state == SRL_RX_DONE) {
|
||||||
|
// check if this is keepalive message
|
||||||
|
if (*buffer == '#') {
|
||||||
|
aprsis_last_keepalive_ts = main_get_master_time();
|
||||||
|
|
||||||
|
aprsis_last_keepalive_long_ts = main_get_master_time();
|
||||||
|
|
||||||
|
aprsis_keepalive_received_counter++;
|
||||||
|
|
||||||
|
gsm_sim800_tcpip_async_receive(aprsis_serial_port, aprsis_gsm_modem_state, 0, 61000, aprsis_receive_callback);
|
||||||
|
}
|
||||||
|
else if (aprsis_check_is_message(buffer, message_ln) == 1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aprsis_another_received_counter++;
|
||||||
|
|
||||||
|
gsm_sim800_tcpip_async_receive(aprsis_serial_port, aprsis_gsm_modem_state, 0, 61000, aprsis_receive_callback);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void aprsis_init(
|
void aprsis_init(
|
||||||
srl_context_t * context,
|
srl_context_t * context,
|
||||||
gsm_sim800_state_t * gsm_modem_state,
|
gsm_sim800_state_t * gsm_modem_state,
|
||||||
|
@ -394,29 +467,6 @@ sim800_return_t aprsis_disconnect(void) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void aprsis_receive_callback(srl_context_t* srl_context) {
|
|
||||||
|
|
||||||
// if something was actually received
|
|
||||||
if (srl_context->srl_rx_state == SRL_RX_DONE) {
|
|
||||||
// check if this is keepalive message
|
|
||||||
if (*(srl_get_rx_buffer(srl_context)) == '#') {
|
|
||||||
aprsis_last_keepalive_ts = main_get_master_time();
|
|
||||||
|
|
||||||
aprsis_last_keepalive_long_ts = main_get_master_time();
|
|
||||||
|
|
||||||
aprsis_keepalive_received_counter++;
|
|
||||||
|
|
||||||
gsm_sim800_tcpip_async_receive(aprsis_serial_port, aprsis_gsm_modem_state, 0, 61000, aprsis_receive_callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
aprsis_another_received_counter++;
|
|
||||||
|
|
||||||
gsm_sim800_tcpip_async_receive(aprsis_serial_port, aprsis_gsm_modem_state, 0, 61000, aprsis_receive_callback);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pooler function which check periodically if APRS-IS connection is alive.
|
* Pooler function which check periodically if APRS-IS connection is alive.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "main_master_time.h"
|
#include "main_master_time.h"
|
||||||
|
|
||||||
|
#include "ax25_t.h"
|
||||||
#include "cfifo.h"
|
#include "cfifo.h"
|
||||||
#include "afsk.h"
|
#include "afsk.h"
|
||||||
|
|
||||||
|
@ -50,15 +51,15 @@
|
||||||
|
|
||||||
struct AX25Msg; // fwd declaration
|
struct AX25Msg; // fwd declaration
|
||||||
|
|
||||||
/**
|
|
||||||
* Type for AX25 messages callback.
|
|
||||||
*/
|
|
||||||
typedef void (*ax25_callback_t)(struct AX25Msg *ax25_rxed_frame);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type for channel free wait timeout callback
|
* Create an AX25Call structure on the fly.
|
||||||
|
* \param str callsign, can be 6 characters or shorter.
|
||||||
|
* \param id ssid associated with the callsign.
|
||||||
*/
|
*/
|
||||||
typedef void (*ax25_ch_free_timeout_callback_t)(void);
|
#define AX25_CALL(str, id) {.call = (str), .ssid = (id) }
|
||||||
|
#define AX25_PATH(dst, src, ...) { dst, src, ## __VA_ARGS__ }
|
||||||
|
|
||||||
|
|
||||||
typedef struct AX25Ctx
|
typedef struct AX25Ctx
|
||||||
{
|
{
|
||||||
|
@ -81,54 +82,6 @@ typedef struct AX25Ctx
|
||||||
|
|
||||||
} AX25Ctx;
|
} AX25Ctx;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AX25 Call sign.
|
|
||||||
*/
|
|
||||||
typedef struct AX25Call
|
|
||||||
{
|
|
||||||
char call[6]; ///< Call string, max 6 character
|
|
||||||
uint8_t ssid; ///< SSID (secondary station ID) for the call
|
|
||||||
} AX25Call;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an AX25Call structure on the fly.
|
|
||||||
* \param str callsign, can be 6 characters or shorter.
|
|
||||||
* \param id ssid associated with the callsign.
|
|
||||||
*/
|
|
||||||
#define AX25_CALL(str, id) {.call = (str), .ssid = (id) }
|
|
||||||
#define AX25_PATH(dst, src, ...) { dst, src, ## __VA_ARGS__ }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of Repeaters in a AX25 message.
|
|
||||||
*/
|
|
||||||
#define AX25_MAX_RPT 8
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AX25 Message.
|
|
||||||
* Used to handle AX25 sent/received messages.
|
|
||||||
*/
|
|
||||||
typedef struct AX25Msg
|
|
||||||
{
|
|
||||||
|
|
||||||
AX25Call src; ///< Source adress
|
|
||||||
AX25Call dst; ///< Destination address
|
|
||||||
AX25Call rpt_lst[AX25_MAX_RPT]; ///< List of repeaters
|
|
||||||
uint8_t rpt_cnt; ///< Number of repeaters in this message
|
|
||||||
uint8_t rpt_flags; ///< Has-been-repeated flags for each repeater (bit-mapped)
|
|
||||||
#define AX25_REPEATED(msg, idx) ((msg)->rpt_flags & BV(idx))
|
|
||||||
uint16_t ctrl; ///< AX25 control field
|
|
||||||
uint8_t pid; ///< AX25 PID field
|
|
||||||
const uint8_t *info; ///< Pointer to the info field (payload) of the message
|
|
||||||
uint16_t len; ///< Payload length
|
|
||||||
uint8_t raw_data[CONFIG_AX25_FRAME_BUF_LEN]; /// Surowa zawarto<74><6F> ramki przekopiowana z Ctx->buff
|
|
||||||
short int raw_msg_len; // wielkosc surowej ramki
|
|
||||||
|
|
||||||
} AX25Msg;
|
|
||||||
|
|
||||||
extern AX25Msg ax25_rxed_frame;
|
extern AX25Msg ax25_rxed_frame;
|
||||||
extern char ax25_new_msg_rx_flag;
|
extern char ax25_new_msg_rx_flag;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* ax25_t.h
|
||||||
|
*
|
||||||
|
* Created on: Apr 20, 2024
|
||||||
|
* Author: mateusz
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_APRS_AX25_T_H_
|
||||||
|
#define INCLUDE_APRS_AX25_T_H_
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "ax25_config.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of Repeaters in a AX25 message.
|
||||||
|
*/
|
||||||
|
#define AX25_MAX_RPT 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AX25 Call sign.
|
||||||
|
*/
|
||||||
|
typedef struct AX25Call
|
||||||
|
{
|
||||||
|
char call[6]; ///< Call string, max 6 character
|
||||||
|
uint8_t ssid; ///< SSID (secondary station ID) for the call
|
||||||
|
} AX25Call;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AX25 Message.
|
||||||
|
* Used to handle AX25 sent/received messages.
|
||||||
|
*/
|
||||||
|
typedef struct AX25Msg
|
||||||
|
{
|
||||||
|
|
||||||
|
AX25Call src; ///< Source adress
|
||||||
|
AX25Call dst; ///< Destination address
|
||||||
|
AX25Call rpt_lst[AX25_MAX_RPT]; ///< List of repeaters
|
||||||
|
uint8_t rpt_cnt; ///< Number of repeaters in this message
|
||||||
|
uint8_t rpt_flags; ///< Has-been-repeated flags for each repeater (bit-mapped)
|
||||||
|
#define AX25_REPEATED(msg, idx) ((msg)->rpt_flags & BV(idx))
|
||||||
|
uint16_t ctrl; ///< AX25 control field
|
||||||
|
uint8_t pid; ///< AX25 PID field
|
||||||
|
const uint8_t *info; ///< Pointer to the info field (payload) of the message
|
||||||
|
uint16_t len; ///< Payload length
|
||||||
|
uint8_t raw_data[CONFIG_AX25_FRAME_BUF_LEN]; /// Surowa zawarto<74><6F> ramki przekopiowana z Ctx->buff
|
||||||
|
short int raw_msg_len; // wielkosc surowej ramki
|
||||||
|
|
||||||
|
} AX25Msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type for AX25 messages callback.
|
||||||
|
*/
|
||||||
|
typedef void (*ax25_callback_t)(struct AX25Msg *ax25_rxed_frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type for channel free wait timeout callback
|
||||||
|
*/
|
||||||
|
typedef void (*ax25_ch_free_timeout_callback_t)(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* INCLUDE_APRS_AX25_T_H_ */
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* message.h
|
||||||
|
*
|
||||||
|
* Created on: Apr 20, 2024
|
||||||
|
* Author: mateusz
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_APRS_MESSAGE_H_
|
||||||
|
#define INCLUDE_APRS_MESSAGE_H_
|
||||||
|
|
||||||
|
#include "ax25_t.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "./stored_configuration_nvm/config_data.h"
|
||||||
|
|
||||||
|
#define MESSAGE_MAX_LENGHT 67
|
||||||
|
|
||||||
|
typedef struct message_t {
|
||||||
|
AX25Call from;
|
||||||
|
AX25Call to;
|
||||||
|
uint8_t content[MESSAGE_MAX_LENGHT];
|
||||||
|
uint8_t number;
|
||||||
|
}message_t;
|
||||||
|
|
||||||
|
typedef enum message_source_t {
|
||||||
|
MESSAGE_SOURCE_APRSIS,
|
||||||
|
MESSAGE_SOURCE_RADIO
|
||||||
|
|
||||||
|
}message_source_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode received data to look for an APRS message and put it into a structure
|
||||||
|
* @param message pointer to data received from APRS-IS
|
||||||
|
* @param message_ln lenght of a buffer content
|
||||||
|
* @param content_position optional position of an APRS message content (recipient callsign). if set to zero function will look for it
|
||||||
|
* @param src
|
||||||
|
* @param output parsed APRS message content
|
||||||
|
* @return zero if message has been found and decoded, non zero if parsing failed
|
||||||
|
*/
|
||||||
|
uint8_t message_decode_from_aprsis(const uint8_t * const message, const uint16_t message_ln, uint16_t content_position, message_source_t src, message_t * output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param config_data
|
||||||
|
* @param message
|
||||||
|
* @return zero if this is a message to us, non zero otherwise
|
||||||
|
*/
|
||||||
|
uint8_t message_is_for_me(config_data_basic_t * config_data, const message_t * const message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param out_buffer
|
||||||
|
* @param out_buffer_ln
|
||||||
|
* @param message
|
||||||
|
* @param src how this message has been received
|
||||||
|
*/
|
||||||
|
void message_create_ack_for(uint8_t * out_buffer, const uint16_t out_buffer_ln, const message_t * const message, const message_source_t src);
|
||||||
|
|
||||||
|
#endif /* INCLUDE_APRS_MESSAGE_H_ */
|
|
@ -0,0 +1,361 @@
|
||||||
|
/*
|
||||||
|
* message.c
|
||||||
|
*
|
||||||
|
* Created on: Apr 20, 2024
|
||||||
|
* Author: mateusz
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "message.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
|
||||||
|
#define MESSAGE_RECIPIENT_FIELD_SIZE 9
|
||||||
|
|
||||||
|
#define MESSAGE_SSID_CHARS_LN 2
|
||||||
|
|
||||||
|
#define MESSAGE_ATOI_BUFFER 5 ///!< include room of null terminator
|
||||||
|
|
||||||
|
#define MESSAGE_SENDER_CALL_SSID_MAXLEN 9
|
||||||
|
|
||||||
|
#define MESSAGE_CURRENT_CHAR *(message + content_position + i)
|
||||||
|
|
||||||
|
#define MESSAGE_CURRENT_SENDER_CHAR *(message + i)
|
||||||
|
|
||||||
|
#define MESSAGE_IS_DIGIT(c) (c >= '0' && c <= '9')
|
||||||
|
|
||||||
|
#define MESSAGE_ACK_REMAINING_BUF (out_buffer_ln - current_pos)
|
||||||
|
|
||||||
|
#define MESSAGE_ACK_CURRENT_POS (char*)(out_buffer + current_pos)
|
||||||
|
|
||||||
|
static char message_atoi_buffer[MESSAGE_ATOI_BUFFER];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode received data to look for an APRS message and put it into a structure
|
||||||
|
* @param message pointer to data received from APRS-IS
|
||||||
|
* @param message_ln lenght of a buffer content
|
||||||
|
* @param content_position optional position of an APRS message content (recipient callsign). if set to zero function will look for it
|
||||||
|
* @param output parsed APRS message content
|
||||||
|
* @return zero if message has been found and decoded, non zero if parsing failed
|
||||||
|
*/
|
||||||
|
uint8_t message_decode_from_aprsis(const uint8_t * const message, const uint16_t message_ln, uint16_t content_position, message_source_t src, message_t * output) {
|
||||||
|
|
||||||
|
// example message:: SP8EBC>APX216,TCPIP*,qAC,NINTH::SR9WXZ :tedt{0s}\r\n
|
||||||
|
|
||||||
|
// result returned by the function, although shamesly it is also used as local aux variable
|
||||||
|
// in few places of this function :( this is what You sometimes do to save some stack.
|
||||||
|
uint8_t result = 0xFF;
|
||||||
|
|
||||||
|
uint16_t i = 0;
|
||||||
|
|
||||||
|
if (output == 0x00) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message_ln < (MESSAGE_SENDER_CALL_SSID_MAXLEN + MESSAGE_RECIPIENT_FIELD_SIZE)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(message_atoi_buffer, 0x00, MESSAGE_ATOI_BUFFER);
|
||||||
|
|
||||||
|
// if start position of APRS message (position of recipient callsign) has not been provided
|
||||||
|
if ((src == MESSAGE_SOURCE_APRSIS) && (content_position == 0)) {
|
||||||
|
|
||||||
|
// look for it
|
||||||
|
for (i = 0; i < message_ln; i++) {
|
||||||
|
const uint8_t * this_character = message + i;
|
||||||
|
|
||||||
|
const uint8_t * next_character = message + i + 1;
|
||||||
|
|
||||||
|
// break on an end of input string
|
||||||
|
if (*this_character == 0x00) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if double semicolon has been found
|
||||||
|
if ((*this_character == ':') && (*next_character == ':')) {
|
||||||
|
// APRS message starts after second semicolong
|
||||||
|
content_position = i + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the iterator, it will be used across this function
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// check content position one more time to verify
|
||||||
|
// if input data contains APRS message at all
|
||||||
|
if (
|
||||||
|
((src == MESSAGE_SOURCE_APRSIS) && (content_position != 0)) ||
|
||||||
|
(src == MESSAGE_SOURCE_RADIO)
|
||||||
|
) {
|
||||||
|
|
||||||
|
// set this variable to zero as now it will be used as a local
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
// clear output structure to make room for new data
|
||||||
|
memset(output, 0x00, sizeof(message_t));
|
||||||
|
|
||||||
|
//extract sender call and SSID only if this message has been received from APRS-IS in pure text form
|
||||||
|
if (src == MESSAGE_SOURCE_APRSIS) {
|
||||||
|
// fast forward any potential whitespace at the begining
|
||||||
|
while (MESSAGE_CURRENT_SENDER_CHAR == ' ') {
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (i >= message_ln) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract sender callsign
|
||||||
|
for (; i < MESSAGE_SENDER_CALL_SSID_MAXLEN; i++) {
|
||||||
|
|
||||||
|
// if SSID separator or sender end character ('>') has been reached
|
||||||
|
if (MESSAGE_CURRENT_SENDER_CHAR == '-' || MESSAGE_CURRENT_SENDER_CHAR == '>') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->from.call[result++] = MESSAGE_CURRENT_SENDER_CHAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if sender has SSID
|
||||||
|
if (MESSAGE_CURRENT_SENDER_CHAR == '-') {
|
||||||
|
// jumps to next character. otherwise separating '-'
|
||||||
|
// will be interpreted as a minus/negitive sign
|
||||||
|
i++;
|
||||||
|
|
||||||
|
result = 0; // here used as a local iterator
|
||||||
|
|
||||||
|
// extract SSID
|
||||||
|
for (; i < MESSAGE_RECIPIENT_FIELD_SIZE; i++) {
|
||||||
|
// copy characters to aux buffer
|
||||||
|
message_atoi_buffer[result++] = MESSAGE_CURRENT_SENDER_CHAR;
|
||||||
|
|
||||||
|
// check if there isn't enough characters
|
||||||
|
if (result == MESSAGE_ATOI_BUFFER) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert SSID to int
|
||||||
|
output->from.ssid = atoi(message_atoi_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the iterator, it will be used across this function
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// clear content_position iterator
|
||||||
|
content_position = 0;
|
||||||
|
|
||||||
|
// find a begining of the message in data from radio channel
|
||||||
|
while (MESSAGE_CURRENT_CHAR != ':') {
|
||||||
|
content_position++;
|
||||||
|
|
||||||
|
if (content_position >= message_ln) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// jump over ':'
|
||||||
|
content_position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract recipient
|
||||||
|
for (; i < MESSAGE_RECIPIENT_FIELD_SIZE; i++) {
|
||||||
|
|
||||||
|
// look if end of callsign or separating '-' has been found
|
||||||
|
if (MESSAGE_CURRENT_CHAR == ' ' || MESSAGE_CURRENT_CHAR == '-') {
|
||||||
|
break; // and go for SSID reading
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy recipient callsign character per character
|
||||||
|
output->to.call[i] = MESSAGE_CURRENT_CHAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if callsign has SSID set
|
||||||
|
if (MESSAGE_CURRENT_CHAR == '-') {
|
||||||
|
// jumps to next character. otherwise separating '-'
|
||||||
|
// will be interpreted as a minus/negitive sign
|
||||||
|
i++;
|
||||||
|
|
||||||
|
result = 0; // here used as a local iterator
|
||||||
|
|
||||||
|
// extract SSID
|
||||||
|
for (; i < MESSAGE_RECIPIENT_FIELD_SIZE; i++) {
|
||||||
|
// copy characters to aux buffer
|
||||||
|
message_atoi_buffer[result++] = MESSAGE_CURRENT_CHAR;
|
||||||
|
|
||||||
|
// check if there isn't enough characters
|
||||||
|
if (result == MESSAGE_ATOI_BUFFER) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert SSID to int
|
||||||
|
output->to.ssid = atoi(message_atoi_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != MESSAGE_ATOI_BUFFER && /* if SSID extraction was OK and end of a buffer hasn't been reached */
|
||||||
|
(
|
||||||
|
(i < MESSAGE_RECIPIENT_FIELD_SIZE) || /* if recipient and callsign has been read before ':' separating from message content */
|
||||||
|
((i == MESSAGE_RECIPIENT_FIELD_SIZE) && (MESSAGE_CURRENT_CHAR == ':')) /* if a position of separating ':' was reached and ':' is there */
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
|
||||||
|
// reinitialize buffer before next usage
|
||||||
|
memset(message_atoi_buffer, 0x00, MESSAGE_ATOI_BUFFER);
|
||||||
|
|
||||||
|
// check if the iterator is set now to position of ':' separating
|
||||||
|
// recipient an the message itself
|
||||||
|
while(MESSAGE_CURRENT_CHAR != ':' && i <= MESSAGE_RECIPIENT_FIELD_SIZE) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// one more incrementation to jump over ':' and land on the first character of the message
|
||||||
|
i++;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
// then copy message, which ends on a counter, something like '{1'
|
||||||
|
while(MESSAGE_CURRENT_CHAR != ':' && i + content_position < message_ln) {
|
||||||
|
output->content[result++] = MESSAGE_CURRENT_CHAR;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// break on message counter separator
|
||||||
|
if (MESSAGE_CURRENT_CHAR == '{') {
|
||||||
|
i++; // move to first digit of a counter
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check which condition has ended previous 'while' loop and if an end of the buffer has been reached
|
||||||
|
if (i + content_position < message_ln) {
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
// now iterator is set (should be set) on a first digit of message counter
|
||||||
|
// copy everything until first non digit character is found
|
||||||
|
while (MESSAGE_IS_DIGIT(MESSAGE_CURRENT_CHAR)) {
|
||||||
|
message_atoi_buffer[result++] = MESSAGE_CURRENT_CHAR;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// check if there isn't enough characters
|
||||||
|
if (result == MESSAGE_ATOI_BUFFER) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert message counter from string to int
|
||||||
|
output->number = atoi(message_atoi_buffer);
|
||||||
|
|
||||||
|
if (result < MESSAGE_ATOI_BUFFER) {
|
||||||
|
// new we are done (??)
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param config_data
|
||||||
|
* @param message
|
||||||
|
* @return zero if this is a message to us, non zero otherwise
|
||||||
|
*/
|
||||||
|
uint8_t message_is_for_me(config_data_basic_t * config_data, const message_t * const message)
|
||||||
|
{
|
||||||
|
const int callsign = strncmp(config_data->callsign, message->to.call, 6);
|
||||||
|
|
||||||
|
if (callsign == 0 && (config_data->ssid == message->to.ssid)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param out_buffer
|
||||||
|
* @param out_buffer_ln
|
||||||
|
* @param message
|
||||||
|
* @param src how this message has been received
|
||||||
|
*/
|
||||||
|
void message_create_ack_for(uint8_t * out_buffer, const uint16_t out_buffer_ln, const message_t * const message, const message_source_t src)
|
||||||
|
{
|
||||||
|
int current_pos = 0;
|
||||||
|
|
||||||
|
uint8_t call_position = 0;
|
||||||
|
|
||||||
|
// clear output buffer
|
||||||
|
memset(out_buffer, 0x00, out_buffer_ln);
|
||||||
|
|
||||||
|
if (src == MESSAGE_SOURCE_APRSIS) {
|
||||||
|
|
||||||
|
// put my callsign
|
||||||
|
for (; call_position < 6; call_position++) {
|
||||||
|
// break on null character
|
||||||
|
if (message->to.call[call_position] == 0x00) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy callsign data
|
||||||
|
out_buffer[current_pos + call_position] = message->to.call[call_position];
|
||||||
|
}
|
||||||
|
|
||||||
|
current_pos += call_position;
|
||||||
|
|
||||||
|
call_position = 0;
|
||||||
|
|
||||||
|
// check if I have a SSID
|
||||||
|
if (message->to.ssid != 0) {
|
||||||
|
current_pos += snprintf(MESSAGE_ACK_CURRENT_POS, MESSAGE_ACK_REMAINING_BUF, "-%d", message->to.ssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// constant part
|
||||||
|
current_pos += snprintf(MESSAGE_ACK_CURRENT_POS, MESSAGE_ACK_REMAINING_BUF, ">AKLPRZ::");
|
||||||
|
|
||||||
|
// put sender callsign, station I received this message from
|
||||||
|
for (; call_position < 6; call_position++) {
|
||||||
|
// break on null character
|
||||||
|
if (message->from.call[call_position] == 0x00) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy callsign data
|
||||||
|
out_buffer[current_pos + call_position] = message->from.call[call_position];
|
||||||
|
}
|
||||||
|
|
||||||
|
// put sender SSID, station I received this message from
|
||||||
|
if (message->from.ssid != 0) {
|
||||||
|
call_position += snprintf(MESSAGE_ACK_CURRENT_POS + call_position, MESSAGE_ACK_REMAINING_BUF, "-%d", message->from.ssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if callsign was shorter than 6 characters
|
||||||
|
while (call_position < 9) {
|
||||||
|
// copy callsign data
|
||||||
|
out_buffer[current_pos + call_position] = ' ';
|
||||||
|
|
||||||
|
call_position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// callsign + ssid + padding must be exactly 9 characters long
|
||||||
|
current_pos += 9;
|
||||||
|
|
||||||
|
// then put 'ackXX' where X is message number
|
||||||
|
current_pos += snprintf(MESSAGE_ACK_CURRENT_POS, MESSAGE_ACK_REMAINING_BUF, ":ack%d", message->number);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Ładowanie…
Reference in New Issue