Scanner config management code

This commit is contained in:
2026-05-19 23:02:09 +03:00
parent d5738d460c
commit 96233d2ae5
3 changed files with 281 additions and 27 deletions
+1
View File
@@ -18,6 +18,7 @@ board_build.partitions = default.csv
build_flags =
-DARDUINO_USB_CDC_ON_BOOT=1
-DBOARD_HAS_PSRAM
-DCORE_DEBUG_LEVEL=0
lib_deps =
h2zero/NimBLE-Arduino
+223 -23
View File
@@ -5,9 +5,14 @@
#include "freertos/queue.h"
#include <HTTPClient.h>
#include <PubSubClient.h>
#include <Preferences.h>
#include "esp_system.h"
Preferences prefs;
Config config;
CB cb;
char MQTT_PUB_TOPIC[sizeof(MQTT_TOPIC) + sizeof(DEV_NAME) - 1];
String MQTT_PUB_TOPIC;
String serial_buffer = "";
std::unordered_map<std::string, Tag> tags;
std::unordered_map<std::string, UUIDCacheEntry> uuid_cache;
SemaphoreHandle_t uuid_mtx;
@@ -27,7 +32,7 @@ void cleanupCache()
{
uint32_t age = now - it->second.last_check;
if (age > UUID_CACHE_CLEAN_TIMEOUT)
if (age > config.interval.uuid_cache_clean_timeout)
{
Serial.printf("Erasing %s from cache after being inactive for %dms.\n",
it->first.c_str(),
@@ -47,7 +52,7 @@ void cleanupTags()
for (auto it = tags.begin(); it != tags.end();)
{
if ((now - it->second.getLastSeen()) >= TAG_TIMEOUT)
if ((now - it->second.getLastSeen()) >= config.interval.tag_timeout)
{
Serial.printf("Erasing %s from memory after being inactive for %dms.\n",
it->first.c_str(),
@@ -69,7 +74,7 @@ void httpTask(void *)
{
HTTPClient http;
String url = UUID_CHECK_ENDPOINT + String(ev.uuid);
String url = config.api.url + config.api.uuid_check_endpoint + String("/") + String(ev.uuid);
http.setTimeout(3000);
http.setReuse(false);
@@ -82,6 +87,19 @@ void httpTask(void *)
int code = http.GET();
if (code < 0)
{
xSemaphoreTake(uuid_mtx, portMAX_DELAY);
uuid_cache[ev.uuid] = {
UUIDState::RETRY,
millis()};
xSemaphoreGive(uuid_mtx);
http.end();
continue;
}
bool valid = (code == 200);
http.end();
@@ -110,8 +128,8 @@ void mqttTask(void *)
{
while (!mqtt.connected())
{
Serial.printf("MQTT Disconnected. Connecting to %s:%d\n", MQTT_HOST, MQTT_PORT);
if (mqtt.connect(DEV_NAME, MQTT_USER, MQTT_PASS))
Serial.printf("MQTT Disconnected. Connecting to %s:%d\n", config.mqtt.host.c_str(), config.mqtt.port);
if (mqtt.connect(config.dev_name.c_str(), config.mqtt.username.c_str(), config.mqtt.password.c_str()))
Serial.println("MQTT connected.");
vTaskDelay(pdMS_TO_TICKS(1000));
}
@@ -125,7 +143,7 @@ void mqttTask(void *)
ev.uuid,
ev.ema);
bool ok = mqtt.publish(MQTT_PUB_TOPIC, payload);
bool ok = mqtt.publish(MQTT_PUB_TOPIC.c_str(), payload);
if (!ok)
Serial.println("Failed to publish on MQTT.");
@@ -143,7 +161,7 @@ void processEvent(const BleEvent &event)
uint32_t now = millis();
if (it == uuid_cache.end())
if (it == uuid_cache.end() || (it->second.state == UUIDState::RETRY))
{
uuid_cache[event.uuid] = {UUIDState::PENDING, now};
@@ -158,7 +176,7 @@ void processEvent(const BleEvent &event)
}
if (it->second.state == UUIDState::INVALID &&
now - it->second.last_check > UUID_CACHE_RETRY_TIMEOUT)
now - it->second.last_check > config.interval.uuid_cache_retry_timeout)
{
it->second.state = UUIDState::PENDING;
it->second.last_check = now;
@@ -202,9 +220,9 @@ void CB::onResult(const NimBLEAdvertisedDevice *d)
return;
NimBLEUUID uuid = d->getServiceUUID(0);
const std::string &name = d->getName();
const String name(d->getName().c_str());
if ((uuid.bitSize() != 128) || (name != TAG_NAME))
if ((uuid.bitSize() != 128) || (name != config.tag_name))
return;
BleEvent event;
@@ -215,23 +233,170 @@ void CB::onResult(const NimBLEAdvertisedDevice *d)
xQueueSend(ble_queue, &event, pdMS_TO_TICKS(5));
}
void saveConfig()
{
prefs.begin("config", false);
prefs.putUInt(CLEANUP_INTERVAL_CONFIG_KEY, config.interval.cleanup);
prefs.putUInt(TAG_TIMEOUT_CONFIG_KEY, config.interval.tag_timeout);
prefs.putUInt(UUID_CACHE_RETRY_TIMEOUT_CONFIG_KEY, config.interval.uuid_cache_retry_timeout);
prefs.putUInt(UUID_CACHE_CLEAN_TIMEOUT_CONFIG_KEY, config.interval.uuid_cache_clean_timeout);
prefs.putString(API_URL_CONFIG_KEY, config.api.url);
prefs.putString(UUID_CHECK_ENDPOINT_CONFIG_KEY, config.api.uuid_check_endpoint);
prefs.putString(MQTT_HOST_CONFIG_KEY, config.mqtt.host);
prefs.putUShort(MQTT_PORT_CONFIG_KEY, config.mqtt.port);
prefs.putString(MQTT_USER_CONFIG_KEY, config.mqtt.username);
prefs.putString(MQTT_PASS_CONFIG_KEY, config.mqtt.password);
prefs.putString(MQTT_TOPIC_CONFIG_KEY, config.mqtt.topic);
prefs.putString(WIFI_SSID_CONFIG_KEY, config.wifi.ssid);
prefs.putString(WIFI_PASS_CONFIG_KEY, config.wifi.password);
prefs.putString(DEV_NAME_CONFIG_KEY, config.dev_name);
prefs.putString(TAG_NAME_CONFIG_KEY, config.tag_name);
prefs.end();
}
void loadConfig()
{
prefs.begin("config", true);
config.interval.cleanup = prefs.getUInt(CLEANUP_INTERVAL_CONFIG_KEY, CLEANUP_INTERVAL);
config.interval.tag_timeout = prefs.getUInt(TAG_TIMEOUT_CONFIG_KEY, TAG_TIMEOUT);
config.interval.uuid_cache_retry_timeout = prefs.getUInt(UUID_CACHE_RETRY_TIMEOUT_CONFIG_KEY, UUID_CACHE_RETRY_TIMEOUT);
config.interval.uuid_cache_clean_timeout = prefs.getUInt(UUID_CACHE_CLEAN_TIMEOUT_CONFIG_KEY, UUID_CACHE_CLEAN_TIMEOUT);
config.api.url = prefs.getString(API_URL_CONFIG_KEY, API_URL);
config.api.uuid_check_endpoint = prefs.getString(UUID_CHECK_ENDPOINT_CONFIG_KEY, UUID_CHECK_ENDPOINT);
config.mqtt.host = prefs.getString(MQTT_HOST_CONFIG_KEY, MQTT_HOST);
config.mqtt.port = prefs.getUShort(MQTT_PORT_CONFIG_KEY, MQTT_PORT);
config.mqtt.username = prefs.getString(MQTT_USER_CONFIG_KEY, MQTT_USER);
config.mqtt.password = prefs.getString(MQTT_PASS_CONFIG_KEY, MQTT_PASS);
config.mqtt.topic = prefs.getString(MQTT_TOPIC_CONFIG_KEY, MQTT_TOPIC);
config.wifi.ssid = prefs.getString(WIFI_SSID_CONFIG_KEY, WIFI_SSID);
config.wifi.password = prefs.getString(WIFI_PASS_CONFIG_KEY, WIFI_PASS);
config.dev_name = prefs.getString(DEV_NAME_CONFIG_KEY, DEV_NAME);
config.tag_name = prefs.getString(TAG_NAME_CONFIG_KEY, TAG_NAME);
prefs.end();
}
void handleCommand(String line)
{
if (line.startsWith("set "))
{
int p1 = line.indexOf(' ', 4);
String key = line.substring(4, p1);
String value = line.substring(p1 + 1);
if (key.length() == 0 || value.length() == 0)
return;
if (key == CLEANUP_INTERVAL_CONFIG_KEY)
config.interval.cleanup = (uint32_t)value.toInt();
else if (key == TAG_TIMEOUT_CONFIG_KEY)
config.interval.tag_timeout = (uint32_t)value.toInt();
else if (key == UUID_CACHE_RETRY_TIMEOUT_CONFIG_KEY)
config.interval.uuid_cache_retry_timeout = (uint32_t)value.toInt();
else if (key == UUID_CACHE_CLEAN_TIMEOUT_CONFIG_KEY)
config.interval.uuid_cache_clean_timeout = (uint32_t)value.toInt();
else if (key == API_URL_CONFIG_KEY)
config.api.url = value;
else if (key == UUID_CHECK_ENDPOINT_CONFIG_KEY)
config.api.uuid_check_endpoint = value;
else if (key == MQTT_HOST_CONFIG_KEY)
config.mqtt.host = value;
else if (key == MQTT_PORT_CONFIG_KEY)
config.mqtt.port = value.toInt();
else if (key == MQTT_USER_CONFIG_KEY)
config.mqtt.username = value;
else if (key == MQTT_PASS_CONFIG_KEY)
config.mqtt.password = value;
else if (key == MQTT_TOPIC_CONFIG_KEY)
config.mqtt.topic = value;
else if (key == WIFI_SSID_CONFIG_KEY)
config.wifi.ssid = value;
else if (key == WIFI_PASS_CONFIG_KEY)
config.wifi.password = value;
else if (key == DEV_NAME_CONFIG_KEY)
config.dev_name = value;
else if (key == TAG_NAME_CONFIG_KEY)
config.tag_name = value;
}
else if (line == "save")
saveConfig();
else if (line.startsWith("show "))
{
String key = line.substring(5);
if (key.length() == 0)
return;
if (key == CLEANUP_INTERVAL_CONFIG_KEY)
Serial.println(config.interval.cleanup);
else if (key == TAG_TIMEOUT_CONFIG_KEY)
Serial.println(config.interval.tag_timeout);
else if (key == UUID_CACHE_RETRY_TIMEOUT_CONFIG_KEY)
Serial.println(config.interval.uuid_cache_retry_timeout);
else if (key == UUID_CACHE_CLEAN_TIMEOUT_CONFIG_KEY)
Serial.println(config.interval.uuid_cache_clean_timeout);
else if (key == API_URL_CONFIG_KEY)
Serial.println(config.api.url);
else if (key == UUID_CHECK_ENDPOINT_CONFIG_KEY)
Serial.println(config.api.uuid_check_endpoint);
else if (key == MQTT_HOST_CONFIG_KEY)
Serial.println(config.mqtt.host);
else if (key == MQTT_PORT_CONFIG_KEY)
Serial.println(config.mqtt.port);
else if (key == MQTT_USER_CONFIG_KEY)
Serial.println(config.mqtt.username);
else if (key == MQTT_PASS_CONFIG_KEY)
Serial.println(config.mqtt.password);
else if (key == MQTT_TOPIC_CONFIG_KEY)
Serial.println(config.mqtt.topic);
else if (key == WIFI_SSID_CONFIG_KEY)
Serial.println(config.wifi.ssid);
else if (key == WIFI_PASS_CONFIG_KEY)
Serial.println(config.wifi.password);
else if (key == DEV_NAME_CONFIG_KEY)
Serial.println(config.dev_name);
else if (key == TAG_NAME_CONFIG_KEY)
Serial.println(config.tag_name);
}
else if (line == "reboot")
{
Serial.println("Rebooting...");
Serial.flush();
esp_restart();
}
else if (line == "help")
{
Serial.println("Commands:");
Serial.println(" set <key> <value> - Set a configuration value");
Serial.println(" show <key> - Show a configuration value");
Serial.println(" save - Save configuration to non-volatile storage");
Serial.println(" reboot - Reboot the device");
Serial.println(" help - Show this help message");
}
}
void setup()
{
Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PASS);
loadConfig();
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
WiFi.begin(config.wifi.ssid.c_str(), config.wifi.password.c_str());
Serial.println("\nWiFi connected");
MQTT_PUB_TOPIC = config.mqtt.topic + config.dev_name;
snprintf(MQTT_PUB_TOPIC, sizeof(MQTT_PUB_TOPIC), "%s%s", MQTT_TOPIC, DEV_NAME);
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setServer(config.mqtt.host.c_str(), config.mqtt.port);
mqtt.setKeepAlive(60);
mqtt.setSocketTimeout(5);
@@ -244,7 +409,7 @@ void setup()
xTaskCreatePinnedToCore(mqttTask, "mqtt", 4096, NULL, 1, NULL, 1);
xTaskCreatePinnedToCore(httpTask, "http", 4096, NULL, 1, NULL, 1);
NimBLEDevice::init(DEV_NAME);
NimBLEDevice::init(config.dev_name.c_str());
NimBLEScan *scan = NimBLEDevice::getScan();
@@ -264,10 +429,45 @@ void loop()
static uint32_t last_cleanup = 0;
if (millis() - last_cleanup >= CLEANUP_INTERVAL)
if (millis() - last_cleanup >= config.interval.cleanup)
{
cleanupTags();
cleanupCache();
last_cleanup = millis();
}
while (Serial.available())
{
char c = Serial.read();
if (c == '\r')
continue;
if (c == '\n')
{
Serial.print(c);
serial_buffer.trim();
if (serial_buffer.length() > 0)
handleCommand(serial_buffer);
serial_buffer = "";
Serial.printf("%s> ", config.dev_name.c_str());
}
else if (c == '\b')
{
if (serial_buffer.length() > 0)
{
serial_buffer.remove(serial_buffer.length() - 1);
Serial.print("\b \b");
}
}
else
{
Serial.print(c);
serial_buffer += c;
}
}
}
+57 -4
View File
@@ -5,12 +5,29 @@
#include <NimBLEDevice.h>
#include <string>
#define CLEANUP_INTERVAL 5 * 1000 // ms
#define TAG_TIMEOUT 60 * 1000 // ms
#define UUID_CACHE_RETRY_TIMEOUT 5 * 60 * 1000 // ms
#define CLEANUP_INTERVAL_CONFIG_KEY "int.cln"
#define TAG_TIMEOUT_CONFIG_KEY "int.tagto"
#define UUID_CACHE_RETRY_TIMEOUT_CONFIG_KEY "int.urtry"
#define UUID_CACHE_CLEAN_TIMEOUT_CONFIG_KEY "int.ucclean"
#define API_URL_CONFIG_KEY "api.url"
#define UUID_CHECK_ENDPOINT_CONFIG_KEY "api.uuidchk"
#define MQTT_HOST_CONFIG_KEY "mq.host"
#define MQTT_PORT_CONFIG_KEY "mq.port"
#define MQTT_USER_CONFIG_KEY "mq.user"
#define MQTT_PASS_CONFIG_KEY "mq.pass"
#define MQTT_TOPIC_CONFIG_KEY "mq.topic"
#define WIFI_SSID_CONFIG_KEY "wf.ssid"
#define WIFI_PASS_CONFIG_KEY "wf.pass"
#define DEV_NAME_CONFIG_KEY "dev.name"
#define TAG_NAME_CONFIG_KEY "tag.name"
#define CLEANUP_INTERVAL 5 * 1000 // ms
#define TAG_TIMEOUT 60 * 1000 // ms
#define UUID_CACHE_RETRY_TIMEOUT 5 * 60 * 1000 // ms
#define UUID_CACHE_CLEAN_TIMEOUT 60 * 60 * 1000 // ms
#define API_URL "http://192.168.1.2"
#define UUID_CHECK_ENDPOINT "/check"
#define TAG_NAME "X6TAG"
#define UUID_CHECK_ENDPOINT "http://192.168.1.2/check/"
#define MQTT_HOST "192.168.1.2"
#define MQTT_PORT 1883
#define MQTT_USER "user"
@@ -20,6 +37,41 @@
#define WIFI_PASS "x32hbh54673ngccdsfa9"
#define DEV_NAME "Scanner_Room_A"
struct Config
{
struct Interval
{
uint32_t cleanup;
uint32_t tag_timeout;
uint32_t uuid_cache_retry_timeout;
uint32_t uuid_cache_clean_timeout;
} interval;
struct API
{
String url;
String uuid_check_endpoint;
} api;
struct MQTT
{
String host;
uint16_t port;
String username;
String password;
String topic;
} mqtt;
struct WiFi
{
String ssid;
String password;
} wifi;
String dev_name;
String tag_name;
};
struct BleEvent
{
char uuid[37];
@@ -40,6 +92,7 @@ struct HttpEvent
enum class UUIDState
{
PENDING,
RETRY,
VALID,
INVALID
};