mirror of
https://gitlab.com/fabinfra/fabhardware/fabreader3.git
synced 2025-03-12 22:51:42 +01:00
364 lines
12 KiB
C
364 lines
12 KiB
C
|
#include <sys/cdefs.h>
|
||
|
#include <stdio.h>
|
||
|
#include <esp_err.h>
|
||
|
#include <esp_wifi.h>
|
||
|
#include <esp_event.h>
|
||
|
#include <esp_log.h>
|
||
|
#include <nvs_flash.h>
|
||
|
#include <mqtt_client.h>
|
||
|
#include <esp_crt_bundle.h>
|
||
|
|
||
|
#include "fab-reader2.h"
|
||
|
#include "platform.h"
|
||
|
#include "st25R3911_interrupt.h"
|
||
|
#include "DEV_Config.h"
|
||
|
|
||
|
#include "pollingtagdetect.h"
|
||
|
#include "epd.h"
|
||
|
#include "ota.h"
|
||
|
|
||
|
#define SPI_CLK 5
|
||
|
#define SPI_MOSI 6
|
||
|
#define SPI_MISO 7
|
||
|
|
||
|
#define ESP_INTR_FLAG_DEFAULT 0
|
||
|
|
||
|
portMUX_TYPE CommProtectLock = portMUX_INITIALIZER_UNLOCKED;
|
||
|
|
||
|
esp_err_t init_mqtt(void);
|
||
|
|
||
|
static void IRAM_ATTR gpio_isr_handler(void *arg) {
|
||
|
st25r3911Isr();
|
||
|
ets_printf("Interrupt\n");
|
||
|
}
|
||
|
|
||
|
static void network_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
||
|
{
|
||
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||
|
esp_wifi_connect();
|
||
|
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||
|
esp_wifi_connect();
|
||
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||
|
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||
|
ESP_LOGI("network", "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||
|
ESP_ERROR_CHECK(init_mqtt());
|
||
|
ESP_LOGI("main", "init_mqtt done");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* @brief Event handler registered to receive MQTT events
|
||
|
*
|
||
|
* This function is called by the MQTT client event loop.
|
||
|
*
|
||
|
* @param handler_args user data registered to the event.
|
||
|
* @param base Event base for the handler(always MQTT Base in this example).
|
||
|
* @param event_id The id for the received event.
|
||
|
* @param event_data The data for the event, esp_mqtt_event_handle_t.
|
||
|
*/
|
||
|
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||
|
{
|
||
|
ESP_LOGD("mqtt", "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
|
||
|
esp_mqtt_event_handle_t event = event_data;
|
||
|
esp_mqtt_client_handle_t client = event->client;
|
||
|
int msg_id;
|
||
|
switch ((esp_mqtt_event_id_t)event_id) {
|
||
|
case MQTT_EVENT_CONNECTED:
|
||
|
ESP_LOGI("mqtt", "MQTT_EVENT_CONNECTED");
|
||
|
|
||
|
char id[6] = "00000";
|
||
|
sprintf(id, "%05d", CONFIG_FABREADER2_ID);
|
||
|
|
||
|
// Register Reader
|
||
|
msg_id = esp_mqtt_client_publish(client, "fabreader", id, 0, 0, 0);
|
||
|
ESP_LOGI("mqtt", "sent publish successful, msg_id=%d", msg_id);
|
||
|
|
||
|
char topic_requestOTA[] = "fabreader/00000/requestOTA";
|
||
|
sprintf(topic_requestOTA, "fabreader/%05d/requestOTA", CONFIG_FABREADER2_ID);
|
||
|
msg_id = esp_mqtt_client_subscribe(client, topic_requestOTA, 0);
|
||
|
ESP_LOGI("mqtt", "sent subscribe successful, msg_id=%d", msg_id);
|
||
|
|
||
|
char topic_stopOTA[] = "fabreader/00000/stopOTA";
|
||
|
sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", CONFIG_FABREADER2_ID);
|
||
|
msg_id = esp_mqtt_client_subscribe(client, topic_stopOTA, 0);
|
||
|
ESP_LOGI("mqtt", "sent subscribe successful, msg_id=%d", msg_id);
|
||
|
|
||
|
char topic_display[] = "fabreader/00000/display/#";
|
||
|
sprintf(topic_display, "fabreader/%05d/display/#", CONFIG_FABREADER2_ID);
|
||
|
msg_id = esp_mqtt_client_subscribe(client, topic_display, 0);
|
||
|
ESP_LOGI("mqtt", "sent subscribe successful, msg_id=%d", msg_id);
|
||
|
|
||
|
break;
|
||
|
case MQTT_EVENT_DISCONNECTED:
|
||
|
ESP_LOGI("mqtt", "MQTT_EVENT_DISCONNECTED");
|
||
|
break;
|
||
|
|
||
|
case MQTT_EVENT_SUBSCRIBED:
|
||
|
ESP_LOGI("mqtt", "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||
|
break;
|
||
|
case MQTT_EVENT_UNSUBSCRIBED:
|
||
|
ESP_LOGI("mqtt", "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||
|
break;
|
||
|
case MQTT_EVENT_PUBLISHED:
|
||
|
ESP_LOGI("mqtt", "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||
|
break;
|
||
|
case MQTT_EVENT_DATA:
|
||
|
ESP_LOGI("mqtt", "MQTT_EVENT_DATA");
|
||
|
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||
|
printf("DATA=%.*s\r\n", event->data_len, event->data);
|
||
|
|
||
|
if (hasActiveOTA()) {
|
||
|
continueOTA(client, event->topic, event->data, event->data_len);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
case MQTT_EVENT_ERROR:
|
||
|
ESP_LOGE("mqtt", "MQTT_EVENT_ERROR");
|
||
|
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
|
||
|
ESP_LOGE("mqtt", "Last error code reported from esp-tls: 0x%x", event->error_handle->esp_tls_last_esp_err);
|
||
|
ESP_LOGE("mqtt", "Last tls stack error number: 0x%x", event->error_handle->esp_tls_stack_err);
|
||
|
ESP_LOGE("mqtt", "Last captured errno : %d (%s)", event->error_handle->esp_transport_sock_errno,
|
||
|
strerror(event->error_handle->esp_transport_sock_errno));
|
||
|
} else if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) {
|
||
|
ESP_LOGE("mqtt", "Connection refused error: 0x%x", event->error_handle->connect_return_code);
|
||
|
} else {
|
||
|
ESP_LOGW("mqtt", "Unknown error type: 0x%x", event->error_handle->error_type);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
ESP_LOGI("mqtt", "Other event id:%d", event->event_id);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
esp_err_t init_gpio(void) {
|
||
|
gpio_config_t io_conf = {};
|
||
|
//disable interrupt
|
||
|
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||
|
//set as output mode
|
||
|
io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
|
||
|
//bit mask of the pins that you want to set,e.g.GPIO18/19
|
||
|
io_conf.pin_bit_mask = (1ULL << ST25R391X_SS_PIN) | (1ULL << EPD_CS_PIN) | (1ULL << EPD_DC_PIN) | (1ULL << EPD_RST_PIN);
|
||
|
//disable pull-down mode
|
||
|
io_conf.pull_down_en = 0;
|
||
|
//disable pull-up mode
|
||
|
io_conf.pull_up_en = 0;
|
||
|
//configure GPIO with the given settings
|
||
|
esp_err_t ret = gpio_config(&io_conf);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
|
||
|
io_conf.mode = GPIO_MODE_INPUT;
|
||
|
io_conf.pin_bit_mask = (1ULL << EPD_BUSY_PIN);
|
||
|
|
||
|
ret = gpio_config(&io_conf);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
|
||
|
//interrupt of rising edge
|
||
|
io_conf.intr_type = GPIO_INTR_POSEDGE;
|
||
|
//bit mask of the pins, use GPIO4/5 here
|
||
|
io_conf.pin_bit_mask = (1ULL << ST25R391X_INT_PIN);
|
||
|
//set as input mode
|
||
|
io_conf.mode = GPIO_MODE_INPUT;
|
||
|
//disable pull-down mode
|
||
|
io_conf.pull_down_en = 0;
|
||
|
//enable pull-up mode
|
||
|
io_conf.pull_up_en = 0;
|
||
|
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||
|
|
||
|
ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT));
|
||
|
//hook isr handler for specific gpio pin
|
||
|
ESP_ERROR_CHECK(gpio_isr_handler_add(ST25R391X_INT_PIN, gpio_isr_handler, NULL));
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
esp_err_t init_spi(void) {
|
||
|
spi_bus_config_t buscfg = {
|
||
|
.miso_io_num=SPI_MISO,
|
||
|
.mosi_io_num=SPI_MOSI,
|
||
|
.sclk_io_num=SPI_CLK,
|
||
|
.quadwp_io_num=-1,
|
||
|
.quadhd_io_num=-1,
|
||
|
};
|
||
|
esp_err_t ret = spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
|
||
|
spi_device_interface_config_t nfc_devcfg = {
|
||
|
.clock_speed_hz=SPI_MASTER_FREQ_8M, //Clock out at 26 MHz
|
||
|
.mode=1, //SPI mode 1
|
||
|
.spics_io_num=-1, //CS pin
|
||
|
.queue_size=1, //We want to be able to queue 7 transactions at a time
|
||
|
};
|
||
|
|
||
|
spi_device_handle_t nfc_spi;
|
||
|
ret = spi_bus_add_device(SPI3_HOST, &nfc_devcfg, &nfc_spi);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
st25r3911_spi_init(nfc_spi);
|
||
|
|
||
|
spi_device_interface_config_t epd_devcfg = {
|
||
|
.clock_speed_hz=SPI_MASTER_FREQ_8M, //Clock out at 26 MHz
|
||
|
.mode=0, //SPI mode 1
|
||
|
.spics_io_num=-1, //CS pin
|
||
|
.queue_size=1, //We want to be able to queue 7 transactions at a time
|
||
|
};
|
||
|
|
||
|
spi_device_handle_t epd_spi;
|
||
|
ret = spi_bus_add_device(SPI3_HOST, &epd_devcfg, &epd_spi);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
DEV_SPI_Init(epd_spi);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
esp_err_t init_eventloop() {
|
||
|
esp_err_t ret = esp_event_loop_create_default();
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
esp_err_t init_wifi() {
|
||
|
esp_err_t ret;
|
||
|
ret = esp_netif_init();
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
|
||
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||
|
ret = esp_wifi_init(&cfg);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
|
||
|
ret = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &network_event_handler, NULL, NULL);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &network_event_handler, NULL, NULL);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
|
||
|
|
||
|
// Initialize default station as network interface instance (esp-netif)
|
||
|
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
|
||
|
assert(sta_netif);
|
||
|
|
||
|
// Initialize and start WiFi
|
||
|
wifi_config_t wifi_config = {
|
||
|
.sta = {
|
||
|
.ssid = DEFAULT_SSID,
|
||
|
.password = DEFAULT_PWD,
|
||
|
.scan_method = DEFAULT_SCAN_METHOD,
|
||
|
.sort_method = DEFAULT_SORT_METHOD,
|
||
|
.threshold.rssi = DEFAULT_RSSI,
|
||
|
.threshold.authmode = DEFAULT_AUTHMODE,
|
||
|
},
|
||
|
};
|
||
|
ret = esp_wifi_set_mode(WIFI_MODE_STA);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
ret = esp_wifi_start();
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
esp_err_t init_nvs() {
|
||
|
// Initialize NVS
|
||
|
esp_err_t ret = nvs_flash_init();
|
||
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||
|
ret = nvs_flash_init();
|
||
|
}
|
||
|
ESP_ERROR_CHECK( ret );
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
esp_err_t init_mqtt() {
|
||
|
esp_err_t ret;
|
||
|
const esp_mqtt_client_config_t mqtt_cfg = {
|
||
|
.uri = CONFIG_BROKER_URI,
|
||
|
.crt_bundle_attach = esp_crt_bundle_attach
|
||
|
};
|
||
|
|
||
|
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
||
|
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
|
||
|
ret = esp_mqtt_client_register_event(client, MQTT_EVENT_ANY, mqtt_event_handler, NULL);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
ret = esp_mqtt_client_start(client);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
|
||
|
mqtt_client = client;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
esp_err_t init_epd() {
|
||
|
esp_err_t ret;
|
||
|
|
||
|
reader_info_t reader_info = {
|
||
|
.reader_id = CONFIG_FABREADER2_ID,
|
||
|
.battery_level = 100
|
||
|
};
|
||
|
|
||
|
buttons_t buttons = {
|
||
|
.btn0 = "X",
|
||
|
.btn1 = "<",
|
||
|
.btn2 = "O",
|
||
|
.btn3 = ">"
|
||
|
};
|
||
|
|
||
|
display_t display = {
|
||
|
.canvas = NULL,
|
||
|
.image = NULL,
|
||
|
.machine_name = "",
|
||
|
.state = "IDLE",
|
||
|
.buttons = buttons,
|
||
|
.reader_info = reader_info
|
||
|
};
|
||
|
ret = epd_init(display);
|
||
|
ESP_ERROR_CHECK(ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
_Noreturn static void cycle_task(void *arg) {
|
||
|
while (1) {
|
||
|
TagDetectCycle();
|
||
|
// ESP_LOGI("cycle_task", "running tag detect cycle_task");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void app_main(void) {
|
||
|
// Log basic information about the system
|
||
|
ESP_LOGI("startup", "Startup..");
|
||
|
ESP_LOGI("startup", "Built with IDF version: %s", esp_get_idf_version());
|
||
|
esp_chip_info_t chip_info;
|
||
|
esp_chip_info(&chip_info);
|
||
|
ESP_LOGI("startup", "This is %s chip with %d CPU cores, WiFi%s%s, ",
|
||
|
chip_info.model == CHIP_ESP32S3 ? "ESP32S3" : CHIP_ESP32S2 ? "ESP32S2" : "unknown",
|
||
|
chip_info.cores,
|
||
|
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
||
|
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
|
||
|
|
||
|
|
||
|
// Initialize peripherals
|
||
|
ESP_ERROR_CHECK(init_gpio());
|
||
|
ESP_LOGI("main", "init_gpio done");
|
||
|
ESP_ERROR_CHECK(init_spi());
|
||
|
ESP_LOGI("main", "init_spi done");
|
||
|
// ESP_ERROR_CHECK(init_epd());
|
||
|
ESP_LOGI("main", "init_epd done");
|
||
|
ESP_ERROR_CHECK(init_nvs());
|
||
|
ESP_LOGI("main", "init_nvs done");
|
||
|
ESP_ERROR_CHECK(init_eventloop());
|
||
|
ESP_LOGI("main", "init_eventloop done");
|
||
|
ESP_ERROR_CHECK(init_wifi());
|
||
|
ESP_LOGI("main", "init_wifi done");
|
||
|
|
||
|
// epd_update_state("OTA...");
|
||
|
|
||
|
// Start main application
|
||
|
ESP_ERROR_CHECK(TagDetectInit());
|
||
|
ESP_LOGI("main", "TagDetectInit done");
|
||
|
xTaskCreate(cycle_task, "cycle_task", 4096, NULL, tskIDLE_PRIORITY, NULL);
|
||
|
ESP_LOGI("main", "cycle_task sheduled");
|
||
|
|
||
|
|
||
|
ESP_LOGI("app", "Free memory: %d bytes", esp_get_free_heap_size());
|
||
|
|
||
|
|
||
|
}
|