Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added redis with event source module #76

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ IF(ENABLE_ARM64)
set(VCPKG_OVERLAY_TRIPLETS ../vcpkg/triplets/community/arm64-linux.cmake)
ENDIF(ENABLE_ARM64)

#use /MP only for language CXX (and not CUDA) and MSVC for both targets

add_compile_options($<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/MP>)

set(CMAKE_CXX_STANDARD 14)

project(APRAPIPES)

set(CMAKE_CXX_STANDARD 17)

#use /MP only for language CXX (and not CUDA) and MSVC for both targets

add_compile_options($<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/MP>)

IF(ENABLE_LINUX)
set(ENV{PKG_CONFIG_PATH} "${CMAKE_SOURCE_DIR}/../thirdparty/gst-build/gst-build-1.16/outInstall/lib/x86_64-linux-gnu/pkgconfig/")
Expand Down Expand Up @@ -71,6 +69,8 @@ ENDIF(NOT ENABLE_ARM64 AND NOT ENABLE_WINDOWS)
find_package(Boost COMPONENTS system thread filesystem serialization log chrono unit_test_framework REQUIRED)

find_package(OpenCV CONFIG REQUIRED)
find_package(redis++ CONFIG REQUIRED)
find_package(hiredis CONFIG REQUIRED)
find_package(BZip2 REQUIRED)
find_package(ZLIB REQUIRED)
find_package(liblzma REQUIRED)
Expand Down Expand Up @@ -266,9 +266,10 @@ SET(IP_FILES
src/BrightnessContrastControlXform.cpp
src/VirtualPTZ.cpp
src/WebCamSource.cpp
src/RedisDBReader.cpp
src/EventSource.cpp
src/FaceDetectorXform.cpp
src/TextOverlayXForm.cpp

)


Expand Down Expand Up @@ -298,6 +299,8 @@ SET(IP_FILES_H
include/BrightnessContrastControlXform.h
include/VirtualPTZ.h
include/WebCamSource.h
include/RedisDBReader.h
include/EventSource.h
include/ApraFaceInfo.h
include/FaceDetectsInfo.h
include/FaceDetectorXform.h
Expand Down Expand Up @@ -545,6 +548,8 @@ SET(UT_FILES
test/brightness_contrast_tests.cpp
test/virtualptz_tests.cpp
test/webcam_source_tests.cpp
test/redisreader_tests.cpp
test/eventsource_tests.cpp
test/facedetectorXform_tests.cpp
test/sound_record_tests.cpp
test/pullstratergy_tests.cpp
Expand Down
19 changes: 19 additions & 0 deletions base/include/EventSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "Module.h"
#include <sw/redis++/redis++.h>


class EventSource
{
public:
EventSource();
virtual ~EventSource();
void setPropsAfterReceivingCallback();
void callbackWatcher(sw::redis::Redis& redis);
void listenKey(std::string key, std::function<void()> callback);
void onChange(std::string key);
bool subscriber_running;
private:
std::map<std::string,std::function<void()>> listenKeys;
};
13 changes: 13 additions & 0 deletions base/include/RedisDBReader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <sw/redis++/redis++.h>
#include "GstOnvifRtspSink.h"

class RedisDBReader
{
public:
void *readValueFromVideoEncoderByField(sw::redis::Redis &redis, std::string encoderName, std::string fieldName);
void *readImageSettingValue(sw::redis::Redis &redis, std::string imagingSetting);
std::vector<GStreamerOnvifRTSPSinkProps::User> getUsersList(sw::redis::Redis &redis);
std::vector<std::string> getSetMembers(sw::redis::Redis &redis, std::string setName);
std::unordered_map<std::string, std::string> getHash(sw::redis::Redis &redis, std::string hashName);
std::string getValueByKeyName(sw::redis::Redis &redis, std::string keyName);
};
58 changes: 58 additions & 0 deletions base/src/EventSource.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "EventSource.h"
#include <sw/redis++/redis++.h>

EventSource::EventSource()
{
}

EventSource::~EventSource()
{
subscriber_running = false;
}

void EventSource::callbackWatcher(sw::redis::Redis& redis)
{

auto subscriber = redis.subscriber();
subscriber.on_pmessage([&](std::string pattern, std::string channel, std::string msg)
{
onChange(pattern);
});

subscriber.psubscribe({"__keyspace@1__:onvif.media.Profiles*",
"__keyspace@1__:onvif.media.VideoEncoder*",
"__keyspace@1__:onvif.media.MetadataConfiguration*",
"__keyspace@1__:onvif.users.User*",
"__keyspace@1__:onvif.media.OSDConfigurations*",
"__keyspace@1__:onvif.media.VideoSourceConfiguration*"});
subscriber_running = true;
while (subscriber_running)
{
try
{
subscriber.consume();
}
catch (const sw::redis::TimeoutError &e)
{
continue;
}
catch (const sw::redis::Error &err)
{
std::cout << "caught some other err" << std::endl;
// Handle other exceptions.
}
}
}

void EventSource::listenKey(std::string key, std::function<void()> callback)
{
listenKeys.emplace(key, callback);
return;
}

void EventSource::onChange(std::string key)
{
auto callbackIterator = listenKeys.find(key);
callbackIterator->second();
return;
}
52 changes: 52 additions & 0 deletions base/src/RedisDBReader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "RedisDBReader.h"
#include <vector>
#include <string_view>
#include <string>
#include <memory>
#include <unordered_set>
#include <unordered_map>
#include <iostream>
#include <sstream>
#include "AIPExceptions.h"
#include "GstOnvifRtspSink.h"


std::vector<GStreamerOnvifRTSPSinkProps::User> RedisDBReader::getUsersList(sw::redis::Redis &redis)
{
std::unordered_set<std::string> user_keys;
std::vector<GStreamerOnvifRTSPSinkProps::User> users;
redis.smembers("onvif.users.User", std::inserter(user_keys, user_keys.begin()));
for (const auto& user_key : user_keys) {
std::unordered_map<std::string, std::string> userinfo;
redis.hgetall(user_key, std::inserter(userinfo, userinfo.begin()));
try {
GStreamerOnvifRTSPSinkProps::User user = { userinfo.at("userName"), userinfo.at("password") };
users.emplace_back(user);
LOG_INFO << "Got username " << user.username;
} catch (std::out_of_range &exc) {
LOG_ERROR << "could not retrieve user information for " << user_key;
}
}
return users;
}

std::unordered_map<std::string, std::string> RedisDBReader::getHash(sw::redis::Redis &redis, std::string hashName)
{
std::unordered_map<std::string, std::string> hashdata;
redis.hgetall(hashName,std::inserter(hashdata,hashdata.begin()));
return hashdata;
}

std::string RedisDBReader::getValueByKeyName(sw::redis::Redis &redis, std::string keyName)
{
LOG_INFO << "Fetching value for key named " << keyName;
auto val = redis.get(static_cast<sw::redis::StringView>(keyName));
return *val;
}

std::vector<std::string> RedisDBReader::getSetMembers(sw::redis::Redis &redis, std::string setName)
{
std::vector<std::string> members;
redis.smembers(static_cast<sw::redis::StringView>(setName),std::inserter(members,members.begin()));
return members;
}
53 changes: 53 additions & 0 deletions base/test/eventsource_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//read the key from db
//make properties and set props
//define some keys
//instantiate brightness class
//

#include <boost/test/unit_test.hpp>
#include <sw/redis++/redis++.h>
#include "EventSource.h"
#include "Logger.h"
#include "AIPExceptions.h"
#include "RedisDBReader.h"
#include "StatSink.h"
#include "GstOnvifRtspSink.h"

BOOST_AUTO_TEST_SUITE(eventsource_tests)

BOOST_AUTO_TEST_CASE(eventsourcetest, *boost::unit_test::disabled())
{
//Redis DB needs to be populated - prerequisite
LoggerProps logprops;
logprops.logLevel = boost::log::trivial::severity_level::info;
Logger::initLogger(logprops);

sw::redis::ConnectionOptions connection_options;
connection_options.type = sw::redis::ConnectionType::UNIX;
connection_options.path = "/run/redis/redis.sock";
connection_options.db = 1;
connection_options.socket_timeout = std::chrono::milliseconds(10000);
sw::redis::Redis redis = sw::redis::Redis(connection_options);

auto redisReader = boost::shared_ptr<RedisDBReader>(new RedisDBReader());
auto eventSource = boost::shared_ptr<EventSource>(new EventSource());
GStreamerOnvifRTSPSinkProps props;
auto rtspSink = boost::shared_ptr<GStreamerOnvifRTSPSink>(new GStreamerOnvifRTSPSink(props));

eventSource->listenKey("__keyspace@1__:onvif.users.User*", [&]() -> void
{
auto userList = redisReader->getUsersList(redis);
if (!userList.empty())
{
props.userList = userList;
rtspSink->setProps(props);
LOG_INFO << "userList Fetched on callback";
}
});

eventSource->callbackWatcher(redis);
boost::this_thread::sleep_for(boost::chrono::seconds(10000));
LOG_INFO << "userList Fetched";
}

BOOST_AUTO_TEST_SUITE_END()
124 changes: 124 additions & 0 deletions base/test/redisreader_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include <boost/test/unit_test.hpp>
#include <sw/redis++/redis++.h>

#include "Logger.h"
#include "AIPExceptions.h"
#include "RedisDBReader.h"
#include "StatSink.h"
#include <cstdlib>

#define MAP_STRING_TO_BOOL(str, var) ( \
std::istringstream(map.find(str)->second) >> std::boolalpha >> var)

#define MAP_STRING_TO_INT(str, var) ( \
var = atoi(map.find(str)->second.c_str()))

#define MAP_STRING_TO_STRING(str, var) ( \
var = map.find(str)->second)

BOOST_AUTO_TEST_SUITE(redisreader_tests)

BOOST_AUTO_TEST_CASE(readertest, *boost::unit_test::disabled())
{
struct VideoEncoder
{
bool multicastautostart;
std::string token;
int multicastTTL;
int bitrate;
int framerate;
std::string multicastIPAddress;
bool multicastEnable;
std::string encoding;
int govlength;
std::string name;
int multicastPort;
VideoEncoder(boost::shared_ptr<RedisDBReader> redisReader, sw::redis::Redis &redis, std::string videoEncoderName)
{
update(redisReader, redis, videoEncoderName);
}

void update(boost::shared_ptr<RedisDBReader> redisReader, sw::redis::Redis &redis, std::string videoEncoderName)
{
char hashName[1000];

sprintf(hashName, "onvif.media.VideoEncoder#%s", videoEncoderName.c_str());
auto map = redisReader->getHash(redis, hashName);

MAP_STRING_TO_BOOL("multicastautostart", multicastautostart);

MAP_STRING_TO_STRING("token", token);

MAP_STRING_TO_INT("multicastTTL", multicastTTL);

MAP_STRING_TO_INT("bitrate", bitrate);

MAP_STRING_TO_INT("framerate", framerate);

MAP_STRING_TO_STRING("multicastIPAddress", multicastIPAddress);

MAP_STRING_TO_BOOL("multicastEnable", multicastEnable);

MAP_STRING_TO_STRING("encoding", encoding);

MAP_STRING_TO_INT("govlength", govlength);

MAP_STRING_TO_STRING("name", name);

MAP_STRING_TO_INT("multicastPort", multicastPort);
}
};

struct Profile
{
bool fixed;
std::string videoEncoderToken;
std::string videoSourceToken;
std::string name;
std::string token;
Profile(boost::shared_ptr<RedisDBReader> redisReader, sw::redis::Redis &redis, std::string profileName)
{
update(redisReader, redis, profileName);
}

void update(boost::shared_ptr<RedisDBReader> redisReader, sw::redis::Redis &redis, std::string profileName)
{
char hashName[1000];
sprintf(hashName, "onvif.media.Profiles#%s", profileName.c_str());
auto map = redisReader->getHash(redis, hashName);

MAP_STRING_TO_BOOL("fixed", fixed);

MAP_STRING_TO_STRING("videoEncoderToken", videoEncoderToken);

MAP_STRING_TO_STRING("videoSourceToken", videoSourceToken);

MAP_STRING_TO_STRING("name", name);

MAP_STRING_TO_STRING("token", token);
}
};
//Redis DB needs to be populated - prerequisite
LoggerProps logprops;
logprops.logLevel = boost::log::trivial::severity_level::info;
Logger::initLogger(logprops);

sw::redis::ConnectionOptions connection_options;
connection_options.type = sw::redis::ConnectionType::UNIX;
connection_options.path = "/run/redis/redis.sock";
connection_options.db = 1;
connection_options.socket_timeout = std::chrono::milliseconds(1000);
sw::redis::Redis redis = sw::redis::Redis(connection_options);

// auto redisInstance = boost::shared_ptr<RedisRepositoryController>(new RedisRepositoryController());
auto redisReader = boost::shared_ptr<RedisDBReader>(new RedisDBReader());
auto userList = redisReader->getUsersList(redis);
auto videoEncoderRGBCameraH264 = VideoEncoder(redisReader, redis, "rgbcamera_H264");
LOG_INFO << videoEncoderRGBCameraH264.bitrate;
auto profileFixed0 = Profile(redisReader, redis, "Fixed_0");
LOG_INFO << profileFixed0.videoEncoderToken;
auto profiles = redisReader->getSetMembers(redis, "onvif.media.Profiles");
LOG_INFO << "userList Fetched";
}

BOOST_AUTO_TEST_SUITE_END()