diff --git a/lib/groundlight/src/groundlight.cpp b/lib/groundlight/src/groundlight.cpp index 58e2a45..a931c28 100644 --- a/lib/groundlight/src/groundlight.cpp +++ b/lib/groundlight/src/groundlight.cpp @@ -367,7 +367,6 @@ String get_query_id(const String &jsonResults) { StaticJsonDocument groundlight_json_doc; -// Parses the detectors from the Groundlight API. detector_list get_detector_list(const char *endpoint, const char *apiToken) { deserializeJson(groundlight_json_doc, get_detectors(endpoint, apiToken)); JsonArray detectors = groundlight_json_doc["results"]; @@ -375,12 +374,19 @@ detector_list get_detector_list(const char *endpoint, const char *apiToken) { for (int i = 0; i < detectors.size(); i++) { _detector_list[i].confidence_threshold = detectors[i]["confidence_threshold"]; - strcpy(_detector_list[i].id, detectors[i]["id"]); - strcpy(_detector_list[i].type, detectors[i]["type"]); - strcpy(_detector_list[i].created_at, detectors[i]["created_at"]); - strcpy(_detector_list[i].name, detectors[i]["name"]); - strcpy(_detector_list[i].query, detectors[i]["query"]); - strcpy(_detector_list[i].group_name, detectors[i]["group_name"]); + strlcpy(_detector_list[i].id, detectors[i]["id"], sizeof(_detector_list[i].id)); + strlcpy(_detector_list[i].type, detectors[i]["type"], sizeof(_detector_list[i].type)); + strlcpy(_detector_list[i].created_at, detectors[i]["created_at"], sizeof((_detector_list[i].created_at))); + strlcpy(_detector_list[i].name, detectors[i]["name"], sizeof(_detector_list[i].name)); + strlcpy(_detector_list[i].query, detectors[i]["query"], sizeof(_detector_list[i].query)); + strlcpy(_detector_list[i].group_name, detectors[i]["group_name"], sizeof(_detector_list[i].group_name)); + if (!detectors[i]["metadata"].isNull()) { + String metadataStr; + serializeJson(detectors[i]["metadata"], metadataStr); + strlcpy(_detector_list[i].metadata, metadataStr.c_str(), sizeof(_detector_list[i].metadata)); + } else { + _detector_list[i].metadata[0] = '\0'; + } } detector_list res = { _detector_list, detectors.size() }; return res; @@ -401,16 +407,38 @@ String detector_to_string(detector d) { res += d.group_name; res += "\n\tConfidence threshold: "; res += d.confidence_threshold; + res += "\n\tMetadata: "; + res += d.metadata; return res; } detector get_detector_by_id(const char *endpoint, const char *detectorId, const char *apiToken) { detector_list detectors = get_detector_list(endpoint, apiToken); + detector det = { "NONE", "NONE", "NONE", "NONE", "NONE", "NONE", 0.0, "None" }; for (int i = 0; i < detectors.size; i++) { if (String(detectors.detectors[i].id) == String(detectorId)) { - return detectors.detectors[i]; + det = detectors.detectors[i]; + break; + } + } + if (0 +
WiFi SSID: - WiFi Password: + WiFi Password: + API Key: + Autoconfig: + Detector Id: - API Key: Query Delay (seconds): Endpoint: - Target Confidence: - Motion Alpha (float between 0 and 1): - Motion Beta (float between 0 and 1): - Stacklight UUID: - Slack URL: - Email: - Email Endpoint: - Email Key: - Email Host: - Twilio SID: - Twilio Token: - Twilio Number: - Twilio Recipient: - + Target Confidence: )rawliteral" + #ifdef ENABLE_STACKLIGHT + R"rawliteral( + Enable Motion Detector: + + Enable Stacklight: + + )rawliteral" + #else + #endif + R"rawliteral(
)rawliteral"; @@ -355,19 +375,72 @@ String processor(const String& var) { else if (var == "mot_a" && preferences.isKey("mot_a")) out = String(preferences.getString("mot_a", "0.0")); else if (var == "mot_b" && preferences.isKey("mot_b")) out = String(preferences.getString("mot_b", "0.0")); else if (var == "sl_uuid" && preferences.isKey("sl_uuid")) out = preferences.getString("sl_uuid", ""); - else if (var == "slack_url" && preferences.isKey("slack_url")) out = preferences.getString("slack_url", ""); - else if (var == "email" && preferences.isKey("email")) out = preferences.getString("email", ""); - else if (var == "email_endpoint" && preferences.isKey("emailEndpoint")) out = preferences.getString("emailEndpoint", ""); - else if (var == "email_key" && preferences.isKey("emailKey")) out = preferences.getString("emailKey", ""); - else if (var == "email_host" && preferences.isKey("emailHost")) out = preferences.getString("emailHost", ""); - else if (var == "twilio_sid" && preferences.isKey("twilioSID")) out = preferences.getString("twilioSID", ""); - else if (var == "twilio_token" && preferences.isKey("twilioKey")) out = preferences.getString("twilioKey", ""); - else if (var == "twilio_number" && preferences.isKey("twilioNumber")) out = preferences.getString("twilioNumber", ""); - else if (var == "twilio_recipient" && preferences.isKey("twilioEndpoint")) out = preferences.getString("twilioEndpoint", ""); + else if (var == "autoconfig" && preferences.isKey("autoconfig")) out = preferences.getString("autoconfig", ""); preferences.end(); return out; // return var; } + +bool shouldPerformAutoConfig(AsyncWebServerRequest *request) { + bool autoconfigEnabled = request->hasParam("autoconfig"); + bool ssidFilled = request->hasParam("ssid") && request->getParam("ssid")->value() != ""; + bool passwordFilled = request->hasParam("pw") && request->getParam("pw")->value() != ""; + bool apiKeyFilled = request->hasParam("api_key") && request->getParam("api_key")->value() != ""; + + return autoconfigEnabled && ssidFilled && passwordFilled && apiKeyFilled; +} + +void performAutoConfig(AsyncWebServerRequest *request){ + const char* endpoint = groundlight_endpoint; + const char* apiToken = groundlight_API_key; + String mac = WiFi.macAddress(); + mac.replace(":", ""); + mac = mac.substring(6); + String esp_detector_name = (StringSumHelper) "ESP32-CAM-" + mac; + debug_printf("esp cam detector name: %s\n",esp_detector_name.c_str()); + detector esp_det = get_detector_by_name(endpoint, esp_detector_name.c_str(), apiToken); + if (strcmp(esp_det.id, "NONE") == 0) { + preferences.putString("det_id", "DETECTOR NOT FOUND"); + debug_printf("Error: Detector not found."); + return; + } + preferences.putString("det_id", esp_det.id); + strcpy(groundlight_det_id, esp_det.id); + String metadataStr = esp_det.metadata; + DynamicJsonDocument metadataDoc(1024); + DeserializationError error = deserializeJson(metadataDoc, metadataStr); + if (error) { + debug_printf(("deserializeJson() failed: ")); + debug_printf(error.c_str()); + return; + } + if (metadataDoc.containsKey("Query Delay (seconds)") && !metadataDoc["Query Delay (seconds)"].isNull()) { + query_delay = metadataDoc["Query Delay (seconds)"]; + preferences.putInt("query_delay", query_delay); + } + if (metadataDoc.containsKey("Target Confidence") && !metadataDoc["Target Confidence"].isNull()) { + targetConfidence = metadataDoc["Target Confidence"]; + preferences.putFloat("tConf", targetConfidence); + } + if (metadataDoc.containsKey("Motion Alpha (float between 0 and 1)") && !metadataDoc["Motion Alpha (float between 0 and 1)"].isNull()){ + String mot_a = metadataDoc["Motion Alpha (float between 0 and 1)"]; + preferences.putString("mot_a",mot_a); + } else if (metadataDoc.containsKey("Motion Alpha (float between 0 and 1)") && metadataDoc["Motion Alpha (float between 0 and 1)"].isNull()){ + preferences.remove("mot_a"); + } + if (metadataDoc.containsKey("Motion Beta (float between 0 and 1)") && !metadataDoc["Motion Beta (float between 0 and 1)"].isNull()){ + String mot_b = metadataDoc["Motion Beta (float between 0 and 1)"]; + preferences.putString("mot_b",mot_b); + } else if(metadataDoc.containsKey("Motion Beta (float between 0 and 1)") && metadataDoc["Motion Beta (float between 0 and 1)"].isNull()){ + preferences.remove("mot_b"); + } + if (metadataDoc.containsKey("Stacklight UUID") && !metadataDoc["Stacklight UUID"].isNull()){ + String sl_uuid = metadataDoc["Stacklight UUID"]; + preferences.putString("sl_uuid",sl_uuid); + } else if (metadataDoc.containsKey("Stacklight UUID") && metadataDoc["Stacklight UUID"].isNull()){ + preferences.remove("sl_uuid"); + } +} #endif void setup() { @@ -467,61 +540,43 @@ void setup() { preferences.putString("password", request->getParam("pw")->value()); strcpy(password, request->getParam("pw")->value().c_str()); } - if (request->hasParam("det_id") && request->getParam("det_id")->value() != "") { - preferences.putString("det_id", request->getParam("det_id")->value()); - strcpy(groundlight_det_id, request->getParam("det_id")->value().c_str()); - } if (request->hasParam("api_key") && request->getParam("api_key")->value() != "") { preferences.putString("api_key", request->getParam("api_key")->value()); strcpy(groundlight_API_key, request->getParam("api_key")->value().c_str()); } - if (request->hasParam("query_delay") && request->getParam("query_delay")->value() != "") { - query_delay = request->getParam("query_delay")->value().toInt(); - preferences.putInt("query_delay", query_delay); - } - if (request->hasParam("endpoint") && request->getParam("endpoint")->value() != "") { - preferences.putString("endpoint", request->getParam("endpoint")->value()); - strcpy(groundlight_endpoint, request->getParam("endpoint")->value().c_str()); - } - if (request->hasParam("tConf") && request->getParam("tConf")->value() != "") { - targetConfidence = request->getParam("tConf")->value().toFloat(); - preferences.putFloat("tConf", targetConfidence); - } - if (request->hasParam("mot_a") && request->getParam("mot_a")->value() != "") { - preferences.putString("mot_a", request->getParam("mot_a")->value()); - } - if (request->hasParam("mot_b") && request->getParam("mot_b")->value() != "") { - preferences.putString("mot_b", request->getParam("mot_b")->value()); - } - if (request->hasParam("sl_uuid") && request->getParam("sl_uuid")->value() != "") { - preferences.putString("sl_uuid", request->getParam("sl_uuid")->value()); - } - if (request->hasParam("slack_url") && request->getParam("slack_url")->value() != "") { - preferences.putString("slack_url", request->getParam("slack_url")->value()); - } - if (request->hasParam("email") && request->getParam("email")->value() != "") { - preferences.putString("email", request->getParam("email")->value()); - } - if (request->hasParam("email_endpoint") && request->getParam("email_endpoint")->value() != "") { - preferences.putString("emailEndpoint", request->getParam("email_endpoint")->value()); - } - if (request->hasParam("email_key") && request->getParam("email_key")->value() != "") { - preferences.putString("emailKey", request->getParam("email_key")->value()); - } - if (request->hasParam("email_host") && request->getParam("email_host")->value() != "") { - preferences.putString("emailHost", request->getParam("email_host")->value()); - } - if (request->hasParam("twilio_sid") && request->getParam("twilio_sid")->value() != "") { - preferences.putString("twilioSID", request->getParam("twilio_sid")->value()); - } - if (request->hasParam("twilio_token") && request->getParam("twilio_token")->value() != "") { - preferences.putString("twilioKey", request->getParam("twilio_token")->value()); - } - if (request->hasParam("twilio_number") && request->getParam("twilio_number")->value() != "") { - preferences.putString("twilioNumber", request->getParam("twilio_number")->value()); - } - if (request->hasParam("twilio_recipient") && request->getParam("twilio_recipient")->value() != "") { - preferences.putString("twilioEndpoint", request->getParam("twilio_recipient")->value()); + + if (shouldPerformAutoConfig(request)){ + performAutoConfig(request); + } else { + if (request->hasParam("det_id") && request->getParam("det_id")->value() != "") { + preferences.putString("det_id", request->getParam("det_id")->value()); + strcpy(groundlight_det_id, request->getParam("det_id")->value().c_str()); + } + if (request->hasParam("query_delay") && request->getParam("query_delay")->value() != "") { + query_delay = request->getParam("query_delay")->value().toInt(); + preferences.putInt("query_delay", query_delay); + } + if (request->hasParam("endpoint") && request->getParam("endpoint")->value() != "") { + preferences.putString("endpoint", request->getParam("endpoint")->value()); + strcpy(groundlight_endpoint, request->getParam("endpoint")->value().c_str()); + } + if (request->hasParam("tConf") && request->getParam("tConf")->value() != "") { + targetConfidence = request->getParam("tConf")->value().toFloat(); + preferences.putFloat("tConf", targetConfidence); + } + if (request->hasParam("mot_a") && request->getParam("mot_a")->value() != "") { + preferences.putString("mot_a", request->getParam("mot_a")->value()); + } + if (request->hasParam("mot_b") && request->getParam("mot_b")->value() != "") { + preferences.putString("mot_b", request->getParam("mot_b")->value()); + } + if (request->hasParam("sl_uuid") && request->getParam("sl_uuid")->value() != "") { + preferences.putString("sl_uuid", request->getParam("sl_uuid")->value()); + } + if (request->hasParam("autoconfig") && request->getParam("autoconfig")->value() != "") { + preferences.putString("autoconfig", request->getParam("autoconfig")->value()); + } + } // request->send(200, "text/html", "Configuration sent to your ESP Camera
Return to Home Page"); request->send_P(200, "text/html", sent_html); @@ -541,7 +596,7 @@ void setup() { WiFi.begin(ssid, password); wifi_configured = true; } - +#ifdef ENABLE_STACKLIGHT if (preferences.isKey("ssid") && preferences.isKey("sl_uuid") && !preferences.isKey("sl_ip")) { WiFi.disconnect(); @@ -568,6 +623,7 @@ void setup() { } WiFi.begin(ssid, password); } +#endif if (preferences.isKey("endpoint") && preferences.getString("endpoint", "") != "") { preferences.getString("endpoint", groundlight_endpoint, 60); @@ -634,13 +690,13 @@ void setup() { // alloc memory for 565 frames frame_565 = (uint8_t *) ps_malloc(FRAME_ARR_LEN); frame_565_old = (uint8_t *) ps_malloc(FRAME_ARR_LEN); - - debug_printf("detector_id : %s\n",groundlight_det_id); + #ifdef LED_BUILTIN digitalWrite(LED_BUILTIN, LOW); #endif } + void listener(void * parameter) { char input3[1000]; int input3_index = 0; @@ -787,6 +843,7 @@ void loop () { } if (WiFi.isConnected()) { debug_printf("WIFI connected to SSID %s\n", ssid); + } else { debug_printf("unable to connect to wifi status code %d! (skipping image query and looping again)\n", WiFi.status()); return; @@ -861,12 +918,14 @@ void loop () { notificationState = NOTIFICATION_ATTEMPT_FAILED; } } - preferences.begin("config"); - if (preferences.isKey("sl_uuid")) { - if (!notifyStacklight(last_label)) { - debug_println("Failed to notify stacklight"); + #ifdef ENABLE_STACKLIGHT + preferences.begin("config"); + if (preferences.isKey("sl_uuid")) { + if (!notifyStacklight(last_label)) { + debug_println("Failed to notify stacklight"); + } } - } + #endif resultDoc.clear(); preferences.end(); if (WiFi.SSID() != ssid) { @@ -957,36 +1016,6 @@ bool try_save_config(char * input) { } else { preferences.remove("endpoint"); } - if (doc["additional_config"].containsKey("notificationOptions") && doc["additional_config"]["notificationOptions"] != "None") { - debug_println("Found notification options!"); - preferences.putString("notiOptns", (const char *)doc["additional_config"]["notificationOptions"]); - if (doc["additional_config"].containsKey("slack") && doc["additional_config"]["slack"].containsKey("slackKey")) { - debug_println("Found slack!"); - preferences.putString("slackKey", (const char *)doc["additional_config"]["slack"]["slackKey"]); - preferences.putString("slackEndpoint", (const char *)doc["additional_config"]["slack"]["slackEndpoint"]); - } else { - preferences.remove("slackKey"); - preferences.remove("slackEndpoint"); - } - if (doc["additional_config"].containsKey("twilio") && doc["additional_config"]["twilio"].containsKey("twilioKey")) { - debug_println("Found twilio!"); - preferences.putString("twilioSID", (const char *)doc["additional_config"]["twilio"]["twilioSID"]); - preferences.putString("twilioKey", (const char *)doc["additional_config"]["twilio"]["twilioKey"]); - preferences.putString("twilioNumber", (const char *)doc["additional_config"]["twilio"]["twilioNumber"]); - preferences.putString("twilioEndpoint", (const char *)doc["additional_config"]["twilio"]["twilioEndpoint"]); - } else { - preferences.remove("twilioKey"); - } - if (doc["additional_config"].containsKey("email") && doc["additional_config"]["email"].containsKey("emailKey")) { - debug_println("Found email!"); - preferences.putString("emailKey", (const char *)doc["additional_config"]["email"]["emailKey"]); - preferences.putString("emailEndpoint", (const char *)doc["additional_config"]["email"]["emailEndpoint"]); - preferences.putString("email", (const char *)doc["additional_config"]["email"]["email"]); - preferences.putString("emailHost", (const char *)doc["additional_config"]["email"]["emailHost"]); - } else { - preferences.remove("emailKey"); - } - } if (doc["additional_config"].containsKey("stacklight") && doc["additional_config"]["stacklight"].containsKey("uuid")) { debug_println("Found stacklight!"); preferences.putString("sl_uuid", (const char *)doc["additional_config"]["stacklight"]["uuid"]); @@ -1159,7 +1188,7 @@ bool sendNotifications(char *label, camera_fb_t *fb) { preferences.end(); return worked; } - +#ifdef ENABLE_STACKLIGHT bool notifyStacklight(const char * label) { preferences.begin("config"); if (!preferences.isKey("sl_uuid")) { @@ -1200,6 +1229,7 @@ bool notifyStacklight(const char * label) { preferences.end(); return isKey; } +#endif bool decodeWorkingHoursString(String working_hours) { // 08:17 @@ -1246,22 +1276,6 @@ void try_answer_query(String input) { if (preferences.isKey("notiOptns")) { synthesisDoc["additional_config"]["notificationOptions"] = preferences.getString("notiOptns", "None"); } - if (preferences.isKey("slackKey") && preferences.isKey("slackEndpoint")) { - synthesisDoc["additional_config"]["slack"]["slackKey"] = preferences.getString("slackKey", "None"); - synthesisDoc["additional_config"]["slack"]["slackEndpoint"] = preferences.getString("slackEndpoint", "None"); - } - if (preferences.isKey("twilioSID") && preferences.isKey("twilioKey") && preferences.isKey("twilioNumber") && preferences.isKey("twilioEndpoint")) { - synthesisDoc["additional_config"]["twilio"]["twilioSID"] = preferences.getString("twilioSID", "None"); - synthesisDoc["additional_config"]["twilio"]["twilioKey"] = preferences.getString("twilioKey", "None"); - synthesisDoc["additional_config"]["twilio"]["twilioNumber"] = preferences.getString("twilioNumber", "None"); - synthesisDoc["additional_config"]["twilio"]["twilioEndpoint"] = preferences.getString("twilioEndpoint", "None"); - } - if (preferences.isKey("emailKey") && preferences.isKey("email") && preferences.isKey("emailEndpoint")) { - synthesisDoc["additional_config"]["email"]["emailKey"] = preferences.getString("emailKey", "None"); - synthesisDoc["additional_config"]["email"]["emailEndpoint"] = preferences.getString("emailEndpoint", "None"); - synthesisDoc["additional_config"]["email"]["email"] = preferences.getString("email", "None"); - synthesisDoc["additional_config"]["email"]["emailHost"] = preferences.getString("emailHost", "None"); - } if (preferences.isKey("sl_uuid")) { synthesisDoc["additional_config"]["stacklight"]["uuid"] = preferences.getString("sl_uuid", "None"); if (preferences.isKey("sl_switch")) { @@ -1332,4 +1346,4 @@ bool is_motion_detected(camera_fb_t* frame, int alpha, int beta) { } return motion_detected; -} +} \ No newline at end of file