From b4cd12017c07eb1448badcf086da243c92ef13be Mon Sep 17 00:00:00 2001 From: Mateusz Lubecki Date: Sat, 22 Jul 2023 10:08:19 +0200 Subject: [PATCH] - KISS DID: distinguish size_byte value for integer and float types - KISS DID: returning did value as first two bytes, before size_byte - KISS diagnostics: bugfix in NRC service identifier - APRS-IS comm: better way to close tcp connection in case of connecting failure - functions to send status via radio channel moved to separate files. --- src/aprsis.c | 75 +++++++++++++++++-- src/kiss_protocol/kiss_callback.c | 6 ++ src/kiss_protocol/kiss_did.c | 100 +++++++++++++++++++++++--- src/kiss_protocol/kiss_nrc_response.c | 5 +- src/main.c | 19 ++++- src/packet_tx_handler.c | 1 + src/pwr_save.c | 37 +++++++++- src/rte_main.c | 2 + 8 files changed, 221 insertions(+), 24 deletions(-) diff --git a/src/aprsis.c b/src/aprsis.c index fabf524..2bc2997 100644 --- a/src/aprsis.c +++ b/src/aprsis.c @@ -9,6 +9,8 @@ #include "main.h" #include "text.h" +#include "etc/aprsis_config.h" + #include "gsm/sim800c.h" #include @@ -16,6 +18,9 @@ srl_context_t * aprsis_serial_port; +/** + * Pointer to used gsm_modem_state + */ gsm_sim800_state_t * aprsis_gsm_modem_state; /** @@ -44,14 +49,24 @@ int32_t aprsis_passcode; char aprsis_login_string[64]; /** - * Default APRS-IS address to be used by + * Default APRS-IS address to be used by 'aprsis_connect_and_login_default' function */ const char * aprsis_default_server_address; +/** + * String with a callsign and a ssid in aprsis format. Used sent auto beacon + * when connection to APRS-IS server is established + */ const char * aprsis_callsign_with_ssid; +/** + * Lenght of APRS-IS server address string + */ uint16_t aprsis_default_server_address_ln = 0; +/** + * TCP port used to connect to default APRS-IS server. + */ uint16_t aprsis_default_server_port; /** @@ -66,11 +81,30 @@ uint8_t aprsis_connected = 0; const char * aprsis_sucessfull_login = "# logresp\0"; +/** + * Counter of unsuccessful connects to APRS-IS, to trigger GSM modem reset. + * Please note that it works differently that 'aprsis_reset_on_timeout' and + * has nothing to do with a timeouts of already established connection. This + * counter will trigger GSM modem reset even if no APRS-IS connection has + * been established at all. It protects against a situation when GSM modem + * is not able to register in cellular network, SIM card is not working for + * some reason etc. Of course there is no guarantee that a reset in such + * case will help, but there is nothing better to do. + */ +uint8_t aprsis_unsucessfull_conn_counter = 0; + /** * A timestamp when server has send anything */ uint32_t aprsis_last_keepalive_ts = 0; +/** + * Set to one if the GSM modem shall be immediately reset when APRS-IS communication + * time out. Please note that this is different that 'aprsis_unsucessfull_conn_counter' + * and reseting GSM mode after many unsuccessfull connection attempts! This + * comes in when the connection has been established at least one time. It won't + * help if there is some problem with establishing connection at all. + */ uint32_t aprsis_reset_on_timeout = 0; #define APRSIS_TIMEOUT_MS 123000//123000 @@ -205,23 +239,40 @@ aprsis_return_t aprsis_connect_and_login(const char * address, uint8_t address_l } else { // if authoruzation wasn't successfull drop a connection - disconnection_result = gsm_sim800_tcpip_close(aprsis_serial_port, aprsis_gsm_modem_state, 0); + disconnection_result = aprsis_disconnect(); + + // increase failure counter + aprsis_unsucessfull_conn_counter++; } } } else { - disconnection_result = gsm_sim800_tcpip_close(aprsis_serial_port, aprsis_gsm_modem_state, 0); + disconnection_result = aprsis_disconnect(); + + // increase failure counter + aprsis_unsucessfull_conn_counter++; } } else { - disconnection_result = gsm_sim800_tcpip_close(aprsis_serial_port, aprsis_gsm_modem_state, 1); + disconnection_result = aprsis_disconnect(); + + // increase failure counter + aprsis_unsucessfull_conn_counter++; } } // if a connection has been ordered to close, but there were severe errors during that - if (disconnection_result == SIM800_TCP_CLOSE_UNCERTAIN || disconnection_result == SIM800_RECEIVING_TIMEOUT) { + if (disconnection_result == SIM800_TCP_CLOSE_UNCERTAIN || + disconnection_result == SIM800_RECEIVING_TIMEOUT || + aprsis_unsucessfull_conn_counter > APRSIS_FAILED_CONN_ATTEMPTS_TO_RESET_GSM) { + + // reset unsuccesfull connection counter back to zero + aprsis_unsucessfull_conn_counter = 0; + + // and reset GSM modem gsm_sim800_reset(aprsis_gsm_modem_state); } + } return out; @@ -238,12 +289,17 @@ aprsis_return_t aprsis_connect_and_login_default(uint8_t auto_send_beacon) { return aprsis_connect_and_login(aprsis_default_server_address, aprsis_default_server_address_ln, aprsis_default_server_port, auto_send_beacon); } -void aprsis_disconnect(void) { - gsm_sim800_tcpip_close(aprsis_serial_port, aprsis_gsm_modem_state, 0); +sim800_return_t aprsis_disconnect(void) { + + sim800_return_t out; + + out = gsm_sim800_tcpip_close(aprsis_serial_port, aprsis_gsm_modem_state, 0); aprsis_logged = 0; aprsis_connected = 0; + + return out; } void aprsis_receive_callback(srl_context_t* srl_context) { @@ -278,6 +334,7 @@ void aprsis_check_alive(void) { aprsis_connected = 0; + // check if it is intendend to reset GSM modem in case of timeout if (aprsis_reset_on_timeout == 0) { // close connection with force flag as it is uncertain if a remote server // finished connection explicitly, or the connection is stuck for @@ -491,3 +548,7 @@ void aprsis_igate_to_aprsis(AX25Msg *msg, const char * callsign_with_ssid) { char * aprsis_get_tx_buffer(void) { return aprsis_packet_tx_buffer; } + +uint8_t aprsis_get_aprsis_logged(void) { + return aprsis_logged; +} diff --git a/src/kiss_protocol/kiss_callback.c b/src/kiss_protocol/kiss_callback.c index d611f59..16dca61 100644 --- a/src/kiss_protocol/kiss_callback.c +++ b/src/kiss_protocol/kiss_callback.c @@ -221,6 +221,12 @@ int32_t kiss_callback_program_startup(uint8_t* input_frame_from_host, uint16_t i int32_t kiss_callback_read_did(uint8_t* input_frame_from_host, uint16_t input_len, uint8_t* response_buffer, uint16_t buffer_size) { + /** + * Response frame structure + * + * FEND, KISS_READ_DID_RESP, DID_lsb, DID_msb, size_byte, DATA (...), FEND + */ + int32_t out = 0; // result to be returned to the host PC diff --git a/src/kiss_protocol/kiss_did.c b/src/kiss_protocol/kiss_did.c index a21d3e8..5082e8a 100644 --- a/src/kiss_protocol/kiss_did.c +++ b/src/kiss_protocol/kiss_did.c @@ -71,6 +71,15 @@ static uint8_t kiss_did_how_much_data(kiss_did_numeric_definition_t * definition if (definition->third_data != &DID_EMPTY) { out++; } + else { + // zero data size as DID_EMPTY is only a dummy placeholder + definition->third_data_size = 0; + } + } + else { + // zero data size as DID_EMPTY is only a dummy placeholder + definition->third_data_size = 0; + definition->second_data_size = 0; } } } @@ -79,7 +88,7 @@ static uint8_t kiss_did_how_much_data(kiss_did_numeric_definition_t * definition } /** - * Checks if this DID + * Checks if this DID defines data with float * @param definition * @return */ @@ -87,7 +96,11 @@ static int kiss_did_validate_is_float(kiss_did_numeric_definition_t * definition int out = 0; if (definition != 0) { - + if (kiss_did_how_much_data(definition) >= 1) { + if (definition->first_data_size == 0 && definition->second_data_size == 0 && definition->third_data_size == 0) { + out = 1; + } + } } return out; @@ -229,11 +242,11 @@ uint8_t kiss_did_response(uint16_t identifier, uint8_t * output_buffer, uint16_t * float (also one, two or three). size_byte is used to distinguish * between these three formats. It works like that * - * 0y - If most significant nibble is set to zero, size_byte will + * 0y - If most significant bit is set to zero, size_byte will * signalize string DID as ASCII characters from basic ASIC * table are from range 0 to 127 - * 10 - If most significant nibble is set to zero AND less significant - * nibble is set to zero this DID returns integer data. In such + * 10 - If most significant bit is set to zero AND next significant + * bit is set to zero this DID returns integer data. In such * case three groups of two bits controls a size of data according * to 'kiss_did_sizeof_to_sizebyte_mapping'. If a group of two bits * is set to 0 it means that DID consist less than 3 variables @@ -272,8 +285,15 @@ uint8_t kiss_did_response(uint16_t identifier, uint8_t * output_buffer, uint16_t // check if this is string did const int is_string = kiss_did_validate_is_string(&found); + // check if this is float number did + const int is_float = kiss_did_validate_is_float(&found); + // if something has been found and it is valid - if (found.identifier != 0xFFFFu && is_valid == 1) { + if (found.identifier != 0xFFFFu && is_valid == 1 && is_float == 0) { + + // put DID itself at the begining of a response + output_buffer[0] = (identifier & 0xFF); + output_buffer[1] = (identifier & 0xFF00) >> 8; // set the sign bit in size_byte to distinguish that from ASCII did. // ASCII characters are from range 0 - 127 so they never have that @@ -289,9 +309,10 @@ uint8_t kiss_did_response(uint16_t identifier, uint8_t * output_buffer, uint16_t // append a size of third data source size_byte |= (kiss_did_sizeof_to_sizebyte_mapping[found.third_data_size] << 4); - output_buffer[0] = size_byte; + output_buffer[2] = size_byte; - output_buffer++; + // move after DID value and size_byte + output_buffer += 3; //append first data source memcpy(output_buffer, found.first_data, found.first_data_size); @@ -324,15 +345,74 @@ uint8_t kiss_did_response(uint16_t identifier, uint8_t * output_buffer, uint16_t // also include size_byte in this calculation out++; + // include DID value itself + out += 2; + + } + else if (found.identifier != 0xFFFFu && is_valid == 1 && is_float == 1) { + + // put DID itself at the begining of a response + output_buffer[0] = (identifier & 0xFF); + output_buffer[1] = (identifier & 0xFF00) >> 8; + + // set two most significant bits to one to signalize that it is + size_byte |= 0xC0u; + + size_byte |= number_of_data_source; + + output_buffer[2] = size_byte; + + // move after DID value and size_byte + output_buffer += 3; + + //append first data source + memcpy(output_buffer, found.first_data, sizeof(float)); + + //move forward a poiner to response buffer + output_buffer += sizeof(float); + + out += found.first_data_size; + + if (number_of_data_source > 1) { + //append second data source + memcpy(output_buffer, found.second_data, sizeof(float)); + + //move forward a poiner to response buffer + output_buffer += sizeof(float); + + out += sizeof(float); + } + + if (number_of_data_source > 2) { + //append third data source + memcpy(output_buffer, found.third_data, sizeof(float)); + + //move forward a poitner to response buffer + output_buffer += sizeof(float); + + out += sizeof(float); + } + + // also include size_byte in this calculation + out++; + + // include DID value itself + out += 2; + } else if (found.identifier != 0xFFFFu && is_string == 1) { + + // put DID itself at the begining of a response + output_buffer[0] = (identifier & 0xFF); + output_buffer[1] = (identifier & 0xFF00) >> 8; + // if this is a string DID const char * str = (char *)found.first_data; const size_t str_len = strlen(str); - if (str_len > buffer_ln) { - memcpy(output_buffer, found.first_data, buffer_ln); + if (str_len - 2 > buffer_ln) { + memcpy(output_buffer + 2, found.first_data, buffer_ln); } else { memcpy(output_buffer, found.first_data, str_len); diff --git a/src/kiss_protocol/kiss_nrc_response.c b/src/kiss_protocol/kiss_nrc_response.c index baa9cff..03040e1 100644 --- a/src/kiss_protocol/kiss_nrc_response.c +++ b/src/kiss_protocol/kiss_nrc_response.c @@ -9,6 +9,7 @@ #include #include "kiss_communication/kiss_communication_nrc_t.h" #include "kiss_communication/kiss_communication.h" +#include "kiss_communication/kiss_communication_service_ids.h" #include "kiss_configuation.h" #include @@ -21,7 +22,7 @@ static const uint8_t kiss_nrc_response_unknown_service[KISS_NRC_RESPONSE_UNKNOWN FEND, NONSTANDARD, KISS_NRC_RESPONSE_UNKNOWN_SERVICE_LN, - KISS_COMMUNICATION_NRC_SERVICE, + KISS_NEGATIVE_RESPONSE_SERVICE, NRC_SERVICE_NOT_SUPPORTED, FEND}; @@ -29,7 +30,7 @@ static const uint8_t kiss_nrc_response_out_of_range[KISS_NRC_RESPONSE_OUT_OF_RAN FEND, NONSTANDARD, KISS_NRC_RESPONSE_UNKNOWN_SERVICE_LN, - KISS_COMMUNICATION_NRC_SERVICE, + KISS_NEGATIVE_RESPONSE_SERVICE, NRC_REQUEST_OUT_OF_RANGE, FEND }; diff --git a/src/main.c b/src/main.c index 409bf6e..e8ffb75 100644 --- a/src/main.c +++ b/src/main.c @@ -1181,7 +1181,7 @@ int main(int argc, char* argv[]){ // if aprsis is logged if (aprsis_connected == 1) { - aprsis_igate_to_aprsis(&ax25_rxed_frame, &main_callsign_with_ssid); + aprsis_igate_to_aprsis(&ax25_rxed_frame, (const char *)&main_callsign_with_ssid); } #endif @@ -1432,7 +1432,22 @@ int main(int argc, char* argv[]){ #ifdef PARAMETEO if (main_config_data_mode->gsm == 1) { - if (gsm_sim800_gprs_ready == 1) { + // check if GSM modem must be power-cycled / restarted like after + // waking up from deep sleep or chaning power saving mode + if (rte_main_reset_gsm_modem == 1) { + // rest the flag + rte_main_reset_gsm_modem = 0; + + // reset gsm modem + gsm_sim800_reset(&main_gsm_state); + + // please remember that a reset might not be performed if + // the GSM modem is inhibited completely, due to current + // power saving mode and few another things. In that case + // the flag will be cleared but modem NOT restarted + } + + if (aprsis_get_aprsis_logged() == 1) { led_control_led1_upper(true); } else { diff --git a/src/packet_tx_handler.c b/src/packet_tx_handler.c index 14e0125..1cb65e0 100644 --- a/src/packet_tx_handler.c +++ b/src/packet_tx_handler.c @@ -9,6 +9,7 @@ #include "station_config_target_hw.h" #include "./aprs/beacon.h" +#include "./aprs/status.h" #include "./aprs/wx.h" #include "./aprs/telemetry.h" diff --git a/src/pwr_save.c b/src/pwr_save.c index edd23be..83a2f40 100644 --- a/src/pwr_save.c +++ b/src/pwr_save.c @@ -18,8 +18,9 @@ #include "packet_tx_handler.h" #include "wx_handler.h" #include "main.h" -#include "telemetry.h" +#include "status.h" #include "afsk_pr.h" +#include "gsm/sim800c.h" #include "rte_main.h" @@ -312,6 +313,9 @@ int pwr_save_switch_mode_to_c0(void) { // turn ON +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_enable(); + // deinhibit GSM modem + gsm_sim800_inhibit(0); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -349,6 +353,9 @@ int pwr_save_switch_mode_to_c1(void) { // turn ON +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_enable(); + // inhibit GSM modem + gsm_sim800_inhibit(1); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -387,6 +394,9 @@ void pwr_save_switch_mode_to_c2(void) { // turn ON +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_enable(); + // inhibit GSM modem + gsm_sim800_inhibit(1); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -421,6 +431,9 @@ void pwr_save_switch_mode_to_c3(void) { // turn ON +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_enable(); + // deinhibit GSM modem + gsm_sim800_inhibit(0); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -456,6 +469,9 @@ int pwr_save_switch_mode_to_m4(void) { // turn ON +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_enable(); + // inhibit GSM modem + gsm_sim800_inhibit(1); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -490,6 +506,9 @@ int pwr_save_switch_mode_to_m4a(void) { // turn ON +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_enable(); + // deinhibit GSM modem + gsm_sim800_inhibit(0); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -525,6 +544,9 @@ void pwr_save_switch_mode_to_i5(void) { // turn OFF +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_disable(); + // inhibit GSM modem + gsm_sim800_inhibit(1); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -575,6 +597,9 @@ void pwr_save_switch_mode_to_l6(uint16_t sleep_time) { // turn OFF +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_disable(); + // de inhibit GSM modem + gsm_sim800_inhibit(0); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -640,6 +665,9 @@ void pwr_save_switch_mode_to_l7(uint16_t sleep_time) { // turn OFF +5V_C (SD card, PT100 interface and Op Amplifier) io___cntrl_vbat_c_disable(); + // inhibit GSM modem + gsm_sim800_inhibit(1); + // unlock access to backup registers pwr_save_unclock_rtc_backup_regs(); @@ -915,7 +943,7 @@ void pwr_save_pooling_handler(const config_data_mode_t * config, const config_da } else { // WX + GSM (only) if (timers->wx_transmit_period >= 5) { - // if stations is configured to send wx packet less often than every 5 minutes + // if stations is configured to send wx packet less frequent than every 5 minutes if (minutes_to_wx > 1) { main_set_monitor(16); @@ -924,7 +952,7 @@ void pwr_save_pooling_handler(const config_data_mode_t * config, const config_da pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - 60); // TODO: !!! } else { - if (pwr_save_seconds_to_wx <= 30) { + if (pwr_save_seconds_to_wx <= 50) { // if there is 30 seconds or less to next wx packet reinit_sensors = pwr_save_switch_mode_to_c0(); } @@ -1005,6 +1033,9 @@ void pwr_save_pooling_handler(const config_data_mode_t * config, const config_da // reinitialize all i2c sensors wx_force_i2c_sensor_reset = 1; + // reset GSM modem, internally this also check if GSM modem is inhibited or not + rte_main_reset_gsm_modem = 1; + // reinitialize everything realted to anemometer analog_anemometer_init(main_config_data_mode->wx_anemometer_pulses_constant, 38, 100, 1); diff --git a/src/rte_main.c b/src/rte_main.c index 75ce1f3..17083a9 100644 --- a/src/rte_main.c +++ b/src/rte_main.c @@ -29,5 +29,7 @@ uint16_t rte_main_wakeup_count = 0; uint16_t rte_main_going_sleep_count = 0; uint32_t rte_main_last_sleep_master_time = 0; + +uint8_t rte_main_reset_gsm_modem = 0; #endif