Move Poller_Healthy and Trigger state into Amcrest_API and ONVIF modules. Add lastTopic and lastValue to onvif. Add values to event notes. Reverse logic for event ending to look for false, as the value could be other things like isMotion or IsPeople.

This commit is contained in:
Isaac Connor
2024-09-18 12:27:26 -04:00
parent 8c96d3004b
commit 331390ea20
4 changed files with 48 additions and 35 deletions

View File

@@ -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

View File

@@ -326,6 +326,8 @@ class Monitor : public std::enable_shared_from_this<Monitor> {
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<Monitor> {
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<Monitor> {
~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<Monitor> {
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<Monitor> {
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 {

View File

@@ -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");

View File

@@ -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);
}