Added db logger functions. Chnaged to newest mqtt++ version.

This commit is contained in:
2020-11-17 10:08:34 +01:00
parent 0fff81be48
commit 2cb0fd1fed
14 changed files with 261 additions and 39 deletions

View File

@@ -9,9 +9,10 @@ find_package(spdlog CONFIG REQUIRED)
find_package(OpenSSL REQUIRED)
include(FindLua)
find_package(lua REQUIRED)
find_package(InfluxDB REQUIRED)
find_package(eclipse-paho-mqtt-c CONFIG REQUIRED)
add_executable(thrawn src/main.cpp src src/thrawn_api.cpp src/Service.cpp src/Cache.cpp src/LuaEngine.cpp lib/mqtt++/src/mqtt++.cpp)
target_link_libraries(thrawn ${LIBS} spdlog::spdlog ${LUA_LIBRARIES} OpenSSL::SSL eclipse-paho-mqtt-c::paho-mqtt3cs-static)
add_executable(thrawn src/main.cpp src src/thrawn_api.cpp src/thrawn_api_db_logger.cpp src/Service.cpp src/Cache.cpp src/LuaEngine.cpp lib/mqtt++/src/mqtt++.cpp src/DBLogger.cpp)
target_link_libraries(thrawn ${LIBS} spdlog::spdlog InfluxData::InfluxDB ${LUA_LIBRARIES} OpenSSL::SSL eclipse-paho-mqtt-c::paho-mqtt3cs-static)
target_include_directories(thrawn PRIVATE ${LUA_INCLUDE_DIR})
install(TARGETS thrawn DESTINATION bin)

View File

@@ -1,22 +1,19 @@
#include "Cache.h"
#include <algorithm>
std::vector<TopicState> Cache::topic_states(std::vector<std::string>& topics) {
std::vector<TopicState> states;
for (const auto& topic : topics) {
auto hit = std::find_if(cache.begin(), cache.end(), [&](TopicState& cache_state) {
return cache_state.topic == topic;
});
if (hit != cache.end()) {
states.push_back(*hit);
#include "mqtt++.h"
#include <iostream>
std::optional<std::string> Cache::cached_topic_value(const std::string& topic) {
for (const auto& state : m_cache) {
if (state.topic == topic) {
return state.value;
}
}
return states;
return std::nullopt;
}
TopicState Cache::set_topic_value(const std::string& topic, const std::string& value) {
for (auto& state : cache) {
for (auto& state : m_cache) {
if (state.topic == topic) {
state.value = value;
@@ -24,5 +21,5 @@ TopicState Cache::set_topic_value(const std::string& topic, const std::string& v
}
}
return cache.emplace_back(topic, value);
return m_cache.emplace_back(topic, value);
}

View File

@@ -3,12 +3,13 @@
#include <string>
#include <vector>
#include "Service.h"
#include <optional>
class Cache {
private:
std::vector<TopicState> cache;
std::vector<TopicState> m_cache;
public:
std::vector<TopicState> topic_states(std::vector<std::string>& topics);
TopicState set_topic_value(const std::string& topic, const std::string& value);
std::optional<std::string> cached_topic_value(const std::string& topic);
};
#endif // CACHE_H

53
src/DBLogger.cpp Normal file
View File

@@ -0,0 +1,53 @@
/*
auto influxdb =
influxdb->write(influxdb::Point{"test"}
.addField("value2", "mu")
.addTag("host", "localhost")
);
*/
#include "DBLogger.h"
#include "InfluxDBFactory.h"
#include "spdlog/spdlog.h"
//url = http://localhost:8086
//databse = test
DBLogger::DBLogger(const std::string& url, const std::string& database) {
m_influx = influxdb::InfluxDBFactory::Get(url + "/?db=" + database);
}
void DBLogger::write_light(const std::string_view room, const std::string_view name, const bool is_on) {
try {
m_influx->write(influxdb::Point("light")
.addTag("room", room)
.addTag("name", name)
.addField("on", is_on ? 1 : 0));
}catch (const std::exception& e) {
spdlog::error("Could not perform influx write for '{}' in room '{}'", room, name);
}
}
void DBLogger::write_light_dimmable(const std::string_view room, const std::string_view name, const bool is_on, const int brightness) {
try {
m_influx->write(influxdb::Point("light")
.addTag("room", room)
.addTag("name", name)
.addField("on", is_on ? 1 : 0)
.addField("brightness", brightness));
}catch (const std::exception& e) {
spdlog::error("Could not perform influx write for '{}' in room '{}'", room, name);
}
}
void DBLogger::write_light_tuneable_white(const std::string_view room, const std::string_view name, const bool is_on, const int brightness, const int color_temperature) {
try {
m_influx->write(influxdb::Point("light")
.addTag("room", room)
.addTag("name", name)
.addField("on", is_on ? 1 : 0)
.addField("brightness", brightness)
.addField("color_temp", color_temperature));
}catch (const std::exception& e) {
spdlog::error("Could not perform influx write for '{}' in room '{}'", room, name);
}
}

20
src/DBLogger.h Normal file
View File

@@ -0,0 +1,20 @@
#if !defined(DBLOGGER_H)
#define DBLOGGER_H
#include <string>
#include "InfluxDB.h"
#include <memory>
#include <string_view>
class DBLogger {
private:
std::unique_ptr<influxdb::InfluxDB> m_influx;
public:
void write_light(const std::string_view room, const std::string_view name, const bool is_on);
void write_light_dimmable(const std::string_view room, const std::string_view name, const bool is_on, const int brightness);
void write_light_tuneable_white(const std::string_view room, const std::string_view name, const bool is_on, const int brightness, const int color_temperature);
DBLogger(const std::string& url, const std::string& database);
};
#endif // DBLOGGER_H

View File

@@ -1,7 +1,6 @@
#include "LuaEngine.h"
LuaEngine::LuaEngine() {
}
LuaEngine::LuaEngine() : db_logger("http://localhost:8086", "test") {}
void LuaEngine::load_services() {
for (auto& service : services) {

View File

@@ -5,12 +5,15 @@
#include <vector>
#include <functional>
#include <string>
#include "DBLogger.h"
class LuaEngine {
private:
LuaEngine();
public:
std::function<void(const TopicState& state)> publish;
DBLogger db_logger;
static LuaEngine& get_instance() {
static LuaEngine instance;
@@ -24,9 +27,34 @@ class LuaEngine {
void start_services();
LuaService* create_service(std::string filename);
LuaService* service_by_lua_state(lua_State* lua);
LuaEngine(LuaEngine const&) = delete;
void operator=(LuaEngine const&) = delete;
};
template<typename Arg, typename... Args>
inline bool check_arguments(lua_State* lua, int stack_pos) {
return check_arguments<Args...>(lua, stack_pos+1) && check_arguments<Arg>(lua, stack_pos);
}
template<typename Arg, typename... Args>
inline bool check_arguments(lua_State* lua) {
int num_arg = sizeof...(Args) + 1;
return check_arguments<Arg, Args...>(lua, num_arg * -1);
}
template <>
inline bool check_arguments<std::string>(lua_State* lua, int stack_pos) {
return lua_isstring(lua, stack_pos);
}
template <>
inline bool check_arguments<int>(lua_State* lua, int stack_pos) {
return lua_isnumber(lua, stack_pos);
}
template <>
inline bool check_arguments<bool>(lua_State* lua, int stack_pos) {
return lua_isnumber(lua, stack_pos);
}
#endif // LUA_ENGINE_H

View File

@@ -57,8 +57,21 @@ LuaService::LuaService(std::string filename) {
lua_pushcfunction(lua, thrawn_topic_state_str);
lua_setglobal(lua, "thrawn_topic_state_str");
lua_pushcfunction(lua, thrawn_topic_cache);
lua_setglobal(lua, "thrawn_topic_cache");
lua_pushcfunction(lua, thrawn_cached_topic);
lua_setglobal(lua, "thrawn_cached_topic");
lua_pushcfunction(lua, thrawn_topic_components);
lua_setglobal(lua, "thrawn_topic_components");
lua_pushcfunction(lua, thrawn_log_light);
lua_setglobal(lua, "thrawn_log_light");
lua_pushcfunction(lua, thrawn_log_light_dimmable);
lua_setglobal(lua, "thrawn_log_light_dimmable");
lua_pushcfunction(lua, thrawn_log_light_tw);
lua_setglobal(lua, "thrawn_log_light_tw");
if (luaL_loadfile(lua, filename.c_str()) != 0) {

View File

@@ -3,6 +3,6 @@
#define THRAWN_MAJOR_VERSION 1
#define THRAWN_MINOR_VERSION 0
#define THRAWN_PATCH_VERSION 4
#define THRAWN_PATCH_VERSION 5
#endif // VERSION_H

View File

@@ -39,7 +39,6 @@ int main(int argc, char* argv[]) {
std::string version_topic_value = std::to_string(THRAWN_MAJOR_VERSION) + "." + std::to_string(THRAWN_MINOR_VERSION) + "." + std::to_string(THRAWN_PATCH_VERSION);
std::string lastWillConnected = "1";
/*
* Parsing arguments
* Show version or load path
@@ -69,12 +68,12 @@ int main(int argc, char* argv[]) {
mqtt.publish(last_will.topic, lastWillConnected);
mqtt.publish(version_topic, version_topic_value);
mqtt.subscribe("#", [&] (const char* topic, const std::string& msg) {
mqtt.subscribe("#", [&] (const std::string& topic, const std::string& msg) {
LuaEngine::get_instance().cache.set_topic_value(topic, msg);
for (auto& service : LuaEngine::get_instance().services) {
for (const std::string& sub_topic : service.subscriptions) {
if (sub_topic == topic) {
if (mqttpp::sub_matches_topic(sub_topic, topic)) {
service.on_update(TopicState(topic, msg));
}
}

View File

@@ -3,7 +3,7 @@
#include "Cache.h"
#include "LuaEngine.h"
#include "spdlog/spdlog.h"
#include <sstream>
/*
HELPER
*/
@@ -23,8 +23,8 @@ void push_list_topic_state(lua_State* lua, std::vector<TopicState> states) {
int i = 1;
for (auto& state : states) {
lua_pushinteger(lua, i);
push_topic_state_table(lua, state);
lua_pushstring(lua, state.topic.c_str());
lua_pushstring(lua, state.value.c_str());
lua_settable(lua, -3);
i++;
@@ -39,9 +39,9 @@ int thrawn_log(lua_State* lua)
if(paramCount != 1)
{
return -1;
}
}
if (!lua_isstring (lua, -1)) {
if (!check_arguments<std::string>(lua)) {
return -1;
}
@@ -135,20 +135,58 @@ int thrawn_subscribe(lua_State* lua) {
return 0;
}
int thrawn_topic_cache(lua_State* lua) {
int thrawn_cached_topic(lua_State* lua) {
int paramCount = lua_gettop(lua);
if(paramCount != 0){
if (paramCount != 1){
return -1;
}
LuaEngine& lua_engine = LuaEngine::get_instance();
LuaService* service = lua_engine.service_by_lua_state(lua);
if (!lua_isstring(lua, -1)) {
return -1;
}
push_list_topic_state(lua, lua_engine.cache.topic_states(service->subscriptions));
const auto& cached_value = LuaEngine::get_instance().cache.cached_topic_value(lua_tostring(lua, -1));
return 1;
if (cached_value) {
lua_pushstring(lua, cached_value.value().c_str());
}else {
lua_pushnil(lua);
}
return 1;
}
int thrawn_topic_components(lua_State* lua) {
int paramCount = lua_gettop(lua);
if (paramCount != 1) {
return -1;
}
if (!lua_isstring(lua, -1)) {
return -1;
}
std::vector<std::string> string_components;
std::stringstream topic(lua_tostring(lua, -1));
std::string token;
while (std::getline(topic, token, '/')) {
string_components.push_back(token);
}
lua_newtable(lua);
int i = 1;
for (const std::string& comp : string_components) {
lua_pushinteger(lua, i);
lua_pushstring(lua, comp.c_str());
lua_settable(lua, -3);
i++;
}
return 1;
}
// thrawn_publish(topic, value)
int thrawn_publish(lua_State* lua) {
int paramCount = lua_gettop(lua);

View File

@@ -25,11 +25,21 @@ int thrawn_create_topic_state(lua_State* lua);
int thrawn_topic_state_str(lua_State* lua);
int thrawn_topic_cache(lua_State* lua);
int thrawn_topic_components(lua_State* lua);
int thrawn_cached_topic(lua_State* lua);
// Function in LUA
void call_thrawn_on_start(LuaService& service);
void call_thrawn_on_update(LuaService& service, TopicState state);
//Database logging
int thrawn_log_light(lua_State* lua);
int thrawn_log_light_dimmable(lua_State* lua);
int thrawn_log_light_tw(lua_State* lua);
#endif // THRAWN_API_H

View File

@@ -0,0 +1,63 @@
#include "thrawn_api.h"
#include "LuaEngine.h"
//void write_light(const std::string_view name, const bool is_on);
int thrawn_log_light(lua_State* lua) {
int paramCount = lua_gettop(lua);
if (paramCount != 3) {
return -1;
}
//Param 1: room
//Param 2: name
//Param 3: is_on
if (!lua_isstring(lua, -3) || !lua_isstring (lua, -2) || !lua_isboolean (lua, -1)) {
return -1;
}
LuaEngine::get_instance().db_logger.write_light(lua_tostring(lua, -3), lua_tostring(lua, -2), lua_toboolean(lua, -1));
return 0;
}
int thrawn_log_light_dimmable(lua_State* lua) {
int paramCount = lua_gettop(lua);
if (paramCount != 4) {
return -1;
}
//Param 1: room
//Param 2: name
//Param 3: is_on
//Param 4: brightness
if (!lua_isstring(lua, -4) | !lua_isstring(lua, -3) || !lua_isboolean(lua, -2) || !lua_isinteger(lua, -1)) {
return -1;
}
LuaEngine::get_instance().db_logger.write_light_dimmable(lua_tostring(lua, -4), lua_tostring(lua, -3), lua_toboolean(lua, -2), lua_tointeger(lua, -1));
return 0;
}
int thrawn_log_light_tw(lua_State* lua) {
int paramCount = lua_gettop(lua);
if (paramCount != 5) {
return -1;
}
//Param 1: room
//Param 2: name
//Param 3: is_on
//Param 4: brightness
//Param 5: color_temperature
if (!lua_isstring(lua, -5) || !lua_isstring(lua, -4) || !lua_isboolean(lua, -3) || !lua_isinteger(lua, -2) || !lua_isinteger(lua, -1)) {
return -1;
}
LuaEngine::get_instance().db_logger.write_light_tuneable_white(lua_tostring(lua, -5), lua_tostring(lua, -4), lua_toboolean(lua, -3), lua_tointeger(lua, -2), lua_tointeger(lua, -1));
return 0;
}