mirror of
https://gitee.com/js-yhsec/energy_storage.git
synced 2026-05-27 18:59:26 +08:00
新增http、mqtt运行库,实现mqtt功能, 新增spdlog
This commit is contained in:
BIN
bin/Release/paho-mqtt3a.dll
Normal file
BIN
bin/Release/paho-mqtt3a.dll
Normal file
Binary file not shown.
BIN
bin/Release/paho-mqtt3c.dll
Normal file
BIN
bin/Release/paho-mqtt3c.dll
Normal file
Binary file not shown.
@@ -67,6 +67,8 @@ include_directories(
|
|||||||
${THIRDPARTY_PATH}/mysql/include
|
${THIRDPARTY_PATH}/mysql/include
|
||||||
${THIRDPARTY_PATH}/nlohmann_json-3.11.2
|
${THIRDPARTY_PATH}/nlohmann_json-3.11.2
|
||||||
${THIRDPARTY_PATH}/cpp-httplib-0.25.0
|
${THIRDPARTY_PATH}/cpp-httplib-0.25.0
|
||||||
|
${THIRDPARTY_PATH}/paho_mqtt/include
|
||||||
|
${THIRDPARTY_PATH}/spdlog-1.13.0/include
|
||||||
${PVLIBS_PATH}/include/pvserver
|
${PVLIBS_PATH}/include/pvserver
|
||||||
${PVLIBS_PATH}/include/rllib
|
${PVLIBS_PATH}/include/rllib
|
||||||
)
|
)
|
||||||
@@ -98,7 +100,9 @@ target_link_libraries(${PROJECT_NAME}
|
|||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
ws2_32 iphlpapi
|
ws2_32 iphlpapi
|
||||||
${THIRDPARTY_PATH}/mysql/lib/x64/libmysql.lib
|
${THIRDPARTY_PATH}/mysql/lib/x64/libmysql.lib
|
||||||
|
${THIRDPARTY_PATH}/paho_mqtt/lib/paho-mqtt3a.lib
|
||||||
|
${THIRDPARTY_PATH}/paho_mqtt/lib/paho-mqtt3c.lib
|
||||||
${PVLIBS_PATH}/x64/serverlib.lib
|
${PVLIBS_PATH}/x64/serverlib.lib
|
||||||
${PVLIBS_PATH}/x64/rllib.lib
|
${PVLIBS_PATH}/x64/rllib.lib
|
||||||
)
|
|
||||||
|
|
||||||
|
)
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "database/Dao.h"
|
#include "database/Dao.h"
|
||||||
#include "common/JsonN.h"
|
#include "common/JsonN.h"
|
||||||
#include "common/Snowflake.h"
|
#include "common/Snowflake.h"
|
||||||
|
#include "common/Spdlogger.h"
|
||||||
|
|
||||||
|
|
||||||
void ElectPeriod::parse(std::string jsonstr)
|
void ElectPeriod::parse(std::string jsonstr)
|
||||||
@@ -39,7 +40,7 @@ void AppData::initFromDB()
|
|||||||
auto dao = DaoEntity::create("");
|
auto dao = DaoEntity::create("");
|
||||||
if (!dao->isConnected())
|
if (!dao->isConnected())
|
||||||
{
|
{
|
||||||
XLOGE() << "Database connected error.";
|
spdlog::info("Database connected error.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ void AppData::initFromDB()
|
|||||||
this->mapWorkMode[workModeId] = name;
|
this->mapWorkMode[workModeId] = name;
|
||||||
str += ("工作模式: {" + std::to_string(workModeId)+":" + name + "},");
|
str += ("工作模式: {" + std::to_string(workModeId)+":" + name + "},");
|
||||||
}
|
}
|
||||||
XLOGD() << str;
|
spdlog::info(str);
|
||||||
}
|
}
|
||||||
{ // 数据库读取策略类型定义
|
{ // 数据库读取策略类型定义
|
||||||
str = "", result.clear();
|
str = "", result.clear();
|
||||||
@@ -70,7 +71,7 @@ void AppData::initFromDB()
|
|||||||
this->mapPolicyType[policyTypeId] = name;
|
this->mapPolicyType[policyTypeId] = name;
|
||||||
str += ("策略类型: {" + std::to_string(policyTypeId) + ":" + name + "},");
|
str += ("策略类型: {" + std::to_string(policyTypeId) + ":" + name + "},");
|
||||||
}
|
}
|
||||||
XLOGD() << str;
|
spdlog::info(str);
|
||||||
}
|
}
|
||||||
{ // 数据库读取设备类型定义
|
{ // 数据库读取设备类型定义
|
||||||
str = "", result.clear();
|
str = "", result.clear();
|
||||||
@@ -87,7 +88,7 @@ void AppData::initFromDB()
|
|||||||
mapping.deviceType.push_back({std::to_string(item->typeId), item->name});
|
mapping.deviceType.push_back({std::to_string(item->typeId), item->name});
|
||||||
str += ("设备类型: {" + std::to_string(item->typeId) + ":" + item->name + "},");
|
str += ("设备类型: {" + std::to_string(item->typeId) + ":" + item->name + "},");
|
||||||
}
|
}
|
||||||
XLOGD() << str;
|
spdlog::info(str);
|
||||||
}
|
}
|
||||||
{ // 数据库读取角色定义
|
{ // 数据库读取角色定义
|
||||||
str = "", result.clear();
|
str = "", result.clear();
|
||||||
@@ -103,7 +104,7 @@ void AppData::initFromDB()
|
|||||||
mapping.role.push_back({std::to_string(item->roleId), item->name});
|
mapping.role.push_back({std::to_string(item->roleId), item->name});
|
||||||
str += ("角色: {" + std::to_string(item->roleId) + ":" + item->name + "},");
|
str += ("角色: {" + std::to_string(item->roleId) + ":" + item->name + "},");
|
||||||
}
|
}
|
||||||
XLOGD() << str;
|
spdlog::info(str);
|
||||||
}
|
}
|
||||||
{ // 数据库读取场站信息
|
{ // 数据库读取场站信息
|
||||||
str = "", result.clear();
|
str = "", result.clear();
|
||||||
@@ -116,7 +117,7 @@ void AppData::initFromDB()
|
|||||||
mapping.stationName.push_back({std::to_string(station->id), station->name});
|
mapping.stationName.push_back({std::to_string(station->id), station->name});
|
||||||
str += ("场站: {" + std::to_string(station->id) + ":" + station->name + "},");
|
str += ("场站: {" + std::to_string(station->id) + ":" + station->name + "},");
|
||||||
}
|
}
|
||||||
XLOGD() << str;
|
spdlog::info(str);
|
||||||
}
|
}
|
||||||
{ // 数据库读取设备信息
|
{ // 数据库读取设备信息
|
||||||
str = "", result.clear();
|
str = "", result.clear();
|
||||||
@@ -135,7 +136,7 @@ void AppData::initFromDB()
|
|||||||
}
|
}
|
||||||
else
|
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
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
int AppData::getStationCount()
|
||||||
|
{
|
||||||
|
return mapStation.size();
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Station> AppData::getStationByName(std::string name)
|
std::shared_ptr<Station> AppData::getStationByName(std::string name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "common/Fields.h"
|
#include "common/Fields.h"
|
||||||
#include "app/Config.h"
|
#include "app/Config.h"
|
||||||
|
#include "common/Spdlogger.h"
|
||||||
|
|
||||||
class Station;
|
class Station;
|
||||||
class Device;
|
class Device;
|
||||||
@@ -66,6 +67,7 @@ public:
|
|||||||
User getUser(std::string token);
|
User getUser(std::string token);
|
||||||
|
|
||||||
std::shared_ptr<Station> getStation(int stationId);
|
std::shared_ptr<Station> getStation(int stationId);
|
||||||
|
int getStationCount();
|
||||||
|
|
||||||
std::shared_ptr<Station> getStationByName(std::string name);
|
std::shared_ptr<Station> getStationByName(std::string name);
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,9 @@
|
|||||||
#include "database/Dao.h"
|
#include "database/Dao.h"
|
||||||
#include "app/Station.h"
|
#include "app/Station.h"
|
||||||
#include "app/Device.h"
|
#include "app/Device.h"
|
||||||
|
#include "protocol/HttpEntity.h"
|
||||||
|
#include "common/Spdlogger.h"
|
||||||
|
#include "protocol/MqttEntity.h"
|
||||||
|
|
||||||
void Application::init()
|
void Application::init()
|
||||||
{
|
{
|
||||||
@@ -21,41 +22,77 @@ void Application::init()
|
|||||||
Config::option.database.user,
|
Config::option.database.user,
|
||||||
Config::option.database.passwd,
|
Config::option.database.passwd,
|
||||||
Config::option.database.dbname);
|
Config::option.database.dbname);
|
||||||
XLOGI() << "[APP] set database option: host=" << Config::option.database.host
|
spdlog::info("[app] set database option: host={}, port={}, user={}, dbname={}",
|
||||||
<< ", port=" << Config::option.database.port
|
Config::option.database.host,
|
||||||
<< ", user=" << Config::option.database.user
|
Config::option.database.port,
|
||||||
<< ", dbname=" << Config::option.database.dbname;
|
Config::option.database.user,
|
||||||
|
Config::option.database.dbname);
|
||||||
|
|
||||||
// 连接数据库,读取基础信息
|
// 连接数据库,读取基础信息
|
||||||
|
|
||||||
// 初始化系统基础数据
|
// 初始化系统基础数据
|
||||||
appdata_.init();
|
appdata.init();
|
||||||
|
|
||||||
// 创建设备处理线程
|
// 创建设备处理线程
|
||||||
std::thread([=]() { runThreadDevice(); }).detach();
|
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();
|
std::thread([=]() { runThreadMain(); }).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Application::runThreadMain()
|
|
||||||
{
|
|
||||||
while (!isQuit())
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Application::runThreadDevice()
|
void Application::runThreadDevice()
|
||||||
{
|
{
|
||||||
while (!isQuit())
|
while (!isQuit)
|
||||||
{
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::runThreadMain()
|
||||||
|
{
|
||||||
|
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));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "common/Logger.h"
|
|
||||||
#include "Operator.h"
|
#include "Operator.h"
|
||||||
#include "app/AppData.h"
|
#include "app/AppData.h"
|
||||||
|
|
||||||
|
class MqttClient;
|
||||||
|
|
||||||
class Application
|
class Application
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -17,24 +18,25 @@ public:
|
|||||||
|
|
||||||
static AppData& data()
|
static AppData& data()
|
||||||
{
|
{
|
||||||
return Application::instance().appdata_;
|
return Application::instance().appdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
bool isQuit() { return isQuit_; }
|
Operator& getOperator() { return op; }
|
||||||
Operator& getOperator() { return op_; }
|
|
||||||
|
|
||||||
void runThreadMain();
|
void runThreadMain();
|
||||||
|
|
||||||
void runThreadDevice();
|
void runThreadDevice();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool isQuit_ = false;
|
bool isQuit = false;
|
||||||
|
|
||||||
// 登录的管理员信息
|
// 登录的管理员信息
|
||||||
Operator op_;
|
Operator op;
|
||||||
|
|
||||||
// 应用数据
|
// 应用数据
|
||||||
AppData appdata_;
|
AppData appdata;
|
||||||
|
|
||||||
|
std::shared_ptr<MqttClient> mqttCli;
|
||||||
};
|
};
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include "common/JsonN.h"
|
#include "common/JsonN.h"
|
||||||
#include "Logger.h"
|
#include "common/Spdlogger.h"
|
||||||
#include "AppData.h"
|
#include "AppData.h"
|
||||||
|
|
||||||
AppOption Config::option;
|
AppOption Config::option;
|
||||||
@@ -14,10 +14,10 @@ bool Config::init(std::string filename)
|
|||||||
bool ret = NJson::load(filename, jsonroot);
|
bool ret = NJson::load(filename, jsonroot);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
XLOGE() << "[APP] load config failed, filename=" << filename;
|
spdlog::error("[config] load config file failed, filename={}", filename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
XLOGI() << "[APP] load config success, filename=" << filename;
|
spdlog::info("[config] load config file success, filename={}", filename);
|
||||||
|
|
||||||
if (jsonroot.contains("database"))
|
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.passwd = json.contains("passwd") ? json.at("passwd") : "";
|
||||||
option.database.dbname = json.contains("dbname") ? json.at("dbname") : "";
|
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
|
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"];
|
NJsonNode json = jsonroot.at("http");
|
||||||
option.useToken = !token.empty();
|
std:string token;
|
||||||
|
NJson::read(json, "token", token);
|
||||||
|
option.http.useToken = !token.empty();
|
||||||
|
NJson::read(json, "port", option.http.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -14,7 +14,12 @@ struct DatabaseOption
|
|||||||
struct AppOption
|
struct AppOption
|
||||||
{
|
{
|
||||||
DatabaseOption database;
|
DatabaseOption database;
|
||||||
bool useToken {true};
|
|
||||||
|
struct {
|
||||||
|
bool useToken {true};
|
||||||
|
int port {0};
|
||||||
|
} http;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Config
|
class Config
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "database/SQL.h"
|
#include "database/SQL.h"
|
||||||
#include "common/fields.h"
|
#include "common/fields.h"
|
||||||
#include "app/Device.h"
|
#include "app/Device.h"
|
||||||
|
#include "common/Spdlogger.h"
|
||||||
|
|
||||||
|
|
||||||
Station::Station() : id(0)
|
Station::Station() : id(0)
|
||||||
@@ -71,7 +72,7 @@ void Station::setWorkMode(int modeId)
|
|||||||
Errcode err = DAO::exec(NULL, sql);
|
Errcode err = DAO::exec(NULL, sql);
|
||||||
if (err != Errcode::OK)
|
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);
|
Errcode err = DAO::exec(NULL, sql);
|
||||||
if (err != Errcode::OK)
|
if (err != Errcode::OK)
|
||||||
{
|
{
|
||||||
XLOGE() << "set station policy failed.";
|
spdlog::error("set station policy failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
int id {};
|
int id {};
|
||||||
std::string name;
|
std::string name;
|
||||||
|
bool isConnected {false};
|
||||||
|
|
||||||
int workModeId {}; // 运行模式
|
int workModeId {}; // 运行模式
|
||||||
int runPolicyId {}; // 运行策略
|
int runPolicyId {}; // 运行策略
|
||||||
|
|||||||
50
src/common/Spdlogger.cpp
Normal file
50
src/common/Spdlogger.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#include "Spdlogger.h"
|
||||||
|
|
||||||
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
|
#include <spdlog/sinks/daily_file_sink.h>
|
||||||
|
|
||||||
|
//std::shared_ptr<spdlog::logger> Spdlogger::logger_ = spdlog::stdout_color_mt("sys");
|
||||||
|
//std::shared_ptr<spdlog::logger> Spdlogger::logger = spdlog::daily_logger_mt("daily_logger", "ees.log", 0, 0);
|
||||||
|
|
||||||
|
void Spdlogger::init(spdlog::level::level_enum log_level, std::string filename)
|
||||||
|
{
|
||||||
|
if (!filename.empty()) {
|
||||||
|
//logger = spdlog::daily_logger_mt("daily_logger", filename, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//logger_ = spdlog::stdout_color_mt("sys");
|
||||||
|
//logger_ = spdlog::daily_logger_mt("daily_logger", "log/pvs.log", 0, 0);
|
||||||
|
// set log level : spdlog::level::debug
|
||||||
|
//logger->set_level(log_level);
|
||||||
|
//logger->flush_on(log_level);
|
||||||
|
|
||||||
|
|
||||||
|
// 创建控制台接收器
|
||||||
|
auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||||
|
consoleSink->set_level(spdlog::level::info); // 设置控制台日志等级
|
||||||
|
//consoleSink->set_pattern("[%T] [%^%l%$] %v"); // 设置日志格式
|
||||||
|
|
||||||
|
// 创建文件接收器
|
||||||
|
//auto fileSink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/mcs.log", true);
|
||||||
|
//fileSink->set_level(spdlog::level::debug); // 设置文件日志等级
|
||||||
|
//fileSink->set_pattern("[%T] [%l] %v"); // 设置日志格式
|
||||||
|
|
||||||
|
// 每日文件sink(可选,每天生成新文件)
|
||||||
|
auto dailySink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logs/mcs.log", 0, 0);
|
||||||
|
dailySink->set_level(spdlog::level::debug);
|
||||||
|
//dailySink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");
|
||||||
|
|
||||||
|
// 创建一个多重接收器的 logger
|
||||||
|
std::vector<spdlog::sink_ptr> sinks {consoleSink, dailySink};
|
||||||
|
auto logger = std::make_shared<spdlog::logger>("", sinks.begin(), sinks.end());
|
||||||
|
|
||||||
|
// 设置全局 logger
|
||||||
|
spdlog::set_default_logger(logger);
|
||||||
|
spdlog::set_level(spdlog::level::debug); // 设置全局日志等级为 debug
|
||||||
|
spdlog::flush_on(spdlog::level::info); // 开启日志刷新
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spdlogger::drop()
|
||||||
|
{
|
||||||
|
spdlog::drop_all();
|
||||||
|
}
|
||||||
36
src/common/Spdlogger.h
Normal file
36
src/common/Spdlogger.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include <spdlog/sinks/stdout_color_sinks.h> // 彩色控制台日志
|
||||||
|
#include <spdlog/sinks/basic_file_sink.h> // 文件日志
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class Spdlogger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void init(spdlog::level::level_enum log_level, std::string filename);
|
||||||
|
static void drop();
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
static void debug(spdlog::format_string_t<Args...> fmt, Args &&...args) {
|
||||||
|
//if (logger) logger->debug(fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
static void info(spdlog::format_string_t<Args...> fmt, Args &&...args) {
|
||||||
|
//if (logger) logger->info(fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
static void warn(spdlog::format_string_t<Args...> fmt, Args &&...args) {
|
||||||
|
//if (logger) logger->warn(fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
static void error(spdlog::format_string_t<Args...> fmt, Args &&...args) {
|
||||||
|
//if (logger) logger->error(fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//static std::shared_ptr<spdlog::logger> logger;
|
||||||
|
};
|
||||||
@@ -90,9 +90,9 @@ class TimeTick
|
|||||||
public:
|
public:
|
||||||
int64_t tickMS_ = 0;
|
int64_t tickMS_ = 0;
|
||||||
|
|
||||||
TimeTick()
|
TimeTick(int t=0)
|
||||||
{
|
{
|
||||||
tickMS_ = Utils::time();
|
if (t !=0) { tickMS_ = Utils::time(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool elapse(int64_t ms, bool reset = true)
|
bool elapse(int64_t ms, bool reset = true)
|
||||||
|
|||||||
@@ -67,12 +67,12 @@ Errcode DAO::update(std::shared_ptr<DaoEntity> dao, std::string tableName, Field
|
|||||||
std::string primaryVal = params.remove(primaryKey);
|
std::string primaryVal = params.remove(primaryKey);
|
||||||
if (primaryVal.empty())
|
if (primaryVal.empty())
|
||||||
{
|
{
|
||||||
XLOGE() << "DAO update [" + tableName + "] failed, " << primaryKey << "=NULL.";
|
spdlog::error("DAO update [{}] failed,{} is NULL.", tableName, primaryKey);
|
||||||
return Errcode::ERR_PARAM;
|
return Errcode::ERR_PARAM;
|
||||||
}
|
}
|
||||||
if (params.size() == 0)
|
if (params.size() == 0)
|
||||||
{
|
{
|
||||||
XLOGE() << "DAO update [" + tableName + "] failed, params size=0.";
|
spdlog::error("DAO update [{}] failed, params size=0.", tableName);
|
||||||
return Errcode::ERR_PARAM_NUL;
|
return Errcode::ERR_PARAM_NUL;
|
||||||
}
|
}
|
||||||
std::string condition = "WHERE " + primaryKey + "='" + primaryVal + "'";
|
std::string condition = "WHERE " + primaryKey + "='" + primaryVal + "'";
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "DaoEntity.h"
|
#include "DaoEntity.h"
|
||||||
#include "DataModelDef.h"
|
#include "DataModelDef.h"
|
||||||
#include "common/Logger.h"
|
|
||||||
#include "errcode.h"
|
#include "errcode.h"
|
||||||
|
|
||||||
class DAO
|
class DAO
|
||||||
|
|||||||
52
src/main.cpp
52
src/main.cpp
@@ -19,39 +19,21 @@
|
|||||||
#include "pv/PvUser.h"
|
#include "pv/PvUser.h"
|
||||||
|
|
||||||
#include "rlsocket.h"
|
#include "rlsocket.h"
|
||||||
#include "protocol/HttpEntity.h"
|
#include "common/Spdlogger.h"
|
||||||
|
|
||||||
enum EAA
|
|
||||||
{
|
|
||||||
A = 1,
|
|
||||||
B = 2
|
#include <stdio.h>
|
||||||
};
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define wsa rlwsa
|
#define wsa rlwsa
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
EAA aa = EAA(100);
|
|
||||||
std::cout << aa;
|
|
||||||
|
|
||||||
std::thread([]() {
|
|
||||||
while (1) {
|
|
||||||
HttpEntity http;
|
|
||||||
http.listen("0.0.0.0", 19800);
|
|
||||||
}
|
|
||||||
}).detach();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 设置控制台输出为 UTF-8 编码
|
|
||||||
SetConsoleOutputCP(CP_UTF8);
|
|
||||||
// 设置控制台输入为 UTF-8 编码(如果需要输入中文)
|
|
||||||
SetConsoleCP(CP_UTF8);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
NJsonNode jsonroot;
|
NJsonNode jsonroot;
|
||||||
NJson::parse(R"({"name": "Alice", "age": 25, "data":[["1","1","1"],["1","1","1"],["1","1","1"]]})", jsonroot);
|
NJson::parse(R"({"name": "Alice", "age": 25, "data":[["1","1","1"],["1","1","1"],["1","1","1"]]})", jsonroot);
|
||||||
std::cout << (jsonroot.is_null() ? "ERROR" : "OK") << std::endl;
|
|
||||||
|
|
||||||
std::vector<std::vector<std::string>> v1;
|
std::vector<std::vector<std::string>> v1;
|
||||||
NJson::read<std::vector<std::vector<std::string>>>(jsonroot, "data", v1);
|
NJson::read<std::vector<std::vector<std::string>>>(jsonroot, "data", v1);
|
||||||
@@ -70,14 +52,23 @@ int main(int argc, char** argv)
|
|||||||
jsonroot1["price_off_peak"] = 0.53;
|
jsonroot1["price_off_peak"] = 0.53;
|
||||||
jsonroot1["periods"] = vec;
|
jsonroot1["periods"] = vec;
|
||||||
|
|
||||||
std::cout << jsonroot1.dump();
|
std::cout << jsonroot1.dump() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, bool> mapT;
|
// 设置控制台输出为 UTF-8 编码
|
||||||
bool ff = mapT[1];
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
// 设置控制台输入为 UTF-8 编码(如果需要输入中文)
|
||||||
|
SetConsoleCP(CP_UTF8);
|
||||||
|
|
||||||
rlwsa();
|
Spdlogger::init(spdlog::level::debug, "");
|
||||||
rlSocket socket("127.0.0.1", 19801, 1);
|
spdlog::info("[main] start ... ====================================================================================================");
|
||||||
|
spdlog::info("spd info");
|
||||||
|
spdlog::debug("spd debug");
|
||||||
|
spdlog::error("spd error");
|
||||||
|
|
||||||
|
|
||||||
|
//rlwsa();
|
||||||
|
//rlSocket socket("127.0.0.1", 19801, 1);
|
||||||
//int ret = socket.connect();
|
//int ret = socket.connect();
|
||||||
//std::string s1 = "helloworld";
|
//std::string s1 = "helloworld";
|
||||||
//socket.write(s1.c_str(), s1.size());
|
//socket.write(s1.c_str(), s1.size());
|
||||||
@@ -91,7 +82,6 @@ int main(int argc, char** argv)
|
|||||||
// std::cout << "===>>> " << std::string(buf.begin(), buf.end());
|
// std::cout << "===>>> " << std::string(buf.begin(), buf.end());
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
std::cout << "===>>> main start ... " << std::endl;
|
|
||||||
|
|
||||||
////std::cout << Snowflake::instance().getId() << std::endl;
|
////std::cout << Snowflake::instance().getId() << std::endl;
|
||||||
//for (int i = 0; i<=10; ++i) {
|
//for (int i = 0; i<=10; ++i) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "common/Snowflake.h"
|
#include "common/Snowflake.h"
|
||||||
#include "app/Application.h"
|
#include "app/Application.h"
|
||||||
#include "app/AppData.h"
|
#include "app/AppData.h"
|
||||||
|
#include "app/Config.h"
|
||||||
|
|
||||||
static NJsonNode FieldsToJsonArray(std::vector<Fields> vecFields)
|
static NJsonNode FieldsToJsonArray(std::vector<Fields> vecFields)
|
||||||
{
|
{
|
||||||
@@ -116,65 +117,72 @@ static std::map<std::string, HandlerOptions> g_mapHttpHandler =
|
|||||||
|
|
||||||
{"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {"token"})},
|
{"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {"token"})},
|
||||||
|
|
||||||
|
{"/queryStatSystem", HandlerOptions(&HttpEntity::queryStatSystem, {"token"})},
|
||||||
|
{"/queryStatTotal", HandlerOptions(&HttpEntity::queryStatTotal, {"token"})},
|
||||||
|
{"/queryStatDayList", HandlerOptions(&HttpEntity::queryStatDayList, {"token"})},
|
||||||
|
|
||||||
//{"/insert", HandlerOptions(&HttpEntity::insert, {})},
|
//{"/insert", HandlerOptions(&HttpEntity::insert, {})},
|
||||||
//{"/update", HandlerOptions(&HttpEntity::update, {})},
|
//{"/update", HandlerOptions(&HttpEntity::update, {})},
|
||||||
//{"/delete", HandlerOptions(&HttpEntity::delete, {})},
|
//{"/delete", HandlerOptions(&HttpEntity::delete, {})},
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HttpEntity::HttpEntity()
|
||||||
void HttpEntity::listen(std::string addr, int port)
|
|
||||||
{
|
{
|
||||||
|
bool useToken = Config::option.http.useToken;
|
||||||
for (auto& item : g_mapHttpHandler)
|
for (auto& item : g_mapHttpHandler)
|
||||||
{
|
{
|
||||||
std::string name = item.first;
|
std::string name = item.first;
|
||||||
HandlerOptions& handler = item.second;
|
HandlerOptions& handler = item.second;
|
||||||
this->httpsvr.Get(name, [=, &handler](const httplib::Request& req, httplib::Response& resp)
|
this->httpsvr.Get(name, [=, &handler](const httplib::Request& req, httplib::Response& resp)
|
||||||
{
|
|
||||||
NJsonNode json;
|
|
||||||
Errcode errcode = Errcode::OK;
|
|
||||||
|
|
||||||
if (name != "/login" && Config::option.useToken)
|
|
||||||
{
|
{
|
||||||
// 验证token
|
spdlog::info("[http] request: {}", name);
|
||||||
std::string token = req.get_param_value("token");
|
NJsonNode json;
|
||||||
if (token.empty())
|
Errcode errcode = Errcode::OK;
|
||||||
|
|
||||||
|
if (name != "/login" && useToken)
|
||||||
{
|
{
|
||||||
errcode = Errcode::ERR_TOKEN;
|
// 验证token
|
||||||
}
|
std::string token = req.get_param_value("token");
|
||||||
else
|
if (token.empty())
|
||||||
{
|
|
||||||
User user = Application::data().getUser(token);
|
|
||||||
if (user.userId.empty())
|
|
||||||
{
|
{
|
||||||
errcode = Errcode::ERR_TOKEN;
|
errcode = Errcode::ERR_TOKEN;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
User user = Application::data().getUser(token);
|
||||||
|
if (user.userId.empty())
|
||||||
|
{
|
||||||
|
errcode = Errcode::ERR_TOKEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string errmsg;
|
std::string errmsg;
|
||||||
if (errcode == Errcode::OK)
|
if (errcode == Errcode::OK)
|
||||||
{
|
|
||||||
if (!HttpHelper::CheckRequestParam(req, resp, handler.requiredKeys, errmsg))
|
|
||||||
{
|
{
|
||||||
errcode = Errcode::ERR_PARAM;
|
if (!HttpHelper::CheckRequestParam(req, resp, handler.requiredKeys, errmsg))
|
||||||
|
{
|
||||||
|
errcode = Errcode::ERR_PARAM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errcode = (this->*(handler.func))(req, resp, json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
errcode = (this->*(handler.func))(req, resp, json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
json["errcode"] = errcode;
|
json["errcode"] = errcode;
|
||||||
json["errmsg"] = ErrcodeStr(errcode) + (errmsg.empty() ? "" : (":"+errmsg));
|
json["errmsg"] = ErrcodeStr(errcode) + (errmsg.empty() ? "" : (":"+errmsg));
|
||||||
resp.set_content(json.dump(), "text/plain; charset=utf-8");
|
resp.set_content(json.dump(), "text/plain; charset=utf-8");
|
||||||
resp.status = 200;
|
resp.status = 200;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpEntity::listen(std::string addr, int port)
|
||||||
|
{
|
||||||
if (addr.empty()) addr = "0.0.0.0";
|
if (addr.empty()) addr = "0.0.0.0";
|
||||||
httpsvr.listen(addr, port);
|
spdlog::info("[http] start listen: addr={}:{},token={}", addr, port, Config::option.http.useToken);
|
||||||
|
httpsvr.listen(addr, port); // 阻塞
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpEntity::registGet(std::string name, void (HttpEntity::* func)(const httplib::Request& req, httplib::Response& resp))
|
void HttpEntity::registGet(std::string name, void (HttpEntity::* func)(const httplib::Request& req, httplib::Response& resp))
|
||||||
@@ -500,3 +508,58 @@ Errcode HttpEntity::queryPredictionDetail(const httplib::Request& req, httplib::
|
|||||||
json["data"] = jsonData;
|
json["data"] = jsonData;
|
||||||
return Errcode::OK;
|
return Errcode::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Errcode HttpEntity::queryStatSystem(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||||
|
{
|
||||||
|
auto& appdata = Application::data();
|
||||||
|
|
||||||
|
json["launch_date"] = "2025-01-01"; //: 系统上线启用日期,格式:yyyy-mm-dd
|
||||||
|
json["income_total"] = "0.00"; // : 累计收益(元),精度0.01
|
||||||
|
json["station_num"] = Utils::toStr(appdata.getStationCount()); // : 能源站数量
|
||||||
|
json["storage_device_num "] = Utils::toStr(appdata.getStationCount()); //: 储能设备数量
|
||||||
|
json["solar_device_num"] = "0"; // : 光伏设备数量
|
||||||
|
json["capacity_total"] = "0.000"; // : 储能总容量(kWh),精度0.001
|
||||||
|
json["elect_gen"] = "0.000"; // : 发电总电量(kWh),精度0.001
|
||||||
|
json["elect_grid"] = "0.000"; // : 入网种电量(kWh),精度0.001
|
||||||
|
json["storage_elect_in"] = "0.000"; // : 储能充电总电量(kWh),精度0.001
|
||||||
|
json["storage_elect_out"] = "0.000"; // : 储能放电总电量(kWh),精度0.001
|
||||||
|
|
||||||
|
return Errcode::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Errcode HttpEntity::queryStatTotal(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||||
|
{
|
||||||
|
std::string station_id = req.get_param_value("station_id");
|
||||||
|
std::string category = req.get_param_value("category");
|
||||||
|
|
||||||
|
json["dt"] = "2025-01-01"; //日期
|
||||||
|
json["storage_elect_in"] = "123.123"; //储能充电电量(kWh),精度:0.001
|
||||||
|
json["storage_elect_out"] = "123.123"; //储能放电电量(kWh),精度:0.001
|
||||||
|
json["storage_num_in"] = "1"; //储能设备充电次数
|
||||||
|
json["storage_num_out"] = "1"; //储能设备放电次数
|
||||||
|
json["storage_num_err"] = "1"; //储能设备故障次数
|
||||||
|
json["solar_elect_gen"] = "123.123"; //光伏发电电量(kWh),精度:0.001
|
||||||
|
json["solar_elect_grid"] = "123.123"; //光伏入网电量(kWh),精度:0.001
|
||||||
|
json["solar_num_err"] = "1"; //光伏设备故障次数
|
||||||
|
json["charge_elect"] = "123.123"; //充电设备充电电量(kWh),精度:0.001
|
||||||
|
json["charge_num"] = "1"; //充电设备充电次数
|
||||||
|
json["charge_num_err"] = "1"; //充电设备故障次数
|
||||||
|
json["income_elect"] = ""; //发电收益(元),精度:0.01
|
||||||
|
json["income_charge"] = ""; //充电收益(元),精度:0.01
|
||||||
|
json["usage"] = "";
|
||||||
|
return Errcode::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Errcode HttpEntity::queryStatDayList(const httplib::Request& req, httplib::Response& resp, NJsonNode& json)
|
||||||
|
{
|
||||||
|
std::string station_id = req.get_param_value("station_id");
|
||||||
|
std::string category = req.get_param_value("category");
|
||||||
|
std::string dt_start = req.get_param_value("dt_start");
|
||||||
|
std::string dt_end = req.get_param_value("dt_end");
|
||||||
|
|
||||||
|
if (!dt_start.empty() && dt_end.empty())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return Errcode::OK;
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ class HttpEntity
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
httplib::Server httpsvr;
|
httplib::Server httpsvr;
|
||||||
|
HttpEntity();
|
||||||
void listen(std::string addr, int port);
|
void listen(std::string addr, int port);
|
||||||
void registGet(std::string name, void (HttpEntity::* func)(const httplib::Request& req, httplib::Response& resp));
|
void registGet(std::string name, void (HttpEntity::* func)(const httplib::Request& req, httplib::Response& resp));
|
||||||
|
|
||||||
@@ -55,4 +56,7 @@ public:
|
|||||||
|
|
||||||
Errcode queryPredictionDetail(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
Errcode queryPredictionDetail(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||||
|
|
||||||
|
Errcode queryStatSystem(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||||
|
Errcode queryStatTotal(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||||
|
Errcode queryStatDayList(const httplib::Request& req, httplib::Response& resp, NJsonNode& json);
|
||||||
};
|
};
|
||||||
265
src/protocol/MqttEntity.cpp
Normal file
265
src/protocol/MqttEntity.cpp
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
#include "MqttEntity.h"
|
||||||
|
#include "common/Spdlogger.h"
|
||||||
|
#include "common/JsonN.h"
|
||||||
|
|
||||||
|
#define TIMEOUT 10000L
|
||||||
|
|
||||||
|
int MqttClient::init(string addr, string client_id, string username, string password, std::vector<std::string> vecTopic)
|
||||||
|
{
|
||||||
|
this->addr = addr;
|
||||||
|
this->vecTopic = vecTopic;
|
||||||
|
|
||||||
|
MQTTAsync_connectOptions option = MQTTAsync_connectOptions_initializer;
|
||||||
|
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
|
||||||
|
int rc {0};
|
||||||
|
|
||||||
|
// "tcp://localhost:1883"
|
||||||
|
rc = MQTTAsync_create(&client, addr.c_str(), client_id.c_str(), MQTTCLIENT_PERSISTENCE_NONE, NULL);
|
||||||
|
if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
spdlog::error("[mqtt] MQTTAsync_create error: {}", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
MQTTAsync_connectionLost* onConnectionLost =
|
||||||
|
[](void* context, char* cause)
|
||||||
|
{
|
||||||
|
static_cast<MqttClient*>(context)->onConnectionLost(cause);
|
||||||
|
};
|
||||||
|
MQTTAsync_messageArrived* onMessageArrived =
|
||||||
|
[](void* context, char* topicName, int topicLen, MQTTAsync_message* message)->int
|
||||||
|
{
|
||||||
|
return static_cast<MqttClient*>(context)->onMessageArrived(topicName, topicLen, message);
|
||||||
|
};
|
||||||
|
MQTTAsync_deliveryComplete* onDeliveryComplete =
|
||||||
|
[](void* context, MQTTAsync_token token)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//设置连接丢失、接受消息的回调函数
|
||||||
|
rc = MQTTAsync_setCallbacks(client, this, onConnectionLost, onMessageArrived, onDeliveryComplete);
|
||||||
|
if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
spdlog::error("[mqtt] MQTTAsync_setCallbacks error");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
option.keepAliveInterval = 20;
|
||||||
|
option.cleansession = 1;
|
||||||
|
option.onSuccess = [](void* context, MQTTAsync_successData* resp) { static_cast<MqttClient*>(context)->onConnectSuccess(resp); };;
|
||||||
|
option.onFailure = [](void* context, MQTTAsync_failureData* resp) { static_cast<MqttClient*>(context)->onConnectFaiure(resp); };
|
||||||
|
option.context = this;
|
||||||
|
option.username = username.c_str();
|
||||||
|
option.password = password.c_str();
|
||||||
|
|
||||||
|
//断开重连设置
|
||||||
|
option.automaticReconnect = 1;//设置非零,断开自动重连
|
||||||
|
option.minRetryInterval = 5; //单位秒,重连间隔次数,每次重新连接失败时,重试间隔都会加倍,直到最大间隔
|
||||||
|
option.maxRetryInterval = 60;//单位秒,最大重连尝试间隔
|
||||||
|
|
||||||
|
rc = MQTTAsync_connect(client, &option);
|
||||||
|
if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
spdlog::error("[mqtt] MQTTAsync_connect error");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//MQTTAsync_disconnect(client, NULL);
|
||||||
|
//MQTTAsync_destroy(&client);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SubscribInfo
|
||||||
|
{
|
||||||
|
std::function<void(int id)> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
void MqttClient::subscribe(std::vector<std::string> vecTopics, std::function<void(int)> callback)
|
||||||
|
{
|
||||||
|
SubscribInfo* info = new SubscribInfo();
|
||||||
|
info->callback = callback;
|
||||||
|
|
||||||
|
MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
|
||||||
|
options.context = info;
|
||||||
|
options.onSuccess = [](void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
spdlog::info("[mqtt] subscribe success.");
|
||||||
|
SubscribInfo* info = (SubscribInfo*)context;
|
||||||
|
info->callback(0);
|
||||||
|
delete info;
|
||||||
|
|
||||||
|
};
|
||||||
|
options.onFailure = [](void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
spdlog::error("[mqtt] subscribe failed.");
|
||||||
|
SubscribInfo* info = (SubscribInfo*)context;
|
||||||
|
info->callback(-1);
|
||||||
|
delete info;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int count = 3;
|
||||||
|
char* topicsTmp[] = {
|
||||||
|
"topic/aa",
|
||||||
|
"topic/bb",
|
||||||
|
"topic/cc"
|
||||||
|
};
|
||||||
|
std::vector<int> qosTmp(count, 1); // 为每个主题指定 QoS
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
int rc = MQTTAsync_subscribeMany(client, count, topicsTmp, qosTmp.data(), &options);
|
||||||
|
if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
spdlog::error("[mqtt] subscribe failed, err={}", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MqttClient::publish(string topic, string text)
|
||||||
|
{
|
||||||
|
spdlog::info("MQTT publish: topic={}, text={}", topic, text);
|
||||||
|
|
||||||
|
MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
|
||||||
|
//options.onSuccess = onSend;
|
||||||
|
//options.onFailure = onSendFailure;
|
||||||
|
options.context = this;
|
||||||
|
|
||||||
|
MQTTAsync_message msg = MQTTAsync_message_initializer;
|
||||||
|
msg.qos = 1;
|
||||||
|
msg.payload = text.data();
|
||||||
|
msg.payloadlen = text.size();
|
||||||
|
msg.retained = 0;
|
||||||
|
|
||||||
|
int rc = MQTTAsync_sendMessage(client, topic.c_str(), &msg, &options);
|
||||||
|
if (rc == MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
spdlog::info("MQTT send message success, topic={}, text={}", topic, text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spdlog::error("MQTT send message error, topic={}, text={}", topic, text);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MqttClient::onConnectionLost(char* cause)
|
||||||
|
{
|
||||||
|
this->isConnected = false;
|
||||||
|
spdlog::error("MQTT connection lost, cause={}", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* msg)
|
||||||
|
{
|
||||||
|
int len = msg->payloadlen;
|
||||||
|
char* payload = (char*)msg->payload;
|
||||||
|
spdlog::info("MQTT message arrived: topic=[{},{}], payload len={}, payload msg={}", topic, msg->qos, len, payload);
|
||||||
|
|
||||||
|
// 必须释放消息内存!
|
||||||
|
MQTTAsync_freeMessage(&msg);
|
||||||
|
MQTTAsync_free(topic);
|
||||||
|
return 1; // 1表示消息已经处理
|
||||||
|
}
|
||||||
|
|
||||||
|
// 交付完成回调(可选)
|
||||||
|
void MqttClient::onDeliveryComplete(MQTTAsync_token token)
|
||||||
|
{
|
||||||
|
//spdlog::info("MQTT delivery complete, token={}", token);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MqttClient::onConnectSuccess( MQTTAsync_successData* resp)
|
||||||
|
{
|
||||||
|
this->isConnected = true;
|
||||||
|
//spdlog::info("[mqtt] connect success: {}", addr);
|
||||||
|
//MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
|
||||||
|
//options.context = this;
|
||||||
|
//options.onSuccess = [](void* context, MQTTAsync_successData* response)
|
||||||
|
// {
|
||||||
|
// spdlog::info("[mqtt] subscribe success.");
|
||||||
|
// };
|
||||||
|
//options.onFailure = [](void* context, MQTTAsync_failureData* response)
|
||||||
|
// {
|
||||||
|
// spdlog::info("[mqtt] subscribe failed.");
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
//for (auto& topic: vecTopic)
|
||||||
|
//{
|
||||||
|
// int rc = MQTTAsync_subscribe(client, topic.c_str(), qos, &options);
|
||||||
|
// if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
// {
|
||||||
|
// spdlog::error("[mqtt] subscribe [{},{}] failed, err={}", topic, qos, rc);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// spdlog::info("[mqtt] subscribe [{},{}] success", topic, qos);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
void MqttClient::onConnectFaiure(MQTTAsync_failureData* resp)
|
||||||
|
{
|
||||||
|
this->isConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string MQTT::packEquipmentInfo(mqtt::EquipmentInfo& info)
|
||||||
|
{
|
||||||
|
NJsonNode jsonroot;
|
||||||
|
jsonroot["EquipmentID"] = info.EquipmentID.c_str();
|
||||||
|
jsonroot["ManufacturerID"] = info.ManufacturerID.c_str();
|
||||||
|
jsonroot["EquipmentModel"] = info.EquipmentModel.c_str();
|
||||||
|
jsonroot["ProductionDate"] = info.ProductionDate.c_str();
|
||||||
|
jsonroot["OpenForBusinessDate"] = info.OpenForBusinessDate.c_str();
|
||||||
|
jsonroot["EquipmentType"] = info.EquipmentType;
|
||||||
|
return jsonroot.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string MQTT::packSwapEquipmentStatusInfo(string node_id)
|
||||||
|
{
|
||||||
|
NJsonNode jsonroot;
|
||||||
|
return jsonroot.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string MQTT::packNotifyStationInfo()
|
||||||
|
{
|
||||||
|
NJsonNode jsonroot;
|
||||||
|
return jsonroot.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string MQTT::packNotifyAlarm()
|
||||||
|
{
|
||||||
|
NJsonNode jsonroot;
|
||||||
|
return jsonroot.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
string MQTT::packNotifyChargeStatus()
|
||||||
|
{
|
||||||
|
NJsonNode jsonroot;
|
||||||
|
return jsonroot.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
string MQTT::packNotifySwapStatus()
|
||||||
|
{
|
||||||
|
NJsonNode jsonroot;
|
||||||
|
return jsonroot.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
string MQTT::packNotifyChargeOrder()
|
||||||
|
{
|
||||||
|
NJsonNode jsonroot;
|
||||||
|
return jsonroot.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string MQTT::packNotifySwapOrder()
|
||||||
|
{
|
||||||
|
NJsonNode jsonroot;
|
||||||
|
return jsonroot.dump();
|
||||||
|
}
|
||||||
368
src/protocol/MqttEntity.h
Normal file
368
src/protocol/MqttEntity.h
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include "MQTTAsync.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class MqttClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int init(string addr, string client_id, string username, string password, std::vector<std::string> vecTopic);
|
||||||
|
|
||||||
|
void subscribe(std::vector<std::string> topics, std::function<void(int)> callback);
|
||||||
|
|
||||||
|
int publish(string topic, string text);
|
||||||
|
|
||||||
|
void onConnectionLost(char* cause);
|
||||||
|
int onMessageArrived(char* topic, int len, MQTTAsync_message* msg);
|
||||||
|
void onDeliveryComplete(MQTTAsync_token token);
|
||||||
|
|
||||||
|
void onConnectSuccess(MQTTAsync_successData* resp);
|
||||||
|
void onConnectFaiure(MQTTAsync_failureData* resp);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
MQTTAsync client = nullptr;
|
||||||
|
std::vector<std::string> vecTopic;
|
||||||
|
std::string addr; // "tcp://localhost:1883"
|
||||||
|
int qos {1};
|
||||||
|
std::string clientId;
|
||||||
|
bool isConnected {false};
|
||||||
|
bool isSubscribed {false};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// <数据方向>/<数据格式>/<厂家ID>/<指令>/<设备标识,上行可选>
|
||||||
|
// Topic 字段说明
|
||||||
|
// 数据方向 :
|
||||||
|
//·down:下行,用于管理平台向厂家平台发送指令
|
||||||
|
// up :上行,用于厂家平台向管理平台推送设备应答或主报数据数据格式:基础格式为json,其他格式均为对json字符串进行二次编码
|
||||||
|
// json : body内的数据采用json编码
|
||||||
|
// base64 : body内数据先采用ison编码,然后再使用base64编码的字符串
|
||||||
|
// rsa : body内数据先采用json编码,然后采用 rsa 算法加密的base64字符串(rsa 密钥由管理平台提供)
|
||||||
|
// sm2 : body内数据先采用json编码,然后采用 sm2 算法加密的base64字符串(sm2 密钥由管理平台提供)
|
||||||
|
//·厂家ID : 由管理平台定义
|
||||||
|
//·命令ID : 用于指定读取/设置/控制的具体内容,如读取数据,读取时钟等等,具体参考 交互类指令协议设备标识 : 用于标识设备的唯一id,具体定义见3.2中的 context.dev_id 说明,上行时可不提供。
|
||||||
|
|
||||||
|
// <数据方向>/<数据格式>/<厂家ID>/<指令>/<设备标识,上行可选>
|
||||||
|
#define TOPIC_PCS_YC "up/json/预制舱01/PCS_YC"
|
||||||
|
#define TOPIC_PCS_YC "up/json/预制舱01/PCS_YC"
|
||||||
|
|
||||||
|
|
||||||
|
#define MQTT_TOPIC_NOTIFY_STATION "notification_stationInfo" // 充(换)电站信息变化推送
|
||||||
|
#define MQTT_TOPIC_QUERY_STATION "query_stations_info" // 查询充(换)电站信息
|
||||||
|
#define MQTT_TOPIC_NOTIFY_ALARM "notification_alarmInfo" // 告警信息推送
|
||||||
|
#define MQTT_TOPIC_NOTIFY_CHARGE_STATUS "notification_connectorStatus" //充电设备状态变化推送
|
||||||
|
#define MQTT_TOPIC_NOTIFY_SWAP_STATUS "notification_swapStatus" //换电设备状态变化推送
|
||||||
|
#define MQTT_TOPIC_QUERY_STATUS "query_station_status" //查询站内设备接口状态
|
||||||
|
#define MQTT_TOPIC_NOTIFY_CHARGE_ORDER "notification_orderInfo" //充电电量信息推送
|
||||||
|
#define MQTT_TOPIC_QUERY_ORDER "query_order_info" //查询充电电量信息
|
||||||
|
#define MQTT_TOPIC_NOTIFY_SWAP_ORDER "notification_swapInfo" //换电记录信息推送
|
||||||
|
#define MQTT_TOPIC_QUERY_SWAP_ORDER "query_swap_info" //查询换电电量信息
|
||||||
|
|
||||||
|
namespace mqtt
|
||||||
|
{
|
||||||
|
// 充(换)电运营商信息
|
||||||
|
struct OperatorInfo
|
||||||
|
{
|
||||||
|
string OperatorID; // 运营商ID 组织机构代码 是 字符串 9 字符
|
||||||
|
string OperatorName; // 运营商名称 机构全称 是 字符串 <= 64 字符
|
||||||
|
string OperatorTel1; // 运营商电话1 运营商客服电话 1 是 字符串 <= 32 字符
|
||||||
|
string OperatorTel2; // 运营商电话2 运营商客服电话 2 否 字符串 <= 32 字符
|
||||||
|
string OperatorRegAddress; // 运营商注册地址 运营商注册地址 否 字符串 <= 64 字符
|
||||||
|
string OperatorNote; // 备注 备注信息 否 字符串 <= 255 字符
|
||||||
|
};
|
||||||
|
|
||||||
|
// 充(换)电站信息
|
||||||
|
struct StationInfo
|
||||||
|
{
|
||||||
|
string StationID; // 充(换)电站 ID 运营商自定义的唯一编码 是 字符串 <= 20 字 符
|
||||||
|
string OperatorID; // 运营商 ID 电动汽车充(换)电服务平台的运营商 ID 是 字符串 9 字符
|
||||||
|
string EquipmentOwnerID; // 设备所属方 ID 设备所属方组织机构代码,所属方为个人时可不填 否 字符串 9 字符
|
||||||
|
|
||||||
|
string StationName; // 充(换)电站名称 充(换)电站名称的描述 是 字符串 <= 50 字
|
||||||
|
|
||||||
|
string CountryCode; // 充(换)电站国家代码 比如 CN 是 字符串 2 字符
|
||||||
|
string AreaCode; // 充(换)电站省市辖区编码 填写内容为参照 GB / T2260,以民政部发布最新数据为准 是 字符串 <= 20 字符
|
||||||
|
string Address; // 详细地址 是 字符串<= 100字符
|
||||||
|
string StationTel; // 站点电话 能够联系场站工作人员进行协助的联系电话 否 字符串<= 30 字符
|
||||||
|
string ServiceTel; // 服务电话 平台服务电话,例如 400 电话 是 字符串<= 30字符
|
||||||
|
string ServiceType; // *服务类型 1:充电 2:换电 3:充换电 255:其他 是 整型
|
||||||
|
string StationType; // 站点类型 1:公共充(换)电站 2:专用充(换)电站 3:居民充电站 255:其他 是 整型
|
||||||
|
string StationStatus; // 站点状态 0:未知 1:建设中 5:关闭下线 6:维护中 50:正常使用 是 整型
|
||||||
|
string ParkNums; // 车位数量 可停放进行充电的车位总数, 默认:0 未知 是 整型
|
||||||
|
float StationLng; // 经度 GCJ - 02 坐标系 是 浮点型 保留小数点后6 位
|
||||||
|
float StationLat; // 纬度 GCJ - 02 坐标系 是 浮点型保留小数点后6 位
|
||||||
|
string SiteGuide; // 站点引导描述性文字,用于引导车主找到充电车位 否 字符串<= 255字符
|
||||||
|
|
||||||
|
|
||||||
|
int Construction; // 建设场所
|
||||||
|
//101:公共服务场所
|
||||||
|
//102:公共停车场
|
||||||
|
//103:城市交通节点
|
||||||
|
//104:加油站
|
||||||
|
//105:具备停车条件的充电区域
|
||||||
|
//106:高速服务区
|
||||||
|
//201:政府机关
|
||||||
|
//202:公共机构
|
||||||
|
//203:企业事业单位
|
||||||
|
//204:公交
|
||||||
|
//205:环卫
|
||||||
|
//206:物流
|
||||||
|
//207:出租车
|
||||||
|
//208:港口码头
|
||||||
|
//209:重卡换电场所
|
||||||
|
//210:矿卡换电场所
|
||||||
|
//301:居民(小)区
|
||||||
|
//255:其他
|
||||||
|
// 是 整型
|
||||||
|
string Pictures; // 站点照片 充(换)电设备照片、充(换)电车位照片、停车场入口照片 是 字符串数组 无照片时可传空数组
|
||||||
|
string MatchCars; // 服务车型描述 描述该站点可充(换)电服务 的车辆类型:如大巴、物流车、私家乘用车、出租车、重卡型卡车等 否 字符串<= 255字符
|
||||||
|
string ParkInfo; // 车位楼层及数量描述车位楼层以及数量信息 否 字符串<= 100字符
|
||||||
|
int OpenAllDay; // *全天开放 0:否 1:是 是 整型
|
||||||
|
string OpenForBusinessDate; // *投运日期 站点投运日期 yyyy - MM - dd 格式 是 字符串
|
||||||
|
string BusineHours; // 营业时间 营业时间描述 否 字符串<=255字符
|
||||||
|
|
||||||
|
string ElectricityFee; // *电费费率 示例 [{"StartTime":"000000","Price":"1.0000"},{"StartTime":"120000","Price":"1.2000"}] 否 字符串 <= 2000 字符
|
||||||
|
string ServiceFee; // *服务费率 示例[{"StartTime":"000000","Price":"1.0000"},{"StartTime":"120000","Price":"1.2000"}] 否 字符串 <= 2000 字符
|
||||||
|
|
||||||
|
|
||||||
|
string ParkOwner; // *停车场产权方 停车场产权人 否 字符串
|
||||||
|
string ParkManager; // *停车场管理方 停车场管理人(如:XX 物业) 否 字符串
|
||||||
|
int ParkType; // 停车费类型 0:免费 1:不免费 2:限时免费停车 3:充电限时减免 255:参考场地实际收费标准 否 整型
|
||||||
|
string ParkFee; // 停车费描述 停车费率描述 否 字符串 <= 255字符
|
||||||
|
string Payment; // 支付方式 支付方式: 刷卡、线上、现金其中电子钱包类卡为刷卡,身份鉴权卡、微信 / 支付宝等在线支付、APP 支付为线上否 字符串<= 20 字符
|
||||||
|
int SupportOrder; // 是否支持预约 0:不支持预约 1:支持预约。不填默认为 0 否 整型
|
||||||
|
string Remark; // 备注 其他备注信息 否 字符串<= 100字符
|
||||||
|
string EquipmentInfos; // 充电设备信息列表 该充(换)电站所有充电设备 信息对象数组 是 EquipmentInfos[],参照 4.4
|
||||||
|
string SwapEquipmentInfos; // *换电设备信息列表 该充(换)电站所有换电设备。换电站以及充换电站提供此数据,充电站默认空数组。 是 SwapEquipmentInfo[],参照 4.6 换电工位信息
|
||||||
|
int BatteryNo; // *备用电池数量换电站内可提供更换最大电池数量。换电站以及充换电站提供此数据,充电站默认填0。 是 整型
|
||||||
|
};
|
||||||
|
|
||||||
|
// 充电设备信息
|
||||||
|
struct EquipmentInfo
|
||||||
|
{
|
||||||
|
string EquipmentID;
|
||||||
|
string ManufacturerID;
|
||||||
|
string EquipmentModel;
|
||||||
|
string ProductionDate;
|
||||||
|
string OpenForBusinessDate;
|
||||||
|
int EquipmentType;
|
||||||
|
int EquipmentStatus;
|
||||||
|
vector<int> ConnectorInfos;
|
||||||
|
float EquipmentLng;
|
||||||
|
float EquipmentLat;
|
||||||
|
float Power;
|
||||||
|
string EquipmentName;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 充电设备接口信息
|
||||||
|
struct ConnectorInfo
|
||||||
|
{
|
||||||
|
string ConnectorID; // 充电设备接口编码 充电设备接口编码,同一运营商内唯一 是 字符串 <= 64 字符
|
||||||
|
string ConnectorName; // 充电设备接口名称 否 字符串 <= 30 字符
|
||||||
|
int ConnectorType; // 充电设备接口类型
|
||||||
|
//1:家用插座(模式 2)
|
||||||
|
//2:交流接口插座(模式 3,连接方式 B )
|
||||||
|
//3:交流接口插头(带枪线,模式 3,连接方式 C)
|
||||||
|
//4:直流接口枪头(带枪线,模式 4)
|
||||||
|
//5:无线充电座
|
||||||
|
//6:其他
|
||||||
|
//7:对换电站电池箱的接口
|
||||||
|
//是 整型
|
||||||
|
int VoltageUpperLimits; // 额定电压上限 单位:V 是 整型
|
||||||
|
int VoltageLowerLimits; // 额定电压下限 单位:V 交流可与额定电压上限相同 是 整型
|
||||||
|
int ConstantVoltageUpperLimits; // *恒功率电压上限 单位:V 否 整型
|
||||||
|
int ConstantVoltageLowerLimits; // *恒功率电压下限 单位:V 否 整型
|
||||||
|
int Current; // 额定电流 单位:A 是 整型
|
||||||
|
float Power; // 额定功率 单位:kW 是 浮点型 保留小数点后一位
|
||||||
|
string ParkNo; // 车位号 停车场车位编号,或充电架编号 否 字符串 <= 10 字符
|
||||||
|
int NationalStandard; // 国家标准 1:2011 2 : 2015 3 : 兼容 2011 和 2015 是 整型
|
||||||
|
};
|
||||||
|
|
||||||
|
// 换电设备信息(SwapEquipmentInfo)
|
||||||
|
class SwapEquipmentInfo
|
||||||
|
{
|
||||||
|
string EquipmentID; // 设备编码 换电设备唯一编码,同一运营商下唯一 是 字符串 <= 64 字符
|
||||||
|
string ManufacturerID; // 设备生产商组织机构代码 设备生产商组织机构代码 否 字符串 9 字符
|
||||||
|
string EquipmentModel; // 设备型号 由设备生厂商定义的设备型号 否 字符串 <= 20 字符
|
||||||
|
string ProductionDate; // 设备生产日期 YYYY - MM - DD 否 字符串 10 字符
|
||||||
|
string OpenForBusinessDate; // *投运日期 充电桩投运日期 yyyy - MM - dd 格式 是 字符串
|
||||||
|
string OpreateStatus; // 运营状态 0:未知 1:建设中 5:关闭下线 6:维护中 50:正常使用 是 整型
|
||||||
|
int EquipmentType; // 换电设备类型 填写内容为参照GB29317 - 2021 4.3节中的描述 1:侧向换电 2:底部换电 3:顶部换电 4:端部换电 5:中置换电 255:其他 是 整型
|
||||||
|
string MatchCars; // 服务车型描述 描述该设备可服务的车辆类型以及 型号等 否 字符串<= 1000 字符
|
||||||
|
string SupplyBattery; // 提供电池描述 描述该设备提供的电池类型以及型号等 否 字符串<= 100 字符
|
||||||
|
};
|
||||||
|
|
||||||
|
//电池箱信息
|
||||||
|
struct BatteryInfo
|
||||||
|
{
|
||||||
|
string BatteryNo; // 电池箱编号 运营商自定义唯一编码 是 字符串 <= 32 字
|
||||||
|
string BatteryOwnerID; // 电池所属方ID 设备所属方组织机构代码,所属方为个人时可不填 否 字符串 9 字符
|
||||||
|
string ManufacturerID; // 设备生产商组织机构代码 设备生产商组织机构代码 否 字符串 9 字符
|
||||||
|
string BatteryModel; // 电池型号 由设备生厂商定义的设备型号 否 字符串 <= 20 字符
|
||||||
|
string ProductionDate; // 设备生产日期 YYYY - MM - DD 否 字符串 10 字符
|
||||||
|
string OpenForBusinessDate; // 投运日期 电池投运日期 yyyy - MM - dd 格式 是 字符串
|
||||||
|
int CellNum; // 电池箱所含单体电池个数 电池箱所含单体个数 是 整型
|
||||||
|
int SeriesNum; // 单体电池串联总数 串联总数 否 整型
|
||||||
|
int ParallelNum; // 单体电池并联总数 并联总数 否 整型
|
||||||
|
int BatteryType; // 电池类型
|
||||||
|
//1:磷酸铁锂电池
|
||||||
|
//2:锰酸锂电池
|
||||||
|
//3:钴酸锂电池
|
||||||
|
//4:三元材料电池
|
||||||
|
//5:聚合物锂离子电池
|
||||||
|
//6:钛酸锂电池
|
||||||
|
//7:燃料电池
|
||||||
|
//255:其它
|
||||||
|
//是 整型
|
||||||
|
float RatedCapacity; // 电池箱额定容量 单位:Ah,小数点后 1 位 是 浮点型
|
||||||
|
float RatedVoltage; // 电池箱额定电压 单位:V,小数点后 1 位 是 浮点型
|
||||||
|
};
|
||||||
|
|
||||||
|
// 充电设备接口状态
|
||||||
|
struct ConnectorStatusInfo
|
||||||
|
{
|
||||||
|
string ConnectorID; // 充电设备接口编码 充电设备接口编码,同一运营商内唯一 是 字符串<= 64 字符
|
||||||
|
string UpdateTime; // 状态更新时间 本次状态变化的时间,格式“yyyy -MM - dd HH : mm:ss” 是 字符串 <= 20 字符
|
||||||
|
int Status; // 接口状态 0:离线 1:空闲 2:占用(未充电) 3:占用(充电中) 4:占用(预约锁定) 255:故障 是 整型
|
||||||
|
int ParkStatus; // 车位状态 0:未知 10:空闲 50:占用 否 整型
|
||||||
|
int LockStatus; // 地锁状态 0:未知 10:已解锁 50:已上锁 否 整型
|
||||||
|
int CurrentA; // A 相电流 单位:A,默认:0 含直流(输出) 是 整型
|
||||||
|
int CurrentB; // B 相电流 单位:A,默认:0 否 整型
|
||||||
|
int CurrentC; // C 相电流 单位:A,默认:0 否 整型
|
||||||
|
int VoltageA; // A 相电压 单位:V,默认:0 含直流(输出) 是 整型
|
||||||
|
int VoltageB; // B 相电压 单位:V,默认:0 否 整型
|
||||||
|
int VoltageC; // C 相电压 单位:V,默认:0 否 整型
|
||||||
|
float SOC; // *剩余电量 默认:0 交流充电桩采集不到SOC 值的填 0 是 浮点型
|
||||||
|
string Begin_time; // *开始充电时间 格式 为 yyyy-MM-dd HH:mm:ss 是 字符串
|
||||||
|
float Current_kwh; // *本次已充电量 单位:kWh 是 浮点型
|
||||||
|
float Current_meter; // *当前电表读数 单位:kWh 否 浮点型
|
||||||
|
string Vin; // *车架号 否 字符串 <= 20 字符
|
||||||
|
//BatteryStatusInfo //*电池状态信息 充电设备有电池情况下需上报 是 BatteryStatusInfo,参照4.9
|
||||||
|
};
|
||||||
|
|
||||||
|
// 电池箱状态
|
||||||
|
struct BatteryStatusInfo
|
||||||
|
{
|
||||||
|
string BatteryNo; // 电池箱编号 (充电设备有电池情况下需上报) 是 字符串<= 32 字符
|
||||||
|
string UpdateTime; // 状态更新时间 本次状态变化的时间,格式“yyyy -MM - dd HH : mm:ss” 是 字符串 <= 20 字符
|
||||||
|
float Voltage; // 当前电压 单位:V,小数点后 2 位 (充电设备有电池情况下需上报) 是 浮点型
|
||||||
|
float Current; // 当前电流 单位:V,小数点后 2 位 (充电设备有电池情况下需上报) 是 浮点型
|
||||||
|
float SOC; // 当前 Soc 当前电池电量百分比,范围:0~100,小数点后 1 位 (充电设备有电池情况下需上报) 是 浮点型
|
||||||
|
float SOH; // 当前 Soh 当前电池健康度,范围:0~100,小数点后 1 位(充电设备有电池情况下需上报)是 浮点型
|
||||||
|
int BatteryIsFault; // 电池箱是否故障 0:未知 1:是 2:否 (充电设备有电池情况下需上报) 是 整型
|
||||||
|
int MaxVoltageBatteryNo; // 最高电压单体电池编号 充电设备有电池情况下需上报 否 整型
|
||||||
|
float MaxVoltage; // 最高电压单体电池电压值单位: V,小数点后3位 充电设备有电池情况下需上报 否 浮点型
|
||||||
|
int MinVoltageBatteryNo; // 最低电压单体电池编号 充电设备有电池情况下需上报 否 整型
|
||||||
|
float MinVoltage; // 最低电压单体电池电压值 单位: V,小数点后 3 位 充电设备有电池情况下需上报 否 浮点型
|
||||||
|
float MaxTempBatteryNo; // 最高温度测温点编号 充电设备有电池情况下需上报 否 整型
|
||||||
|
int MaxTemp; // 最高温度测温点温度值 单位:℃ 充电设备有电池情况下需上报 否 整型
|
||||||
|
int MinTempBatteryNo; // 最低温度测温点编号 充电设备有电池情况下需上报 否 整型
|
||||||
|
int MinTemp; // 最低温度测温点温度值 单位:℃ 充电设备有电池情况下需上报 否 整型
|
||||||
|
};
|
||||||
|
|
||||||
|
// 换电设备状态(SwapEquipmentStatusInfo)
|
||||||
|
struct SwapEquipmentStatusInfo
|
||||||
|
{
|
||||||
|
string EquipmentID; // 换电设备编码 换电设备编码,同一运营商内唯一 是 字符串 <= 64 字符
|
||||||
|
string UpdateTime; // 状态更新时间 本次状态变化的时间,格式“yyyy - MM - dd HH : mm:ss” 是 字符串 <= 20 字符
|
||||||
|
int Status; // 换电设备状态 0:离线 1:空闲 2:工作 255:故障 是 整型
|
||||||
|
int SwapMode; // 换电模式 0:手动模式 1:半自动模式 2:全自动模式 3:检修模式 否 整型
|
||||||
|
};
|
||||||
|
|
||||||
|
// 充(换)电站状态(StationStatusInfo)
|
||||||
|
struct StationStatusInfo
|
||||||
|
{
|
||||||
|
string StationID; // 充(换)电站 ID 运营商自定义的唯一编码 是 字符串 <= 20 字符
|
||||||
|
string ConnectorStatusInfos; // 充电设备接口状态列表 充(换)电站下所有充电设备接口的状态对象数组 是 ConnectorStatusInfos[], 参照 5.6
|
||||||
|
|
||||||
|
string SwapEquipmentStatusInfo; // 换电设备状态列 所有充电设备接口的是 SwapEquipmentStatusInfo[]表 状态 ,参照4.10
|
||||||
|
};
|
||||||
|
|
||||||
|
//充电电量信息(OrderInfo)
|
||||||
|
struct OrderInfo
|
||||||
|
{
|
||||||
|
string OperatorID; // 运营商 ID 统一社会信用代码 是 字符串 9 字符
|
||||||
|
string ConnectorID; // 充电设备接口编码 充电设备接口编码,同一充(换)电运营平台内唯一 是 字符串 <= 26 字符
|
||||||
|
string StartChargeSeq; // 充电业务编号 运营商充电业务编号 是 字符串 <= 32 字符
|
||||||
|
int UserChargeType; // 用户发起充电类型 1:充(换)电运营平台注册用户 2 : 监管平台注册用户 3 : 其他 否 整型
|
||||||
|
string MobileNumber; // 用户手机号 若用户发起充电类型为APP,用户手机号必填否 字符串
|
||||||
|
float Money; // 本次充电消费总金额 单位:元 若通过苏e充APP启动,此字段为必填项。 否 浮点型
|
||||||
|
float ElectMoney; // 本次充电电费总金额 单位:元 若通过苏e充APP启动,此字段为必填项。 否 浮点型
|
||||||
|
float ServiceMoney; // 本次充电服务费金额 单位:元 若通过苏e充APP启动,此字段为必填项。 否 浮点型
|
||||||
|
float Elect; // 本次充电电量 单位 kWh,精度0.001,如果不设置峰谷电价,平电量等于本次充电电量,其他分电量为零。 是 浮点型
|
||||||
|
float CuspElect; // *尖阶段电量 单位 kWh,精度0.001 是 浮点型
|
||||||
|
float PeakElect; // *峰阶段电量 单位 kWh,精度0.001 是 浮点型
|
||||||
|
float FlatElect; // *平阶段电量 单位 kWh,精度0.001, 是 浮点型
|
||||||
|
float ValleyElect; // *谷阶段电量 单位 kWh,精度0.001 是 浮点型
|
||||||
|
float StartTime; // 本次充电开始时间 格式“yyyy - MM - ddHH : mm:ss” 是 字符串
|
||||||
|
float EndTime; // 本次充电结束时间 格式“yyyy - MM - ddHH : mm: ss” 是 字符串
|
||||||
|
float PaymentAmount; // 支付金额 支付金额 若通过苏e充APP启动,此字段为必填项。 否 浮点型 保留小数点后 2 位
|
||||||
|
float MeterValueStart; // *电表总起值 单位 kWh,精度0.001 是 浮点型 保留小数点后三位
|
||||||
|
float MeterValueEnd; // *电表总止值 单位 kWh,精度0.001 是 浮点型 保留小数点后三位
|
||||||
|
float Vin; // *本次充电车架号 充电设备有车辆VIN码需上报 否 字符串 <= 64 字符
|
||||||
|
float BatteryNo; // *本次充电电池编号 充电设备有电池情况下需上报 否 字符串 <= 64 字符
|
||||||
|
float ExchangeChargeSeq;// *换电记录编号 格式“运营商 ID + 唯一编号”,27 字符,如果有对应的换电记录需要填写是 字符串 <= 40 字符
|
||||||
|
};
|
||||||
|
|
||||||
|
// 换电记录信息(SwapInfo)
|
||||||
|
struct SwapInfo
|
||||||
|
{
|
||||||
|
string OperatorID; //运营商 ID 统一社会信用代码 是 字符串 9 字符
|
||||||
|
string EquipmentID; // 换电设备编码 换电设备接口编码,同一充(换)电运营平台内唯一 是 字符串 <= 40 字符
|
||||||
|
|
||||||
|
string ExchangeChargeSeq; // 换电记录编号 格式“运营商 ID + 唯一编号”,27 字 符 是 字符串
|
||||||
|
string SwapMode; // 换电模式 0:手动模式 1:半自动模式 2:全自动模式 3:检修模式 否 整型
|
||||||
|
string CarNo; // 车牌号 否 字符串 <= 16 字符
|
||||||
|
string Vin; // 车辆VIN码 车辆识别码;见GB - T - 27930 - 2015国标PGN512 BMS 和车辆辨识报文(BRM)约定 否 字符串
|
||||||
|
string RepDownBatteryNo;// 换下电池箱编号 运营商自定义唯一 编码, 是 字符串 <= 32 字符
|
||||||
|
string RepDownBatterySoc;// 换下电池箱SOC 电池电量百分比,范围:0~100, 是 整型
|
||||||
|
string RepOnBatteryNo;//换上电池箱编号 运营商自定义唯一编码,是 字符串 <= 32 字符
|
||||||
|
int RepOnBatterySoc; //换上电池箱SOC 电池电量百分比,范围:0~100 是 整型
|
||||||
|
float TotalPower; //换上电池箱总充入电量 单位:度(kWh) 是 浮点型 保留小数点后两位
|
||||||
|
string StartTime; //换电开始时间 格式“yyyy - MM - dd HH : mm:ss” 是 字符串
|
||||||
|
string EndTime; //换电结束时间 格式“yyyy - MM - dd HH : mm: ss” 是 字符串
|
||||||
|
};
|
||||||
|
|
||||||
|
// 充(换)电设备告警信息(AlarmInfo)
|
||||||
|
struct AlarmInfo
|
||||||
|
{
|
||||||
|
string EquipmentID; // 设备编码 充电接口唯一编码,对同一运营商,保证唯一 是 字符串 23 字符
|
||||||
|
int EquipmentType; //设备类型 1:充电设备 2:换电设备 整型
|
||||||
|
string Alert_time; //告警时间 格 式 为 yyyy - MMdd HH : mm:ss 是 字符串
|
||||||
|
int Alert_code; //告警代码 告警代码 是 整型
|
||||||
|
string Describe; //描述 文字描述,最大长度 256字符。是 字符串 256 字符
|
||||||
|
int Status; //状态 告警发生:0;告警 恢复: 1,默认为 0。是 整型
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MQTT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static string packEquipmentInfo(mqtt::EquipmentInfo& info);
|
||||||
|
|
||||||
|
static string packSwapEquipmentStatusInfo(string node_name);
|
||||||
|
|
||||||
|
// 充(换)电站信息变化推送
|
||||||
|
static string packNotifyStationInfo();
|
||||||
|
|
||||||
|
// 告警信息推送
|
||||||
|
static string packNotifyAlarm();
|
||||||
|
|
||||||
|
// 充电设备状态变化推送, 充电启停或者离线状态改变时推送,充电过程中每分钟一次推送
|
||||||
|
static string packNotifyChargeStatus();
|
||||||
|
|
||||||
|
// 换电设备状态变化推送
|
||||||
|
static string packNotifySwapStatus();
|
||||||
|
|
||||||
|
// 充电电量信息推送(chon), 充电结束后5分钟内推送
|
||||||
|
static string packNotifyChargeOrder();
|
||||||
|
|
||||||
|
// 换电记录信息推送, 换电结束后5分钟内推送
|
||||||
|
static string packNotifySwapOrder();
|
||||||
|
};
|
||||||
11882
thirdparty/cpp-httplib-0.25.0/httplib.h
vendored
Normal file
11882
thirdparty/cpp-httplib-0.25.0/httplib.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
47
thirdparty/paho_mqtt/CODE_OF_CONDUCT.md
vendored
Normal file
47
thirdparty/paho_mqtt/CODE_OF_CONDUCT.md
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Community Code of Conduct
|
||||||
|
|
||||||
|
**Version 1.2
|
||||||
|
August 19, 2020**
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as community members, contributors, committers, and project leaders pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
With the support of the Eclipse Foundation staff (the “Staff”), project committers and leaders are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project committers and leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the Eclipse Foundation project or its community in public spaces. Examples of representing a project or community include posting via an official social media account, or acting as a project representative at an online or offline event. Representation of a project may be further defined and clarified by project committers, leaders, or the EMO.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Staff at codeofconduct@eclipse.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The Staff is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project committers or leaders who do not follow the Code of Conduct in good faith may face temporary or permanent repercussions as determined by the Staff.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org) , version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct/)
|
||||||
|
|
||||||
63
thirdparty/paho_mqtt/CONTRIBUTING.md
vendored
Normal file
63
thirdparty/paho_mqtt/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# Contributing to Paho
|
||||||
|
|
||||||
|
Thanks for your interest in this project!
|
||||||
|
|
||||||
|
You can contribute bugfixes and new features by sending pull requests through GitHub.
|
||||||
|
|
||||||
|
## Legal
|
||||||
|
|
||||||
|
In order for your contribution to be accepted, it must comply with the Eclipse Foundation IP policy.
|
||||||
|
|
||||||
|
Please read the [Eclipse Foundation policy on accepting contributions via Git](http://wiki.eclipse.org/Development_Resources/Contributing_via_Git).
|
||||||
|
|
||||||
|
1. Sign the [Eclipse ECA](http://www.eclipse.org/legal/ECA.php)
|
||||||
|
1. Register for an Eclipse Foundation User ID. You can register [here](https://dev.eclipse.org/site_login/createaccount.php).
|
||||||
|
2. Log into the [Eclipse projects forge](https://www.eclipse.org/contribute/cla), and click on 'Eclipse Contributor Agreement'.
|
||||||
|
2. Go to your [account settings](https://dev.eclipse.org/site_login/myaccount.php#open_tab_accountsettings) and add your GitHub username to your account.
|
||||||
|
3. Make sure that you _sign-off_ your Git commits in the following format:
|
||||||
|
``` Signed-off-by: Alex Smith <alexsmith@nowhere.com> ``` This is usually at the bottom of the commit message. You can automate this by adding the '-s' flag when you make the commits. e.g. ```git commit -s -m "Adding a cool feature"```
|
||||||
|
4. Ensure that the email address that you make your commits with is the same one you used to sign up to the Eclipse Foundation website with.
|
||||||
|
|
||||||
|
## Contributing a change
|
||||||
|
|
||||||
|
1. [Fork the repository on GitHub](https://github.com/eclipse/paho.mqtt.c/fork)
|
||||||
|
2. Clone the forked repository onto your computer: ``` git clone https://github.com/<your username>/paho.mqtt.c.git ```
|
||||||
|
3. Create a new branch from the latest ```develop``` branch with ```git checkout -b YOUR_BRANCH_NAME origin/develop```
|
||||||
|
4. Make your changes
|
||||||
|
5. If developing a new feature, make sure to include JUnit tests.
|
||||||
|
6. Ensure that all new and existing tests pass.
|
||||||
|
7. Commit the changes into the branch: ``` git commit -s ``` Make sure that your commit message is meaningful and describes your changes correctly.
|
||||||
|
8. If you have a lot of commits for the change, squash them into a single / few commits.
|
||||||
|
9. Push the changes in your branch to your forked repository.
|
||||||
|
10. Finally, go to [https://github.com/eclipse/paho.mqtt.c](https://github.com/eclipse/paho.mqtt.c) and create a pull request from your "YOUR_BRANCH_NAME" branch to the ```develop``` one to request review and merge of the commits in your pushed branch.
|
||||||
|
|
||||||
|
What happens next depends on the content of the patch.
|
||||||
|
If it is 100% authored by the contributor with less than 1000 lines of new product code that meets
|
||||||
|
the needs of the project (refactored, test code and sample code is excluded from the count), then it
|
||||||
|
can be pulled into the main repository. When there are more than 1000 lines of new product code,
|
||||||
|
more steps are required. More details are provided in the [handbook](https://www.eclipse.org/projects/handbook/#ip).
|
||||||
|
|
||||||
|
## Developer resources:
|
||||||
|
|
||||||
|
|
||||||
|
Information regarding source code management, builds, coding standards, and more.
|
||||||
|
|
||||||
|
- [https://projects.eclipse.org/projects/iot.paho/developer](https://projects.eclipse.org/projects/iot.paho/developer)
|
||||||
|
|
||||||
|
Contact:
|
||||||
|
--------
|
||||||
|
|
||||||
|
Contact the project developers via the project's development
|
||||||
|
[mailing list](https://dev.eclipse.org/mailman/listinfo/paho-dev).
|
||||||
|
|
||||||
|
Search for bugs:
|
||||||
|
----------------
|
||||||
|
|
||||||
|
This project uses GitHub Issues here: [github.com/eclipse/paho.mqtt.c/issues](https://github.com/eclipse/paho.mqtt.c/issues) to track ongoing development and issues.
|
||||||
|
|
||||||
|
Create a new bug:
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Be sure to search for existing bugs before you create another one. Remember that contributions are always welcome!
|
||||||
|
|
||||||
|
- [Create new Paho bug](https://github.com/eclipse/paho.mqtt.c/issues/new)
|
||||||
13
thirdparty/paho_mqtt/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
13
thirdparty/paho_mqtt/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
Thank you for your interest in this project managed by the Eclipse Foundation.
|
||||||
|
|
||||||
|
The guidelines for contributions can be found in the CONTRIBUTING.md file.
|
||||||
|
|
||||||
|
At a minimum, you must sign the Eclipse ECA, and sign off each commit.
|
||||||
|
|
||||||
|
To complete and submit a ECA, log into the Eclipse projects forge
|
||||||
|
You will need to create an account with the Eclipse Foundation if you have not already done so.
|
||||||
|
Be sure to use the same email address when you register for the account that you intend to use when you commit to Git.
|
||||||
|
Go to https://accounts.eclipse.org/user/eca to sign the Eclipse ECA.
|
||||||
|
|
||||||
|
|
||||||
358
thirdparty/paho_mqtt/README.md
vendored
Normal file
358
thirdparty/paho_mqtt/README.md
vendored
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
[](https://travis-ci.org/eclipse/paho.mqtt.c)
|
||||||
|
[](https://lgtm.com/projects/g/eclipse/paho.mqtt.c/alerts/)
|
||||||
|
[](https://scan.coverity.com/projects/paho-c)
|
||||||
|
|
||||||
|
# Eclipse Paho C Client Library for the MQTT Protocol
|
||||||
|
|
||||||
|
This repository contains the source code for the [Eclipse Paho](http://eclipse.org/paho) MQTT C client library.
|
||||||
|
|
||||||
|
This code builds libraries which enable applications to connect to an [MQTT](http://mqtt.org) broker to publish messages, and to subscribe to topics and receive published messages.
|
||||||
|
|
||||||
|
Synchronous and various asynchronous programming models are supported.
|
||||||
|
|
||||||
|
## Information About MQTT
|
||||||
|
|
||||||
|
* [MQTT website](http://mqtt.org)
|
||||||
|
* [The MQTT 3.1.1 standard](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html)
|
||||||
|
* [The MQTT 5.0 standard](https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html)
|
||||||
|
* [HiveMQ introduction to MQTT](https://www.hivemq.com/mqtt/)
|
||||||
|
* [OASIS Introduction to MQTT presentation](https://www.oasis-open.org/committees/download.php/49205/MQTT-OASIS-Webinar.pdf)
|
||||||
|
|
||||||
|
## Libraries
|
||||||
|
|
||||||
|
The Paho C client comprises four variant libraries, shared or static:
|
||||||
|
|
||||||
|
* paho-mqtt3a - asynchronous (MQTTAsync)
|
||||||
|
* paho-mqtt3as - asynchronous with SSL/TLS (MQTTAsync)
|
||||||
|
* paho-mqtt3c - "classic" / synchronous (MQTTClient)
|
||||||
|
* paho-mqtt3cs - "classic" / synchronous with SSL/TLS (MQTTClient)
|
||||||
|
|
||||||
|
[Which Paho C API to use, with some history, for context](https://modelbasedtesting.co.uk/2013/10/13/which-paho-mqtt-c-api-to-use-and-some-history/)
|
||||||
|
|
||||||
|
## Usage and API
|
||||||
|
|
||||||
|
Detailed API documentation [is available online](https://eclipse-paho.github.io/paho.mqtt.c/MQTTClient/html/). It is also available by building the Doxygen docs in the ``doc`` directory.
|
||||||
|
|
||||||
|
Samples are available in the Doxygen docs and also in `src/samples` for reference. These are:
|
||||||
|
|
||||||
|
- *paho_c_pub.c* and *paho_c_sub.c:* command line utilities to publish and subscribe, -h will give help
|
||||||
|
- *paho_cs_pub.c* and *paho_cs_sub.c:* command line utilities using MQTTClient to publish and subscribe
|
||||||
|
- *MQTTClient_publish.c, MQTTClient_subscribe.c* and *MQTTClient_publish_async.c:* MQTTClient simple code examples
|
||||||
|
- *MQTTAsync_publish.c* and *MQTTAsync_subscribe.c:* MQTTAsync simple code examples
|
||||||
|
|
||||||
|
Some potentially useful blog posts:
|
||||||
|
|
||||||
|
- [Paho client MQTT 5.0 support and command line utilities](https://modelbasedtesting.co.uk/2018/08/08/paho-c-client-mqtt-5-0-and-command-line-utilities/)
|
||||||
|
- [MQTT, QoS and persistence](https://modelbasedtesting.co.uk/2013/11/24/mqtt-qos-and-persistence/)
|
||||||
|
- [A story of MQTT 5.0](https://modelbasedtesting.co.uk/2018/04/09/a-story-of-mqtt-5-0/)
|
||||||
|
|
||||||
|
[Various MQTT and MQTT-SN talks I've given.](https://modelbasedtesting.co.uk/talks-ive-given/)
|
||||||
|
|
||||||
|
### Supported Network Protocols
|
||||||
|
|
||||||
|
The library supports connecting to an MQTT server using TCP, SSL/TLS, Unix-domain sockets, and websockets (secure and insecure). This is chosen by the client using the URI supplied in the connect options. It can be specified as:
|
||||||
|
|
||||||
|
"mqtt://<host>:<port>" - TCP, unsecure
|
||||||
|
"tcp://<host>:<port>" (same)
|
||||||
|
|
||||||
|
"mqtts://<host>:<port>" - SSL/TLS
|
||||||
|
"ssl://<host>:<port>" (same)
|
||||||
|
|
||||||
|
"unix:///path/to/socket - UNIX-domain socket (*nix systems only)
|
||||||
|
|
||||||
|
"ws://<host>:<port>[/path]" - Websockets, unsecure
|
||||||
|
"wss://<host>:<port>[/path]" - Websockets, secure
|
||||||
|
|
||||||
|
The "mqtt://" and "tcp://" schemas are identical. They indicate an insecure connection over TCP. The "mqtt://" variation is new for the library, but becoming more common across different MQTT libraries.
|
||||||
|
|
||||||
|
Similarly, the "mqtts://" and "ssl://" schemas are identical. They specify a secure connection over SSL/TLS sockets. The use any of the secure connect options requires that you compile the library with the `PAHO_WITH_SSL=TRUE` CMake option to include OpenSSL. In addition, you _must_ specify `ssl_options` when you connect to the broker - i.e. you must add an instance of `ssl_options` to the `connect_options` when calling `connect()`.
|
||||||
|
|
||||||
|
The use of Unix-domain sockets requires the build option of `PAHO_WITH_UNIX_SOCKETS=TRUE` is required. This is only available on *nix-style systems like Linux and macOS. It is not vailable on Windows.
|
||||||
|
|
||||||
|
## Runtime tracing
|
||||||
|
|
||||||
|
A number of environment variables control runtime tracing of the C library.
|
||||||
|
|
||||||
|
Tracing is switched on using `MQTT_C_CLIENT_TRACE` (a value of ON traces to stdout, any other value should specify a file to trace to).
|
||||||
|
|
||||||
|
The verbosity of the output is controlled using the `MQTT_C_CLIENT_TRACE_LEVEL` environment variable - valid values are ERROR, PROTOCOL, MINIMUM, MEDIUM and MAXIMUM (from least to most verbose).
|
||||||
|
|
||||||
|
The variable `MQTT_C_CLIENT_TRACE_MAX_LINES` limits the number of lines of trace that are output.
|
||||||
|
|
||||||
|
```
|
||||||
|
export MQTT_C_CLIENT_TRACE=ON
|
||||||
|
export MQTT_C_CLIENT_TRACE_LEVEL=PROTOCOL
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reporting bugs
|
||||||
|
|
||||||
|
Please open issues in the Github project: https://github.com/eclipse-paho/paho.mqtt.c/issues.
|
||||||
|
|
||||||
|
## More information
|
||||||
|
|
||||||
|
Discussion of the Paho clients takes place on the [Eclipse paho-dev mailing list](https://dev.eclipse.org/mailman/listinfo/paho-dev).
|
||||||
|
|
||||||
|
## Follow Eclipse Paho on Twitter: [@eclipsepaho](https://twitter.com/eclipsepaho)
|
||||||
|
|
||||||
|
General questions about the MQTT protocol are discussed in the [MQTT Google Group](https://groups.google.com/forum/?hl=en-US&fromgroups#!forum/mqtt).
|
||||||
|
|
||||||
|
There is more information available via the [MQTT community site](http://mqtt.org).
|
||||||
|
|
||||||
|
|
||||||
|
## Building with CMake
|
||||||
|
|
||||||
|
The build process currently supports a number of Linux "flavors" including ARM and s390, OS X, AIX and Solaris as well as the Windows operating system. The build process requires the following tools:
|
||||||
|
* [CMake](http://cmake.org)
|
||||||
|
* [GNU Make](https://www.gnu.org/software/make/) or [Ninja](https://martine.github.io/ninja/)
|
||||||
|
* A conforming C compiler, such as [gcc](https://gcc.gnu.org/), [Clang](https://clang.llvm.org/), etc
|
||||||
|
|
||||||
|
On Debian based systems this would mean that the following packages have to be installed:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ apt-get install build-essential gcc make cmake cmake-gui cmake-curses-gui
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, in order to build a debian package from the source code, the following packages have to be installed
|
||||||
|
|
||||||
|
```
|
||||||
|
$ apt-get install fakeroot devscripts dh-make lsb-release
|
||||||
|
```
|
||||||
|
|
||||||
|
Ninja can be downloaded from its github project page in the "releases" section. Optionally it is possible to build binaries with SSL/TLS support. This requires the OpenSSL libraries and includes to be available. E. g. on Debian:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ apt-get install libssl-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
The documentation requires doxygen and optionally graphviz:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ apt-get install doxygen graphviz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building your application with CMake
|
||||||
|
|
||||||
|
If the Paho C library was built with CMake and is already installed on the system, it is relatively easy to set up a CMake build for your application. (If it's not already built and installed read the next section).
|
||||||
|
|
||||||
|
The library can be built with several options which create variations of the library for asynchronous or synchronous use; encryption (SSL/TLS) support or not; and whether the library is shared or static. CMake exports all of the libraries that were built as targets, and the user can chose which is best suited for an application.
|
||||||
|
|
||||||
|
The package is named: **eclipse-paho-mqtt-c**
|
||||||
|
|
||||||
|
The namespace for all the targets is also: **eclipse-paho-mqtt-c**
|
||||||
|
|
||||||
|
The target names are the same as the library names. The static libraries append *-static* to the target name even for platforms that use the same base name for shared and static libraries. So:
|
||||||
|
|
||||||
|
Target|Description
|
||||||
|
------|-----------
|
||||||
|
paho-mqtt3a | asynchronous, no encryption
|
||||||
|
paho-mqtt3as | asynchronous with SSL/TLS support
|
||||||
|
paho-mqtt3c | synchronous, no encryption
|
||||||
|
paho-mqtt3cs | synchronous with SSL/TLS support
|
||||||
|
paho-mqtt3a-static | asynchronous, no encryption, static linkage
|
||||||
|
paho-mqtt3as-static | asynchronous with SSL/TLS support, static linkage
|
||||||
|
paho-mqtt3c-static | synchronous, no encryption, static linkage
|
||||||
|
paho-mqtt3cs-static | synchronous with SSL/TLS support, static linkage
|
||||||
|
|
||||||
|
Remember, though, that not all of these targets may be available. It depends on how the library was built.
|
||||||
|
|
||||||
|
A sample *CMakeLists.txt* for an application that uses the asynchronous library with encryption support *(paho-mqtt3as)* might look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
project(MyMQTTApp VERSION 1.0.0 LANGUAGES C)
|
||||||
|
|
||||||
|
find_package(eclipse-paho-mqtt-c REQUIRED)
|
||||||
|
|
||||||
|
add_executable(MyMQTTApp MyMQTTApp.c)
|
||||||
|
target_link_libraries(MQTTVersion eclipse-paho-mqtt-c::paho-mqtt3as)
|
||||||
|
```
|
||||||
|
|
||||||
|
If the library was installed to a non-traditional location, you may need to tell CMake where to find it using `CMAKE_PREFIX_PATH`. For example, if you installed it in */opt/mqtt/paho.mqtt.c*
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cmake -DCMAKE_PREFIX_PATH=/opt/mqtt/paho.mqtt.c ..
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building the Paho C library with CMake
|
||||||
|
|
||||||
|
Before compiling, determine the value of some variables in order to configure features, library locations, and other options:
|
||||||
|
|
||||||
|
Variable | Default Value | Description
|
||||||
|
------------ | ------------- | -------------
|
||||||
|
PAHO_BUILD_SHARED | TRUE | Build a shared version of the libraries
|
||||||
|
PAHO_BUILD_STATIC | FALSE | Build a static version of the libraries
|
||||||
|
PAHO_HIGH_PERFORMANCE | FALSE | When set to true, the debugging aids internal tracing and heap tracking are not included.
|
||||||
|
PAHO_WITH_SSL | FALSE | Flag that defines whether to build ssl-enabled binaries too.
|
||||||
|
OPENSSL_ROOT_DIR | "" (system default) | Directory containing your OpenSSL installation (i.e. `/usr/local` when headers are in `/usr/local/include` and libraries are in `/usr/local/lib`)
|
||||||
|
PAHO_WITH_LIBRESSL | FALSE | Flag that defines whether to build ssl-enabled binaries with LibreSSL instead of OpenSSL.
|
||||||
|
LIBRESSL_ROOT_DIR | "" (system default) | Directory containing your LibreSSL installation (i.e. `/usr/local` when headers are in `/usr/local/include` and libraries are in `/usr/local/lib`)
|
||||||
|
PAHO_WITH_UNIX_SOCKETS | FALSE | (*nix systems only) Flag to enable support for UNIX-domain sockets
|
||||||
|
PAHO_BUILD_DOCUMENTATION | FALSE | Create and install the HTML based API documentation (requires Doxygen)
|
||||||
|
PAHO_BUILD_SAMPLES | FALSE | Build sample programs
|
||||||
|
PAHO_ENABLE_TESTING | TRUE | Build test and run
|
||||||
|
MQTT_TEST_BROKER | tcp://localhost:1883 | MQTT connection URL for a broker to use during test execution
|
||||||
|
MQTT_TEST_PROXY | tcp://localhost:1883 | Hostname of the test proxy to use
|
||||||
|
MQTT_SSL_HOSTNAME | localhost | Hostname of a test SSL MQTT broker to use
|
||||||
|
PAHO_BUILD_DEB_PACKAGE | FALSE | Build debian package
|
||||||
|
|
||||||
|
Using these variables CMake can be used to generate your Ninja or Make files. Using CMake, building out-of-source is the default. Therefore it is recommended to invoke all build commands inside your chosen build directory but outside of the source tree.
|
||||||
|
|
||||||
|
An example build session targeting the build platform could look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mkdir /tmp/build.paho ; cd /tmp/build.paho
|
||||||
|
$ cmake -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_DOCUMENTATION=TRUE \
|
||||||
|
-DPAHO_BUILD_SAMPLES=TRUE ~/paho.mqtt.c
|
||||||
|
```
|
||||||
|
|
||||||
|
Invoking cmake and specifying build options can also be performed using cmake-gui or ccmake (see https://cmake.org/runningcmake/). For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ccmake ~/paho.mqtt.c
|
||||||
|
```
|
||||||
|
|
||||||
|
To compile/link the binaries, to install, or to generate packages, use these commands:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cmake --build .
|
||||||
|
|
||||||
|
$ cmake --build . --target install
|
||||||
|
|
||||||
|
$ cmake --build . --target package
|
||||||
|
```
|
||||||
|
|
||||||
|
To build, install, or generate packages, you can also use the generated builder like _ninja_ or _make_ directly after invoking the initial CMake configuration step, such as `ninja package` or `make -j <number-of-jpbs> package`.
|
||||||
|
|
||||||
|
### Debug builds
|
||||||
|
|
||||||
|
Debug builds can be performed by defining the value of the `CMAKE_BUILD_TYPE` option to `Debug`. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cmake -DCMAKE_BUILD_TYPE=Debug ~/paho.mqtt.c
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running the tests
|
||||||
|
|
||||||
|
Test code is available in the `test` directory. The tests can be built and executed with the CMake build system. The test execution requires a MQTT broker running. By default, the build system uses `localhost`, however it is possible to configure the build to use an external broker. These parameters are documented in the Build Requirements section above.
|
||||||
|
|
||||||
|
After ensuring a MQTT broker is available, it is possible to execute the tests by starting the proxy and running `ctest` as described below:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python ../test/mqttsas.py &
|
||||||
|
$ ctest -VV
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cross compilation
|
||||||
|
|
||||||
|
Cross compilation using CMake is performed by using so called "toolchain files" (see: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html).
|
||||||
|
|
||||||
|
The path to the toolchain file can be specified by using CMake's `-DCMAKE_TOOLCHAIN_FILE` option. In case no toolchain file is specified, the build is performed for the native build platform.
|
||||||
|
|
||||||
|
For your convenience toolchain files for the following platforms can be found in the `cmake` directory of Eclipse Paho:
|
||||||
|
* Linux x86
|
||||||
|
* Linux ARM11 (a.k.a. the Raspberry Pi)
|
||||||
|
* Windows x86_64
|
||||||
|
* Windows x86
|
||||||
|
|
||||||
|
The provided toolchain files assume that required compilers/linkers are to be found in the environment, i. e. the PATH-Variable of your user or system. If you prefer, you can also specify the absolute location of your compilers in the toolchain files.
|
||||||
|
|
||||||
|
Example invocation for the Raspberry Pi:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cmake -GNinja -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_SAMPLES=TRUE \
|
||||||
|
-DPAHO_BUILD_DOCUMENTATION=TRUE \
|
||||||
|
-DOPENSSL_LIB_SEARCH_PATH=/tmp/libssl-dev/usr/lib/arm-linux-gnueabihf \
|
||||||
|
-DOPENSSL_INC_SEARCH_PATH="/tmp/libssl-dev/usr/include/openssl;/tmp/libssl-dev/usr/include/arm-linux-gnueabihf" \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=~/paho.mqtt.c/cmake/toolchain.linux-arm11.cmake \
|
||||||
|
~/paho.mqtt.c
|
||||||
|
```
|
||||||
|
|
||||||
|
Compilers for the Raspberry Pi and other ARM targets can be obtained from ARM (https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads)
|
||||||
|
|
||||||
|
This example assumes that OpenSSL-libraries and includes have been installed in the `/tmp/libssl-dev` directory.
|
||||||
|
|
||||||
|
Example invocation for Windows 64 bit:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cmake -DPAHO_BUILD_SAMPLES=TRUE \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=~/paho.mqtt.c/cmake/toolchain.win64.cmake \
|
||||||
|
~/paho.mqtt.c
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case the libraries and executable are not linked against OpenSSL Libraries. Cross compilers for the Windows platform can be installed on Debian like systems like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ apt-get install gcc-mingw-w64-x86-64 gcc-mingw-w64-i686
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build instructions for GNU Make
|
||||||
|
|
||||||
|
Ensure the OpenSSL development package is installed. Then from the client library base directory run:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make
|
||||||
|
$ sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
This will build and install the libraries. To uninstall:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo make uninstall
|
||||||
|
```
|
||||||
|
|
||||||
|
To build the documentation requires doxygen and optionally graphviz.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make html
|
||||||
|
```
|
||||||
|
|
||||||
|
The provided GNU Makefile is intended to perform all build steps in the ```build``` directory within the source-tree of Eclipse Paho. Generated binares, libraries, and the documentation can be found in the ```build/output``` directory after completion.
|
||||||
|
|
||||||
|
Options that are passed to the compiler/linker can be specified by typical Unix build variables:
|
||||||
|
|
||||||
|
Variable | Description
|
||||||
|
------------ | -------------
|
||||||
|
CC | Path to the C compiler
|
||||||
|
CFLAGS | Flags passed to compiler calls
|
||||||
|
LDFLAGS | Flags passed to linker calls
|
||||||
|
|
||||||
|
## Building paho-mqtt - Using vcpkg
|
||||||
|
|
||||||
|
You can download and install paho-mqtt using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||||
|
|
||||||
|
git clone https://github.com/Microsoft/vcpkg.git
|
||||||
|
cd vcpkg
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
./vcpkg integrate install
|
||||||
|
./vcpkg install paho-mqtt
|
||||||
|
|
||||||
|
The paho-mqtt port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||||
|
|
||||||
|
## Fully static builds with musl libc
|
||||||
|
|
||||||
|
(By Frank Pagliughi)
|
||||||
|
|
||||||
|
[musl libc](https://musl.libc.org/) is is an implementation of the C standard library built on top of the Linux system call API, including interfaces defined in the base language standard, POSIX, and widely agreed-upon extensions.
|
||||||
|
|
||||||
|
Users of the Rust library, which wraps this one, had been complaining that they could not compile using the musl build tools. Musl is a small std C lib that can be statically linked. With the latest Paho C library (and a very minor tweak to the build), we're now able to build Rust apps using musl and Paho C that are fully static; no runtime dependencies on the platform; not even on the standard C lib.
|
||||||
|
|
||||||
|
$ ./async_publish
|
||||||
|
Publishing a message on the 'test' topic
|
||||||
|
|
||||||
|
$ ldd async_publish
|
||||||
|
not a dynamic executable
|
||||||
|
|
||||||
|
So, for example, if maintaining a suite of apps for some newer and older embedded Linux boards, the same executables could be deployed without worry about the C ABI on the particular boards.
|
||||||
|
|
||||||
|
Certainly C apps using the Paho library could do this also.
|
||||||
|
|
||||||
|
## Microsoft Windows
|
||||||
|
|
||||||
|
### Calling convention
|
||||||
|
|
||||||
|
As is normal for C programs on Windows, the calling convention is __cdecl. See the Microsoft documentation here:
|
||||||
|
|
||||||
|
https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=vs-2019
|
||||||
|
|
||||||
|
If you call this library from another language, you may need to take this into account.
|
||||||
|
|
||||||
16
thirdparty/paho_mqtt/SECURITY.md
vendored
Normal file
16
thirdparty/paho_mqtt/SECURITY.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
This project follows the [Eclipse Vulnerability Reporting Policy](https://www.eclipse.org/security/policy.php).
|
||||||
|
Vulnerabilities are tracked by the Eclipse security team, in cooperation with the project lead.
|
||||||
|
Fixing vulnerabilities is taken care of by the project committers, with assistance and guidance of the security
|
||||||
|
team.
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Eclipse Paho provides security updates for the most recent version only.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
We recommend that in case of suspected vulnerabilities you do not create a GitHub issue, but instead contact the
|
||||||
|
Eclipse Security Team directly sending an email to security@eclipse.org.
|
||||||
|
|
||||||
28
thirdparty/paho_mqtt/about.html
vendored
Normal file
28
thirdparty/paho_mqtt/about.html
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>About</title>
|
||||||
|
</head>
|
||||||
|
<body lang="EN-US">
|
||||||
|
<h2>About This Content</h2>
|
||||||
|
|
||||||
|
<p><em>April 6, 2020</em></p>
|
||||||
|
<h3>License</h3>
|
||||||
|
|
||||||
|
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
|
||||||
|
indicated below, the Content is provided to you under the terms and conditions of the
|
||||||
|
Eclipse Public License Version 2.0 ("EPL") and Eclipse Distribution License Version 1.0 ("EDL").
|
||||||
|
A copy of the EPL is available at
|
||||||
|
<a href="https://www.eclipse.org/legal/epl-2.0/">https://www.eclipse.org/legal/epl-2.0/</a>
|
||||||
|
and a copy of the EDL is available at
|
||||||
|
<a href="http://www.eclipse.org/org/documents/edl-v10.php">http://www.eclipse.org/org/documents/edl-v10.php</a>.
|
||||||
|
For purposes of the EPL, "Program" will mean the Content.</p>
|
||||||
|
|
||||||
|
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
|
||||||
|
being redistributed by another party ("Redistributor") and different terms and conditions may
|
||||||
|
apply to your use of any object code in the Content. Check the Redistributor's license that was
|
||||||
|
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
|
||||||
|
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
|
||||||
|
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
BIN
thirdparty/paho_mqtt/bin/MQTTAsync_publish.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/MQTTAsync_publish.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/MQTTAsync_publish_time.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/MQTTAsync_publish_time.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/MQTTAsync_subscribe.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/MQTTAsync_subscribe.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/MQTTClient_publish.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/MQTTClient_publish.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/MQTTClient_publish_async.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/MQTTClient_publish_async.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/MQTTClient_subscribe.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/MQTTClient_subscribe.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/MQTTVersion.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/MQTTVersion.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/paho_c_pub.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/paho_c_pub.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/paho_c_sub.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/paho_c_sub.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/paho_cs_pub.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/paho_cs_pub.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/bin/paho_cs_sub.exe
vendored
Normal file
BIN
thirdparty/paho_mqtt/bin/paho_cs_sub.exe
vendored
Normal file
Binary file not shown.
15
thirdparty/paho_mqtt/edl-v10
vendored
Normal file
15
thirdparty/paho_mqtt/edl-v10
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
Eclipse Distribution License - v 1.0
|
||||||
|
|
||||||
|
Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
2404
thirdparty/paho_mqtt/include/MQTTAsync.h
vendored
Normal file
2404
thirdparty/paho_mqtt/include/MQTTAsync.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
188
thirdparty/paho_mqtt/include/MQTTAsyncUtils.h
vendored
Normal file
188
thirdparty/paho_mqtt/include/MQTTAsyncUtils.h
vendored
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2024 IBM Corp. and others
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial implementation and documentation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTASYNCUTILS_H_)
|
||||||
|
#define MQTTASYNCUTILS_H_
|
||||||
|
|
||||||
|
#include "MQTTPacket.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
|
||||||
|
#define URI_TCP "tcp://"
|
||||||
|
#define URI_MQTT "mqtt://"
|
||||||
|
#define URI_WS "ws://"
|
||||||
|
#define URI_WSS "wss://"
|
||||||
|
#define URI_UNIX "unix://"
|
||||||
|
|
||||||
|
enum MQTTAsync_threadStates
|
||||||
|
{
|
||||||
|
STOPPED, STARTING, RUNNING, STOPPING
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MQTTAsync_message* msg;
|
||||||
|
char* topicName;
|
||||||
|
int topicLen;
|
||||||
|
unsigned int seqno; /* only used on restore */
|
||||||
|
} qEntry;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
MQTTAsync_onSuccess* onSuccess;
|
||||||
|
MQTTAsync_onFailure* onFailure;
|
||||||
|
MQTTAsync_onSuccess5* onSuccess5;
|
||||||
|
MQTTAsync_onFailure5* onFailure5;
|
||||||
|
MQTTAsync_token token;
|
||||||
|
void* context;
|
||||||
|
START_TIME_TYPE start_time;
|
||||||
|
MQTTProperties properties;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
char** topics;
|
||||||
|
int* qoss;
|
||||||
|
MQTTSubscribe_options opts;
|
||||||
|
MQTTSubscribe_options* optlist;
|
||||||
|
} sub;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
char** topics;
|
||||||
|
} unsub;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char* destinationName;
|
||||||
|
int payloadlen;
|
||||||
|
void* payload;
|
||||||
|
int qos;
|
||||||
|
int retained;
|
||||||
|
} pub;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int internal;
|
||||||
|
int timeout;
|
||||||
|
enum MQTTReasonCodes reasonCode;
|
||||||
|
} dis;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int currentURI;
|
||||||
|
int MQTTVersion; /**< current MQTT version being used to connect */
|
||||||
|
} conn;
|
||||||
|
} details;
|
||||||
|
} MQTTAsync_command;
|
||||||
|
|
||||||
|
typedef struct MQTTAsync_struct
|
||||||
|
{
|
||||||
|
char* serverURI;
|
||||||
|
int unixsock;
|
||||||
|
int ssl;
|
||||||
|
int websocket;
|
||||||
|
Clients* c;
|
||||||
|
|
||||||
|
/* "Global", to the client, callback definitions */
|
||||||
|
MQTTAsync_connectionLost* cl;
|
||||||
|
MQTTAsync_messageArrived* ma;
|
||||||
|
MQTTAsync_deliveryComplete* dc;
|
||||||
|
void* clContext; /* the context to be associated with the conn lost callback*/
|
||||||
|
void* maContext; /* the context to be associated with the msg arrived callback*/
|
||||||
|
void* dcContext; /* the context to be associated with the deliv complete callback*/
|
||||||
|
|
||||||
|
MQTTAsync_connected* connected;
|
||||||
|
void* connected_context; /* the context to be associated with the connected callback*/
|
||||||
|
|
||||||
|
MQTTAsync_disconnected* disconnected;
|
||||||
|
void* disconnected_context; /* the context to be associated with the disconnected callback*/
|
||||||
|
|
||||||
|
MQTTAsync_updateConnectOptions* updateConnectOptions;
|
||||||
|
void* updateConnectOptions_context;
|
||||||
|
|
||||||
|
/* Each time connect is called, we store the options that were used. These are reused in
|
||||||
|
any call to reconnect, or an automatic reconnect attempt */
|
||||||
|
MQTTAsync_command connect; /* Connect operation properties */
|
||||||
|
MQTTAsync_command disconnect; /* Disconnect operation properties */
|
||||||
|
MQTTAsync_command* pending_write; /* Is there a socket write pending? */
|
||||||
|
|
||||||
|
List* responses;
|
||||||
|
unsigned int command_seqno;
|
||||||
|
|
||||||
|
MQTTPacket* pack;
|
||||||
|
|
||||||
|
/* added for offline buffering */
|
||||||
|
MQTTAsync_createOptions* createOptions;
|
||||||
|
int shouldBeConnected;
|
||||||
|
int noBufferedMessages; /* the current number of buffered (publish) messages for this client */
|
||||||
|
|
||||||
|
/* added for automatic reconnect */
|
||||||
|
int automaticReconnect;
|
||||||
|
int minRetryInterval;
|
||||||
|
int maxRetryInterval;
|
||||||
|
int serverURIcount;
|
||||||
|
char** serverURIs;
|
||||||
|
int connectTimeout;
|
||||||
|
|
||||||
|
int currentInterval;
|
||||||
|
int currentIntervalBase;
|
||||||
|
START_TIME_TYPE lastConnectionFailedTime;
|
||||||
|
int retrying;
|
||||||
|
int reconnectNow;
|
||||||
|
|
||||||
|
/* MQTT V5 properties */
|
||||||
|
MQTTProperties* connectProps;
|
||||||
|
MQTTProperties* willProps;
|
||||||
|
|
||||||
|
} MQTTAsyncs;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MQTTAsync_command command;
|
||||||
|
MQTTAsyncs* client;
|
||||||
|
unsigned int seqno; /* only used on restore */
|
||||||
|
int not_restored;
|
||||||
|
char* key; /* if not_restored, this holds the key */
|
||||||
|
} MQTTAsync_queuedCommand;
|
||||||
|
|
||||||
|
void MQTTAsync_lock_mutex(mutex_type amutex);
|
||||||
|
void MQTTAsync_unlock_mutex(mutex_type amutex);
|
||||||
|
void MQTTAsync_terminate(void);
|
||||||
|
#if !defined(NO_PERSISTENCE)
|
||||||
|
int MQTTAsync_restoreCommands(MQTTAsyncs* client);
|
||||||
|
#endif
|
||||||
|
int MQTTAsync_addCommand(MQTTAsync_queuedCommand* command, int command_size);
|
||||||
|
void MQTTAsync_emptyMessageQueue(Clients* client);
|
||||||
|
void MQTTAsync_freeResponses(MQTTAsyncs* m);
|
||||||
|
void MQTTAsync_freeCommands(MQTTAsyncs* m);
|
||||||
|
int MQTTAsync_unpersistCommandsAndMessages(Clients* c);
|
||||||
|
void MQTTAsync_closeSession(Clients* client, enum MQTTReasonCodes reasonCode, MQTTProperties* props);
|
||||||
|
int MQTTAsync_disconnect1(MQTTAsync handle, const MQTTAsync_disconnectOptions* options, int internal);
|
||||||
|
int MQTTAsync_assignMsgId(MQTTAsyncs* m);
|
||||||
|
int MQTTAsync_getNoBufferedMessages(MQTTAsyncs* m);
|
||||||
|
void MQTTAsync_writeContinue(SOCKET socket);
|
||||||
|
void MQTTAsync_writeComplete(SOCKET socket, int rc);
|
||||||
|
void setRetryLoopInterval(int keepalive);
|
||||||
|
void MQTTAsync_NULLPublishResponses(MQTTAsyncs* m);
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#else
|
||||||
|
#define WINAPI
|
||||||
|
#endif
|
||||||
|
|
||||||
|
thread_return_type WINAPI MQTTAsync_sendThread(void* n);
|
||||||
|
thread_return_type WINAPI MQTTAsync_receiveThread(void* n);
|
||||||
|
|
||||||
|
#endif /* MQTTASYNCUTILS_H_ */
|
||||||
2004
thirdparty/paho_mqtt/include/MQTTClient.h
vendored
Normal file
2004
thirdparty/paho_mqtt/include/MQTTClient.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
277
thirdparty/paho_mqtt/include/MQTTClientPersistence.h
vendored
Normal file
277
thirdparty/paho_mqtt/include/MQTTClientPersistence.h
vendored
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2020 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* \brief This structure represents a persistent data store, used to store
|
||||||
|
* outbound and inbound messages, in order to achieve reliable messaging.
|
||||||
|
*
|
||||||
|
* The MQTT Client persists QoS1 and QoS2 messages in order to meet the
|
||||||
|
* assurances of delivery associated with these @ref qos levels. The messages
|
||||||
|
* are saved in persistent storage
|
||||||
|
* The type and context of the persistence implementation are specified when
|
||||||
|
* the MQTT client is created (see MQTTClient_create()). The default
|
||||||
|
* persistence type (::MQTTCLIENT_PERSISTENCE_DEFAULT) uses a file system-based
|
||||||
|
* persistence mechanism. The <i>persistence_context</i> argument passed to
|
||||||
|
* MQTTClient_create() when using the default peristence is a string
|
||||||
|
* representing the location of the persistence directory. If the context
|
||||||
|
* argument is NULL, the working directory will be used.
|
||||||
|
*
|
||||||
|
* To use memory-based persistence, an application passes
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_NONE as the <i>persistence_type</i> to
|
||||||
|
* MQTTClient_create(). This can lead to message loss in certain situations,
|
||||||
|
* but can be appropriate in some cases (see @ref qos).
|
||||||
|
*
|
||||||
|
* Client applications can provide their own persistence mechanism by passing
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_USER as the <i>persistence_type</i>. To implement a
|
||||||
|
* custom persistence mechanism, the application must pass an initialized
|
||||||
|
* ::MQTTClient_persistence structure as the <i>persistence_context</i>
|
||||||
|
* argument to MQTTClient_create().
|
||||||
|
*
|
||||||
|
* If the functions defined return an ::MQTTCLIENT_PERSISTENCE_ERROR then the
|
||||||
|
* state of the persisted data should remain as it was prior to the function
|
||||||
|
* being called. For example, if Persistence_put() returns
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR, then it is assumed tha tthe persistent store
|
||||||
|
* does not contain the data that was passed to the function. Similarly, if
|
||||||
|
* Persistence_remove() returns ::MQTTCLIENT_PERSISTENCE_ERROR then it is
|
||||||
|
* assumed that the data to be removed is still held in the persistent store.
|
||||||
|
*
|
||||||
|
* It is up to the persistence implementation to log any error information that
|
||||||
|
* may be required to diagnose a persistence mechanism failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
/// @cond EXCLUDE
|
||||||
|
*/
|
||||||
|
#if !defined(MQTTCLIENTPERSISTENCE_H)
|
||||||
|
#define MQTTCLIENTPERSISTENCE_H
|
||||||
|
/*
|
||||||
|
/// @endcond
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This <i>persistence_type</i> value specifies the default file system-based
|
||||||
|
* persistence mechanism (see MQTTClient_create()).
|
||||||
|
*/
|
||||||
|
#define MQTTCLIENT_PERSISTENCE_DEFAULT 0
|
||||||
|
/**
|
||||||
|
* This <i>persistence_type</i> value specifies a memory-based
|
||||||
|
* persistence mechanism (see MQTTClient_create()).
|
||||||
|
*/
|
||||||
|
#define MQTTCLIENT_PERSISTENCE_NONE 1
|
||||||
|
/**
|
||||||
|
* This <i>persistence_type</i> value specifies an application-specific
|
||||||
|
* persistence mechanism (see MQTTClient_create()).
|
||||||
|
*/
|
||||||
|
#define MQTTCLIENT_PERSISTENCE_USER 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application-specific persistence functions must return this error code if
|
||||||
|
* there is a problem executing the function.
|
||||||
|
*/
|
||||||
|
#define MQTTCLIENT_PERSISTENCE_ERROR -2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the persistent store.
|
||||||
|
*
|
||||||
|
* Either open the existing persistent store for this client ID or create a new
|
||||||
|
* one if one doesn't exist. If the persistent store is already open, return
|
||||||
|
* without taking any action.
|
||||||
|
*
|
||||||
|
* An application can use the same client identifier to connect to many
|
||||||
|
* different servers. The <i>clientid</i> in conjunction with the
|
||||||
|
* <i>serverURI</i> uniquely identifies the persistence store required.
|
||||||
|
*
|
||||||
|
* @param handle The address of a pointer to a handle for this persistence
|
||||||
|
* implementation. This function must set handle to a valid reference to the
|
||||||
|
* persistence following a successful return.
|
||||||
|
* The handle pointer is passed as an argument to all the other
|
||||||
|
* persistence functions. It may include the context parameter and/or any other
|
||||||
|
* data for use by the persistence functions.
|
||||||
|
* @param clientID The client identifier for which the persistent store should
|
||||||
|
* be opened.
|
||||||
|
* @param serverURI The connection string specified when the MQTT client was
|
||||||
|
* created (see MQTTClient_create()).
|
||||||
|
* @param context A pointer to any data required to initialize the persistent
|
||||||
|
* store (see ::MQTTClient_persistence).
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise return
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR.
|
||||||
|
*/
|
||||||
|
typedef int (*Persistence_open)(void** handle, const char* clientID, const char* serverURI, void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Close the persistent store referred to by the handle.
|
||||||
|
*
|
||||||
|
* @param handle The handle pointer from a successful call to
|
||||||
|
* Persistence_open().
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise return
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR.
|
||||||
|
*/
|
||||||
|
typedef int (*Persistence_close)(void* handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Put the specified data into the persistent store.
|
||||||
|
*
|
||||||
|
* @param handle The handle pointer from a successful call to
|
||||||
|
* Persistence_open().
|
||||||
|
* @param key A string used as the key for the data to be put in the store. The
|
||||||
|
* key is later used to retrieve data from the store with Persistence_get().
|
||||||
|
* @param bufcount The number of buffers to write to the persistence store.
|
||||||
|
* @param buffers An array of pointers to the data buffers associated with
|
||||||
|
* this <i>key</i>.
|
||||||
|
* @param buflens An array of lengths of the data buffers. <i>buflen[n]</i>
|
||||||
|
* gives the length of <i>buffer[n]</i>.
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise return
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR.
|
||||||
|
*/
|
||||||
|
typedef int (*Persistence_put)(void* handle, char* key, int bufcount, char* buffers[], int buflens[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve the specified data from the persistent store.
|
||||||
|
*
|
||||||
|
* @param handle The handle pointer from a successful call to
|
||||||
|
* Persistence_open().
|
||||||
|
* @param key A string that is the key for the data to be retrieved. This is
|
||||||
|
* the same key used to save the data to the store with Persistence_put().
|
||||||
|
* @param buffer The address of a pointer to a buffer. This function sets the
|
||||||
|
* pointer to point at the retrieved data, if successful.
|
||||||
|
* @param buflen The address of an int that is set to the length of
|
||||||
|
* <i>buffer</i> by this function if successful.
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise return
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR.
|
||||||
|
*/
|
||||||
|
typedef int (*Persistence_get)(void* handle, char* key, char** buffer, int* buflen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove the data for the specified key from the store.
|
||||||
|
*
|
||||||
|
* @param handle The handle pointer from a successful call to
|
||||||
|
* Persistence_open().
|
||||||
|
* @param key A string that is the key for the data to be removed from the
|
||||||
|
* store. This is the same key used to save the data to the store with
|
||||||
|
* Persistence_put().
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise return
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR.
|
||||||
|
*/
|
||||||
|
typedef int (*Persistence_remove)(void* handle, char* key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the keys in this persistent data store.
|
||||||
|
*
|
||||||
|
* @param handle The handle pointer from a successful call to
|
||||||
|
* Persistence_open().
|
||||||
|
* @param keys The address of a pointer to pointers to strings. Assuming
|
||||||
|
* successful execution, this function allocates memory to hold the returned
|
||||||
|
* keys (strings used to store the data with Persistence_put()). It also
|
||||||
|
* allocates memory to hold an array of pointers to these strings. <i>keys</i>
|
||||||
|
* is set to point to the array of pointers to strings.
|
||||||
|
* @param nkeys A pointer to the number of keys in this persistent data store.
|
||||||
|
* This function sets the number of keys, if successful.
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise return
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR.
|
||||||
|
*/
|
||||||
|
typedef int (*Persistence_keys)(void* handle, char*** keys, int* nkeys);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the persistence store, so that it no longer contains any
|
||||||
|
* persisted data.
|
||||||
|
*
|
||||||
|
* @param handle The handle pointer from a successful call to
|
||||||
|
* Persistence_open().
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise return
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR.
|
||||||
|
*/
|
||||||
|
typedef int (*Persistence_clear)(void* handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether any data has been persisted using the specified key.
|
||||||
|
*
|
||||||
|
* @param handle The handle pointer from a successful call to
|
||||||
|
* Persistence_open().
|
||||||
|
* @param key The string to be tested for existence in the store.
|
||||||
|
* @return Return 0 if the key was found in the store, otherwise return
|
||||||
|
* ::MQTTCLIENT_PERSISTENCE_ERROR.
|
||||||
|
*/
|
||||||
|
typedef int (*Persistence_containskey)(void* handle, char* key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A structure containing the function pointers to a persistence
|
||||||
|
* implementation and the context or state that will be shared across all
|
||||||
|
* the persistence functions.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* A pointer to any data required to initialize the persistent store.
|
||||||
|
*/
|
||||||
|
void* context;
|
||||||
|
/**
|
||||||
|
* A function pointer to an implementation of Persistence_open().
|
||||||
|
*/
|
||||||
|
Persistence_open popen;
|
||||||
|
/**
|
||||||
|
* A function pointer to an implementation of Persistence_close().
|
||||||
|
*/
|
||||||
|
Persistence_close pclose;
|
||||||
|
/**
|
||||||
|
* A function pointer to an implementation of Persistence_put().
|
||||||
|
*/
|
||||||
|
Persistence_put pput;
|
||||||
|
/**
|
||||||
|
* A function pointer to an implementation of Persistence_get().
|
||||||
|
*/
|
||||||
|
Persistence_get pget;
|
||||||
|
/**
|
||||||
|
* A function pointer to an implementation of Persistence_remove().
|
||||||
|
*/
|
||||||
|
Persistence_remove premove;
|
||||||
|
/**
|
||||||
|
* A function pointer to an implementation of Persistence_keys().
|
||||||
|
*/
|
||||||
|
Persistence_keys pkeys;
|
||||||
|
/**
|
||||||
|
* A function pointer to an implementation of Persistence_clear().
|
||||||
|
*/
|
||||||
|
Persistence_clear pclear;
|
||||||
|
/**
|
||||||
|
* A function pointer to an implementation of Persistence_containskey().
|
||||||
|
*/
|
||||||
|
Persistence_containskey pcontainskey;
|
||||||
|
} MQTTClient_persistence;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback which is invoked just before a write to persistence. This can be
|
||||||
|
* used to transform the data, for instance to encrypt it.
|
||||||
|
* @param context The context as set in ::MQTTAsync_setBeforePersistenceWrite
|
||||||
|
* @param bufcount The number of buffers to write to the persistence store.
|
||||||
|
* @param buffers An array of pointers to the data buffers.
|
||||||
|
* @param buflens An array of lengths of the data buffers.
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise non 0.
|
||||||
|
*/
|
||||||
|
typedef int MQTTPersistence_beforeWrite(void* context, int bufcount, char* buffers[], int buflens[]);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback which is invoked just after a read from persistence. This can be
|
||||||
|
* used to transform the data, for instance to decrypt it.
|
||||||
|
* @param context The context as set in ::MQTTAsync_setAfterPersistenceRead
|
||||||
|
* @param buffer The address of a pointer to a buffer.
|
||||||
|
* @param buflen The address of an int that is the length of the buffer.
|
||||||
|
* @return Return 0 if the function completes successfully, otherwise non 0.
|
||||||
|
*/
|
||||||
|
typedef int MQTTPersistence_afterRead(void* context, char** buffer, int* buflen);
|
||||||
|
|
||||||
|
#endif
|
||||||
36
thirdparty/paho_mqtt/include/MQTTExportDeclarations.h
vendored
Normal file
36
thirdparty/paho_mqtt/include/MQTTExportDeclarations.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2020, 2020 Andreas Walter
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Andreas Walter - initially moved export declarations into separate fle
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(EXPORTDECLARATIONS_H)
|
||||||
|
#define EXPORTDECLARATIONS_H
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# if defined(PAHO_MQTT_EXPORTS)
|
||||||
|
# define LIBMQTT_API __declspec(dllexport)
|
||||||
|
# elif defined(PAHO_MQTT_IMPORTS)
|
||||||
|
# define LIBMQTT_API __declspec(dllimport)
|
||||||
|
# else
|
||||||
|
# define LIBMQTT_API
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# if defined(PAHO_MQTT_EXPORTS)
|
||||||
|
# define LIBMQTT_API __attribute__ ((visibility ("default")))
|
||||||
|
# else
|
||||||
|
# define LIBMQTT_API extern
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
272
thirdparty/paho_mqtt/include/MQTTPacket.h
vendored
Normal file
272
thirdparty/paho_mqtt/include/MQTTPacket.h
vendored
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2024 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
* Ian Craggs, Allan Stockdill-Mander - SSL updates
|
||||||
|
* Ian Craggs - MQTT 3.1.1 support
|
||||||
|
* Ian Craggs - big endian Linux reversed definition
|
||||||
|
* Ian Craggs - MQTT 5.0 support
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTPACKET_H)
|
||||||
|
#define MQTTPACKET_H
|
||||||
|
|
||||||
|
#include "Socket.h"
|
||||||
|
#if defined(OPENSSL)
|
||||||
|
#include "SSLSocket.h"
|
||||||
|
#endif
|
||||||
|
#include "LinkedList.h"
|
||||||
|
#include "Clients.h"
|
||||||
|
|
||||||
|
typedef unsigned int bit;
|
||||||
|
typedef void* (*pf)(int, unsigned char, char*, size_t);
|
||||||
|
|
||||||
|
#include "MQTTProperties.h"
|
||||||
|
#include "MQTTReasonCodes.h"
|
||||||
|
|
||||||
|
enum errors
|
||||||
|
{
|
||||||
|
MQTTPACKET_BAD = -4,
|
||||||
|
MQTTPACKET_BUFFER_TOO_SHORT = -2,
|
||||||
|
MQTTPACKET_READ_ERROR = -1,
|
||||||
|
MQTTPACKET_READ_COMPLETE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum msgTypes
|
||||||
|
{
|
||||||
|
CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
|
||||||
|
PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
|
||||||
|
PINGREQ, PINGRESP, DISCONNECT, AUTH
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
#include <endian.h>
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
#define REVERSED 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitfields for the MQTT header byte.
|
||||||
|
*/
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
/*unsigned*/ char byte; /**< the whole byte */
|
||||||
|
#if defined(REVERSED)
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int type : 4; /**< message type nibble */
|
||||||
|
bit dup : 1; /**< DUP flag bit */
|
||||||
|
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
|
||||||
|
bit retain : 1; /**< retained flag bit */
|
||||||
|
} bits;
|
||||||
|
#else
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bit retain : 1; /**< retained flag bit */
|
||||||
|
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
|
||||||
|
bit dup : 1; /**< DUP flag bit */
|
||||||
|
unsigned int type : 4; /**< message type nibble */
|
||||||
|
} bits;
|
||||||
|
#endif
|
||||||
|
} Header;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for a connect packet.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Header header; /**< MQTT header byte */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
unsigned char all; /**< all connect flags */
|
||||||
|
#if defined(REVERSED)
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bit username : 1; /**< 3.1 user name */
|
||||||
|
bit password : 1; /**< 3.1 password */
|
||||||
|
bit willRetain : 1; /**< will retain setting */
|
||||||
|
unsigned int willQoS : 2; /**< will QoS value */
|
||||||
|
bit will : 1; /**< will flag */
|
||||||
|
bit cleanstart : 1; /**< cleansession flag */
|
||||||
|
int : 1; /**< unused */
|
||||||
|
} bits;
|
||||||
|
#else
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int : 1; /**< unused */
|
||||||
|
bit cleanstart : 1; /**< cleansession flag */
|
||||||
|
bit will : 1; /**< will flag */
|
||||||
|
unsigned int willQoS : 2; /**< will QoS value */
|
||||||
|
bit willRetain : 1; /**< will retain setting */
|
||||||
|
bit password : 1; /**< 3.1 password */
|
||||||
|
bit username : 1; /**< 3.1 user name */
|
||||||
|
} bits;
|
||||||
|
#endif
|
||||||
|
} flags; /**< connect flags byte */
|
||||||
|
|
||||||
|
char *Protocol, /**< MQTT protocol name */
|
||||||
|
*clientID, /**< string client id */
|
||||||
|
*willTopic, /**< will topic */
|
||||||
|
*willMsg; /**< will payload */
|
||||||
|
|
||||||
|
int keepAliveTimer; /**< keepalive timeout value in seconds */
|
||||||
|
unsigned char version; /**< MQTT version number */
|
||||||
|
} Connect;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for a connack packet.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Header header; /**< MQTT header byte */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
unsigned char all; /**< all connack flags */
|
||||||
|
#if defined(REVERSED)
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int reserved : 7; /**< message type nibble */
|
||||||
|
bit sessionPresent : 1; /**< was a session found on the server? */
|
||||||
|
} bits;
|
||||||
|
#else
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bit sessionPresent : 1; /**< was a session found on the server? */
|
||||||
|
unsigned int reserved : 7; /**< message type nibble */
|
||||||
|
} bits;
|
||||||
|
#endif
|
||||||
|
} flags; /**< connack flags byte */
|
||||||
|
unsigned char rc; /**< connack reason code */
|
||||||
|
unsigned int MQTTVersion; /**< the version of MQTT */
|
||||||
|
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
|
||||||
|
} Connack;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for a packet with header only.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Header header; /**< MQTT header byte */
|
||||||
|
} MQTTPacket;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for a suback packet.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Header header; /**< MQTT header byte */
|
||||||
|
int msgId; /**< MQTT message id */
|
||||||
|
int MQTTVersion; /**< the version of MQTT */
|
||||||
|
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
|
||||||
|
List* qoss; /**< list of granted QoSs (MQTT 3/4) / reason codes (MQTT 5) */
|
||||||
|
} Suback;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for an MQTT V5 unsuback packet.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Header header; /**< MQTT header byte */
|
||||||
|
int msgId; /**< MQTT message id */
|
||||||
|
int MQTTVersion; /**< the version of MQTT */
|
||||||
|
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
|
||||||
|
List* reasonCodes; /**< list of reason codes */
|
||||||
|
} Unsuback;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for a publish packet.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Header header; /**< MQTT header byte */
|
||||||
|
char* topic; /**< topic string */
|
||||||
|
int topiclen;
|
||||||
|
int msgId; /**< MQTT message id */
|
||||||
|
char* payload; /**< binary payload, length delimited */
|
||||||
|
int payloadlen; /**< payload length */
|
||||||
|
int MQTTVersion; /**< the version of MQTT */
|
||||||
|
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
|
||||||
|
uint8_t mask[4]; /**< the websockets mask the payload is masked with, if any */
|
||||||
|
} Publish;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data for one of the ack packets.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Header header; /**< MQTT header byte */
|
||||||
|
int msgId; /**< MQTT message id */
|
||||||
|
unsigned char rc; /**< MQTT 5 reason code */
|
||||||
|
int MQTTVersion; /**< the version of MQTT */
|
||||||
|
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
|
||||||
|
} Ack;
|
||||||
|
|
||||||
|
typedef Ack Puback;
|
||||||
|
typedef Ack Pubrec;
|
||||||
|
typedef Ack Pubrel;
|
||||||
|
typedef Ack Pubcomp;
|
||||||
|
|
||||||
|
int MQTTPacket_encode(char* buf, size_t length);
|
||||||
|
int MQTTPacket_decode(networkHandles* net, size_t* value);
|
||||||
|
int readInt(char** pptr);
|
||||||
|
char* readUTF(char** pptr, char* enddata);
|
||||||
|
unsigned char readChar(char** pptr);
|
||||||
|
void writeChar(char** pptr, char c);
|
||||||
|
void writeInt(char** pptr, int anInt);
|
||||||
|
void writeUTF(char** pptr, const char* string);
|
||||||
|
void writeData(char** pptr, const void* data, int datalen);
|
||||||
|
|
||||||
|
const char* MQTTPacket_name(int ptype);
|
||||||
|
|
||||||
|
void* MQTTPacket_Factory(int MQTTVersion, networkHandles* net, int* error);
|
||||||
|
int MQTTPacket_send(networkHandles* net, Header header, char* buffer, size_t buflen, int free, int MQTTVersion);
|
||||||
|
int MQTTPacket_sends(networkHandles* net, Header header, PacketBuffers* buffers, int MQTTVersion);
|
||||||
|
|
||||||
|
void* MQTTPacket_header_only(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
|
||||||
|
int MQTTPacket_send_disconnect(Clients* client, enum MQTTReasonCodes reason, MQTTProperties* props);
|
||||||
|
|
||||||
|
void* MQTTPacket_publish(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
|
||||||
|
void MQTTPacket_freePublish(Publish* pack);
|
||||||
|
int MQTTPacket_formatPayload(int buflen, char* buf, int payloadlen, char* payload);
|
||||||
|
int MQTTPacket_send_publish(Publish* pack, int dup, int qos, int retained, networkHandles* net, const char* clientID);
|
||||||
|
int MQTTPacket_send_puback(int MQTTVersion, int msgid, networkHandles* net, const char* clientID);
|
||||||
|
void* MQTTPacket_ack(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
|
||||||
|
|
||||||
|
void MQTTPacket_freeAck(Ack* pack);
|
||||||
|
void MQTTPacket_freeSuback(Suback* pack);
|
||||||
|
void MQTTPacket_freeUnsuback(Unsuback* pack);
|
||||||
|
int MQTTPacket_send_pubrec(int MQTTVersion, int msgid, networkHandles* net, const char* clientID);
|
||||||
|
int MQTTPacket_send_pubrel(int MQTTVersion, int msgid, int dup, networkHandles* net, const char* clientID);
|
||||||
|
int MQTTPacket_send_pubcomp(int MQTTVersion, int msgid, networkHandles* net, const char* clientID);
|
||||||
|
|
||||||
|
void MQTTPacket_free_packet(MQTTPacket* pack);
|
||||||
|
|
||||||
|
void writeInt4(char** pptr, unsigned int anInt);
|
||||||
|
unsigned int readInt4(char** pptr);
|
||||||
|
void writeMQTTLenString(char** pptr, MQTTLenString lenstring);
|
||||||
|
int MQTTLenStringRead(MQTTLenString* lenstring, char** pptr, char* enddata);
|
||||||
|
int MQTTPacket_VBIlen(int rem_len);
|
||||||
|
int MQTTPacket_decodeBuf(char* buf, unsigned int* value);
|
||||||
|
|
||||||
|
#include "MQTTPacketOut.h"
|
||||||
|
|
||||||
|
#endif /* MQTTPACKET_H */
|
||||||
39
thirdparty/paho_mqtt/include/MQTTPacketOut.h
vendored
Normal file
39
thirdparty/paho_mqtt/include/MQTTPacketOut.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2018 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
* Ian Craggs, Allan Stockdill-Mander - SSL updates
|
||||||
|
* Ian Craggs - MQTT 3.1.1 support
|
||||||
|
* Ian Craggs - MQTT 5.0 support
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTPACKETOUT_H)
|
||||||
|
#define MQTTPACKETOUT_H
|
||||||
|
|
||||||
|
#include "MQTTPacket.h"
|
||||||
|
|
||||||
|
int MQTTPacket_send_connect(Clients* client, int MQTTVersion,
|
||||||
|
MQTTProperties* connectProperties, MQTTProperties* willProperties);
|
||||||
|
void* MQTTPacket_connack(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
|
||||||
|
void MQTTPacket_freeConnack(Connack* pack);
|
||||||
|
|
||||||
|
int MQTTPacket_send_pingreq(networkHandles* net, const char* clientID);
|
||||||
|
|
||||||
|
int MQTTPacket_send_subscribe(List* topics, List* qoss, MQTTSubscribe_options* opts, MQTTProperties* props,
|
||||||
|
int msgid, int dup, Clients* client);
|
||||||
|
void* MQTTPacket_suback(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
|
||||||
|
|
||||||
|
int MQTTPacket_send_unsubscribe(List* topics, MQTTProperties* props, int msgid, int dup, Clients* client);
|
||||||
|
void* MQTTPacket_unsuback(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
|
||||||
|
|
||||||
|
#endif
|
||||||
99
thirdparty/paho_mqtt/include/MQTTPersistence.h
vendored
Normal file
99
thirdparty/paho_mqtt/include/MQTTPersistence.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2022 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
* Ian Craggs - async client updates
|
||||||
|
* Ian Craggs - fix for bug 432903 - queue persistence
|
||||||
|
* Ian Craggs - MQTT V5 updates
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTPERSISTENCE_H)
|
||||||
|
#define MQTTPERSISTENCE_H
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Clients.h"
|
||||||
|
#include "MQTTProperties.h"
|
||||||
|
|
||||||
|
/** Stem of the key for a sent PUBLISH QoS1 or QoS2 */
|
||||||
|
#define PERSISTENCE_PUBLISH_SENT "s-"
|
||||||
|
/** Stem of the key for a sent PUBREL */
|
||||||
|
#define PERSISTENCE_PUBREL "sc-"
|
||||||
|
/** Stem of the key for a received PUBLISH QoS2 */
|
||||||
|
#define PERSISTENCE_PUBLISH_RECEIVED "r-"
|
||||||
|
|
||||||
|
/** Stem of the key for a sent MQTT V5 PUBLISH QoS1 or QoS2 */
|
||||||
|
#define PERSISTENCE_V5_PUBLISH_SENT "s5-"
|
||||||
|
/** Stem of the key for a sent MQTT V5 PUBREL */
|
||||||
|
#define PERSISTENCE_V5_PUBREL "sc5-"
|
||||||
|
/** Stem of the key for a received MQTT V5 PUBLISH QoS2 */
|
||||||
|
#define PERSISTENCE_V5_PUBLISH_RECEIVED "r5-"
|
||||||
|
|
||||||
|
/** Stem of the key for an async client command */
|
||||||
|
#define PERSISTENCE_COMMAND_KEY "c-"
|
||||||
|
/** Stem of the key for an MQTT V5 async client command */
|
||||||
|
#define PERSISTENCE_V5_COMMAND_KEY "c5-"
|
||||||
|
/** Stem of the key for an client incoming message queue */
|
||||||
|
#define PERSISTENCE_QUEUE_KEY "q-"
|
||||||
|
/** Stem of the key for an MQTT V5 incoming message queue */
|
||||||
|
#define PERSISTENCE_V5_QUEUE_KEY "q5-"
|
||||||
|
/** Maximum length of a stem for a persistence key */
|
||||||
|
#define PERSISTENCE_MAX_STEM_LENGTH 4
|
||||||
|
/** Maximum allowed length of a persistence key */
|
||||||
|
#define PERSISTENCE_MAX_KEY_LENGTH 10
|
||||||
|
/** Maximum size of an integer sequence number appended to a persistence key */
|
||||||
|
#define PERSISTENCE_SEQNO_LIMIT 1000000 /*10^(PERSISTENCE_MAX_KEY_LENGTH - PERSISTENCE_MAX_STEM_LENGTH)*/
|
||||||
|
|
||||||
|
int MQTTPersistence_create(MQTTClient_persistence** per, int type, void* pcontext);
|
||||||
|
int MQTTPersistence_initialize(Clients* c, const char* serverURI);
|
||||||
|
int MQTTPersistence_close(Clients* c);
|
||||||
|
int MQTTPersistence_clear(Clients* c);
|
||||||
|
int MQTTPersistence_restorePackets(Clients* c);
|
||||||
|
void* MQTTPersistence_restorePacket(int MQTTVersion, char* buffer, size_t buflen);
|
||||||
|
void MQTTPersistence_insertInOrder(List* list, void* content, size_t size);
|
||||||
|
int MQTTPersistence_putPacket(SOCKET socket, char* buf0, size_t buf0len, int count,
|
||||||
|
char** buffers, size_t* buflens, int htype, int msgId, int scr, int MQTTVersion);
|
||||||
|
int MQTTPersistence_remove(Clients* c, char* type, int qos, int msgId);
|
||||||
|
void MQTTPersistence_wrapMsgID(Clients *c);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char struct_id[4];
|
||||||
|
int struct_version;
|
||||||
|
int payloadlen;
|
||||||
|
void* payload;
|
||||||
|
int qos;
|
||||||
|
int retained;
|
||||||
|
int dup;
|
||||||
|
int msgid;
|
||||||
|
MQTTProperties properties;
|
||||||
|
} MQTTPersistence_message;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MQTTPersistence_message* msg;
|
||||||
|
char* topicName;
|
||||||
|
int topicLen;
|
||||||
|
unsigned int seqno; /* only used on restore */
|
||||||
|
} MQTTPersistence_qEntry;
|
||||||
|
|
||||||
|
int MQTTPersistence_unpersistQueueEntry(Clients* client, MQTTPersistence_qEntry* qe);
|
||||||
|
int MQTTPersistence_persistQueueEntry(Clients* aclient, MQTTPersistence_qEntry* qe);
|
||||||
|
int MQTTPersistence_restoreMessageQueue(Clients* c);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
36
thirdparty/paho_mqtt/include/MQTTPersistenceDefault.h
vendored
Normal file
36
thirdparty/paho_mqtt/include/MQTTPersistenceDefault.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2018 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTPERSISTENCEDEFAULT_H)
|
||||||
|
#define MQTTPERSISTENCEDEFAULT_H
|
||||||
|
|
||||||
|
/** Extension of the filename */
|
||||||
|
#define MESSAGE_FILENAME_EXTENSION ".msg"
|
||||||
|
|
||||||
|
/* prototypes of the functions for the default file system persistence */
|
||||||
|
int pstopen(void** handle, const char* clientID, const char* serverURI, void* context);
|
||||||
|
int pstclose(void* handle);
|
||||||
|
int pstput(void* handle, char* key, int bufcount, char* buffers[], int buflens[]);
|
||||||
|
int pstget(void* handle, char* key, char** buffer, int* buflen);
|
||||||
|
int pstremove(void* handle, char* key);
|
||||||
|
int pstkeys(void* handle, char*** keys, int* nkeys);
|
||||||
|
int pstclear(void* handle);
|
||||||
|
int pstcontainskey(void* handle, char* key);
|
||||||
|
|
||||||
|
int pstmkdir(char *pPathname);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
225
thirdparty/paho_mqtt/include/MQTTProperties.h
vendored
Normal file
225
thirdparty/paho_mqtt/include/MQTTProperties.h
vendored
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017, 2024 IBM Corp. and others
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTPROPERTIES_H)
|
||||||
|
#define MQTTPROPERTIES_H
|
||||||
|
|
||||||
|
#include "MQTTExportDeclarations.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MQTT_INVALID_PROPERTY_ID -2
|
||||||
|
|
||||||
|
/** The one byte MQTT V5 property indicator */
|
||||||
|
enum MQTTPropertyCodes {
|
||||||
|
MQTTPROPERTY_CODE_PAYLOAD_FORMAT_INDICATOR = 1, /**< The value is 1 */
|
||||||
|
MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL = 2, /**< The value is 2 */
|
||||||
|
MQTTPROPERTY_CODE_CONTENT_TYPE = 3, /**< The value is 3 */
|
||||||
|
MQTTPROPERTY_CODE_RESPONSE_TOPIC = 8, /**< The value is 8 */
|
||||||
|
MQTTPROPERTY_CODE_CORRELATION_DATA = 9, /**< The value is 9 */
|
||||||
|
MQTTPROPERTY_CODE_SUBSCRIPTION_IDENTIFIER = 11, /**< The value is 11 */
|
||||||
|
MQTTPROPERTY_CODE_SESSION_EXPIRY_INTERVAL = 17, /**< The value is 17 */
|
||||||
|
MQTTPROPERTY_CODE_ASSIGNED_CLIENT_IDENTIFIER = 18,/**< The value is 18 */
|
||||||
|
MQTTPROPERTY_CODE_ASSIGNED_CLIENT_IDENTIFER = 18,/**< The value is 18 (obsolete, misspelled) */
|
||||||
|
MQTTPROPERTY_CODE_SERVER_KEEP_ALIVE = 19, /**< The value is 19 */
|
||||||
|
MQTTPROPERTY_CODE_AUTHENTICATION_METHOD = 21, /**< The value is 21 */
|
||||||
|
MQTTPROPERTY_CODE_AUTHENTICATION_DATA = 22, /**< The value is 22 */
|
||||||
|
MQTTPROPERTY_CODE_REQUEST_PROBLEM_INFORMATION = 23,/**< The value is 23 */
|
||||||
|
MQTTPROPERTY_CODE_WILL_DELAY_INTERVAL = 24, /**< The value is 24 */
|
||||||
|
MQTTPROPERTY_CODE_REQUEST_RESPONSE_INFORMATION = 25,/**< The value is 25 */
|
||||||
|
MQTTPROPERTY_CODE_RESPONSE_INFORMATION = 26, /**< The value is 26 */
|
||||||
|
MQTTPROPERTY_CODE_SERVER_REFERENCE = 28, /**< The value is 28 */
|
||||||
|
MQTTPROPERTY_CODE_REASON_STRING = 31, /**< The value is 31 */
|
||||||
|
MQTTPROPERTY_CODE_RECEIVE_MAXIMUM = 33, /**< The value is 33*/
|
||||||
|
MQTTPROPERTY_CODE_TOPIC_ALIAS_MAXIMUM = 34, /**< The value is 34 */
|
||||||
|
MQTTPROPERTY_CODE_TOPIC_ALIAS = 35, /**< The value is 35 */
|
||||||
|
MQTTPROPERTY_CODE_MAXIMUM_QOS = 36, /**< The value is 36 */
|
||||||
|
MQTTPROPERTY_CODE_RETAIN_AVAILABLE = 37, /**< The value is 37 */
|
||||||
|
MQTTPROPERTY_CODE_USER_PROPERTY = 38, /**< The value is 38 */
|
||||||
|
MQTTPROPERTY_CODE_MAXIMUM_PACKET_SIZE = 39, /**< The value is 39 */
|
||||||
|
MQTTPROPERTY_CODE_WILDCARD_SUBSCRIPTION_AVAILABLE = 40,/**< The value is 40 */
|
||||||
|
MQTTPROPERTY_CODE_SUBSCRIPTION_IDENTIFIERS_AVAILABLE = 41,/**< The value is 41 */
|
||||||
|
MQTTPROPERTY_CODE_SHARED_SUBSCRIPTION_AVAILABLE = 42/**< The value is 241 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a printable string description of an MQTT V5 property code.
|
||||||
|
* @param value an MQTT V5 property code.
|
||||||
|
* @return the printable string description of the input property code.
|
||||||
|
* NULL if the code was not found.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API const char* MQTTPropertyName(enum MQTTPropertyCodes value);
|
||||||
|
|
||||||
|
/** The one byte MQTT V5 property type */
|
||||||
|
enum MQTTPropertyTypes {
|
||||||
|
MQTTPROPERTY_TYPE_BYTE,
|
||||||
|
MQTTPROPERTY_TYPE_TWO_BYTE_INTEGER,
|
||||||
|
MQTTPROPERTY_TYPE_FOUR_BYTE_INTEGER,
|
||||||
|
MQTTPROPERTY_TYPE_VARIABLE_BYTE_INTEGER,
|
||||||
|
MQTTPROPERTY_TYPE_BINARY_DATA,
|
||||||
|
MQTTPROPERTY_TYPE_UTF_8_ENCODED_STRING,
|
||||||
|
MQTTPROPERTY_TYPE_UTF_8_STRING_PAIR
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the MQTT V5 type code of an MQTT V5 property.
|
||||||
|
* @param value an MQTT V5 property code.
|
||||||
|
* @return the MQTT V5 type code of the input property. -1 if the code was not found.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API int MQTTProperty_getType(enum MQTTPropertyCodes value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data for a length delimited string
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int len; /**< the length of the string */
|
||||||
|
char* data; /**< pointer to the string data */
|
||||||
|
} MQTTLenString;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure to hold an MQTT version 5 property of any type
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
enum MQTTPropertyCodes identifier; /**< The MQTT V5 property id. A multi-byte integer. */
|
||||||
|
/** The value of the property, as a union of the different possible types. */
|
||||||
|
union {
|
||||||
|
unsigned char byte; /**< holds the value of a byte property type */
|
||||||
|
unsigned short integer2; /**< holds the value of a 2 byte integer property type */
|
||||||
|
unsigned int integer4; /**< holds the value of a 4 byte integer property type */
|
||||||
|
struct {
|
||||||
|
MQTTLenString data; /**< The value of a string property, or the name of a user property. */
|
||||||
|
MQTTLenString value; /**< The value of a user property. */
|
||||||
|
};
|
||||||
|
} value;
|
||||||
|
} MQTTProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MQTT version 5 property list
|
||||||
|
*/
|
||||||
|
typedef struct MQTTProperties
|
||||||
|
{
|
||||||
|
int count; /**< number of property entries in the array */
|
||||||
|
int max_count; /**< max number of properties that the currently allocated array can store */
|
||||||
|
int length; /**< mbi: byte length of all properties */
|
||||||
|
MQTTProperty *array; /**< array of properties */
|
||||||
|
} MQTTProperties;
|
||||||
|
|
||||||
|
#define MQTTProperties_initializer {0, 0, 0, NULL}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length of the properties structure when serialized ready for network transmission.
|
||||||
|
* @param props an MQTT V5 property structure.
|
||||||
|
* @return the length in bytes of the properties when serialized.
|
||||||
|
*/
|
||||||
|
int MQTTProperties_len(const MQTTProperties* props);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a property pointer to the property array. Memory is allocated in this function,
|
||||||
|
* so MQTTClient_create or MQTTAsync_create must be called first to initialize the
|
||||||
|
* internal heap tracking. Alternatively MQTTAsync_global_init() can be called first
|
||||||
|
* or build with the HIGH_PERFORMANCE option which disables the heap tracking.
|
||||||
|
* @param props The property list to add the property to.
|
||||||
|
* @param prop The property to add to the list.
|
||||||
|
* @return 0 on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API int MQTTProperties_add(MQTTProperties* props, const MQTTProperty* prop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the given property list to a character buffer, e.g. for writing to the network.
|
||||||
|
* @param pptr pointer to the buffer - move the pointer as we add data
|
||||||
|
* @param properties pointer to the property list, can be NULL
|
||||||
|
* @return whether the write succeeded or not: number of bytes written, or < 0 on failure.
|
||||||
|
*/
|
||||||
|
int MQTTProperties_write(char** pptr, const MQTTProperties* properties);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a property list from a character buffer into an array.
|
||||||
|
* @param properties pointer to the property list to be filled. Should be initalized but empty.
|
||||||
|
* @param pptr pointer to the character buffer.
|
||||||
|
* @param enddata pointer to the end of the character buffer so we don't read beyond.
|
||||||
|
* @return 1 if the properties were read successfully.
|
||||||
|
*/
|
||||||
|
int MQTTProperties_read(MQTTProperties* properties, char** pptr, char* enddata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free all memory allocated to the property list, including any to individual properties.
|
||||||
|
* @param properties pointer to the property list.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API void MQTTProperties_free(MQTTProperties* properties);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the contents of a property list, allocating additional memory if needed.
|
||||||
|
* @param props pointer to the property list.
|
||||||
|
* @return the duplicated property list.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API MQTTProperties MQTTProperties_copy(const MQTTProperties* props);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if property list contains a specific property.
|
||||||
|
* @param props pointer to the property list.
|
||||||
|
* @param propid the property id to check for.
|
||||||
|
* @return 1 if found, 0 if not.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API int MQTTProperties_hasProperty(const MQTTProperties *props, enum MQTTPropertyCodes propid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of instances of a property id. Most properties can exist only once.
|
||||||
|
* User properties and subscription ids can exist more than once.
|
||||||
|
* @param props pointer to the property list.
|
||||||
|
* @param propid the property id to check for.
|
||||||
|
* @return the number of times found. Can be 0.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API int MQTTProperties_propertyCount(const MQTTProperties *props, enum MQTTPropertyCodes propid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the integer value of a specific property. The property given must be a numeric type.
|
||||||
|
* @param props pointer to the property list.
|
||||||
|
* @param propid the property id to check for.
|
||||||
|
* @return the integer value of the property. -9999999 on failure.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API int64_t MQTTProperties_getNumericValue(const MQTTProperties *props, enum MQTTPropertyCodes propid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the integer value of a specific property when it's not the only instance.
|
||||||
|
* The property given must be a numeric type.
|
||||||
|
* @param props pointer to the property list.
|
||||||
|
* @param propid the property id to check for.
|
||||||
|
* @param index the instance number, starting at 0.
|
||||||
|
* @return the integer value of the property. -9999999 on failure.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API int64_t MQTTProperties_getNumericValueAt(const MQTTProperties *props, enum MQTTPropertyCodes propid, int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the property structure for a specific property.
|
||||||
|
* @param props pointer to the property list.
|
||||||
|
* @param propid the property id to check for.
|
||||||
|
* @return the pointer to the property structure if found. NULL if not found.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API MQTTProperty* MQTTProperties_getProperty(const MQTTProperties *props, enum MQTTPropertyCodes propid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the property structure for a specific property when it's not the only instance.
|
||||||
|
* @param props pointer to the property list.
|
||||||
|
* @param propid the property id to check for.
|
||||||
|
* @param index the instance number, starting at 0.
|
||||||
|
* @return the pointer to the property structure if found. NULL if not found.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API MQTTProperty* MQTTProperties_getPropertyAt(const MQTTProperties *props, enum MQTTPropertyCodes propid, int index);
|
||||||
|
|
||||||
|
#endif /* MQTTPROPERTIES_H */
|
||||||
46
thirdparty/paho_mqtt/include/MQTTProtocol.h
vendored
Normal file
46
thirdparty/paho_mqtt/include/MQTTProtocol.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2022 IBM Corp., Ian Craggs
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
* Ian Craggs - MQTT 3.1.1 updates
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTPROTOCOL_H)
|
||||||
|
#define MQTTPROTOCOL_H
|
||||||
|
|
||||||
|
#include "LinkedList.h"
|
||||||
|
#include "MQTTPacket.h"
|
||||||
|
#include "Clients.h"
|
||||||
|
|
||||||
|
#define MAX_MSG_ID 65535
|
||||||
|
#define MAX_CLIENTID_LEN 65535
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SOCKET socket;
|
||||||
|
Publications* p;
|
||||||
|
} pending_write;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
List publications;
|
||||||
|
unsigned int msgs_received;
|
||||||
|
unsigned int msgs_sent;
|
||||||
|
List pending_writes; /* for qos 0 writes not complete */
|
||||||
|
} MQTTProtocol;
|
||||||
|
|
||||||
|
|
||||||
|
#include "MQTTProtocolOut.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
62
thirdparty/paho_mqtt/include/MQTTProtocolClient.h
vendored
Normal file
62
thirdparty/paho_mqtt/include/MQTTProtocolClient.h
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2022 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
* Ian Craggs, Allan Stockdill-Mander - SSL updates
|
||||||
|
* Ian Craggs - MQTT 3.1.1 updates
|
||||||
|
* Rong Xiang, Ian Craggs - C++ compatibility
|
||||||
|
* Ian Craggs - add debug definition of MQTTStrdup for when needed
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTPROTOCOLCLIENT_H)
|
||||||
|
#define MQTTPROTOCOLCLIENT_H
|
||||||
|
|
||||||
|
#include "LinkedList.h"
|
||||||
|
#include "MQTTPacket.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "MQTTProtocol.h"
|
||||||
|
#include "Messages.h"
|
||||||
|
#include "MQTTProperties.h"
|
||||||
|
|
||||||
|
#define MAX_MSG_ID 65535
|
||||||
|
#define MAX_CLIENTID_LEN 65535
|
||||||
|
|
||||||
|
int MQTTProtocol_startPublish(Clients* pubclient, Publish* publish, int qos, int retained, Messages** m);
|
||||||
|
Messages* MQTTProtocol_createMessage(Publish* publish, Messages** mm, int qos, int retained, int allocatePayload);
|
||||||
|
Publications* MQTTProtocol_storePublication(Publish* publish, int* len);
|
||||||
|
int messageIDCompare(void* a, void* b);
|
||||||
|
int MQTTProtocol_assignMsgId(Clients* client);
|
||||||
|
void MQTTProtocol_removePublication(Publications* p);
|
||||||
|
void Protocol_processPublication(Publish* publish, Clients* client, int allocatePayload);
|
||||||
|
|
||||||
|
int MQTTProtocol_handlePublishes(void* pack, SOCKET sock);
|
||||||
|
int MQTTProtocol_handlePubacks(void* pack, SOCKET sock, Publications** pubToRemove);
|
||||||
|
int MQTTProtocol_handlePubrecs(void* pack, SOCKET sock, Publications** pubToRemove);
|
||||||
|
int MQTTProtocol_handlePubrels(void* pack, SOCKET sock);
|
||||||
|
int MQTTProtocol_handlePubcomps(void* pack, SOCKET sock, Publications** pubToRemove);
|
||||||
|
|
||||||
|
void MQTTProtocol_closeSession(Clients* c, int sendwill);
|
||||||
|
void MQTTProtocol_keepalive(START_TIME_TYPE);
|
||||||
|
void MQTTProtocol_retry(START_TIME_TYPE, int, int);
|
||||||
|
void MQTTProtocol_freeClient(Clients* client);
|
||||||
|
void MQTTProtocol_emptyMessageList(List* msgList);
|
||||||
|
void MQTTProtocol_freeMessageList(List* msgList);
|
||||||
|
|
||||||
|
char* MQTTStrncpy(char *dest, const char* src, size_t num);
|
||||||
|
char* MQTTStrdup(const char* src);
|
||||||
|
|
||||||
|
void MQTTProtocol_writeAvailable(SOCKET socket);
|
||||||
|
|
||||||
|
//#define MQTTStrdup(src) MQTTStrncpy(malloc(strlen(src)+1), src, strlen(src)+1)
|
||||||
|
|
||||||
|
#endif
|
||||||
66
thirdparty/paho_mqtt/include/MQTTProtocolOut.h
vendored
Normal file
66
thirdparty/paho_mqtt/include/MQTTProtocolOut.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2022 IBM Corp., Ian Craggs, and others
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
* Ian Craggs, Allan Stockdill-Mander - SSL updates
|
||||||
|
* Ian Craggs - MQTT 3.1.1 support
|
||||||
|
* Ian Craggs - SNI support
|
||||||
|
* Ian Craggs - MQTT 5.0 support
|
||||||
|
* Sven Gambel - add generic proxy support
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTPROTOCOLOUT_H)
|
||||||
|
#define MQTTPROTOCOLOUT_H
|
||||||
|
|
||||||
|
#include "LinkedList.h"
|
||||||
|
#include "MQTTPacket.h"
|
||||||
|
#include "Clients.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "Messages.h"
|
||||||
|
#include "MQTTProtocol.h"
|
||||||
|
#include "MQTTProtocolClient.h"
|
||||||
|
|
||||||
|
#define MQTT_DEFAULT_PORT 1883
|
||||||
|
#define SECURE_MQTT_DEFAULT_PORT 8883
|
||||||
|
#define WS_DEFAULT_PORT 80
|
||||||
|
#define WSS_DEFAULT_PORT 443
|
||||||
|
#define PROXY_DEFAULT_PORT 8080
|
||||||
|
|
||||||
|
size_t MQTTProtocol_addressPort(const char* uri, int* port, const char **topic, int default_port);
|
||||||
|
void MQTTProtocol_reconnect(const char* ip_address, Clients* client);
|
||||||
|
#if defined(OPENSSL)
|
||||||
|
#if defined(__GNUC__) && defined(__linux__)
|
||||||
|
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int unixsock, int ssl, int websocket, int MQTTVersion,
|
||||||
|
MQTTProperties* connectProperties, MQTTProperties* willProperties, long timeout);
|
||||||
|
#else
|
||||||
|
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int unixsock, int ssl, int websocket, int MQTTVersion,
|
||||||
|
MQTTProperties* connectProperties, MQTTProperties* willProperties);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(__GNUC__) && defined(__linux__)
|
||||||
|
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int unixsock, int websocket, int MQTTVersion,
|
||||||
|
MQTTProperties* connectProperties, MQTTProperties* willProperties, long timeout);
|
||||||
|
#else
|
||||||
|
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int unixsock, int websocket, int MQTTVersion,
|
||||||
|
MQTTProperties* connectProperties, MQTTProperties* willProperties);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
int MQTTProtocol_handlePingresps(void* pack, SOCKET sock);
|
||||||
|
int MQTTProtocol_subscribe(Clients* client, List* topics, List* qoss, int msgID,
|
||||||
|
MQTTSubscribe_options* opts, MQTTProperties* props);
|
||||||
|
int MQTTProtocol_handleSubacks(void* pack, SOCKET sock);
|
||||||
|
int MQTTProtocol_unsubscribe(Clients* client, List* topics, int msgID, MQTTProperties* props);
|
||||||
|
int MQTTProtocol_handleUnsubacks(void* pack, SOCKET sock);
|
||||||
|
int MQTTProtocol_handleDisconnects(void* pack, SOCKET sock);
|
||||||
|
|
||||||
|
#endif
|
||||||
79
thirdparty/paho_mqtt/include/MQTTReasonCodes.h
vendored
Normal file
79
thirdparty/paho_mqtt/include/MQTTReasonCodes.h
vendored
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017, 2020 IBM Corp. and others
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTREASONCODES_H)
|
||||||
|
#define MQTTREASONCODES_H
|
||||||
|
|
||||||
|
#include "MQTTExportDeclarations.h"
|
||||||
|
|
||||||
|
/** The MQTT V5 one byte reason code */
|
||||||
|
enum MQTTReasonCodes {
|
||||||
|
MQTTREASONCODE_SUCCESS = 0,
|
||||||
|
MQTTREASONCODE_NORMAL_DISCONNECTION = 0,
|
||||||
|
MQTTREASONCODE_GRANTED_QOS_0 = 0,
|
||||||
|
MQTTREASONCODE_GRANTED_QOS_1 = 1,
|
||||||
|
MQTTREASONCODE_GRANTED_QOS_2 = 2,
|
||||||
|
MQTTREASONCODE_DISCONNECT_WITH_WILL_MESSAGE = 4,
|
||||||
|
MQTTREASONCODE_NO_MATCHING_SUBSCRIBERS = 16,
|
||||||
|
MQTTREASONCODE_NO_SUBSCRIPTION_FOUND = 17,
|
||||||
|
MQTTREASONCODE_CONTINUE_AUTHENTICATION = 24,
|
||||||
|
MQTTREASONCODE_RE_AUTHENTICATE = 25,
|
||||||
|
MQTTREASONCODE_UNSPECIFIED_ERROR = 128,
|
||||||
|
MQTTREASONCODE_MALFORMED_PACKET = 129,
|
||||||
|
MQTTREASONCODE_PROTOCOL_ERROR = 130,
|
||||||
|
MQTTREASONCODE_IMPLEMENTATION_SPECIFIC_ERROR = 131,
|
||||||
|
MQTTREASONCODE_UNSUPPORTED_PROTOCOL_VERSION = 132,
|
||||||
|
MQTTREASONCODE_CLIENT_IDENTIFIER_NOT_VALID = 133,
|
||||||
|
MQTTREASONCODE_BAD_USER_NAME_OR_PASSWORD = 134,
|
||||||
|
MQTTREASONCODE_NOT_AUTHORIZED = 135,
|
||||||
|
MQTTREASONCODE_SERVER_UNAVAILABLE = 136,
|
||||||
|
MQTTREASONCODE_SERVER_BUSY = 137,
|
||||||
|
MQTTREASONCODE_BANNED = 138,
|
||||||
|
MQTTREASONCODE_SERVER_SHUTTING_DOWN = 139,
|
||||||
|
MQTTREASONCODE_BAD_AUTHENTICATION_METHOD = 140,
|
||||||
|
MQTTREASONCODE_KEEP_ALIVE_TIMEOUT = 141,
|
||||||
|
MQTTREASONCODE_SESSION_TAKEN_OVER = 142,
|
||||||
|
MQTTREASONCODE_TOPIC_FILTER_INVALID = 143,
|
||||||
|
MQTTREASONCODE_TOPIC_NAME_INVALID = 144,
|
||||||
|
MQTTREASONCODE_PACKET_IDENTIFIER_IN_USE = 145,
|
||||||
|
MQTTREASONCODE_PACKET_IDENTIFIER_NOT_FOUND = 146,
|
||||||
|
MQTTREASONCODE_RECEIVE_MAXIMUM_EXCEEDED = 147,
|
||||||
|
MQTTREASONCODE_TOPIC_ALIAS_INVALID = 148,
|
||||||
|
MQTTREASONCODE_PACKET_TOO_LARGE = 149,
|
||||||
|
MQTTREASONCODE_MESSAGE_RATE_TOO_HIGH = 150,
|
||||||
|
MQTTREASONCODE_QUOTA_EXCEEDED = 151,
|
||||||
|
MQTTREASONCODE_ADMINISTRATIVE_ACTION = 152,
|
||||||
|
MQTTREASONCODE_PAYLOAD_FORMAT_INVALID = 153,
|
||||||
|
MQTTREASONCODE_RETAIN_NOT_SUPPORTED = 154,
|
||||||
|
MQTTREASONCODE_QOS_NOT_SUPPORTED = 155,
|
||||||
|
MQTTREASONCODE_USE_ANOTHER_SERVER = 156,
|
||||||
|
MQTTREASONCODE_SERVER_MOVED = 157,
|
||||||
|
MQTTREASONCODE_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158,
|
||||||
|
MQTTREASONCODE_CONNECTION_RATE_EXCEEDED = 159,
|
||||||
|
MQTTREASONCODE_MAXIMUM_CONNECT_TIME = 160,
|
||||||
|
MQTTREASONCODE_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161,
|
||||||
|
MQTTREASONCODE_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a printable string description of an MQTT V5 reason code.
|
||||||
|
* @param value an MQTT V5 reason code.
|
||||||
|
* @return the printable string description of the input reason code.
|
||||||
|
* NULL if the code was not found.
|
||||||
|
*/
|
||||||
|
LIBMQTT_API const char* MQTTReasonCode_toString(enum MQTTReasonCodes value);
|
||||||
|
|
||||||
|
#endif
|
||||||
46
thirdparty/paho_mqtt/include/MQTTSubscribeOpts.h
vendored
Normal file
46
thirdparty/paho_mqtt/include/MQTTSubscribeOpts.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2018 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(SUBOPTS_H)
|
||||||
|
#define SUBOPTS_H
|
||||||
|
|
||||||
|
/** The MQTT V5 subscribe options, apart from QoS which existed before V5. */
|
||||||
|
typedef struct MQTTSubscribe_options
|
||||||
|
{
|
||||||
|
/** The eyecatcher for this structure. Must be MQSO. */
|
||||||
|
char struct_id[4];
|
||||||
|
/** The version number of this structure. Must be 0.
|
||||||
|
*/
|
||||||
|
int struct_version;
|
||||||
|
/** To not receive our own publications, set to 1.
|
||||||
|
* 0 is the original MQTT behaviour - all messages matching the subscription are received.
|
||||||
|
*/
|
||||||
|
unsigned char noLocal;
|
||||||
|
/** To keep the retain flag as on the original publish message, set to 1.
|
||||||
|
* If 0, defaults to the original MQTT behaviour where the retain flag is only set on
|
||||||
|
* publications sent by a broker if in response to a subscribe request.
|
||||||
|
*/
|
||||||
|
unsigned char retainAsPublished;
|
||||||
|
/** 0 - send retained messages at the time of the subscribe (original MQTT behaviour)
|
||||||
|
* 1 - send retained messages on subscribe only if the subscription is new
|
||||||
|
* 2 - do not send retained messages at all
|
||||||
|
*/
|
||||||
|
unsigned char retainHandling;
|
||||||
|
} MQTTSubscribe_options;
|
||||||
|
|
||||||
|
#define MQTTSubscribe_options_initializer { {'M', 'Q', 'S', 'O'}, 0, 0, 0, 0 }
|
||||||
|
|
||||||
|
#endif
|
||||||
49
thirdparty/paho_mqtt/include/MQTTTime.h
vendored
Normal file
49
thirdparty/paho_mqtt/include/MQTTTime.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2020 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(MQTTTIME_H)
|
||||||
|
#define MQTTTIME_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#if WINVER >= _WIN32_WINNT_VISTA
|
||||||
|
#define START_TIME_TYPE ULONGLONG
|
||||||
|
#define START_TIME_ZERO 0
|
||||||
|
#else
|
||||||
|
#define START_TIME_TYPE DWORD
|
||||||
|
#define START_TIME_ZERO 0
|
||||||
|
#endif
|
||||||
|
#elif defined(AIX)
|
||||||
|
#define START_TIME_TYPE struct timespec
|
||||||
|
#define START_TIME_ZERO {0, 0}
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#define START_TIME_TYPE struct timeval
|
||||||
|
#define START_TIME_ZERO {0, 0}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ELAPSED_TIME_TYPE uint64_t
|
||||||
|
#define DIFF_TIME_TYPE int64_t
|
||||||
|
|
||||||
|
void MQTTTime_sleep(ELAPSED_TIME_TYPE milliseconds);
|
||||||
|
START_TIME_TYPE MQTTTime_start_clock(void);
|
||||||
|
START_TIME_TYPE MQTTTime_now(void);
|
||||||
|
ELAPSED_TIME_TYPE MQTTTime_elapsed(START_TIME_TYPE milliseconds);
|
||||||
|
DIFF_TIME_TYPE MQTTTime_difftime(START_TIME_TYPE t_new, START_TIME_TYPE t_old);
|
||||||
|
|
||||||
|
#endif
|
||||||
BIN
thirdparty/paho_mqtt/lib/paho-mqtt3a.dll
vendored
Normal file
BIN
thirdparty/paho_mqtt/lib/paho-mqtt3a.dll
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/lib/paho-mqtt3a.lib
vendored
Normal file
BIN
thirdparty/paho_mqtt/lib/paho-mqtt3a.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/lib/paho-mqtt3c.dll
vendored
Normal file
BIN
thirdparty/paho_mqtt/lib/paho-mqtt3c.dll
vendored
Normal file
Binary file not shown.
BIN
thirdparty/paho_mqtt/lib/paho-mqtt3c.lib
vendored
Normal file
BIN
thirdparty/paho_mqtt/lib/paho-mqtt3c.lib
vendored
Normal file
Binary file not shown.
108
thirdparty/paho_mqtt/notice.html
vendored
Normal file
108
thirdparty/paho_mqtt/notice.html
vendored
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
|
||||||
|
<title>Eclipse Foundation Software User Agreement</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body lang="EN-US">
|
||||||
|
<h2>Eclipse Foundation Software User Agreement</h2>
|
||||||
|
<p>April 6, 2020</p>
|
||||||
|
|
||||||
|
<h3>Usage Of Content</h3>
|
||||||
|
|
||||||
|
<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
|
||||||
|
(COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
|
||||||
|
CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
|
||||||
|
OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
|
||||||
|
NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
|
||||||
|
CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
|
||||||
|
|
||||||
|
<h3>Applicable Licenses</h3>
|
||||||
|
|
||||||
|
<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 2.0
|
||||||
|
("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="https://www.eclipse.org/legal/epl-2.0/">https://www.eclipse.org/legal/epl-2.0/</a>.
|
||||||
|
For purposes of the EPL, "Program" will mean the Content.</p>
|
||||||
|
|
||||||
|
<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
|
||||||
|
repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li>
|
||||||
|
<li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li>
|
||||||
|
<li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins
|
||||||
|
and/or Fragments associated with that Feature.</li>
|
||||||
|
<li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and
|
||||||
|
Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module
|
||||||
|
including, but not limited to the following locations:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The top-level (root) directory</li>
|
||||||
|
<li>Plug-in and Fragment directories</li>
|
||||||
|
<li>Inside Plug-ins and Fragments packaged as JARs</li>
|
||||||
|
<li>Sub-directories of the directory named "src" of certain Plug-ins</li>
|
||||||
|
<li>Feature directories</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the
|
||||||
|
installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
|
||||||
|
inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature.
|
||||||
|
Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
|
||||||
|
that directory.</p>
|
||||||
|
|
||||||
|
<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
|
||||||
|
OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
|
||||||
|
<li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
|
||||||
|
<li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
|
||||||
|
<li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
|
||||||
|
<li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
|
||||||
|
<li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
|
||||||
|
contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Use of Provisioning Technology</h3>
|
||||||
|
|
||||||
|
<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
|
||||||
|
Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or
|
||||||
|
other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to
|
||||||
|
install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
|
||||||
|
href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
|
||||||
|
("Specification").</p>
|
||||||
|
|
||||||
|
<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
|
||||||
|
applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
|
||||||
|
in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
|
||||||
|
Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology
|
||||||
|
on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based
|
||||||
|
product.</li>
|
||||||
|
<li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
|
||||||
|
accessed and copied to the Target Machine.</li>
|
||||||
|
<li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
|
||||||
|
Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target
|
||||||
|
Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
|
||||||
|
the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
|
||||||
|
indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3>Cryptography</h3>
|
||||||
|
|
||||||
|
<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
|
||||||
|
another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
|
||||||
|
possession, or use, and re-export of encryption software, to see if this is permitted.</p>
|
||||||
|
|
||||||
|
<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
188
thirdparty/paho_mqtt/samples/MQTTAsync_publish.c
vendored
Normal file
188
thirdparty/paho_mqtt/samples/MQTTAsync_publish.c
vendored
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MQTTAsync.h"
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WRS_KERNEL)
|
||||||
|
#include <OsWrapper.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ADDRESS "tcp://test.mosquitto.org:1883"
|
||||||
|
#define CLIENTID "ExampleClientPub"
|
||||||
|
#define TOPIC "MQTT Examples"
|
||||||
|
#define PAYLOAD "Hello World!"
|
||||||
|
#define QOS 1
|
||||||
|
#define TIMEOUT 10000L
|
||||||
|
|
||||||
|
int finished = 0;
|
||||||
|
|
||||||
|
void connlost(void *context, char *cause)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
printf("\nConnection lost\n");
|
||||||
|
if (cause)
|
||||||
|
printf(" cause: %s\n", cause);
|
||||||
|
|
||||||
|
printf("Reconnecting\n");
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start connect, return code %d\n", rc);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
printf("Disconnect failed\n");
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
printf("Successful disconnection\n");
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSendFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
printf("Message send failed token %d error code %d\n", response->token, response->code);
|
||||||
|
opts.onSuccess = onDisconnect;
|
||||||
|
opts.onFailure = onDisconnectFailure;
|
||||||
|
opts.context = client;
|
||||||
|
if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start disconnect, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSend(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
printf("Message with token value %d delivery confirmed\n", response->token);
|
||||||
|
opts.onSuccess = onDisconnect;
|
||||||
|
opts.onFailure = onDisconnectFailure;
|
||||||
|
opts.context = client;
|
||||||
|
if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start disconnect, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnectFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
printf("Connect failed, rc %d\n", response ? response->code : 0);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
|
||||||
|
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
printf("Successful connection\n");
|
||||||
|
opts.onSuccess = onSend;
|
||||||
|
opts.onFailure = onSendFailure;
|
||||||
|
opts.context = client;
|
||||||
|
pubmsg.payload = PAYLOAD;
|
||||||
|
pubmsg.payloadlen = (int)strlen(PAYLOAD);
|
||||||
|
pubmsg.qos = QOS;
|
||||||
|
pubmsg.retained = 0;
|
||||||
|
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start sendMessage, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* m)
|
||||||
|
{
|
||||||
|
/* not expecting any messages */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
MQTTAsync client;
|
||||||
|
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
|
||||||
|
printf("Using server at %s\n", uri);
|
||||||
|
|
||||||
|
if ((rc = MQTTAsync_create(&client, uri, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to create client object, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = MQTTAsync_setCallbacks(client, client, connlost, messageArrived, NULL)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to set callback, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
conn_opts.onSuccess = onConnect;
|
||||||
|
conn_opts.onFailure = onConnectFailure;
|
||||||
|
conn_opts.context = client;
|
||||||
|
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start connect, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Waiting for publication of %s\n"
|
||||||
|
"on topic %s for client with ClientID: %s\n",
|
||||||
|
PAYLOAD, TOPIC, CLIENTID);
|
||||||
|
while (!finished)
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep(100);
|
||||||
|
#else
|
||||||
|
usleep(10000L);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MQTTAsync_destroy(&client);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
218
thirdparty/paho_mqtt/samples/MQTTAsync_publish_time.c
vendored
Normal file
218
thirdparty/paho_mqtt/samples/MQTTAsync_publish_time.c
vendored
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2023 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
* Frank Pagliughi - loop to repeatedly read and sent time values.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
// This is a somewhat contrived example to show an application that publishes
|
||||||
|
// continuously, like a data acquisition app might do. In this case, though,
|
||||||
|
// we don't have a sensor to read, so we use the system time as the number
|
||||||
|
// of milliseconds since the epoch to simulate a data input.
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "MQTTAsync.h"
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#include <Minwinbase.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WRS_KERNEL)
|
||||||
|
#include <OsWrapper.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Better not to flood a public broker. Test against localhost.
|
||||||
|
#define ADDRESS "mqtt://localhost:1883"
|
||||||
|
|
||||||
|
#define CLIENTID "ExampleClientTimePub"
|
||||||
|
#define TOPIC "data/time"
|
||||||
|
#define QOS 1
|
||||||
|
#define TIMEOUT 10000L
|
||||||
|
#define SAMPLE_PERIOD 10L // in ms
|
||||||
|
|
||||||
|
volatile int finished = 0;
|
||||||
|
volatile int connected = 0;
|
||||||
|
|
||||||
|
void connlost(void *context, char *cause)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
printf("\nConnection lost\n");
|
||||||
|
if (cause)
|
||||||
|
printf(" cause: %s\n", cause);
|
||||||
|
|
||||||
|
printf("Reconnecting\n");
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start connect, return code %d\n", rc);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
printf("Disconnect failed\n");
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
printf("Successful disconnection\n");
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSendFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
printf("Message send failed token %d error code %d\n", response->token, response->code);
|
||||||
|
opts.onSuccess = onDisconnect;
|
||||||
|
opts.onFailure = onDisconnectFailure;
|
||||||
|
opts.context = client;
|
||||||
|
if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start disconnect, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSend(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
// This gets called when a message is acknowledged successfully.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnectFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
printf("Connect failed, rc %d\n", response ? response->code : 0);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
printf("Successful connection\n");
|
||||||
|
connected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* m)
|
||||||
|
{
|
||||||
|
/* not expecting any messages */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t getTime(void)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
FILETIME ft;
|
||||||
|
GetSystemTimeAsFileTime(&ft);
|
||||||
|
return ((((int64_t) ft.dwHighDateTime) << 8) + ft.dwLowDateTime) / 10000;
|
||||||
|
#else
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
return ((int64_t) ts.tv_sec * 1000) + ((int64_t) ts.tv_nsec / 1000000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
MQTTAsync client;
|
||||||
|
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||||
|
|
||||||
|
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
|
||||||
|
MQTTAsync_responseOptions pub_opts = MQTTAsync_responseOptions_initializer;
|
||||||
|
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ((rc = MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to create client object, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = MQTTAsync_setCallbacks(client, client, connlost, messageArrived, NULL)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to set callback, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
conn_opts.onSuccess = onConnect;
|
||||||
|
conn_opts.onFailure = onConnectFailure;
|
||||||
|
conn_opts.context = client;
|
||||||
|
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start connect, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!connected) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep(100);
|
||||||
|
#else
|
||||||
|
usleep(100000L);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!finished) {
|
||||||
|
int64_t t = getTime();
|
||||||
|
|
||||||
|
char buf[256];
|
||||||
|
int n = snprintf(buf, sizeof(buf), "%lld", (long long) t);
|
||||||
|
printf("%s\n", buf);
|
||||||
|
|
||||||
|
pub_opts.onSuccess = onSend;
|
||||||
|
pub_opts.onFailure = onSendFailure;
|
||||||
|
pub_opts.context = client;
|
||||||
|
|
||||||
|
pubmsg.payload = buf;
|
||||||
|
pubmsg.payloadlen = n;
|
||||||
|
pubmsg.qos = QOS;
|
||||||
|
pubmsg.retained = 0;
|
||||||
|
|
||||||
|
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &pub_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start sendMessage, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep(SAMPLE_PERIOD);
|
||||||
|
#else
|
||||||
|
usleep(SAMPLE_PERIOD * 1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
MQTTAsync_destroy(&client);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
206
thirdparty/paho_mqtt/samples/MQTTAsync_subscribe.c
vendored
Normal file
206
thirdparty/paho_mqtt/samples/MQTTAsync_subscribe.c
vendored
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MQTTAsync.h"
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WRS_KERNEL)
|
||||||
|
#include <OsWrapper.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ADDRESS "tcp://test.mosquitto.org:1883"
|
||||||
|
#define CLIENTID "ExampleClientSub"
|
||||||
|
#define TOPIC "MQTT Examples"
|
||||||
|
#define PAYLOAD "Hello World!"
|
||||||
|
#define QOS 1
|
||||||
|
#define TIMEOUT 10000L
|
||||||
|
|
||||||
|
int disc_finished = 0;
|
||||||
|
int subscribed = 0;
|
||||||
|
int finished = 0;
|
||||||
|
|
||||||
|
void onConnect(void* context, MQTTAsync_successData* response);
|
||||||
|
void onConnectFailure(void* context, MQTTAsync_failureData* response);
|
||||||
|
|
||||||
|
void connlost(void *context, char *cause)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
printf("\nConnection lost\n");
|
||||||
|
if (cause)
|
||||||
|
printf(" cause: %s\n", cause);
|
||||||
|
|
||||||
|
printf("Reconnecting\n");
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
conn_opts.onSuccess = onConnect;
|
||||||
|
conn_opts.onFailure = onConnectFailure;
|
||||||
|
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start connect, return code %d\n", rc);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
|
||||||
|
{
|
||||||
|
printf("Message arrived\n");
|
||||||
|
printf(" topic: %s\n", topicName);
|
||||||
|
printf(" message: %.*s\n", message->payloadlen, (char*)message->payload);
|
||||||
|
MQTTAsync_freeMessage(&message);
|
||||||
|
MQTTAsync_free(topicName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
printf("Disconnect failed, rc %d\n", response->code);
|
||||||
|
disc_finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
printf("Successful disconnection\n");
|
||||||
|
disc_finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSubscribe(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
printf("Subscribe succeeded\n");
|
||||||
|
subscribed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
printf("Subscribe failed, rc %d\n", response->code);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnectFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
printf("Connect failed, rc %d\n", response->code);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
printf("Successful connection\n");
|
||||||
|
|
||||||
|
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
|
||||||
|
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
|
||||||
|
opts.onSuccess = onSubscribe;
|
||||||
|
opts.onFailure = onSubscribeFailure;
|
||||||
|
opts.context = client;
|
||||||
|
if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start subscribe, return code %d\n", rc);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
MQTTAsync client;
|
||||||
|
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||||
|
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
|
||||||
|
printf("Using server at %s\n", uri);
|
||||||
|
|
||||||
|
if ((rc = MQTTAsync_create(&client, uri, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL))
|
||||||
|
!= MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to create client, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = MQTTAsync_setCallbacks(client, client, connlost, msgarrvd, NULL)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to set callbacks, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto destroy_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
conn_opts.onSuccess = onConnect;
|
||||||
|
conn_opts.onFailure = onConnectFailure;
|
||||||
|
conn_opts.context = client;
|
||||||
|
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start connect, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto destroy_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!subscribed && !finished)
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep(100);
|
||||||
|
#else
|
||||||
|
usleep(10000L);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (finished)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ch = getchar();
|
||||||
|
} while (ch!='Q' && ch != 'q');
|
||||||
|
|
||||||
|
disc_opts.onSuccess = onDisconnect;
|
||||||
|
disc_opts.onFailure = onDisconnectFailure;
|
||||||
|
if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to start disconnect, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto destroy_exit;
|
||||||
|
}
|
||||||
|
while (!disc_finished)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep(100);
|
||||||
|
#else
|
||||||
|
usleep(10000L);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy_exit:
|
||||||
|
MQTTAsync_destroy(&client);
|
||||||
|
exit:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
75
thirdparty/paho_mqtt/samples/MQTTClient_publish.c
vendored
Normal file
75
thirdparty/paho_mqtt/samples/MQTTClient_publish.c
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MQTTClient.h"
|
||||||
|
|
||||||
|
#define ADDRESS "tcp://test.mosquitto.org:1883"
|
||||||
|
#define CLIENTID "ExampleClientPub"
|
||||||
|
#define TOPIC "MQTT Examples"
|
||||||
|
#define PAYLOAD "Hello World!"
|
||||||
|
#define QOS 1
|
||||||
|
#define TIMEOUT 10000L
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
MQTTClient client;
|
||||||
|
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
|
||||||
|
MQTTClient_message pubmsg = MQTTClient_message_initializer;
|
||||||
|
MQTTClient_deliveryToken token;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
|
||||||
|
printf("Using server at %s\n", uri);
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_create(&client, uri, CLIENTID,
|
||||||
|
MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to create client, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to connect, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pubmsg.payload = PAYLOAD;
|
||||||
|
pubmsg.payloadlen = (int)strlen(PAYLOAD);
|
||||||
|
pubmsg.qos = QOS;
|
||||||
|
pubmsg.retained = 0;
|
||||||
|
if ((rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to publish message, return code %d\n", rc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Waiting for up to %d seconds for publication of %s\n"
|
||||||
|
"on topic %s for client with ClientID: %s\n",
|
||||||
|
(int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
|
||||||
|
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
|
||||||
|
printf("Message with delivery token %d delivered\n", token);
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
|
||||||
|
printf("Failed to disconnect, return code %d\n", rc);
|
||||||
|
MQTTClient_destroy(&client);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
131
thirdparty/paho_mqtt/samples/MQTTClient_publish_async.c
vendored
Normal file
131
thirdparty/paho_mqtt/samples/MQTTClient_publish_async.c
vendored
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MQTTClient.h"
|
||||||
|
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ADDRESS "tcp://test.mosquitto.org:1883"
|
||||||
|
#define CLIENTID "ExampleClientPub"
|
||||||
|
#define TOPIC "MQTT Examples"
|
||||||
|
#define PAYLOAD "Hello World!"
|
||||||
|
#define QOS 1
|
||||||
|
#define TIMEOUT 10000L
|
||||||
|
|
||||||
|
MQTTClient_deliveryToken deliveredtoken;
|
||||||
|
|
||||||
|
void delivered(void *context, MQTTClient_deliveryToken dt)
|
||||||
|
{
|
||||||
|
printf("Message with token value %d delivery confirmed\n", dt);
|
||||||
|
deliveredtoken = dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
|
||||||
|
{
|
||||||
|
printf("Message arrived\n");
|
||||||
|
printf(" topic: %s\n", topicName);
|
||||||
|
printf(" message: %.*s\n", message->payloadlen, (char*)message->payload);
|
||||||
|
MQTTClient_freeMessage(&message);
|
||||||
|
MQTTClient_free(topicName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connlost(void *context, char *cause)
|
||||||
|
{
|
||||||
|
printf("\nConnection lost\n");
|
||||||
|
if (cause)
|
||||||
|
printf(" cause: %s\n", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
MQTTClient client;
|
||||||
|
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
|
||||||
|
MQTTClient_message pubmsg = MQTTClient_message_initializer;
|
||||||
|
MQTTClient_deliveryToken token;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
|
||||||
|
printf("Using server at %s\n", uri);
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_create(&client, uri, CLIENTID,
|
||||||
|
MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to create client, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to set callbacks, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto destroy_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to connect, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto destroy_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pubmsg.payload = PAYLOAD;
|
||||||
|
pubmsg.payloadlen = (int)strlen(PAYLOAD);
|
||||||
|
pubmsg.qos = QOS;
|
||||||
|
pubmsg.retained = 0;
|
||||||
|
deliveredtoken = 0;
|
||||||
|
if ((rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to publish message, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Waiting for publication of %s\n"
|
||||||
|
"on topic %s for client with ClientID: %s\n",
|
||||||
|
PAYLOAD, TOPIC, CLIENTID);
|
||||||
|
while (deliveredtoken != token)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep(100);
|
||||||
|
#else
|
||||||
|
usleep(10000L);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to disconnect, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy_exit:
|
||||||
|
MQTTClient_destroy(&client);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
118
thirdparty/paho_mqtt/samples/MQTTClient_subscribe.c
vendored
Normal file
118
thirdparty/paho_mqtt/samples/MQTTClient_subscribe.c
vendored
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "MQTTClient.h"
|
||||||
|
|
||||||
|
#define ADDRESS "tcp://test.mosquitto.org:1883"
|
||||||
|
#define CLIENTID "ExampleClientSub"
|
||||||
|
#define TOPIC "MQTT Examples"
|
||||||
|
#define PAYLOAD "Hello World!"
|
||||||
|
#define QOS 1
|
||||||
|
#define TIMEOUT 10000L
|
||||||
|
|
||||||
|
volatile MQTTClient_deliveryToken deliveredtoken;
|
||||||
|
|
||||||
|
void delivered(void *context, MQTTClient_deliveryToken dt)
|
||||||
|
{
|
||||||
|
printf("Message with token value %d delivery confirmed\n", dt);
|
||||||
|
deliveredtoken = dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
|
||||||
|
{
|
||||||
|
printf("Message arrived\n");
|
||||||
|
printf(" topic: %s\n", topicName);
|
||||||
|
printf(" message: %.*s\n", message->payloadlen, (char*)message->payload);
|
||||||
|
MQTTClient_freeMessage(&message);
|
||||||
|
MQTTClient_free(topicName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connlost(void *context, char *cause)
|
||||||
|
{
|
||||||
|
printf("\nConnection lost\n");
|
||||||
|
if (cause)
|
||||||
|
printf(" cause: %s\n", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
MQTTClient client;
|
||||||
|
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
|
||||||
|
printf("Using server at %s\n", uri);
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_create(&client, uri, CLIENTID,
|
||||||
|
MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to create client, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to set callbacks, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto destroy_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_opts.keepAliveInterval = 20;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to connect, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto destroy_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
|
||||||
|
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
|
||||||
|
if ((rc = MQTTClient_subscribe(client, TOPIC, QOS)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to subscribe, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ch = getchar();
|
||||||
|
} while (ch!='Q' && ch != 'q');
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_unsubscribe(client, TOPIC)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to unsubscribe, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
printf("Failed to disconnect, return code %d\n", rc);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
destroy_exit:
|
||||||
|
MQTTClient_destroy(&client);
|
||||||
|
exit:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
519
thirdparty/paho_mqtt/samples/paho_c_pub.c
vendored
Normal file
519
thirdparty/paho_mqtt/samples/paho_c_pub.c
vendored
Normal file
@@ -0,0 +1,519 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs and others
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
* Guilherme Maciel Ferreira - add keep alive option
|
||||||
|
* Ian Craggs - add full capability
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "MQTTAsync.h"
|
||||||
|
#include "pubsub_opts.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#define sleep Sleep
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WRS_KERNEL)
|
||||||
|
#include <OsWrapper.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
volatile int toStop = 0;
|
||||||
|
|
||||||
|
struct pubsub_opts opts =
|
||||||
|
{
|
||||||
|
1, 0, 0, 0, "\n", 100, /* debug/app options */
|
||||||
|
NULL, NULL, 1, 0, 0, /* message options */
|
||||||
|
MQTTVERSION_DEFAULT, NULL, "paho-c-pub", 0, 0, NULL, NULL, "localhost", "1883", NULL, 10, /* MQTT options */
|
||||||
|
NULL, NULL, 0, 0, /* will options */
|
||||||
|
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* TLS options */
|
||||||
|
0, {NULL, NULL}, /* MQTT V5 options */
|
||||||
|
NULL, NULL, /* HTTP and HTTPS proxies */
|
||||||
|
};
|
||||||
|
|
||||||
|
MQTTAsync_responseOptions pub_opts = MQTTAsync_responseOptions_initializer;
|
||||||
|
MQTTProperty property;
|
||||||
|
MQTTProperties props = MQTTProperties_initializer;
|
||||||
|
|
||||||
|
|
||||||
|
void mysleep(int ms)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep(ms);
|
||||||
|
#else
|
||||||
|
usleep(ms * 1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cfinish(int sig)
|
||||||
|
{
|
||||||
|
signal(SIGINT, NULL);
|
||||||
|
toStop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* m)
|
||||||
|
{
|
||||||
|
/* not expecting any messages */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int disconnected = 0;
|
||||||
|
|
||||||
|
void onDisconnect5(void* context, MQTTAsync_successData5* response)
|
||||||
|
{
|
||||||
|
disconnected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
disconnected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int connected = 0;
|
||||||
|
void myconnect(MQTTAsync client);
|
||||||
|
int mypublish(MQTTAsync client, int datalen, char* data);
|
||||||
|
|
||||||
|
void onConnectFailure5(void* context, MQTTAsync_failureData5* response)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Connect failed, rc %s reason code %s\n",
|
||||||
|
MQTTAsync_strerror(response->code),
|
||||||
|
MQTTReasonCode_toString(response->reasonCode));
|
||||||
|
connected = -1;
|
||||||
|
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onConnectFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Connect failed, rc %s\n", response ? MQTTAsync_strerror(response->code) : "none");
|
||||||
|
connected = -1;
|
||||||
|
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnect5(void* context, MQTTAsync_successData5* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Connected\n");
|
||||||
|
|
||||||
|
if (opts.null_message == 1)
|
||||||
|
rc = mypublish(client, 0, "");
|
||||||
|
else if (opts.message)
|
||||||
|
rc = mypublish(client, (int)strlen(opts.message), opts.message);
|
||||||
|
else if (opts.filename)
|
||||||
|
{
|
||||||
|
int data_len = 0;
|
||||||
|
char* buffer = readfile(&data_len, &opts);
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
toStop = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = mypublish(client, data_len, buffer);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onConnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Connected\n");
|
||||||
|
|
||||||
|
if (opts.null_message == 1)
|
||||||
|
rc = mypublish(client, 0, "");
|
||||||
|
else if (opts.message)
|
||||||
|
rc = mypublish(client, (int)strlen(opts.message), opts.message);
|
||||||
|
else if (opts.filename)
|
||||||
|
{
|
||||||
|
int data_len = 0;
|
||||||
|
char* buffer = readfile(&data_len, &opts);
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
toStop = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = mypublish(client, data_len, buffer);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int published = 0;
|
||||||
|
|
||||||
|
void onPublishFailure5(void* context, MQTTAsync_failureData5* response)
|
||||||
|
{
|
||||||
|
if (opts.verbose)
|
||||||
|
fprintf(stderr, "Publish failed, rc %s reason code %s\n",
|
||||||
|
MQTTAsync_strerror(response->code),
|
||||||
|
MQTTReasonCode_toString(response->reasonCode));
|
||||||
|
published = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPublishFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
if (opts.verbose)
|
||||||
|
fprintf(stderr, "Publish failed, rc %s\n", MQTTAsync_strerror(response->code));
|
||||||
|
published = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onPublish5(void* context, MQTTAsync_successData5* response)
|
||||||
|
{
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Publish succeeded, reason code %s\n",
|
||||||
|
MQTTReasonCode_toString(response->reasonCode));
|
||||||
|
|
||||||
|
if (opts.null_message || opts.message || opts.filename)
|
||||||
|
toStop = 1;
|
||||||
|
|
||||||
|
published = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onPublish(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Publish succeeded\n");
|
||||||
|
|
||||||
|
if (opts.null_message || opts.message || opts.filename)
|
||||||
|
toStop = 1;
|
||||||
|
|
||||||
|
published = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int onSSLError(const char *str, size_t len, void *context)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
return fprintf(stderr, "SSL error: %s\n", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int onPSKAuth(const char* hint,
|
||||||
|
char* identity,
|
||||||
|
unsigned int max_identity_len,
|
||||||
|
unsigned char* psk,
|
||||||
|
unsigned int max_psk_len,
|
||||||
|
void* context)
|
||||||
|
{
|
||||||
|
int psk_len;
|
||||||
|
int k, n;
|
||||||
|
|
||||||
|
int rc = 0;
|
||||||
|
struct pubsub_opts* opts = context;
|
||||||
|
|
||||||
|
/* printf("Trying TLS-PSK auth with hint: %s\n", hint);*/
|
||||||
|
|
||||||
|
if (opts->psk == NULL || opts->psk_identity == NULL)
|
||||||
|
{
|
||||||
|
/* printf("No PSK entered\n"); */
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* psk should be array of bytes. This is a quick and dirty way to
|
||||||
|
* convert hex to bytes without input validation */
|
||||||
|
psk_len = (int)strlen(opts->psk) / 2;
|
||||||
|
if (psk_len > max_psk_len)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "PSK too long\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
for (k=0, n=0; k < psk_len; k++, n += 2)
|
||||||
|
{
|
||||||
|
sscanf(&opts->psk[n], "%2hhx", &psk[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* identity should be NULL terminated string */
|
||||||
|
strncpy(identity, opts->psk_identity, max_identity_len);
|
||||||
|
if (identity[max_identity_len - 1] != '\0')
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Identity too long\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function should return length of psk on success. */
|
||||||
|
rc = psk_len;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void myconnect(MQTTAsync client)
|
||||||
|
{
|
||||||
|
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||||
|
MQTTAsync_SSLOptions ssl_opts = MQTTAsync_SSLOptions_initializer;
|
||||||
|
MQTTAsync_willOptions will_opts = MQTTAsync_willOptions_initializer;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Connecting\n");
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTAsync_connectOptions conn_opts5 = MQTTAsync_connectOptions_initializer5;
|
||||||
|
conn_opts = conn_opts5;
|
||||||
|
conn_opts.onSuccess5 = onConnect5;
|
||||||
|
conn_opts.onFailure5 = onConnectFailure5;
|
||||||
|
conn_opts.cleanstart = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
conn_opts.onSuccess = onConnect;
|
||||||
|
conn_opts.onFailure = onConnectFailure;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
}
|
||||||
|
conn_opts.keepAliveInterval = opts.keepalive;
|
||||||
|
conn_opts.username = opts.username;
|
||||||
|
conn_opts.password = opts.password;
|
||||||
|
conn_opts.MQTTVersion = opts.MQTTVersion;
|
||||||
|
conn_opts.context = client;
|
||||||
|
conn_opts.automaticReconnect = 1;
|
||||||
|
conn_opts.httpProxy = opts.http_proxy;
|
||||||
|
conn_opts.httpsProxy = opts.https_proxy;
|
||||||
|
|
||||||
|
if (opts.will_topic) /* will options */
|
||||||
|
{
|
||||||
|
will_opts.message = opts.will_payload;
|
||||||
|
will_opts.topicName = opts.will_topic;
|
||||||
|
will_opts.qos = opts.will_qos;
|
||||||
|
will_opts.retained = opts.will_retain;
|
||||||
|
conn_opts.will = &will_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.connection && (strncmp(opts.connection, "ssl://", 6) == 0 ||
|
||||||
|
strncmp(opts.connection, "tls://", 6) == 0 ||
|
||||||
|
strncmp(opts.connection, "mqtts://", 7) == 0 ||
|
||||||
|
strncmp(opts.connection, "wss://", 6) == 0))
|
||||||
|
{
|
||||||
|
if (opts.insecure)
|
||||||
|
ssl_opts.verify = 0;
|
||||||
|
else
|
||||||
|
ssl_opts.verify = 1;
|
||||||
|
ssl_opts.CApath = opts.capath;
|
||||||
|
ssl_opts.keyStore = opts.cert;
|
||||||
|
ssl_opts.trustStore = opts.cafile;
|
||||||
|
ssl_opts.privateKey = opts.key;
|
||||||
|
ssl_opts.privateKeyPassword = opts.keypass;
|
||||||
|
ssl_opts.enabledCipherSuites = opts.ciphers;
|
||||||
|
ssl_opts.ssl_error_cb = onSSLError;
|
||||||
|
ssl_opts.ssl_error_context = client;
|
||||||
|
ssl_opts.ssl_psk_cb = onPSKAuth;
|
||||||
|
ssl_opts.ssl_psk_context = &opts;
|
||||||
|
conn_opts.ssl = &ssl_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = 0;
|
||||||
|
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to start connect, return code %s\n", MQTTAsync_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int mypublish(MQTTAsync client, int datalen, char* data)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Publishing data of length %d\n", datalen);
|
||||||
|
|
||||||
|
rc = MQTTAsync_send(client, opts.topic, datalen, data, opts.qos, opts.retained, &pub_opts);
|
||||||
|
if (opts.verbose && rc != MQTTASYNC_SUCCESS && !opts.quiet)
|
||||||
|
fprintf(stderr, "Error from MQTTAsync_send: %s\n", MQTTAsync_strerror(rc));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void trace_callback(enum MQTTASYNC_TRACE_LEVELS level, char* message)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Trace : %d, %s\n", level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
|
||||||
|
MQTTAsync_createOptions create_opts = MQTTAsync_createOptions_initializer;
|
||||||
|
MQTTAsync client;
|
||||||
|
char* buffer = NULL;
|
||||||
|
char* url = NULL;
|
||||||
|
int url_allocated = 0;
|
||||||
|
int rc = 0;
|
||||||
|
const char* version = NULL;
|
||||||
|
const char* program_name = "paho_c_pub";
|
||||||
|
MQTTAsync_nameValue* infos = MQTTAsync_getVersionInfo();
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
struct sigaction sa;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
|
||||||
|
|
||||||
|
if (getopts(argc, argv, &opts) != 0)
|
||||||
|
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
|
||||||
|
|
||||||
|
if (opts.connection)
|
||||||
|
url = opts.connection;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = malloc(100);
|
||||||
|
url_allocated = 1;
|
||||||
|
sprintf(url, "%s:%s", opts.host, opts.port);
|
||||||
|
}
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("URL is %s\n", url);
|
||||||
|
|
||||||
|
if (opts.tracelevel > 0)
|
||||||
|
{
|
||||||
|
MQTTAsync_setTraceCallback(trace_callback);
|
||||||
|
MQTTAsync_setTraceLevel(opts.tracelevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_opts.sendWhileDisconnected = 1;
|
||||||
|
if (opts.MQTTVersion >= MQTTVERSION_5)
|
||||||
|
create_opts.MQTTVersion = MQTTVERSION_5;
|
||||||
|
rc = MQTTAsync_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE, NULL, &create_opts);
|
||||||
|
if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to create client, return code: %s\n", MQTTAsync_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
signal(SIGINT, cfinish);
|
||||||
|
signal(SIGTERM, cfinish);
|
||||||
|
#else
|
||||||
|
memset(&sa, 0, sizeof(struct sigaction));
|
||||||
|
sa.sa_handler = cfinish;
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
|
||||||
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = MQTTAsync_setCallbacks(client, client, NULL, messageArrived, NULL);
|
||||||
|
if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to set callbacks, return code: %s\n", MQTTAsync_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.MQTTVersion >= MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
pub_opts.onSuccess5 = onPublish5;
|
||||||
|
pub_opts.onFailure5 = onPublishFailure5;
|
||||||
|
|
||||||
|
if (opts.message_expiry > 0)
|
||||||
|
{
|
||||||
|
property.identifier = MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL;
|
||||||
|
property.value.integer4 = opts.message_expiry;
|
||||||
|
MQTTProperties_add(&props, &property);
|
||||||
|
}
|
||||||
|
if (opts.user_property.name)
|
||||||
|
{
|
||||||
|
property.identifier = MQTTPROPERTY_CODE_USER_PROPERTY;
|
||||||
|
property.value.data.data = opts.user_property.name;
|
||||||
|
property.value.data.len = (int)strlen(opts.user_property.name);
|
||||||
|
property.value.value.data = opts.user_property.value;
|
||||||
|
property.value.value.len = (int)strlen(opts.user_property.value);
|
||||||
|
MQTTProperties_add(&props, &property);
|
||||||
|
}
|
||||||
|
pub_opts.properties = props;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pub_opts.onSuccess = onPublish;
|
||||||
|
pub_opts.onFailure = onPublishFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
myconnect(client);
|
||||||
|
|
||||||
|
while (!toStop)
|
||||||
|
{
|
||||||
|
int data_len = 0;
|
||||||
|
int delim_len = 0;
|
||||||
|
|
||||||
|
if (opts.stdin_lines)
|
||||||
|
{
|
||||||
|
buffer = malloc(opts.maxdatalen);
|
||||||
|
|
||||||
|
delim_len = (int)strlen(opts.delimiter);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buffer[data_len++] = getchar();
|
||||||
|
if (data_len > delim_len)
|
||||||
|
{
|
||||||
|
if (strncmp(opts.delimiter, &buffer[data_len - delim_len], delim_len) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (data_len < opts.maxdatalen);
|
||||||
|
|
||||||
|
rc = mypublish(client, data_len, buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mysleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.message == 0 && opts.null_message == 0 && opts.filename == 0)
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
if (opts.MQTTVersion >= MQTTVERSION_5)
|
||||||
|
disc_opts.onSuccess5 = onDisconnect5;
|
||||||
|
else
|
||||||
|
disc_opts.onSuccess = onDisconnect;
|
||||||
|
if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to start disconnect, return code: %s\n", MQTTAsync_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!disconnected)
|
||||||
|
mysleep(100);
|
||||||
|
|
||||||
|
MQTTAsync_destroy(&client);
|
||||||
|
|
||||||
|
if (url_allocated)
|
||||||
|
free(url);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
351
thirdparty/paho_mqtt/samples/paho_c_sub.c
vendored
Normal file
351
thirdparty/paho_mqtt/samples/paho_c_sub.c
vendored
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs and others
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
* Ian Craggs - fix for bug 413429 - connectionLost not called
|
||||||
|
* Guilherme Maciel Ferreira - add keep alive option
|
||||||
|
* Ian Craggs - add full capability
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "MQTTAsync.h"
|
||||||
|
#include "MQTTClientPersistence.h"
|
||||||
|
#include "pubsub_opts.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#define sleep Sleep
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WRS_KERNEL)
|
||||||
|
#include <OsWrapper.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
volatile int finished = 0;
|
||||||
|
int subscribed = 0;
|
||||||
|
int disconnected = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void mysleep(int ms)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
Sleep(ms);
|
||||||
|
#else
|
||||||
|
usleep(ms * 1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cfinish(int sig)
|
||||||
|
{
|
||||||
|
signal(SIGINT, NULL);
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct pubsub_opts opts =
|
||||||
|
{
|
||||||
|
0, 0, 0, 0, "\n", 100, /* debug/app options */
|
||||||
|
NULL, NULL, 1, 0, 0, /* message options */
|
||||||
|
MQTTVERSION_DEFAULT, NULL, "paho-c-sub", 0, 0, NULL, NULL, "localhost", "1883", NULL, 10, /* MQTT options */
|
||||||
|
NULL, NULL, 0, 0, /* will options */
|
||||||
|
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* TLS options */
|
||||||
|
0, {NULL, NULL}, /* MQTT V5 options */
|
||||||
|
NULL, NULL, /* HTTP and HTTPS proxies */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int messageArrived(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
|
||||||
|
{
|
||||||
|
size_t delimlen = 0;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("%d %s\t", message->payloadlen, topicName);
|
||||||
|
if (opts.delimiter)
|
||||||
|
delimlen = strlen(opts.delimiter);
|
||||||
|
if (opts.delimiter == NULL || (message->payloadlen > delimlen &&
|
||||||
|
strncmp(opts.delimiter, &((char*)message->payload)[message->payloadlen - delimlen], delimlen) == 0))
|
||||||
|
printf("%.*s", message->payloadlen, (char*)message->payload);
|
||||||
|
else
|
||||||
|
printf("%.*s%s", message->payloadlen, (char*)message->payload, opts.delimiter);
|
||||||
|
if (message->struct_version == 1 && opts.verbose)
|
||||||
|
logProperties(&message->properties);
|
||||||
|
fflush(stdout);
|
||||||
|
MQTTAsync_freeMessage(&message);
|
||||||
|
MQTTAsync_free(topicName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onDisconnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
disconnected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onSubscribe5(void* context, MQTTAsync_successData5* response)
|
||||||
|
{
|
||||||
|
subscribed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSubscribe(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
subscribed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onSubscribeFailure5(void* context, MQTTAsync_failureData5* response)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Subscribe failed, rc %s reason code %s\n",
|
||||||
|
MQTTAsync_strerror(response->code),
|
||||||
|
MQTTReasonCode_toString(response->reasonCode));
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Subscribe failed, rc %s\n",
|
||||||
|
MQTTAsync_strerror(response->code));
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnectFailure5(void* context, MQTTAsync_failureData5* response)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Connect failed, rc %s reason code %s\n",
|
||||||
|
MQTTAsync_strerror(response->code),
|
||||||
|
MQTTReasonCode_toString(response->reasonCode));
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnectFailure(void* context, MQTTAsync_failureData* response)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Connect failed, rc %s\n", response ? MQTTAsync_strerror(response->code) : "none");
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnect5(void* context, MQTTAsync_successData5* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_callOptions copts = MQTTAsync_callOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Subscribing to topic %s with client %s at QoS %d\n", opts.topic, opts.clientid, opts.qos);
|
||||||
|
|
||||||
|
copts.onSuccess5 = onSubscribe5;
|
||||||
|
copts.onFailure5 = onSubscribeFailure5;
|
||||||
|
copts.context = client;
|
||||||
|
if ((rc = MQTTAsync_subscribe(client, opts.topic, opts.qos, &copts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to start subscribe, return code %s\n", MQTTAsync_strerror(rc));
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onConnect(void* context, MQTTAsync_successData* response)
|
||||||
|
{
|
||||||
|
MQTTAsync client = (MQTTAsync)context;
|
||||||
|
MQTTAsync_responseOptions ropts = MQTTAsync_responseOptions_initializer;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Subscribing to topic %s with client %s at QoS %d\n", opts.topic, opts.clientid, opts.qos);
|
||||||
|
|
||||||
|
ropts.onSuccess = onSubscribe;
|
||||||
|
ropts.onFailure = onSubscribeFailure;
|
||||||
|
ropts.context = client;
|
||||||
|
if ((rc = MQTTAsync_subscribe(client, opts.topic, opts.qos, &ropts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to start subscribe, return code %s\n", MQTTAsync_strerror(rc));
|
||||||
|
finished = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||||
|
|
||||||
|
|
||||||
|
void trace_callback(enum MQTTASYNC_TRACE_LEVELS level, char* message)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Trace : %d, %s\n", level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
MQTTAsync client;
|
||||||
|
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
|
||||||
|
MQTTAsync_createOptions create_opts = MQTTAsync_createOptions_initializer;
|
||||||
|
MQTTAsync_willOptions will_opts = MQTTAsync_willOptions_initializer;
|
||||||
|
MQTTAsync_SSLOptions ssl_opts = MQTTAsync_SSLOptions_initializer;
|
||||||
|
int rc = 0;
|
||||||
|
char* url = NULL;
|
||||||
|
const char* version = NULL;
|
||||||
|
const char* program_name = "paho_c_sub";
|
||||||
|
MQTTAsync_nameValue* infos = MQTTAsync_getVersionInfo();
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
struct sigaction sa;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
|
||||||
|
|
||||||
|
if (getopts(argc, argv, &opts) != 0)
|
||||||
|
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
|
||||||
|
|
||||||
|
if (strchr(opts.topic, '#') || strchr(opts.topic, '+'))
|
||||||
|
opts.verbose = 1;
|
||||||
|
|
||||||
|
if (opts.connection)
|
||||||
|
url = opts.connection;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = malloc(100);
|
||||||
|
sprintf(url, "%s:%s", opts.host, opts.port);
|
||||||
|
}
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("URL is %s\n", url);
|
||||||
|
|
||||||
|
if (opts.tracelevel > 0)
|
||||||
|
{
|
||||||
|
MQTTAsync_setTraceCallback(trace_callback);
|
||||||
|
MQTTAsync_setTraceLevel(opts.tracelevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.MQTTVersion >= MQTTVERSION_5)
|
||||||
|
create_opts.MQTTVersion = MQTTVERSION_5;
|
||||||
|
rc = MQTTAsync_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE,
|
||||||
|
NULL, &create_opts);
|
||||||
|
if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to create client, return code: %s\n", MQTTAsync_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = MQTTAsync_setCallbacks(client, client, NULL, messageArrived, NULL);
|
||||||
|
if (rc != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to set callbacks, return code: %s\n", MQTTAsync_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
signal(SIGINT, cfinish);
|
||||||
|
signal(SIGTERM, cfinish);
|
||||||
|
#else
|
||||||
|
memset(&sa, 0, sizeof(struct sigaction));
|
||||||
|
sa.sa_handler = cfinish;
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
|
||||||
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTAsync_connectOptions conn_opts5 = MQTTAsync_connectOptions_initializer5;
|
||||||
|
conn_opts = conn_opts5;
|
||||||
|
conn_opts.onSuccess5 = onConnect5;
|
||||||
|
conn_opts.onFailure5 = onConnectFailure5;
|
||||||
|
conn_opts.cleanstart = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
conn_opts.onSuccess = onConnect;
|
||||||
|
conn_opts.onFailure = onConnectFailure;
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
}
|
||||||
|
conn_opts.keepAliveInterval = opts.keepalive;
|
||||||
|
conn_opts.username = opts.username;
|
||||||
|
conn_opts.password = opts.password;
|
||||||
|
conn_opts.MQTTVersion = opts.MQTTVersion;
|
||||||
|
conn_opts.context = client;
|
||||||
|
conn_opts.automaticReconnect = 1;
|
||||||
|
conn_opts.httpProxy = opts.http_proxy;
|
||||||
|
conn_opts.httpsProxy = opts.https_proxy;
|
||||||
|
|
||||||
|
if (opts.will_topic) /* will options */
|
||||||
|
{
|
||||||
|
will_opts.message = opts.will_payload;
|
||||||
|
will_opts.topicName = opts.will_topic;
|
||||||
|
will_opts.qos = opts.will_qos;
|
||||||
|
will_opts.retained = opts.will_retain;
|
||||||
|
conn_opts.will = &will_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.connection && (strncmp(opts.connection, "ssl://", 6) == 0 ||
|
||||||
|
strncmp(opts.connection, "tls://", 6) == 0||
|
||||||
|
strncmp(opts.connection, "mqtts://", 7) == 0 ||
|
||||||
|
strncmp(opts.connection, "wss://", 6) == 0))
|
||||||
|
{
|
||||||
|
ssl_opts.verify = (opts.insecure) ? 0 : 1;
|
||||||
|
ssl_opts.CApath = opts.capath;
|
||||||
|
ssl_opts.keyStore = opts.cert;
|
||||||
|
ssl_opts.trustStore = opts.cafile;
|
||||||
|
ssl_opts.privateKey = opts.key;
|
||||||
|
ssl_opts.privateKeyPassword = opts.keypass;
|
||||||
|
ssl_opts.enabledCipherSuites = opts.ciphers;
|
||||||
|
conn_opts.ssl = &ssl_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to start connect, return code %s\n", MQTTAsync_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!subscribed)
|
||||||
|
mysleep(100);
|
||||||
|
|
||||||
|
if (finished)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
while (!finished)
|
||||||
|
mysleep(100);
|
||||||
|
|
||||||
|
disc_opts.onSuccess = onDisconnect;
|
||||||
|
if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to start disconnect, return code: %s\n", MQTTAsync_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!disconnected)
|
||||||
|
mysleep(100);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MQTTAsync_destroy(&client);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
327
thirdparty/paho_mqtt/samples/paho_cs_pub.c
vendored
Normal file
327
thirdparty/paho_mqtt/samples/paho_cs_pub.c
vendored
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
* Ian Craggs - add full capability
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "MQTTClient.h"
|
||||||
|
#include "MQTTClientPersistence.h"
|
||||||
|
#include "pubsub_opts.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define sleep Sleep
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
volatile int toStop = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void cfinish(int sig)
|
||||||
|
{
|
||||||
|
signal(SIGINT, NULL);
|
||||||
|
toStop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct pubsub_opts opts =
|
||||||
|
{
|
||||||
|
1, 0, 0, 0, "\n", 100, /* debug/app options */
|
||||||
|
NULL, NULL, 1, 0, 0, /* message options */
|
||||||
|
MQTTVERSION_DEFAULT, NULL, "paho-cs-pub", 0, 0, NULL, NULL, "localhost", "1883", NULL, 10, /* MQTT options */
|
||||||
|
NULL, NULL, 0, 0, /* will options */
|
||||||
|
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* TLS options */
|
||||||
|
0, {NULL, NULL}, /* MQTT V5 options */
|
||||||
|
NULL, NULL, /* HTTP and HTTPS proxies */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int myconnect(MQTTClient client)
|
||||||
|
{
|
||||||
|
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
|
||||||
|
MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;
|
||||||
|
MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Connecting\n");
|
||||||
|
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTClient_connectOptions conn_opts5 = MQTTClient_connectOptions_initializer5;
|
||||||
|
conn_opts = conn_opts5;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_opts.keepAliveInterval = opts.keepalive;
|
||||||
|
conn_opts.username = opts.username;
|
||||||
|
conn_opts.password = opts.password;
|
||||||
|
conn_opts.MQTTVersion = opts.MQTTVersion;
|
||||||
|
conn_opts.httpProxy = opts.http_proxy;
|
||||||
|
conn_opts.httpsProxy = opts.https_proxy;
|
||||||
|
|
||||||
|
if (opts.will_topic) /* will options */
|
||||||
|
{
|
||||||
|
will_opts.message = opts.will_payload;
|
||||||
|
will_opts.topicName = opts.will_topic;
|
||||||
|
will_opts.qos = opts.will_qos;
|
||||||
|
will_opts.retained = opts.will_retain;
|
||||||
|
conn_opts.will = &will_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.connection && (strncmp(opts.connection, "ssl://", 6) == 0 ||
|
||||||
|
strncmp(opts.connection, "tls://", 6) == 0 ||
|
||||||
|
strncmp(opts.connection, "mqtts://", 7) == 0 ||
|
||||||
|
strncmp(opts.connection, "wss://", 6) == 0))
|
||||||
|
{
|
||||||
|
if (opts.insecure)
|
||||||
|
ssl_opts.verify = 0;
|
||||||
|
else
|
||||||
|
ssl_opts.verify = 1;
|
||||||
|
ssl_opts.CApath = opts.capath;
|
||||||
|
ssl_opts.keyStore = opts.cert;
|
||||||
|
ssl_opts.trustStore = opts.cafile;
|
||||||
|
ssl_opts.privateKey = opts.key;
|
||||||
|
ssl_opts.privateKeyPassword = opts.keypass;
|
||||||
|
ssl_opts.enabledCipherSuites = opts.ciphers;
|
||||||
|
conn_opts.ssl = &ssl_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTProperties props = MQTTProperties_initializer;
|
||||||
|
MQTTProperties willProps = MQTTProperties_initializer;
|
||||||
|
MQTTResponse response = MQTTResponse_initializer;
|
||||||
|
|
||||||
|
conn_opts.cleanstart = 1;
|
||||||
|
response = MQTTClient_connect5(client, &conn_opts, &props, &willProps);
|
||||||
|
rc = response.reasonCode;
|
||||||
|
MQTTResponse_free(response);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
rc = MQTTClient_connect(client, &conn_opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.verbose && rc == MQTTCLIENT_SUCCESS)
|
||||||
|
printf("Connected\n");
|
||||||
|
else if (rc != MQTTCLIENT_SUCCESS && !opts.quiet)
|
||||||
|
fprintf(stderr, "Connect failed return code: %s\n", MQTTClient_strerror(rc));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int messageArrived(void* context, char* topicName, int topicLen, MQTTClient_message* m)
|
||||||
|
{
|
||||||
|
/* not expecting any messages */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void connectionLost(void* context, char* reason)
|
||||||
|
{
|
||||||
|
MQTTClient client = (MQTTClient)context;
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("ConnectionLost, reconnecting\n");
|
||||||
|
myconnect(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void trace_callback(enum MQTTCLIENT_TRACE_LEVELS level, char* message)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Trace : %d, %s\n", level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
MQTTClient client;
|
||||||
|
MQTTProperties pub_props = MQTTProperties_initializer;
|
||||||
|
MQTTClient_createOptions createOpts = MQTTClient_createOptions_initializer;
|
||||||
|
MQTTClient_deliveryToken last_token;
|
||||||
|
char* buffer = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
char* url;
|
||||||
|
const char* version = NULL;
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
struct sigaction sa;
|
||||||
|
#endif
|
||||||
|
const char* program_name = "paho_cs_pub";
|
||||||
|
MQTTClient_nameValue* infos = MQTTClient_getVersionInfo();
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
|
||||||
|
|
||||||
|
if (getopts(argc, argv, &opts) != 0)
|
||||||
|
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
|
||||||
|
|
||||||
|
if (opts.connection)
|
||||||
|
url = opts.connection;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = malloc(100);
|
||||||
|
sprintf(url, "%s:%s", opts.host, opts.port);
|
||||||
|
}
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("URL is %s\n", url);
|
||||||
|
|
||||||
|
if (opts.tracelevel > 0)
|
||||||
|
{
|
||||||
|
MQTTClient_setTraceCallback(trace_callback);
|
||||||
|
MQTTClient_setTraceLevel(opts.tracelevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.MQTTVersion >= MQTTVERSION_5)
|
||||||
|
createOpts.MQTTVersion = MQTTVERSION_5;
|
||||||
|
rc = MQTTClient_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE,
|
||||||
|
NULL, &createOpts);
|
||||||
|
if (rc != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to create client, return code: %s\n", MQTTClient_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
signal(SIGINT, cfinish);
|
||||||
|
signal(SIGTERM, cfinish);
|
||||||
|
#else
|
||||||
|
memset(&sa, 0, sizeof(struct sigaction));
|
||||||
|
sa.sa_handler = cfinish;
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
|
||||||
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = MQTTClient_setCallbacks(client, client, connectionLost, messageArrived, NULL);
|
||||||
|
if (rc != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to set callbacks, return code: %s\n", MQTTClient_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myconnect(client) != MQTTCLIENT_SUCCESS)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (opts.MQTTVersion >= MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTProperty property;
|
||||||
|
|
||||||
|
if (opts.message_expiry > 0)
|
||||||
|
{
|
||||||
|
property.identifier = MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL;
|
||||||
|
property.value.integer4 = opts.message_expiry;
|
||||||
|
MQTTProperties_add(&pub_props, &property);
|
||||||
|
}
|
||||||
|
if (opts.user_property.name)
|
||||||
|
{
|
||||||
|
property.identifier = MQTTPROPERTY_CODE_USER_PROPERTY;
|
||||||
|
property.value.data.data = opts.user_property.name;
|
||||||
|
property.value.data.len = (int)strlen(opts.user_property.name);
|
||||||
|
property.value.value.data = opts.user_property.value;
|
||||||
|
property.value.value.len = (int)strlen(opts.user_property.value);
|
||||||
|
MQTTProperties_add(&pub_props, &property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!toStop)
|
||||||
|
{
|
||||||
|
int data_len = 0;
|
||||||
|
int delim_len = 0;
|
||||||
|
|
||||||
|
if (opts.stdin_lines)
|
||||||
|
{
|
||||||
|
buffer = malloc(opts.maxdatalen);
|
||||||
|
|
||||||
|
delim_len = (int)strlen(opts.delimiter);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int c = getchar();
|
||||||
|
|
||||||
|
if (c < 0)
|
||||||
|
goto exit;
|
||||||
|
buffer[data_len++] = c;
|
||||||
|
if (data_len > delim_len)
|
||||||
|
{
|
||||||
|
if (strncmp(opts.delimiter, &buffer[data_len - delim_len], delim_len) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (data_len < opts.maxdatalen);
|
||||||
|
}
|
||||||
|
else if (opts.message)
|
||||||
|
{
|
||||||
|
buffer = opts.message;
|
||||||
|
data_len = (int)strlen(opts.message);
|
||||||
|
}
|
||||||
|
else if (opts.filename)
|
||||||
|
{
|
||||||
|
buffer = readfile(&data_len, &opts);
|
||||||
|
if (buffer == NULL)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (opts.verbose)
|
||||||
|
fprintf(stderr, "Publishing data of length %d\n", data_len);
|
||||||
|
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTResponse response = MQTTResponse_initializer;
|
||||||
|
|
||||||
|
response = MQTTClient_publish5(client, opts.topic, data_len, buffer, opts.qos, opts.retained, &pub_props, &last_token);
|
||||||
|
rc = response.reasonCode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = MQTTClient_publish(client, opts.topic, data_len, buffer, opts.qos, opts.retained, &last_token);
|
||||||
|
if (opts.stdin_lines == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
myconnect(client);
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTResponse response = MQTTResponse_initializer;
|
||||||
|
|
||||||
|
response = MQTTClient_publish5(client, opts.topic, data_len, buffer, opts.qos, opts.retained, &pub_props, &last_token);
|
||||||
|
rc = response.reasonCode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = MQTTClient_publish(client, opts.topic, data_len, buffer, opts.qos, opts.retained, &last_token);
|
||||||
|
}
|
||||||
|
if (opts.qos > 0)
|
||||||
|
MQTTClient_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = MQTTClient_waitForCompletion(client, last_token, 5000);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (opts.filename || opts.stdin_lines)
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
rc = MQTTClient_disconnect5(client, 0, MQTTREASONCODE_SUCCESS, NULL);
|
||||||
|
else
|
||||||
|
rc = MQTTClient_disconnect(client, 0);
|
||||||
|
|
||||||
|
MQTTClient_destroy(&client);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
257
thirdparty/paho_mqtt/samples/paho_cs_sub.c
vendored
Normal file
257
thirdparty/paho_mqtt/samples/paho_cs_sub.c
vendored
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs and others
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
* Ian Craggs - change delimiter option from char to string
|
||||||
|
* Guilherme Maciel Ferreira - add keep alive option
|
||||||
|
* Ian Craggs - add full capability
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "MQTTClient.h"
|
||||||
|
#include "MQTTClientPersistence.h"
|
||||||
|
#include "pubsub_opts.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define sleep Sleep
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
volatile int toStop = 0;
|
||||||
|
|
||||||
|
|
||||||
|
struct pubsub_opts opts =
|
||||||
|
{
|
||||||
|
0, 0, 0, 0, "\n", 100, /* debug/app options */
|
||||||
|
NULL, NULL, 1, 0, 0, /* message options */
|
||||||
|
MQTTVERSION_DEFAULT, NULL, "paho-cs-sub", 0, 0, NULL, NULL, "localhost", "1883", NULL, 10, /* MQTT options */
|
||||||
|
NULL, NULL, 0, 0, /* will options */
|
||||||
|
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* TLS options */
|
||||||
|
0, {NULL, NULL}, /* MQTT V5 options */
|
||||||
|
NULL, NULL, /* HTTP and HTTPS proxies */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int myconnect(MQTTClient client)
|
||||||
|
{
|
||||||
|
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
|
||||||
|
MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;
|
||||||
|
MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("Connecting\n");
|
||||||
|
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTClient_connectOptions conn_opts5 = MQTTClient_connectOptions_initializer5;
|
||||||
|
conn_opts = conn_opts5;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_opts.keepAliveInterval = opts.keepalive;
|
||||||
|
conn_opts.username = opts.username;
|
||||||
|
conn_opts.password = opts.password;
|
||||||
|
conn_opts.MQTTVersion = opts.MQTTVersion;
|
||||||
|
conn_opts.httpProxy = opts.http_proxy;
|
||||||
|
conn_opts.httpsProxy = opts.https_proxy;
|
||||||
|
|
||||||
|
if (opts.will_topic) /* will options */
|
||||||
|
{
|
||||||
|
will_opts.message = opts.will_payload;
|
||||||
|
will_opts.topicName = opts.will_topic;
|
||||||
|
will_opts.qos = opts.will_qos;
|
||||||
|
will_opts.retained = opts.will_retain;
|
||||||
|
conn_opts.will = &will_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.connection && (strncmp(opts.connection, "ssl://", 6) == 0 ||
|
||||||
|
strncmp(opts.connection, "tls://", 6) == 0 ||
|
||||||
|
strncmp(opts.connection, "mqtts://", 7) == 0 ||
|
||||||
|
strncmp(opts.connection, "wss://", 6) == 0))
|
||||||
|
{
|
||||||
|
if (opts.insecure)
|
||||||
|
ssl_opts.verify = 0;
|
||||||
|
else
|
||||||
|
ssl_opts.verify = 1;
|
||||||
|
ssl_opts.CApath = opts.capath;
|
||||||
|
ssl_opts.keyStore = opts.cert;
|
||||||
|
ssl_opts.trustStore = opts.cafile;
|
||||||
|
ssl_opts.privateKey = opts.key;
|
||||||
|
ssl_opts.privateKeyPassword = opts.keypass;
|
||||||
|
ssl_opts.enabledCipherSuites = opts.ciphers;
|
||||||
|
conn_opts.ssl = &ssl_opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.MQTTVersion == MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTProperties props = MQTTProperties_initializer;
|
||||||
|
MQTTProperties willProps = MQTTProperties_initializer;
|
||||||
|
MQTTResponse response = MQTTResponse_initializer;
|
||||||
|
|
||||||
|
conn_opts.cleanstart = 1;
|
||||||
|
response = MQTTClient_connect5(client, &conn_opts, &props, &willProps);
|
||||||
|
rc = response.reasonCode;
|
||||||
|
MQTTResponse_free(response);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
conn_opts.cleansession = 1;
|
||||||
|
rc = MQTTClient_connect(client, &conn_opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.verbose && rc == MQTTCLIENT_SUCCESS)
|
||||||
|
fprintf(stderr, "Connected\n");
|
||||||
|
else if (rc != MQTTCLIENT_SUCCESS && !opts.quiet)
|
||||||
|
fprintf(stderr, "Connect failed return code: %s\n", MQTTClient_strerror(rc));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cfinish(int sig)
|
||||||
|
{
|
||||||
|
signal(SIGINT, NULL);
|
||||||
|
toStop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void trace_callback(enum MQTTCLIENT_TRACE_LEVELS level, char* message)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Trace : %d, %s\n", level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
MQTTClient client;
|
||||||
|
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
|
||||||
|
MQTTClient_createOptions createOpts = MQTTClient_createOptions_initializer;
|
||||||
|
int rc = 0;
|
||||||
|
char* url;
|
||||||
|
const char* version = NULL;
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
struct sigaction sa;
|
||||||
|
#endif
|
||||||
|
const char* program_name = "paho_cs_sub";
|
||||||
|
MQTTClient_nameValue* infos = MQTTClient_getVersionInfo();
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
|
||||||
|
|
||||||
|
if (getopts(argc, argv, &opts) != 0)
|
||||||
|
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
|
||||||
|
|
||||||
|
if (strchr(opts.topic, '#') || strchr(opts.topic, '+'))
|
||||||
|
opts.verbose = 1;
|
||||||
|
|
||||||
|
if (opts.connection)
|
||||||
|
url = opts.connection;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = malloc(100);
|
||||||
|
sprintf(url, "%s:%s", opts.host, opts.port);
|
||||||
|
}
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("URL is %s\n", url);
|
||||||
|
|
||||||
|
if (opts.tracelevel > 0)
|
||||||
|
{
|
||||||
|
MQTTClient_setTraceCallback(trace_callback);
|
||||||
|
MQTTClient_setTraceLevel(opts.tracelevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.MQTTVersion >= MQTTVERSION_5)
|
||||||
|
createOpts.MQTTVersion = MQTTVERSION_5;
|
||||||
|
rc = MQTTClient_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE,
|
||||||
|
NULL, &createOpts);
|
||||||
|
if (rc != MQTTCLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Failed to create client, return code: %s\n", MQTTClient_strerror(rc));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
signal(SIGINT, cfinish);
|
||||||
|
signal(SIGTERM, cfinish);
|
||||||
|
#else
|
||||||
|
memset(&sa, 0, sizeof(struct sigaction));
|
||||||
|
sa.sa_handler = cfinish;
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
|
||||||
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (myconnect(client) != MQTTCLIENT_SUCCESS)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (opts.MQTTVersion >= MQTTVERSION_5)
|
||||||
|
{
|
||||||
|
MQTTResponse response = MQTTClient_subscribe5(client, opts.topic, opts.qos, NULL, NULL);
|
||||||
|
rc = response.reasonCode;
|
||||||
|
MQTTResponse_free(response);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = MQTTClient_subscribe(client, opts.topic, opts.qos);
|
||||||
|
if (rc != MQTTCLIENT_SUCCESS && rc != opts.qos)
|
||||||
|
{
|
||||||
|
if (!opts.quiet)
|
||||||
|
fprintf(stderr, "Error %d subscribing to topic %s\n", rc, opts.topic);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!toStop)
|
||||||
|
{
|
||||||
|
char* topicName = NULL;
|
||||||
|
int topicLen;
|
||||||
|
MQTTClient_message* message = NULL;
|
||||||
|
|
||||||
|
rc = MQTTClient_receive(client, &topicName, &topicLen, &message, 1000);
|
||||||
|
if (rc == MQTTCLIENT_DISCONNECTED)
|
||||||
|
myconnect(client);
|
||||||
|
else if (message)
|
||||||
|
{
|
||||||
|
size_t delimlen = 0;
|
||||||
|
|
||||||
|
if (opts.verbose)
|
||||||
|
printf("%s\t", topicName);
|
||||||
|
if (opts.delimiter)
|
||||||
|
delimlen = strlen(opts.delimiter);
|
||||||
|
if (opts.delimiter == NULL || (message->payloadlen > delimlen &&
|
||||||
|
strncmp(opts.delimiter, &((char*)message->payload)[message->payloadlen - delimlen], delimlen) == 0))
|
||||||
|
printf("%.*s", message->payloadlen, (char*)message->payload);
|
||||||
|
else
|
||||||
|
printf("%.*s%s", message->payloadlen, (char*)message->payload, opts.delimiter);
|
||||||
|
if (message->struct_version == 1 && opts.verbose)
|
||||||
|
logProperties(&message->properties);
|
||||||
|
fflush(stdout);
|
||||||
|
MQTTClient_freeMessage(&message);
|
||||||
|
MQTTClient_free(topicName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MQTTClient_disconnect(client, 0);
|
||||||
|
|
||||||
|
MQTTClient_destroy(&client);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
521
thirdparty/paho_mqtt/samples/pubsub_opts.c
vendored
Normal file
521
thirdparty/paho_mqtt/samples/pubsub_opts.c
vendored
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2012, 2018 IBM Corp.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v2.0
|
||||||
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||||
|
*
|
||||||
|
* The Eclipse Public License is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
* and the Eclipse Distribution License is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ian Craggs - initial contribution
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "pubsub_opts.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
int printVersionInfo(pubsub_opts_nameValue* info)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
printf("\nLibrary information:\n");
|
||||||
|
while (info->name)
|
||||||
|
{
|
||||||
|
printf("%s: %s\n", info->name, info->value);
|
||||||
|
info++;
|
||||||
|
rc = 1; /* at least one value printed */
|
||||||
|
}
|
||||||
|
if (rc == 1)
|
||||||
|
printf("\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void usage(struct pubsub_opts* opts, pubsub_opts_nameValue* name_values, const char* program_name)
|
||||||
|
{
|
||||||
|
printf("Eclipse Paho MQTT C %s\n", opts->publisher ? "publisher" : "subscriber");
|
||||||
|
printVersionInfo(name_values);
|
||||||
|
|
||||||
|
printf("Usage: %s [topicname] [-t topic] [-c connection] [-h host] [-p port]\n"
|
||||||
|
" [-q qos] [-i clientid] [-u username] [-P password] [-k keepalive_timeout]\n"
|
||||||
|
, program_name);
|
||||||
|
printf(" [-V MQTT-version] [--quiet] [--trace trace-level]\n");
|
||||||
|
if (opts->publisher)
|
||||||
|
{
|
||||||
|
printf(" [-r] [-n] [-m message] [-f filename]\n");
|
||||||
|
printf(" [--maxdatalen len] [--message-expiry seconds] [--user-property name value]\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf(" [-R] [--no-delimiter]\n");
|
||||||
|
printf(" [--will-topic topic] [--will-payload message] [--will-qos qos] [--will-retain]\n");
|
||||||
|
printf(" [--cafile filename] [--capath dirname] [--cert filename] [--key filename]\n"
|
||||||
|
" [--keypass string] [--ciphers string] [--insecure]");
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"\n\n -t (--topic) : MQTT topic to %s to\n"
|
||||||
|
" -c (--connection) : connection string, overrides host/port e.g wss://hostname:port/ws. Use this option\n"
|
||||||
|
" rather than host/port to connect with TLS and/or web sockets. No default.\n"
|
||||||
|
" -h (--host) : host to connect to. Default is %s.\n"
|
||||||
|
" -p (--port) : network port to connect to. Default is %s.\n"
|
||||||
|
" -q (--qos) : MQTT QoS to %s with (0, 1 or 2). Default is %d.\n"
|
||||||
|
" -V (--MQTTversion) : MQTT version (31, 311, or 5). Default is 311.\n"
|
||||||
|
" --quiet : do not print error messages.\n"
|
||||||
|
" --trace : print internal trace (\"error\", \"min\", \"max\" or \"protocol\").\n",
|
||||||
|
opts->publisher ? "publish" : "subscribe", opts->host, opts->port,
|
||||||
|
opts->publisher ? "publish" : "subscribe", opts->qos);
|
||||||
|
|
||||||
|
if (opts->publisher)
|
||||||
|
{
|
||||||
|
printf(" -r (--retained) : use MQTT retain option. Default is off.\n");
|
||||||
|
printf(" -n (--null-message) : send 0-length message.\n");
|
||||||
|
printf(" -m (--message) : the payload to send.\n");
|
||||||
|
printf(" -f (--filename) : use the contents of the named file as the payload.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(
|
||||||
|
" -i (--clientid) : MQTT client id. Default is %s.\n"
|
||||||
|
" -u (--username) : MQTT username. No default.\n"
|
||||||
|
" -P (--password) : MQTT password. No default.\n"
|
||||||
|
" -k (--keepalive) : MQTT keepalive timeout value. Default is %d seconds.\n"
|
||||||
|
" --delimiter : delimiter string. Default is \\n.\n",
|
||||||
|
opts->clientid, opts->keepalive);
|
||||||
|
|
||||||
|
if (opts->publisher)
|
||||||
|
{
|
||||||
|
printf(" --maxdatalen : maximum length of data to read when publishing strings (default is %d)\n",
|
||||||
|
opts->maxdatalen);
|
||||||
|
printf(" --message-expiry : MQTT 5 only. Sets the message expiry property in seconds.\n");
|
||||||
|
printf(" --user-property : MQTT 5 only. Sets a user property.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" --no-delimiter : do not use a delimiter string between messages.\n");
|
||||||
|
printf(" -R (--no-retained) : do not print retained messages.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(
|
||||||
|
" --will-topic : will topic on connect. No default.\n"
|
||||||
|
" --will-payload : will message. If the will topic is set, but not payload, a null message will be set.\n"
|
||||||
|
" --will-retain : set the retained flag on the will message. The default is off.\n"
|
||||||
|
" --will-qos : the will message QoS. The default is 0.\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
printf(
|
||||||
|
" --cafile : a filename for the TLS truststore.\n"
|
||||||
|
" --capath : a directory name containing TLS trusted server certificates.\n"
|
||||||
|
" --cert : a filename for the TLS keystore containing client certificates.\n"
|
||||||
|
" --key : client private key file.\n"
|
||||||
|
" --keypass : password for the client private key file.\n"
|
||||||
|
" --ciphers : the list of cipher suites that the client will present to the server during\n"
|
||||||
|
" the TLS handshake.\n"
|
||||||
|
" --insecure : don't check that the server certificate common name matches the hostname.\n"
|
||||||
|
" --psk : pre-shared-key in hexadecimal (no leading 0x) \n"
|
||||||
|
" --psk-identity : client identity string for TLS-PSK mode.\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
printf(
|
||||||
|
" --http-proxy : HTTP proxy string.\n"
|
||||||
|
" --https-proxy : HTTPS proxy string.\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
printf("\nSee http://eclipse.org/paho for more information about the Eclipse Paho project.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int getopts(int argc, char** argv, struct pubsub_opts* opts)
|
||||||
|
{
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
if (argv[1][0] != '-')
|
||||||
|
{
|
||||||
|
opts->topic = argv[1];
|
||||||
|
count = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count < argc)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[count], "--verbose") == 0 || strcmp(argv[count], "-v") == 0)
|
||||||
|
opts->verbose = 1;
|
||||||
|
else if (strcmp(argv[count], "--quiet") == 0)
|
||||||
|
opts->quiet = 1;
|
||||||
|
else if (strcmp(argv[count], "--qos") == 0 || strcmp(argv[count], "-q") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[count], "0") == 0)
|
||||||
|
opts->qos = 0;
|
||||||
|
else if (strcmp(argv[count], "1") == 0)
|
||||||
|
opts->qos = 1;
|
||||||
|
else if (strcmp(argv[count], "2") == 0)
|
||||||
|
opts->qos = 2;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--connection") == 0 || strcmp(argv[count], "-c") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->connection = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--host") == 0 || strcmp(argv[count], "-h") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->host = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--port") == 0 || strcmp(argv[count], "-p") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->port = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--http-proxy") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->http_proxy = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--https-proxy") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->https_proxy = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--clientid") == 0 || strcmp(argv[count], "-i") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->clientid = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--username") == 0 || strcmp(argv[count], "-u") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->username = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--password") == 0 || strcmp(argv[count], "-P") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->password = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--maxdatalen") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->maxdatalen = atoi(argv[count]);
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--delimiter") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->delimiter = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--no-delimiter") == 0)
|
||||||
|
opts->delimiter = NULL;
|
||||||
|
else if (strcmp(argv[count], "--keepalive") == 0 || strcmp(argv[count], "-k") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->keepalive = atoi(argv[count]);
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--topic") == 0 || strcmp(argv[count], "-t") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->topic = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--will-topic") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->will_topic = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--will-payload") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->will_payload = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--will-qos") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->will_qos = atoi(argv[count]);
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--will-retain") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->will_retain = 1;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--insecure") == 0)
|
||||||
|
opts->insecure = 1;
|
||||||
|
else if (strcmp(argv[count], "--capath") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->capath = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--cafile") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->cafile = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--cert") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->cert = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--key") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->key = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--keypass") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->keypass = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--ciphers") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->ciphers = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--psk") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->psk = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--psk-identity") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->psk_identity = argv[count];
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "-V") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[count], "mqttv31") == 0 || strcmp(argv[count], "31") == 0)
|
||||||
|
opts->MQTTVersion = MQTTVERSION_3_1;
|
||||||
|
else if (strcmp(argv[count], "mqttv311") == 0 || strcmp(argv[count], "311") == 0)
|
||||||
|
opts->MQTTVersion = MQTTVERSION_3_1_1;
|
||||||
|
else if (strcmp(argv[count], "mqttv5") == 0 || strcmp(argv[count], "5") == 0)
|
||||||
|
opts->MQTTVersion = MQTTVERSION_5;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--trace") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[count], "error") == 0)
|
||||||
|
opts->tracelevel = MQTTASYNC_TRACE_ERROR;
|
||||||
|
else if (strcmp(argv[count], "protocol") == 0)
|
||||||
|
opts->tracelevel = MQTTASYNC_TRACE_PROTOCOL;
|
||||||
|
else if (strcmp(argv[count], "min") == 0 || strcmp(argv[count], "on") == 0)
|
||||||
|
opts->tracelevel = MQTTASYNC_TRACE_MINIMUM;
|
||||||
|
else if (strcmp(argv[count], "max") == 0)
|
||||||
|
opts->tracelevel = MQTTASYNC_TRACE_MAXIMUM;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (opts->publisher == 0)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[count], "--no-retained") == 0 || strcmp(argv[count], "-R") == 0)
|
||||||
|
opts->retained = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unknown option %s\n", argv[count]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (opts->publisher == 1)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[count], "--retained") == 0 || strcmp(argv[count], "-r") == 0)
|
||||||
|
opts->retained = 1;
|
||||||
|
else if (strcmp(argv[count], "--user-property") == 0)
|
||||||
|
{
|
||||||
|
if (count + 2 < argc)
|
||||||
|
{
|
||||||
|
opts->user_property.name = argv[++count];
|
||||||
|
opts->user_property.value = argv[++count];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "--message-expiry") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
opts->message_expiry = atoi(argv[count]);
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "-m") == 0 || strcmp(argv[count], "--message") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
{
|
||||||
|
opts->stdin_lines = 0;
|
||||||
|
opts->message = argv[count];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "-f") == 0 || strcmp(argv[count], "--filename") == 0)
|
||||||
|
{
|
||||||
|
if (++count < argc)
|
||||||
|
{
|
||||||
|
opts->stdin_lines = 0;
|
||||||
|
opts->filename = argv[count];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[count], "-n") == 0 || strcmp(argv[count], "--null-message") == 0)
|
||||||
|
{
|
||||||
|
opts->stdin_lines = 0;
|
||||||
|
opts->null_message = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unknown option %s\n", argv[count]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unknown option %s\n", argv[count]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts->topic == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* readfile(int* data_len, struct pubsub_opts* opts)
|
||||||
|
{
|
||||||
|
char* buffer = NULL;
|
||||||
|
long filesize = 0L;
|
||||||
|
FILE* infile = fopen(opts->filename, "rb");
|
||||||
|
|
||||||
|
if (infile == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't open file %s\n", opts->filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fseek(infile, 0, SEEK_END);
|
||||||
|
filesize = ftell(infile);
|
||||||
|
rewind(infile);
|
||||||
|
|
||||||
|
buffer = malloc(sizeof(char)*filesize);
|
||||||
|
if (buffer == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't allocate buffer to read file %s\n", opts->filename);
|
||||||
|
fclose(infile);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*data_len = (int)fread(buffer, 1, filesize, infile);
|
||||||
|
if (*data_len != filesize)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%d bytes read of %ld expected for file %s\n", *data_len, filesize, opts->filename);
|
||||||
|
fclose(infile);
|
||||||
|
free(buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(infile);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void logProperties(MQTTProperties *props)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < props->count; ++i)
|
||||||
|
{
|
||||||
|
int id = props->array[i].identifier;
|
||||||
|
const char* name = MQTTPropertyName(id);
|
||||||
|
char* intformat = "Property name %s value %d\n";
|
||||||
|
|
||||||
|
switch (MQTTProperty_getType(id))
|
||||||
|
{
|
||||||
|
case MQTTPROPERTY_TYPE_BYTE:
|
||||||
|
printf(intformat, name, props->array[i].value.byte);
|
||||||
|
break;
|
||||||
|
case MQTTPROPERTY_TYPE_TWO_BYTE_INTEGER:
|
||||||
|
printf(intformat, name, props->array[i].value.integer2);
|
||||||
|
break;
|
||||||
|
case MQTTPROPERTY_TYPE_FOUR_BYTE_INTEGER:
|
||||||
|
printf(intformat, name, props->array[i].value.integer4);
|
||||||
|
break;
|
||||||
|
case MQTTPROPERTY_TYPE_VARIABLE_BYTE_INTEGER:
|
||||||
|
printf(intformat, name, props->array[i].value.integer4);
|
||||||
|
break;
|
||||||
|
case MQTTPROPERTY_TYPE_BINARY_DATA:
|
||||||
|
case MQTTPROPERTY_TYPE_UTF_8_ENCODED_STRING:
|
||||||
|
printf("Property name %s value len %.*s\n", name,
|
||||||
|
props->array[i].value.data.len, props->array[i].value.data.data);
|
||||||
|
break;
|
||||||
|
case MQTTPROPERTY_TYPE_UTF_8_STRING_PAIR:
|
||||||
|
printf("Property name %s key %.*s value %.*s\n", name,
|
||||||
|
props->array[i].value.data.len, props->array[i].value.data.data,
|
||||||
|
props->array[i].value.value.len, props->array[i].value.value.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
thirdparty/spdlog-1.13.0/.clang-format
vendored
Normal file
19
thirdparty/spdlog-1.13.0/.clang-format
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Google
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
Standard: c++17
|
||||||
|
IndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
ColumnLimit: 100
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
BinPackParameters: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
PackConstructorInitializers: Never
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
IndentPPDirectives: BeforeHash
|
||||||
|
SortIncludes: Never
|
||||||
|
...
|
||||||
|
|
||||||
54
thirdparty/spdlog-1.13.0/.clang-tidy
vendored
Normal file
54
thirdparty/spdlog-1.13.0/.clang-tidy
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
Checks: 'cppcoreguidelines-*,
|
||||||
|
performance-*,
|
||||||
|
modernize-*,
|
||||||
|
google-*,
|
||||||
|
misc-*
|
||||||
|
cert-*,
|
||||||
|
readability-*,
|
||||||
|
clang-analyzer-*,
|
||||||
|
-performance-unnecessary-value-param,
|
||||||
|
-modernize-use-trailing-return-type,
|
||||||
|
-google-runtime-references,
|
||||||
|
-misc-non-private-member-variables-in-classes,
|
||||||
|
-readability-braces-around-statements,
|
||||||
|
-google-readability-braces-around-statements,
|
||||||
|
-cppcoreguidelines-avoid-magic-numbers,
|
||||||
|
-readability-magic-numbers,
|
||||||
|
-readability-magic-numbers,
|
||||||
|
-cppcoreguidelines-pro-type-vararg,
|
||||||
|
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||||
|
-cppcoreguidelines-avoid-c-arrays,
|
||||||
|
-modernize-avoid-c-arrays,
|
||||||
|
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||||
|
-readability-named-parameter,
|
||||||
|
-cert-env33-c
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
|
WarningsAsErrors: ''
|
||||||
|
HeaderFilterRegex: '*spdlog/[^f].*'
|
||||||
|
AnalyzeTemporaryDtors: false
|
||||||
|
FormatStyle: none
|
||||||
|
|
||||||
|
CheckOptions:
|
||||||
|
- key: google-readability-braces-around-statements.ShortStatementLines
|
||||||
|
value: '1'
|
||||||
|
- key: google-readability-function-size.StatementThreshold
|
||||||
|
value: '800'
|
||||||
|
- key: google-readability-namespace-comments.ShortNamespaceLines
|
||||||
|
value: '10'
|
||||||
|
- key: google-readability-namespace-comments.SpacesBeforeComments
|
||||||
|
value: '2'
|
||||||
|
- key: modernize-loop-convert.MaxCopySize
|
||||||
|
value: '16'
|
||||||
|
- key: modernize-loop-convert.MinConfidence
|
||||||
|
value: reasonable
|
||||||
|
- key: modernize-loop-convert.NamingStyle
|
||||||
|
value: CamelCase
|
||||||
|
- key: modernize-pass-by-value.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: modernize-use-nullptr.NullMacros
|
||||||
|
value: 'NULL'
|
||||||
|
|
||||||
6
thirdparty/spdlog-1.13.0/.git-blame-ignore-revs
vendored
Normal file
6
thirdparty/spdlog-1.13.0/.git-blame-ignore-revs
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# clang-format
|
||||||
|
1a0bfc7a89f2d58e22605a4dc7e18a9a555b65aa
|
||||||
|
95c226e9c92928e20ccdac0d060e7241859e282b
|
||||||
|
9d52261185b5f2c454c381d626ec5c84d7b195f4
|
||||||
|
4b2a8219d5d1b40062d030441adde7d1fb0d4f84
|
||||||
|
0a53eafe18d983c7c8ba4cadd02d0cc7f7308f28
|
||||||
1
thirdparty/spdlog-1.13.0/.gitattributes
vendored
Normal file
1
thirdparty/spdlog-1.13.0/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* text=false
|
||||||
78
thirdparty/spdlog-1.13.0/.github/workflows/ci.yml
vendored
Normal file
78
thirdparty/spdlog-1.13.0/.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
name: ci
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
config:
|
||||||
|
- { compiler: gcc, version: 7, build_type: Release, cppstd: 11 }
|
||||||
|
- { compiler: gcc, version: 9, build_type: Release, cppstd: 17 }
|
||||||
|
- { compiler: gcc, version: 11, build_type: Debug, cppstd: 20 }
|
||||||
|
- { compiler: gcc, version: 12, build_type: Release, cppstd: 20 }
|
||||||
|
- { compiler: clang, version: 12, build_type: Debug, cppstd: 17, asan: OFF }
|
||||||
|
- { compiler: clang, version: 15, build_type: Release, cppstd: 20, asan: OFF }
|
||||||
|
container:
|
||||||
|
image: ${{ matrix.config.compiler == 'clang' && 'teeks99/clang-ubuntu' || matrix.config.compiler }}:${{ matrix.config.version }}
|
||||||
|
name: "${{ matrix.config.compiler}} ${{ matrix.config.version }} (C++${{ matrix.config.cppstd }}, ${{ matrix.config.build_type }})"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Setup
|
||||||
|
run: |
|
||||||
|
apt-get update && apt-get install -y curl git pkg-config libsystemd-dev
|
||||||
|
CMAKE_VERSION="3.24.2"
|
||||||
|
curl -sSL https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-x86_64.sh -o install-cmake.sh
|
||||||
|
chmod +x install-cmake.sh
|
||||||
|
./install-cmake.sh --prefix=/usr/local --skip-license
|
||||||
|
- name: Setup Compiler
|
||||||
|
if: matrix.config.compiler == 'clang'
|
||||||
|
run: |
|
||||||
|
if [[ "${{ matrix.config.version }}" -ge 4 ]]; then
|
||||||
|
scripts/ci_setup_clang.sh "${{ matrix.config.version }}"
|
||||||
|
echo "CXXFLAGS=-stdlib=libc++" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
echo "CC=clang-${{ matrix.config.version }}" >> $GITHUB_ENV
|
||||||
|
echo "CXX=clang++-${{ matrix.config.version }}" >> $GITHUB_ENV
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
mkdir -p build && cd build
|
||||||
|
cmake .. \
|
||||||
|
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||||
|
-DCMAKE_CXX_STANDARD=${{ matrix.config.cppstd }} \
|
||||||
|
-DSPDLOG_BUILD_EXAMPLE=${{ matrix.config.examples || 'ON' }} \
|
||||||
|
-DSPDLOG_BUILD_EXAMPLE_HO=${{ matrix.config.examples || 'ON' }} \
|
||||||
|
-DSPDLOG_BUILD_WARNINGS=ON \
|
||||||
|
-DSPDLOG_BUILD_BENCH=OFF \
|
||||||
|
-DSPDLOG_BUILD_TESTS=ON \
|
||||||
|
-DSPDLOG_BUILD_TESTS_HO=OFF \
|
||||||
|
-DSPDLOG_SANITIZE_ADDRESS=${{ matrix.config.asan || 'ON' }}
|
||||||
|
make -j2
|
||||||
|
ctest -j2 --output-on-failure
|
||||||
|
|
||||||
|
build_osx:
|
||||||
|
runs-on: macOS-latest
|
||||||
|
name: "OS X Clang (C++11, Release)"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
mkdir -p build && cd build
|
||||||
|
cmake .. \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_CXX_STANDARD=11 \
|
||||||
|
-DSPDLOG_BUILD_EXAMPLE=ON \
|
||||||
|
-DSPDLOG_BUILD_EXAMPLE_HO=ON \
|
||||||
|
-DSPDLOG_BUILD_WARNINGS=ON \
|
||||||
|
-DSPDLOG_BUILD_BENCH=OFF \
|
||||||
|
-DSPDLOG_BUILD_TESTS=ON \
|
||||||
|
-DSPDLOG_BUILD_TESTS_HO=OFF \
|
||||||
|
-DSPDLOG_SANITIZE_ADDRESS=OFF
|
||||||
|
make -j2
|
||||||
|
ctest -j2 --output-on-failure
|
||||||
|
|
||||||
95
thirdparty/spdlog-1.13.0/.gitignore
vendored
Normal file
95
thirdparty/spdlog-1.13.0/.gitignore
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# Auto generated files
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
build/*
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.suo
|
||||||
|
*.tlog
|
||||||
|
*.ilk
|
||||||
|
*.log
|
||||||
|
*.pdb
|
||||||
|
*.idb
|
||||||
|
*.iobj
|
||||||
|
*.ipdb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# Codelite
|
||||||
|
.codelite
|
||||||
|
|
||||||
|
# KDevelop
|
||||||
|
*.kdev4
|
||||||
|
|
||||||
|
# .orig files
|
||||||
|
*.orig
|
||||||
|
|
||||||
|
# example files
|
||||||
|
example/*
|
||||||
|
!example/example.cpp
|
||||||
|
!example/bench.cpp
|
||||||
|
!example/utils.h
|
||||||
|
!example/Makefile*
|
||||||
|
!example/example.sln
|
||||||
|
!example/example.vcxproj
|
||||||
|
!example/CMakeLists.txt
|
||||||
|
!example/meson.build
|
||||||
|
!example/multisink.cpp
|
||||||
|
!example/jni
|
||||||
|
|
||||||
|
# generated files
|
||||||
|
generated
|
||||||
|
version.rc
|
||||||
|
|
||||||
|
# Cmake
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
/tests/tests.VC.VC.opendb
|
||||||
|
/tests/tests.VC.db
|
||||||
|
/tests/tests
|
||||||
|
/tests/logs/*
|
||||||
|
spdlogConfig.cmake
|
||||||
|
spdlogConfigVersion.cmake
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
# idea
|
||||||
|
.idea/
|
||||||
|
.cache/
|
||||||
|
.vscode/
|
||||||
|
cmake-build-*/
|
||||||
|
*.db
|
||||||
|
*.ipch
|
||||||
|
*.filters
|
||||||
|
*.db-wal
|
||||||
|
*.opendb
|
||||||
|
*.db-shm
|
||||||
|
*.vcxproj
|
||||||
|
*.tcl
|
||||||
|
*.user
|
||||||
|
*.sln
|
||||||
|
|
||||||
|
# macos
|
||||||
|
*.DS_store
|
||||||
|
*.xcodeproj/
|
||||||
359
thirdparty/spdlog-1.13.0/CMakeLists.txt
vendored
Normal file
359
thirdparty/spdlog-1.13.0/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
# Copyright(c) 2019 spdlog authors Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.11)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Start spdlog project
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
include(cmake/utils.cmake)
|
||||||
|
include(cmake/ide.cmake)
|
||||||
|
|
||||||
|
spdlog_extract_version()
|
||||||
|
|
||||||
|
project(spdlog VERSION ${SPDLOG_VERSION} LANGUAGES CXX)
|
||||||
|
message(STATUS "Build spdlog: ${SPDLOG_VERSION}")
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Set default build to release
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Compiler config
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(SPDLOG_USE_STD_FORMAT)
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
elseif(NOT CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# make sure __cplusplus is defined when using msvc and enable parallel build
|
||||||
|
if(MSVC)
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus /MP")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS")
|
||||||
|
set(CMAKE_CXX_EXTENSIONS ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Set SPDLOG_MASTER_PROJECT to ON if we are building spdlog
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Check if spdlog is being used directly or via add_subdirectory, but allow overriding
|
||||||
|
if(NOT DEFINED SPDLOG_MASTER_PROJECT)
|
||||||
|
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||||
|
set(SPDLOG_MASTER_PROJECT ON)
|
||||||
|
else()
|
||||||
|
set(SPDLOG_MASTER_PROJECT OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(SPDLOG_BUILD_ALL "Build all artifacts" OFF)
|
||||||
|
|
||||||
|
# build shared option
|
||||||
|
option(SPDLOG_BUILD_SHARED "Build shared library" OFF)
|
||||||
|
|
||||||
|
# precompiled headers option
|
||||||
|
option(SPDLOG_ENABLE_PCH "Build static or shared library using precompiled header to speed up compilation time" OFF)
|
||||||
|
|
||||||
|
# build position independent code
|
||||||
|
option(SPDLOG_BUILD_PIC "Build position independent code (-fPIC)" OFF)
|
||||||
|
|
||||||
|
# example options
|
||||||
|
option(SPDLOG_BUILD_EXAMPLE "Build example" ${SPDLOG_MASTER_PROJECT})
|
||||||
|
option(SPDLOG_BUILD_EXAMPLE_HO "Build header only example" OFF)
|
||||||
|
|
||||||
|
# testing options
|
||||||
|
option(SPDLOG_BUILD_TESTS "Build tests" OFF)
|
||||||
|
option(SPDLOG_BUILD_TESTS_HO "Build tests using the header only version" OFF)
|
||||||
|
|
||||||
|
# bench options
|
||||||
|
option(SPDLOG_BUILD_BENCH "Build benchmarks (Requires https://github.com/google/benchmark.git to be installed)" OFF)
|
||||||
|
|
||||||
|
# sanitizer options
|
||||||
|
option(SPDLOG_SANITIZE_ADDRESS "Enable address sanitizer in tests" OFF)
|
||||||
|
|
||||||
|
# warning options
|
||||||
|
option(SPDLOG_BUILD_WARNINGS "Enable compiler warnings" OFF)
|
||||||
|
|
||||||
|
# install options
|
||||||
|
option(SPDLOG_SYSTEM_INCLUDES "Include as system headers (skip for clang-tidy)." OFF)
|
||||||
|
option(SPDLOG_INSTALL "Generate the install target" ${SPDLOG_MASTER_PROJECT})
|
||||||
|
option(SPDLOG_USE_STD_FORMAT "Use std::format instead of fmt library." OFF)
|
||||||
|
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
|
||||||
|
option(SPDLOG_FMT_EXTERNAL_HO "Use external fmt header-only library instead of bundled" OFF)
|
||||||
|
option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF)
|
||||||
|
|
||||||
|
if(SPDLOG_FMT_EXTERNAL AND SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
message(FATAL_ERROR "SPDLOG_FMT_EXTERNAL and SPDLOG_FMT_EXTERNAL_HO are mutually exclusive")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
message(FATAL_ERROR "SPDLOG_USE_STD_FORMAT and SPDLOG_FMT_EXTERNAL_HO are mutually exclusive")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL)
|
||||||
|
message(FATAL_ERROR "SPDLOG_USE_STD_FORMAT and SPDLOG_FMT_EXTERNAL are mutually exclusive")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# misc tweakme options
|
||||||
|
if(WIN32)
|
||||||
|
option(SPDLOG_WCHAR_SUPPORT "Support wchar api" OFF)
|
||||||
|
option(SPDLOG_WCHAR_FILENAMES "Support wchar filenames" OFF)
|
||||||
|
else()
|
||||||
|
set(SPDLOG_WCHAR_SUPPORT OFF CACHE BOOL "non supported option" FORCE)
|
||||||
|
set(SPDLOG_WCHAR_FILENAMES OFF CACHE BOOL "non supported option" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
|
option(SPDLOG_CLOCK_COARSE "Use CLOCK_REALTIME_COARSE instead of the regular clock," OFF)
|
||||||
|
else()
|
||||||
|
set(SPDLOG_CLOCK_COARSE OFF CACHE BOOL "non supported option" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(SPDLOG_PREVENT_CHILD_FD "Prevent from child processes to inherit log file descriptors" OFF)
|
||||||
|
option(SPDLOG_NO_THREAD_ID "prevent spdlog from querying the thread id on each log call if thread id is not needed" OFF)
|
||||||
|
option(SPDLOG_NO_TLS "prevent spdlog from using thread local storage" OFF)
|
||||||
|
option(
|
||||||
|
SPDLOG_NO_ATOMIC_LEVELS
|
||||||
|
"prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently"
|
||||||
|
OFF)
|
||||||
|
option(SPDLOG_DISABLE_DEFAULT_LOGGER "Disable default logger creation" OFF)
|
||||||
|
|
||||||
|
# clang-tidy
|
||||||
|
option(SPDLOG_TIDY "run clang-tidy" OFF)
|
||||||
|
|
||||||
|
if(SPDLOG_TIDY)
|
||||||
|
set(CMAKE_CXX_CLANG_TIDY "clang-tidy")
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
message(STATUS "Enabled clang-tidy")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SPDLOG_BUILD_PIC)
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Static/Shared library
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
set(SPDLOG_SRCS src/spdlog.cpp src/stdout_sinks.cpp src/color_sinks.cpp src/file_sinks.cpp src/async.cpp src/cfg.cpp)
|
||||||
|
|
||||||
|
if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
list(APPEND SPDLOG_SRCS src/bundled_fmtlib_format.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SPDLOG_BUILD_SHARED OR BUILD_SHARED_LIBS)
|
||||||
|
if(WIN32)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
|
||||||
|
list(APPEND SPDLOG_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||||
|
endif()
|
||||||
|
add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
|
||||||
|
target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB)
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(spdlog PUBLIC $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<NOT:$<COMPILE_LANGUAGE:CUDA>>>:/wd4251
|
||||||
|
/wd4275>)
|
||||||
|
endif()
|
||||||
|
if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
target_compile_definitions(spdlog PRIVATE FMT_EXPORT PUBLIC FMT_SHARED)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
add_library(spdlog STATIC ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(spdlog::spdlog ALIAS spdlog)
|
||||||
|
|
||||||
|
set(SPDLOG_INCLUDES_LEVEL "")
|
||||||
|
if(SPDLOG_SYSTEM_INCLUDES)
|
||||||
|
set(SPDLOG_INCLUDES_LEVEL "SYSTEM")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(spdlog PUBLIC SPDLOG_COMPILED_LIB)
|
||||||
|
target_include_directories(spdlog ${SPDLOG_INCLUDES_LEVEL} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
|
||||||
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||||
|
target_link_libraries(spdlog PUBLIC Threads::Threads)
|
||||||
|
spdlog_enable_warnings(spdlog)
|
||||||
|
|
||||||
|
set_target_properties(spdlog PROPERTIES VERSION ${SPDLOG_VERSION} SOVERSION
|
||||||
|
${SPDLOG_VERSION_MAJOR}.${SPDLOG_VERSION_MINOR})
|
||||||
|
set_target_properties(spdlog PROPERTIES DEBUG_POSTFIX d)
|
||||||
|
|
||||||
|
if(COMMAND target_precompile_headers AND SPDLOG_ENABLE_PCH)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pch.h.in ${PROJECT_BINARY_DIR}/spdlog_pch.h @ONLY)
|
||||||
|
target_precompile_headers(spdlog PRIVATE ${PROJECT_BINARY_DIR}/spdlog_pch.h)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Header only version
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
add_library(spdlog_header_only INTERFACE)
|
||||||
|
add_library(spdlog::spdlog_header_only ALIAS spdlog_header_only)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
spdlog_header_only ${SPDLOG_INCLUDES_LEVEL} INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
|
||||||
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||||
|
target_link_libraries(spdlog_header_only INTERFACE Threads::Threads)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Use fmt package if using external fmt
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
if(NOT TARGET fmt::fmt)
|
||||||
|
find_package(fmt CONFIG REQUIRED)
|
||||||
|
endif()
|
||||||
|
target_compile_definitions(spdlog PUBLIC SPDLOG_FMT_EXTERNAL)
|
||||||
|
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_FMT_EXTERNAL)
|
||||||
|
|
||||||
|
# use external fmt-header-nly
|
||||||
|
if(SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
target_link_libraries(spdlog PUBLIC fmt::fmt-header-only)
|
||||||
|
target_link_libraries(spdlog_header_only INTERFACE fmt::fmt-header-only)
|
||||||
|
else() # use external compile fmt
|
||||||
|
target_link_libraries(spdlog PUBLIC fmt::fmt)
|
||||||
|
target_link_libraries(spdlog_header_only INTERFACE fmt::fmt)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(PKG_CONFIG_REQUIRES fmt) # add dependency to pkg-config
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Add required libraries for Android CMake build
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(ANDROID)
|
||||||
|
target_link_libraries(spdlog PUBLIC log)
|
||||||
|
target_link_libraries(spdlog_header_only INTERFACE log)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Misc definitions according to tweak options
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
set(SPDLOG_WCHAR_TO_UTF8_SUPPORT ${SPDLOG_WCHAR_SUPPORT})
|
||||||
|
foreach(
|
||||||
|
SPDLOG_OPTION
|
||||||
|
SPDLOG_WCHAR_TO_UTF8_SUPPORT
|
||||||
|
SPDLOG_WCHAR_FILENAMES
|
||||||
|
SPDLOG_NO_EXCEPTIONS
|
||||||
|
SPDLOG_CLOCK_COARSE
|
||||||
|
SPDLOG_PREVENT_CHILD_FD
|
||||||
|
SPDLOG_NO_THREAD_ID
|
||||||
|
SPDLOG_NO_TLS
|
||||||
|
SPDLOG_NO_ATOMIC_LEVELS
|
||||||
|
SPDLOG_DISABLE_DEFAULT_LOGGER
|
||||||
|
SPDLOG_USE_STD_FORMAT)
|
||||||
|
if(${SPDLOG_OPTION})
|
||||||
|
target_compile_definitions(spdlog PUBLIC ${SPDLOG_OPTION})
|
||||||
|
target_compile_definitions(spdlog_header_only INTERFACE ${SPDLOG_OPTION})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# If exceptions are disabled, disable them in the bundled fmt as well
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(SPDLOG_NO_EXCEPTIONS)
|
||||||
|
if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
target_compile_definitions(spdlog PUBLIC FMT_EXCEPTIONS=0)
|
||||||
|
endif()
|
||||||
|
if(NOT MSVC)
|
||||||
|
target_compile_options(spdlog PRIVATE -fno-exceptions)
|
||||||
|
else()
|
||||||
|
target_compile_options(spdlog PRIVATE /EHs-c-)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Build binaries
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(SPDLOG_BUILD_EXAMPLE OR SPDLOG_BUILD_EXAMPLE_HO OR SPDLOG_BUILD_ALL)
|
||||||
|
message(STATUS "Generating example(s)")
|
||||||
|
add_subdirectory(example)
|
||||||
|
spdlog_enable_warnings(example)
|
||||||
|
if(SPDLOG_BUILD_EXAMPLE_HO)
|
||||||
|
spdlog_enable_warnings(example_header_only)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SPDLOG_BUILD_TESTS OR SPDLOG_BUILD_TESTS_HO OR SPDLOG_BUILD_ALL)
|
||||||
|
message(STATUS "Generating tests")
|
||||||
|
enable_testing()
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SPDLOG_BUILD_BENCH OR SPDLOG_BUILD_ALL)
|
||||||
|
message(STATUS "Generating benchmarks")
|
||||||
|
add_subdirectory(bench)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Install
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(SPDLOG_INSTALL)
|
||||||
|
message(STATUS "Generating install")
|
||||||
|
set(project_config_in "${CMAKE_CURRENT_LIST_DIR}/cmake/spdlogConfig.cmake.in")
|
||||||
|
set(project_config_out "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfig.cmake")
|
||||||
|
set(config_targets_file "spdlogConfigTargets.cmake")
|
||||||
|
set(version_config_file "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfigVersion.cmake")
|
||||||
|
set(export_dest_dir "${CMAKE_INSTALL_LIBDIR}/cmake/spdlog")
|
||||||
|
set(pkgconfig_install_dir "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
|
set(pkg_config "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc")
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Include files
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" PATTERN "fmt/bundled" EXCLUDE)
|
||||||
|
install(
|
||||||
|
TARGETS spdlog spdlog_header_only
|
||||||
|
EXPORT spdlog
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
|
if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
install(DIRECTORY include/${PROJECT_NAME}/fmt/bundled/
|
||||||
|
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/fmt/bundled/")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Install pkg-config file
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
set(PKG_CONFIG_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
else()
|
||||||
|
set(PKG_CONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
endif()
|
||||||
|
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
set(PKG_CONFIG_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
else()
|
||||||
|
set(PKG_CONFIG_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
endif()
|
||||||
|
get_target_property(PKG_CONFIG_DEFINES spdlog INTERFACE_COMPILE_DEFINITIONS)
|
||||||
|
string(REPLACE ";" " -D" PKG_CONFIG_DEFINES "${PKG_CONFIG_DEFINES}")
|
||||||
|
string(CONCAT PKG_CONFIG_DEFINES "-D" "${PKG_CONFIG_DEFINES}")
|
||||||
|
configure_file("cmake/${PROJECT_NAME}.pc.in" "${pkg_config}" @ONLY)
|
||||||
|
install(FILES "${pkg_config}" DESTINATION "${pkgconfig_install_dir}")
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Install CMake config files
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
export(TARGETS spdlog spdlog_header_only NAMESPACE spdlog::
|
||||||
|
FILE "${CMAKE_CURRENT_BINARY_DIR}/${config_targets_file}")
|
||||||
|
install(EXPORT spdlog DESTINATION ${export_dest_dir} NAMESPACE spdlog:: FILE ${config_targets_file})
|
||||||
|
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
configure_package_config_file("${project_config_in}" "${project_config_out}" INSTALL_DESTINATION ${export_dest_dir})
|
||||||
|
|
||||||
|
write_basic_package_version_file("${version_config_file}" COMPATIBILITY SameMajorVersion)
|
||||||
|
install(FILES "${project_config_out}" "${version_config_file}" DESTINATION "${export_dest_dir}")
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Support creation of installable packages
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
include(cmake/spdlogCPack.cmake)
|
||||||
|
endif()
|
||||||
24
thirdparty/spdlog-1.13.0/INSTALL
vendored
Normal file
24
thirdparty/spdlog-1.13.0/INSTALL
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Header only version:
|
||||||
|
==================================================================
|
||||||
|
Just copy the files to your build tree and use a C++11 compiler.
|
||||||
|
Or use CMake:
|
||||||
|
add_executable(example_header_only example.cpp)
|
||||||
|
target_link_libraries(example_header_only spdlog::spdlog_header_only)
|
||||||
|
|
||||||
|
|
||||||
|
Compiled library version:
|
||||||
|
==================================================================
|
||||||
|
CMake:
|
||||||
|
add_executable(example example.cpp)
|
||||||
|
target_link_libraries(example spdlog::spdlog)
|
||||||
|
|
||||||
|
Or copy files src/*.cpp to your build tree and pass the -DSPDLOG_COMPILED_LIB to the compiler.
|
||||||
|
|
||||||
|
Tested on:
|
||||||
|
gcc 4.8.1 and above
|
||||||
|
clang 3.5
|
||||||
|
Visual Studio 2013
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
26
thirdparty/spdlog-1.13.0/LICENSE
vendored
Normal file
26
thirdparty/spdlog-1.13.0/LICENSE
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016 Gabi Melman.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
-- NOTE: Third party dependency used by this software --
|
||||||
|
This software depends on the fmt lib (MIT License),
|
||||||
|
and users must comply to its license: https://raw.githubusercontent.com/fmtlib/fmt/master/LICENSE
|
||||||
|
|
||||||
500
thirdparty/spdlog-1.13.0/README.md
vendored
Normal file
500
thirdparty/spdlog-1.13.0/README.md
vendored
Normal file
@@ -0,0 +1,500 @@
|
|||||||
|
# spdlog
|
||||||
|
|
||||||
|
Very fast, header-only/compiled, C++ logging library. [](https://github.com/gabime/spdlog/actions/workflows/ci.yml) [](https://ci.appveyor.com/project/gabime/spdlog) [](https://github.com/gabime/spdlog/releases/latest)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
#### Header-only version
|
||||||
|
Copy the include [folder](https://github.com/gabime/spdlog/tree/v1.x/include/spdlog) to your build tree and use a C++11 compiler.
|
||||||
|
|
||||||
|
#### Compiled version (recommended - much faster compile times)
|
||||||
|
```console
|
||||||
|
$ git clone https://github.com/gabime/spdlog.git
|
||||||
|
$ cd spdlog && mkdir build && cd build
|
||||||
|
$ cmake .. && make -j
|
||||||
|
```
|
||||||
|
see example [CMakeLists.txt](https://github.com/gabime/spdlog/blob/v1.x/example/CMakeLists.txt) on how to use.
|
||||||
|
|
||||||
|
## Platforms
|
||||||
|
* Linux, FreeBSD, OpenBSD, Solaris, AIX
|
||||||
|
* Windows (msvc 2013+, cygwin)
|
||||||
|
* macOS (clang 3.5+)
|
||||||
|
* Android
|
||||||
|
|
||||||
|
## Package managers:
|
||||||
|
* Debian: `sudo apt install libspdlog-dev`
|
||||||
|
* Homebrew: `brew install spdlog`
|
||||||
|
* MacPorts: `sudo port install spdlog`
|
||||||
|
* FreeBSD: `pkg install spdlog`
|
||||||
|
* Fedora: `dnf install spdlog`
|
||||||
|
* Gentoo: `emerge dev-libs/spdlog`
|
||||||
|
* Arch Linux: `pacman -S spdlog`
|
||||||
|
* openSUSE: `sudo zypper in spdlog-devel`
|
||||||
|
* vcpkg: `vcpkg install spdlog`
|
||||||
|
* conan: `spdlog/[>=1.4.1]`
|
||||||
|
* conda: `conda install -c conda-forge spdlog`
|
||||||
|
* build2: ```depends: spdlog ^1.8.2```
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
* Very fast (see [benchmarks](#benchmarks) below).
|
||||||
|
* Headers only or compiled
|
||||||
|
* Feature-rich formatting, using the excellent [fmt](https://github.com/fmtlib/fmt) library.
|
||||||
|
* Asynchronous mode (optional)
|
||||||
|
* [Custom](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting) formatting.
|
||||||
|
* Multi/Single threaded loggers.
|
||||||
|
* Various log targets:
|
||||||
|
* Rotating log files.
|
||||||
|
* Daily log files.
|
||||||
|
* Console logging (colors supported).
|
||||||
|
* syslog.
|
||||||
|
* Windows event log.
|
||||||
|
* Windows debugger (```OutputDebugString(..)```).
|
||||||
|
* Log to Qt widgets ([example](#log-to-qt-with-nice-colors)).
|
||||||
|
* Easily [extendable](https://github.com/gabime/spdlog/wiki/4.-Sinks#implementing-your-own-sink) with custom log targets.
|
||||||
|
* Log filtering - log levels can be modified at runtime as well as compile time.
|
||||||
|
* Support for loading log levels from argv or environment var.
|
||||||
|
* [Backtrace](#backtrace-support) support - store debug messages in a ring buffer and display them later on demand.
|
||||||
|
|
||||||
|
## Usage samples
|
||||||
|
|
||||||
|
#### Basic usage
|
||||||
|
```c++
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
spdlog::info("Welcome to spdlog!");
|
||||||
|
spdlog::error("Some error message with arg: {}", 1);
|
||||||
|
|
||||||
|
spdlog::warn("Easy padding in numbers like {:08d}", 12);
|
||||||
|
spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
|
||||||
|
spdlog::info("Support for floats {:03.2f}", 1.23456);
|
||||||
|
spdlog::info("Positional args are {1} {0}..", "too", "supported");
|
||||||
|
spdlog::info("{:<30}", "left aligned");
|
||||||
|
|
||||||
|
spdlog::set_level(spdlog::level::debug); // Set global log level to debug
|
||||||
|
spdlog::debug("This message should be displayed..");
|
||||||
|
|
||||||
|
// change log pattern
|
||||||
|
spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
|
||||||
|
|
||||||
|
// Compile time log levels
|
||||||
|
// define SPDLOG_ACTIVE_LEVEL to desired level
|
||||||
|
SPDLOG_TRACE("Some trace message with param {}", 42);
|
||||||
|
SPDLOG_DEBUG("Some debug message");
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
#### Create stdout/stderr logger object
|
||||||
|
```c++
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
|
void stdout_example()
|
||||||
|
{
|
||||||
|
// create a color multi-threaded logger
|
||||||
|
auto console = spdlog::stdout_color_mt("console");
|
||||||
|
auto err_logger = spdlog::stderr_color_mt("stderr");
|
||||||
|
spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Basic file logger
|
||||||
|
```c++
|
||||||
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
void basic_logfile_example()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic-log.txt");
|
||||||
|
}
|
||||||
|
catch (const spdlog::spdlog_ex &ex)
|
||||||
|
{
|
||||||
|
std::cout << "Log init failed: " << ex.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
#### Rotating files
|
||||||
|
```c++
|
||||||
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
void rotating_example()
|
||||||
|
{
|
||||||
|
// Create a file rotating logger with 5 MB size max and 3 rotated files
|
||||||
|
auto max_size = 1048576 * 5;
|
||||||
|
auto max_files = 3;
|
||||||
|
auto logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", max_size, max_files);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Daily files
|
||||||
|
```c++
|
||||||
|
|
||||||
|
#include "spdlog/sinks/daily_file_sink.h"
|
||||||
|
void daily_example()
|
||||||
|
{
|
||||||
|
// Create a daily logger - a new file is created every day at 2:30 am
|
||||||
|
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Backtrace support
|
||||||
|
```c++
|
||||||
|
// Debug messages can be stored in a ring buffer instead of being logged immediately.
|
||||||
|
// This is useful to display debug logs only when needed (e.g. when an error happens).
|
||||||
|
// When needed, call dump_backtrace() to dump them to your log.
|
||||||
|
|
||||||
|
spdlog::enable_backtrace(32); // Store the latest 32 messages in a buffer.
|
||||||
|
// or my_logger->enable_backtrace(32)..
|
||||||
|
for(int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
spdlog::debug("Backtrace message {}", i); // not logged yet..
|
||||||
|
}
|
||||||
|
// e.g. if some error happened:
|
||||||
|
spdlog::dump_backtrace(); // log them now! show the last 32 messages
|
||||||
|
// or my_logger->dump_backtrace(32)..
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Periodic flush
|
||||||
|
```c++
|
||||||
|
// periodically flush all *registered* loggers every 3 seconds:
|
||||||
|
// warning: only use if all your loggers are thread-safe ("_mt" loggers)
|
||||||
|
spdlog::flush_every(std::chrono::seconds(3));
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Stopwatch
|
||||||
|
```c++
|
||||||
|
// Stopwatch support for spdlog
|
||||||
|
#include "spdlog/stopwatch.h"
|
||||||
|
void stopwatch_example()
|
||||||
|
{
|
||||||
|
spdlog::stopwatch sw;
|
||||||
|
spdlog::debug("Elapsed {}", sw);
|
||||||
|
spdlog::debug("Elapsed {:.3}", sw);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Log binary data in hex
|
||||||
|
```c++
|
||||||
|
// many types of std::container<char> types can be used.
|
||||||
|
// ranges are supported too.
|
||||||
|
// format flags:
|
||||||
|
// {:X} - print in uppercase.
|
||||||
|
// {:s} - don't separate each byte with space.
|
||||||
|
// {:p} - don't print the position on each line start.
|
||||||
|
// {:n} - don't split the output into lines.
|
||||||
|
// {:a} - show ASCII if :n is not set.
|
||||||
|
|
||||||
|
#include "spdlog/fmt/bin_to_hex.h"
|
||||||
|
|
||||||
|
void binary_example()
|
||||||
|
{
|
||||||
|
auto console = spdlog::get("console");
|
||||||
|
std::array<char, 80> buf;
|
||||||
|
console->info("Binary example: {}", spdlog::to_hex(buf));
|
||||||
|
console->info("Another binary example:{:n}", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10));
|
||||||
|
// more examples:
|
||||||
|
// logger->info("uppercase: {:X}", spdlog::to_hex(buf));
|
||||||
|
// logger->info("uppercase, no delimiters: {:Xs}", spdlog::to_hex(buf));
|
||||||
|
// logger->info("uppercase, no delimiters, no position info: {:Xsp}", spdlog::to_hex(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Logger with multi sinks - each with a different format and log level
|
||||||
|
```c++
|
||||||
|
|
||||||
|
// create a logger with 2 targets, with different log levels and formats.
|
||||||
|
// The console will show only warnings or errors, while the file will log all.
|
||||||
|
void multi_sink_example()
|
||||||
|
{
|
||||||
|
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||||
|
console_sink->set_level(spdlog::level::warn);
|
||||||
|
console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v");
|
||||||
|
|
||||||
|
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multisink.txt", true);
|
||||||
|
file_sink->set_level(spdlog::level::trace);
|
||||||
|
|
||||||
|
spdlog::logger logger("multi_sink", {console_sink, file_sink});
|
||||||
|
logger.set_level(spdlog::level::debug);
|
||||||
|
logger.warn("this should appear in both console and file");
|
||||||
|
logger.info("this message should not appear in the console, only in the file");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### User-defined callbacks about log events
|
||||||
|
```c++
|
||||||
|
|
||||||
|
// create a logger with a lambda function callback, the callback will be called
|
||||||
|
// each time something is logged to the logger
|
||||||
|
void callback_example()
|
||||||
|
{
|
||||||
|
auto callback_sink = std::make_shared<spdlog::sinks::callback_sink_mt>([](const spdlog::details::log_msg &msg) {
|
||||||
|
// for example you can be notified by sending an email to yourself
|
||||||
|
});
|
||||||
|
callback_sink->set_level(spdlog::level::err);
|
||||||
|
|
||||||
|
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||||
|
spdlog::logger logger("custom_callback_logger", {console_sink, callback_sink});
|
||||||
|
|
||||||
|
logger.info("some info log");
|
||||||
|
logger.error("critical issue"); // will notify you
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Asynchronous logging
|
||||||
|
```c++
|
||||||
|
#include "spdlog/async.h"
|
||||||
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
void async_example()
|
||||||
|
{
|
||||||
|
// default thread pool settings can be modified *before* creating the async logger:
|
||||||
|
// spdlog::init_thread_pool(8192, 1); // queue with 8k items and 1 backing thread.
|
||||||
|
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
|
||||||
|
// alternatively:
|
||||||
|
// auto async_file = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async_file_logger", "logs/async_log.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Asynchronous logger with multi sinks
|
||||||
|
```c++
|
||||||
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
|
||||||
|
void multi_sink_example2()
|
||||||
|
{
|
||||||
|
spdlog::init_thread_pool(8192, 1);
|
||||||
|
auto stdout_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt >();
|
||||||
|
auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("mylog.txt", 1024*1024*10, 3);
|
||||||
|
std::vector<spdlog::sink_ptr> sinks {stdout_sink, rotating_sink};
|
||||||
|
auto logger = std::make_shared<spdlog::async_logger>("loggername", sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
|
||||||
|
spdlog::register_logger(logger);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### User-defined types
|
||||||
|
```c++
|
||||||
|
template<>
|
||||||
|
struct fmt::formatter<my_type> : fmt::formatter<std::string>
|
||||||
|
{
|
||||||
|
auto format(my_type my, format_context &ctx) const -> decltype(ctx.out())
|
||||||
|
{
|
||||||
|
return format_to(ctx.out(), "[my_type i={}]", my.i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void user_defined_example()
|
||||||
|
{
|
||||||
|
spdlog::info("user defined type: {}", my_type(14));
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### User-defined flags in the log pattern
|
||||||
|
```c++
|
||||||
|
// Log patterns can contain custom flags.
|
||||||
|
// the following example will add new flag '%*' - which will be bound to a <my_formatter_flag> instance.
|
||||||
|
#include "spdlog/pattern_formatter.h"
|
||||||
|
class my_formatter_flag : public spdlog::custom_flag_formatter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override
|
||||||
|
{
|
||||||
|
std::string some_txt = "custom-flag";
|
||||||
|
dest.append(some_txt.data(), some_txt.data() + some_txt.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<custom_flag_formatter> clone() const override
|
||||||
|
{
|
||||||
|
return spdlog::details::make_unique<my_formatter_flag>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void custom_flags_example()
|
||||||
|
{
|
||||||
|
auto formatter = std::make_unique<spdlog::pattern_formatter>();
|
||||||
|
formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v");
|
||||||
|
spdlog::set_formatter(std::move(formatter));
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Custom error handler
|
||||||
|
```c++
|
||||||
|
void err_handler_example()
|
||||||
|
{
|
||||||
|
// can be set globally or per logger(logger->set_error_handler(..))
|
||||||
|
spdlog::set_error_handler([](const std::string &msg) { spdlog::get("console")->error("*** LOGGER ERROR ***: {}", msg); });
|
||||||
|
spdlog::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### syslog
|
||||||
|
```c++
|
||||||
|
#include "spdlog/sinks/syslog_sink.h"
|
||||||
|
void syslog_example()
|
||||||
|
{
|
||||||
|
std::string ident = "spdlog-example";
|
||||||
|
auto syslog_logger = spdlog::syslog_logger_mt("syslog", ident, LOG_PID);
|
||||||
|
syslog_logger->warn("This is warning that will end up in syslog.");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
#### Android example
|
||||||
|
```c++
|
||||||
|
#include "spdlog/sinks/android_sink.h"
|
||||||
|
void android_example()
|
||||||
|
{
|
||||||
|
std::string tag = "spdlog-android";
|
||||||
|
auto android_logger = spdlog::android_logger_mt("android", tag);
|
||||||
|
android_logger->critical("Use \"adb shell logcat\" to view this message.");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Load log levels from the env variable or argv
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include "spdlog/cfg/env.h"
|
||||||
|
int main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
spdlog::cfg::load_env_levels();
|
||||||
|
// or from the command line:
|
||||||
|
// ./example SPDLOG_LEVEL=info,mylogger=trace
|
||||||
|
// #include "spdlog/cfg/argv.h" // for loading levels from argv
|
||||||
|
// spdlog::cfg::load_argv_levels(argc, argv);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
So then you can:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ export SPDLOG_LEVEL=info,mylogger=trace
|
||||||
|
$ ./example
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Log file open/close event handlers
|
||||||
|
```c++
|
||||||
|
// You can get callbacks from spdlog before/after a log file has been opened or closed.
|
||||||
|
// This is useful for cleanup procedures or for adding something to the start/end of the log file.
|
||||||
|
void file_events_example()
|
||||||
|
{
|
||||||
|
// pass the spdlog::file_event_handlers to file sinks for open/close log file notifications
|
||||||
|
spdlog::file_event_handlers handlers;
|
||||||
|
handlers.before_open = [](spdlog::filename_t filename) { spdlog::info("Before opening {}", filename); };
|
||||||
|
handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) { fputs("After opening\n", fstream); };
|
||||||
|
handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) { fputs("Before closing\n", fstream); };
|
||||||
|
handlers.after_close = [](spdlog::filename_t filename) { spdlog::info("After closing {}", filename); };
|
||||||
|
auto my_logger = spdlog::basic_logger_st("some_logger", "logs/events-sample.txt", true, handlers);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Replace the Default Logger
|
||||||
|
```c++
|
||||||
|
void replace_default_logger_example()
|
||||||
|
{
|
||||||
|
auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true);
|
||||||
|
spdlog::set_default_logger(new_logger);
|
||||||
|
spdlog::info("new logger log message");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
#### Log to Qt with nice colors
|
||||||
|
```c++
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/sinks/qt_sinks.h"
|
||||||
|
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||||
|
{
|
||||||
|
setMinimumSize(640, 480);
|
||||||
|
auto log_widget = new QTextEdit(this);
|
||||||
|
setCentralWidget(log_widget);
|
||||||
|
int max_lines = 500; // keep the text widget to max 500 lines. remove old lines if needed.
|
||||||
|
auto logger = spdlog::qt_color_logger_mt("qt_logger", log_widget, max_lines);
|
||||||
|
logger->info("Some info message");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
## Benchmarks
|
||||||
|
|
||||||
|
Below are some [benchmarks](https://github.com/gabime/spdlog/blob/v1.x/bench/bench.cpp) done in Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz
|
||||||
|
|
||||||
|
#### Synchronous mode
|
||||||
|
```
|
||||||
|
[info] **************************************************************
|
||||||
|
[info] Single thread, 1,000,000 iterations
|
||||||
|
[info] **************************************************************
|
||||||
|
[info] basic_st Elapsed: 0.17 secs 5,777,626/sec
|
||||||
|
[info] rotating_st Elapsed: 0.18 secs 5,475,894/sec
|
||||||
|
[info] daily_st Elapsed: 0.20 secs 5,062,659/sec
|
||||||
|
[info] empty_logger Elapsed: 0.07 secs 14,127,300/sec
|
||||||
|
[info] **************************************************************
|
||||||
|
[info] C-string (400 bytes). Single thread, 1,000,000 iterations
|
||||||
|
[info] **************************************************************
|
||||||
|
[info] basic_st Elapsed: 0.41 secs 2,412,483/sec
|
||||||
|
[info] rotating_st Elapsed: 0.72 secs 1,389,196/sec
|
||||||
|
[info] daily_st Elapsed: 0.42 secs 2,393,298/sec
|
||||||
|
[info] null_st Elapsed: 0.04 secs 27,446,957/sec
|
||||||
|
[info] **************************************************************
|
||||||
|
[info] 10 threads, competing over the same logger object, 1,000,000 iterations
|
||||||
|
[info] **************************************************************
|
||||||
|
[info] basic_mt Elapsed: 0.60 secs 1,659,613/sec
|
||||||
|
[info] rotating_mt Elapsed: 0.62 secs 1,612,493/sec
|
||||||
|
[info] daily_mt Elapsed: 0.61 secs 1,638,305/sec
|
||||||
|
[info] null_mt Elapsed: 0.16 secs 6,272,758/sec
|
||||||
|
```
|
||||||
|
#### Asynchronous mode
|
||||||
|
```
|
||||||
|
[info] -------------------------------------------------
|
||||||
|
[info] Messages : 1,000,000
|
||||||
|
[info] Threads : 10
|
||||||
|
[info] Queue : 8,192 slots
|
||||||
|
[info] Queue memory : 8,192 x 272 = 2,176 KB
|
||||||
|
[info] -------------------------------------------------
|
||||||
|
[info]
|
||||||
|
[info] *********************************
|
||||||
|
[info] Queue Overflow Policy: block
|
||||||
|
[info] *********************************
|
||||||
|
[info] Elapsed: 1.70784 secs 585,535/sec
|
||||||
|
[info] Elapsed: 1.69805 secs 588,910/sec
|
||||||
|
[info] Elapsed: 1.7026 secs 587,337/sec
|
||||||
|
[info]
|
||||||
|
[info] *********************************
|
||||||
|
[info] Queue Overflow Policy: overrun
|
||||||
|
[info] *********************************
|
||||||
|
[info] Elapsed: 0.372816 secs 2,682,285/sec
|
||||||
|
[info] Elapsed: 0.379758 secs 2,633,255/sec
|
||||||
|
[info] Elapsed: 0.373532 secs 2,677,147/sec
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
Documentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki/1.-QuickStart) pages.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Thanks to [JetBrains](https://www.jetbrains.com/?from=spdlog) for donating product licenses to help develop **spdlog** <a href="https://www.jetbrains.com/?from=spdlog"><img src="logos/jetbrains-variant-4.svg" width="94" align="center" /></a>
|
||||||
|
|
||||||
|
|
||||||
89
thirdparty/spdlog-1.13.0/appveyor.yml
vendored
Normal file
89
thirdparty/spdlog-1.13.0/appveyor.yml
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
version: 1.0.{build}
|
||||||
|
image: Visual Studio 2017
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
||||||
|
BUILD_TYPE: Debug
|
||||||
|
BUILD_SHARED: 'OFF'
|
||||||
|
FATAL_ERRORS: 'OFF'
|
||||||
|
WCHAR: 'ON'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
|
USE_STD_FORMAT: 'OFF'
|
||||||
|
CXX_STANDARD: 11
|
||||||
|
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
BUILD_SHARED: 'OFF'
|
||||||
|
FATAL_ERRORS: 'OFF'
|
||||||
|
WCHAR: 'OFF'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
|
USE_STD_FORMAT: 'OFF'
|
||||||
|
CXX_STANDARD: 11
|
||||||
|
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
BUILD_SHARED: 'ON'
|
||||||
|
FATAL_ERRORS: 'OFF'
|
||||||
|
WCHAR: 'OFF'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'ON'
|
||||||
|
USE_STD_FORMAT: 'OFF'
|
||||||
|
CXX_STANDARD: 11
|
||||||
|
- GENERATOR: '"Visual Studio 15 2017 Win64"'
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
BUILD_SHARED: 'ON'
|
||||||
|
FATAL_ERRORS: 'OFF'
|
||||||
|
WCHAR: 'ON'
|
||||||
|
WCHAR_FILES: 'ON'
|
||||||
|
BUILD_EXAMPLE: 'OFF'
|
||||||
|
USE_STD_FORMAT: 'OFF'
|
||||||
|
CXX_STANDARD: 11
|
||||||
|
- GENERATOR: '"Visual Studio 16 2019" -A x64'
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
BUILD_SHARED: 'ON'
|
||||||
|
FATAL_ERRORS: 'ON'
|
||||||
|
WCHAR: 'OFF'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'OFF'
|
||||||
|
USE_STD_FORMAT: 'OFF'
|
||||||
|
CXX_STANDARD: 17
|
||||||
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
- GENERATOR: '"Visual Studio 17 2022" -A x64'
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
BUILD_SHARED: 'ON'
|
||||||
|
FATAL_ERRORS: 'ON'
|
||||||
|
WCHAR: 'OFF'
|
||||||
|
WCHAR_FILES: 'OFF'
|
||||||
|
BUILD_EXAMPLE: 'OFF'
|
||||||
|
USE_STD_FORMAT: 'ON'
|
||||||
|
CXX_STANDARD: 20
|
||||||
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||||
|
- GENERATOR: '"Visual Studio 17 2022" -A x64'
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
BUILD_SHARED: 'ON'
|
||||||
|
FATAL_ERRORS: 'ON'
|
||||||
|
WCHAR: 'ON'
|
||||||
|
WCHAR_FILES: 'ON'
|
||||||
|
BUILD_EXAMPLE: 'OFF'
|
||||||
|
USE_STD_FORMAT: 'ON'
|
||||||
|
CXX_STANDARD: 20
|
||||||
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||||
|
build_script:
|
||||||
|
- cmd: >-
|
||||||
|
set
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
|
||||||
|
cd build
|
||||||
|
|
||||||
|
set PATH=%PATH%;C:\Program Files\Git\usr\bin
|
||||||
|
|
||||||
|
cmake -G %GENERATOR% -D CMAKE_BUILD_TYPE=%BUILD_TYPE% -D BUILD_SHARED_LIBS=%BUILD_SHARED% -D SPDLOG_WCHAR_SUPPORT=%WCHAR% -D SPDLOG_WCHAR_FILENAMES=%WCHAR_FILES% -D SPDLOG_BUILD_EXAMPLE=%BUILD_EXAMPLE% -D SPDLOG_BUILD_EXAMPLE_HO=%BUILD_EXAMPLE% -D SPDLOG_BUILD_TESTS=ON -D SPDLOG_BUILD_TESTS_HO=OFF -D SPDLOG_BUILD_WARNINGS=%FATAL_ERRORS% -D SPDLOG_USE_STD_FORMAT=%USE_STD_FORMAT% -D CMAKE_CXX_STANDARD=%CXX_STANDARD% ..
|
||||||
|
|
||||||
|
cmake --build . --config %BUILD_TYPE%
|
||||||
|
|
||||||
|
before_test:
|
||||||
|
- set PATH=%PATH%;C:\projects\spdlog\build\_deps\catch2-build\src\%BUILD_TYPE%;C:\projects\spdlog\build\%BUILD_TYPE%
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- C:\projects\spdlog\build\tests\%BUILD_TYPE%\spdlog-utests.exe
|
||||||
37
thirdparty/spdlog-1.13.0/bench/CMakeLists.txt
vendored
Normal file
37
thirdparty/spdlog-1.13.0/bench/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Copyright(c) 2019 spdlog authors Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.11)
|
||||||
|
project(spdlog_bench CXX)
|
||||||
|
|
||||||
|
if(NOT TARGET spdlog)
|
||||||
|
# Stand-alone build
|
||||||
|
find_package(spdlog CONFIG REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
find_package(benchmark CONFIG)
|
||||||
|
if(NOT benchmark_FOUND)
|
||||||
|
message(STATUS "Using CMake Version ${CMAKE_VERSION}")
|
||||||
|
# User can fetch googlebenchmark
|
||||||
|
message(STATUS "Downloading GoogleBenchmark")
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
# disable tests
|
||||||
|
set(BENCHMARK_ENABLE_TESTING OFF CACHE INTERNAL "")
|
||||||
|
# Do not build and run googlebenchmark tests
|
||||||
|
FetchContent_Declare(googlebenchmark GIT_REPOSITORY https://github.com/google/benchmark.git GIT_TAG v1.6.0)
|
||||||
|
FetchContent_MakeAvailable(googlebenchmark)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(bench bench.cpp)
|
||||||
|
spdlog_enable_warnings(bench)
|
||||||
|
target_link_libraries(bench PRIVATE spdlog::spdlog)
|
||||||
|
|
||||||
|
add_executable(async_bench async_bench.cpp)
|
||||||
|
target_link_libraries(async_bench PRIVATE spdlog::spdlog)
|
||||||
|
|
||||||
|
add_executable(latency latency.cpp)
|
||||||
|
target_link_libraries(latency PRIVATE benchmark::benchmark spdlog::spdlog)
|
||||||
|
|
||||||
|
add_executable(formatter-bench formatter-bench.cpp)
|
||||||
|
target_link_libraries(formatter-bench PRIVATE benchmark::benchmark spdlog::spdlog)
|
||||||
168
thirdparty/spdlog-1.13.0/bench/async_bench.cpp
vendored
Normal file
168
thirdparty/spdlog-1.13.0/bench/async_bench.cpp
vendored
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
//
|
||||||
|
// Copyright(c) 2015 Gabi Melman.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// bench.cpp : spdlog benchmarks
|
||||||
|
//
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/async.h"
|
||||||
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
|
||||||
|
#if defined(SPDLOG_USE_STD_FORMAT)
|
||||||
|
#include <format>
|
||||||
|
#elif defined(SPDLOG_FMT_EXTERNAL)
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#else
|
||||||
|
#include "spdlog/fmt/bundled/format.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include <atomic>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::chrono;
|
||||||
|
using namespace spdlog;
|
||||||
|
using namespace spdlog::sinks;
|
||||||
|
using namespace utils;
|
||||||
|
|
||||||
|
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4996) // disable fopen warning under msvc
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
int count_lines(const char *filename) {
|
||||||
|
int counter = 0;
|
||||||
|
auto *infile = fopen(filename, "r");
|
||||||
|
int ch;
|
||||||
|
while (EOF != (ch = getc(infile))) {
|
||||||
|
if ('\n' == ch) counter++;
|
||||||
|
}
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void verify_file(const char *filename, int expected_count) {
|
||||||
|
spdlog::info("Verifying {} to contain {} line..", filename, expected_count);
|
||||||
|
auto count = count_lines(filename);
|
||||||
|
if (count != expected_count) {
|
||||||
|
spdlog::error("Test failed. {} has {} lines instead of {}", filename, count,
|
||||||
|
expected_count);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
spdlog::info("Line count OK ({})\n", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int howmany = 1000000;
|
||||||
|
int queue_size = std::min(howmany + 2, 8192);
|
||||||
|
int threads = 10;
|
||||||
|
int iters = 3;
|
||||||
|
|
||||||
|
try {
|
||||||
|
spdlog::set_pattern("[%^%l%$] %v");
|
||||||
|
if (argc == 1) {
|
||||||
|
spdlog::info("Usage: {} <message_count> <threads> <q_size> <iterations>", argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1) howmany = atoi(argv[1]);
|
||||||
|
if (argc > 2) threads = atoi(argv[2]);
|
||||||
|
if (argc > 3) {
|
||||||
|
queue_size = atoi(argv[3]);
|
||||||
|
if (queue_size > 500000) {
|
||||||
|
spdlog::error("Max queue size allowed: 500,000");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 4) iters = atoi(argv[4]);
|
||||||
|
|
||||||
|
auto slot_size = sizeof(spdlog::details::async_msg);
|
||||||
|
spdlog::info("-------------------------------------------------");
|
||||||
|
spdlog::info("Messages : {:L}", howmany);
|
||||||
|
spdlog::info("Threads : {:L}", threads);
|
||||||
|
spdlog::info("Queue : {:L} slots", queue_size);
|
||||||
|
spdlog::info("Queue memory : {:L} x {:L} = {:L} KB ", queue_size, slot_size,
|
||||||
|
(queue_size * slot_size) / 1024);
|
||||||
|
spdlog::info("Total iters : {:L}", iters);
|
||||||
|
spdlog::info("-------------------------------------------------");
|
||||||
|
|
||||||
|
const char *filename = "logs/basic_async.log";
|
||||||
|
spdlog::info("");
|
||||||
|
spdlog::info("*********************************");
|
||||||
|
spdlog::info("Queue Overflow Policy: block");
|
||||||
|
spdlog::info("*********************************");
|
||||||
|
for (int i = 0; i < iters; i++) {
|
||||||
|
auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
|
||||||
|
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
|
||||||
|
auto logger = std::make_shared<async_logger>(
|
||||||
|
"async_logger", std::move(file_sink), std::move(tp), async_overflow_policy::block);
|
||||||
|
bench_mt(howmany, std::move(logger), threads);
|
||||||
|
// verify_file(filename, howmany);
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("");
|
||||||
|
spdlog::info("*********************************");
|
||||||
|
spdlog::info("Queue Overflow Policy: overrun");
|
||||||
|
spdlog::info("*********************************");
|
||||||
|
// do same test but discard oldest if queue is full instead of blocking
|
||||||
|
filename = "logs/basic_async-overrun.log";
|
||||||
|
for (int i = 0; i < iters; i++) {
|
||||||
|
auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
|
||||||
|
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
|
||||||
|
auto logger =
|
||||||
|
std::make_shared<async_logger>("async_logger", std::move(file_sink), std::move(tp),
|
||||||
|
async_overflow_policy::overrun_oldest);
|
||||||
|
bench_mt(howmany, std::move(logger), threads);
|
||||||
|
}
|
||||||
|
spdlog::shutdown();
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
std::cerr << "Error: " << ex.what() << std::endl;
|
||||||
|
perror("Last error");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_fun(std::shared_ptr<spdlog::logger> logger, int howmany) {
|
||||||
|
for (int i = 0; i < howmany; i++) {
|
||||||
|
logger->info("Hello logger: msg number {}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> logger, int thread_count) {
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
vector<std::thread> threads;
|
||||||
|
auto start = high_resolution_clock::now();
|
||||||
|
|
||||||
|
int msgs_per_thread = howmany / thread_count;
|
||||||
|
int msgs_per_thread_mod = howmany % thread_count;
|
||||||
|
for (int t = 0; t < thread_count; ++t) {
|
||||||
|
if (t == 0 && msgs_per_thread_mod)
|
||||||
|
threads.push_back(
|
||||||
|
std::thread(thread_fun, logger, msgs_per_thread + msgs_per_thread_mod));
|
||||||
|
else
|
||||||
|
threads.push_back(std::thread(thread_fun, logger, msgs_per_thread));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &t : threads) {
|
||||||
|
t.join();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto delta = high_resolution_clock::now() - start;
|
||||||
|
auto delta_d = duration_cast<duration<double>>(delta).count();
|
||||||
|
spdlog::info("Elapsed: {} secs\t {:L}/sec", delta_d, int(howmany / delta_d));
|
||||||
|
}
|
||||||
246
thirdparty/spdlog-1.13.0/bench/bench.cpp
vendored
Normal file
246
thirdparty/spdlog-1.13.0/bench/bench.cpp
vendored
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
//
|
||||||
|
// Copyright(c) 2015 Gabi Melman.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// bench.cpp : spdlog benchmarks
|
||||||
|
//
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
#include "spdlog/sinks/daily_file_sink.h"
|
||||||
|
#include "spdlog/sinks/null_sink.h"
|
||||||
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
|
||||||
|
#if defined(SPDLOG_USE_STD_FORMAT)
|
||||||
|
#include <format>
|
||||||
|
#elif defined(SPDLOG_FMT_EXTERNAL)
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#else
|
||||||
|
#include "spdlog/fmt/bundled/format.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdlib> // EXIT_FAILURE
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
void bench(int howmany, std::shared_ptr<spdlog::logger> log);
|
||||||
|
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, size_t thread_count);
|
||||||
|
|
||||||
|
// void bench_default_api(int howmany, std::shared_ptr<spdlog::logger> log);
|
||||||
|
// void bench_c_string(int howmany, std::shared_ptr<spdlog::logger> log);
|
||||||
|
|
||||||
|
static const size_t file_size = 30 * 1024 * 1024;
|
||||||
|
static const size_t rotating_files = 5;
|
||||||
|
static const int max_threads = 1000;
|
||||||
|
|
||||||
|
void bench_threaded_logging(size_t threads, int iters) {
|
||||||
|
spdlog::info("**************************************************************");
|
||||||
|
spdlog::info(spdlog::fmt_lib::format(
|
||||||
|
std::locale("en_US.UTF-8"), "Multi threaded: {:L} threads, {:L} messages", threads, iters));
|
||||||
|
spdlog::info("**************************************************************");
|
||||||
|
|
||||||
|
auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true);
|
||||||
|
bench_mt(iters, std::move(basic_mt), threads);
|
||||||
|
auto basic_mt_tracing =
|
||||||
|
spdlog::basic_logger_mt("basic_mt/backtrace-on", "logs/basic_mt.log", true);
|
||||||
|
basic_mt_tracing->enable_backtrace(32);
|
||||||
|
bench_mt(iters, std::move(basic_mt_tracing), threads);
|
||||||
|
|
||||||
|
spdlog::info("");
|
||||||
|
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size,
|
||||||
|
rotating_files);
|
||||||
|
bench_mt(iters, std::move(rotating_mt), threads);
|
||||||
|
auto rotating_mt_tracing = spdlog::rotating_logger_mt(
|
||||||
|
"rotating_mt/backtrace-on", "logs/rotating_mt.log", file_size, rotating_files);
|
||||||
|
rotating_mt_tracing->enable_backtrace(32);
|
||||||
|
bench_mt(iters, std::move(rotating_mt_tracing), threads);
|
||||||
|
|
||||||
|
spdlog::info("");
|
||||||
|
auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
|
||||||
|
bench_mt(iters, std::move(daily_mt), threads);
|
||||||
|
auto daily_mt_tracing = spdlog::daily_logger_mt("daily_mt/backtrace-on", "logs/daily_mt.log");
|
||||||
|
daily_mt_tracing->enable_backtrace(32);
|
||||||
|
bench_mt(iters, std::move(daily_mt_tracing), threads);
|
||||||
|
|
||||||
|
spdlog::info("");
|
||||||
|
auto empty_logger = std::make_shared<spdlog::logger>("level-off");
|
||||||
|
empty_logger->set_level(spdlog::level::off);
|
||||||
|
bench(iters, empty_logger);
|
||||||
|
auto empty_logger_tracing = std::make_shared<spdlog::logger>("level-off/backtrace-on");
|
||||||
|
empty_logger_tracing->set_level(spdlog::level::off);
|
||||||
|
empty_logger_tracing->enable_backtrace(32);
|
||||||
|
bench(iters, empty_logger_tracing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench_single_threaded(int iters) {
|
||||||
|
spdlog::info("**************************************************************");
|
||||||
|
spdlog::info(
|
||||||
|
spdlog::fmt_lib::format(std::locale("en_US.UTF-8"), "Single threaded: {} messages", iters));
|
||||||
|
spdlog::info("**************************************************************");
|
||||||
|
|
||||||
|
auto basic_st = spdlog::basic_logger_st("basic_st", "logs/basic_st.log", true);
|
||||||
|
bench(iters, std::move(basic_st));
|
||||||
|
|
||||||
|
auto basic_st_tracing =
|
||||||
|
spdlog::basic_logger_st("basic_st/backtrace-on", "logs/basic_st.log", true);
|
||||||
|
bench(iters, std::move(basic_st_tracing));
|
||||||
|
|
||||||
|
spdlog::info("");
|
||||||
|
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size,
|
||||||
|
rotating_files);
|
||||||
|
bench(iters, std::move(rotating_st));
|
||||||
|
auto rotating_st_tracing = spdlog::rotating_logger_st(
|
||||||
|
"rotating_st/backtrace-on", "logs/rotating_st.log", file_size, rotating_files);
|
||||||
|
rotating_st_tracing->enable_backtrace(32);
|
||||||
|
bench(iters, std::move(rotating_st_tracing));
|
||||||
|
|
||||||
|
spdlog::info("");
|
||||||
|
auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
|
||||||
|
bench(iters, std::move(daily_st));
|
||||||
|
auto daily_st_tracing = spdlog::daily_logger_st("daily_st/backtrace-on", "logs/daily_st.log");
|
||||||
|
daily_st_tracing->enable_backtrace(32);
|
||||||
|
bench(iters, std::move(daily_st_tracing));
|
||||||
|
|
||||||
|
spdlog::info("");
|
||||||
|
auto empty_logger = std::make_shared<spdlog::logger>("level-off");
|
||||||
|
empty_logger->set_level(spdlog::level::off);
|
||||||
|
bench(iters, empty_logger);
|
||||||
|
|
||||||
|
auto empty_logger_tracing = std::make_shared<spdlog::logger>("level-off/backtrace-on");
|
||||||
|
empty_logger_tracing->set_level(spdlog::level::off);
|
||||||
|
empty_logger_tracing->enable_backtrace(32);
|
||||||
|
bench(iters, empty_logger_tracing);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
spdlog::set_automatic_registration(false);
|
||||||
|
spdlog::default_logger()->set_pattern("[%^%l%$] %v");
|
||||||
|
int iters = 250000;
|
||||||
|
size_t threads = 4;
|
||||||
|
try {
|
||||||
|
if (argc > 1) {
|
||||||
|
iters = std::stoi(argv[1]);
|
||||||
|
}
|
||||||
|
if (argc > 2) {
|
||||||
|
threads = std::stoul(argv[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (threads > max_threads) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
spdlog::fmt_lib::format("Number of threads exceeds maximum({})", max_threads));
|
||||||
|
}
|
||||||
|
|
||||||
|
bench_single_threaded(iters);
|
||||||
|
bench_threaded_logging(1, iters);
|
||||||
|
bench_threaded_logging(threads, iters);
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
spdlog::error(ex.what());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench(int howmany, std::shared_ptr<spdlog::logger> log) {
|
||||||
|
using std::chrono::duration;
|
||||||
|
using std::chrono::duration_cast;
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
|
||||||
|
auto start = high_resolution_clock::now();
|
||||||
|
for (auto i = 0; i < howmany; ++i) {
|
||||||
|
log->info("Hello logger: msg number {}", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto delta = high_resolution_clock::now() - start;
|
||||||
|
auto delta_d = duration_cast<duration<double>>(delta).count();
|
||||||
|
|
||||||
|
spdlog::info(spdlog::fmt_lib::format(std::locale("en_US.UTF-8"),
|
||||||
|
"{:<30} Elapsed: {:0.2f} secs {:>16L}/sec", log->name(),
|
||||||
|
delta_d, size_t(howmany / delta_d)));
|
||||||
|
spdlog::drop(log->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, size_t thread_count) {
|
||||||
|
using std::chrono::duration;
|
||||||
|
using std::chrono::duration_cast;
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
threads.reserve(thread_count);
|
||||||
|
auto start = high_resolution_clock::now();
|
||||||
|
for (size_t t = 0; t < thread_count; ++t) {
|
||||||
|
threads.emplace_back([&]() {
|
||||||
|
for (int j = 0; j < howmany / static_cast<int>(thread_count); j++) {
|
||||||
|
log->info("Hello logger: msg number {}", j);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &t : threads) {
|
||||||
|
t.join();
|
||||||
|
};
|
||||||
|
|
||||||
|
auto delta = high_resolution_clock::now() - start;
|
||||||
|
auto delta_d = duration_cast<duration<double>>(delta).count();
|
||||||
|
spdlog::info(spdlog::fmt_lib::format(std::locale("en_US.UTF-8"),
|
||||||
|
"{:<30} Elapsed: {:0.2f} secs {:>16L}/sec", log->name(),
|
||||||
|
delta_d, size_t(howmany / delta_d)));
|
||||||
|
spdlog::drop(log->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void bench_default_api(int howmany, std::shared_ptr<spdlog::logger> log)
|
||||||
|
{
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
using std::chrono::duration;
|
||||||
|
using std::chrono::duration_cast;
|
||||||
|
|
||||||
|
auto orig_default = spdlog::default_logger();
|
||||||
|
spdlog::set_default_logger(log);
|
||||||
|
auto start = high_resolution_clock::now();
|
||||||
|
for (auto i = 0; i < howmany; ++i)
|
||||||
|
{
|
||||||
|
spdlog::info("Hello logger: msg number {}", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto delta = high_resolution_clock::now() - start;
|
||||||
|
auto delta_d = duration_cast<duration<double>>(delta).count();
|
||||||
|
spdlog::drop(log->name());
|
||||||
|
spdlog::set_default_logger(std::move(orig_default));
|
||||||
|
spdlog::info("{:<30} Elapsed: {:0.2f} secs {:>16}/sec", log->name(), delta_d, int(howmany /
|
||||||
|
delta_d));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench_c_string(int howmany, std::shared_ptr<spdlog::logger> log)
|
||||||
|
{
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
using std::chrono::duration;
|
||||||
|
using std::chrono::duration_cast;
|
||||||
|
|
||||||
|
const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra
|
||||||
|
metus cursus " "lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus
|
||||||
|
volutpat mi, eu consequat sem " "libero nec massa. In dapibus ipsum a diam rhoncus gravida. Etiam
|
||||||
|
non dapibus eros. Donec fringilla dui sed " "augue pretium, nec scelerisque est maximus. Nullam
|
||||||
|
convallis, sem nec blandit maximus, nisi turpis ornare " "nisl, sit amet volutpat neque massa eu
|
||||||
|
odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis.";
|
||||||
|
|
||||||
|
auto orig_default = spdlog::default_logger();
|
||||||
|
spdlog::set_default_logger(log);
|
||||||
|
auto start = high_resolution_clock::now();
|
||||||
|
for (auto i = 0; i < howmany; ++i)
|
||||||
|
{
|
||||||
|
spdlog::log(spdlog::level::info, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto delta = high_resolution_clock::now() - start;
|
||||||
|
auto delta_d = duration_cast<duration<double>>(delta).count();
|
||||||
|
spdlog::drop(log->name());
|
||||||
|
spdlog::set_default_logger(std::move(orig_default));
|
||||||
|
spdlog::info("{:<30} Elapsed: {:0.2f} secs {:>16}/sec", log->name(), delta_d, int(howmany /
|
||||||
|
delta_d));
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
71
thirdparty/spdlog-1.13.0/bench/formatter-bench.cpp
vendored
Normal file
71
thirdparty/spdlog-1.13.0/bench/formatter-bench.cpp
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// Copyright(c) 2018 Gabi Melman.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "benchmark/benchmark.h"
|
||||||
|
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/pattern_formatter.h"
|
||||||
|
|
||||||
|
void bench_formatter(benchmark::State &state, std::string pattern) {
|
||||||
|
auto formatter = spdlog::details::make_unique<spdlog::pattern_formatter>(pattern);
|
||||||
|
spdlog::memory_buf_t dest;
|
||||||
|
std::string logger_name = "logger-name";
|
||||||
|
const char *text =
|
||||||
|
"Hello. This is some message with length of 80 ";
|
||||||
|
|
||||||
|
spdlog::source_loc source_loc{"a/b/c/d/myfile.cpp", 123, "some_func()"};
|
||||||
|
spdlog::details::log_msg msg(source_loc, logger_name, spdlog::level::info, text);
|
||||||
|
|
||||||
|
for (auto _ : state) {
|
||||||
|
dest.clear();
|
||||||
|
formatter->format(msg, dest);
|
||||||
|
benchmark::DoNotOptimize(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench_formatters() {
|
||||||
|
// basic patterns(single flag)
|
||||||
|
std::string all_flags = "+vtPnlLaAbBcCYDmdHIMSefFprRTXzEisg@luioO%";
|
||||||
|
std::vector<std::string> basic_patterns;
|
||||||
|
for (auto &flag : all_flags) {
|
||||||
|
auto pattern = std::string("%") + flag;
|
||||||
|
benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern);
|
||||||
|
|
||||||
|
// pattern = std::string("%16") + flag;
|
||||||
|
// benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern);
|
||||||
|
//
|
||||||
|
// // bench center padding
|
||||||
|
// pattern = std::string("%=16") + flag;
|
||||||
|
// benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
// complex patterns
|
||||||
|
std::vector<std::string> patterns = {
|
||||||
|
"[%D %X] [%l] [%n] %v",
|
||||||
|
"[%Y-%m-%d %H:%M:%S.%e] [%l] [%n] %v",
|
||||||
|
"[%Y-%m-%d %H:%M:%S.%e] [%l] [%n] [%t] %v",
|
||||||
|
};
|
||||||
|
for (auto &pattern : patterns) {
|
||||||
|
benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern)
|
||||||
|
->Iterations(2500000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
spdlog::set_pattern("[%^%l%$] %v");
|
||||||
|
if (argc != 2) {
|
||||||
|
spdlog::error("Usage: {} <pattern> (or \"all\" to bench all)", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string pattern = argv[1];
|
||||||
|
if (pattern == "all") {
|
||||||
|
bench_formatters();
|
||||||
|
} else {
|
||||||
|
benchmark::RegisterBenchmark(pattern.c_str(), &bench_formatter, pattern);
|
||||||
|
}
|
||||||
|
benchmark::Initialize(&argc, argv);
|
||||||
|
benchmark::RunSpecifiedBenchmarks();
|
||||||
|
}
|
||||||
220
thirdparty/spdlog-1.13.0/bench/latency.cpp
vendored
Normal file
220
thirdparty/spdlog-1.13.0/bench/latency.cpp
vendored
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
//
|
||||||
|
// Copyright(c) 2018 Gabi Melman.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// latency.cpp : spdlog latency benchmarks
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "benchmark/benchmark.h"
|
||||||
|
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/async.h"
|
||||||
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
#include "spdlog/sinks/daily_file_sink.h"
|
||||||
|
#include "spdlog/sinks/null_sink.h"
|
||||||
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
|
||||||
|
void bench_c_string(benchmark::State &state, std::shared_ptr<spdlog::logger> logger) {
|
||||||
|
const char *msg =
|
||||||
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus "
|
||||||
|
"lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus volutpat mi, "
|
||||||
|
"eu consequat sem "
|
||||||
|
"libero nec massa. In dapibus ipsum a diam rhoncus gravida. Etiam non dapibus eros. Donec "
|
||||||
|
"fringilla dui sed "
|
||||||
|
"augue pretium, nec scelerisque est maximus. Nullam convallis, sem nec blandit maximus, "
|
||||||
|
"nisi turpis ornare "
|
||||||
|
"nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue "
|
||||||
|
"nibh turpis duis.";
|
||||||
|
|
||||||
|
for (auto _ : state) {
|
||||||
|
logger->info(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench_logger(benchmark::State &state, std::shared_ptr<spdlog::logger> logger) {
|
||||||
|
int i = 0;
|
||||||
|
for (auto _ : state) {
|
||||||
|
logger->info("Hello logger: msg number {}...............", ++i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void bench_global_logger(benchmark::State &state, std::shared_ptr<spdlog::logger> logger) {
|
||||||
|
spdlog::set_default_logger(std::move(logger));
|
||||||
|
int i = 0;
|
||||||
|
for (auto _ : state) {
|
||||||
|
spdlog::info("Hello logger: msg number {}...............", ++i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench_disabled_macro(benchmark::State &state, std::shared_ptr<spdlog::logger> logger) {
|
||||||
|
int i = 0;
|
||||||
|
benchmark::DoNotOptimize(i); // prevent unused warnings
|
||||||
|
benchmark::DoNotOptimize(logger); // prevent unused warnings
|
||||||
|
for (auto _ : state) {
|
||||||
|
SPDLOG_LOGGER_DEBUG(logger, "Hello logger: msg number {}...............", i++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bench_disabled_macro_global_logger(benchmark::State &state,
|
||||||
|
std::shared_ptr<spdlog::logger> logger) {
|
||||||
|
spdlog::set_default_logger(std::move(logger));
|
||||||
|
int i = 0;
|
||||||
|
benchmark::DoNotOptimize(i); // prevent unused warnings
|
||||||
|
benchmark::DoNotOptimize(logger); // prevent unused warnings
|
||||||
|
for (auto _ : state) {
|
||||||
|
SPDLOG_DEBUG("Hello logger: msg number {}...............", i++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
void bench_dev_null() {
|
||||||
|
auto dev_null_st = spdlog::basic_logger_st("/dev/null_st", "/dev/null");
|
||||||
|
benchmark::RegisterBenchmark("/dev/null_st", bench_logger, std::move(dev_null_st))
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("/dev/null_st");
|
||||||
|
|
||||||
|
auto dev_null_mt = spdlog::basic_logger_mt("/dev/null_mt", "/dev/null");
|
||||||
|
benchmark::RegisterBenchmark("/dev/null_mt", bench_logger, std::move(dev_null_mt))
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("/dev/null_mt");
|
||||||
|
}
|
||||||
|
#endif // __linux__
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
using spdlog::sinks::null_sink_mt;
|
||||||
|
using spdlog::sinks::null_sink_st;
|
||||||
|
|
||||||
|
size_t file_size = 30 * 1024 * 1024;
|
||||||
|
size_t rotating_files = 5;
|
||||||
|
int n_threads = benchmark::CPUInfo::Get().num_cpus;
|
||||||
|
|
||||||
|
auto full_bench = argc > 1 && std::string(argv[1]) == "full";
|
||||||
|
|
||||||
|
// disabled loggers
|
||||||
|
auto disabled_logger =
|
||||||
|
std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
|
||||||
|
disabled_logger->set_level(spdlog::level::off);
|
||||||
|
benchmark::RegisterBenchmark("disabled-at-compile-time", bench_disabled_macro, disabled_logger);
|
||||||
|
benchmark::RegisterBenchmark("disabled-at-compile-time (global logger)",
|
||||||
|
bench_disabled_macro_global_logger, disabled_logger);
|
||||||
|
benchmark::RegisterBenchmark("disabled-at-runtime", bench_logger, disabled_logger);
|
||||||
|
benchmark::RegisterBenchmark("disabled-at-runtime (global logger)", bench_global_logger,
|
||||||
|
disabled_logger);
|
||||||
|
// with backtrace of 64
|
||||||
|
auto tracing_disabled_logger =
|
||||||
|
std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
|
||||||
|
tracing_disabled_logger->enable_backtrace(64);
|
||||||
|
benchmark::RegisterBenchmark("disabled-at-runtime/backtrace", bench_logger,
|
||||||
|
tracing_disabled_logger);
|
||||||
|
|
||||||
|
auto null_logger_st =
|
||||||
|
std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>());
|
||||||
|
benchmark::RegisterBenchmark("null_sink_st (500_bytes c_str)", bench_c_string,
|
||||||
|
std::move(null_logger_st));
|
||||||
|
benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger_st);
|
||||||
|
benchmark::RegisterBenchmark("null_sink_st (global logger)", bench_global_logger,
|
||||||
|
null_logger_st);
|
||||||
|
// with backtrace of 64
|
||||||
|
auto tracing_null_logger_st =
|
||||||
|
std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>());
|
||||||
|
tracing_null_logger_st->enable_backtrace(64);
|
||||||
|
benchmark::RegisterBenchmark("null_sink_st/backtrace", bench_logger, tracing_null_logger_st);
|
||||||
|
|
||||||
|
#ifdef __linux
|
||||||
|
bench_dev_null();
|
||||||
|
#endif // __linux__
|
||||||
|
|
||||||
|
if (full_bench) {
|
||||||
|
// basic_st
|
||||||
|
auto basic_st = spdlog::basic_logger_st("basic_st", "latency_logs/basic_st.log", true);
|
||||||
|
benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st))->UseRealTime();
|
||||||
|
spdlog::drop("basic_st");
|
||||||
|
// with backtrace of 64
|
||||||
|
auto tracing_basic_st =
|
||||||
|
spdlog::basic_logger_st("tracing_basic_st", "latency_logs/tracing_basic_st.log", true);
|
||||||
|
tracing_basic_st->enable_backtrace(64);
|
||||||
|
benchmark::RegisterBenchmark("basic_st/backtrace", bench_logger,
|
||||||
|
std::move(tracing_basic_st))
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("tracing_basic_st");
|
||||||
|
|
||||||
|
// rotating st
|
||||||
|
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "latency_logs/rotating_st.log",
|
||||||
|
file_size, rotating_files);
|
||||||
|
benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st))
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("rotating_st");
|
||||||
|
// with backtrace of 64
|
||||||
|
auto tracing_rotating_st = spdlog::rotating_logger_st(
|
||||||
|
"tracing_rotating_st", "latency_logs/tracing_rotating_st.log", file_size,
|
||||||
|
rotating_files);
|
||||||
|
benchmark::RegisterBenchmark("rotating_st/backtrace", bench_logger,
|
||||||
|
std::move(tracing_rotating_st))
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("tracing_rotating_st");
|
||||||
|
|
||||||
|
// daily st
|
||||||
|
auto daily_st = spdlog::daily_logger_mt("daily_st", "latency_logs/daily_st.log");
|
||||||
|
benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st))->UseRealTime();
|
||||||
|
spdlog::drop("daily_st");
|
||||||
|
auto tracing_daily_st =
|
||||||
|
spdlog::daily_logger_mt("tracing_daily_st", "latency_logs/daily_st.log");
|
||||||
|
benchmark::RegisterBenchmark("daily_st/backtrace", bench_logger,
|
||||||
|
std::move(tracing_daily_st))
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("tracing_daily_st");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Multi threaded bench, 10 loggers using same logger concurrently
|
||||||
|
//
|
||||||
|
auto null_logger_mt =
|
||||||
|
std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
|
||||||
|
benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)
|
||||||
|
->Threads(n_threads)
|
||||||
|
->UseRealTime();
|
||||||
|
|
||||||
|
// basic_mt
|
||||||
|
auto basic_mt = spdlog::basic_logger_mt("basic_mt", "latency_logs/basic_mt.log", true);
|
||||||
|
benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))
|
||||||
|
->Threads(n_threads)
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("basic_mt");
|
||||||
|
|
||||||
|
// rotating mt
|
||||||
|
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "latency_logs/rotating_mt.log",
|
||||||
|
file_size, rotating_files);
|
||||||
|
benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))
|
||||||
|
->Threads(n_threads)
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("rotating_mt");
|
||||||
|
|
||||||
|
// daily mt
|
||||||
|
auto daily_mt = spdlog::daily_logger_mt("daily_mt", "latency_logs/daily_mt.log");
|
||||||
|
benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))
|
||||||
|
->Threads(n_threads)
|
||||||
|
->UseRealTime();
|
||||||
|
spdlog::drop("daily_mt");
|
||||||
|
}
|
||||||
|
|
||||||
|
// async
|
||||||
|
auto queue_size = 1024 * 1024 * 3;
|
||||||
|
auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
|
||||||
|
auto async_logger = std::make_shared<spdlog::async_logger>(
|
||||||
|
"async_logger", std::make_shared<null_sink_mt>(), std::move(tp),
|
||||||
|
spdlog::async_overflow_policy::overrun_oldest);
|
||||||
|
benchmark::RegisterBenchmark("async_logger", bench_logger, async_logger)
|
||||||
|
->Threads(n_threads)
|
||||||
|
->UseRealTime();
|
||||||
|
|
||||||
|
auto async_logger_tracing = std::make_shared<spdlog::async_logger>(
|
||||||
|
"async_logger_tracing", std::make_shared<null_sink_mt>(), std::move(tp),
|
||||||
|
spdlog::async_overflow_policy::overrun_oldest);
|
||||||
|
async_logger_tracing->enable_backtrace(32);
|
||||||
|
benchmark::RegisterBenchmark("async_logger/tracing", bench_logger, async_logger_tracing)
|
||||||
|
->Threads(n_threads)
|
||||||
|
->UseRealTime();
|
||||||
|
|
||||||
|
benchmark::Initialize(&argc, argv);
|
||||||
|
benchmark::RunSpecifiedBenchmarks();
|
||||||
|
}
|
||||||
32
thirdparty/spdlog-1.13.0/bench/utils.h
vendored
Normal file
32
thirdparty/spdlog-1.13.0/bench/utils.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// Copyright(c) 2015 Gabi Melman.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <locale>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::string format(const T &value) {
|
||||||
|
static std::locale loc("");
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.imbue(loc);
|
||||||
|
ss << value;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline std::string format(const double &value) {
|
||||||
|
static std::locale loc("");
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.imbue(loc);
|
||||||
|
ss << std::fixed << std::setprecision(1) << value;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
18
thirdparty/spdlog-1.13.0/cmake/ide.cmake
vendored
Normal file
18
thirdparty/spdlog-1.13.0/cmake/ide.cmake
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# IDE support for headers
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
set(SPDLOG_HEADERS_DIR "${CMAKE_CURRENT_LIST_DIR}/../include")
|
||||||
|
|
||||||
|
file(GLOB SPDLOG_TOP_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/*.h")
|
||||||
|
file(GLOB SPDLOG_DETAILS_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/details/*.h")
|
||||||
|
file(GLOB SPDLOG_SINKS_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/sinks/*.h")
|
||||||
|
file(GLOB SPDLOG_FMT_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/fmt/*.h")
|
||||||
|
file(GLOB SPDLOG_FMT_BUNDELED_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/fmt/bundled/*.h")
|
||||||
|
set(SPDLOG_ALL_HEADERS ${SPDLOG_TOP_HEADERS} ${SPDLOG_DETAILS_HEADERS} ${SPDLOG_SINKS_HEADERS} ${SPDLOG_FMT_HEADERS}
|
||||||
|
${SPDLOG_FMT_BUNDELED_HEADERS})
|
||||||
|
|
||||||
|
source_group("Header Files\\spdlog" FILES ${SPDLOG_TOP_HEADERS})
|
||||||
|
source_group("Header Files\\spdlog\\details" FILES ${SPDLOG_DETAILS_HEADERS})
|
||||||
|
source_group("Header Files\\spdlog\\sinks" FILES ${SPDLOG_SINKS_HEADERS})
|
||||||
|
source_group("Header Files\\spdlog\\fmt" FILES ${SPDLOG_FMT_HEADERS})
|
||||||
|
source_group("Header Files\\spdlog\\fmt\\bundled\\" FILES ${SPDLOG_FMT_BUNDELED_HEADERS})
|
||||||
258
thirdparty/spdlog-1.13.0/cmake/pch.h.in
vendored
Normal file
258
thirdparty/spdlog-1.13.0/cmake/pch.h.in
vendored
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// fmt/bin_to_hex.h
|
||||||
|
// fmt/bundled/format-inl.h
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
// details/file_helper-inl.h
|
||||||
|
// details/os-inl.h
|
||||||
|
// fmt/bundled/core.h
|
||||||
|
// fmt/bundled/posix.h
|
||||||
|
// logger-inl.h
|
||||||
|
// sinks/daily_file_sink.h
|
||||||
|
// sinks/stdout_sinks.h
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
// details/os-inl.h
|
||||||
|
// fmt/bundled/posix.h
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
// details/os-inl.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// fmt/bundled/core.h
|
||||||
|
// fmt/bundled/format-inl.h
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
// details/os-inl.h
|
||||||
|
// details/os.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// details/pattern_formatter.h
|
||||||
|
// fmt/bundled/chrono.h
|
||||||
|
// sinks/daily_file_sink.h
|
||||||
|
// sinks/rotating_file_sink-inl.h
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
// fmt/bundled/format-inl.h
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
// fmt/bundled/format-inl.h
|
||||||
|
#include <cwchar>
|
||||||
|
|
||||||
|
// fmt/bundled/format-inl.h
|
||||||
|
// fmt/bundled/format.h
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
// fmt/bundled/format-inl.h
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
// details/file_helper-inl.h
|
||||||
|
// fmt/bundled/format.h
|
||||||
|
// fmt/bundled/posix.h
|
||||||
|
// sinks/rotating_file_sink-inl.h
|
||||||
|
#include <cerrno>
|
||||||
|
|
||||||
|
// details/circular_q.h
|
||||||
|
// details/thread_pool-inl.h
|
||||||
|
// fmt/bundled/format-inl.h
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// async_logger-inl.h
|
||||||
|
// cfg/helpers-inl.h
|
||||||
|
// log_levels.h
|
||||||
|
// common.h
|
||||||
|
// details/file_helper-inl.h
|
||||||
|
// details/log_msg.h
|
||||||
|
// details/os-inl.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// details/pattern_formatter.h
|
||||||
|
// details/registry-inl.h
|
||||||
|
// details/registry.h
|
||||||
|
// details/tcp_client-windows.h
|
||||||
|
// details/tcp_client.h
|
||||||
|
// fmt/bundled/core.h
|
||||||
|
// sinks/android_sink.h
|
||||||
|
// sinks/ansicolor_sink.h
|
||||||
|
// sinks/basic_file_sink.h
|
||||||
|
// sinks/daily_file_sink.h
|
||||||
|
// sinks/dup_filter_sink.h
|
||||||
|
// sinks/msvc_sink.h
|
||||||
|
// sinks/ringbuffer_sink.h
|
||||||
|
// sinks/rotating_file_sink-inl.h
|
||||||
|
// sinks/rotating_file_sink.h
|
||||||
|
// sinks/syslog_sink.h
|
||||||
|
// sinks/tcp_sink.h
|
||||||
|
// sinks/win_eventlog_sink.h
|
||||||
|
// sinks/wincolor_sink.h
|
||||||
|
// spdlog.h:
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// cfg/helpers-inl.h
|
||||||
|
// fmt/bundled/chrono.h
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// fmt/bundled/ostream.h
|
||||||
|
// sinks/ostream_sink.h
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
// cfg/log_levels.h
|
||||||
|
// details/registry-inl.h
|
||||||
|
// details/registry.h
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// details/circular_q.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// details/pattern_formatter.h
|
||||||
|
// details/thread_pool.h
|
||||||
|
// fmt/bundled/compile.h
|
||||||
|
// logger.h
|
||||||
|
// sinks/dist_sink.h
|
||||||
|
// sinks/ringbuffer_sink.h
|
||||||
|
// sinks/win_eventlog_sink.h
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// details/os-inl.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// sinks/ansicolor_sink.h
|
||||||
|
// sinks/syslog_sink.h
|
||||||
|
// sinks/systemd_sink.h
|
||||||
|
// sinks/wincolor_sink.h
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
// details/file_helper-inl.h
|
||||||
|
// details/file_helper.h
|
||||||
|
// sinks/rotating_file_sink-inl.h
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
// details/os-inl.h
|
||||||
|
// fmt/bundled/format.h
|
||||||
|
// fmt/bundled/printf.h
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
// common.h
|
||||||
|
// details/backtracer.h
|
||||||
|
// details/null_mutex.h
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
// common.h
|
||||||
|
// details/backtracer.h
|
||||||
|
// details/null_mutex.h
|
||||||
|
#include <locale>
|
||||||
|
|
||||||
|
// common.h
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
|
// common.h
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
// common.h
|
||||||
|
// details/fmt_helper.h
|
||||||
|
// fmt/bundled/core.h
|
||||||
|
// fmt/bundled/ranges.h
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
// cfg/helpers-inl.h
|
||||||
|
// details/null_mutex.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
// async.h
|
||||||
|
// async_logger-inl.h
|
||||||
|
// common.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// details/pattern_formatter.h
|
||||||
|
// details/registry-inl.h
|
||||||
|
// details/registry.h
|
||||||
|
// details/thread_pool.h
|
||||||
|
// fmt/bundled/format.h
|
||||||
|
// sinks/ansicolor_sink.h
|
||||||
|
// sinks/base_sink-inl.h
|
||||||
|
// sinks/dist_sink.h
|
||||||
|
// sinks/stdout_sinks-inl.h
|
||||||
|
// sinks/wincolor_sink.h
|
||||||
|
// spdlog.h
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
// async.h
|
||||||
|
// common.h
|
||||||
|
// details/backtracer.h
|
||||||
|
// details/periodic_worker.h
|
||||||
|
// details/registry-inl.h
|
||||||
|
// details/registry.h
|
||||||
|
// details/thread_pool.h
|
||||||
|
// sinks/tcp_sink.h
|
||||||
|
// spdlog.h
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
// details/mpmc_blocking_q.h
|
||||||
|
// details/periodic_worker.h
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
// details/os-inl.h
|
||||||
|
// fmt/bundled/format.h
|
||||||
|
// fmt/bundled/printf.h
|
||||||
|
// sinks/dist_sink.h
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// common.h
|
||||||
|
// details/file_helper-inl.h
|
||||||
|
// details/fmt_helper.h
|
||||||
|
// details/os-inl.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// details/pattern_formatter.h
|
||||||
|
// details/periodic_worker.h
|
||||||
|
// details/registry-inl.h
|
||||||
|
// details/registry.h
|
||||||
|
// details/thread_pool.h
|
||||||
|
// fmt/bundled/chrono.h
|
||||||
|
// sinks/android_sink.h
|
||||||
|
// sinks/daily_file_sink.h
|
||||||
|
// sinks/dup_filter_sink.h
|
||||||
|
// sinks/rotating_file_sink-inl.h
|
||||||
|
// sinks/rotating_file_sink.h
|
||||||
|
// sinks/tcp_sink.h
|
||||||
|
// spdlog.h
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
// details/file_helper-inl.h
|
||||||
|
// details/os-inl.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// details/periodic_worker.h
|
||||||
|
// details/thread_pool.h
|
||||||
|
// sinks/android_sink.h
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
// async.h
|
||||||
|
// details/backtracer.h
|
||||||
|
// details/console_globals.h
|
||||||
|
// details/mpmc_blocking_q.h
|
||||||
|
// details/pattern_formatter-inl.h
|
||||||
|
// details/periodic_worker.h
|
||||||
|
// details/registry.h
|
||||||
|
// sinks/android_sink.h
|
||||||
|
// sinks/ansicolor_sink.h
|
||||||
|
// sinks/basic_file_sink.h
|
||||||
|
// sinks/daily_file_sink.h
|
||||||
|
// sinks/dist_sink.h
|
||||||
|
// sinks/dup_filter_sink.h
|
||||||
|
// sinks/msvc_sink.h
|
||||||
|
// sinks/null_sink.h
|
||||||
|
// sinks/ostream_sink.h
|
||||||
|
// sinks/ringbuffer_sink.h
|
||||||
|
// sinks/rotating_file_sink-inl.h
|
||||||
|
// sinks/rotating_file_sink.h
|
||||||
|
// sinks/tcp_sink.h
|
||||||
|
// sinks/win_eventlog_sink.h
|
||||||
|
// sinks/wincolor_sink.h
|
||||||
|
//
|
||||||
|
// color_sinks.cpp
|
||||||
|
// file_sinks.cpp
|
||||||
|
// spdlog.cpp
|
||||||
|
// stdout_sinks.cpp
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
// spdlog
|
||||||
|
#include <spdlog/common.h>
|
||||||
13
thirdparty/spdlog-1.13.0/cmake/spdlog.pc.in
vendored
Normal file
13
thirdparty/spdlog-1.13.0/cmake/spdlog.pc.in
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
includedir=@PKG_CONFIG_INCLUDEDIR@
|
||||||
|
libdir=@PKG_CONFIG_LIBDIR@
|
||||||
|
|
||||||
|
Name: lib@PROJECT_NAME@
|
||||||
|
Description: Fast C++ logging library.
|
||||||
|
URL: https://github.com/gabime/@PROJECT_NAME@
|
||||||
|
Version: @SPDLOG_VERSION@
|
||||||
|
CFlags: -I${includedir} @PKG_CONFIG_DEFINES@
|
||||||
|
Libs: -L${libdir} -lspdlog -pthread
|
||||||
|
Requires: @PKG_CONFIG_REQUIRES@
|
||||||
|
|
||||||
60
thirdparty/spdlog-1.13.0/cmake/spdlogCPack.cmake
vendored
Normal file
60
thirdparty/spdlog-1.13.0/cmake/spdlogCPack.cmake
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
set(CPACK_GENERATOR "TGZ;ZIP" CACHE STRING "Semicolon separated list of generators")
|
||||||
|
|
||||||
|
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
|
||||||
|
set(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_BINARY_DIR}" "${PROJECT_NAME}" ALL .)
|
||||||
|
|
||||||
|
set(CPACK_PROJECT_URL "https://github.com/gabime/spdlog")
|
||||||
|
set(CPACK_PACKAGE_VENDOR "Gabi Melman")
|
||||||
|
set(CPACK_PACKAGE_CONTACT "Gabi Melman <gmelman1@gmail.com>")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Fast C++ logging library")
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
||||||
|
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
|
||||||
|
if(PROJECT_VERSION_TWEAK)
|
||||||
|
set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}.${PROJECT_VERSION_TWEAK})
|
||||||
|
endif()
|
||||||
|
set(CPACK_PACKAGE_RELOCATABLE ON CACHE BOOL "Build relocatable package")
|
||||||
|
|
||||||
|
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||||
|
set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_SECTION "libs")
|
||||||
|
set(CPACK_RPM_PACKAGE_URL ${CPACK_PROJECT_URL})
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${CPACK_PROJECT_URL})
|
||||||
|
set(CPACK_RPM_PACKAGE_DESCRIPTION "Very fast, header-only/compiled, C++ logging library.")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Very fast, header-only/compiled, C++ logging library.")
|
||||||
|
|
||||||
|
if(CPACK_PACKAGE_NAME)
|
||||||
|
set(CPACK_RPM_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
set(CPACK_DEBIAN_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
else()
|
||||||
|
set(CPACK_RPM_FILE_NAME "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
set(CPACK_DEBIAN_FILE_NAME "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
set(CPACK_RPM_PACKAGE_NAME "${PROJECT_NAME}")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_NAME "${PROJECT_NAME}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CPACK_RPM_PACKAGE_RELEASE)
|
||||||
|
set(CPACK_RPM_FILE_NAME "${CPACK_RPM_FILE_NAME}-${CPACK_RPM_PACKAGE_RELEASE}")
|
||||||
|
endif()
|
||||||
|
if(CPACK_DEBIAN_PACKAGE_RELEASE)
|
||||||
|
set(CPACK_DEBIAN_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}-${CPACK_DEBIAN_PACKAGE_RELEASE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CPACK_RPM_PACKAGE_ARCHITECTURE)
|
||||||
|
set(CPACK_RPM_FILE_NAME "${CPACK_RPM_FILE_NAME}.${CPACK_RPM_PACKAGE_ARCHITECTURE}")
|
||||||
|
endif()
|
||||||
|
if(CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
|
||||||
|
set(CPACK_DEBIAN_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}.${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||||
|
endif()
|
||||||
|
set(CPACK_RPM_FILE_NAME "${CPACK_RPM_FILE_NAME}.rpm")
|
||||||
|
set(CPACK_DEBIAN_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}.deb")
|
||||||
|
|
||||||
|
if(NOT CPACK_PACKAGE_RELOCATABLE)
|
||||||
|
# Depend on pkgconfig rpm to create the system pkgconfig folder
|
||||||
|
set(CPACK_RPM_PACKAGE_REQUIRES pkgconfig)
|
||||||
|
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
|
||||||
|
"${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CPack)
|
||||||
20
thirdparty/spdlog-1.13.0/cmake/spdlogConfig.cmake.in
vendored
Normal file
20
thirdparty/spdlog-1.13.0/cmake/spdlogConfig.cmake.in
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Copyright(c) 2019 spdlog authors
|
||||||
|
# Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
set(SPDLOG_FMT_EXTERNAL @SPDLOG_FMT_EXTERNAL@)
|
||||||
|
set(SPDLOG_FMT_EXTERNAL_HO @SPDLOG_FMT_EXTERNAL_HO@)
|
||||||
|
set(config_targets_file @config_targets_file@)
|
||||||
|
|
||||||
|
if(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)
|
||||||
|
include(CMakeFindDependencyMacro)
|
||||||
|
find_dependency(fmt CONFIG)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/${config_targets_file}")
|
||||||
|
|
||||||
|
check_required_components(spdlog)
|
||||||
62
thirdparty/spdlog-1.13.0/cmake/utils.cmake
vendored
Normal file
62
thirdparty/spdlog-1.13.0/cmake/utils.cmake
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Get spdlog version from include/spdlog/version.h and put it in SPDLOG_VERSION
|
||||||
|
function(spdlog_extract_version)
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/include/spdlog/version.h" file_contents)
|
||||||
|
string(REGEX MATCH "SPDLOG_VER_MAJOR ([0-9]+)" _ "${file_contents}")
|
||||||
|
if(NOT CMAKE_MATCH_COUNT EQUAL 1)
|
||||||
|
message(FATAL_ERROR "Could not extract major version number from spdlog/version.h")
|
||||||
|
endif()
|
||||||
|
set(ver_major ${CMAKE_MATCH_1})
|
||||||
|
|
||||||
|
string(REGEX MATCH "SPDLOG_VER_MINOR ([0-9]+)" _ "${file_contents}")
|
||||||
|
if(NOT CMAKE_MATCH_COUNT EQUAL 1)
|
||||||
|
message(FATAL_ERROR "Could not extract minor version number from spdlog/version.h")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(ver_minor ${CMAKE_MATCH_1})
|
||||||
|
string(REGEX MATCH "SPDLOG_VER_PATCH ([0-9]+)" _ "${file_contents}")
|
||||||
|
if(NOT CMAKE_MATCH_COUNT EQUAL 1)
|
||||||
|
message(FATAL_ERROR "Could not extract patch version number from spdlog/version.h")
|
||||||
|
endif()
|
||||||
|
set(ver_patch ${CMAKE_MATCH_1})
|
||||||
|
|
||||||
|
set(SPDLOG_VERSION_MAJOR ${ver_major} PARENT_SCOPE)
|
||||||
|
set(SPDLOG_VERSION_MINOR ${ver_minor} PARENT_SCOPE)
|
||||||
|
set(SPDLOG_VERSION_PATCH ${ver_patch} PARENT_SCOPE)
|
||||||
|
set(SPDLOG_VERSION "${ver_major}.${ver_minor}.${ver_patch}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Turn on warnings on the given target
|
||||||
|
function(spdlog_enable_warnings target_name)
|
||||||
|
if(SPDLOG_BUILD_WARNINGS)
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
list(APPEND MSVC_OPTIONS "/W3")
|
||||||
|
if(MSVC_VERSION GREATER 1900) # Allow non fatal security warnings for msvc 2015
|
||||||
|
list(APPEND MSVC_OPTIONS "/WX")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_options(
|
||||||
|
${target_name}
|
||||||
|
PRIVATE $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
|
||||||
|
-Wall
|
||||||
|
-Wextra
|
||||||
|
-Wconversion
|
||||||
|
-pedantic
|
||||||
|
-Werror
|
||||||
|
-Wfatal-errors>
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:${MSVC_OPTIONS}>)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Enable address sanitizer (gcc/clang only)
|
||||||
|
function(spdlog_enable_sanitizer target_name)
|
||||||
|
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
|
message(FATAL_ERROR "Sanitizer supported only for gcc/clang")
|
||||||
|
endif()
|
||||||
|
message(STATUS "Address sanitizer enabled")
|
||||||
|
target_compile_options(${target_name} PRIVATE -fsanitize=address,undefined)
|
||||||
|
target_compile_options(${target_name} PRIVATE -fno-sanitize=signed-integer-overflow)
|
||||||
|
target_compile_options(${target_name} PRIVATE -fno-sanitize-recover=all)
|
||||||
|
target_compile_options(${target_name} PRIVATE -fno-omit-frame-pointer)
|
||||||
|
target_link_libraries(${target_name} PRIVATE -fsanitize=address,undefined -fuse-ld=gold)
|
||||||
|
endfunction()
|
||||||
42
thirdparty/spdlog-1.13.0/cmake/version.rc.in
vendored
Normal file
42
thirdparty/spdlog-1.13.0/cmake/version.rc.in
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#include <windows.h>
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION @SPDLOG_VERSION_MAJOR@,@SPDLOG_VERSION_MINOR@,@SPDLOG_VERSION_PATCH@,0
|
||||||
|
PRODUCTVERSION @SPDLOG_VERSION_MAJOR@,@SPDLOG_VERSION_MINOR@,@SPDLOG_VERSION_PATCH@,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "FileDescription", "spdlog dll\0"
|
||||||
|
VALUE "FileVersion", "@SPDLOG_VERSION@.0\0"
|
||||||
|
VALUE "InternalName", "spdlog.dll\0"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) spdlog\0"
|
||||||
|
VALUE "ProductName", "spdlog\0"
|
||||||
|
VALUE "ProductVersion", "@SPDLOG_VERSION@.0\0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
23
thirdparty/spdlog-1.13.0/example/CMakeLists.txt
vendored
Normal file
23
thirdparty/spdlog-1.13.0/example/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Copyright(c) 2019 spdlog authors Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.11)
|
||||||
|
project(spdlog_examples CXX)
|
||||||
|
|
||||||
|
if(NOT TARGET spdlog)
|
||||||
|
# Stand-alone build
|
||||||
|
find_package(spdlog REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Example of using pre-compiled library
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
add_executable(example example.cpp)
|
||||||
|
target_link_libraries(example PRIVATE spdlog::spdlog $<$<BOOL:${MINGW}>:ws2_32>)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
# Example of using header-only library
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
if(SPDLOG_BUILD_EXAMPLE_HO)
|
||||||
|
add_executable(example_header_only example.cpp)
|
||||||
|
target_link_libraries(example_header_only PRIVATE spdlog::spdlog_header_only)
|
||||||
|
endif()
|
||||||
378
thirdparty/spdlog-1.13.0/example/example.cpp
vendored
Normal file
378
thirdparty/spdlog-1.13.0/example/example.cpp
vendored
Normal file
@@ -0,0 +1,378 @@
|
|||||||
|
//
|
||||||
|
// Copyright(c) 2015 Gabi Melman.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
// spdlog usage example
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
void load_levels_example();
|
||||||
|
void stdout_logger_example();
|
||||||
|
void basic_example();
|
||||||
|
void rotating_example();
|
||||||
|
void daily_example();
|
||||||
|
void callback_example();
|
||||||
|
void async_example();
|
||||||
|
void binary_example();
|
||||||
|
void vector_example();
|
||||||
|
void stopwatch_example();
|
||||||
|
void trace_example();
|
||||||
|
void multi_sink_example();
|
||||||
|
void user_defined_example();
|
||||||
|
void err_handler_example();
|
||||||
|
void syslog_example();
|
||||||
|
void udp_example();
|
||||||
|
void custom_flags_example();
|
||||||
|
void file_events_example();
|
||||||
|
void replace_default_logger_example();
|
||||||
|
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/cfg/env.h" // support for loading levels from the environment variable
|
||||||
|
#include "spdlog/fmt/ostr.h" // support for user defined types
|
||||||
|
|
||||||
|
int main(int, char *[]) {
|
||||||
|
// Log levels can be loaded from argv/env using "SPDLOG_LEVEL"
|
||||||
|
load_levels_example();
|
||||||
|
|
||||||
|
spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR,
|
||||||
|
SPDLOG_VER_PATCH);
|
||||||
|
|
||||||
|
spdlog::warn("Easy padding in numbers like {:08d}", 12);
|
||||||
|
spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
|
||||||
|
spdlog::info("Support for floats {:03.2f}", 1.23456);
|
||||||
|
spdlog::info("Positional args are {1} {0}..", "too", "supported");
|
||||||
|
spdlog::info("{:>8} aligned, {:<8} aligned", "right", "left");
|
||||||
|
|
||||||
|
// Runtime log levels
|
||||||
|
spdlog::set_level(spdlog::level::info); // Set global log level to info
|
||||||
|
spdlog::debug("This message should not be displayed!");
|
||||||
|
spdlog::set_level(spdlog::level::trace); // Set specific logger's log level
|
||||||
|
spdlog::debug("This message should be displayed..");
|
||||||
|
|
||||||
|
// Customize msg format for all loggers
|
||||||
|
spdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [thread %t] %v");
|
||||||
|
spdlog::info("This an info message with custom format");
|
||||||
|
spdlog::set_pattern("%+"); // back to default format
|
||||||
|
spdlog::set_level(spdlog::level::info);
|
||||||
|
|
||||||
|
// Backtrace support
|
||||||
|
// Loggers can store in a ring buffer all messages (including debug/trace) for later inspection.
|
||||||
|
// When needed, call dump_backtrace() to see what happened:
|
||||||
|
spdlog::enable_backtrace(10); // create ring buffer with capacity of 10 messages
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
spdlog::debug("Backtrace message {}", i); // not logged..
|
||||||
|
}
|
||||||
|
// e.g. if some error happened:
|
||||||
|
spdlog::dump_backtrace(); // log them now!
|
||||||
|
|
||||||
|
try {
|
||||||
|
stdout_logger_example();
|
||||||
|
basic_example();
|
||||||
|
rotating_example();
|
||||||
|
daily_example();
|
||||||
|
callback_example();
|
||||||
|
async_example();
|
||||||
|
binary_example();
|
||||||
|
vector_example();
|
||||||
|
multi_sink_example();
|
||||||
|
user_defined_example();
|
||||||
|
err_handler_example();
|
||||||
|
trace_example();
|
||||||
|
stopwatch_example();
|
||||||
|
udp_example();
|
||||||
|
custom_flags_example();
|
||||||
|
file_events_example();
|
||||||
|
replace_default_logger_example();
|
||||||
|
|
||||||
|
// Flush all *registered* loggers using a worker thread every 3 seconds.
|
||||||
|
// note: registered loggers *must* be thread safe for this to work correctly!
|
||||||
|
spdlog::flush_every(std::chrono::seconds(3));
|
||||||
|
|
||||||
|
// Apply some function on all registered loggers
|
||||||
|
spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->info("End of example."); });
|
||||||
|
|
||||||
|
// Release all spdlog resources, and drop all loggers in the registry.
|
||||||
|
// This is optional (only mandatory if using windows + async log).
|
||||||
|
spdlog::shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exceptions will only be thrown upon failed logger or sink construction (not during logging).
|
||||||
|
catch (const spdlog::spdlog_ex &ex) {
|
||||||
|
std::printf("Log initialization failed: %s\n", ex.what());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
|
// or #include "spdlog/sinks/stdout_sinks.h" if no colors needed.
|
||||||
|
void stdout_logger_example() {
|
||||||
|
// Create color multi threaded logger.
|
||||||
|
auto console = spdlog::stdout_color_mt("console");
|
||||||
|
// or for stderr:
|
||||||
|
// auto console = spdlog::stderr_color_mt("error-logger");
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
void basic_example() {
|
||||||
|
// Create basic file logger (not rotated).
|
||||||
|
auto my_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
void rotating_example() {
|
||||||
|
// Create a file rotating logger with 5mb size max and 3 rotated files.
|
||||||
|
auto rotating_logger =
|
||||||
|
spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spdlog/sinks/daily_file_sink.h"
|
||||||
|
void daily_example() {
|
||||||
|
// Create a daily logger - a new file is created every day on 2:30am.
|
||||||
|
auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spdlog/sinks/callback_sink.h"
|
||||||
|
void callback_example() {
|
||||||
|
// Create the logger
|
||||||
|
auto logger = spdlog::callback_logger_mt("custom_callback_logger",
|
||||||
|
[](const spdlog::details::log_msg & /*msg*/) {
|
||||||
|
// do what you need to do with msg
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spdlog/cfg/env.h"
|
||||||
|
void load_levels_example() {
|
||||||
|
// Set the log level to "info" and mylogger to "trace":
|
||||||
|
// SPDLOG_LEVEL=info,mylogger=trace && ./example
|
||||||
|
spdlog::cfg::load_env_levels();
|
||||||
|
// or from command line:
|
||||||
|
// ./example SPDLOG_LEVEL=info,mylogger=trace
|
||||||
|
// #include "spdlog/cfg/argv.h" // for loading levels from argv
|
||||||
|
// spdlog::cfg::load_argv_levels(args, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spdlog/async.h"
|
||||||
|
void async_example() {
|
||||||
|
// Default thread pool settings can be modified *before* creating the async logger:
|
||||||
|
// spdlog::init_thread_pool(32768, 1); // queue with max 32k items 1 backing thread.
|
||||||
|
auto async_file =
|
||||||
|
spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/async_log.txt");
|
||||||
|
// alternatively:
|
||||||
|
// auto async_file =
|
||||||
|
// spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("async_file_logger",
|
||||||
|
// "logs/async_log.txt");
|
||||||
|
|
||||||
|
for (int i = 1; i < 101; ++i) {
|
||||||
|
async_file->info("Async message #{}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log binary data as hex.
|
||||||
|
// Many types of std::container<char> types can be used.
|
||||||
|
// Iterator ranges are supported too.
|
||||||
|
// Format flags:
|
||||||
|
// {:X} - print in uppercase.
|
||||||
|
// {:s} - don't separate each byte with space.
|
||||||
|
// {:p} - don't print the position on each line start.
|
||||||
|
// {:n} - don't split the output to lines.
|
||||||
|
|
||||||
|
#if !defined SPDLOG_USE_STD_FORMAT || defined(_MSC_VER)
|
||||||
|
#include "spdlog/fmt/bin_to_hex.h"
|
||||||
|
void binary_example() {
|
||||||
|
std::vector<char> buf;
|
||||||
|
for (int i = 0; i < 80; i++) {
|
||||||
|
buf.push_back(static_cast<char>(i & 0xff));
|
||||||
|
}
|
||||||
|
spdlog::info("Binary example: {}", spdlog::to_hex(buf));
|
||||||
|
spdlog::info("Another binary example:{:n}",
|
||||||
|
spdlog::to_hex(std::begin(buf), std::begin(buf) + 10));
|
||||||
|
// more examples:
|
||||||
|
// logger->info("uppercase: {:X}", spdlog::to_hex(buf));
|
||||||
|
// logger->info("uppercase, no delimiters: {:Xs}", spdlog::to_hex(buf));
|
||||||
|
// logger->info("uppercase, no delimiters, no position info: {:Xsp}", spdlog::to_hex(buf));
|
||||||
|
// logger->info("hexdump style: {:a}", spdlog::to_hex(buf));
|
||||||
|
// logger->info("hexdump style, 20 chars per line {:a}", spdlog::to_hex(buf, 20));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void binary_example() {
|
||||||
|
// not supported with std::format yet
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Log a vector of numbers
|
||||||
|
#ifndef SPDLOG_USE_STD_FORMAT
|
||||||
|
#include "spdlog/fmt/ranges.h"
|
||||||
|
void vector_example() {
|
||||||
|
std::vector<int> vec = {1, 2, 3};
|
||||||
|
spdlog::info("Vector example: {}", vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void vector_example() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ! DSPDLOG_USE_STD_FORMAT
|
||||||
|
|
||||||
|
// Compile time log levels.
|
||||||
|
// define SPDLOG_ACTIVE_LEVEL to required level (e.g. SPDLOG_LEVEL_TRACE)
|
||||||
|
void trace_example() {
|
||||||
|
// trace from default logger
|
||||||
|
SPDLOG_TRACE("Some trace message.. {} ,{}", 1, 3.23);
|
||||||
|
// debug from default logger
|
||||||
|
SPDLOG_DEBUG("Some debug message.. {} ,{}", 1, 3.23);
|
||||||
|
|
||||||
|
// trace from logger object
|
||||||
|
auto logger = spdlog::get("file_logger");
|
||||||
|
SPDLOG_LOGGER_TRACE(logger, "another trace message");
|
||||||
|
}
|
||||||
|
|
||||||
|
// stopwatch example
|
||||||
|
#include "spdlog/stopwatch.h"
|
||||||
|
#include <thread>
|
||||||
|
void stopwatch_example() {
|
||||||
|
spdlog::stopwatch sw;
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(123));
|
||||||
|
spdlog::info("Stopwatch: {} seconds", sw);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "spdlog/sinks/udp_sink.h"
|
||||||
|
void udp_example() {
|
||||||
|
spdlog::sinks::udp_sink_config cfg("127.0.0.1", 11091);
|
||||||
|
auto my_logger = spdlog::udp_logger_mt("udplog", cfg);
|
||||||
|
my_logger->set_level(spdlog::level::debug);
|
||||||
|
my_logger->info("hello world");
|
||||||
|
}
|
||||||
|
|
||||||
|
// A logger with multiple sinks (stdout and file) - each with a different format and log level.
|
||||||
|
void multi_sink_example() {
|
||||||
|
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||||
|
console_sink->set_level(spdlog::level::warn);
|
||||||
|
console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v");
|
||||||
|
|
||||||
|
auto file_sink =
|
||||||
|
std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multisink.txt", true);
|
||||||
|
file_sink->set_level(spdlog::level::trace);
|
||||||
|
|
||||||
|
spdlog::logger logger("multi_sink", {console_sink, file_sink});
|
||||||
|
logger.set_level(spdlog::level::debug);
|
||||||
|
logger.warn("this should appear in both console and file");
|
||||||
|
logger.info("this message should not appear in the console, only in the file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// User defined types logging
|
||||||
|
struct my_type {
|
||||||
|
int i = 0;
|
||||||
|
explicit my_type(int i)
|
||||||
|
: i(i){};
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef SPDLOG_USE_STD_FORMAT // when using fmtlib
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<my_type> : fmt::formatter<std::string> {
|
||||||
|
auto format(my_type my, format_context &ctx) -> decltype(ctx.out()) {
|
||||||
|
return fmt::format_to(ctx.out(), "[my_type i={}]", my.i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#else // when using std::format
|
||||||
|
template <>
|
||||||
|
struct std::formatter<my_type> : std::formatter<std::string> {
|
||||||
|
auto format(my_type my, format_context &ctx) const -> decltype(ctx.out()) {
|
||||||
|
return format_to(ctx.out(), "[my_type i={}]", my.i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void user_defined_example() { spdlog::info("user defined type: {}", my_type(14)); }
|
||||||
|
|
||||||
|
// Custom error handler. Will be triggered on log failure.
|
||||||
|
void err_handler_example() {
|
||||||
|
// can be set globally or per logger(logger->set_error_handler(..))
|
||||||
|
spdlog::set_error_handler([](const std::string &msg) {
|
||||||
|
printf("*** Custom log error handler: %s ***\n", msg.c_str());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// syslog example (linux/osx/freebsd)
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include "spdlog/sinks/syslog_sink.h"
|
||||||
|
void syslog_example() {
|
||||||
|
std::string ident = "spdlog-example";
|
||||||
|
auto syslog_logger = spdlog::syslog_logger_mt("syslog", ident, LOG_PID);
|
||||||
|
syslog_logger->warn("This is warning that will end up in syslog.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Android example.
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
#include "spdlog/sinks/android_sink.h"
|
||||||
|
void android_example() {
|
||||||
|
std::string tag = "spdlog-android";
|
||||||
|
auto android_logger = spdlog::android_logger_mt("android", tag);
|
||||||
|
android_logger->critical("Use \"adb shell logcat\" to view this message.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Log patterns can contain custom flags.
|
||||||
|
// this will add custom flag '%*' which will be bound to a <my_formatter_flag> instance
|
||||||
|
#include "spdlog/pattern_formatter.h"
|
||||||
|
class my_formatter_flag : public spdlog::custom_flag_formatter {
|
||||||
|
public:
|
||||||
|
void format(const spdlog::details::log_msg &,
|
||||||
|
const std::tm &,
|
||||||
|
spdlog::memory_buf_t &dest) override {
|
||||||
|
std::string some_txt = "custom-flag";
|
||||||
|
dest.append(some_txt.data(), some_txt.data() + some_txt.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<custom_flag_formatter> clone() const override {
|
||||||
|
return spdlog::details::make_unique<my_formatter_flag>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void custom_flags_example() {
|
||||||
|
using spdlog::details::make_unique; // for pre c++14
|
||||||
|
auto formatter = make_unique<spdlog::pattern_formatter>();
|
||||||
|
formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v");
|
||||||
|
// set the new formatter using spdlog::set_formatter(formatter) or
|
||||||
|
// logger->set_formatter(formatter) spdlog::set_formatter(std::move(formatter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_events_example() {
|
||||||
|
// pass the spdlog::file_event_handlers to file sinks for open/close log file notifications
|
||||||
|
spdlog::file_event_handlers handlers;
|
||||||
|
handlers.before_open = [](spdlog::filename_t filename) {
|
||||||
|
spdlog::info("Before opening {}", filename);
|
||||||
|
};
|
||||||
|
handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) {
|
||||||
|
spdlog::info("After opening {}", filename);
|
||||||
|
fputs("After opening\n", fstream);
|
||||||
|
};
|
||||||
|
handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) {
|
||||||
|
spdlog::info("Before closing {}", filename);
|
||||||
|
fputs("Before closing\n", fstream);
|
||||||
|
};
|
||||||
|
handlers.after_close = [](spdlog::filename_t filename) {
|
||||||
|
spdlog::info("After closing {}", filename);
|
||||||
|
};
|
||||||
|
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/events-sample.txt",
|
||||||
|
true, handlers);
|
||||||
|
spdlog::logger my_logger("some_logger", file_sink);
|
||||||
|
my_logger.info("Some log line");
|
||||||
|
}
|
||||||
|
|
||||||
|
void replace_default_logger_example() {
|
||||||
|
// store the old logger so we don't break other examples.
|
||||||
|
auto old_logger = spdlog::default_logger();
|
||||||
|
|
||||||
|
auto new_logger =
|
||||||
|
spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true);
|
||||||
|
spdlog::set_default_logger(new_logger);
|
||||||
|
spdlog::set_level(spdlog::level::info);
|
||||||
|
spdlog::debug("This message should not be displayed!");
|
||||||
|
spdlog::set_level(spdlog::level::trace);
|
||||||
|
spdlog::debug("This message should be displayed..");
|
||||||
|
|
||||||
|
spdlog::set_default_logger(old_logger);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user