changed a whole lot, added motion, refactoring

master
Tibor 10 months ago
parent bb97cf2cdc
commit 04a05f87a4
  1. 6
      config.cpp
  2. 124
      heimdall.cpp
  3. 13
      heimdall.example.cfg
  4. 14
      heimdall.h
  5. 8
      heimdall.vcxproj
  6. 1
      log.h
  7. 6
      main.cpp
  8. 87
      mqttClient.cpp
  9. 2
      script/openDoor.py
  10. BIN
      sounds/ding.wav
  11. BIN
      sounds/notAtHome.wav
  12. BIN
      sounds/onOurWay.wav

@ -60,7 +60,11 @@ config::config(const std::vector<std::string>& options)
auto config::options(const std::string& o) -> const std::string&
{
return _options.at(o);
if (_options.find(o) != _options.end()) {
return _options.at(o);
}
return {};
}
auto config::optionsVec(const std::string& o) -> std::vector<std::string>

@ -27,14 +27,19 @@ heimdall::heimdall(uint8_t gpio_button, uint8_t gpio_opener, std::shared_ptr<tai
registerMqttListener();
// button push function hook
const PictureType pictureType { _conf->options("pictureType") == "motion" ? PictureType::MOTION : PictureType::RASPISTILL };
#ifndef DEBUG_TAI
_btn->f_pushed = [&]() {
if (_btn->is_on()) {
#endif
startMqttAndPlaySound();
takePictureAndSend(_conf->optionsVec("tg_chatIds"));
takePicture(
pictureType,
_conf->optionsVec("tg_chatIds"),
_conf->options("tg_notify") == "true"
);
#ifndef DEBUG_TAI
}
@ -74,37 +79,30 @@ heimdall::~heimdall()
*/
void heimdall::startMqttAndPlaySound()
{
// @TODO change cmdMosquittoPub to usage of mqttClient class
// mosquitto publishing shell command
std::string cmdMosquittoPub {
"mosquitto_pub -h " + _conf->options("mqttHost") +
" -t " + _conf->options("mqttTopic") +
" -m " + _conf->options("mqttToken") + _conf->options("mqttMessage")
};
// door opening. @TODO remove
if (_conf->options("openOnButtonPush") == "true") {
_opener->off(std::chrono::milliseconds(100));
_opener->off(std::chrono::milliseconds(500));
}
// only used when tg_notify is set to "true" in .cfg file
std::string cmdNotifyOnTelegram {};
// sound playback shell command
std::string cmdPlaySound { "aplay " + _conf->options("soundFilePath") };
// Telegram notification
std::string message { _conf->options("tg_notifMessage")};
std::string telegramBotId { _conf->options("tg_botId") };
std::vector<std::string> telegramChatIds { _conf->optionsVec("tg_chatIds") };
std::string cmdNotifyOnTelegram;
if (_conf->options("tg_notify") == "true") {
// Telegram notification
std::string message { _conf->options("tg_notifMessage") };
std::string telegramBotId { _conf->options("tg_botId") };
std::vector<std::string> telegramChatIds { _conf->optionsVec("tg_chatIds") };
for (const std::string& id : telegramChatIds) {
// notification command
cmdNotifyOnTelegram.append(_prepareTelegramMsg(id, message));
for (const std::string& id : telegramChatIds) {
// notification command
cmdNotifyOnTelegram.append(_prepareTelegramMsg(id, message));
// irgendwie so
if (id != telegramChatIds.back()) {
cmdNotifyOnTelegram.append(" && ");
// irgendwie so
if (id != telegramChatIds.back()) {
cmdNotifyOnTelegram.append(" && ");
}
}
}
@ -114,7 +112,7 @@ void heimdall::startMqttAndPlaySound()
LOG_INF("[HD] Button was pushed!");
// execute mqtt publishing async
launcher.go(cmdMosquittoPub);
_mqttClient->send(_conf->options("mqttToken") + _conf->options("mqttMessage"));
LOG_DBG("[HD] Creating thread for sound playback: " + cmdPlaySound);
// execute sound playback async
@ -122,40 +120,56 @@ void heimdall::startMqttAndPlaySound()
#endif
// @TODO if (telegramNotificationEnabled in config)
LOG_DBG("[HD] Creating thread for Telegram notification: " + cmdNotifyOnTelegram);
launcher.go(cmdNotifyOnTelegram);
if (_conf->options("tg_notify") == "true") {
LOG_DBG("[HD] Creating thread for Telegram notification: " + cmdNotifyOnTelegram);
launcher.go(cmdNotifyOnTelegram);
}
}
/**
* @brief Takes a picture using raspistill and sends it via Telegram
*/
void heimdall::takePictureAndSend(const std::vector<std::string>& recipients)
* @brief Triggers a picture taking command using either raspistill or motion and saves it as {pictureName}.jpg
*/
void heimdall::takePicture(PictureType type, std::vector<std::string> const& recipients, bool notifyOnTelegram)
{
std::string quality { "80" };
std::string delay { "1s" };
std::string rotation { "270" };
std::string iso { "600" };
std::string width { "600" };
std::string height { "800" };
std::string pictureName { "door.jpg" };
std::string cmd {
"raspistill -q " + quality +
" -t " + delay +
" --rotation " + rotation +
" -ISO " + iso +
" -w " + width +
" -h " + height +
" -o " + pictureName
};
/* We are appending the commands to the picture taking process
* since we are using threads but not futures so we don't know
* when the picture taking process is done.
*/
for (auto const& recipient : recipients) {
cmd.append(" && " + _prepareTelegramPhoto(recipient, "./" + pictureName));
std::string cmd {};
switch (type) {
case PictureType::RASPISTILL:
{
std::string quality { "80" };
std::string delay { "1s" };
std::string rotation { "270" };
std::string iso { "600" };
std::string width { "600" };
std::string height { "800" };
cmd = "raspistill -q " + quality +
" -t " + delay +
" --rotation " + rotation +
" -ISO " + iso +
" -w " + width +
" -h " + height +
" -o " + pictureName;
break;
}
case PictureType::MOTION:
{
cmd = "curl -o door.jpg " + _conf->options("motion_webcamUrl") + "?api_key=" + _conf->options("motion_apiKey");
}
default:
break;
}
if (notifyOnTelegram) {
/* We are appending the commands to the picture taking process
* since we are using threads but not futures so we don't know
* when the picture taking process is done.
*/
for (auto const& recipient : recipients) {
cmd.append(" && " + _prepareTelegramPhoto(recipient, "./" + pictureName));
}
}
threadLauncher::inst().go(cmd);

@ -6,6 +6,7 @@ mqttClientId = "1";
mqttHost = "my.mqtthost.org";
mqttPort = "1883";
mqttTopic = "every/thing/#";
mqttToken = "mySuP3rstr0ngT0k3n_"
mqttMessage = "dingdong";
# sound vars
@ -15,10 +16,20 @@ soundFilePath = "/home/myuser/dingdong.wav";
rtspServerHome = "/home/myuser/rtsp/";
# Telegram stuff
tg_notify = "true";
tg_notifMessage = "Hello, ding dong! Take a look.";
tg_botId = "bot1234567890:ABCdEF-Gh1IjKlMNOpQ2RsTuvWx_3YZabCd";
tg_chatIds = [
"12345678",
"901234567",
"890123456"
];
];
# diverse stuff
openOnButtonPush = "false";
# webcam configuration (self-implemented)
# picture type. types: [motion, raspistill]
pictureType = "raspistill";
motion_webcamUrl = "http://localhost:8080";
motion_apiKey = "myweirdapikey";

@ -21,14 +21,26 @@ namespace tai {
class heimdall
{
public:
/**
* @brief the PictureType "motion" uses a self-implemented way of returning the webcam
* picture using motion and some self-written php functions. Please consider using "raspistill"
* as your default picture type.
*/
enum class PictureType
{
RASPISTILL = 0,
MOTION
};
explicit heimdall(uint8_t gpio, uint8_t gpio_opener, std::shared_ptr<tai::config> conf);
~heimdall();
// methods
void startMqttAndPlaySound();
void takePictureAndSend(const std::vector<std::string>&);
void takePicture(PictureType type, std::vector<std::string> const& chat_id, bool notify_on_telegram);
void registerMqttListener();
std::shared_ptr<mqttClient> getMqttClient() { return _mqttClient; };
std::shared_ptr<tai::config> getConfig() { return _conf; };
private:
// members

@ -98,7 +98,7 @@
<AdditionalSourcesToCopyMapping>heimdall.cfg:=projects/$(RemoteOutRelDir)/heimdall.cfg;sounds/ding.wav:=projects/$(RemoteOutRelDir)/sounds/ding.wav;sounds/notAtHome.wav:=projects/$(RemoteOutRelDir)/sounds/notAtHome.wav;sounds/onOurWay.wav:=projects/$(RemoteOutRelDir)/sounds/onOurWay.wav;script/openDoor.py:=projects/$(RemoteOutRelDir)/script/openDoor.py</AdditionalSourcesToCopyMapping>
</PostBuildEvent>
<RemotePreBuildEvent>
<Command>rm $(RemoteOutDir)heimdall.cfg; if [ ! -d $(RemoteOutDir)sounds ]; then mkdir $(RemoteOutDir)sounds; fi; if [ ! -d $(RemoteOutDir)script ]; then mkdir $(RemoteOutDir)script; fi; </Command>
<Command>rm -f $(RemoteOutDir)heimdall.cfg; if [ ! -d $(RemoteOutDir)sounds ]; then mkdir $(RemoteOutDir)sounds; fi; if [ ! -d $(RemoteOutDir)script ]; then mkdir $(RemoteOutDir)script; fi; </Command>
</RemotePreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
@ -133,7 +133,7 @@
<AdditionalSourcesToCopyMapping>heimdall.cfg:=projects/$(RemoteOutRelDir)/heimdall.cfg;sounds/ding.wav:=projects/$(RemoteOutRelDir)/sounds/ding.wav;sounds/notAtHome.wav:=projects/$(RemoteOutRelDir)/sounds/notAtHome.wav;sounds/onOurWay.wav:=projects/$(RemoteOutRelDir)/sounds/onOurWay.wav;script/openDoor.py:=projects/$(RemoteOutRelDir)/script/openDoor.py</AdditionalSourcesToCopyMapping>
</PostBuildEvent>
<RemotePreBuildEvent>
<Command>rm $(RemoteOutDir)heimdall.cfg; if [ ! -d $(RemoteOutDir)sounds ]; then mkdir $(RemoteOutDir)sounds; fi; if [ ! -d $(RemoteOutDir)script ]; then mkdir $(RemoteOutDir)script; fi; </Command>
<Command>rm -f $(RemoteOutDir)heimdall.cfg; if [ ! -d $(RemoteOutDir)sounds ]; then mkdir $(RemoteOutDir)sounds; fi; if [ ! -d $(RemoteOutDir)script ]; then mkdir $(RemoteOutDir)script; fi; </Command>
</RemotePreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
@ -154,7 +154,7 @@
<AdditionalSourcesToCopyMapping>heimdall.cfg:=projects/$(RemoteOutRelDir)/heimdall.cfg;sounds/ding.wav:=projects/$(RemoteOutRelDir)/sounds/ding.wav;sounds/notAtHome.wav:=projects/$(RemoteOutRelDir)/sounds/notAtHome.wav;sounds/onOurWay.wav:=projects/$(RemoteOutRelDir)/sounds/onOurWay.wav;script/openDoor.py:=projects/$(RemoteOutRelDir)/script/openDoor.py</AdditionalSourcesToCopyMapping>
</PostBuildEvent>
<RemotePreBuildEvent>
<Command>rm $(RemoteOutDir)heimdall.cfg; if [ ! -d $(RemoteOutDir)sounds ]; then mkdir $(RemoteOutDir)sounds; fi; if [ ! -d $(RemoteOutDir)script ]; then mkdir $(RemoteOutDir)script; fi; </Command>
<Command>rm -f $(RemoteOutDir)heimdall.cfg; if [ ! -d $(RemoteOutDir)sounds ]; then mkdir $(RemoteOutDir)sounds; fi; if [ ! -d $(RemoteOutDir)script ]; then mkdir $(RemoteOutDir)script; fi; </Command>
</RemotePreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
@ -175,7 +175,7 @@
<AdditionalSourcesToCopyMapping>heimdall.cfg:=projects/$(RemoteOutRelDir)/heimdall.cfg;sounds/ding.wav:=projects/$(RemoteOutRelDir)/sounds/ding.wav;sounds/notAtHome.wav:=projects/$(RemoteOutRelDir)/sounds/notAtHome.wav;sounds/onOurWay.wav:=projects/$(RemoteOutRelDir)/sounds/onOurWay.wav;script/openDoor.py:=projects/$(RemoteOutRelDir)/script/openDoor.py</AdditionalSourcesToCopyMapping>
</PostBuildEvent>
<RemotePreBuildEvent>
<Command>rm $(RemoteOutDir)heimdall.cfg; if [ ! -d $(RemoteOutDir)sounds ]; then mkdir $(RemoteOutDir)sounds; fi; if [ ! -d $(RemoteOutDir)script ]; then mkdir $(RemoteOutDir)script; fi; </Command>
<Command>rm -f $(RemoteOutDir)heimdall.cfg; if [ ! -d $(RemoteOutDir)sounds ]; then mkdir $(RemoteOutDir)sounds; fi; if [ ! -d $(RemoteOutDir)script ]; then mkdir $(RemoteOutDir)script; fi; </Command>
</RemotePreBuildEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

@ -102,6 +102,5 @@ private:
#define LOG_WRN(x) tai::Log::logger().log(x, tai::Log::Level::WARNING)
#define LOG_ERR(x) tai::Log::logger().log(x, tai::Log::Level::ERROR)
#define LOG_FTL(x) tai::Log::logger().log(x, tai::Log::Level::FATAL)
#define LOG_UKN(x) tai::Log::logger().log(x, tai::Log::Level::UNKNOWN)
#endif // LOG_H

@ -26,10 +26,14 @@ int main(int argc, char* argv[]) {
"mqttMessage",
"soundFilePath",
"rtspServerHome",
"tg_notify",
"tg_notifMessage",
"tg_botId",
"tg_chatIds",
"openOnButtonPush"
"openOnButtonPush",
"pictureType",
"motion_apiKey",
"motion_webcamUrl"
};
std::shared_ptr<tai::config> conf { std::make_shared<tai::config>(configOptions) };

@ -3,6 +3,8 @@
#include "log.h"
#include "threadLauncher.h"
#include "heimdall.h"
namespace tai
{
@ -124,6 +126,10 @@ void mqttClient::on_message(const struct mosquitto_message* message)
LOG_INF("[MQTT] Triggering \"Open door\" procedure: " + openDoorCmd);
if (!send(_token + "triggeredOnOpenDoor")) {
LOG_WRN("[MQTT] Unable to send feedback message for trigger function.");
}
threadLauncher::inst().go(openDoorCmd);
}
@ -132,6 +138,10 @@ void mqttClient::on_message(const struct mosquitto_message* message)
LOG_INF("[MQTT] Triggering \"Not at home\" procedure: " + notAtHomeCmd);
if (!send(_token + "triggeredOnPlayNotAtHome")) {
LOG_WRN("[MQTT] Unable to send feedback message for trigger function.");
}
threadLauncher::inst().go(notAtHomeCmd);
}
@ -140,35 +150,66 @@ void mqttClient::on_message(const struct mosquitto_message* message)
LOG_INF("[MQTT] Triggering \"On our way\" procedure: " + onOurWayCmd);
if (!send(_token + "triggeredOnPlayOnOurWay")) {
LOG_WRN("[MQTT] Unable to send feedback message for trigger function.");
}
threadLauncher::inst().go(onOurWayCmd);
}
if (msg.find("onTakePicture") != std::string::npos) {
std::string chat_id { msg.substr(msg.find_last_of(':') + 1, msg.size() - 1) };
std::string quality { "80" };
std::string delay { "1s" };
std::string rotation { "270" };
std::string iso { "600" };
std::string width { "600" };
std::string height { "800" };
std::string pictureName { "door_manual.jpg" };
std::string cmd {
"raspistill -q " + quality +
" -t " + delay +
" --rotation " + rotation +
" -ISO " + iso +
" -w " + width +
" -h " + height +
" -o " + pictureName
};
cmd.append(" && ");
cmd.append("curl -s --location --request GET 'https://api.telegram.org/" + _conf->options("tg_botId") + "/sendPhoto?chat_id=" + chat_id + "' --form 'photo=@\"./" + pictureName + "\"' > /dev/null");
LOG_INF("[MQTT] Triggering picture record: " + cmd);
std::string chatId { msg.substr(msg.find_last_of(':') + 1, msg.size() - 1) };
LOG_INF("[MQTT] Triggering picture record for chat ID " + chatId);
std::string pictureName { "door.jpg" };
std::string cmd {};
heimdall::PictureType type =
_conf->options("pictureType") == "raspistill"
? heimdall::PictureType::RASPISTILL
: heimdall::PictureType::MOTION;
switch (type) {
case heimdall::PictureType::RASPISTILL:
{
std::string quality{ "80" };
std::string delay{ "1s" };
std::string rotation{ "270" };
std::string iso{ "600" };
std::string width{ "600" };
std::string height{ "800" };
cmd = "raspistill -q " + quality +
" -t " + delay +
" --rotation " + rotation +
" -ISO " + iso +
" -w " + width +
" -h " + height +
" -o " + pictureName;
break;
}
case heimdall::PictureType::MOTION:
{
cmd = "curl -o door.jpg " + _conf->options("motion_webcamUrl") + "?api_key=" + _conf->options("motion_apiKey");
}
default:
break;
}
bool notifyOnTelegram = _conf->options("tg_notify") == "true";
if (notifyOnTelegram) {
std::string appCmd("curl -s --location --request GET 'https://api.telegram.org/" + _conf->options("tg_botId") + "/sendPhoto?chat_id=" + chatId + "' --form 'photo=@\"" + pictureName + "\"' > /dev/null");
cmd.append(" && " + appCmd);
}
threadLauncher::inst().go(cmd);
if (!send(_token + "triggeredOnTakePicture")) {
LOG_WRN("[MQTT] Unable to send feedback message for trigger function.");
}
}
}

@ -6,5 +6,5 @@ GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
GPIO.output(12, False)
time.sleep(0.1)
time.sleep(0.5)
GPIO.output(12, True)

Binary file not shown.

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save