commit 4546808c73baff9530445a7f2c9cd1584f31b47a Author: JDierkse Date: Fri May 1 11:25:56 2020 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cedca15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.o.* +*.d.* +*.a.* +.*.swp +.AppleDouble +.debug +.gdbinit* +gdb* +core-* +*-core +core.* +*.core +CameraRecorder* +!CameraRecorder.cc +!CameraRecorder.ini diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..876e403 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Makefiles"] + path = Makefiles + url = https://gogs.dierkse.nl/JDierkse/Makefiles diff --git a/API/Makefile b/API/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/API/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/API/WebAPI.cpp b/API/WebAPI.cpp new file mode 100644 index 0000000..3a66e03 --- /dev/null +++ b/API/WebAPI.cpp @@ -0,0 +1,94 @@ +#include "WebAPI.h" +#include "Recorder/Recorder.h" +#include "Recorder/DigooRecorder.h" +#include "Recorder/FoscamRecorder.h" +#include "Recorder/VStarCamRecorder.h" +#include "Recorder/WatchBotRecorder.h" +#include "Recorder/ZModoRecorder.h" +#include +#include + + +namespace CameraRecorder { +namespace API { + +// API Description + +// Status Query +// Goal: Provide status information based on POST data +// Use: DomoticaSite status update +// URL: http:///API////// + +WebAPI::WebAPI() +{ +} + +WebAPI::~WebAPI() +{ +} + +std::string WebAPI::ProcessQuery(ctpl::thread_pool* pThreadPool, Http::HttpClient* pHttpClient, const std::string& path, const std::string& ffmpeg, const std::string& uri, const std::vector& postData) +{ + std::string output; + + std::vector uriTokens = StringAlgorithm::split(uri, '/'); + + if (uriTokens.size() < 7) + return std::string(); + + std::string action = uriTokens[1]; + std::string brand = uriTokens[2]; + + Recorder::Settings settings; + settings.Path = path; + settings.IpAddress = uriTokens[3]; + settings.Port = uriTokens[4]; + settings.Username = uriTokens[5]; + settings.Password = uriTokens[6]; + + if (StringAlgorithm::iequals("Digoo", brand)) + { + auto recorder = Recorder::DigooRecorder(pHttpClient, settings); + if (StringAlgorithm::iequals("Snapshot", action)) + output = recorder.Snapshot(pThreadPool); + else if (StringAlgorithm::iequals("Video", action)) + output = recorder.Video(pThreadPool, ffmpeg); + } + else if (StringAlgorithm::iequals("Foscam", brand)) + { + auto recorder = Recorder::FoscamRecorder(pHttpClient, settings); + if (StringAlgorithm::iequals("Snapshot", action)) + output = recorder.Snapshot(pThreadPool); + else if (StringAlgorithm::iequals("Video", action)) + output = recorder.Video(pThreadPool, ffmpeg); + } + else if (StringAlgorithm::iequals("VStarCam", brand)) + { + auto recorder = Recorder::VStarCamRecorder(pHttpClient, settings); + if (StringAlgorithm::iequals("Snapshot", action)) + output = recorder.Snapshot(pThreadPool); + else if (StringAlgorithm::iequals("Video", action)) + output = recorder.Video(pThreadPool, ffmpeg); + } + else if (StringAlgorithm::iequals("WatchBot", brand)) + { + auto recorder = Recorder::WatchBotRecorder(pHttpClient, settings); + if (StringAlgorithm::iequals("Snapshot", action)) + output = recorder.Snapshot(pThreadPool); + else if (StringAlgorithm::iequals("Video", action)) + output = recorder.Video(pThreadPool, ffmpeg); + } + else if (StringAlgorithm::iequals("ZModo", brand)) + { + auto recorder = Recorder::ZModoRecorder(pHttpClient, settings); + if (StringAlgorithm::iequals("Snapshot", action)) + output = recorder.Snapshot(pThreadPool); + else if (StringAlgorithm::iequals("Video", action)) + output = recorder.Video(pThreadPool, ffmpeg); + } + + return output; +} + +} // namespace API +} // namespace CameraRecorder diff --git a/API/WebAPI.h b/API/WebAPI.h new file mode 100644 index 0000000..443f11a --- /dev/null +++ b/API/WebAPI.h @@ -0,0 +1,31 @@ +#ifndef API_WEBAPI_H +#define API_WEBAPI_H + +#include +#include +#include +#include + + +namespace Http { + +class HttpClient; + +} // namespace Http + +namespace CameraRecorder { +namespace API { + +class WebAPI +{ +public: + WebAPI(); + ~WebAPI(); + + static std::string ProcessQuery(ctpl::thread_pool* pThreadPool, Http::HttpClient* pHttpClient, const std::string& path, const std::string& ffmpeg, const std::string& uri, const std::vector& postData); +}; + +} // namespace API +} // namespace DomoticaServer + +#endif // API_WEBAPI_H diff --git a/Application/CameraRecorder.cc b/Application/CameraRecorder.cc new file mode 100644 index 0000000..62c2922 --- /dev/null +++ b/Application/CameraRecorder.cc @@ -0,0 +1,66 @@ +#include "API/WebAPI.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int main(int argc, char** argv) +{ + try + { + Logging::OpenLog(); + Logging::SetLogMask(Logging::Severity::Debug); + + INIReader iniReader("CameraRecorder.ini"); + if (iniReader.ParseError() != 0) + throw std::runtime_error("Can't read CameraRecorder.ini."); + + Logging::Log(Logging::Severity::Info, "Starting CameraRecorder"); + + int port = iniReader.GetInteger("CameraRecorder", "Port", 0); + if (port == 0) + throw std::runtime_error("Port directive missing in ini file."); + + std::string path = iniReader.Get("CameraRecorder", "Path", ""); + if (path.empty()) + throw std::runtime_error("Path directive missing in ini file."); + + std::string ffmpeg = iniReader.Get("CameraRecorder", "FFMPEG", ""); + if (ffmpeg.empty()) + throw std::runtime_error("FFMPEG directive missing in ini file."); + + ctpl::thread_pool threadPool(6); + Http::HttpClient httpClient; + auto callback = std::bind(&CameraRecorder::API::WebAPI::ProcessQuery, &threadPool, &httpClient, path, ffmpeg, std::placeholders::_1, std::placeholders::_2); + + Http::HttpServer server(port, callback); + Logging::Log(Logging::Severity::Info, "Startup Complete"); + server.Wait(); + + Logging::Log(Logging::Severity::Info, "Stopping CameraRecorder..."); + + Logging::CloseLog(); + } + catch (const std::exception& e) + { + std::cerr << "Exception caught" << std::endl; + + std::stringstream ss; + ss << "Type : " << typeid(e).name() << std::endl; + ss << "ERROR: " << e.what() << std::endl; + + Logging::Log(Logging::Severity::Error, ss.str()); + + Logging::CloseLog(); + + return -1; + } + + return 0; +} diff --git a/Application/Makefile b/Application/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/Application/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/CameraRecorder.ini b/CameraRecorder.ini new file mode 100644 index 0000000..9701845 --- /dev/null +++ b/CameraRecorder.ini @@ -0,0 +1,4 @@ +[CameraRecorder] +Port = +Target = +FFMPEG = diff --git a/Libraries/CTPL b/Libraries/CTPL new file mode 120000 index 0000000..61ac13c --- /dev/null +++ b/Libraries/CTPL @@ -0,0 +1 @@ +../../Libraries/CTPL \ No newline at end of file diff --git a/Libraries/Http b/Libraries/Http new file mode 120000 index 0000000..5fe3319 --- /dev/null +++ b/Libraries/Http @@ -0,0 +1 @@ +../../Libraries/Http \ No newline at end of file diff --git a/Libraries/Logging b/Libraries/Logging new file mode 120000 index 0000000..2b4f659 --- /dev/null +++ b/Libraries/Logging @@ -0,0 +1 @@ +../../Libraries/Logging \ No newline at end of file diff --git a/Libraries/Utilities b/Libraries/Utilities new file mode 120000 index 0000000..88f16bc --- /dev/null +++ b/Libraries/Utilities @@ -0,0 +1 @@ +../../Libraries/Utilities \ No newline at end of file diff --git a/Libraries/inih b/Libraries/inih new file mode 120000 index 0000000..f48979f --- /dev/null +++ b/Libraries/inih @@ -0,0 +1 @@ +../../Libraries/inih \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 120000 index 0000000..6aa5187 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +Makefiles/Makefile \ No newline at end of file diff --git a/Makefile.conf b/Makefile.conf new file mode 100644 index 0000000..c260047 --- /dev/null +++ b/Makefile.conf @@ -0,0 +1,22 @@ +# +# Makefile.conf +# + +LFLAGS += -lHttp -lcurl +LFLAGS += -L$(ROOTPATH)/Libraries/Http/lib/$(ARCH) +CFLAGS += -I$(ROOTPATH)/Libraries/Http/include + +LFLAGS += -lLogging +LFLAGS += -L$(ROOTPATH)/Libraries/Logging/lib/$(ARCH) +CFLAGS += -I$(ROOTPATH)/Libraries/Logging/include + +LFLAGS += -lUtilities +LFLAGS += -L$(ROOTPATH)/Libraries/Utilities/lib/$(ARCH) +CFLAGS += -I$(ROOTPATH)/Libraries/Utilities/include + +CFLAGS += -I$(ROOTPATH)/Libraries/CTPL +CFLAGS += -I$(ROOTPATH)/Libraries/inih + +LFLAGS += -pthread -lm +CFLAGS += -I$(ROOTPATH) -I$(ROOTPATH)/Libraries +DEBUGDIR := .debug diff --git a/Makefile.target b/Makefile.target new file mode 100644 index 0000000..188452f --- /dev/null +++ b/Makefile.target @@ -0,0 +1,13 @@ +# +# Makefile.target +# + +CameraRecorder.$(ARCH): $(OBJECTS) Application/CameraRecorder.o.$(ARCH) + $(call build_target_arch,$@,$^) + +CameraRecorder: + $(call build_target,$@) + +.DEFAULT_GOAL := CameraRecorder + +TARGETS += CameraRecorder diff --git a/Makefiles b/Makefiles new file mode 160000 index 0000000..5e11355 --- /dev/null +++ b/Makefiles @@ -0,0 +1 @@ +Subproject commit 5e113555ebd4e049b287b3c94c4ef33e151ea4e6 diff --git a/Recorder/DigooRecorder.cpp b/Recorder/DigooRecorder.cpp new file mode 100644 index 0000000..bd3a561 --- /dev/null +++ b/Recorder/DigooRecorder.cpp @@ -0,0 +1,32 @@ +#include "DigooRecorder.h" +#include +#include + + +namespace CameraRecorder { +namespace Recorder { + +DigooRecorder::DigooRecorder(Http::HttpClient* pHttpClient, const Settings& settings) : + m_pHttpClient(pHttpClient), + m_settings(settings) +{ +} + +DigooRecorder::~DigooRecorder() +{ +} + +std::string DigooRecorder::Snapshot(ctpl::thread_pool* pThreadPool) +{ + Logging::Log(Logging::Severity::Debug, "DigooRecorder Snapshot"); + return std::string(); +} + +std::string DigooRecorder::Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) +{ + Logging::Log(Logging::Severity::Debug, "DigooRecorder Video"); + return std::string(); +} + +} // namespace Recorder +} // namespace CameraRecorder diff --git a/Recorder/DigooRecorder.h b/Recorder/DigooRecorder.h new file mode 100644 index 0000000..69e3294 --- /dev/null +++ b/Recorder/DigooRecorder.h @@ -0,0 +1,34 @@ +#ifndef RECORDER_DIGOORECORDER_H +#define RECORDER_DIGOORECORDER_H + +#include "Recorder.h" +#include "Settings.h" + + +namespace Http { + +class HttpClient; + +} // namespace Http + +namespace CameraRecorder { +namespace Recorder { + +class DigooRecorder : public virtual Recorder +{ +public: + DigooRecorder(Http::HttpClient* pHttpClient, const Settings& settings); + ~DigooRecorder(); + + virtual std::string Snapshot(ctpl::thread_pool* pThreadPool) override; + virtual std::string Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) override; + +private: + Http::HttpClient* m_pHttpClient; + Settings m_settings; +}; + +} // namespace Recorder +} // namespace CameraRecorder + +#endif // RECORDER_DIGOORECORDER_H diff --git a/Recorder/FoscamRecorder.cpp b/Recorder/FoscamRecorder.cpp new file mode 100644 index 0000000..86a4e55 --- /dev/null +++ b/Recorder/FoscamRecorder.cpp @@ -0,0 +1,71 @@ +#include "FoscamRecorder.h" +#include "Util.h" +#include +#include +#include +#include +#include + + +namespace CameraRecorder { +namespace Recorder { + +FoscamRecorder::FoscamRecorder(Http::HttpClient* pHttpClient, const Settings& settings) : + m_pHttpClient(pHttpClient), + m_settings(settings) +{ +} + +FoscamRecorder::~FoscamRecorder() +{ +} + +std::string FoscamRecorder::Snapshot(ctpl::thread_pool* pThreadPool) +{ + Logging::Log(Logging::Severity::Debug, "FoscamRecorder Snapshot"); + std::stringstream url; + url << "http://" << m_settings.IpAddress << ":" << m_settings.Port << "/cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=" << m_settings.Username << "&pwd=" << m_settings.Password; + + std::stringstream fileName; + fileName << m_settings.Path << "/" << m_settings.IpAddress << "/" << GetDateTimeString() << ".jpg"; + + try + { + std::ofstream file(fileName.str()); + file << m_pHttpClient->GetUrlContents(url.str()); + file.close(); + } + catch (const std::exception& e) + { + std::stringstream ss; + ss << "CameraDevice::PerformFoscamAction() - Error: " << e.what() << std::endl; + Logging::Log(Logging::Severity::Error, ss.str()); + return std::string(); + } + + return fileName.str(); +} + +std::string FoscamRecorder::Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) +{ + Logging::Log(Logging::Severity::Debug, "FoscamRecorder Video"); + int port = 65534; + + std::stringstream url; + url << "rtsp://" << m_settings.Username << ":" << m_settings.Password << "@" << m_settings.IpAddress << ":" << port << "/videoSub"; + + std::stringstream fileName; + fileName << m_settings.Path << "/" << m_settings.IpAddress << "/" << GetDateTimeString() << ".mp4"; + + std::stringstream command; + command << ffmpeg << " -i \"" << url.str() << "\" -t 30 -c:v copy -an -strict experimental " << fileName.str() << " > /dev/null 2>&1"; + + std::string cmd(command.str()); + Logging::Log(Logging::Severity::Debug, cmd); + pThreadPool->push( [cmd](int) { int retval = std::system(cmd.c_str()); } ); + + return fileName.str(); +} + +} // namespace Recorder +} // namespace CameraRecorder diff --git a/Recorder/FoscamRecorder.h b/Recorder/FoscamRecorder.h new file mode 100644 index 0000000..fb5555d --- /dev/null +++ b/Recorder/FoscamRecorder.h @@ -0,0 +1,34 @@ +#ifndef RECORDER_FOSCAMRECORDER_H +#define RECORDER_FOSCAMRECORDER_H + +#include "Recorder.h" +#include "Settings.h" + + +namespace Http { + +class HttpClient; + +} // namespace Http + +namespace CameraRecorder { +namespace Recorder { + +class FoscamRecorder : public virtual Recorder +{ +public: + FoscamRecorder(Http::HttpClient* pHttpClient, const Settings& settings); + ~FoscamRecorder(); + + virtual std::string Snapshot(ctpl::thread_pool* pThreadPool) override; + virtual std::string Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) override; + +private: + Http::HttpClient* m_pHttpClient; + Settings m_settings; +}; + +} // namespace Recorder +} // namespace CameraRecorder + +#endif // RECORDER_FOSCAMRECORDER_H diff --git a/Recorder/Makefile b/Recorder/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/Recorder/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/Recorder/Recorder.cpp b/Recorder/Recorder.cpp new file mode 100644 index 0000000..6ed4850 --- /dev/null +++ b/Recorder/Recorder.cpp @@ -0,0 +1,16 @@ +#include "Recorder.h" + + +namespace CameraRecorder { +namespace Recorder { + +Recorder::Recorder() +{ +} + +Recorder::~Recorder() +{ +} + +} // namespace Recorder +} // namespace CameraRecorder diff --git a/Recorder/Recorder.h b/Recorder/Recorder.h new file mode 100644 index 0000000..7200ebf --- /dev/null +++ b/Recorder/Recorder.h @@ -0,0 +1,24 @@ +#ifndef RECORDER_RECORDER_H +#define RECORDER_RECORDER_H + +#include +#include + + +namespace CameraRecorder { +namespace Recorder { + +class Recorder +{ +public: + Recorder(); + ~Recorder(); + + virtual std::string Snapshot(ctpl::thread_pool* pThreadPool) = 0; + virtual std::string Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) = 0; +}; + +} // namespace Recorder +} // namespace CameraRecorder + +#endif // RECORDER_RECORDER_H diff --git a/Recorder/Settings.h b/Recorder/Settings.h new file mode 100644 index 0000000..769b9c8 --- /dev/null +++ b/Recorder/Settings.h @@ -0,0 +1,22 @@ +#ifndef RECORDER_SETTINGS_H +#define RECORDER_SETTINGS_H + +#include + + +namespace CameraRecorder { +namespace Recorder { + +struct Settings +{ + std::string Path; + std::string IpAddress; + std::string Port; + std::string Username; + std::string Password; +}; + +} // namespace Recorder +} // namespace CameraRecorder + +#endif // RECORDER_SETTINGS_H diff --git a/Recorder/Util.cpp b/Recorder/Util.cpp new file mode 100644 index 0000000..78bfbd7 --- /dev/null +++ b/Recorder/Util.cpp @@ -0,0 +1,25 @@ +#include "Util.h" +#include +#include + + +namespace CameraRecorder { +namespace Recorder { + +std::string GetDateTimeString(bool omitSeparator) +{ + std::array buffer; + buffer.fill(0); + std::time_t t = std::time(nullptr); + std::tm* tm = std::localtime(&t); + + if (omitSeparator) + strftime(buffer.data(), sizeof(buffer), "%Y%m%d%H%M%S", tm); + else + strftime(buffer.data(), sizeof(buffer), "%Y%m%d-%H%M%S", tm); + + return buffer.data(); +} + +} // namespace Recorder +} // namespace CameraRecorder diff --git a/Recorder/Util.h b/Recorder/Util.h new file mode 100644 index 0000000..6cfd777 --- /dev/null +++ b/Recorder/Util.h @@ -0,0 +1,15 @@ +#ifndef RECORDER_UTIL_H +#define RECORDER_UTIL_H + +#include + + +namespace CameraRecorder { +namespace Recorder { + +std::string GetDateTimeString(bool omitSeparator = false); + +} // namespace Recorder +} // namespace CameraRecorder + +#endif // RECORDER_UTIL_H diff --git a/Recorder/VStarCamRecorder.cpp b/Recorder/VStarCamRecorder.cpp new file mode 100644 index 0000000..f2c85b5 --- /dev/null +++ b/Recorder/VStarCamRecorder.cpp @@ -0,0 +1,74 @@ +#include "VStarCamRecorder.h" +#include "Util.h" +#include +#include +#include +#include + + +namespace CameraRecorder { +namespace Recorder { + +VStarCamRecorder::VStarCamRecorder(Http::HttpClient* pHttpClient, const Settings& settings) : + m_pHttpClient(pHttpClient), + m_settings(settings) +{ +} + +VStarCamRecorder::~VStarCamRecorder() +{ +} + +std::string VStarCamRecorder::Snapshot(ctpl::thread_pool* pThreadPool) +{ + Logging::Log(Logging::Severity::Debug, "VStarCamRecorder Snapshot"); + std::stringstream url; + url << "http://" << m_settings.Username << ":" << m_settings.Password << "@" << m_settings.IpAddress << ":" << m_settings.Port << "/img/snapshot.cgi?res=0"; + + std::stringstream fileName; + fileName << m_settings.Path << "/" << m_settings.IpAddress << "/VSTA000000XXXXX_0_" << GetDateTimeString(true); + + int i = 0; + while (i < 3) + { + try + { + std::ofstream file(fileName.str() + "_" + std::to_string(i) + ".jpg"); + file << m_pHttpClient->GetUrlContents(url.str()); + file.close(); + } + catch (const std::exception& e) + { + std::stringstream ss; + ss << "CameraDevice::PerformVStarCamAction() - Error: " << e.what() << std::endl; + Logging::Log(Logging::Severity::Error, ss.str()); + } + ++i; + } + + return fileName.str() + "_0.jpg"; +} + +std::string VStarCamRecorder::Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) +{ + Logging::Log(Logging::Severity::Debug, "VStarCamRecorder Video"); + int port = 10554; + + std::stringstream url; + url << "rtsp://" << m_settings.Username << ":" << m_settings.Password << "@" << m_settings.IpAddress << ":" << port << "/udp/av0_0"; + + std::stringstream fileName; + fileName << m_settings.Path << "/" << m_settings.IpAddress << "/VSTA000000XXXXX_0_" << GetDateTimeString(true) << ".mp4"; + + std::stringstream command; + command << ffmpeg << " -i \"" << url.str() << "\" -t 30 -c:v copy -c:a aac -b:a 8k -strict experimental " << fileName.str() << " > /dev/null 2>&1"; + + std::string cmd(command.str()); + Logging::Log(Logging::Severity::Debug, cmd); + pThreadPool->push( [cmd](int) { int retval = std::system(cmd.c_str()); } ); + + return fileName.str(); +} + +} // namespace Recorder +} // namespace CameraRecorder diff --git a/Recorder/VStarCamRecorder.h b/Recorder/VStarCamRecorder.h new file mode 100644 index 0000000..0398390 --- /dev/null +++ b/Recorder/VStarCamRecorder.h @@ -0,0 +1,34 @@ +#ifndef RECORDER_VSTARCAMRECORDER_H +#define RECORDER_VSTARCAMRECORDER_H + +#include "Recorder.h" +#include "Settings.h" + + +namespace Http { + +class HttpClient; + +} // namespace Http + +namespace CameraRecorder { +namespace Recorder { + +class VStarCamRecorder : public virtual Recorder +{ +public: + VStarCamRecorder(Http::HttpClient* pHttpClient, const Settings& settings); + ~VStarCamRecorder(); + + virtual std::string Snapshot(ctpl::thread_pool* pThreadPool) override; + virtual std::string Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) override; + +private: + Http::HttpClient* m_pHttpClient; + Settings m_settings; +}; + +} // namespace Recorder +} // namespace CameraRecorder + +#endif // RECORDER_VSTARCAMRECORDER_H diff --git a/Recorder/WatchBotRecorder.cpp b/Recorder/WatchBotRecorder.cpp new file mode 100644 index 0000000..713d62a --- /dev/null +++ b/Recorder/WatchBotRecorder.cpp @@ -0,0 +1,71 @@ +#include "WatchBotRecorder.h" +#include "Util.h" +#include +#include +#include +#include + + +namespace CameraRecorder { +namespace Recorder { + +WatchBotRecorder::WatchBotRecorder(Http::HttpClient* pHttpClient, const Settings& settings) : + m_pHttpClient(pHttpClient), + m_settings(settings) +{ +} + +WatchBotRecorder::~WatchBotRecorder() +{ +} + +std::string WatchBotRecorder::Snapshot(ctpl::thread_pool* pThreadPool) +{ + Logging::Log(Logging::Severity::Debug, "WatchBotRecorder Snapshot"); + std::stringstream url; + url << "http://" << m_settings.IpAddress << ":" << m_settings.Port << "/snapshot.cgi?user=" << m_settings.Username << "&pwd=" << m_settings.Password; + + std::stringstream fileName; + fileName << m_settings.Path << "/" << m_settings.IpAddress << "/" << GetDateTimeString() << ".jpg"; + + try + { + std::ofstream file(fileName.str()); + file << m_pHttpClient->GetUrlContents(url.str()); + file.close(); + } + catch (const std::exception& e) + { + std::stringstream ss; + ss << "CameraDevice::PerformWatchBotAction() - Error: " << e.what() << std::endl; + Logging::Log(Logging::Severity::Error, ss.str()); + return std::string(); + } + + return fileName.str(); +} + +std::string WatchBotRecorder::Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) +{ + Logging::Log(Logging::Severity::Debug, "WatchBotRecorder Video"); +/* + std::stringstream url; + url << "http://" << m_settings.IpAddress << ":" << m_settings.Port << "/videostream.asf?user=" << m_settings.Username << "&pwd=" << m_settings.Password << "&resolution=64&rate=0"; + + std::stringstream fileName; + fileName << m_settings.Path << "/" << m_settings.IpAddress << "/" << GetDateTimeString() << ".mp4"; + + std::stringstream command; + command << "ffmpeg -i \"" << url.str() << "\" -t 30 -c:v copy -c:a aac -b:a 8k -strict experimental " << fileName.str() << " > /dev/null 2>&1"; + + std::string cmd(command.str()); + Logging::Log(Logging::Severity::Debug, cmd); + pThreadPool->push( [cmd](int) { int retval = std::system(cmd.c_str()); } ); + + return fileName.str(); +*/ + return std::string(); +} + +} // namespace Recorder +} // namespace CameraRecorder diff --git a/Recorder/WatchBotRecorder.h b/Recorder/WatchBotRecorder.h new file mode 100644 index 0000000..7625512 --- /dev/null +++ b/Recorder/WatchBotRecorder.h @@ -0,0 +1,34 @@ +#ifndef RECORDER_WATCHBOTRECORDER_H +#define RECORDER_WATCHBOTRECORDER_H + +#include "Recorder.h" +#include "Settings.h" + + +namespace Http { + +class HttpClient; + +} // namespace Http + +namespace CameraRecorder { +namespace Recorder { + +class WatchBotRecorder : public virtual Recorder +{ +public: + WatchBotRecorder(Http::HttpClient* pHttpClient, const Settings& settings); + ~WatchBotRecorder(); + + virtual std::string Snapshot(ctpl::thread_pool* pThreadPool) override; + virtual std::string Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) override; + +private: + Http::HttpClient* m_pHttpClient; + Settings m_settings; +}; + +} // namespace Recorder +} // namespace CameraRecorder + +#endif // RECORDER_WATCHBOTRECORDER_H diff --git a/Recorder/ZModoRecorder.cpp b/Recorder/ZModoRecorder.cpp new file mode 100644 index 0000000..5f3d10d --- /dev/null +++ b/Recorder/ZModoRecorder.cpp @@ -0,0 +1,32 @@ +#include "ZModoRecorder.h" +#include +#include + + +namespace CameraRecorder { +namespace Recorder { + +ZModoRecorder::ZModoRecorder(Http::HttpClient* pHttpClient, const Settings& settings) : + m_pHttpClient(pHttpClient), + m_settings(settings) +{ +} + +ZModoRecorder::~ZModoRecorder() +{ +} + +std::string ZModoRecorder::Snapshot(ctpl::thread_pool* pThreadPool) +{ + Logging::Log(Logging::Severity::Debug, "ZModoRecorder Snapshot"); + return std::string(); +} + +std::string ZModoRecorder::Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) +{ + Logging::Log(Logging::Severity::Debug, "ZModoRecorder Video"); + return std::string(); +} + +} // namespace Recorder +} // namespace CameraRecorder diff --git a/Recorder/ZModoRecorder.h b/Recorder/ZModoRecorder.h new file mode 100644 index 0000000..2997f3a --- /dev/null +++ b/Recorder/ZModoRecorder.h @@ -0,0 +1,34 @@ +#ifndef RECORDER_ZMODORECORDER_H +#define RECORDER_ZMODORECORDER_H + +#include "Recorder.h" +#include "Settings.h" + + +namespace Http { + +class HttpClient; + +} // namespace Http + +namespace CameraRecorder { +namespace Recorder { + +class ZModoRecorder : public virtual Recorder +{ +public: + ZModoRecorder(Http::HttpClient* pHttpClient, const Settings& settings); + ~ZModoRecorder(); + + virtual std::string Snapshot(ctpl::thread_pool* pThreadPool) override; + virtual std::string Video(ctpl::thread_pool* pThreadPool, const std::string& ffmpeg) override; + +private: + Http::HttpClient* m_pHttpClient; + Settings m_settings; +}; + +} // namespace Recorder +} // namespace CameraRecorder + +#endif // RECORDER_ZMODORECORDER_H