新增http、mqtt运行库,实现mqtt功能, 新增spdlog

This commit is contained in:
lixiaoyuan
2025-09-01 20:08:40 +08:00
parent e0b64a20c4
commit 94e467b65e
245 changed files with 54182 additions and 117 deletions

View File

@@ -6,6 +6,7 @@
#include "database/Dao.h"
#include "common/JsonN.h"
#include "common/Snowflake.h"
#include "common/Spdlogger.h"
void ElectPeriod::parse(std::string jsonstr)
@@ -39,7 +40,7 @@ void AppData::initFromDB()
auto dao = DaoEntity::create("");
if (!dao->isConnected())
{
XLOGE() << "Database connected error.";
spdlog::info("Database connected error.");
return;
}
@@ -57,7 +58,7 @@ void AppData::initFromDB()
this->mapWorkMode[workModeId] = name;
str += ("工作模式: {" + std::to_string(workModeId)+":" + name + "},");
}
XLOGD() << str;
spdlog::info(str);
}
{ // 数据库读取策略类型定义
str = "", result.clear();
@@ -70,7 +71,7 @@ void AppData::initFromDB()
this->mapPolicyType[policyTypeId] = name;
str += ("策略类型: {" + std::to_string(policyTypeId) + ":" + name + "},");
}
XLOGD() << str;
spdlog::info(str);
}
{ // 数据库读取设备类型定义
str = "", result.clear();
@@ -87,7 +88,7 @@ void AppData::initFromDB()
mapping.deviceType.push_back({std::to_string(item->typeId), item->name});
str += ("设备类型: {" + std::to_string(item->typeId) + ":" + item->name + "},");
}
XLOGD() << str;
spdlog::info(str);
}
{ // 数据库读取角色定义
str = "", result.clear();
@@ -103,7 +104,7 @@ void AppData::initFromDB()
mapping.role.push_back({std::to_string(item->roleId), item->name});
str += ("角色: {" + std::to_string(item->roleId) + ":" + item->name + "},");
}
XLOGD() << str;
spdlog::info(str);
}
{ // 数据库读取场站信息
str = "", result.clear();
@@ -116,7 +117,7 @@ void AppData::initFromDB()
mapping.stationName.push_back({std::to_string(station->id), station->name});
str += ("场站: {" + std::to_string(station->id) + ":" + station->name + "},");
}
XLOGD() << str;
spdlog::info(str);
}
{ // 数据库读取设备信息
str = "", result.clear();
@@ -135,7 +136,7 @@ void AppData::initFromDB()
}
else
{
XLOGE() << "init device error: unknown station_id:[" << stationId << "] device_id=" << deviceId;
spdlog::error("init device error: unknown station_id:, device_id=", stationId, deviceId);
}
}
}
@@ -207,7 +208,7 @@ void AppData::initFromDB()
}
else
{
XLOGE() << "init staticis data error: unknown station_id:[" << stationId << "] dt=" << dt;
spdlog::error("init staticis data error: unknown station_id:{}, dt={}", stationId, dt);
}
}
}
@@ -227,6 +228,10 @@ std::shared_ptr<Station> AppData::getStation(int stationId)
}
return nullptr;
}
int AppData::getStationCount()
{
return mapStation.size();
}
std::shared_ptr<Station> AppData::getStationByName(std::string name)
{

View File

@@ -7,6 +7,7 @@
#include <unordered_map>
#include "common/Fields.h"
#include "app/Config.h"
#include "common/Spdlogger.h"
class Station;
class Device;
@@ -66,6 +67,7 @@ public:
User getUser(std::string token);
std::shared_ptr<Station> getStation(int stationId);
int getStationCount();
std::shared_ptr<Station> getStationByName(std::string name);

View File

@@ -7,8 +7,9 @@
#include "database/Dao.h"
#include "app/Station.h"
#include "app/Device.h"
#include "protocol/HttpEntity.h"
#include "common/Spdlogger.h"
#include "protocol/MqttEntity.h"
void Application::init()
{
@@ -21,41 +22,77 @@ void Application::init()
Config::option.database.user,
Config::option.database.passwd,
Config::option.database.dbname);
XLOGI() << "[APP] set database option: host=" << Config::option.database.host
<< ", port=" << Config::option.database.port
<< ", user=" << Config::option.database.user
<< ", dbname=" << Config::option.database.dbname;
spdlog::info("[app] set database option: host={}, port={}, user={}, dbname={}",
Config::option.database.host,
Config::option.database.port,
Config::option.database.user,
Config::option.database.dbname);
// 连接数据库,读取基础信息
// 初始化系统基础数据
appdata_.init();
appdata.init();
// 创建设备处理线程
std::thread([=]() { runThreadDevice(); }).detach();
// 创建HTTP服务线程
std::thread([=]() {
while (!isQuit) {
MqttClient mqttCli;
mqttCli.init("tcp://localhost:1883", "AAAAAAAAA", "", "", {"topic/test"}); // 不阻塞
HttpEntity http;
http.listen("0.0.0.0", Config::option.http.port); // 阻塞
}
}).detach();
// 创建主业务循环线程
std::thread([=]() { runThreadMain(); }).detach();
}
void Application::runThreadMain()
void Application::runThreadDevice()
{
while (!isQuit())
while (!isQuit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void Application::runThreadDevice()
void Application::runThreadMain()
{
while (!isQuit())
{
std::string addr = "tcp://localhost:1883";
mqttCli = std::make_shared<MqttClient>();
mqttCli->init(addr, "ESS", "", "", {});
while (!isQuit)
{
// 连接场站
static TimeTick ttStation;
if (ttStation.elapse(10000))
{
if (!mqttCli->isConnected)
{
}
else
{
for (auto& item: appdata.mapStation)
{
auto station = item.second;
if (station && !station->isConnected)
{
std::vector<std::string> vecTopics = {"topic/test" + std::to_string(station->id)};
mqttCli->subscribe(vecTopics, [=](int id)
{
station->isConnected = (id == 0);
});
}
break;
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));

View File

@@ -2,10 +2,11 @@
#include <thread>
#include "common/Logger.h"
#include "Operator.h"
#include "app/AppData.h"
class MqttClient;
class Application
{
public:
@@ -17,24 +18,25 @@ public:
static AppData& data()
{
return Application::instance().appdata_;
return Application::instance().appdata;
}
void init();
bool isQuit() { return isQuit_; }
Operator& getOperator() { return op_; }
Operator& getOperator() { return op; }
void runThreadMain();
void runThreadDevice();
public:
bool isQuit_ = false;
bool isQuit = false;
// 登录的管理员信息
Operator op_;
Operator op;
// 应用数据
AppData appdata_;
AppData appdata;
std::shared_ptr<MqttClient> mqttCli;
};

View File

@@ -3,7 +3,7 @@
#include <fstream>
#include "common/JsonN.h"
#include "Logger.h"
#include "common/Spdlogger.h"
#include "AppData.h"
AppOption Config::option;
@@ -14,10 +14,10 @@ bool Config::init(std::string filename)
bool ret = NJson::load(filename, jsonroot);
if (!ret)
{
XLOGE() << "[APP] load config failed, filename=" << filename;
spdlog::error("[config] load config file failed, filename={}", filename);
return false;
}
XLOGI() << "[APP] load config success, filename=" << filename;
spdlog::info("[config] load config file success, filename={}", filename);
if (jsonroot.contains("database"))
{
@@ -28,17 +28,20 @@ bool Config::init(std::string filename)
option.database.passwd = json.contains("passwd") ? json.at("passwd") : "";
option.database.dbname = json.contains("dbname") ? json.at("dbname") : "";
XLOGI() << "[APP] load database config end. host=" << option.database.host;
spdlog::info("[config] parse database success. host={}", option.database.host);
}
else
{
XLOGI() << "[APP] load database config error: not found. host=" << option.database.host;
spdlog::info("[config] parse database failed: not found. host={}", option.database.host);
}
if (jsonroot.contains("token"))
if (jsonroot.contains("http"))
{
std::string token = jsonroot["token"];
option.useToken = !token.empty();
NJsonNode json = jsonroot.at("http");
std:string token;
NJson::read(json, "token", token);
option.http.useToken = !token.empty();
NJson::read(json, "port", option.http.port);
}
return true;

View File

@@ -14,7 +14,12 @@ struct DatabaseOption
struct AppOption
{
DatabaseOption database;
bool useToken {true};
struct {
bool useToken {true};
int port {0};
} http;
};
class Config

View File

@@ -1,160 +0,0 @@
#include "Dao1.h"
#include "common/Logger.h"
#include "common/Utils.h"
#include "common/Snowflake.h"
enum class EnDatabaseErr
{
SUCCESS = 0,
};
std::shared_ptr<DaoEntity> DAO1::get(std::string tableName)
{
return std::make_shared<DaoEntity>(tableName);
}
Errcode DAO1::login(std::shared_ptr<DaoEntity> dao, std::string account, std::string passwd, Fields& fields)
{
std::string err;
std::string t = Utils::timeStr();
if (!dao)
{
dao = std::make_shared<DaoEntity>("");
}
if (!dao->isConnected())
{
err = "数据库连接错误";
DAO1::writeSystemLog(dao, 2, "", account, "用户登录失败:" + err);
return Errcode::ERR_DB_CONN;
}
std::string sql = "SELECT u.*, ur.role_id FROM `user` u"
" LEFT JOIN user_role ur ON u.user_id = ur.user_id WHERE u.account=" + account + "';";
std::vector<Fields> result;
bool ret = dao->exec(sql, result);
if (!ret)
{
err = "数据库操作错误";
DAO1::writeSystemLog(dao, 2, "", account, "用户登录失败:" + err);
return Errcode::ERR_DB_CONN;
}
if (result.size() <=0)
{
err = "用户不存在";
DAO1::writeSystemLog(dao, 2, "", account, "用户登录失败:" + err);
return Errcode::ERR_LOGIN_USER_NOTEXIST;
}
fields = result[0];
std::string userId = fields.value("user_id");
int loginCount = fields.get<int>("login_count");
// 判断密码
if (passwd != fields.value("passwd"))
{
err = "密码错误";
DAO1::writeSystemLog(dao, 2, userId, account, "用户登录失败:" + err);
return Errcode::ERR_LOGIN_PASSWD;
}
// 读取用户权限
{
result.clear();
std::string sql = "SELECT rp.role_id, rp.permission_id, p.name FROM role_permission rp "
"LEFT JOIN permission p ON p.permission_id = rp.permission_id"
"WHERE rp.role_id = 1;";
}
err = "登录成功";
// 数据库更新用户登录信息
sql = "UPDATE user SET login_time='" + t + "', login_count='" + std::to_string(loginCount + 1) + "' WHERE user_id = '" + userId + "'; ";
ret = dao->exec(sql);
if (!ret)
{
XLOGE() << "更新用户登录信息失败sql=" << sql;
}
DAO1::writeSystemLog(dao, 2, userId, account, "用户登录成功");
return Errcode::OK;
}
bool DAO1::writeSystemLog(std::shared_ptr<DaoEntity> dao, int type, std::string userId, std::string account, std::string text)
{
if (!dao)
{
dao = std::make_shared<DaoEntity>("");
}
if (!dao->isConnected())
{
return false;
}
// 数据库写入登录日志
dao->setTableName("system_log");
Fields fieldsLog;
fieldsLog.set("log_id", Snowflake::instance().getIdStr());
fieldsLog.set("type", 2);
fieldsLog.set("user_id", userId);
fieldsLog.set("user_account", account);
fieldsLog.set("content", text);
fieldsLog.set("create_time", Utils::timeStr());
bool ret = dao->insertFields({fieldsLog});
return ret;
}
bool DAO1::queryUser(std::vector<Fields>& res)
{
std::shared_ptr<DaoEntity> dao = std::make_shared<DaoEntity>("");
if (!dao->isConnected())
{
return false;
}
std::string sql = "SELECT u.*, r.role_id, r.name role_name from USER u LEFT JOIN user_role ur ON u.user_id = ur.user_id LEFT JOIN `role` r ON r.role_id = ur.role_id;";
bool ret = dao->exec(sql, res);
return ret;
}
int DAO1::insertUser(Fields& fields)
{
std::shared_ptr<DaoEntity> dao = std::make_shared<DaoEntity>("user");
if (!dao->isConnected())
{
return 1;
}
std::string account = fields.value("account");
// step1: 查询
std::vector<Fields> res;
bool ret = dao->exec("SELECT * from user WHERE account='" + account + "';", res);
if (!ret)
{
return 1;
}
if (res.size() > 0)
{
return 1;
}
fields.set("user_id", Snowflake::instance().getIdStr());
fields.set("create_time", Utils::timeStr());
ret = dao->insertFields(fields);
return (ret) ? 0 : 1;
}
int DAO1::updateUserById(std::string id, Fields& fields)
{
std::shared_ptr<DaoEntity> dao = std::make_shared<DaoEntity>("user");
if (!dao->isConnected())
{
return 1;
}
string sqlC = "WHERE user_id='" + id + "'";
bool ret = dao->updateFields(fields, sqlC);
return (ret) ? 0 : 1;
}

View File

@@ -1,32 +0,0 @@
#include "database/DaoEntity.h"
#include "app/errcode.h"
class DAO1
{
public:
static std::shared_ptr<DaoEntity> get(std::string tableName="");
static Errcode login(std::shared_ptr<DaoEntity> dao, std::string account, std::string passwd, Fields& res);
static bool writeSystemLog(std::shared_ptr<DaoEntity> dao, int type, std::string userId, std::string account, std::string text);
// =======================================================================
// 用户管理数据操作
/**
* 查询用户
*/
static bool queryUser(std::vector<Fields>& res);
/**
* 新增用户
*/
static int insertUser(Fields& fields);
/**
* 修改用户信息
*/
static int updateUserById(std::string id, Fields& fields);
};

View File

@@ -3,6 +3,7 @@
#include "database/SQL.h"
#include "common/fields.h"
#include "app/Device.h"
#include "common/Spdlogger.h"
Station::Station() : id(0)
@@ -71,7 +72,7 @@ void Station::setWorkMode(int modeId)
Errcode err = DAO::exec(NULL, sql);
if (err != Errcode::OK)
{
XLOGE() << "set station work mode failed.";
spdlog::error("set station work mode failed.");
}
}
@@ -83,6 +84,6 @@ void Station::setPolicy(int policyId)
Errcode err = DAO::exec(NULL, sql);
if (err != Errcode::OK)
{
XLOGE() << "set station policy failed.";
spdlog::error("set station policy failed.");
}
}

View File

@@ -28,6 +28,7 @@ public:
public:
int id {};
std::string name;
bool isConnected {false};
int workModeId {}; // 运行模式
int runPolicyId {}; // 运行策略