pull/2/head
Mateusz Lubecki 2021-03-22 22:28:26 +01:00
rodzic 135e11b6fb
commit f84a46da5c
19 zmienionych plików z 425 dodań i 204 usunięć

Wyświetl plik

@ -21,6 +21,12 @@ typedef struct config_data_mode_t {
uint8_t wx;
uint8_t wx_umb;
uint8_t wx_modbus;
uint8_t wx_davis;
uint8_t victron;
uint8_t digi_viscous;
@ -29,6 +35,7 @@ typedef struct config_data_mode_t {
uint8_t digi_viscous_delay_sec;
} config_data_mode_t;
typedef struct config_data_basic_t {
@ -69,7 +76,32 @@ typedef struct config_data_basic_t {
} config_data_basic_t;
typedef struct config_data_umb_t {
uint16_t slave_class;
uint16_t slave_id;
uint16_t channel_windspeed;
uint16_t channel_wingsusts;
uint16_t channel_winddirection;
uint16_t channel_temperature;
uint16_t channel_qfe;
/**
* #define _UMB_CHANNEL_WINDSPEED 460
#define _UMB_CHANNEL_WINDGUSTS 440
#define _UMB_CHANNEL_WINDDIRECTION 580
#define _UMB_CHANNEL_TEMPERATURE 100
#define _UMB_CHANNEL_QFE
*/
} config_data_umb_t;
extern const config_data_basic_t config_data_basic;
extern const config_data_mode_t config_data_mode;
extern const config_data_umb_t config_data_umb;
#endif /* CONFIG_DATA_H_ */

Wyświetl plik

@ -4,8 +4,8 @@
#include "aprs/ax25.h"
#include "drivers/serial.h"
#define SW_VER "DF13"
#define SW_DATE "13032021"
#define SW_VER "DF14"
#define SW_DATE "22032021"
#define SYSTICK_TICKS_PER_SECONDS 100
#define SYSTICK_TICKS_PERIOD 10
@ -34,6 +34,8 @@ extern char main_own_aprs_msg[OWN_APRS_MSG_LN];
extern srl_context_t* main_kiss_srl_ctx_ptr;
extern srl_context_t* main_wx_srl_ctx_ptr;
extern uint8_t main_kiss_enabled;
extern char after_tx_lock;
extern unsigned short rx10m, tx10m, digi10m, digidrop10m, kiss10m;

Wyświetl plik

@ -23,4 +23,7 @@ extern uint16_t rte_pv_battery_voltage;
extern uint16_t rte_pv_cell_voltage;
extern uint16_t rte_pv_load_current;
extern uint16_t rte_pv_messages_count;
extern uint16_t rte_pv_corrupted_messages_count;
#endif /* RTE_PV_H_ */

Wyświetl plik

@ -67,14 +67,12 @@ extern bme280_qf_t rte_wx_bme280_qf;
extern analog_wind_qf_t rte_wx_wind_qf;
#ifdef _UMB_MASTER
extern umb_frame_t rte_wx_umb;
extern umb_context_t rte_wx_umb_context;
extern uint8_t rte_wx_umb_last_status;
extern int16_t rte_wx_umb_channel_values[UMB_CHANNELS_STORAGE_CAPAC][2];
// stores the value in 0.1 incremenets
#endif
extern umb_qf_t rte_wx_umb_qf;
extern uint8_t rte_wx_davis_station_avaliable;

Wyświetl plik

@ -14,7 +14,9 @@
#include "station_config.h"
/**
*
*/
const config_data_mode_t config_data_mode = {
#ifdef _DIGI
.digi = 1,
@ -28,6 +30,25 @@ const config_data_mode_t config_data_mode = {
.wx = 0,
#endif
#ifdef _MODBUS_RTU
.wx_modbus = 1,
#else
.wx_modbus = 0,
#endif
#ifdef _MODBUS_RTU
.wx_modbus = 1,
#else
.wx_modbus = 0,
#endif
#ifdef _UMB_MASTER
.wx_umb = 1,
#else
.wx_umb = 0,
#endif
#ifdef _VICTRON
.victron = 1,
#else
@ -55,6 +76,9 @@ const config_data_mode_t config_data_mode = {
#endif
};
/**
*
*/
const config_data_basic_t config_data_basic = {
.callsign = _CALL,
.ssid = _SSID,
@ -109,3 +133,34 @@ const config_data_basic_t config_data_basic = {
#endif
};
/**
*
*/
const config_data_umb_t config_data_umb = {
#ifdef _UMB_SLAVE_ID
.slave_id = _UMB_SLAVE_ID,
#else
.slave_id = 0,
#endif
#ifdef _UMB_SLAVE_CLASS
.slave_class = _UMB_SLAVE_CLASS,
#else
.slave_class = 0,
#endif
#if defined (_UMB_SLAVE_ID) && defined (_UMB_SLAVE_CLASS)
.channel_windspeed = _UMB_CHANNEL_WINDSPEED,
.channel_wingsusts = _UMB_CHANNEL_WINDGUSTS,
.channel_winddirection = _UMB_CHANNEL_WINDDIRECTION,
.channel_temperature = _UMB_CHANNEL_TEMPERATURE,
.channel_qfe = _UMB_CHANNEL_QFE
#else
.channel_windspeed = 0xFFFF,
.channel_wingsusts = 0xFFFF,
.channel_winddirection = 0xFFFF,
.channel_temperature = 0xFFFF,
.channel_qfe = 0xFFFF
#endif
};

Wyświetl plik

@ -29,9 +29,7 @@
#include "aprs/dac.h"
#include "aprs/beacon.h"
#ifdef _VICTRON
#include "ve_direct_protocol/parser.h"
#endif
#include "rte_wx.h"
#include "rte_pv.h"
@ -59,11 +57,9 @@
#include <drivers/bme280.h>
#endif
#ifdef _UMB_MASTER
#include "umb_master/umb_master.h"
#include "umb_master/umb_channel_pool.h"
#include "umb_master/umb_0x26_status.h"
#endif
#endif // _METEO
@ -167,13 +163,9 @@ char main_own_aprs_msg[OWN_APRS_MSG_LN];
volatile uint8_t retval = 100;
uint16_t buffer_len = 0;
#ifdef _VICTRON
#endif
#ifdef _UMB_MASTER
// return value from UMB related functions
umb_retval_t main_umb_retval = UMB_UNINITIALIZED;
#endif
char after_tx_lock;
@ -306,6 +298,15 @@ int main(int argc, char* argv[]){
main_target_kiss_baudrate = _SERIAL_BAUDRATE;
#endif
// if Victron VE-direct protocol is enabled set the baudrate to the 19200u
if (config_data_mode.victron == 1) {
main_target_kiss_baudrate = 19200u;
// and disable the kiss TNC option as it shares the same port
main_kiss_enabled = 0;
}
#if (defined(PARATNC_HWREV_B) || defined(PARATNC_HWREV_C)) && defined(_DAVIS_SERIAL)
// reinitialize the KISS serial port temporary to davis baudrate
main_target_kiss_baudrate = DAVIS_DEFAULT_BAUDRATE;
@ -391,7 +392,6 @@ int main(int argc, char* argv[]){
main_wx_srl_ctx_ptr->te_port = GPIOA;
#endif
// initialize APRS path with zeros
memset (main_own_path, 0x00, sizeof(main_own_path));
@ -493,47 +493,51 @@ int main(int argc, char* argv[]){
bme280_read_calibration(bme280_calibration_data);
#endif
// preparing initial beacon which will be sent to host PC using KISS protocol via UART
main_own_aprs_msg_len = sprintf(main_own_aprs_msg, "=%07.2f%c%c%08.2f%c%c %s", (float)_LAT, _LATNS, _SYMBOL_F, (float)_LON, _LONWE, _SYMBOL_S, _COMMENT);
if (main_kiss_enabled == 1) {
// preparing initial beacon which will be sent to host PC using KISS protocol via UART
main_own_aprs_msg_len = sprintf(main_own_aprs_msg, "=%07.2f%c%c%08.2f%c%c %s", (float)_LAT, _LATNS, _SYMBOL_F, (float)_LON, _LONWE, _SYMBOL_S, _COMMENT);
// terminating the aprs message
main_own_aprs_msg[main_own_aprs_msg_len] = 0;
// terminating the aprs message
main_own_aprs_msg[main_own_aprs_msg_len] = 0;
// 'sending' the message which will only encapsulate it inside AX25 protocol (ax25_starttx is not called here)
//ax25_sendVia(&main_ax25, main_own_path, (sizeof(main_own_path) / sizeof(*(main_own_path))), main_own_aprs_msg, main_own_aprs_msg_len);
ln = ax25_sendVia_toBuffer(main_own_path, (sizeof(main_own_path) / sizeof(*(main_own_path))), main_own_aprs_msg, main_own_aprs_msg_len, srl_usart1_tx_buffer, TX_BUFFER_1_LN);
// 'sending' the message which will only encapsulate it inside AX25 protocol (ax25_starttx is not called here)
//ax25_sendVia(&main_ax25, main_own_path, (sizeof(main_own_path) / sizeof(*(main_own_path))), main_own_aprs_msg, main_own_aprs_msg_len);
ln = ax25_sendVia_toBuffer(main_own_path, (sizeof(main_own_path) / sizeof(*(main_own_path))), main_own_aprs_msg, main_own_aprs_msg_len, srl_usart1_tx_buffer, TX_BUFFER_1_LN);
// SendKISSToHost function cleares the output buffer hence routine need to wait till the UART will be ready for next transmission.
// Here this could be omitted because UART isn't used before but general idea
while(main_kiss_srl_ctx.srl_tx_state != SRL_TX_IDLE && main_kiss_srl_ctx.srl_tx_state != SRL_TX_ERROR);
// SendKISSToHost function cleares the output buffer hence routine need to wait till the UART will be ready for next transmission.
// Here this could be omitted because UART isn't used before but general idea
while(main_kiss_srl_ctx.srl_tx_state != SRL_TX_IDLE && main_kiss_srl_ctx.srl_tx_state != SRL_TX_ERROR);
// converting AX25 with beacon to KISS format
//ln = SendKISSToHost(main_afsk.tx_buf + 1, main_afsk.tx_fifo.tail - main_afsk.tx_fifo.head - 4, srl_tx_buffer, TX_BUFFER_LN);
// converting AX25 with beacon to KISS format
//ln = SendKISSToHost(main_afsk.tx_buf + 1, main_afsk.tx_fifo.tail - main_afsk.tx_fifo.head - 4, srl_tx_buffer, TX_BUFFER_LN);
// checking if KISS-framing was done correctly
if (ln != KISS_TOO_LONG_FRM) {
#ifdef SERIAL_TX_TEST_MODE
// infinite loop for testing UART transmission
for (;;) {
retval = srl_receive_data(main_kiss_srl_ctx_ptr, 100, FEND, FEND, 0, 0, 0);
#endif
retval = srl_start_tx(main_kiss_srl_ctx_ptr, ln);
// checking if KISS-framing was done correctly
if (ln != KISS_TOO_LONG_FRM) {
#ifdef SERIAL_TX_TEST_MODE
// infinite loop for testing UART transmission
for (;;) {
#ifdef SERIAL_TX_TEST_MODE
while(main_kiss_srl_ctx_ptr->srl_tx_state != SRL_TX_IDLE);
// while(srl_rx_state != SRL_RX_DONE);
retval = srl_receive_data(main_kiss_srl_ctx_ptr, 100, FEND, FEND, 0, 0, 0);
#endif
retval = srl_start_tx(main_kiss_srl_ctx_ptr, ln);
GPIOC->ODR = (GPIOC->ODR ^ GPIO_Pin_9);
#ifdef SERIAL_TX_TEST_MODE
while(main_kiss_srl_ctx_ptr->srl_tx_state != SRL_TX_IDLE);
// while(srl_rx_state != SRL_RX_DONE);
if (main_kiss_srl_ctx_ptr->srl_rx_state == SRL_RX_DONE) {
GPIOC->ODR = (GPIOC->ODR ^ GPIO_Pin_8);
GPIOC->ODR = (GPIOC->ODR ^ GPIO_Pin_9);
retval = 200;
if (main_kiss_srl_ctx_ptr->srl_rx_state == SRL_RX_DONE) {
GPIOC->ODR = (GPIOC->ODR ^ GPIO_Pin_8);
retval = 200;
}
}
#endif
}
#endif
}
}
// reinitializing AFSK and AX25 driver
AFSK_Init(&main_afsk);
@ -548,27 +552,23 @@ int main(int argc, char* argv[]){
wx_get_all_measurements();
#endif
#if defined _VICTRON && !defined _UMB_MASTER
// initializing protocol parser
ve_direct_parser_init(&rte_pv_struct, &rte_pv_average);
// start serial port i/o transaction depending on station configuration
if (config_data_mode.victron == 1) {
// initializing protocol parser
ve_direct_parser_init(&rte_pv_struct, &rte_pv_average);
// enabling timeout handling for serial port. This is required because VE protocol frame may vary in lenght
// and serial port driver could finish reception only either on stop character or when declared number of bytes
// has been received.
srl_switch_timeout(main_wx_srl_ctx_ptr, 1, 100);
// enabling timeout handling for serial port. This is required because VE protocol frame may vary in lenght
// and serial port driver could finish reception only either on stop character or when declared number of bytes
// has been received.
srl_switch_timeout(main_kiss_srl_ctx_ptr, 1, 100);
// switching UART to receive mode to be ready for data from charging controller
srl_receive_data(main_wx_srl_ctx_ptr, VE_DIRECT_MAX_FRAME_LN, 0x0D, 0, 0, 0, 0);
#elif !defined _VICTRON && defined _UMB_MASTER
// srl_receive_data(8, SOH, 0x00, 0, 6, 12);
#elif ! defined _VICTRON && !defined _UMB_MASTER
// switching UART to receive mode to be ready for KISS frames from host
srl_receive_data(main_kiss_srl_ctx_ptr, 100, FEND, FEND, 0, 0, 0);
#endif
// switching UART to receive mode to be ready for data from charging controller
srl_receive_data(main_kiss_srl_ctx_ptr, VE_DIRECT_MAX_FRAME_LN, 0x0D, 0, 0, 0, 0);
}
else {
// switching UART to receive mode to be ready for KISS frames from host
srl_receive_data(main_kiss_srl_ctx_ptr, 100, FEND, FEND, 0, 0, 0);
}
io_oc_output_low();
GPIO_ResetBits(GPIOC, GPIO_Pin_8 | GPIO_Pin_9);
@ -580,9 +580,10 @@ int main(int argc, char* argv[]){
beacon_send_own();
#endif
#if defined(_UMB_MASTER)
// initialize UMB transaction
if (config_data_mode.wx_umb == 1) {
umb_0x26_status_request(&rte_wx_umb, &rte_wx_umb_context);
#endif
}
#ifdef INTERNAL_WATCHDOG
// reload watchdog counter
@ -622,7 +623,9 @@ int main(int argc, char* argv[]){
SendWXFrameToBuffer(rte_wx_average_windspeed, rte_wx_max_windspeed, rte_wx_average_winddirection, rte_wx_temperature_average_dallas_valid, rte_wx_pressure_valid, rte_wx_humidity, srl_usart1_tx_buffer, TX_BUFFER_1_LN, &ln);
srl_start_tx(main_kiss_srl_ctx_ptr, ln);
if (main_kiss_enabled == 1) {
srl_start_tx(main_kiss_srl_ctx_ptr, ln);
}
#endif // #ifndef _METEO
}
@ -655,65 +658,74 @@ int main(int argc, char* argv[]){
rx10m++;
}
#if defined _VICTRON
// if new KISS message has been received from the host
if (srl_rx_state == SRL_RX_DONE || srl_rx_state == SRL_RX_ERROR) {
// if Victron VE.direct client is enabled
if (config_data_mode.victron == 1) {
// cutting received string to Checksum, everything after will be skipped
ve_direct_cut_to_checksum(srl_get_rx_buffer(), RX_BUFFER_LN, &buffer_len);
// if new KISS message has been received from the host
if (main_kiss_srl_ctx_ptr->srl_rx_state == SRL_RX_DONE || main_kiss_srl_ctx_ptr->srl_rx_state == SRL_RX_ERROR) {
// checking if this frame is ok
ve_direct_validate_checksum(srl_get_rx_buffer(), buffer_len, &retval);
// cutting received string to Checksum, everything after will be skipped
ve_direct_cut_to_checksum(srl_get_rx_buffer(main_kiss_srl_ctx_ptr), TX_BUFFER_1_LN, &buffer_len);
if (retval == 1) {
// parsing data from input serial buffer to
retval = ve_direct_parse_to_raw_struct(srl_get_rx_buffer(), buffer_len, &rte_pv_struct);
// checking if this frame is ok
ve_direct_validate_checksum(srl_get_rx_buffer(main_kiss_srl_ctx_ptr), buffer_len, &retval);
if (retval == 0) {
ve_direct_add_to_average(&rte_pv_struct, &rte_pv_average);
if (retval == 1) {
// parsing data from input serial buffer to
retval = ve_direct_parse_to_raw_struct(srl_get_rx_buffer(main_kiss_srl_ctx_ptr), buffer_len, &rte_pv_struct);
ve_direct_get_averages(&rte_pv_average, &rte_pv_battery_current, &rte_pv_battery_voltage, &rte_pv_cell_voltage, &rte_pv_load_current);
if (retval == 0) {
ve_direct_add_to_average(&rte_pv_struct, &rte_pv_average);
ve_direct_set_sys_voltage(&rte_pv_struct, &rte_pv_sys_voltage);
ve_direct_get_averages(&rte_pv_average, &rte_pv_battery_current, &rte_pv_battery_voltage, &rte_pv_cell_voltage, &rte_pv_load_current);
ve_direct_store_errors(&rte_pv_struct, &rte_pv_last_error);
ve_direct_set_sys_voltage(&rte_pv_struct, &rte_pv_sys_voltage);
ve_direct_store_errors(&rte_pv_struct, &rte_pv_last_error);
rte_pv_messages_count++;
}
}
else {
rte_pv_corrupted_messages_count++;
}
srl_receive_data(main_kiss_srl_ctx_ptr, VE_DIRECT_MAX_FRAME_LN, 0x0D, 0, 0, 0, 0);
}
}
else if (config_data_mode.wx_umb == 1) {
// if some UMB data have been received
if (main_wx_srl_ctx_ptr->srl_rx_state == SRL_RX_DONE) {
umb_pooling_handler(&rte_wx_umb_context, REASON_RECEIVE_IDLE, master_time);
}
srl_receive_data(main_wx_srl_ctx_ptr, VE_DIRECT_MAX_FRAME_LN, 0x0D, 0, 0, 0, 0);
}
#elif defined _UMB_MASTER
// if some UMB data have been received
if (main_wx_srl_ctx_ptr->srl_rx_state == SRL_RX_DONE) {
umb_pooling_handler(&rte_wx_umb_context, REASON_RECEIVE_IDLE, master_time);
}
// if there were an error during receiving frame from host, restart rxing once again
if (main_wx_srl_ctx_ptr->srl_rx_state == SRL_RX_ERROR) {
umb_pooling_handler(&rte_wx_umb_context, REASON_RECEIVE_ERROR, master_time);
}
// if there were an error during receiving frame from host, restart rxing once again
if (main_wx_srl_ctx_ptr->srl_rx_state == SRL_RX_ERROR) {
umb_pooling_handler(&rte_wx_umb_context, REASON_RECEIVE_ERROR, master_time);
if (main_wx_srl_ctx_ptr->srl_tx_state == SRL_TX_IDLE) {
umb_pooling_handler(&rte_wx_umb_context, REASON_TRANSMIT_IDLE, master_time);
}
}
else {
// if new KISS message has been received from the host
if (main_kiss_srl_ctx_ptr->srl_rx_state == SRL_RX_DONE && main_kiss_enabled == 1) {
// parse incoming data and then transmit on radio freq
short res = ParseReceivedKISS(srl_get_rx_buffer(main_kiss_srl_ctx_ptr), srl_get_num_bytes_rxed(main_kiss_srl_ctx_ptr), &main_ax25, &main_afsk);
if (res == 0)
kiss10m++; // increase kiss messages counter
if (main_wx_srl_ctx_ptr->srl_tx_state == SRL_TX_IDLE) {
umb_pooling_handler(&rte_wx_umb_context, REASON_TRANSMIT_IDLE, master_time);
}
#else
// if new KISS message has been received from the host
if (main_kiss_srl_ctx_ptr->srl_rx_state == SRL_RX_DONE && main_kiss_enabled == 1) {
// parse incoming data and then transmit on radio freq
short res = ParseReceivedKISS(srl_get_rx_buffer(main_kiss_srl_ctx_ptr), srl_get_num_bytes_rxed(main_kiss_srl_ctx_ptr), &main_ax25, &main_afsk);
if (res == 0)
kiss10m++; // increase kiss messages counter
// restart KISS receiving to be ready for next frame
srl_receive_data(main_kiss_srl_ctx_ptr, 120, FEND, FEND, 0, 0, 0);
}
// restart KISS receiving to be ready for next frame
srl_receive_data(main_kiss_srl_ctx_ptr, 120, FEND, FEND, 0, 0, 0);
// if there were an error during receiving frame from host, restart rxing once again
if (main_kiss_srl_ctx_ptr->srl_rx_state == SRL_RX_ERROR && main_kiss_enabled == 1) {
srl_receive_data(main_kiss_srl_ctx_ptr, 120, FEND, FEND, 0, 0, 0);
}
}
// if there were an error during receiving frame from host, restart rxing once again
if (main_kiss_srl_ctx_ptr->srl_rx_state == SRL_RX_ERROR && main_kiss_enabled == 1) {
srl_receive_data(main_kiss_srl_ctx_ptr, 120, FEND, FEND, 0, 0, 0);
}
#endif
// if Davis wx station is enabled and it is alive
if (main_davis_serial_enabled == 1) {
@ -741,9 +753,11 @@ int main(int argc, char* argv[]){
wx_get_all_measurements();
#endif
#if defined(_UMB_MASTER)
umb_0x26_status_request(&rte_wx_umb, &rte_wx_umb_context);
#endif
//#if defined(_UMB_MASTER)
if (config_data_mode.wx_umb == 1) {
umb_0x26_status_request(&rte_wx_umb, &rte_wx_umb_context);
}
//#endif
if (main_davis_serial_enabled == 1) {
davis_trigger_rxcheck_packet();
@ -806,13 +820,17 @@ int main(int argc, char* argv[]){
if (main_ten_second_pool_timer < 10) {
#if defined(_UMB_MASTER)
umb_channel_pool(&rte_wx_umb, &rte_wx_umb_context);
#endif
//#if defined(_UMB_MASTER)
if (config_data_mode.wx_umb == 1) {
umb_channel_pool(&rte_wx_umb, &rte_wx_umb_context);
}
//#endif
#if defined(_UMB_MASTER)
rte_wx_umb_qf = umb_get_current_qf(&rte_wx_umb_context, master_time);
#endif
//#if defined(_UMB_MASTER)
if (config_data_mode.wx_umb == 1) {
rte_wx_umb_qf = umb_get_current_qf(&rte_wx_umb_context, master_time);
}
//#endif
wx_pool_anemometer();

Wyświetl plik

@ -16,6 +16,8 @@
#include "main.h"
#include "delay.h"
#include "config_data.h"
#define _TELEM_DESCR_INTERVAL 150
uint8_t packet_tx_beacon_interval = _BCN_INTERVAL;
@ -87,11 +89,13 @@ void packet_tx_handler(void) {
#endif
if (packet_tx_error_status_counter >= packet_tx_error_status_interval) {
#if defined(_UMB_MASTER)
umb_construct_status_str(&rte_wx_umb_context, main_own_aprs_msg, sizeof(main_own_aprs_msg), &ln, master_time);
//#if defined(_UMB_MASTER)
if (config_data_mode.wx_umb) {
umb_construct_status_str(&rte_wx_umb_context, main_own_aprs_msg, sizeof(main_own_aprs_msg), &ln, master_time);
packet_tx_multi_per_call_handler();
#endif
packet_tx_multi_per_call_handler();
}
//#endif
packet_tx_error_status_counter = 0;
}
@ -151,7 +155,20 @@ void packet_tx_handler(void) {
rte_main_trigger_modbus_status = 1;
}
#endif
if (packet_tx_meteo_kiss_counter >= packet_tx_meteo_kiss_interval) {
// check if Victron VE.Direct serial protocol client is enabled and it is
// a time to send status message
if (config_data_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);
}
if (packet_tx_meteo_kiss_counter >= packet_tx_meteo_kiss_interval && main_kiss_enabled == 1) {
srl_wait_for_tx_completion(main_kiss_srl_ctx_ptr);
@ -274,25 +291,33 @@ void packet_tx_handler(void) {
rte_wx_wind_qf = AN_WIND_QF_UNKNOWN;
}
#ifdef _VICTRON
//#ifdef _VICTRON
//
telemetry_send_values_pv(rx10m, digi10m, rte_pv_battery_current, rte_pv_battery_voltage, rte_pv_cell_voltage, dallas_qf, pressure_qf, humidity_qf);
if (config_data_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);
}
else {
//
#else
//#else
//
#if defined _DALLAS_AS_TELEM
// 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);
#elif defined _METEO
// 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, rte_wx_temperature_ms_valid, dallas_qf, pressure_qf, humidity_qf, wind_qf);
#else
// if user will disable both _METEO and _DALLAS_AS_TELEM value will be zeroed internally anyway
telemetry_send_values(rx10m, tx10m, digi10m, kiss10m, 0.0f, dallas_qf, pressure_qf, humidity_qf, wind_qf);
#endif
// #if defined _DALLAS_AS_TELEM
// 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);
// #elif defined _METEO
if (config_data_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, rte_wx_temperature_ms_valid, dallas_qf, pressure_qf, humidity_qf, wind_qf);
}
// #else
else {
// if user will disable both _METEO and _DALLAS_AS_TELEM value will be zeroed internally anyway
telemetry_send_values(rx10m, tx10m, digi10m, kiss10m, 0.0f, dallas_qf, pressure_qf, humidity_qf, wind_qf);
}
// #endif
//
#endif
//#endif
}
packet_tx_telemetry_counter = 0;
rx10m = 0, tx10m = 0, digi10m = 0, kiss10m = 0;
@ -304,22 +329,29 @@ void packet_tx_handler(void) {
if (packet_tx_telemetry_descr_counter >= packet_tx_telemetry_descr_interval) {
packet_tx_multi_per_call_handler();
#ifdef _VICTRON
telemetry_send_chns_description_pv();
//#ifdef _VICTRON
if (config_data_mode.victron == 1) {
telemetry_send_chns_description_pv();
main_wait_for_tx_complete();
//telemetry_send_status_pv(&rte_pv_average, &rte_pv_last_error, rte_pv_struct.system_state);
}
//#else
else {
telemetry_send_chns_description();
telemetry_send_status(&rte_pv_average, &rte_pv_last_error, rte_pv_struct.system_state);
packet_tx_multi_per_call_handler();
#else
telemetry_send_chns_description();
//telemetry_send_status();
}
telemetry_send_status();
#endif
#if defined _UMB_MASTER
umb_clear_error_history(&rte_wx_umb_context);
#endif
//#endif
//#if defined _UMB_MASTER
if (config_data_mode.wx_umb == 1) {
umb_clear_error_history(&rte_wx_umb_context);
}
//#endif
packet_tx_telemetry_descr_counter = 0;
}

Wyświetl plik

@ -17,3 +17,6 @@ int16_t rte_pv_battery_current;
uint16_t rte_pv_battery_voltage;
uint16_t rte_pv_cell_voltage;
uint16_t rte_pv_load_current;
uint16_t rte_pv_messages_count = 0;
uint16_t rte_pv_corrupted_messages_count = 0;

Wyświetl plik

@ -42,13 +42,11 @@ bme280_qf_t rte_wx_bme280_qf = BME280_QF_UKNOWN;
analog_wind_qf_t rte_wx_wind_qf = AN_WIND_QF_UNKNOWN;
#ifdef _UMB_MASTER
umb_frame_t rte_wx_umb;
umb_context_t rte_wx_umb_context;
uint8_t rte_wx_umb_last_status = 0;
int16_t rte_wx_umb_channel_values[UMB_CHANNELS_STORAGE_CAPAC][2]; // first dimension stores the channel number and the second one
// stores the value in 0.1 incremenets
#endif
umb_qf_t rte_wx_umb_qf = UMB_QF_UNITIALIZED;
uint8_t rte_wx_davis_station_avaliable = 0;

Wyświetl plik

@ -19,6 +19,8 @@
#include "station_config.h"
#include "config_data.h"
#ifdef _MODBUS_RTU
#include "modbus_rtu/rtu_getters.h"
#include "modbus_rtu/rtu_return_values.h"
@ -57,12 +59,14 @@ void wx_get_all_measurements(void) {
int8_t modbus_qf = 0;
float pressure_average_sum = 0.0f;
#if defined(_UMB_MASTER) && !defined(_DAVIS_SERIAL) && !defined(_MODBUS_RTU)
if (rte_wx_umb_qf == UMB_QF_FULL) {
rte_wx_temperature_average_dallas_valid = umb_get_temperature();
rte_wx_pressure_valid = umb_get_qfe();
//#if defined(_UMB_MASTER) && !defined(_DAVIS_SERIAL) && !defined(_MODBUS_RTU)
if (config_data_mode.wx_umb == 1) {
if (rte_wx_umb_qf == UMB_QF_FULL) {
rte_wx_temperature_average_dallas_valid = umb_get_temperature();
rte_wx_pressure_valid = umb_get_qfe();
}
}
#endif
//#endif
#if !defined(_UMB_MASTER) && !defined(_DAVIS_SERIAL) && defined(_MODBUS_RTU)

Wyświetl plik

@ -50,7 +50,6 @@ extern "C"
{
#endif
#ifdef _VICTRON
void telemetry_send_values_pv ( uint8_t rx_pkts,
uint8_t digi_pkts,
int16_t raw_battery_current,
@ -60,9 +59,8 @@ void telemetry_send_values_pv ( uint8_t rx_pkts,
ms5611_qf_t ms_qf,
dht22QF ds_qf);
void telemetry_send_chns_description_pv(void);
void telemetry_send_status(ve_direct_average_struct* avg, ve_direct_error_reason* last_error, ve_direct_system_state state);
void telemetry_send_status_pv(ve_direct_average_struct* avg, ve_direct_error_reason* last_error, ve_direct_system_state state, uint32_t master_time, uint16_t messages_count, uint16_t corrupted_messages_count);
#else
void telemetry_send_values( uint8_t rx_pkts,
uint8_t tx_pkts,
uint8_t digi_pkts,
@ -75,8 +73,6 @@ void telemetry_send_values( uint8_t rx_pkts,
void telemetry_send_chns_description(void);
void telemetry_send_status(void);
#endif
void telemetry_send_status_raw_values_modbus(void);
#ifdef __cplusplus

Wyświetl plik

@ -13,10 +13,6 @@
#include <umb_master/umb_context_t.h>
#include <umb_master/umb_call_reason.h>
#include <umb_master/umb_qf_t.h>
#include "station_config.h"
#ifdef _UMB_MASTER
void umb_master_init(umb_context_t* ctx, srl_context_t* serial_ctx);
umb_retval_t umb_parse_serial_buffer_to_frame(uint8_t* serial_buffer, uint16_t buffer_ln, umb_frame_t* frame);
@ -34,6 +30,5 @@ int16_t umb_get_winddirection(void);
float umb_get_temperature(void);
float umb_get_qfe(void);
#endif
#endif /* INCLUDE_UMB_MASTER_UMB_MASTER_H_ */

Wyświetl plik

@ -20,7 +20,6 @@
uint16_t telemetry_counter = 0;
#ifdef _VICTRON
void telemetry_send_chns_description_pv(void) {
while (main_afsk.sending == 1);
@ -151,19 +150,19 @@ void telemetry_send_values_pv ( uint8_t rx_pkts,
main_own_aprs_msg[main_own_aprs_msg_len] = 0;
ax25_sendVia(&main_ax25, main_own_path, main_own_path_ln, main_own_aprs_msg, main_own_aprs_msg_len);
after_tx_lock = 1;
while(ax25.dcd == true);
while (main_ax25.dcd == 1);
afsk_txStart(&main_afsk);
}
void telemetry_send_status(ve_direct_average_struct* avg, ve_direct_error_reason* last_error, ve_direct_system_state state) {
void telemetry_send_status_pv(ve_direct_average_struct* avg, ve_direct_error_reason* last_error, ve_direct_system_state state, uint32_t master_time, uint16_t messages_count, uint16_t corrupted_messages_count) {
char string_buff_err[24], string_buff_state[23];
ve_direct_state_to_string(state, string_buff_state, 23);
ve_direct_error_to_string(*last_error, string_buff_err, 24);
main_own_aprs_msg_len = snprintf(main_own_aprs_msg, sizeof(main_own_aprs_msg), "> FwVersion %s BatAmpsMin %d BatAmpsMax %d %s %s", SW_VER, avg->min_battery_current, avg->max_battery_current, string_buff_state, string_buff_err);
main_own_aprs_msg_len = snprintf(main_own_aprs_msg, sizeof(main_own_aprs_msg), ">MT %X, MC %X, CMC %X, IMIN %d, IMAX %d, ST %s, ERR %s", master_time, (uint32_t)messages_count, (uint32_t)corrupted_messages_count, avg->min_battery_current, avg->max_battery_current, string_buff_state, string_buff_err);
ax25_sendVia(&main_ax25, main_own_path, main_own_path_ln, main_own_aprs_msg, main_own_aprs_msg_len);
afsk_txStart(&main_afsk);
@ -173,8 +172,7 @@ void telemetry_send_status(ve_direct_average_struct* avg, ve_direct_error_reason
avg->min_battery_current = 0;
*last_error = ERR_UNINITIALIZED;
}
#else
////
/**
* Sends four frames with telemetry description
@ -397,7 +395,6 @@ void telemetry_send_status(void) {
}
#endif
void telemetry_send_status_raw_values_modbus(void) {
#ifdef _MODBUS_RTU

Wyświetl plik

@ -10,6 +10,22 @@
#define MODBUS_RTU_MIN_03_04_RESP_LN 7 // one register to read
/**
* 2021-03-21 03:06:56 CET: SR6WXP>AKLPRZ,WIDE2-1,qAS,SQ6NDL:=5038.00N101747.00E# DigiW1 + WX ~ Lotnisko Polska Nowa Wies ~ https://www.facebook.com/aeroklub.opolski
* 2021-03-21 03:06:58 CET: SR6WXP>AKLPRZ,WIDE2-1,qAR,SR9NSK:T#237,023,004,001,000,122,10000110
* 2021-03-21 03:07:58 CET: SR6WXP>AKLPRZ,WIDE2-1,qAO,SR6NKB:>F1V FFED, F2V 47, F3V 0, F4V 0, F5V 0, F6V 0
* 2021-03-21 03:08:59 CET: SR6WXP>AKLPRZ,WIDE2-1,qAR,SR9NSK:!5038.00N/01747.00E_344/006g011t025r...p...P...b09952h71
* 2021-03-21 03:11:59 CET: SR6WXP>AKLPRZ,WIDE2-1,qAO,SR6NKB:>F1V FFEE, F2V 47, F3V 0, F4V 0, F5V 0, F6V 0
* 2021-03-21 03:13:00 CET: SR6WXP>AKLPRZ,WIDE2-1,qAO,SR6NKB:!5038.00N/01747.00E_352/005g009t025r...p...P...b09951h71
* 2021-03-21 03:16:00 CET: SR6WXP>AKLPRZ,WIDE2-1,qAO,SR6NKB:>F1V FFEE, F2V 47, F3V 0, F4V 0, F5V 0, F6V 0
* 2021-03-21 03:17:01 CET: SR6WXP>AKLPRZ,WIDE2-1,qAR,SR9NSK:!5038.00N/01747.00E_348/006g008t025r...p...P...b09950h71
*
* 2021-03-21 05:36:27 CET: SR6WXP>AKLPRZ,WIDE2-1,qAS,SQ6NDL:>F1V FFFA, F2V 46, F3V 0, F4V 0, F5V 0, F6V 0
* 2021-03-21 05:37:28 CET: SR6WXP>AKLPRZ,WIDE2-1,qAS,SQ6NDL:!5038.00N/01747.00E_339/003g007t027r...p...P...b09923h70
* 2021-03-21 05:37:30 CET: SR6WXP>AKLPRZ,WIDE2-1,qAR,SR9NSK:T#252,026,004,001,000,122,10000110
* 2021-03-21 05:40:30 CET: SR6WXP>AKLPRZ,WIDE2-1,qAS,SQ6NDL:>F1V FFFA, F2V 46, F3V 0, F4V 0, F5V 0, F6V 0
*/
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output, rtu_exception_t* exception) {
uint32_t retval = MODBUS_RET_UNINITIALIZED;

Wyświetl plik

@ -7,7 +7,7 @@
#include "../umb_master/umb_master.h"
#include "../umb_master/umb_0x23_offline_data.h"
#include "station_config.h"
#include "config_data.h"
#include "rte_wx.h"
#include "main.h"
@ -27,8 +27,6 @@
#define SIGNED_LONG_LN 4
#define FLOAT_LN 4
#ifdef _UMB_MASTER
umb_retval_t umb_0x23_offline_data_request(umb_frame_t* frame, umb_context_t* ctx, uint16_t channel_number) {
if (ctx->state != UMB_STATUS_IDLE && ctx->state != UMB_STATUS_ERROR) {
@ -36,8 +34,8 @@ umb_retval_t umb_0x23_offline_data_request(umb_frame_t* frame, umb_context_t* ct
}
frame->command_id = 0x23;
frame->slave_class = _UMB_SLAVE_CLASS;
frame->slave_id = _UMB_SLAVE_ID;
frame->slave_class = (uint8_t)(config_data_umb.slave_class & 0xFF);
frame->slave_id = (uint8_t)(config_data_umb.slave_id & 0xFF);
frame->lenght = 2;
// channels are little endian 16 bit unsigned integer
@ -192,5 +190,3 @@ umb_retval_t umb_0x23_offline_data_callback(umb_frame_t* frame, umb_context_t* c
return output;
}
#endif

Wyświetl plik

@ -7,13 +7,11 @@
#include "../umb_master/umb_master.h"
#include "../umb_master/umb_0x26_status.h"
#include "station_config.h"
#include "config_data.h"
#include "main.h"
#include <string.h>
#ifdef _UMB_MASTER
umb_retval_t umb_0x26_status_request(umb_frame_t* frame, umb_context_t* ctx) {
if (ctx->state != UMB_STATUS_IDLE && ctx->state != UMB_STATUS_ERROR) {
@ -21,8 +19,8 @@ umb_retval_t umb_0x26_status_request(umb_frame_t* frame, umb_context_t* ctx) {
}
frame->command_id = 0x26;
frame->slave_class = _UMB_SLAVE_CLASS;
frame->slave_id = _UMB_SLAVE_ID;
frame->slave_class = (uint8_t)(config_data_umb.slave_class & 0xFF);
frame->slave_id = (uint8_t)(config_data_umb.slave_id & 0xFF);
frame->lenght = 0;
memset(frame->payload, 0x00, UMB_FRAME_MAX_PAYLOAD_LN);
@ -74,5 +72,4 @@ umb_retval_t umb_0x26_status_callback(umb_frame_t* frame, umb_context_t* ctx) {
return output;
}
#endif

Wyświetl plik

@ -7,10 +7,8 @@
#include <umb_master/umb_channel_pool.h>
#include <umb_master/umb_0x23_offline_data.h>
#include "station_config.h"
void umb_channel_pool(umb_frame_t *frame, umb_context_t *ctx) {
#if defined(_UMB_MASTER)
if (ctx->channel_number_it >= UMB_CHANNELS_STORAGE_CAPAC)
ctx->channel_number_it = 0;
@ -22,6 +20,5 @@ void umb_channel_pool(umb_frame_t *frame, umb_context_t *ctx) {
}
ctx->channel_number_it++;
#endif
}

Wyświetl plik

@ -13,9 +13,7 @@
#include <umb_master/umb_master.h>
#include <umb_master/umb_channel_pool.h>
#include <rte_wx.h>
#include "station_config.h"
#ifdef _UMB_MASTER
#include "config_data.h"
#define SOH 0x01
#define STX 0x02
@ -50,23 +48,23 @@ void umb_master_init(umb_context_t* ctx, srl_context_t* serial_ctx) {
rte_wx_umb_channel_values[i][0] = 0xFFFF;
#ifdef _UMB_CHANNEL_WINDSPEED
ctx->channel_numbers[0] = _UMB_CHANNEL_WINDSPEED;
ctx->channel_numbers[0] = config_data_umb.channel_windspeed;
#endif
#ifdef _UMB_CHANNEL_WINDGUSTS
ctx->channel_numbers[1] = _UMB_CHANNEL_WINDGUSTS;
ctx->channel_numbers[1] = config_data_umb.channel_wingsusts;
#endif
#ifdef _UMB_CHANNEL_WINDDIRECTION
ctx->channel_numbers[2] = _UMB_CHANNEL_WINDDIRECTION;
ctx->channel_numbers[2] = config_data_umb.channel_winddirection;
#endif
#ifdef _UMB_CHANNEL_TEMPERATURE
ctx->channel_numbers[3] = _UMB_CHANNEL_TEMPERATURE;
ctx->channel_numbers[3] = config_data_umb.channel_temperature;
#endif
#ifdef _UMB_CHANNEL_QFE
ctx->channel_numbers[4] = _UMB_CHANNEL_QFE;
ctx->channel_numbers[4] = config_data_umb.channel_qfe;
#endif
}
@ -131,8 +129,8 @@ umb_retval_t umb_parse_frame_to_serial_buffer(uint8_t* serial_buffer, uint16_t b
serial_buffer[i++] = SOH;
serial_buffer[i++] = V10;
serial_buffer[i++] = _UMB_SLAVE_ID;
serial_buffer[i++] = _UMB_SLAVE_CLASS << 4;
serial_buffer[i++] = (uint8_t)(config_data_umb.slave_id & 0xFF); //_UMB_SLAVE_ID;
serial_buffer[i++] = (uint8_t)(config_data_umb.slave_class & 0xFF) << 4;//_UMB_SLAVE_CLASS << 4;
serial_buffer[i++] = MASTER_ID;
serial_buffer[i++] = MASTER_CLASS;
serial_buffer[i++] = frame->lenght + 2;
@ -440,7 +438,7 @@ uint16_t umb_get_windspeed(void) {
uint16_t out = 0;
for (int i = 0; i < UMB_CHANNELS_STORAGE_CAPAC; i++) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)_UMB_CHANNEL_WINDSPEED) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)config_data_umb.channel_windspeed) {
out = (uint16_t)rte_wx_umb_channel_values[i][1];
break;
}
@ -453,7 +451,7 @@ uint16_t umb_get_windgusts(void) {
uint16_t out = 0;
for (int i = 0; i < UMB_CHANNELS_STORAGE_CAPAC; i++) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)_UMB_CHANNEL_WINDGUSTS) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)config_data_umb.channel_wingsusts) {
out = (uint16_t)rte_wx_umb_channel_values[i][1];
break;
}
@ -466,7 +464,7 @@ int16_t umb_get_winddirection(void) {
int16_t out = 0;
for (int i = 0; i < UMB_CHANNELS_STORAGE_CAPAC; i++) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)_UMB_CHANNEL_WINDDIRECTION) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)config_data_umb.channel_winddirection) {
out = (int16_t)rte_wx_umb_channel_values[i][1];
break;
}
@ -479,7 +477,7 @@ float umb_get_temperature(void) {
float out = 0.0f;
for (int i = 0; i < UMB_CHANNELS_STORAGE_CAPAC; i++) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)_UMB_CHANNEL_TEMPERATURE) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)config_data_umb.channel_temperature) {
out = (float)rte_wx_umb_channel_values[i][1] * 0.1f;
break;
}
@ -492,7 +490,7 @@ float umb_get_qfe(void) {
float out = 0;
for (int i = 0; i < UMB_CHANNELS_STORAGE_CAPAC; i++) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)_UMB_CHANNEL_QFE) {
if (rte_wx_umb_channel_values[i][0] == (int16_t)config_data_umb.channel_qfe) {
out = (float)rte_wx_umb_channel_values[i][1] * 0.1f;
break;
}
@ -501,4 +499,3 @@ float umb_get_qfe(void) {
return out;
}
#endif

Wyświetl plik

@ -186,10 +186,38 @@ void ve_direct_validate_checksum(uint8_t* input, uint16_t input_ln, uint8_t* val
i -= 2;
for (; i < input_ln; i++) {
// workaround of the problem with loosing \n or \r characters
// don't ask why and what this crap is all about. i had no time
// to debug the connection between the controller and pv charging regulator
sum += *(input + i);
if (i > 0) {
// if \n is the current character check if the previous one was \r
if (*(input + i) == '\n' && *(input + i - 1) != '\r') {
// if not assume that it was received and add it to the checksum
sum += '\r';
// proceed to next character
continue;
}
// if \r is the current character but the next one isn't \n
if (*(input + i) == '\r' && *(input + i + 1) != '\n') {
// if not assume that it was received and add it to the checksum
sum += '\n';
// proceed to next character
continue;
}
}
}
sum %= 256;
sum %= 0xFF;
if (sum == 0)
*valid = 1;
@ -453,3 +481,60 @@ void ve_direct_state_to_string(ve_direct_system_state input, char* output, int8_
case STATE_INVERTING: snprintf(output, output_ln, "STATE_INVERTING"); break;
}
}
/**
*
*
*
*"\r\nPID\t0xA042\r\nFW\t127\r\nSER#\tHQ1723BQTPC\nV\t13780\nI\t190\r\nVPV\t17770\r\nPPV\t3\r\nCS\t5\r\nERR\t0\r\nLOAD\tON\nIL\t0\nH19\t593\r\nH20\t1\r\nH21\t12\r\nH22\t7\r\nH23\t93\r\nHSDS\t167\nChecksum\t8"
*
*
*\r\nPID\t0xA042
*\r\nFW\t127
*\r\nSER#\tHQ1723BQTPC
*\nV\t13780
*\nI\t190
*\r\nVPV\t17770
*\r\nPPV\t3
*\r\nCS\t5
*\r\nERR\t0
*\r\nLOAD\tON
*\nIL\t0
*\nH19\t593
*\r\nH20\t1
*\r\nH21\t12
*\r\nH22\t7
*\r\nH23\t93
*\r\nHSDS\t167
*\nChecksum\t8"
*
* Z:\home\mateusz\Documents\___STM32\VE_DIRECT_3.bin (3/22/2021 7:08:36 PM)
* StartOffset(h): 00000000, EndOffset(h): 0000009B, Length(h): 0000009C
*
*unsigned char rawData[156] = {
* 0x0D, 0x0A, 0x50, 0x49, 0x44, 0x09, 0x30, 0x78, 0x41, 0x30, 0x34, 0x32,
* 0x0D, 0x0A, 0x46, 0x57, 0x09, 0x31, 0x32, 0x37, 0x0D, 0x0A, 0x53, 0x45,
* 0x52, 0x23, 0x09, 0x48, 0x51, 0x31, 0x37, 0x32, 0x33, 0x42, 0x51, 0x54,
* 0x50, 0x43, 0x0A, 0x56, 0x09, 0x31, 0x33, 0x37, 0x38, 0x30, 0x0A, 0x49,
* 0x09, 0x31, 0x39, 0x30, 0x0D, 0x0A, 0x56, 0x50, 0x56, 0x09, 0x31, 0x37,
* 0x37, 0x37, 0x30, 0x0D, 0x0A, 0x50, 0x50, 0x56, 0x09, 0x33, 0x0D, 0x0A,
* 0x43, 0x53, 0x09, 0x35, 0x0D, 0x0A, 0x45, 0x52, 0x52, 0x09, 0x30, 0x0D,
* 0x0A, 0x4C, 0x4F, 0x41, 0x44, 0x09, 0x4F, 0x4E, 0x0A, 0x49, 0x4C, 0x09,
* 0x30, 0x0A, 0x48, 0x31, 0x39, 0x09, 0x35, 0x39, 0x33, 0x0D, 0x0A, 0x48,
* 0x32, 0x30, 0x09, 0x31, 0x0D, 0x0A, 0x48, 0x32, 0x31, 0x09, 0x31, 0x32,
* 0x0D, 0x0A, 0x48, 0x32, 0x32, 0x09, 0x37, 0x0D, 0x0A, 0x48, 0x32, 0x33,
* 0x09, 0x39, 0x33, 0x0D, 0x0A, 0x48, 0x53, 0x44, 0x53, 0x09, 0x31, 0x36,
* 0x37, 0x0A, 0x43, 0x68, 0x65, 0x63, 0x6B, 0x73, 0x75, 0x6D, 0x09, 0x38
*};
*
* 0D 0A 50 49 44 09 30 78 41 30 34 32 0D 0A 46 57 09 31 32 37 0D 0A 53 45 52 23 09 48 51 31 37 32 33 42 51 54 50 43 0A 56 09 31 33 37 38 30 0A 49 09 31 39 30 0D 0A 56 50 56 09 31 37 37 37 30 0D 0A 50 50 56 09 33 0D 0A 43 53 09 35 0D 0A 45 52 52 09 30 0D 0A 4C 4F 41 44 09 4F 4E 0A 49 4C 09 30 0A 48 31 39 09 35 39 33 0D 0A 48 32 30 09 31 0D 0A 48 32 31 09 31 32 0D 0A 48 32 32 09 37 0D 0A 48 32 33 09 39 33 0D 0A 48 53 44 53 09 31 36 37 0A 43 68 65 63 6B 73 75 6D 09 38
*
*
*
*
*
*
*
*
*/