fix:修补蓝牙配网bug
This commit is contained in:
@@ -19,7 +19,12 @@
|
|||||||
"Bash(sed -i 's/#define BTN_PAGE_SWITCH_PIN 10/#define BTN_PAGE_SWITCH_PIN 5/' include/config.h)",
|
"Bash(sed -i 's/#define BTN_PAGE_SWITCH_PIN 10/#define BTN_PAGE_SWITCH_PIN 5/' include/config.h)",
|
||||||
"Bash(sed -i 's/#define BTN_LONG_PRESS_MS 3000/#define BTN_LONG_PRESS_MS 1500/' include/config.h)",
|
"Bash(sed -i 's/#define BTN_LONG_PRESS_MS 3000/#define BTN_LONG_PRESS_MS 1500/' include/config.h)",
|
||||||
"Bash(sed -i 's/#define WATER_SENSOR_PIN 6 /#define WATER_SENSOR_PIN 45/' include/config.h)",
|
"Bash(sed -i 's/#define WATER_SENSOR_PIN 6 /#define WATER_SENSOR_PIN 45/' include/config.h)",
|
||||||
"Bash(sed -i 's/#define BUZZER_PIN 7 /#define BUZZER_PIN 21/' include/config.h)"
|
"Bash(sed -i 's/#define BUZZER_PIN 7 /#define BUZZER_PIN 21/' include/config.h)",
|
||||||
|
"PowerShell(Get-ChildItem \"$env:USERPROFILE\\\\.claude\" -ErrorAction SilentlyContinue; if \\(-not $?\\) { Write-Host \"No .claude at USERPROFILE\" })",
|
||||||
|
"Read(//c/Users/杨志佳/.claude/**)",
|
||||||
|
"Read(//d/ClaudeData/.claude/**)",
|
||||||
|
"Read(//c/Users/杨志佳/.claude/projects/d--PlatformIO1-Projects-Healthv2-0/memory/**)",
|
||||||
|
"Read(//d/PlatformIO1/Projects/Healthv2.0/ai/sessions/memory/**)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
ai/sessions/039b833c-6a52-4065-b35b-a12fce48084e.jsonl
Normal file
11
ai/sessions/039b833c-6a52-4065-b35b-a12fce48084e.jsonl
Normal file
File diff suppressed because one or more lines are too long
3349
ai/sessions/152c3275-1d69-42eb-bd73-a8a55eb17975.jsonl
Normal file
3349
ai/sessions/152c3275-1d69-42eb-bd73-a8a55eb17975.jsonl
Normal file
File diff suppressed because one or more lines are too long
18
ai/sessions/4519239c-d0ec-42cb-afab-57b7fb20a0d1.jsonl
Normal file
18
ai/sessions/4519239c-d0ec-42cb-afab-57b7fb20a0d1.jsonl
Normal file
File diff suppressed because one or more lines are too long
3505
ai/sessions/49fba966-60be-4542-a6c1-b5b7e0e566bb.jsonl
Normal file
3505
ai/sessions/49fba966-60be-4542-a6c1-b5b7e0e566bb.jsonl
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
{"agentType":"Explore","description":"Research U8g2 Chinese font options","toolUseId":"call_01_W4SVsAkWKYYPD3AllArZ6173","spawnDepth":1}
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
{"agentType":"Explore","description":"Explore existing patterns and GPIO","toolUseId":"call_00_wiJSGewBjcUTBxzRBDKV0217","spawnDepth":1}
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:31:WiFiManagerParameter::WiFiManagerParameter(const char *custom) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:37: _customHTML = custom;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:48:WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *label, const char *defaultValue, int length, const char *custom) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:49: init(id, label, defaultValue, length, custom, WFM_LABEL_DEFAULT);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:52:WiFiManagerParameter::WiFiManagerParameter(const char *id, const char *label, const char *defaultValue, int length, const char *custom, int labelPlacement) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:53: init(id, label, defaultValue, length, custom, labelPlacement);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:56:void WiFiManagerParameter::init(const char *id, const char *label, const char *defaultValue, int length, const char *custom, int labelPlacement) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:60: _customHTML = custom;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:124:const char* WiFiManagerParameter::getCustomHTML() const {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:125: return _customHTML;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:159: DEBUG_WM(WM_DEBUG_DEV,F("Updated _max_params:"),_max_params);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:220: if(_debug && _debugLevel >= WM_DEBUG_DEV) debugPlatformInfo();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:254: WiFi.persistent(false); // disable persistent so scannetworks and mode switching do not cause overwrites
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:283: // bool wifiIsSaved = getWiFiIsSaved();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:284: bool wifiIsSaved = true; // workaround until I can check esp32 wifiisinit and has nvs
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:287: setupHostname(true);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:302: // check if wifi is saved, (has autoconnect) to speed up cp start
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:304: if(wifiIsSaved){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:308: // attempt to connect using saved settings, on fail fallback to AP config portal
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:320: if(esp32persistent) WiFi.persistent(false); // disable persistent for esp32 after esp_wifi_start or else saves wont work
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:332: setupHostname(true);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:338: // @todo check if correct ssid == saved ssid when already connected
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:374: DEBUG_WM(F("No Credentials are Saved, skipping connect"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:392:bool WiFiManager::setupHostname(bool restart){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:455: // WiFi.reconnect(); // This does not reset dhcp
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:457: delay(200); // do not remove, need a delay for disconnect to change status()
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:481: // setup optional soft AP static ip config
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:484: DEBUG_WM(F("Custom AP IP/GW/Subnet:"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:560: setupConfigPortal();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:618:void WiFiManager::setupHTTPServer(){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:626: DEBUG_WM(WM_DEBUG_VERBOSE,F("http server started with custom port: "),_httpPort); // @todo not showing ip
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:630: server.reset(new WM_WebServer(_httpPort));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:631: // This is not the safest way to reset the webserver, it can cause crashes on callbacks initilized before this and since its a shared pointer...
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:641: /* Setup httpd callbacks, web pages: root, wifi config pages, SO captive portal detectors and not found. */
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:646: server->on(WM_G(R_wifinoscan), std::bind(&WiFiManager::handleWifi, this, false));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:647: server->on(WM_G(R_wifisave), std::bind(&WiFiManager::handleWifiSave, this));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:648: server->on(WM_G(R_info), std::bind(&WiFiManager::handleInfo, this));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:650: server->on(WM_G(R_paramsave), std::bind(&WiFiManager::handleParamSave, this));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:651: server->on(WM_G(R_restart), std::bind(&WiFiManager::handleReset, this));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:652: server->on(WM_G(R_exit), std::bind(&WiFiManager::handleExit, this));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:653: server->on(WM_G(R_close), std::bind(&WiFiManager::handleClose, this));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:658: server->on(WM_G(R_update), std::bind(&WiFiManager::handleUpdate, this));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:659: server->on(WM_G(R_updatedone), HTTP_POST, std::bind(&WiFiManager::handleUpdateDone, this), std::bind(&WiFiManager::handleUpdating, this));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:667:void WiFiManager::setupDNSD(){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:668: dnsServer.reset(new DNSServer());
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:670: /* Setup the DNS server redirecting all the domains to the apIP */
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:679:void WiFiManager::setupConfigPortal() {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:680: setupHTTPServer();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:681: _lastscan = 0; // reset network scan cache
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:682: if(_preloadwifiscan) WiFi_scanNetworks(true,true); // preload wifiscan , async
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:707: //setup AP
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:719: // HANDLE issues with STA connections, shutdown sta if not connected, or else this will hang channel scanning and softap will not respond
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:759: DEBUG_WM(WM_DEBUG_DEV,F("setupConfigPortal"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:761: setupConfigPortal();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:764: DEBUG_WM(WM_DEBUG_DEV,F("setupDNSD"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:766: setupDNSD();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:819: DEBUG_WM(WM_DEBUG_NOTIFY,F("config portal exiting"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:832: MDNS.update();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:837: if(_allowExit && (configPortalHasTimeout() || abort)){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:861: * returns WL_IDLE_STATUS or WL_CONNECTED/WL_CONNECT_FAILED upon connect/save flag
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:874: // Waiting for save...
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:878: DEBUG_WM(WM_DEBUG_VERBOSE,F("processing save"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:880: if(_enableCaptivePortal) delay(_cpclosedelay); // keeps the captiveportal from closing to fast.
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:885: DEBUG_WM(WM_DEBUG_VERBOSE,F("No ssid, skipping wifi save"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:890: uint8_t res = connectWifi(_ssid, _pass, _connectonsave) == WL_CONNECTED;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:891: if (res || (!_connectonsave)) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:893: if(!_connectonsave){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:894: DEBUG_WM(F("SAVED with no connect to new AP"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:896: DEBUG_WM(F("Connect to new AP [SUCCESS]"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:902: if ( _savewificallback != NULL) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:904: DEBUG_WM(WM_DEBUG_VERBOSE,F("[CB] _savewificallback calling"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:906: _savewificallback(); // @CALLBACK
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:908: if(!_connectonsave) return WL_IDLE_STATUS;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:913: DEBUG_WM(WM_DEBUG_ERROR,F("[ERROR] Connect to new AP Failed"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:919: // do save callback
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:920: // @todo this is more of an exiting callback than a save, clarify when this should actually occur
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:921: // confirm or verify data was saved to make this more accurate callback
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:922: if ( _savewificallback != NULL) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:924: DEBUG_WM(WM_DEBUG_VERBOSE,F("[CB] WiFi/Param save callback"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:926: _savewificallback(); // @CALLBACK
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:932: // clear save strings
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:975: server.reset();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:977: WiFi.scanDelete(); // free wifi scan results
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:982: dnsServer.reset();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1010: DEBUG_WM(WM_DEBUG_VERBOSE,F("configportal closed"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1028: // make sure sta is on before `begin` so it does not call enablesta->mode while persistent is ON ( which would save WM AP state to eeprom !)
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1044: // if ssid argument provided connect to that
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1048: // @todo connect=false seems to disconnect sta in begin() so not sure if _connectonsave is useful at all
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1051: if(_saveTimeout > 0){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1052: connRes = waitForConnectResult(_saveTimeout); // use default save timeout for saves to prevent bugs in esp->waitforconnectresult loop
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1060: // connect using saved ssid if there is one
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1067: DEBUG_WM(F("No wifi saved, skipping"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1089: if(connRes != WL_SCAN_COMPLETED){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1090: updateConxResult(connRes);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1097: * connect to a new wifi ap
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1102: * @return connect only save if false
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1122: * connect to stored wifi
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1130: DEBUG_WM(F("Connecting to SAVED AP:"),WiFi_SSID(true));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1164: DEBUG_WM(WM_DEBUG_VERBOSE,F("Custom static IP/GW/Subnet/DNS"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1168: DEBUG_WM(WM_DEBUG_VERBOSE,F("Custom static DNS"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1174: DEBUG_WM(WM_DEBUG_VERBOSE,F("Custom STA IP/GW/Subnet"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1193:void WiFiManager::updateConxResult(uint8_t status){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1281: page += _customHeadElement;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1336: String str = FPSTR(HTTP_ROOT_MAIN); // @todo custom title
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1346: if(_preloadwifiscan) WiFi_scanNetworks(_scancachetime,true); // preload wifiscan throttled, async
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1355:void WiFiManager::handleWifi(boolean scan) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1361: if (scan) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1365: WiFi_scanNetworks(server->hasArg(F("refresh")),false); //wifiscan, force if arg refresh
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1366: page += getScanItemOut();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1371: pitem.replace(FPSTR(T_v), F("wifisave")); // set form action
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1396: page += FPSTR(HTTP_SCAN_LINK);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1421: pitem.replace(FPSTR(T_v), F("paramsave"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1443: if((String)_menutokens[menuId] == "custom" && _customMenuHTML!=NULL){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1444: page += _customMenuHTML;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1454:// // is it possible in softap mode to detect aps without scanning
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1455:// bool WiFiManager::WiFi_scanNetworksForAP(bool force){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1456:// WiFi_scanNetworks(force);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1459:void WiFiManager::WiFi_scanComplete(int networksFound){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1460: _lastscan = millis();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1463: DEBUG_WM(WM_DEBUG_VERBOSE,F("WiFi Scan ASYNC completed"), "in "+(String)(_lastscan - _startscan)+" ms");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1464: DEBUG_WM(WM_DEBUG_VERBOSE,F("WiFi Scan ASYNC found:"),_numNetworks);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1468:bool WiFiManager::WiFi_scanNetworks(){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1469: return WiFi_scanNetworks(false,false);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1472:bool WiFiManager::WiFi_scanNetworks(unsigned int cachetime,bool async){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1473: return WiFi_scanNetworks(millis()-_lastscan > cachetime,async);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1475:bool WiFiManager::WiFi_scanNetworks(unsigned int cachetime){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1476: return WiFi_scanNetworks(millis()-_lastscan > cachetime,false);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1478:bool WiFiManager::WiFi_scanNetworks(bool force,bool async){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1480: // DEBUG_WM(WM_DEBUG_DEV,"scanNetworks async:",async == true);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1481: // DEBUG_WM(WM_DEBUG_DEV,_numNetworks,(millis()-_lastscan ));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1482: // DEBUG_WM(WM_DEBUG_DEV,"scanNetworks force:",force == true);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1485: // if 0 networks, rescan @note this was a kludge, now disabling to test real cause ( maybe wifi not init etc)
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1487: if(_numNetworks == 0 && _autoforcerescan){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1488: DEBUG_WM(WM_DEBUG_DEV,"NO APs found forcing new scan");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1492: // if scan is empty or stale (last scantime > _scancachetime), this avoids fast reloading wifi page and constant scan delayed page loads appearing to freeze.
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1493: if(!_lastscan || (_lastscan>0 && (millis()-_lastscan > _scancachetime))){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1499: _startscan = millis();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1500: if(async && _asyncScan){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1504: DEBUG_WM(WM_DEBUG_VERBOSE,F("WiFi Scan ASYNC started"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1507: WiFi.scanNetworksAsync(std::bind(&WiFiManager::WiFi_scanComplete,this,_1));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1509: DEBUG_WM(WM_DEBUG_VERBOSE,F("WiFi Scan SYNC started"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1510: res = WiFi.scanNetworks();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1514: DEBUG_WM(WM_DEBUG_VERBOSE,F("WiFi Scan ASYNC started"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1516: res = WiFi.scanNetworks(true);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1521: DEBUG_WM(WM_DEBUG_VERBOSE,F("WiFi Scan SYNC started"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1522: res = WiFi.scanNetworks();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1524: if(res == WIFI_SCAN_FAILED){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1526: DEBUG_WM(WM_DEBUG_ERROR,F("[ERROR] scan failed"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1529: else if(res == WIFI_SCAN_RUNNING){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1531: DEBUG_WM(WM_DEBUG_ERROR,F("[ERROR] scan waiting"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1533: while(WiFi.scanComplete() == WIFI_SCAN_RUNNING){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1539: _numNetworks = WiFi.scanComplete();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1542: _lastscan = millis();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1544: DEBUG_WM(WM_DEBUG_VERBOSE,F("WiFi Scan completed"), "in "+(String)(_lastscan - _startscan)+" ms");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1550: DEBUG_WM(WM_DEBUG_VERBOSE,F("Scan is cached"),(String)(millis()-_lastscan )+" ms ago");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1556:String WiFiManager::WiFiManager::getScanItemOut(){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1559: if(!_numNetworks) WiFi_scanNetworks(); // scan in case this gets called before any scans
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1564: DEBUG_WM(F("No networks found"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1617: HTTP_ITEM_STR.replace("{h}",_scanDispOptions ? "" : "h");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1619: HTTP_ITEM_STR.replace("{h}",_scanDispOptions ? "h" : "");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1697: // @todo how can we get these accurate settings from memory , wifi_get_ip_info does not seem to reveal if struct ip_info is static or not
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1769: // if no ID use customhtml for item, else generate from param string
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1779: if(tok_c)pitem.replace(FPSTR(T_c), _params[i]->getCustomHTML()); // T_c meant for additional attributes, not html, but can stuff
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1781: pitem = _params[i]->getCustomHTML();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1805: * HTTPD CALLBACK save form and redirect to WLAN config page again
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1807:void WiFiManager::handleWifiSave() {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1809: DEBUG_WM(WM_DEBUG_VERBOSE,F("<- HTTP WiFi save "));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1814: //SAVE/connect here
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1821: DEBUG_WM(WM_DEBUG_VERBOSE,F("Detected WiFi password change"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1826: String requestinfo = "SERVER_REQUEST\n----------------\n";
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1827: requestinfo += "URI: ";
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1828: requestinfo += server->uri();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1829: requestinfo += "\nMethod: ";
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1830: requestinfo += (server->method() == HTTP_GET) ? "GET" : "POST";
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1831: requestinfo += "\nArguments: ";
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1832: requestinfo += server->args();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1833: requestinfo += "\n";
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1835: requestinfo += " " + server->argName(i) + ": " + server->arg(i) + "\n";
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1838: DEBUG_WM(WM_DEBUG_MAX,requestinfo);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1872: if (_presavewificallback != NULL) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1873: _presavewificallback(); // @CALLBACK
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1876: if(_paramsInWifi) doParamSave();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1881: page = getHTTPHead(FPSTR(S_titlewifisettings)); // @token titleparamsaved
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1882: page += FPSTR(HTTP_PARAMSAVED);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1885: page = getHTTPHead(FPSTR(S_titlewifisaved)); // @token titlewifisaved
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1886: page += FPSTR(HTTP_SAVED);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1896: DEBUG_WM(WM_DEBUG_DEV,F("Sent wifi save page"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1899: connect = true; //signal ready to connect/reset process in processConfigPortal
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1902:void WiFiManager::handleParamSave() {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1905: DEBUG_WM(WM_DEBUG_VERBOSE,F("<- HTTP Param save "));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1912: doParamSave();
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1914: String page = getHTTPHead(FPSTR(S_titleparamsaved)); // @token titleparamsaved
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1915: page += FPSTR(HTTP_PARAMSAVED);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1922: DEBUG_WM(WM_DEBUG_DEV,F("Sent param save page"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1926:void WiFiManager::doParamSave(){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1927: // @todo use new callback for before paramsaves, is this really needed?
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1928: if ( _presaveparamscallback != NULL) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1929: _presaveparamscallback(); // @CALLBACK
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1966: if ( _saveparamscallback != NULL) {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1967: _saveparamscallback(); // @CALLBACK
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1973: * HTTPD CALLBACK info page
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1975:void WiFiManager::handleInfo() {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1977: DEBUG_WM(WM_DEBUG_VERBOSE,F("<- HTTP Info"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1980: String page = getHTTPHead(FPSTR(S_titleinfo)); // @token titleinfo
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1983: uint16_t infos = 0;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1986: //@todo wrap in build flag to remove all info code for memory saving
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1988: infos = 28;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:1989: String infoids[] = {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2002: F("lastreset"),
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2021: // add esp_chip_info ?
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2022: infos = 27;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2023: String infoids[] = {
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2034: F("lastreset"),
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2055: for(size_t i=0; i<infos;i++){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2056: if(infoids[i] != NULL) page += getInfoData(infoids[i]);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2061: page += getInfoData("aboutver");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2062: page += getInfoData("aboutarduinover");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2063: page += getInfoData("aboutidfver");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2064: page += getInfoData("aboutdate");
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2067: if(_showInfoUpdate){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2071: if(_showInfoErase) page += FPSTR(HTTP_ERASEBTN);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2079: DEBUG_WM(WM_DEBUG_DEV,F("Sent info page"));
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2083:String WiFiManager::getInfoData(String id){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2087: p = FPSTR(HTTP_INFO_esphead);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2093: p = FPSTR(HTTP_INFO_wifihead);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2098: p = FPSTR(HTTP_INFO_uptime);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2103: p = FPSTR(HTTP_INFO_chipid);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2108: p = FPSTR(HTTP_INFO_chiprev);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2120: p = FPSTR(HTTP_INFO_fchipid);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2125: p = FPSTR(HTTP_INFO_idesize);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2130: p = FPSTR(HTTP_INFO_flashsize);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2133: p = FPSTR(HTTP_INFO_psrsize);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2139: p = FPSTR(HTTP_INFO_corever);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2145: p = FPSTR(HTTP_INFO_bootver);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2150: p = FPSTR(HTTP_INFO_cpufreq);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2154: p = FPSTR(HTTP_INFO_freeheap);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2158: p = FPSTR(HTTP_INFO_memsketch);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2163: p = FPSTR(HTTP_INFO_memsmeter);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2167: else if(id==F("lastreset")){
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2169: p = FPSTR(HTTP_INFO_lastreset);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2170: p.replace(FPSTR(T_1),(String)ESP.getResetReason());
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2173: p = FPSTR(HTTP_INFO_lastreset);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2175: int reason = rtc_get_reset_reason(i);
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2180: case 1 : p.replace(tok,F("Vbat power on reset"));break;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2181: case 3 : p.replace(tok,F("Software reset digital core"));break;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2182: case 4 : p.replace(tok,F("Legacy watch dog reset digital core"));break;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2183: case 5 : p.replace(tok,F("Deep Sleep reset digital core"));break;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2184: case 6 : p.replace(tok,F("Reset by SLC module, reset digital core"));break;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2185: case 7 : p.replace(tok,F("Timer Group0 Watch dog reset digital core"));break;
|
||||||
|
.pio\libdeps\esp32-s3-devkitc-1\WiFiManager\WiFiManager.cpp:2186: case 8 : p.replace(tok,F("Timer Group1 Watch dog reset digital core"));break;
|
||||||
|
|
||||||
|
[Showing results with pagination = limit: 250]
|
||||||
Binary file not shown.
84
ai/sessions/7b1d8ddd-ba8d-4816-89f7-eabe285a91d1.jsonl
Normal file
84
ai/sessions/7b1d8ddd-ba8d-4816-89f7-eabe285a91d1.jsonl
Normal file
File diff suppressed because one or more lines are too long
8
ai/sessions/7c56d773-03b0-4edc-b149-7e681104cbc4.jsonl
Normal file
8
ai/sessions/7c56d773-03b0-4edc-b149-7e681104cbc4.jsonl
Normal file
File diff suppressed because one or more lines are too long
637
ai/sessions/861a1013-414b-44f3-b2a2-ee22ec67de60.jsonl
Normal file
637
ai/sessions/861a1013-414b-44f3-b2a2-ee22ec67de60.jsonl
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
434
ai/sessions/a6977a47-a6fb-42b8-b390-320c1530a1d7.jsonl
Normal file
434
ai/sessions/a6977a47-a6fb-42b8-b390-320c1530a1d7.jsonl
Normal file
File diff suppressed because one or more lines are too long
39
ai/sessions/af1f2385-2d2f-484c-9b19-4d9ed408b70c.jsonl
Normal file
39
ai/sessions/af1f2385-2d2f-484c-9b19-4d9ed408b70c.jsonl
Normal file
File diff suppressed because one or more lines are too long
16
ai/sessions/cff99f1c-b57e-4de3-980d-3dee4488b633.jsonl
Normal file
16
ai/sessions/cff99f1c-b57e-4de3-980d-3dee4488b633.jsonl
Normal file
File diff suppressed because one or more lines are too long
1964
ai/sessions/d07c3716-a856-4ff7-b6ef-cd0a3519488e.jsonl
Normal file
1964
ai/sessions/d07c3716-a856-4ff7-b6ef-cd0a3519488e.jsonl
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
{"agentType":"Explore","description":"查找报警和水浸逻辑","toolUseId":"call_00_wPSOk3gDw0mP3Mj0s8Xb0494","spawnDepth":1}
|
||||||
21
ai/sessions/ef4ebee4-da99-4e24-8c3e-fea9949042fa.jsonl
Normal file
21
ai/sessions/ef4ebee4-da99-4e24-8c3e-fea9949042fa.jsonl
Normal file
File diff suppressed because one or more lines are too long
@@ -19,7 +19,7 @@
|
|||||||
// --- 雷达型号选择 ---
|
// --- 雷达型号选择 ---
|
||||||
#define RADAR_TYPE_ABD1 0 // R60ABD1: 心率/呼吸精准, 跌倒一般
|
#define RADAR_TYPE_ABD1 0 // R60ABD1: 心率/呼吸精准, 跌倒一般
|
||||||
#define RADAR_TYPE_AFD1 1 // R60AFD1: 跌倒/姿态精准, 无心率呼吸
|
#define RADAR_TYPE_AFD1 1 // R60AFD1: 跌倒/姿态精准, 无心率呼吸
|
||||||
#define RADAR_TYPE RADAR_TYPE_AFD1 // 演示用 AFD1 (跌倒精准)
|
#define RADAR_TYPE RADAR_TYPE_AFD1 // AFD1 (跌倒/姿态精准)
|
||||||
|
|
||||||
// --- 毫米波雷达 ---
|
// --- 毫米波雷达 ---
|
||||||
#define RADAR_UART_PORT Serial2
|
#define RADAR_UART_PORT Serial2
|
||||||
@@ -120,8 +120,9 @@
|
|||||||
// 6. 上报配置 (协议规范 §4.1, §7.2)
|
// 6. 上报配置 (协议规范 §4.1, §7.2)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
#define REPORT_INTERVAL_MS 1000 // 遥测上报周期 1秒
|
#define REPORT_INTERVAL_MS 1000 // 遥测上报周期 1秒 (有人时)
|
||||||
#define REPORT_QOS 0 // 遥测 QoS 0
|
#define REPORT_QOS 0 // 遥测 QoS 0
|
||||||
|
#define PRESENCE_HEARTBEAT_MS 60000 // 无人心跳间隔 60秒 (4G省流量)
|
||||||
#define STATUS_QOS 1 // 状态/响应 QoS 1
|
#define STATUS_QOS 1 // 状态/响应 QoS 1
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -173,10 +174,11 @@
|
|||||||
|
|
||||||
struct TelemetryData {
|
struct TelemetryData {
|
||||||
// --- 设备标识 ---
|
// --- 设备标识 ---
|
||||||
char saleid[12]; // 站点编号 "10100001"
|
char saleid[12]; // 站点编号 (已弃用)
|
||||||
char gateid[16]; // 网关编号 "10100001001"
|
char gateid[16]; // 网关编号
|
||||||
char meterId[8]; // 节点ID "ENV001"
|
char meterId[8]; // 节点ID (已弃用, 新用 gateid+后缀)
|
||||||
char meterName[16]; // 设备型号 "RadarDHT11"
|
char meterName[16]; // 设备型号 "RadarDHT11"
|
||||||
|
char deviceType[16]; // 设备类型枚举 bedroom/bathroom/...
|
||||||
|
|
||||||
// --- 环境数据 (DHT11) ---
|
// --- 环境数据 (DHT11) ---
|
||||||
float temp; // 温度 ℃
|
float temp; // 温度 ℃
|
||||||
@@ -193,6 +195,8 @@ struct TelemetryData {
|
|||||||
uint8_t heartRate; // 心率 bpm (无效=0)
|
uint8_t heartRate; // 心率 bpm (无效=0)
|
||||||
uint8_t breathRate; // 呼吸 次/分 (无效=0)
|
uint8_t breathRate; // 呼吸 次/分 (无效=0)
|
||||||
uint8_t body; // 人体能量/体征值
|
uint8_t body; // 人体能量/体征值
|
||||||
|
uint8_t sleepState; // 睡眠状态 0=清醒 1=浅睡 2=深睡
|
||||||
|
uint8_t sleepScore; // 睡眠评分 0~100
|
||||||
bool radarValid; // 雷达数据有效性
|
bool radarValid; // 雷达数据有效性
|
||||||
bool vitalValid; // 心率呼吸有效性
|
bool vitalValid; // 心率呼吸有效性
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ public:
|
|||||||
/** 本地报警上报 status/{gateid}/alarm (§4.7 扩展) */
|
/** 本地报警上报 status/{gateid}/alarm (§4.7 扩展) */
|
||||||
void publishLocalAlarm(uint8_t alarmType, bool triggered, const char* desc);
|
void publishLocalAlarm(uint8_t alarmType, bool triggered, const char* desc);
|
||||||
|
|
||||||
|
/** 无人极简报文 (仅 Presence+RadarValid, 省4G流量) */
|
||||||
|
void publishPresenceOnly(bool presence, bool radarValid, uint32_t sequence);
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 回调注册 (协议规范 §5)
|
// 回调注册 (协议规范 §5)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ struct RadarRawData {
|
|||||||
uint8_t breathRate; // 呼吸
|
uint8_t breathRate; // 呼吸
|
||||||
uint8_t body; // 体动/能量值
|
uint8_t body; // 体动/能量值
|
||||||
uint16_t distance; // 距离 cm
|
uint16_t distance; // 距离 cm
|
||||||
|
uint8_t sleepState; // 睡眠状态: 0=清醒 1=浅睡 2=深睡
|
||||||
|
uint8_t sleepScore; // 睡眠评分: 0~100
|
||||||
|
|
||||||
bool radarValid; // 雷达有效性
|
bool radarValid; // 雷达有效性
|
||||||
bool vitalValid; // 生命体征有效性
|
bool vitalValid; // 生命体征有效性
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ enum SleepStatus : uint8_t {
|
|||||||
SLEEP_AWAKE = 0, // 清醒
|
SLEEP_AWAKE = 0, // 清醒
|
||||||
SLEEP_LIGHT = 1, // 浅睡
|
SLEEP_LIGHT = 1, // 浅睡
|
||||||
SLEEP_DEEP = 2, // 深睡
|
SLEEP_DEEP = 2, // 深睡
|
||||||
|
SLEEP_ABSENT = 3, // 离床/无人/无效
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -19,6 +19,10 @@
|
|||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
#include <DNSServer.h>
|
#include <DNSServer.h>
|
||||||
#include <LittleFS.h>
|
#include <LittleFS.h>
|
||||||
|
#include <BLEDevice.h>
|
||||||
|
#include <BLEServer.h>
|
||||||
|
#include <BLEUtils.h>
|
||||||
|
#include <BLE2902.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
@@ -29,9 +33,10 @@ struct DeviceConfig {
|
|||||||
char mqtt_user[20];
|
char mqtt_user[20];
|
||||||
char mqtt_pass[20];
|
char mqtt_pass[20];
|
||||||
char device_id[20];
|
char device_id[20];
|
||||||
char env_note[20]; // 环境备注
|
char env_note[20]; // 环境备注 (房间名)
|
||||||
char wifi_ssid[33]; // WiFi SSID (持久化)
|
char env_type[16]; // 环境类型 bedroom/bathroom/...
|
||||||
char wifi_pass[65]; // WiFi 密码 (持久化)
|
char wifi_ssid[33]; // WiFi SSID
|
||||||
|
char wifi_pass[65]; // WiFi 密码
|
||||||
};
|
};
|
||||||
|
|
||||||
class WiFiMgmt {
|
class WiFiMgmt {
|
||||||
@@ -50,6 +55,8 @@ public:
|
|||||||
const char* getDeviceId() const;
|
const char* getDeviceId() const;
|
||||||
const char* getEnvNote() const;
|
const char* getEnvNote() const;
|
||||||
void startConfigPortal();
|
void startConfigPortal();
|
||||||
|
void handleBLEProvision(const char* json); // BLE 配网回调
|
||||||
|
void enqueueBLEJson(const char* json); // BLE 线程安全入队 (仅暂存)
|
||||||
void resetSettings();
|
void resetSettings();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -70,6 +77,10 @@ private:
|
|||||||
void _updateWifiScan(); // WiFi 扫描缓存
|
void _updateWifiScan(); // WiFi 扫描缓存
|
||||||
String _htmlPage(); // 返回配网 HTML 页面
|
String _htmlPage(); // 返回配网 HTML 页面
|
||||||
|
|
||||||
|
// BLE 蓝牙配网
|
||||||
|
void _startBLE();
|
||||||
|
void _stopBLE();
|
||||||
|
|
||||||
WebServer* _server;
|
WebServer* _server;
|
||||||
DNSServer* _dns;
|
DNSServer* _dns;
|
||||||
DeviceConfig _config;
|
DeviceConfig _config;
|
||||||
@@ -91,6 +102,17 @@ private:
|
|||||||
// LED 独立任务
|
// LED 独立任务
|
||||||
TaskHandle_t _ledTaskHandle;
|
TaskHandle_t _ledTaskHandle;
|
||||||
volatile uint8_t _ledMode; // 0=灭 1=慢闪 2=快闪 3=常亮
|
volatile uint8_t _ledMode; // 0=灭 1=慢闪 2=快闪 3=常亮
|
||||||
|
|
||||||
|
// BLE
|
||||||
|
BLEServer* _bleServer;
|
||||||
|
BLECharacteristic* _bleInfoChar; // READ: 设备信息
|
||||||
|
BLECharacteristic* _bleChar; // WRITE+NOTIFY: 配网
|
||||||
|
BLEAdvertising* _bleAdv;
|
||||||
|
|
||||||
|
// BLE 回调保护: 不在 BTC_TASK 栈里做 Flash 写操作
|
||||||
|
String _blePendingJson; // 待处理的 BLE 配网 JSON
|
||||||
|
bool _blePendingFlag; // 有未处理的 BLE 数据
|
||||||
|
void _processBLEPending(); // 在 loop() 上下文处理
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WIFI_MANAGER_H
|
#endif // WIFI_MANAGER_H
|
||||||
|
|||||||
@@ -1,262 +0,0 @@
|
|||||||
/**
|
|
||||||
* wm_strings_zh.h
|
|
||||||
* 中文语言包 for WiFiManager
|
|
||||||
* 基于 wm_strings_en.h 翻译
|
|
||||||
*
|
|
||||||
* WiFiManager, a library for the ESP8266/Arduino platform
|
|
||||||
* for configuration of WiFi credentials using a Captive Portal
|
|
||||||
*
|
|
||||||
* @author Creator tzapu
|
|
||||||
* @author tablatronix
|
|
||||||
* @version 0.0.0
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _WM_STRINGS_ZH_H_
|
|
||||||
#define _WM_STRINGS_ZH_H_
|
|
||||||
|
|
||||||
// strings files must include a consts file!
|
|
||||||
#include "wm_consts_en.h" // include constants, tokens, routes
|
|
||||||
|
|
||||||
const char WM_LANGUAGE[] PROGMEM = "zh-CN"; // i18n lang code
|
|
||||||
|
|
||||||
const char HTTP_HEAD_START[] PROGMEM = "<!DOCTYPE html>"
|
|
||||||
"<html lang='zh-CN'><head>"
|
|
||||||
"<meta name='format-detection' content='telephone=no'>"
|
|
||||||
"<meta charset='UTF-8'>"
|
|
||||||
"<meta name='viewport' content='width=device-width,initial-scale=1,user-scalable=no'/>"
|
|
||||||
"<title>{v}</title>";
|
|
||||||
|
|
||||||
const char HTTP_SCRIPT[] PROGMEM = "<script>function c(l){"
|
|
||||||
"document.getElementById('s').value=l.getAttribute('data-ssid')||l.innerText||l.textContent;"
|
|
||||||
"p = l.nextElementSibling.classList.contains('l');"
|
|
||||||
"document.getElementById('p').disabled = !p;"
|
|
||||||
"if(p)document.getElementById('p').focus();};"
|
|
||||||
"function f() {var x = document.getElementById('p');x.type==='password'?x.type='text':x.type='password';}"
|
|
||||||
"</script>";
|
|
||||||
|
|
||||||
const char HTTP_HEAD_END[] PROGMEM = "</head><body class='{c}'><div class='wrap'>"; // {c} = _bodyclass
|
|
||||||
|
|
||||||
const char HTTP_ROOT_MAIN[] PROGMEM = "<h1>{t}</h1><h3>{v}</h3>";
|
|
||||||
|
|
||||||
const char * const HTTP_PORTAL_MENU[] PROGMEM = {
|
|
||||||
"<form action='/wifi' method='get'><button>配置 WiFi</button></form><br/>\n", // MENU_WIFI
|
|
||||||
"<form action='/0wifi' method='get'><button>配置 WiFi (不扫描)</button></form><br/>\n", // MENU_WIFINOSCAN
|
|
||||||
"<form action='/info' method='get'><button>系统信息</button></form><br/>\n", // MENU_INFO
|
|
||||||
"<form action='/param' method='get'><button>参数设置</button></form><br/>\n", // MENU_PARAM
|
|
||||||
"<form action='/close' method='get'><button>关闭页面</button></form><br/>\n", // MENU_CLOSE
|
|
||||||
"<form action='/restart' method='get'><button>重启设备</button></form><br/>\n", // MENU_RESTART
|
|
||||||
"<form action='/exit' method='get'><button>退出配网</button></form><br/>\n", // MENU_EXIT
|
|
||||||
"<form action='/erase' method='get'><button class='D'>清除配置</button></form><br/>\n", // MENU_ERASE
|
|
||||||
"<form action='/update' method='get'><button>固件升级</button></form><br/>\n", // MENU_UPDATE
|
|
||||||
"<hr><br/>" // MENU_SEP
|
|
||||||
};
|
|
||||||
|
|
||||||
const char HTTP_PORTAL_OPTIONS[] PROGMEM = "";
|
|
||||||
const char HTTP_ITEM_QI[] PROGMEM = "<div role='img' aria-label='{r}%' title='{r}%' class='q q-{q} {i} {h}'></div>";
|
|
||||||
const char HTTP_ITEM_QP[] PROGMEM = "<div class='q {h}'>{r}%</div>";
|
|
||||||
const char HTTP_ITEM[] PROGMEM = "<div><a href='#p' onclick='c(this)' data-ssid='{V}'>{v}</a>{qi}{qp}</div>";
|
|
||||||
|
|
||||||
const char HTTP_FORM_START[] PROGMEM = "<form method='POST' action='{v}'>";
|
|
||||||
const char HTTP_FORM_WIFI[] PROGMEM = "<label for='s'>WiFi 名称 (SSID)</label><input id='s' name='s' maxlength='32' autocorrect='off' autocapitalize='none' placeholder='{v}'><br/><label for='p'>WiFi 密码</label><input id='p' name='p' maxlength='64' type='password' placeholder='{p}'><input type='checkbox' id='showpass' onclick='f()'> <label for='showpass'>显示密码</label><br/>";
|
|
||||||
const char HTTP_FORM_WIFI_END[] PROGMEM = "";
|
|
||||||
const char HTTP_FORM_STATIC_HEAD[] PROGMEM = "<hr><br/>";
|
|
||||||
const char HTTP_FORM_END[] PROGMEM = "<br/><br/><button type='submit'>保存配置</button></form>";
|
|
||||||
const char HTTP_FORM_LABEL[] PROGMEM = "<label for='{i}'>{t}</label>";
|
|
||||||
const char HTTP_FORM_PARAM_HEAD[] PROGMEM = "<hr><br/>";
|
|
||||||
const char HTTP_FORM_PARAM[] PROGMEM = "<br/><input id='{i}' name='{n}' maxlength='{l}' value='{v}' {c}>\n";
|
|
||||||
|
|
||||||
const char HTTP_SCAN_LINK[] PROGMEM = "<br/><form action='/wifi?refresh=1' method='POST'><button name='refresh' value='1'>重新扫描</button></form>";
|
|
||||||
const char HTTP_SAVED[] PROGMEM = "<div class='msg'>正在保存配置<br/>尝试连接 WiFi...<br/>如果连接失败,请重新连接 AP 再试一次</div>";
|
|
||||||
const char HTTP_PARAMSAVED[] PROGMEM = "<div class='msg S'>配置已保存<br/></div>";
|
|
||||||
const char HTTP_END[] PROGMEM = "</div></body></html>";
|
|
||||||
const char HTTP_ERASEBTN[] PROGMEM = "<br/><form action='/erase' method='get'><button class='D'>清除 WiFi 配置</button></form>";
|
|
||||||
const char HTTP_UPDATEBTN[] PROGMEM = "<br/><form action='/update' method='get'><button>固件升级</button></form>";
|
|
||||||
const char HTTP_BACKBTN[] PROGMEM = "<hr><br/><form action='/' method='get'><button>返回首页</button></form>";
|
|
||||||
|
|
||||||
const char HTTP_STATUS_ON[] PROGMEM = "<div class='msg S'><strong>已连接</strong> {v}<br/><em><small>IP 地址: {i}</small></em></div>";
|
|
||||||
const char HTTP_STATUS_OFF[] PROGMEM = "<div class='msg {c}'><strong>未连接</strong> {v}{r}</div>";
|
|
||||||
const char HTTP_STATUS_OFFPW[] PROGMEM = "<br/>WiFi 密码错误";
|
|
||||||
const char HTTP_STATUS_OFFNOAP[] PROGMEM = "<br/>未找到该 WiFi";
|
|
||||||
const char HTTP_STATUS_OFFFAIL[] PROGMEM = "<br/>无法连接";
|
|
||||||
const char HTTP_STATUS_NONE[] PROGMEM = "<div class='msg'>未设置 WiFi</div>";
|
|
||||||
const char HTTP_BR[] PROGMEM = "<br/>";
|
|
||||||
|
|
||||||
const char HTTP_STYLE[] PROGMEM = "<style>"
|
|
||||||
".c,body{text-align:center;font-family:'PingFang SC','Microsoft YaHei','Helvetica Neue',sans-serif}div,input,select{padding:5px;font-size:1em;margin:5px 0;box-sizing:border-box}"
|
|
||||||
"input,button,select,.msg{border-radius:.3rem;width: 100%}input[type=radio],input[type=checkbox]{width:auto}"
|
|
||||||
"button,input[type='button'],input[type='submit']{cursor:pointer;border:0;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%}"
|
|
||||||
"input[type='file']{border:1px solid #1fa3ec}"
|
|
||||||
".wrap {text-align:left;display:inline-block;min-width:260px;max-width:500px}"
|
|
||||||
"a{color:#000;font-weight:700;text-decoration:none}a:hover{color:#1fa3ec;text-decoration:underline}"
|
|
||||||
".q{height:16px;margin:0;padding:0 5px;text-align:right;min-width:38px;float:right}.q.q-0:after{background-position-x:0}.q.q-1:after{background-position-x:-16px}.q.q-2:after{background-position-x:-32px}.q.q-3:after{background-position-x:-48px}.q.q-4:after{background-position-x:-64px}.q.l:before{background-position-x:-80px;padding-right:5px}.ql .q{float:left}.q:after,.q:before{content:'';width:16px;height:16px;display:inline-block;background-repeat:no-repeat;background-position: 16px 0;"
|
|
||||||
"background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAQCAMAAADeZIrLAAAAJFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHJj5lAAAAC3RSTlMAIjN3iJmqu8zd7vF8pzcAAABsSURBVHja7Y1BCsAwCASNSVo3/v+/BUEiXnIoXkoX5jAQMxTHzK9cVSnvDxwD8bFx8PhZ9q8FmghXBhqA1faxk92PsxvRc2CCCFdhQCbRkLoAQ3q/wWUBqG35ZxtVzW4Ed6LngPyBU2CobdIDQ5oPWI5nCUwAAAAASUVORK5CYII=');}"
|
|
||||||
"@media (-webkit-min-device-pixel-ratio: 2),(min-resolution: 192dpi){.q:before,.q:after {"
|
|
||||||
"background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALwAAAAgCAMAAACfM+KhAAAALVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOrOgAAAADnRSTlMAESIzRGZ3iJmqu8zd7gKjCLQAAACmSURBVHgB7dDBCoMwEEXRmKlVY3L//3NLhyzqIqSUggy8uxnhCR5Mo8xLt+14aZ7wwgsvvPA/ofv9+44334UXXngvb6XsFhO/VoC2RsSv9J7x8BnYLW+AjT56ud/uePMdb7IP8Bsc/e7h8Cfk912ghsNXWPpDC4hvN+D1560A1QPORyh84VKLjjdvfPFm++i9EWq0348XXnjhhT+4dIbCW+WjZim9AKk4UZMnnCEuAAAAAElFTkSuQmCC');"
|
|
||||||
"background-size: 95px 16px;}}"
|
|
||||||
".msg{padding:20px;margin:20px 0;border:1px solid #eee;border-left-width:5px;border-left-color:#777}.msg h4{margin-top:0;margin-bottom:5px}.msg.P{border-left-color:#1fa3ec}.msg.P h4{color:#1fa3ec}.msg.D{border-left-color:#dc3630}.msg.D h4{color:#dc3630}.msg.S{border-left-color: #5cb85c}.msg.S h4{color: #5cb85c}"
|
|
||||||
"dt{font-weight:bold}dd{margin:0;padding:0 0 0.5em 0;min-height:12px}"
|
|
||||||
"td{vertical-align: top;}"
|
|
||||||
".h{display:none}"
|
|
||||||
"button{transition: 0s opacity;transition-delay: 3s;transition-duration: 0s;cursor: pointer}"
|
|
||||||
"button.D{background-color:#dc3630}"
|
|
||||||
"button:active{opacity:50% !important;cursor:wait;transition-delay: 0s}"
|
|
||||||
"body.invert,body.invert a,body.invert h1 {background-color:#060606;color:#fff;}"
|
|
||||||
"body.invert .msg{color:#fff;background-color:#282828;border-top:1px solid #555;border-right:1px solid #555;border-bottom:1px solid #555;}"
|
|
||||||
"body.invert .q[role=img]{-webkit-filter:invert(1);filter:invert(1);}"
|
|
||||||
":disabled {opacity: 0.5;}"
|
|
||||||
"</style>";
|
|
||||||
|
|
||||||
#ifndef WM_NOHELP
|
|
||||||
const char HTTP_HELP[] PROGMEM =
|
|
||||||
"<br/><h3>可用页面</h3><hr>"
|
|
||||||
"<table class='table'>"
|
|
||||||
"<thead><tr><th>页面</th><th>功能</th></tr></thead><tbody>"
|
|
||||||
"<tr><td><a href='/'>/</a></td>"
|
|
||||||
"<td>主菜单页面</td></tr>"
|
|
||||||
"<tr><td><a href='/wifi'>/wifi</a></td>"
|
|
||||||
"<td>显示 WiFi 扫描结果并配置连接 (/0wifi 不扫描)</td></tr>"
|
|
||||||
"<tr><td><a href='/wifisave'>/wifisave</a></td>"
|
|
||||||
"<td>保存 WiFi 配置并连接设备</td></tr>"
|
|
||||||
"<tr><td><a href='/param'>/param</a></td>"
|
|
||||||
"<td>参数设置页面</td></tr>"
|
|
||||||
"<tr><td><a href='/info'>/info</a></td>"
|
|
||||||
"<td>系统信息页面</td></tr>"
|
|
||||||
"<tr><td><a href='/u'>/u</a></td>"
|
|
||||||
"<td>固件 OTA 升级</td></tr>"
|
|
||||||
"<tr><td><a href='/close'>/close</a></td>"
|
|
||||||
"<td>关闭弹出窗口,配网服务保持运行</td></tr>"
|
|
||||||
"<tr><td>/exit</td>"
|
|
||||||
"<td>退出配网模式,配网服务将关闭</td></tr>"
|
|
||||||
"<tr><td>/restart</td>"
|
|
||||||
"<td>重启设备</td></tr>"
|
|
||||||
"<tr><td>/erase</td>"
|
|
||||||
"<td>清除 WiFi 配置并重启。清除后设备不会自动连接,需重新配网</td></tr>"
|
|
||||||
"</table>"
|
|
||||||
"<p/>GitHub <a href='https://github.com/tzapu/WiFiManager'>https://github.com/tzapu/WiFiManager</a>.";
|
|
||||||
#else
|
|
||||||
const char HTTP_HELP[] PROGMEM = "";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char HTTP_UPDATE[] PROGMEM = "上传新固件<br/><form method='POST' action='u' enctype='multipart/form-data' onchange=\"(function(el){document.getElementById('uploadbin').style.display = el.value=='' ? 'none' : 'initial';})(this)\"><input type='file' name='update' accept='.bin,application/octet-stream'><button id='uploadbin' type='submit' class='h D'>开始升级</button></form><small><a href='http://192.168.4.1/update' target='_blank'>* 如果在配网页面内无法使用,请在浏览器中打开 http://192.168.4.1</a><small>";
|
|
||||||
const char HTTP_UPDATE_FAIL[] PROGMEM = "<div class='msg D'><strong>升级失败!</strong><Br/>请重启设备后重试</div>";
|
|
||||||
const char HTTP_UPDATE_SUCCESS[] PROGMEM = "<div class='msg S'><strong>升级成功!</strong><Br/>设备正在重启...</div>";
|
|
||||||
|
|
||||||
#ifdef WM_JSTEST
|
|
||||||
const char HTTP_JS[] PROGMEM =
|
|
||||||
"<script>function postAjax(url, data, success) {"
|
|
||||||
" var params = typeof data == 'string' ? data : Object.keys(data).map("
|
|
||||||
" function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) }"
|
|
||||||
" ).join('&');"
|
|
||||||
" var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject(\"Microsoft.XMLHTTP\");"
|
|
||||||
" xhr.open('POST', url);"
|
|
||||||
" xhr.onreadystatechange = function() {"
|
|
||||||
" if (xhr.readyState>3 && xhr.status==200) { success(xhr.responseText); }"
|
|
||||||
" };"
|
|
||||||
" xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');"
|
|
||||||
" xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');"
|
|
||||||
" xhr.send(params);"
|
|
||||||
" return xhr;}"
|
|
||||||
"postAjax('/status', 'p1=1&p2=Hello+World', function(data){ console.log(data); });"
|
|
||||||
"postAjax('/status', { p1: 1, p2: 'Hello World' }, function(data){ console.log(data); });"
|
|
||||||
"</script>";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Info html
|
|
||||||
#ifdef ESP32
|
|
||||||
const char HTTP_INFO_esphead[] PROGMEM = "<h3>ESP32 信息</h3><hr><dl>";
|
|
||||||
const char HTTP_INFO_chiprev[] PROGMEM = "<dt>芯片版本</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_lastreset[] PROGMEM = "<dt>上次复位原因</dt><dd>CPU0: {1}<br/>CPU1: {2}</dd>";
|
|
||||||
const char HTTP_INFO_aphost[] PROGMEM = "<dt>AP 主机名</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_psrsize[] PROGMEM = "<dt>PSRAM 大小</dt><dd>{1} 字节</dd>";
|
|
||||||
const char HTTP_INFO_temp[] PROGMEM = "<dt>芯片温度</dt><dd>{1}°C / {2}°F</dd>";
|
|
||||||
const char HTTP_INFO_hall[] PROGMEM = "<dt>霍尔传感器</dt><dd>{1}</dd>";
|
|
||||||
#else
|
|
||||||
const char HTTP_INFO_esphead[] PROGMEM = "<h3>ESP8266 信息</h3><hr><dl>";
|
|
||||||
const char HTTP_INFO_fchipid[] PROGMEM = "<dt>Flash 芯片 ID</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_corever[] PROGMEM = "<dt>Core 版本</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_bootver[] PROGMEM = "<dt>Boot 版本</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_lastreset[] PROGMEM = "<dt>上次复位原因</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_flashsize[] PROGMEM = "<dt>实际 Flash 大小</dt><dd>{1} 字节</dd>";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char HTTP_INFO_memsmeter[] PROGMEM = "<br/><progress value='{1}' max='{2}'></progress></dd>";
|
|
||||||
const char HTTP_INFO_memsketch[] PROGMEM = "<dt>内存 - 程序大小</dt><dd>已用 / 总计<br/>{1} / {2} 字节";
|
|
||||||
const char HTTP_INFO_freeheap[] PROGMEM = "<dt>内存 - 可用堆</dt><dd>{1} 字节</dd>";
|
|
||||||
const char HTTP_INFO_wifihead[] PROGMEM = "<br/><h3>WiFi 信息</h3><hr>";
|
|
||||||
const char HTTP_INFO_uptime[] PROGMEM = "<dt>运行时间</dt><dd>{1} 分 {2} 秒</dd>";
|
|
||||||
const char HTTP_INFO_chipid[] PROGMEM = "<dt>芯片 ID</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_idesize[] PROGMEM = "<dt>Flash 大小</dt><dd>{1} 字节</dd>";
|
|
||||||
const char HTTP_INFO_sdkver[] PROGMEM = "<dt>SDK 版本</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_cpufreq[] PROGMEM = "<dt>CPU 频率</dt><dd>{1}MHz</dd>";
|
|
||||||
const char HTTP_INFO_apip[] PROGMEM = "<dt>AP IP 地址</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_apmac[] PROGMEM = "<dt>AP MAC 地址</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_apssid[] PROGMEM = "<dt>AP SSID</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_apbssid[] PROGMEM = "<dt>BSSID</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_stassid[] PROGMEM = "<dt>Station SSID</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_staip[] PROGMEM = "<dt>Station IP</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_stagw[] PROGMEM = "<dt>网关地址</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_stasub[] PROGMEM = "<dt>子网掩码</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_dnss[] PROGMEM = "<dt>DNS 服务器</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_host[] PROGMEM = "<dt>主机名</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_stamac[] PROGMEM = "<dt>Station MAC</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_conx[] PROGMEM = "<dt>连接状态</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_autoconx[] PROGMEM = "<dt>自动连接</dt><dd>{1}</dd>";
|
|
||||||
|
|
||||||
const char HTTP_INFO_aboutver[] PROGMEM = "<dt>WiFiManager 版本</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_aboutarduino[] PROGMEM = "<dt>Arduino 版本</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_aboutsdk[] PROGMEM = "<dt>ESP-SDK/IDF 版本</dt><dd>{1}</dd>";
|
|
||||||
const char HTTP_INFO_aboutdate[] PROGMEM = "<dt>构建日期</dt><dd>{1}</dd>";
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// 文本常量
|
|
||||||
// ============================================================
|
|
||||||
const char S_brand[] PROGMEM = "健康监测配网";
|
|
||||||
const char S_debugPrefix[] PROGMEM = "*wm:";
|
|
||||||
const char S_y[] PROGMEM = "是";
|
|
||||||
const char S_n[] PROGMEM = "否";
|
|
||||||
const char S_enable[] PROGMEM = "已启用";
|
|
||||||
const char S_disable[] PROGMEM = "已禁用";
|
|
||||||
const char S_GET[] PROGMEM = "GET";
|
|
||||||
const char S_POST[] PROGMEM = "POST";
|
|
||||||
const char S_NA[] PROGMEM = "未知";
|
|
||||||
const char S_passph[] PROGMEM = "********";
|
|
||||||
const char S_titlewifisaved[] PROGMEM = "WiFi 已保存";
|
|
||||||
const char S_titlewifisettings[] PROGMEM = "设置已保存";
|
|
||||||
const char S_titlewifi[] PROGMEM = "配置 WiFi";
|
|
||||||
const char S_titleinfo[] PROGMEM = "系统信息";
|
|
||||||
const char S_titleparam[] PROGMEM = "参数设置";
|
|
||||||
const char S_titleparamsaved[] PROGMEM = "设置已保存";
|
|
||||||
const char S_titleexit[] PROGMEM = "退出配网";
|
|
||||||
const char S_titlereset[] PROGMEM = "重置";
|
|
||||||
const char S_titleerase[] PROGMEM = "清除配置";
|
|
||||||
const char S_titleclose[] PROGMEM = "关闭页面";
|
|
||||||
const char S_options[] PROGMEM = "选项";
|
|
||||||
const char S_nonetworks[] PROGMEM = "未发现 WiFi 网络,请点击刷新重新扫描。";
|
|
||||||
const char S_staticip[] PROGMEM = "静态 IP";
|
|
||||||
const char S_staticgw[] PROGMEM = "静态网关";
|
|
||||||
const char S_staticdns[] PROGMEM = "静态 DNS";
|
|
||||||
const char S_subnet[] PROGMEM = "子网掩码";
|
|
||||||
const char S_exiting[] PROGMEM = "正在退出配网模式";
|
|
||||||
const char S_resetting[] PROGMEM = "设备将在几秒后重启";
|
|
||||||
const char S_closing[] PROGMEM = "可以关闭此页面,配网服务将继续运行";
|
|
||||||
const char S_error[] PROGMEM = "发生错误";
|
|
||||||
const char S_notfound[] PROGMEM = "页面未找到\n\n";
|
|
||||||
const char S_uri[] PROGMEM = "URI: ";
|
|
||||||
const char S_method[] PROGMEM = "\n请求方法: ";
|
|
||||||
const char S_args[] PROGMEM = "\n参数: ";
|
|
||||||
const char S_parampre[] PROGMEM = "param_";
|
|
||||||
|
|
||||||
// debug strings
|
|
||||||
const char D_HR[] PROGMEM = "--------------------";
|
|
||||||
|
|
||||||
// softap ssid default prefix
|
|
||||||
#ifdef ESP8266
|
|
||||||
const char S_ssidpre[] PROGMEM = "ESP";
|
|
||||||
#elif defined(ESP32)
|
|
||||||
const char S_ssidpre[] PROGMEM = "ESP32";
|
|
||||||
#else
|
|
||||||
const char S_ssidpre[] PROGMEM = "WM";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
82
src/main.cpp
82
src/main.cpp
@@ -222,11 +222,13 @@ TelemetryData buildTelemetry(const RadarRawData& radar) {
|
|||||||
memset(&t, 0, sizeof(t));
|
memset(&t, 0, sizeof(t));
|
||||||
|
|
||||||
// 设备标识
|
// 设备标识
|
||||||
strncpy(t.saleid, SALEID_DEFAULT, sizeof(t.saleid) - 1);
|
|
||||||
strncpy(t.gateid, g_mqtt.getGateId(), sizeof(t.gateid) - 1);
|
strncpy(t.gateid, g_mqtt.getGateId(), sizeof(t.gateid) - 1);
|
||||||
strncpy(t.meterId, METER_ID_DEFAULT, sizeof(t.meterId) - 1);
|
|
||||||
strncpy(t.meterName, METER_NAME_DEFAULT, sizeof(t.meterName) - 1);
|
strncpy(t.meterName, METER_NAME_DEFAULT, sizeof(t.meterName) - 1);
|
||||||
|
|
||||||
|
// 环境类型: 从配网配置读取 (默认 bedroom)
|
||||||
|
DeviceConfig cfg = g_wifi.getConfig();
|
||||||
|
strncpy(t.deviceType, cfg.env_type[0] ? cfg.env_type : "bedroom", sizeof(t.deviceType)-1);
|
||||||
|
|
||||||
// DHT11
|
// DHT11
|
||||||
t.temp = g_sensor.getTemp();
|
t.temp = g_sensor.getTemp();
|
||||||
t.humi = g_sensor.getHumi();
|
t.humi = g_sensor.getHumi();
|
||||||
@@ -240,6 +242,8 @@ TelemetryData buildTelemetry(const RadarRawData& radar) {
|
|||||||
t.heartRate = radar.heartRate;
|
t.heartRate = radar.heartRate;
|
||||||
t.breathRate = radar.breathRate;
|
t.breathRate = radar.breathRate;
|
||||||
t.body = radar.body;
|
t.body = radar.body;
|
||||||
|
t.sleepState = radar.sleepState;
|
||||||
|
t.sleepScore = radar.sleepScore;
|
||||||
t.radarValid = radar.radarValid;
|
t.radarValid = radar.radarValid;
|
||||||
t.vitalValid = radar.vitalValid;
|
t.vitalValid = radar.vitalValid;
|
||||||
|
|
||||||
@@ -271,11 +275,18 @@ void onLocalAlarmChange(uint8_t type, bool triggered, const char* desc) {
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
void checkLocalAlarms(const RadarRawData& radar) {
|
void checkLocalAlarms(const RadarRawData& radar) {
|
||||||
|
// 环境类型 → 报警开关
|
||||||
|
const char* env = g_wifi.getConfig().env_type;
|
||||||
|
bool enFall = (strcmp(env, "bathroom") == 0 || strcmp(env, "hallway") == 0 || strcmp(env, "livingroom") == 0);
|
||||||
|
bool enVital = (strcmp(env, "bedroom") == 0);
|
||||||
|
bool enWater = (strcmp(env, "bathroom") == 0);
|
||||||
|
bool enEnv = (strcmp(env, "bedroom") == 0 || strcmp(env, "balcony") == 0 || strcmp(env, "kitchen") == 0);
|
||||||
|
|
||||||
// ─── 前置条件: 有人才检测人体生命体征 ───
|
// ─── 前置条件: 有人才检测人体生命体征 ───
|
||||||
bool humanPresent = radar.presence && radar.radarValid;
|
bool humanPresent = radar.presence && radar.radarValid;
|
||||||
|
|
||||||
// ─── ★★★★★ 人身安全: 跌倒 (有人+30s+2s确认, 5s清除) ───
|
// ─── ★★★★★ 人身安全: 跌倒 (仅浴室/走廊/客厅) ───
|
||||||
if (radar.fall && humanPresent && !g_fallDismissed && millis() > 30000) {
|
if (enFall && radar.fall && humanPresent && !g_fallDismissed && millis() > 30000) {
|
||||||
if (!g_localFallActive) {
|
if (!g_localFallActive) {
|
||||||
// 持续检测中: 必须满 FALL_DETECT_MS 才报警
|
// 持续检测中: 必须满 FALL_DETECT_MS 才报警
|
||||||
if (g_fallDetectMs == 0) {
|
if (g_fallDetectMs == 0) {
|
||||||
@@ -311,9 +322,9 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── ★★★★★ 人身安全: 心率异常 (仅 ABD1, 防抖3次, 30秒后生效) ───
|
// ─── ★★★★★ 人身安全: 心率异常 (仅卧室+ABD1, 防抖3次, 30s) ───
|
||||||
#if RADAR_TYPE != RADAR_TYPE_AFD1
|
#if RADAR_TYPE != RADAR_TYPE_AFD1
|
||||||
if (millis() > 30000 && humanPresent && radar.vitalValid && radar.heartRate > 0) {
|
if (enVital && millis() > 30000 && humanPresent && radar.vitalValid && radar.heartRate > 0) {
|
||||||
bool heartAbn = (radar.heartRate < HEART_RATE_MIN || radar.heartRate > HEART_RATE_MAX);
|
bool heartAbn = (radar.heartRate < HEART_RATE_MIN || radar.heartRate > HEART_RATE_MAX);
|
||||||
if (heartAbn) {
|
if (heartAbn) {
|
||||||
if (++g_heartAbnCnt >= ALARM_HYSTERESIS && !g_localHeartAbnActive) {
|
if (++g_heartAbnCnt >= ALARM_HYSTERESIS && !g_localHeartAbnActive) {
|
||||||
@@ -336,9 +347,9 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
|||||||
}
|
}
|
||||||
#endif // RADAR_TYPE != AFD1
|
#endif // RADAR_TYPE != AFD1
|
||||||
|
|
||||||
// ─── ★★★★★ 人身安全: 呼吸异常 (仅 ABD1, 防抖3次, 30秒后生效) ───
|
// ─── ★★★★★ 人身安全: 呼吸异常 (仅卧室+ABD1, 防抖3次, 30秒后生效) ───
|
||||||
#if RADAR_TYPE != RADAR_TYPE_AFD1
|
#if RADAR_TYPE != RADAR_TYPE_AFD1
|
||||||
if (millis() > 30000 && humanPresent && radar.vitalValid && radar.breathRate > 0) {
|
if (enVital && millis() > 30000 && humanPresent && radar.vitalValid && radar.breathRate > 0) {
|
||||||
bool breathAbn = (radar.breathRate < BREATH_RATE_MIN || radar.breathRate > BREATH_RATE_MAX);
|
bool breathAbn = (radar.breathRate < BREATH_RATE_MIN || radar.breathRate > BREATH_RATE_MAX);
|
||||||
if (breathAbn) {
|
if (breathAbn) {
|
||||||
if (++g_breathAbnCnt >= ALARM_HYSTERESIS && !g_localBreathAbnActive) {
|
if (++g_breathAbnCnt >= ALARM_HYSTERESIS && !g_localBreathAbnActive) {
|
||||||
@@ -361,7 +372,8 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
|||||||
}
|
}
|
||||||
#endif // RADAR_TYPE != AFD1
|
#endif // RADAR_TYPE != AFD1
|
||||||
|
|
||||||
// ─── ★★★ 环境安全: 水浸 ───
|
// ─── ★★★ 环境安全: 水浸 (仅浴室) ───
|
||||||
|
if (enWater) {
|
||||||
bool waterLeak = !g_sensor.getRainDO() && g_sensor.isRainValid();
|
bool waterLeak = !g_sensor.getRainDO() && g_sensor.isRainValid();
|
||||||
if (waterLeak && !g_localWaterActive) {
|
if (waterLeak && !g_localWaterActive) {
|
||||||
g_localWaterActive = true;
|
g_localWaterActive = true;
|
||||||
@@ -370,9 +382,10 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
|||||||
g_localWaterActive = false;
|
g_localWaterActive = false;
|
||||||
g_alarm.clearLocal(AlarmManager::ALARM_WATER_LEAK);
|
g_alarm.clearLocal(AlarmManager::ALARM_WATER_LEAK);
|
||||||
}
|
}
|
||||||
|
} // enWater
|
||||||
|
|
||||||
// ─── ★★ 环境舒适: 温度异常 (防抖3次, 30秒启动静默) ───
|
// ─── ★★ 环境舒适: 温湿度异常 (仅卧室/阳台/厨房, 防抖3次, 30s) ───
|
||||||
if (millis() > 30000 && g_sensor.isDhtValid()) {
|
if (enEnv && millis() > 30000 && g_sensor.isDhtValid()) {
|
||||||
float temp = g_sensor.getTemp();
|
float temp = g_sensor.getTemp();
|
||||||
bool tempAbn = (temp < TEMP_LOW || temp > TEMP_HIGH);
|
bool tempAbn = (temp < TEMP_LOW || temp > TEMP_HIGH);
|
||||||
if (tempAbn) {
|
if (tempAbn) {
|
||||||
@@ -588,20 +601,22 @@ void loop() {
|
|||||||
static bool wasDisconnected = true;
|
static bool wasDisconnected = true;
|
||||||
if (g_mqtt.isConnected()) {
|
if (g_mqtt.isConnected()) {
|
||||||
if (wasDisconnected) {
|
if (wasDisconnected) {
|
||||||
// 刚恢复连接, 同步时间
|
|
||||||
syncTime();
|
syncTime();
|
||||||
wasDisconnected = false;
|
wasDisconnected = false;
|
||||||
}
|
}
|
||||||
// 配网成功后更新 MQTT 配置 (如果有改动) 并上报
|
|
||||||
if (g_wifi.justProvisioned()) {
|
|
||||||
DeviceConfig cfg = g_wifi.getConfig();
|
|
||||||
g_mqtt.setServer(cfg.mqtt_server, atoi(cfg.mqtt_port),
|
|
||||||
cfg.mqtt_user, cfg.mqtt_pass);
|
|
||||||
g_mqtt.publishProvisionStatus("success", "");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
wasDisconnected = true;
|
wasDisconnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 配网成功后: 先更新 MQTT 配置, 再强制重连
|
||||||
|
if (g_wifi.justProvisioned()) {
|
||||||
|
DeviceConfig cfg = g_wifi.getConfig();
|
||||||
|
g_mqtt.disconnect();
|
||||||
|
g_mqtt.setServer(cfg.mqtt_server, atoi(cfg.mqtt_port),
|
||||||
|
cfg.mqtt_user, cfg.mqtt_pass);
|
||||||
|
g_mqtt.connect();
|
||||||
|
g_mqtt.publishProvisionStatus("success", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 3. 传感器 (独立,任何传感器故障不影响其他) ---
|
// --- 3. 传感器 (独立,任何传感器故障不影响其他) ---
|
||||||
@@ -626,19 +641,42 @@ void loop() {
|
|||||||
// --- 5. 报警模块更新 (定时器/闪烁) ---
|
// --- 5. 报警模块更新 (定时器/闪烁) ---
|
||||||
g_alarm.loop();
|
g_alarm.loop();
|
||||||
|
|
||||||
// --- 6. 遥测上报 (1秒周期) ---
|
// --- 6. 遥测上报 ---
|
||||||
|
// 有人时: 每秒全量上报
|
||||||
|
// 无人时: 仅状态变化时发极简报文 + 60秒心跳 (省4G流量)
|
||||||
|
static bool lastPresence = false;
|
||||||
|
static uint32_t lastHeartbeat = 0; // 无人心跳计时
|
||||||
|
|
||||||
|
if (radar.presence) {
|
||||||
|
// ── 有人: 每秒完整上报 ──
|
||||||
if (now - g_lastReportTime >= REPORT_INTERVAL_MS) {
|
if (now - g_lastReportTime >= REPORT_INTERVAL_MS) {
|
||||||
g_lastReportTime = now;
|
g_lastReportTime = now;
|
||||||
|
|
||||||
TelemetryData tele = buildTelemetry(radar);
|
TelemetryData tele = buildTelemetry(radar);
|
||||||
g_mqtt.publishAllPoints(tele, g_sequence);
|
g_mqtt.publishAllPoints(tele, g_sequence);
|
||||||
g_sequence++;
|
g_sequence++;
|
||||||
|
lastHeartbeat = now; // 有人时重置心跳计时
|
||||||
|
|
||||||
// 调试输出 + OLED 显示
|
|
||||||
printDebug(tele);
|
printDebug(tele);
|
||||||
g_display.update(tele, wifiOk, g_alarm.isBuzzerOn(),
|
g_display.update(tele, wifiOk, g_alarm.isBuzzerOn(),
|
||||||
g_alarm.hasActiveAlarm(), g_alarm.getActiveAlarmStr());
|
g_alarm.hasActiveAlarm(), g_alarm.getActiveAlarmStr());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// ── 无人: 状态翻转发一次极简报文, 之后每60秒心跳 ──
|
||||||
|
if (lastPresence != radar.presence || now - lastHeartbeat >= PRESENCE_HEARTBEAT_MS) {
|
||||||
|
g_mqtt.publishPresenceOnly(radar.presence, radar.radarValid, g_sequence);
|
||||||
|
g_sequence++;
|
||||||
|
lastHeartbeat = now;
|
||||||
|
|
||||||
|
// 调试输出
|
||||||
|
Serial.printf("[上报] 无人极简报文 (Presence=0) 序号:%d\n", g_sequence - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// OLED 还是照常刷新 (显示无人状态)
|
||||||
|
TelemetryData tele = buildTelemetry(radar);
|
||||||
|
g_display.update(tele, wifiOk, g_alarm.isBuzzerOn(),
|
||||||
|
g_alarm.hasActiveAlarm(), g_alarm.getActiveAlarmStr());
|
||||||
|
}
|
||||||
|
lastPresence = radar.presence;
|
||||||
|
|
||||||
// --- 7. MQTT 配网状态 (WiFiManager 触发时) ---
|
// --- 7. MQTT 配网状态 (WiFiManager 触发时) ---
|
||||||
// WiFiManager 的 captive portal 启动/关闭时更新状态
|
// WiFiManager 的 captive portal 启动/关闭时更新状态
|
||||||
|
|||||||
@@ -178,20 +178,23 @@ void MQTTManager::publishAllPoints(const TelemetryData& d, uint32_t sequence) {
|
|||||||
snprintf(timeStr, sizeof(timeStr), "2026-01-01 00:00:00");
|
snprintf(timeStr, sizeof(timeStr), "2026-01-01 00:00:00");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建 JSON (协议规范 §4.1)
|
// 构建 JSON (协议规范 V0.08)
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc["saleid"] = d.saleid;
|
|
||||||
doc["gateid"] = d.gateid;
|
doc["gateid"] = d.gateid;
|
||||||
doc["type"] = "report";
|
doc["type"] = "report";
|
||||||
doc["time"] = timeStr;
|
doc["time"] = timeStr;
|
||||||
doc["sequence"] = String(sequence);
|
doc["sequence"] = String(sequence);
|
||||||
doc["source"] = "da";
|
doc["source"] = "da";
|
||||||
|
|
||||||
|
// meter.id = gateid + 后缀 (如 10100001001 → 10100001001001)
|
||||||
|
String meterId = String(d.gateid) + "001";
|
||||||
|
|
||||||
JsonArray meter = doc["meter"].to<JsonArray>();
|
JsonArray meter = doc["meter"].to<JsonArray>();
|
||||||
JsonObject m = meter.add<JsonObject>();
|
JsonObject m = meter.add<JsonObject>();
|
||||||
m["id"] = d.meterId;
|
m["id"] = meterId;
|
||||||
m["status"] = "1";
|
m["status"] = "1";
|
||||||
m["name"] = d.meterName;
|
m["name"] = d.meterName;
|
||||||
|
m["type"] = d.deviceType; // 设备类型枚举
|
||||||
|
|
||||||
JsonObject v = m["values"].to<JsonObject>();
|
JsonObject v = m["values"].to<JsonObject>();
|
||||||
// 环境数据
|
// 环境数据
|
||||||
@@ -205,6 +208,8 @@ void MQTTManager::publishAllPoints(const TelemetryData& d, uint32_t sequence) {
|
|||||||
v["Resident"] = d.resident ? "1" : "0";
|
v["Resident"] = d.resident ? "1" : "0";
|
||||||
// 生命体征
|
// 生命体征
|
||||||
v["Body"] = String(d.body);
|
v["Body"] = String(d.body);
|
||||||
|
v["SleepState"] = String(d.sleepState);
|
||||||
|
v["SleepScore"] = String(d.sleepScore);
|
||||||
v["HeartRate"] = String(d.heartRate);
|
v["HeartRate"] = String(d.heartRate);
|
||||||
v["BreathRate"] = String(d.breathRate);
|
v["BreathRate"] = String(d.breathRate);
|
||||||
v["RadarValid"] = d.radarValid ? "1" : "0";
|
v["RadarValid"] = d.radarValid ? "1" : "0";
|
||||||
@@ -416,6 +421,47 @@ void MQTTManager::publishLocalAlarm(uint8_t alarmType, bool triggered, const cha
|
|||||||
_mqtt.publish(topic.c_str(), payload.c_str());
|
_mqtt.publish(topic.c_str(), payload.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 上行: 无人极简报文 (省4G流量, 仅 Presence + RadarValid)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
void MQTTManager::publishPresenceOnly(bool presence, bool radarValid, uint32_t sequence) {
|
||||||
|
if (!isConnected()) return;
|
||||||
|
|
||||||
|
struct tm timeinfo;
|
||||||
|
char timeStr[24];
|
||||||
|
if (getLocalTime(&timeinfo)) {
|
||||||
|
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeinfo);
|
||||||
|
} else {
|
||||||
|
snprintf(timeStr, sizeof(timeStr), "2026-01-01 00:00:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 极简 JSON: ~120 字节 vs 完整报文 ~500 字节
|
||||||
|
JsonDocument doc;
|
||||||
|
doc["gateid"] = _gateid;
|
||||||
|
doc["type"] = "report";
|
||||||
|
doc["time"] = timeStr;
|
||||||
|
doc["sequence"] = String(sequence);
|
||||||
|
doc["source"] = "da";
|
||||||
|
|
||||||
|
String meterId = String(_gateid) + "001";
|
||||||
|
|
||||||
|
JsonArray meter = doc["meter"].to<JsonArray>();
|
||||||
|
JsonObject m = meter.add<JsonObject>();
|
||||||
|
m["id"] = meterId;
|
||||||
|
m["status"] = "1";
|
||||||
|
m["name"] = METER_NAME_DEFAULT;
|
||||||
|
|
||||||
|
JsonObject v = m["values"].to<JsonObject>();
|
||||||
|
v["Presence"] = presence ? "1" : "0";
|
||||||
|
v["RadarValid"] = radarValid ? "1" : "0";
|
||||||
|
|
||||||
|
String payload;
|
||||||
|
serializeJson(doc, payload);
|
||||||
|
|
||||||
|
_mqtt.publish("report/allpoints", payload.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 回调注册
|
// 回调注册
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -379,16 +379,15 @@ void RadarManager::_extractSleep(const RadarFrame& frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (frame.data_length >= 3) {
|
if (frame.data_length >= 3) {
|
||||||
// data[0]: 入床/离床
|
_data.sleepState = frame.data[1]; // 0=清醒 1=浅睡 2=深睡
|
||||||
// data[1]: 睡眠状态
|
_data.sleepScore = frame.data[2]; // 0~100
|
||||||
// data[2]: 评分
|
_data.lastUpdate = millis();
|
||||||
|
_notifyUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
// 跌倒检测: 可能在睡眠异常标志中
|
|
||||||
if (frame.data_length >= 4) {
|
if (frame.data_length >= 4) {
|
||||||
_data.fall = (frame.data[3] & 0x01) != 0;
|
_data.fall = (frame.data[3] & 0x01) != 0;
|
||||||
_data.resident = (frame.data[3] & 0x02) != 0;
|
_data.resident = (frame.data[3] & 0x02) != 0;
|
||||||
}
|
|
||||||
|
|
||||||
_data.lastUpdate = millis();
|
_data.lastUpdate = millis();
|
||||||
_notifyUpdate();
|
_notifyUpdate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,18 @@
|
|||||||
|
|
||||||
#include "wifi_manager.h"
|
#include "wifi_manager.h"
|
||||||
|
|
||||||
|
// BLE 配网回调: 小程序写入 JSON → 仅在 BLE 栈中暂存, 不直接处理
|
||||||
|
class BLEProvisionCB : public BLECharacteristicCallbacks {
|
||||||
|
void onWrite(BLECharacteristic* ch) override {
|
||||||
|
std::string val = ch->getValue();
|
||||||
|
if (val.length() > 0 && WiFiMgmt::_instance) {
|
||||||
|
Serial.printf("[BLE] 收到配网数据 (%d 字节)\n", val.length());
|
||||||
|
// 仅暂存 → 在 loop() 里处理 (BTC_TASK 栈太小, 写 Flash 会栈溢出)
|
||||||
|
WiFiMgmt::_instance->enqueueBLEJson(val.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
WiFiMgmt* WiFiMgmt::_instance = nullptr;
|
WiFiMgmt* WiFiMgmt::_instance = nullptr;
|
||||||
|
|
||||||
WiFiMgmt::WiFiMgmt()
|
WiFiMgmt::WiFiMgmt()
|
||||||
@@ -16,6 +28,8 @@ WiFiMgmt::WiFiMgmt()
|
|||||||
, _lastScanTime(0)
|
, _lastScanTime(0)
|
||||||
, _provisionSuccess(false)
|
, _provisionSuccess(false)
|
||||||
, _ledTaskHandle(nullptr), _ledMode(0)
|
, _ledTaskHandle(nullptr), _ledMode(0)
|
||||||
|
, _bleServer(nullptr), _bleInfoChar(nullptr), _bleChar(nullptr), _bleAdv(nullptr)
|
||||||
|
, _blePendingFlag(false)
|
||||||
{
|
{
|
||||||
memset(&_config, 0, sizeof(_config));
|
memset(&_config, 0, sizeof(_config));
|
||||||
_instance = this;
|
_instance = this;
|
||||||
@@ -55,6 +69,7 @@ bool WiFiMgmt::begin() {
|
|||||||
strncpy(_config.mqtt_pass, MQTT_DEFAULT_PASS, sizeof(_config.mqtt_pass)-1);
|
strncpy(_config.mqtt_pass, MQTT_DEFAULT_PASS, sizeof(_config.mqtt_pass)-1);
|
||||||
strncpy(_config.device_id, MQTT_DEFAULT_DEVICE, sizeof(_config.device_id)-1);
|
strncpy(_config.device_id, MQTT_DEFAULT_DEVICE, sizeof(_config.device_id)-1);
|
||||||
strncpy(_config.env_note, MQTT_DEFAULT_ENV, sizeof(_config.env_note)-1);
|
strncpy(_config.env_note, MQTT_DEFAULT_ENV, sizeof(_config.env_note)-1);
|
||||||
|
strncpy(_config.env_type, "bedroom", sizeof(_config.env_type)-1);
|
||||||
memset(_config.wifi_ssid, 0, sizeof(_config.wifi_ssid));
|
memset(_config.wifi_ssid, 0, sizeof(_config.wifi_ssid));
|
||||||
memset(_config.wifi_pass, 0, sizeof(_config.wifi_pass));
|
memset(_config.wifi_pass, 0, sizeof(_config.wifi_pass));
|
||||||
}
|
}
|
||||||
@@ -88,26 +103,34 @@ bool WiFiMgmt::begin() {
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
bool WiFiMgmt::loop() {
|
bool WiFiMgmt::loop() {
|
||||||
// --- Portal 模式 ---
|
// --- BLE 待处理数据 (从 loop 上下文安全处理, 不占 BTC_TASK 栈) ---
|
||||||
if (_portalActive) {
|
_processBLEPending();
|
||||||
|
|
||||||
|
// --- 配网完成 → WiFi 连接 (Portal 内/外 统一处理) ---
|
||||||
if (_portalStopFlag) {
|
if (_portalStopFlag) {
|
||||||
|
if (_portalActive) {
|
||||||
_stopPortal();
|
_stopPortal();
|
||||||
|
}
|
||||||
_portalStopFlag = false;
|
_portalStopFlag = false;
|
||||||
if (_pendingSSID.length() > 0) {
|
if (_pendingSSID.length() > 0) {
|
||||||
Serial.printf("[WiFi] 尝试连接: %s\n", _pendingSSID.c_str());
|
Serial.printf("[WiFi] 配网连接: %s\n", _pendingSSID.c_str());
|
||||||
_connected = _tryConnect(_pendingSSID.c_str(), _pendingPass.c_str());
|
_connected = _tryConnect(_pendingSSID.c_str(), _pendingPass.c_str());
|
||||||
_pendingSSID = ""; _pendingPass = "";
|
_pendingSSID = ""; _pendingPass = "";
|
||||||
if (_connected) {
|
if (_connected) {
|
||||||
_setLEDMode(3);
|
_setLEDMode(3);
|
||||||
_provisionSuccess = true; // 标记配网成功
|
_provisionSuccess = true; // 标记配网成功 → main 里触发 MQTT 重连
|
||||||
} else {
|
} else {
|
||||||
_setLEDMode(2);
|
_setLEDMode(2);
|
||||||
_startPortal();
|
if (!_portalActive) {
|
||||||
|
_startPortal(); // 连接失败 → 开 AP 重试
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _connected;
|
return _connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Portal 模式 ---
|
||||||
|
if (_portalActive) {
|
||||||
_dns->processNextRequest();
|
_dns->processNextRequest();
|
||||||
_server->handleClient();
|
_server->handleClient();
|
||||||
delay(10);
|
delay(10);
|
||||||
@@ -173,7 +196,11 @@ bool WiFiMgmt::_connectWiFi() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WiFiMgmt::_tryConnect(const char* ssid, const char* pass) {
|
bool WiFiMgmt::_tryConnect(const char* ssid, const char* pass) {
|
||||||
|
// ★ 先从 AP 模式彻底断开再切 STA,和 _connectWiFi() 保持一致
|
||||||
|
WiFi.disconnect(true);
|
||||||
|
delay(200);
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
|
delay(100);
|
||||||
WiFi.persistent(true); // 确保持久化 WiFi 密码到 NVS (断电不丢)
|
WiFi.persistent(true); // 确保持久化 WiFi 密码到 NVS (断电不丢)
|
||||||
WiFi.begin(ssid, pass);
|
WiFi.begin(ssid, pass);
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
@@ -198,7 +225,6 @@ void WiFiMgmt::_startPortal() {
|
|||||||
if (_portalActive) return;
|
if (_portalActive) return;
|
||||||
|
|
||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
WiFi.mode(WIFI_OFF);
|
|
||||||
delay(200);
|
delay(200);
|
||||||
WiFi.mode(WIFI_AP);
|
WiFi.mode(WIFI_AP);
|
||||||
WiFi.softAPConfig(IPAddress(192,168,4,1), IPAddress(192,168,4,1), IPAddress(255,255,255,0));
|
WiFi.softAPConfig(IPAddress(192,168,4,1), IPAddress(192,168,4,1), IPAddress(255,255,255,0));
|
||||||
@@ -220,10 +246,13 @@ void WiFiMgmt::_startPortal() {
|
|||||||
_portalStartTime = millis();
|
_portalStartTime = millis();
|
||||||
|
|
||||||
Serial.println(("[WiFi] 手机连 AP 后浏览器打开 http://192.168.4.1"));
|
Serial.println(("[WiFi] 手机连 AP 后浏览器打开 http://192.168.4.1"));
|
||||||
|
|
||||||
|
_startBLE(); // 同时启动 BLE 配网广播
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiMgmt::_stopPortal() {
|
void WiFiMgmt::_stopPortal() {
|
||||||
if (!_portalActive) return;
|
if (!_portalActive) return;
|
||||||
|
_stopBLE();
|
||||||
if (_server) { _server->stop(); delete _server; _server = nullptr; }
|
if (_server) { _server->stop(); delete _server; _server = nullptr; }
|
||||||
if (_dns) { _dns->stop(); delete _dns; _dns = nullptr; }
|
if (_dns) { _dns->stop(); delete _dns; _dns = nullptr; }
|
||||||
WiFi.softAPdisconnect(true);
|
WiFi.softAPdisconnect(true);
|
||||||
@@ -246,6 +275,7 @@ void WiFiMgmt::_handleSave() {
|
|||||||
strncpy(_config.wifi_ssid, _pendingSSID.c_str(), sizeof(_config.wifi_ssid)-1);
|
strncpy(_config.wifi_ssid, _pendingSSID.c_str(), sizeof(_config.wifi_ssid)-1);
|
||||||
strncpy(_config.wifi_pass, _pendingPass.c_str(), sizeof(_config.wifi_pass)-1);
|
strncpy(_config.wifi_pass, _pendingPass.c_str(), sizeof(_config.wifi_pass)-1);
|
||||||
if (_server->hasArg("device_id")) strncpy(_config.device_id, _server->arg("device_id").c_str(), sizeof(_config.device_id)-1);
|
if (_server->hasArg("device_id")) strncpy(_config.device_id, _server->arg("device_id").c_str(), sizeof(_config.device_id)-1);
|
||||||
|
if (_server->hasArg("env_type")) strncpy(_config.env_type, _server->arg("env_type").c_str(), sizeof(_config.env_type)-1);
|
||||||
if (_server->hasArg("env_note")) strncpy(_config.env_note, _server->arg("env_note").c_str(), sizeof(_config.env_note)-1);
|
if (_server->hasArg("env_note")) strncpy(_config.env_note, _server->arg("env_note").c_str(), sizeof(_config.env_note)-1);
|
||||||
if (_server->hasArg("mqtt_server")) strncpy(_config.mqtt_server, _server->arg("mqtt_server").c_str(), sizeof(_config.mqtt_server)-1);
|
if (_server->hasArg("mqtt_server")) strncpy(_config.mqtt_server, _server->arg("mqtt_server").c_str(), sizeof(_config.mqtt_server)-1);
|
||||||
if (_server->hasArg("mqtt_port")) strncpy(_config.mqtt_port, _server->arg("mqtt_port").c_str(), sizeof(_config.mqtt_port)-1);
|
if (_server->hasArg("mqtt_port")) strncpy(_config.mqtt_port, _server->arg("mqtt_port").c_str(), sizeof(_config.mqtt_port)-1);
|
||||||
@@ -342,7 +372,21 @@ String WiFiMgmt::_htmlPage() {
|
|||||||
html += "<div class='field'><label>设备编号</label><div class='iwrap'><span class='iicon'>#</span><input type='text' name='device_id' value='";
|
html += "<div class='field'><label>设备编号</label><div class='iwrap'><span class='iicon'>#</span><input type='text' name='device_id' value='";
|
||||||
html += _config.device_id;
|
html += _config.device_id;
|
||||||
html += "'></div></div>";
|
html += "'></div></div>";
|
||||||
html += "<div class='field'><label>安装环境</label><div class='iwrap'><span class='iicon'>🏠</span><input type='text' name='env_note' placeholder='如: 主卧 / 客厅 / 老人房' value='";
|
html += "<div class='field'><label>环境类型</label><div class='iwrap'><span class='iicon'>🏷️</span><select name='env_type'>";
|
||||||
|
const char* envTypes[] = {"bedroom","livingroom","bathroom","hallway","balcony","kitchen"};
|
||||||
|
const char* envLabels[] = {"🛏️ 卧室","🛋️ 客厅","🛁 浴室/卫生间","🚶 走廊","🌿 阳台","🍳 厨房"};
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
html += "<option value='";
|
||||||
|
html += envTypes[i];
|
||||||
|
html += "'";
|
||||||
|
if (strcmp(_config.env_type, envTypes[i]) == 0 || (strlen(_config.env_type) == 0 && i == 0))
|
||||||
|
html += " selected";
|
||||||
|
html += ">";
|
||||||
|
html += envLabels[i];
|
||||||
|
html += "</option>";
|
||||||
|
}
|
||||||
|
html += "</select></div></div>";
|
||||||
|
html += "<div class='field'><label>位置备注</label><div class='iwrap'><span class='iicon'>🏠</span><input type='text' name='env_note' placeholder='如: 主卧 / 客厅 / 老人房' value='";
|
||||||
html += _config.env_note;
|
html += _config.env_note;
|
||||||
html += "'></div></div></div>";
|
html += "'></div></div></div>";
|
||||||
|
|
||||||
@@ -363,6 +407,145 @@ String WiFiMgmt::_htmlPage() {
|
|||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// BLE 蓝牙配网
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
void WiFiMgmt::_startBLE() {
|
||||||
|
// 如果 BLE 栈已在运行, 仅重启广播 (避免 deinit→init 失败)
|
||||||
|
if (_bleServer != nullptr) {
|
||||||
|
if (_bleAdv) {
|
||||||
|
// 重设广告数据 (stop 后 start 需要重新配置)
|
||||||
|
BLEAdvertisementData advData;
|
||||||
|
advData.setCompleteServices(BLEUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b"));
|
||||||
|
advData.setShortName("HealthMon");
|
||||||
|
_bleAdv->setAdvertisementData(advData);
|
||||||
|
_bleAdv->setScanResponse(false);
|
||||||
|
_bleAdv->start();
|
||||||
|
}
|
||||||
|
Serial.println("[BLE] ✅ 广播已重开");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLEDevice::init("HealthMonitor");
|
||||||
|
_bleServer = BLEDevice::createServer();
|
||||||
|
|
||||||
|
BLEService* svc = _bleServer->createService("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
|
||||||
|
|
||||||
|
// 特征1: 设备信息 (READ) — 小程序连接后读取设备编号等
|
||||||
|
_bleInfoChar = svc->createCharacteristic(
|
||||||
|
"4fafc202-1fb5-459e-8fcc-c5c9c331914b",
|
||||||
|
BLECharacteristic::PROPERTY_READ
|
||||||
|
);
|
||||||
|
// 设备信息 JSON (最多 512 字节)
|
||||||
|
JsonDocument info;
|
||||||
|
info["device_id"] = _config.device_id;
|
||||||
|
info["mqtt_server"] = _config.mqtt_server;
|
||||||
|
info["mqtt_port"] = _config.mqtt_port;
|
||||||
|
info["fw_version"] = FW_VERSION;
|
||||||
|
String infoJson;
|
||||||
|
serializeJson(info, infoJson);
|
||||||
|
_bleInfoChar->setValue(infoJson.c_str());
|
||||||
|
|
||||||
|
// 特征2: 配网写入 (WRITE + NOTIFY) — 小程序发配网数据, 设备回复
|
||||||
|
_bleChar = svc->createCharacteristic(
|
||||||
|
"4fafc203-1fb5-459e-8fcc-c5c9c331914b",
|
||||||
|
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY
|
||||||
|
);
|
||||||
|
_bleChar->setCallbacks(new BLEProvisionCB());
|
||||||
|
_bleChar->addDescriptor(new BLE2902()); // 启用 notify
|
||||||
|
_bleChar->setValue(""); // 初始为空
|
||||||
|
|
||||||
|
svc->start();
|
||||||
|
|
||||||
|
_bleAdv = _bleServer->getAdvertising();
|
||||||
|
BLEAdvertisementData advData;
|
||||||
|
advData.setCompleteServices(BLEUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b"));
|
||||||
|
advData.setShortName("HealthMon");
|
||||||
|
_bleAdv->setAdvertisementData(advData);
|
||||||
|
_bleAdv->setScanResponse(false); // 不需要 scan response, 全在主包
|
||||||
|
_bleAdv->start();
|
||||||
|
|
||||||
|
Serial.printf("[BLE] ✅ 配网广播: HealthMonitor device_id=%s\n", _config.device_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiFiMgmt::_stopBLE() {
|
||||||
|
if (!_bleServer) return;
|
||||||
|
|
||||||
|
// ★ 核心修复: 先断开所有 BLE 客户端连接,
|
||||||
|
// 否则手机端缓存连接状态, 下次扫描不到设备
|
||||||
|
size_t connCount = _bleServer->getConnectedCount();
|
||||||
|
if (connCount > 0) {
|
||||||
|
Serial.printf("[BLE] 断开 %d 个已连接客户端\n", connCount);
|
||||||
|
for (size_t i = 0; i < connCount; i++) {
|
||||||
|
_bleServer->disconnect(i);
|
||||||
|
}
|
||||||
|
delay(300); // 等待 BLE 协议栈完成断开流程
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_bleAdv) { _bleAdv->stop(); }
|
||||||
|
Serial.println("[BLE] 广播已暂停");
|
||||||
|
}
|
||||||
|
|
||||||
|
// BLE 线程安全入队 (仅暂存, 不在 BTC_TASK 回调里处理)
|
||||||
|
void WiFiMgmt::enqueueBLEJson(const char* json) {
|
||||||
|
_blePendingJson = json;
|
||||||
|
_blePendingFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在 loop() 上下文中处理 BLE 配网数据 (安全 — 不在 BTC_TASK 栈中)
|
||||||
|
void WiFiMgmt::_processBLEPending() {
|
||||||
|
if (!_blePendingFlag) return;
|
||||||
|
_blePendingFlag = false;
|
||||||
|
Serial.printf("[BLE] loop 处理配网: %s\n", _blePendingJson.c_str());
|
||||||
|
handleBLEProvision(_blePendingJson.c_str());
|
||||||
|
_blePendingJson = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiFiMgmt::handleBLEProvision(const char* json) {
|
||||||
|
JsonDocument doc;
|
||||||
|
DeserializationError err = deserializeJson(doc, json);
|
||||||
|
if (err) {
|
||||||
|
Serial.printf("[BLE] JSON 解析失败: %s\n", err.c_str());
|
||||||
|
if (_bleChar) { _bleChar->setValue("ERR_JSON"); _bleChar->notify(); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取 WiFi 凭证
|
||||||
|
const char* ssid = doc["s"] | "";
|
||||||
|
const char* pass = doc["p"] | "";
|
||||||
|
|
||||||
|
if (strlen(ssid) == 0) {
|
||||||
|
Serial.println("[BLE] 未提供 WiFi SSID");
|
||||||
|
if (_bleChar) { _bleChar->setValue("ERR_NO_SSID"); _bleChar->notify(); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pendingSSID = ssid;
|
||||||
|
_pendingPass = pass;
|
||||||
|
|
||||||
|
// 保存到 LittleFS (和 Web 配网完全相同的逻辑)
|
||||||
|
strncpy(_config.wifi_ssid, ssid, sizeof(_config.wifi_ssid) - 1);
|
||||||
|
strncpy(_config.wifi_pass, pass, sizeof(_config.wifi_pass) - 1);
|
||||||
|
|
||||||
|
if (doc.containsKey("device_id")) strncpy(_config.device_id, doc["device_id"] | "", sizeof(_config.device_id) - 1);
|
||||||
|
if (doc.containsKey("env_note")) strncpy(_config.env_note, doc["env_note"] | "", sizeof(_config.env_note) - 1);
|
||||||
|
if (doc.containsKey("env_type")) strncpy(_config.env_type, doc["env_type"] | "", sizeof(_config.env_type) - 1);
|
||||||
|
if (doc.containsKey("mqtt_server")) strncpy(_config.mqtt_server, doc["mqtt_server"] | "", sizeof(_config.mqtt_server) - 1);
|
||||||
|
if (doc.containsKey("mqtt_port")) strncpy(_config.mqtt_port, doc["mqtt_port"] | "", sizeof(_config.mqtt_port) - 1);
|
||||||
|
if (doc.containsKey("mqtt_user")) strncpy(_config.mqtt_user, doc["mqtt_user"] | "", sizeof(_config.mqtt_user) - 1);
|
||||||
|
if (doc.containsKey("mqtt_pass")) strncpy(_config.mqtt_pass, doc["mqtt_pass"] | "", sizeof(_config.mqtt_pass) - 1);
|
||||||
|
|
||||||
|
_saveConfig();
|
||||||
|
_portalStopFlag = true; // 触发延迟关闭 AP+BLE → 连接 WiFi
|
||||||
|
|
||||||
|
Serial.printf("[BLE] ✅ 配网完成, SSID=%s\n", ssid);
|
||||||
|
|
||||||
|
// 回复 OK
|
||||||
|
if (_bleChar) { _bleChar->setValue("OK"); _bleChar->notify(); }
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 重置
|
// 重置
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -412,6 +595,7 @@ bool WiFiMgmt::_loadConfig() {
|
|||||||
strncpy(_config.mqtt_pass, doc["mqtt_pass"] | MQTT_DEFAULT_PASS, sizeof(_config.mqtt_pass)-1);
|
strncpy(_config.mqtt_pass, doc["mqtt_pass"] | MQTT_DEFAULT_PASS, sizeof(_config.mqtt_pass)-1);
|
||||||
strncpy(_config.device_id, doc["device_id"] | MQTT_DEFAULT_DEVICE, sizeof(_config.device_id)-1);
|
strncpy(_config.device_id, doc["device_id"] | MQTT_DEFAULT_DEVICE, sizeof(_config.device_id)-1);
|
||||||
strncpy(_config.env_note, doc["env_note"] | MQTT_DEFAULT_ENV, sizeof(_config.env_note)-1);
|
strncpy(_config.env_note, doc["env_note"] | MQTT_DEFAULT_ENV, sizeof(_config.env_note)-1);
|
||||||
|
strncpy(_config.env_type, doc["env_type"] | "bedroom", sizeof(_config.env_type)-1);
|
||||||
strncpy(_config.wifi_ssid, doc["wifi_ssid"] | "", sizeof(_config.wifi_ssid)-1);
|
strncpy(_config.wifi_ssid, doc["wifi_ssid"] | "", sizeof(_config.wifi_ssid)-1);
|
||||||
strncpy(_config.wifi_pass, doc["wifi_pass"] | "", sizeof(_config.wifi_pass)-1);
|
strncpy(_config.wifi_pass, doc["wifi_pass"] | "", sizeof(_config.wifi_pass)-1);
|
||||||
Serial.printf("[WiFi] 配置加载, 已存WiFi: %s\n", _config.wifi_ssid[0] ? _config.wifi_ssid : "(空)");
|
Serial.printf("[WiFi] 配置加载, 已存WiFi: %s\n", _config.wifi_ssid[0] ? _config.wifi_ssid : "(空)");
|
||||||
@@ -426,6 +610,7 @@ bool WiFiMgmt::_saveConfig() {
|
|||||||
doc["mqtt_pass"] = _config.mqtt_pass;
|
doc["mqtt_pass"] = _config.mqtt_pass;
|
||||||
doc["device_id"] = _config.device_id;
|
doc["device_id"] = _config.device_id;
|
||||||
doc["env_note"] = _config.env_note;
|
doc["env_note"] = _config.env_note;
|
||||||
|
doc["env_type"] = _config.env_type;
|
||||||
doc["wifi_ssid"] = _config.wifi_ssid;
|
doc["wifi_ssid"] = _config.wifi_ssid;
|
||||||
doc["wifi_pass"] = _config.wifi_pass;
|
doc["wifi_pass"] = _config.wifi_pass;
|
||||||
File file = LittleFS.open(CONFIG_FILE_DEVICE, "w");
|
File file = LittleFS.open(CONFIG_FILE_DEVICE, "w");
|
||||||
|
|||||||
Reference in New Issue
Block a user