|
|
|
@ -6,97 +6,47 @@ |
|
|
|
#include "driver/uart.h" |
|
|
|
#include "esp_log.h" |
|
|
|
#include "tic.h" |
|
|
|
#include "libteleinfo.h" |
|
|
|
|
|
|
|
static const char *TIC_LOGGER = "tic"; |
|
|
|
static QueueHandle_t uart_queue; |
|
|
|
|
|
|
|
uint8_t tic_checksum(uint8_t* buffer, size_t start, size_t end) { |
|
|
|
uint16_t checksum = 0; |
|
|
|
for (size_t i = start; i <= end; i++) { |
|
|
|
checksum += buffer[i]; |
|
|
|
} |
|
|
|
checksum = (checksum & 0x3F) + 0x20; |
|
|
|
return (uint8_t)checksum; |
|
|
|
} |
|
|
|
void tic_data_callback(time_t ts, uint8_t flags, char * name, char * value) { |
|
|
|
char * prefix = ""; |
|
|
|
|
|
|
|
static void tic_uart_events(void *pvParameters) { |
|
|
|
uart_event_t event; |
|
|
|
size_t buffered_size; |
|
|
|
uint8_t* buffer = (uint8_t*) malloc(TIC_READ_BUFFER_SIZE); |
|
|
|
uint8_t methods[2] = {0, 0}; |
|
|
|
for(;;) { |
|
|
|
// Waiting for UART event.
|
|
|
|
if(xQueueReceive(uart_queue, (void * )&event, (portTickType)portMAX_DELAY)) { |
|
|
|
switch(event.type) { |
|
|
|
case UART_FIFO_OVF: |
|
|
|
case UART_BUFFER_FULL: |
|
|
|
case UART_PARITY_ERR: |
|
|
|
case UART_FRAME_ERR: |
|
|
|
ESP_LOGI(TIC_LOGGER, "error: event type %d. Discarding existing data...", event.type); |
|
|
|
uart_flush_input(TIC_UART_NUM); |
|
|
|
xQueueReset(uart_queue); |
|
|
|
break; |
|
|
|
case UART_PATTERN_DET: |
|
|
|
bzero(buffer, TIC_READ_BUFFER_SIZE); |
|
|
|
uart_get_buffered_data_len(TIC_UART_NUM, &buffered_size); |
|
|
|
int pos = uart_pattern_pop_pos(TIC_UART_NUM); |
|
|
|
if (pos == -1) { |
|
|
|
// There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not
|
|
|
|
// record the position. We should set a larger queue size.
|
|
|
|
// As an example, we directly flush the rx buffer here.
|
|
|
|
uart_flush_input(TIC_UART_NUM); |
|
|
|
} else { |
|
|
|
uint8_t* scratch = buffer; |
|
|
|
uart_read_bytes(TIC_UART_NUM, scratch, pos + 1, 100 / portTICK_PERIOD_MS); |
|
|
|
scratch[pos] = '\0'; |
|
|
|
ESP_LOGD(TIC_LOGGER, "read data: '%s', separator at %d", scratch, pos); |
|
|
|
if (flags & LIBTELEINFO_FLAGS_ADDED) |
|
|
|
prefix = "NEW ->"; |
|
|
|
|
|
|
|
// '\n' + tag + sep + value + sep + checksum = at least 6 characters
|
|
|
|
if (pos < 6) { |
|
|
|
ESP_LOGI(TIC_LOGGER, "read string is too short: %d", pos); |
|
|
|
break; |
|
|
|
} |
|
|
|
if (flags & LIBTELEINFO_FLAGS_UPDATED) |
|
|
|
prefix = "MAJ ->"; |
|
|
|
|
|
|
|
// during manual tests, there is no '\n' at the start of the string
|
|
|
|
// but according to Enedis, there is one in the actual data sent.
|
|
|
|
if (scratch[0] == '\n') { |
|
|
|
scratch++; |
|
|
|
pos--; |
|
|
|
} |
|
|
|
ESP_LOGI(TIC_LOGGER, "%s %s=%s", prefix, name, value); |
|
|
|
} |
|
|
|
|
|
|
|
void tic_adps_callback(uint8_t phase) { |
|
|
|
ESP_LOGI(TIC_LOGGER, "ALERTE phase=%d", phase); |
|
|
|
} |
|
|
|
|
|
|
|
if (methods[0] >= TIC_CHECKSUM_THRESHOLD || methods[1] >= TIC_CHECKSUM_THRESHOLD) { |
|
|
|
if (methods[0] >= TIC_CHECKSUM_THRESHOLD && tic_checksum(scratch, 0, pos - 3) == scratch[pos - 1]) { |
|
|
|
ESP_LOGD(TIC_LOGGER, "validated with method1: %s", scratch); |
|
|
|
} else if (methods[1] >= TIC_CHECKSUM_THRESHOLD && tic_checksum(scratch, 0, pos - 2) == scratch[pos - 1]) { |
|
|
|
ESP_LOGD(TIC_LOGGER, "validated with method2: %s", scratch); |
|
|
|
} else { |
|
|
|
ESP_LOGI(TIC_LOGGER, "wrong checksum: %s", scratch); |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (tic_checksum(scratch, 0, pos - 3) == scratch[pos - 1]) { |
|
|
|
methods[0]++; |
|
|
|
ESP_LOGD(TIC_LOGGER, "validated with method 1 while learning: %s", scratch); |
|
|
|
} else if (tic_checksum(scratch, 0, pos - 2) == scratch[pos - 1]) { |
|
|
|
methods[1]++; |
|
|
|
ESP_LOGD(TIC_LOGGER, "validated with method 2 while learning: %s", scratch); |
|
|
|
} else { |
|
|
|
ESP_LOGI(TIC_LOGGER, "wrong checksum: %s", scratch); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
static void tic_uart_read(void *pvParameters) { |
|
|
|
uint8_t* buffer = (uint8_t*) malloc(CONFIG_TIC_UART_READ_BUFFER_SIZE); |
|
|
|
if (buffer == NULL) { |
|
|
|
ESP_LOGE(TIC_LOGGER, "malloc(CONFIG_TIC_UART_READ_BUFFER_SIZE) failed!"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// trim the checksum
|
|
|
|
scratch[pos - 2] = '\0'; |
|
|
|
ESP_LOGD(TIC_LOGGER, "validated: '%s'", scratch); |
|
|
|
} |
|
|
|
break; |
|
|
|
//Others
|
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
for (;;) { |
|
|
|
int len = uart_read_bytes(CONFIG_TIC_UART_PORT_NUM, buffer, CONFIG_TIC_UART_READ_BUFFER_SIZE, 20 / portTICK_RATE_MS); |
|
|
|
if (len == -1) { |
|
|
|
ESP_LOGE(TIC_LOGGER, "uart_read_bytes failed!"); |
|
|
|
break; |
|
|
|
} |
|
|
|
if (len == 0) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
ESP_LOGD(TIC_LOGGER, "uart_read_bytes read %d bytes", len); |
|
|
|
|
|
|
|
libteleinfo_process(buffer, len); |
|
|
|
} |
|
|
|
|
|
|
|
free(buffer); |
|
|
|
buffer = NULL; |
|
|
|
vTaskDelete(NULL); |
|
|
|
@ -128,22 +78,22 @@ void tic_uart_init() { |
|
|
|
}; |
|
|
|
#endif |
|
|
|
// Setup the UART
|
|
|
|
ESP_ERROR_CHECK(uart_driver_install(TIC_UART_NUM, TIC_BUFFER_SIZE, TIC_BUFFER_SIZE, 20, &uart_queue, 0)); |
|
|
|
ESP_ERROR_CHECK(uart_param_config(TIC_UART_NUM, &uart_config)); |
|
|
|
ESP_ERROR_CHECK(uart_set_pin(TIC_UART_NUM, UART_PIN_NO_CHANGE, CONFIG_TIC_UART_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); |
|
|
|
ESP_ERROR_CHECK(uart_enable_pattern_det_baud_intr(TIC_UART_NUM, '\r', 1, 9, 0, 0)); |
|
|
|
ESP_ERROR_CHECK(uart_pattern_queue_reset(TIC_UART_NUM, 20)); |
|
|
|
ESP_ERROR_CHECK(uart_driver_install(CONFIG_TIC_UART_PORT_NUM, CONFIG_TIC_UART_BUFFER_SIZE, 0, 0, NULL, 0)); |
|
|
|
ESP_ERROR_CHECK(uart_param_config(CONFIG_TIC_UART_PORT_NUM, &uart_config)); |
|
|
|
ESP_ERROR_CHECK(uart_set_pin(CONFIG_TIC_UART_PORT_NUM, UART_PIN_NO_CHANGE, CONFIG_TIC_UART_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); |
|
|
|
|
|
|
|
libteleinfo_init(tic_data_callback, tic_adps_callback); |
|
|
|
|
|
|
|
// Create a task to handler UART event from ISR
|
|
|
|
BaseType_t xReturned; |
|
|
|
xReturned = xTaskCreate(tic_uart_events, |
|
|
|
"tic_uart_events", |
|
|
|
xReturned = xTaskCreate(tic_uart_read, |
|
|
|
"tic_uart_read", |
|
|
|
CONFIG_TIC_UART_STACK_SIZE, /* Stack size in words, not bytes. */ |
|
|
|
NULL, /* Parameter passed into the task. */ |
|
|
|
tskIDLE_PRIORITY + 12, |
|
|
|
NULL); |
|
|
|
if (xReturned != pdPASS) { |
|
|
|
ESP_LOGE(TIC_LOGGER, "xTaskCreate('tic_uart_events'): %d", xReturned); |
|
|
|
ESP_LOGE(TIC_LOGGER, "xTaskCreate('tic_uart_read'): %d", xReturned); |
|
|
|
abort(); |
|
|
|
} |
|
|
|
} |