diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 05ea6d6df..77a43c9fd 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -316,8 +316,6 @@ Monitor::Monitor() : //linked_monitors_string n_linked_monitors(0), linked_monitors(nullptr), - Poll_Trigger_State(false), - Event_Poller_Healthy(false), Event_Poller_Closes_Event(false), RTSP2Web_Manager(nullptr), Janus_Manager(nullptr), @@ -1168,10 +1166,8 @@ bool Monitor::connect() { //ONVIF and Amcrest Setup //For now, only support one event type per camera, so share some state. - Poll_Trigger_State = false; if (onvif_event_listener) { // Debug(1, "Starting ONVIF"); - Event_Poller_Healthy = false; if (onvif_options.find("closes_event") != std::string::npos) { //Option to indicate that ONVIF will send a close event message Event_Poller_Closes_Event = true; } @@ -1871,7 +1867,7 @@ bool Monitor::Poll() { std::chrono::system_clock::time_point loop_start_time = std::chrono::system_clock::now(); if (use_Amcrest_API) { - if (Event_Poller_Healthy) { + if (Amcrest_Manager->isHealthy()) { Amcrest_Manager->WaitForMessage(); } else { delete Amcrest_Manager; @@ -1950,17 +1946,18 @@ bool Monitor::Analyse() { Event::StringSetMap noteSetMap; #ifdef WITH_GSOAP - if (onvif_event_listener && Event_Poller_Healthy) { - if ((onvif and onvif->isAlarmed()) or Poll_Trigger_State) { + if (onvif_event_listener) { + if ((onvif and onvif->isAlarmed()) or (Amcrest_Manager and Amcrest_Manager->isAlarmed())) { score += 9; Debug(4, "Triggered on ONVIF"); Event::StringSet noteSet; noteSet.insert("ONVIF"); + noteSet.insert(onvif->lastTopic() + '/' + onvif->lastValue()); noteSetMap[MOTION_CAUSE] = noteSet; cause += "ONVIF"; // If the camera isn't going to send an event close, we need to close it here, but only after it has actually triggered an alarm. if (!Event_Poller_Closes_Event && state == ALARM) - Poll_Trigger_State = false; + onvif->setAlarmed(false); } // end ONVIF_Trigger } // end if (onvif_event_listener && Event_Poller_Healthy) #endif diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 083eba695..7ea14b0ac 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -326,6 +326,8 @@ class Monitor : public std::enable_shared_from_this { Monitor *parent; bool alarmed; bool healthy; + std::string last_topic; + std::string last_value; #ifdef WITH_GSOAP struct soap *soap = nullptr; _tev__CreatePullPointSubscription request; @@ -343,12 +345,17 @@ class Monitor : public std::enable_shared_from_this { void start(); void WaitForMessage(); bool isAlarmed() const { return alarmed; }; + void setAlarmed(bool p_alarmed) { alarmed = p_alarmed; }; bool isHealthy() const { return healthy; }; + const std::string &lastTopic() const { return last_topic; }; + const std::string &lastValue() const { return last_value; }; }; class AmcrestAPI { protected: Monitor *parent; + bool alarmed; + bool healthy; std::string amcrest_response; CURLM *curl_multi = nullptr; CURL *Amcrest_handle = nullptr; @@ -359,8 +366,9 @@ class Monitor : public std::enable_shared_from_this { ~AmcrestAPI(); int API_Connect(); void WaitForMessage(); - bool Amcrest_Alarmed; - int start_Amcrest(); + int start(); + bool isAlarmed() const { return alarmed; }; + bool isHealthy() const { return healthy; }; }; class RTSP2WebManager { @@ -631,8 +639,6 @@ class Monitor : public std::enable_shared_from_this { std::string diag_path_delta; //ONVIF - bool Poll_Trigger_State; - bool Event_Poller_Healthy; bool Event_Poller_Closes_Event; RTSP2WebManager *RTSP2Web_Manager; @@ -718,8 +724,13 @@ class Monitor : public std::enable_shared_from_this { return onvif_event_listener; } int check_janus(); //returns 1 for healthy, 0 for success but missing stream, negative for error. - bool EventPollerHealthy() { - return Event_Poller_Healthy; + bool EventPollerHealthy() const { + if (onvif) { + return onvif->isHealthy(); + } else if (Amcrest_Manager) { + return Amcrest_Manager->isHealthy(); + } + return false; } inline const char *EventPrefix() const { return event_prefix.c_str(); } inline bool Ready() const { diff --git a/src/zm_monitor_amcrest.cpp b/src/zm_monitor_amcrest.cpp index 5d2526503..c46e7bdac 100644 --- a/src/zm_monitor_amcrest.cpp +++ b/src/zm_monitor_amcrest.cpp @@ -21,9 +21,11 @@ Monitor::AmcrestAPI::AmcrestAPI(Monitor *parent_) : parent(parent_), - Amcrest_Alarmed(false) { + alarmed(false), + healthy(false) +{ curl_multi = curl_multi_init(); - start_Amcrest(); + start(); } Monitor::AmcrestAPI::~AmcrestAPI() { @@ -34,7 +36,7 @@ Monitor::AmcrestAPI::~AmcrestAPI() { if (curl_multi != nullptr) curl_multi_cleanup(curl_multi); } -int Monitor::AmcrestAPI::start_Amcrest() { +int Monitor::AmcrestAPI::start() { // init the transfer and start it in multi-handle int running_handles; long response_code; @@ -76,7 +78,7 @@ int Monitor::AmcrestAPI::start_Amcrest() { } if ((curl_error == CURLM_OK) && (running_handles > 0)) { - parent->Event_Poller_Healthy = true; + healthy = true; Debug(1, "AMCREST Healthy"); } else { Warning("AMCREST Response: %s", amcrest_response.c_str()); @@ -94,7 +96,7 @@ void Monitor::AmcrestAPI::WaitForMessage() { int transfers; curl_multi_perform(curl_multi, &open_handles); if (open_handles == 0) { - start_Amcrest(); // http transfer ended, need to restart. + start(); // http transfer ended, need to restart. } else { // wait for max 5 seconds for event. curl_multi_wait(curl_multi, nullptr, 0, 5000, &transfers); @@ -104,13 +106,13 @@ void Monitor::AmcrestAPI::WaitForMessage() { if (amcrest_response.find("action=Start") != std::string::npos) { // Event Start Debug(1, "AMCREST Triggered on ONVIF"); - if (!parent->Poll_Trigger_State) { + if (!alarmed) { Debug(1, "AMCREST Triggered Event"); - parent->Poll_Trigger_State = true; + alarmed = true; } } else if (amcrest_response.find("action=Stop") != std::string::npos) { Debug(1, "AMCREST Triggered off ONVIF"); - parent->Poll_Trigger_State = false; + alarmed = false; if (!parent->Event_Poller_Closes_Event) { // If we get a close event, then we know to expect them. parent->Event_Poller_Closes_Event = true; Debug(1, "AMCREST Setting ClosesEvent"); diff --git a/src/zm_monitor_onvif.cpp b/src/zm_monitor_onvif.cpp index d7f18d134..f55d3f550 100644 --- a/src/zm_monitor_onvif.cpp +++ b/src/zm_monitor_onvif.cpp @@ -168,7 +168,7 @@ void Monitor::ONVIF::WaitForMessage() { for (auto msg : tev__PullMessagesResponse.wsnt__NotificationMessage) { if ((msg->Topic != nullptr) && (msg->Topic->__any.text != nullptr) && - std::strstr(msg->Topic->__any.text, parent->onvif_alarm_txt.c_str()) && + (parent->onvif_alarm_txt.empty() || std::strstr(msg->Topic->__any.text, parent->onvif_alarm_txt.c_str())) && (msg->Message.__any.elts != nullptr) && (msg->Message.__any.elts->next != nullptr) && (msg->Message.__any.elts->next->elts != nullptr) && @@ -176,26 +176,29 @@ void Monitor::ONVIF::WaitForMessage() { (msg->Message.__any.elts->next->elts->atts->next != nullptr) && (msg->Message.__any.elts->next->elts->atts->next->text != nullptr) ) { - Info("Got Motion Alarm!"); - if (strcmp(msg->Message.__any.elts->next->elts->atts->next->text, "true") == 0) { - // Event Start - Info("Triggered on ONVIF"); - if (!alarmed) { - Info("Triggered Event"); - alarmed = true; - // Why sleep? - std::this_thread::sleep_for(std::chrono::seconds(1)); //thread sleep - } - } else { + Info("ONVIF Got Motion Alarm! %s %s", msg->Topic->__any.text, msg->Message.__any.elts->next->elts->atts->next->text); + // Apparently simple motion events, the value is boolean, but for people detection can be things like isMotion, isPeople + if (strcmp(msg->Message.__any.elts->next->elts->atts->next->text, "false") == 0) { Info("Triggered off ONVIF"); alarmed = false; if (!parent->Event_Poller_Closes_Event) { //If we get a close event, then we know to expect them. parent->Event_Poller_Closes_Event = true; Info("Setting ClosesEvent"); } + } else { + // Event Start + Info("Triggered on ONVIF"); + if (!alarmed) { + Info("Triggered Event"); + alarmed = true; + last_topic = msg->Topic->__any.text; + last_value = msg->Message.__any.elts->next->elts->atts->next->text; + // Why sleep? + std::this_thread::sleep_for(std::chrono::seconds(1)); //thread sleep + } } } else { - Debug(1, "Got a message that we couldn't parse"); + Debug(1, "ONVIF Got a message that we couldn't parse"); if ((msg->Topic != nullptr) && (msg->Topic->__any.text != nullptr)) { Debug(1, "text was %s", msg->Topic->__any.text); }