#include "packet_tx_handler.h"
#include "wx_handler.h"
#include "backup_registers.h"

#include "rte_wx.h"
#include "rte_pv.h"
#include "rte_main.h"

#include "station_config.h"
#include "station_config_target_hw.h"

#include "./aprs/beacon.h"
#include "./aprs/status.h"
#include "./aprs/wx.h"
#include "./aprs/telemetry.h"

#include "./drivers/serial.h"

#include "./umb_master/umb_master.h"

#include "../include/etc/rtu_configuration.h"

#ifdef STM32L471xx
#include "aprsis.h"
#include "api/api.h"
#include "pwr_save.h"
#include "nvm.h"

#include "gsm/sim800c_gprs.h"
#endif

#include "main.h"
#include "delay.h"
#include "io.h"

#define _TELEM_DESCR_INTERVAL	150

uint8_t packet_tx_beacon_interval = 0;
uint8_t packet_tx_beacon_counter = 0;

uint8_t packet_tx_error_status_interval = 2;
uint8_t packet_tx_error_status_counter = 0;

uint8_t packet_tx_meteo_interval = 0;
uint8_t packet_tx_meteo_counter = 0;

uint8_t packet_tx_meteo_kiss_interval = 2;
uint8_t packet_tx_meteo_kiss_counter = 0;

uint8_t packet_tx_telemetry_interval = 10;
uint8_t packet_tx_telemetry_counter = 0;

uint8_t packet_tx_telemetry_descr_interval = 155;	// 155
uint8_t packet_tx_telemetry_descr_counter = 10;

uint8_t packet_tx_modbus_raw_values = (uint8_t)(_TELEM_DESCR_INTERVAL - _WX_INTERVAL * (uint8_t)(_TELEM_DESCR_INTERVAL / 38));
uint8_t packet_tx_modbus_status = (uint8_t)(_TELEM_DESCR_INTERVAL - _WX_INTERVAL * (uint8_t)(_TELEM_DESCR_INTERVAL / 5));

uint8_t packet_tx_more_than_one = 0;

#ifdef PARAMETEO
uint8_t packet_tx_trigger_tcp = 0;

uint8_t packet_tx_meteo_gsm_interval = 2;
uint8_t packet_tx_meteo_gsm_counter = 0;

//!< Flag set to one after weather packet has been just send to APRS-IS via GPRS modem and the modem is probably transmitting now
uint8_t packet_tx_meteo_gsm_has_been_sent = 0;

#define API_TRIGGER_STATUS 		(1 << 1)
#define API_TRIGGER_METEO		(1 << 2)
#define APRSIS_TRIGGER_METEO	(1 << 3)
#define RECONNECT_APRSIS		(1 << 7)

nvm_measurement_t packet_tx_nvm;

//!< Flag set to one after the gsm status message is sent over radio.
uint8_t packet_tx_gsm_status_sent = 0;
#endif

void packet_tx_send_wx_frame(void) {
	main_wait_for_tx_complete();

	SendWXFrame(rte_wx_average_windspeed, rte_wx_max_windspeed, rte_wx_average_winddirection, rte_wx_temperature_average_external_valid, rte_wx_pressure_valid, rte_wx_humidity_valid);

}

void packet_tx_init(uint8_t meteo_interval, uint8_t beacon_interval, config_data_powersave_mode_t powersave) {
	packet_tx_meteo_interval = meteo_interval;

	packet_tx_beacon_interval = beacon_interval;

	backup_reg_get_packet_counters(&packet_tx_beacon_counter, &packet_tx_meteo_counter, &packet_tx_meteo_gsm_counter);

	if (powersave == PWSAVE_AGGRESV) {
		// if user selected aggressive powersave mode the meteo counter must be set back to zero
		// to prevent quirks with waking from sleep mode
		packet_tx_meteo_counter = 0;
	}



}

void packet_tx_restore_from_backupregs(void) {

}

/**
 * This function is called from the inside of 'packet_rx_handler' to put an extra wait
 * if more than one packet is sent from the single call to that function. This is required
 * to protect against jamming own frames when any path is configured.
 *
 */
inline void packet_tx_multi_per_call_handler(void) {
	// if this consecutive frame sent from one call to this function
	if (packet_tx_more_than_one > 0) {
		// wait for previous transmission to complete
		main_wait_for_tx_complete();

		// wait for any possible retransmission to kick in
		delay_fixed(2000);

	   // reload watchdog counter
		main_reload_internal_wdg();

	}
	else {
		packet_tx_more_than_one = 1;
	}
}

// this shall be called in 10 seconds interval
void packet_tx_tcp_handler(void) {
#ifdef STM32L471xx

	// TODO: fixme currently there is no way to have APRS-IS and rest api
	// client working at the same time

	aprsis_return_t aprsis_result = APRSIS_UNKNOWN;

	if ((packet_tx_trigger_tcp & APRSIS_TRIGGER_METEO) != 0) {
		if (gsm_sim800_tcpip_tx_busy() == 0 && aprsis_connected == 1) {

				aprsis_send_wx_frame(
						rte_wx_average_windspeed,
						rte_wx_max_windspeed,
						rte_wx_average_winddirection,
						rte_wx_temperature_average_external_valid,
						rte_wx_pressure_valid,
						rte_wx_humidity_valid,
						main_callsign_with_ssid,
						main_string_latitude,
						main_string_longitude,
						main_config_data_basic);

				// clear the flag requesting weather packet transmission
				packet_tx_trigger_tcp ^= APRSIS_TRIGGER_METEO;

				// set this flag to one to inhibit power saving state machine
				// for a while (10 seconds) when GPRS modem is communicating
				// with the GSM radio network and sending the data independently
				// from the controller
				packet_tx_meteo_gsm_has_been_sent = 1;
			}
	}
	else if ((packet_tx_trigger_tcp & API_TRIGGER_STATUS) != 0) {

		// TODO: fixme
		// check if APRS-IS is connected
		if (aprsis_connected != 0) {
			// disconnect it before call to API - this disconnection has blocking IO
			aprsis_disconnect();

			// remember to reconnect APRSIS after all API comm will be done
			packet_tx_trigger_tcp |= RECONNECT_APRSIS;

		}
		// TODO: fixme

		// send status (async)
		api_send_json_status();

		// clear the bit
		packet_tx_trigger_tcp ^= API_TRIGGER_STATUS;
	}
	else if ((packet_tx_trigger_tcp & API_TRIGGER_METEO) != 0) {

		// TODO: fixme
		// check if APRS-IS is connected
		if (aprsis_connected != 0) {
			// disconnect it before call to API - this disconnection has blocking IO
			aprsis_disconnect();

			// remember to reconnect APRSIS after all API comm will be done
			packet_tx_trigger_tcp |= RECONNECT_APRSIS;

		}
		// TODO: fixme

		api_calculate_mac();
		api_send_json_measuremenets();

		// clear the bit
		packet_tx_trigger_tcp ^= API_TRIGGER_METEO;
	}
	else if ((packet_tx_trigger_tcp & RECONNECT_APRSIS) != 0) {
		// TODO: fixme
//		result = aprsis_connect_and_login_default(1);
//
//		if (result == APRSIS_OK) {
			packet_tx_trigger_tcp ^= RECONNECT_APRSIS;
//		}
	}
	else {
		// after 10 second from setting this flag the packet should be
		// sent
		packet_tx_meteo_gsm_has_been_sent = 0;
	}
#endif
}

// this shall be called in 60 seconds intervals
void packet_tx_handler(const config_data_basic_t * const config_basic, const config_data_mode_t * const config_mode) {
	dallas_qf_t dallas_qf = DALLAS_QF_UNKNOWN;

	pressure_qf_t pressure_qf = PRESSURE_QF_UNKNOWN;
	humidity_qf_t humidity_qf = HUMIDITY_QF_UNKNOWN;
	wind_qf_t wind_qf = WIND_QF_UNKNOWN;

	uint16_t ln = 0;

	// set to one if more than one packet will be send from this function at once (like beacon + telemetry)
	packet_tx_more_than_one = 0;

	// increase beacon transmit counters
	packet_tx_beacon_counter++;
	packet_tx_error_status_counter++;
	packet_tx_telemetry_counter++;
	packet_tx_telemetry_descr_counter++;
	if ((main_config_data_mode->wx & WX_ENABLED) == WX_ENABLED) {
		// increase these counters only when WX is enabled
		packet_tx_meteo_counter++;
		packet_tx_meteo_kiss_counter++;
		packet_tx_meteo_gsm_counter++;
	}

	// check if there is a time to send own beacon
	if (packet_tx_beacon_counter >= packet_tx_beacon_interval && packet_tx_beacon_interval != 0) {

		packet_tx_multi_per_call_handler();

		beacon_send_own(0, 0);

		packet_tx_beacon_counter = 0;


	}

	// if WX is enabled
	if ((main_config_data_mode->wx & WX_ENABLED) == WX_ENABLED) {

		// check if there is a time to send meteo packet through RF
		if (packet_tx_meteo_counter >= packet_tx_meteo_interval && packet_tx_meteo_interval != 0) {

#ifdef STM32L471xx
			if (config_mode->nvm_logger != 0) {
				packet_tx_nvm.temperature_humidity = wx_get_nvm_record_temperature();
				packet_tx_nvm.wind = wx_get_nvm_record_wind();
				packet_tx_nvm.timestamp = main_get_nvm_timestamp();

				// write to NVM if it is enabled
				nvm_measurement_store(&packet_tx_nvm);
			}
#endif

			// this function is required if more than one RF frame will be send from this function at once
			// it waits for transmission completion and add some delay to let digipeaters do theris job
			packet_tx_multi_per_call_handler();

			// send WX frame through RF
			SendWXFrame(rte_wx_average_windspeed, rte_wx_max_windspeed, rte_wx_average_winddirection, rte_wx_temperature_average_external_valid, rte_wx_pressure_valid, rte_wx_humidity_valid);

			/**
			 * debug
			 *
			 *	#define REGISTER_LAST_SLEEP	RTC->BKP1R
				#define REGISTER_LAST_WKUP	RTC->BKP2R
				#define REGISTER_COUNTERS	RTC->BKP4R
			 *
			 */

			// service external watchdog while sending weather frame
			io_ext_watchdog_service();

			// check if user want's to send two wx packets one after another
			if (main_config_data_basic->wx_double_transmit == 1) {
				rte_main_trigger_wx_packet = 1;
			}

			packet_tx_meteo_counter = 0;
		}

		// if modus RTU client is enabled with debugging
		if ((main_config_data_mode->wx_modbus & WX_MODBUS_DEBUG) == WX_MODBUS_DEBUG) {
			// send the status packet with raw values of all requested modbus-RTU registers
			if (packet_tx_meteo_counter == (packet_tx_meteo_interval - 1) &&
					packet_tx_telemetry_descr_counter >= packet_tx_modbus_raw_values)
			{


				packet_tx_multi_per_call_handler();

				status_send_raw_values_modbus();
			}
		}

// there is no sense to include support for Victron VE.Direct in parameteo
// which has its own charging controller
#ifndef PARAMETEO
		// check if Victron VE.Direct serial protocol client is enabled and it is
		// a time to send the status message
		if (config_mode->victron == 1 &&
			packet_tx_meteo_counter == (packet_tx_meteo_interval - 1) &&
			packet_tx_telemetry_descr_counter >= packet_tx_modbus_raw_values)
		{
			packet_tx_multi_per_call_handler();

			telemetry_send_status_pv(&rte_pv_average, &rte_pv_last_error, rte_pv_struct.system_state, master_time, rte_pv_messages_count, rte_pv_corrupted_messages_count);

		}
#endif

#ifdef PARAMETEO
		if (packet_tx_meteo_gsm_counter >= packet_tx_meteo_gsm_interval && gsm_sim800_gprs_ready == 1) {
			if (main_config_data_gsm->aprsis_enable == 0 && main_config_data_gsm->api_enable == 1) {
				// and trigger API wx packet transmission
				packet_tx_trigger_tcp |= API_TRIGGER_METEO;
			}
			else if (main_config_data_gsm->aprsis_enable == 1 && main_config_data_gsm->api_enable == 0) {
				packet_tx_trigger_tcp |= APRSIS_TRIGGER_METEO;
			}
			else {
				packet_tx_trigger_tcp = 0;
			}

			packet_tx_meteo_gsm_counter = 0;
		}
#endif

		// send wx frame to KISS host once every two minutes
		if (packet_tx_meteo_kiss_counter >= packet_tx_meteo_kiss_interval && main_kiss_enabled == 1) {

			// wait if serial port is currently used
			srl_wait_for_tx_completion(main_kiss_srl_ctx_ptr);

			// create wx data packet into specified buffer
			SendWXFrameToKissBuffer(rte_wx_average_windspeed, rte_wx_max_windspeed, rte_wx_average_winddirection, rte_wx_temperature_average_external_valid, rte_wx_pressure_valid, rte_wx_humidity_valid, main_kiss_srl_ctx_ptr->srl_tx_buf_pointer, main_kiss_srl_ctx_ptr->srl_tx_buf_ln, &ln);

			srl_start_tx(main_kiss_srl_ctx_ptr, ln);

			packet_tx_meteo_kiss_counter = 0;
		}
	}

	if (packet_tx_telemetry_counter >= packet_tx_telemetry_interval) {

		packet_tx_multi_per_call_handler();

		// ASSEMBLY QUALITY FACTORS

		// if there weren't any errors related to the communication with DS12B20 from previous function call
		if (rte_wx_error_dallas_qf == DALLAS_QF_UNKNOWN) {
			dallas_qf = rte_wx_current_dallas_qf;	// it might be DEGRADATED so we need to copy a value directly

			// reset current QF to check if there will be at least one successfull readout of temperature
			rte_wx_current_dallas_qf = DALLAS_QF_UNKNOWN;
		}

		// if there were any errors
		else {

			// if we had at least one successfull communication with the sensor
			if (rte_wx_current_dallas_qf == DALLAS_QF_FULL || rte_wx_current_dallas_qf == DALLAS_QF_DEGRADATED) {
				// set the error reason
				dallas_qf = DALLAS_QF_DEGRADATED;
			}
			// if they wasn't any successfull comm
			else {
				// set that it is totally dead and not avaliable
				dallas_qf = DALLAS_QF_NOT_AVALIABLE;
			}

			// and reset the error
			rte_wx_error_dallas_qf = DALLAS_QF_UNKNOWN;

			rte_wx_current_dallas_qf = DALLAS_QF_UNKNOWN;
		}

		// get quality factors for internal pressure and humidity sensors
		if (config_mode->wx_ms5611_or_bme == 0) {
			// pressure sensors quality factors

			switch (rte_wx_ms5611_qf) {
				case MS5611_QF_FULL: pressure_qf = PRESSURE_QF_FULL; break;
				case MS5611_QF_NOT_AVALIABLE: pressure_qf = PRESSURE_QF_NOT_AVALIABLE; break;
				case MS5611_QF_DEGRADATED: pressure_qf = PRESSURE_QF_DEGRADATED; break;
				case MS5611_QF_UNKNOWN: pressure_qf = PRESSURE_QF_UNKNOWN; break;
			}

		}
		else if (config_mode->wx_ms5611_or_bme == 1) {
			//#elif defined(_SENSOR_BME280)
			// humidity sensors quality factors
			if (rte_wx_bme280_qf == BME280_QF_UKNOWN) {
				;
			}
			else {
				// use BME280
				switch (rte_wx_bme280_qf) {
					case BME280_QF_FULL:
					case BME280_QF_PRESSURE_DEGRADED: humidity_qf = HUMIDITY_QF_FULL; break;
					case BME280_QF_UKNOWN:
					case BME280_QF_NOT_AVAILABLE: humidity_qf = HUMIDITY_QF_NOT_AVALIABLE; break;
					case BME280_QF_HUMIDITY_DEGRADED:
					case BME280_QF_GEN_DEGRADED: humidity_qf = HUMIDITY_QF_DEGRADATED; break;
				}

				switch (rte_wx_bme280_qf) {
					case BME280_QF_FULL:
					case BME280_QF_HUMIDITY_DEGRADED: pressure_qf = PRESSURE_QF_FULL; break;
					case BME280_QF_UKNOWN:
					case BME280_QF_NOT_AVAILABLE: pressure_qf = PRESSURE_QF_NOT_AVALIABLE; break;
					case BME280_QF_PRESSURE_DEGRADED:
					case BME280_QF_GEN_DEGRADED: pressure_qf = PRESSURE_QF_DEGRADATED; break;
				}

			}
		}
		else {
			pressure_qf = PRESSURE_QF_NOT_AVALIABLE;
			humidity_qf = HUMIDITY_QF_NOT_AVALIABLE;
		}

		// additional check for modbus RTU humidity sensor
		if (config_mode->wx_modbus == 1) {
			// for sake of simplicity there is another variable
			// which holds common information if valid humidity
			// is available or not. This is kinda-sorta duplication of
			// quality factors for each sensor types, although it
			// simplifies few things and omits handling separate
			// Modbus-RTU configuration here
			if (rte_wx_humidity_available == 0) {
				humidity_qf = HUMIDITY_QF_NOT_AVALIABLE;
			}
			else if (rte_wx_humidity_available == 1) {
				humidity_qf = HUMIDITY_QF_FULL;
			}

		}

		// wind quality factor
		if (rte_wx_wind_qf == AN_WIND_QF_UNKNOWN) {
			;
		}
		else {
			switch (rte_wx_wind_qf) {
				case AN_WIND_QF_FULL: wind_qf = WIND_QF_FULL; break;
				case AN_WIND_QF_DEGRADED_DEBOUNCE:
				case AN_WIND_QF_DEGRADED_SLEW:
				case AN_WIND_QF_DEGRADED: wind_qf = WIND_QF_DEGRADATED; break;
				case AN_WIND_QF_NOT_AVALIABLE:
				case AN_WIND_QF_UNKNOWN: wind_qf = WIND_QF_NOT_AVALIABLE; break;
			}

			rte_wx_wind_qf = AN_WIND_QF_UNKNOWN;
		}

		if (config_mode->victron == 1) {
			telemetry_send_values_pv(rx10m, digi10m, rte_pv_battery_current, rte_pv_battery_voltage, rte_pv_cell_voltage, dallas_qf, pressure_qf, humidity_qf, wind_qf);
		}
		else {

#ifdef PARAMETEO
			// if _DALLAS_AS_TELEM will be enabled the fifth channel will be set to temperature measured by DS12B20
			//telemetry_send_values(rx10m, tx10m, digi10m, kiss10m, rte_wx_temperature_dallas_valid, dallas_qf, rte_wx_ms5611_qf, rte_wx_dht_valid.qf, rte_wx_umb_qf);
			if (config_mode->wx == 1) {

				// if _METEO will be enabled, but without _DALLAS_AS_TELEM the fifth channel will be used to transmit temperature from MS5611
				// which may be treated then as 'rack/cabinet internal temperature'. Dallas DS12B10 will be used for ragular WX frames
				telemetry_send_values(rx10m, tx10m, digi10m, rte_main_average_battery_voltage, digidrop10m, rte_wx_temperature_internal_valid, dallas_qf, pressure_qf, humidity_qf, wind_qf, pwr_save_currently_cutoff, config_mode);
			}
			else {
				// if user will disable both _METEO and _DALLAS_AS_TELEM value will be zeroed internally anyway
				telemetry_send_values(rx10m, tx10m, digi10m, rte_main_average_battery_voltage, digidrop10m, 0.0f, dallas_qf, pressure_qf, humidity_qf, wind_qf, pwr_save_currently_cutoff, config_mode);
			}
#else
				// if _DALLAS_AS_TELEM will be enabled the fifth channel will be set to temperature measured by DS12B20
				//telemetry_send_values(rx10m, tx10m, digi10m, kiss10m, rte_wx_temperature_dallas_valid, dallas_qf, rte_wx_ms5611_qf, rte_wx_dht_valid.qf, rte_wx_umb_qf);
			if (config_mode->wx == 1) {

				// if _METEO will be enabled, but without _DALLAS_AS_TELEM the fifth channel will be used to transmit temperature from MS5611
				// which may be treated then as 'rack/cabinet internal temperature'. Dallas DS12B10 will be used for ragular WX frames
				telemetry_send_values(rx10m, tx10m, digi10m, kiss10m, digidrop10m, rte_wx_temperature_internal_valid, dallas_qf, pressure_qf, humidity_qf, wind_qf, config_mode);
			}
			else {
				// if user will disable both _METEO and _DALLAS_AS_TELEM value will be zeroed internally anyway
				telemetry_send_values(rx10m, tx10m, digi10m, kiss10m, digidrop10m, 0.0f, dallas_qf, pressure_qf, humidity_qf, wind_qf, config_mode);
			}
#endif
		}
		packet_tx_telemetry_counter = 0;

		// service external watchdog while sending telemetry
		io_ext_watchdog_service();

#ifdef PARAMETEO
		aprsis_prepare_telemetry(
							telemetry_get_counter(),
							rx10m,
							tx10m,
							digi10m,
							telemetry_scaled_vbatt_voltage,
							digidrop10m,
							telemetry_scaled_temperature,
							telemetry_qf,
							telemetry_degr,
							telemetry_nav,
							telemetry_pressure_qf_navaliable,
							telemetry_humidity_qf_navaliable,
							telemetry_anemometer_degradated,
							telemetry_anemometer_navble,
							telemetry_vbatt_low,
							config_mode);
#endif

		rx10m = 0, tx10m = 0, digi10m = 0, kiss10m = 0, digidrop10m = 0;

	}

	if (packet_tx_telemetry_descr_counter >= packet_tx_telemetry_descr_interval) {

#ifdef PARAMETEO
		rte_main_trigger_gsm_telemetry_descriptions = 1;
		status_send_powersave_registers();
#endif

		packet_tx_multi_per_call_handler();

		if (config_mode->victron == 1) {
			telemetry_send_chns_description_pv(config_basic);


			if (rte_pv_battery_voltage == 0) {
				rte_main_reboot_req = 1;
			}

		}
		else {
			telemetry_send_chns_description(config_basic, config_mode);

			packet_tx_multi_per_call_handler();

		}

		status_send();


		if (config_mode->wx_umb == 1) {

			umb_clear_error_history(&rte_wx_umb_context);
		}

		#ifdef STM32L471xx
		if (main_config_data_gsm->aprsis_enable == 0 && main_config_data_gsm->api_enable == 1) {
			// and trigger API wx packet transmission
			packet_tx_trigger_tcp |= API_TRIGGER_STATUS;
		}
		else {
			packet_tx_trigger_tcp = 0;
		}
		#endif

		packet_tx_telemetry_descr_counter = 0;
	}

	// store counters in backup registers
	backup_reg_set_packet_counters(packet_tx_beacon_counter, packet_tx_meteo_counter, packet_tx_meteo_gsm_counter);

#ifdef STM32L471xx
	// if powersave mode allow to sent extensive status messages
	if (rte_main_curret_powersave_mode != PWSAVE_AGGRESV) {
		// if gsm modem is enabled
		if (main_config_data_mode->gsm != 0) {
			// if gprs is connected
			if (gsm_sim800_gprs_ready == 1) {
				// if no gsm status packet has been sent so far
				if (packet_tx_gsm_status_sent == 0) {

					// send a status
					status_send_gsm();

					// network parameters are not queries while APRS-IS connection is pending
					// so no sense to send status more than once after the initialization
					packet_tx_gsm_status_sent = 1;
				}
			}
			else {
				packet_tx_gsm_status_sent = 0;
			}
		}
	}
#endif


}

void packet_tx_get_current_counters(packet_tx_counter_values_t * out) {

	if (out != 0x00) {
		out->beacon_counter = packet_tx_beacon_counter;
		out->wx_counter = packet_tx_meteo_counter;
		out->gsm_wx_counter = packet_tx_meteo_gsm_counter;
		out->telemetry_counter = packet_tx_telemetry_counter;
		out->telemetry_desc_counter = packet_tx_telemetry_descr_counter;
		out->kiss_counter = packet_tx_meteo_kiss_counter;
	}
}

void packet_tx_set_current_counters(packet_tx_counter_values_t * in) {
	if (in != 0x00) {

		if (in->beacon_counter != 0)
			packet_tx_beacon_counter = in->beacon_counter;

		if (in->wx_counter != 0)
			packet_tx_meteo_counter = in->wx_counter;

		if (in->telemetry_counter != 0)
			packet_tx_telemetry_counter = in->telemetry_counter;

		if (in->telemetry_desc_counter != 0)
			packet_tx_telemetry_descr_counter = in->telemetry_desc_counter;

		if (in->kiss_counter != 0)
			packet_tx_meteo_kiss_counter = in->kiss_counter;

		if (in->gsm_wx_counter != 0)
			packet_tx_meteo_gsm_counter = in->gsm_wx_counter;
	}
	else {
		packet_tx_beacon_counter = 0;
		packet_tx_meteo_counter = 2;
		packet_tx_meteo_gsm_counter = 0;
		packet_tx_telemetry_counter = 0;
		packet_tx_telemetry_descr_counter = 10;
		packet_tx_meteo_kiss_counter = 0;
	}
}

/**
 * Returns how many minutes is left to next weather packet (on radio network!!).
 * Used in power saving state machine and to periodically reset VHF radio
 * if this feature is enabled in configuration
 * @return
 */
int16_t packet_tx_get_minutes_to_next_wx(void) {
	if (packet_tx_meteo_interval != 0) {
		return packet_tx_meteo_interval - packet_tx_meteo_counter;
	}
	else {
		return -1;
	}
}

/**
 * This function checks if at the moment any weather packet is scheduled to be sent
 * to APRS-IS server, or this packet has been just sent and GPRS module probably
 * communicate with GSM network now. The result of this check is used to
 * inhibit power saving state machine temporary, not to turn off or disable
 * GSM modem while it is talking with GSM radio network.
 * @return
 */
uint8_t packet_tx_is_gsm_meteo_pending(void) {
	uint8_t out = 0;
#ifdef STM32L471xx

	if (gsm_sim800_gprs_ready == 1 && (packet_tx_trigger_tcp & APRSIS_TRIGGER_METEO) != 0) {
		out = 1;
	}

	if (packet_tx_meteo_gsm_has_been_sent != 0) {
		out = 1;
	}
#endif

	return out;
}

void packet_tx_force_gsm_status(void) {
#ifdef STM32L471xx
	packet_tx_gsm_status_sent = 0;
#endif
}
