feat: resilient boot + full polish pass
Firmware:
- nfc_engine: add nfc_engine_try_init() (non-fatal, sets s_pn532_ready),
nfc_engine_try_reattach() (soft re-init, skips bus re-init),
nfc_engine_is_ready() accessor
- main: replace ESP_ERROR_CHECK(nfc_engine_init) with nfc_engine_try_init;
device boots and serves web UI even with no PN532 connected
- app_net: add reconnect_task — every 5s retries nfc_engine_try_reattach()
and broadcasts {"channel":"pn532","payload":{"connected":true}} over WS
- app_net: scan_loop_task skips polling when !nfc_engine_is_ready()
- app_net/api_status: always emit pn532Connected bool; null-guard pn532 fw object
- find_sector_hit / program_classic_snapshot_locked: null-guard cJSON array items
- session_capture: abort if xSemaphoreCreateMutex() returns NULL
Web:
- NfcWsContext: track pn532Connected state from WS pn532 channel + status fetch on connect
- App.tsx: live HeaderBadge (LIVE/NO RF/WAIT) replacing static text
- Dashboard: READY/SEARCHING pill with fw version when available
- api.ts: add pn532Connected to Status type
- toast.tsx: fix ID collision (Date.now + Math.random)
- Capture: surface status fetch errors
- ReadAnalyze: add error feedback for readUl when no data returned
- WriteClone: busy state on both write buttons
- RawConsole: toast when frame returns error not response
- Emulate: validate hex before send (non-empty, even length, hex chars only)
- Brute: warn and skip invalid custom key lines
Made-with: Cursor
This commit is contained in:
@@ -26,8 +26,19 @@ typedef struct {
|
||||
bool key_b;
|
||||
} nfc_mifare_key_t;
|
||||
|
||||
/** Legacy: full init including transport — aborts on failure via caller's ESP_ERROR_CHECK. */
|
||||
esp_err_t nfc_engine_init(void);
|
||||
|
||||
/** Non-fatal first-boot init. Returns true if PN532 is present and configured. */
|
||||
bool nfc_engine_try_init(void);
|
||||
|
||||
/** Soft re-attach after transport is already open — skips bus re-init, tries chip commands.
|
||||
* Call from a background retry loop; always safe to call even if already ready. */
|
||||
bool nfc_engine_try_reattach(void);
|
||||
|
||||
/** Returns true when the PN532 was successfully initialised (or re-attached). */
|
||||
bool nfc_engine_is_ready(void);
|
||||
|
||||
esp_err_t nfc_poll_passive_target(nfc_tag_info_t *out);
|
||||
bool nfc_tag_is_mifare_classic(const nfc_tag_info_t *tag);
|
||||
bool nfc_tag_is_mifare_classic_4k(const nfc_tag_info_t *tag);
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
static const char *TAG = "nfc_engine";
|
||||
|
||||
static uint8_t s_tg = 1;
|
||||
static volatile bool s_pn532_ready = false;
|
||||
|
||||
bool nfc_engine_is_ready(void) { return s_pn532_ready; }
|
||||
|
||||
static void hint_type(nfc_tag_info_t *t)
|
||||
{
|
||||
@@ -102,9 +105,51 @@ esp_err_t nfc_engine_init(void)
|
||||
if (pn532_rf_max_retries() != ESP_OK) {
|
||||
ESP_LOGW(TAG, "RF max retries config failed");
|
||||
}
|
||||
s_pn532_ready = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool nfc_engine_try_init(void)
|
||||
{
|
||||
esp_err_t e = pn532_core_init();
|
||||
if (e != ESP_OK) {
|
||||
ESP_LOGW(TAG, "PN532 not found (%s) — AP running, will retry every 5 s", esp_err_to_name(e));
|
||||
s_pn532_ready = false;
|
||||
return false;
|
||||
}
|
||||
e = pn532_sam_config_normal();
|
||||
if (e != ESP_OK) {
|
||||
ESP_LOGW(TAG, "SAM config: %s", esp_err_to_name(e));
|
||||
}
|
||||
uint8_t ic = 0, hi = 0, lo = 0;
|
||||
if (pn532_get_firmware_version(&ic, &hi, &lo) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "PN532 fw ic=0x%02x %u.%u", ic, hi, lo);
|
||||
}
|
||||
if (pn532_rf_max_retries() != ESP_OK) {
|
||||
ESP_LOGW(TAG, "RF max retries config failed");
|
||||
}
|
||||
s_pn532_ready = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nfc_engine_try_reattach(void)
|
||||
{
|
||||
/* Transport already open — just ping the chip and re-apply configuration. */
|
||||
esp_err_t e = pn532_sam_config_normal();
|
||||
if (e != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
uint8_t ic = 0, hi = 0, lo = 0;
|
||||
if (pn532_get_firmware_version(&ic, &hi, &lo) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "PN532 reattached ic=0x%02x %u.%u", ic, hi, lo);
|
||||
}
|
||||
if (pn532_rf_max_retries() != ESP_OK) {
|
||||
ESP_LOGW(TAG, "RF max retries config failed");
|
||||
}
|
||||
s_pn532_ready = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
esp_err_t nfc_poll_passive_target(nfc_tag_info_t *out)
|
||||
{
|
||||
if (!out) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "nfc_engine/session_capture.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include <string.h>
|
||||
|
||||
#define SESSION_CAPTURE_BYTES (48 * 1024)
|
||||
@@ -15,6 +16,10 @@ static SemaphoreHandle_t s_mu;
|
||||
void session_capture_init(void)
|
||||
{
|
||||
s_mu = xSemaphoreCreateMutex();
|
||||
if (!s_mu) {
|
||||
ESP_LOGE("session_capture", "mutex create failed — aborting");
|
||||
abort();
|
||||
}
|
||||
session_capture_clear();
|
||||
s_deep = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user