onetnet平台支持MQTT、CoAP、HTTP等多种协议接入,其中MQTT是基于pub/sub的消息协议,非常适合网络带宽有限的场景,同时其可以保持长连接,具有一定的实效性。另外,最早接触onenet也是通过mqtt接入的,这次也准备把雷达模块尝试用MQTT协议接入onenet,模拟一个人体感应的小夜灯。
代码比较简单,如下,注意需要用自己产品的信息,onenet的使用可以参考:
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <iostream>
#include <vector>
#include <cstdint>
#include <chrono>
#include <iomanip>
#include <string>
#include <sstream>
#include <mosquitto.h>
#include "json.hpp"
using json = nlohmann::json;
// 定义帧头
const uint8_t FRAME_HEADER_TX[2] = {0x55, 0x5A}; // 上位机发送帧头
const uint8_t FRAME_HEADER_RX[2] = {0x55, 0xA5}; // 上位机接收帧头
// 封装函数:获取当前时间字符串
std::string getCurrentTimeString()
{
auto now = std::chrono::system_clock::now();
auto now_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::localtime(&now_time_t), "%Y-%m-%d %H:%M:%S");
return ss.str();
}
// 打开串口
int openSerialPort(const char* portName)
{
int fd = open(portName, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("Failed to open serial port");
return -1;
}
// 配置串口
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
options.c_cflag &= ~PARENB; // 无奇偶校验
options.c_cflag &= ~CSTOPB; // 1位停止位
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8; // 8位数据位
options.c_cflag |= (CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始模式
options.c_iflag &= ~(IXON | IXOFF | IXANY); // 禁用流控
options.c_oflag &= ~OPOST; // 原始输出
if (tcsetattr(fd, TCSANOW, &options) != 0)
{
perror("Failed to condiv serial port");
close(fd);
return -1;
}
return fd;
}
int main()
{
const char *host = "mqtts.heclouds.com";
int port = 1883;
const char *topic = "创建的产品的topic";
const char *client_id= "创建的设备的id";
int keepalive = 60;
mosquitto_lib_init();
struct mosquitto *mosq = mosquitto_new(client_id, true, nullptr);
if (!mosq)
{
std::fprintf(stderr, "Out of memory\n");
return 1;
}
mosquitto_username_pw_set(mosq, "创建的产品的id", "生成的密码");
int rc = mosquitto_connect(mosq, host, port, keepalive);
if (rc != MOSQ_ERR_SUCCESS)
{
std::fprintf(stderr, "Connect failed: %s\n", mosquitto_strerror(rc));
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return 1;
}
int fd = openSerialPort("/dev/ttyS0");
if (fd == -1)
{
return 1;
}
json data = {
{"id", "0"},
{"version", "1.0"},
{"params", {
{"status", {
{"value", false},
{"time", "2024-03-22 22:24:47"}
}},
{"distance", {
{"value", 0},
{"time", "2024-03-22 22:24:47"}
}}
}}
};
unsigned int dataSN = 0;
std::string res;
while(1)
{
char buf[128];
int n = read(fd, buf, sizeof(buf));
if (buf[0] != FRAME_HEADER_RX[0] || buf[1] != FRAME_HEADER_RX[1])
{
continue;
}
// 读取数据长度(大端格式)
uint16_t length = (buf[2] << 8) | buf[3];
printf("length: %d\n", length);
printf("id= %d, status=%d, distance=%ucm\n", buf[7], buf[8], ((buf[9] << 8) | buf[10]));
data["id"] = std::to_string(dataSN++);
data["params"]["status"]["value"] = true;
data["params"]["status"]["time"] = getCurrentTimeString();
data["params"]["distance"]["value"] = ((buf[9] << 8) | buf[10]);
data["params"]["distance"]["time"] = getCurrentTimeString();
res = data.dump();
int ret = mosquitto_publish(mosq, nullptr, topic, res.size(), res.c_str(), 0, false);
if (ret != MOSQ_ERR_SUCCESS)
{
std::fprintf(stderr, "Publish failed: %s\n", mosquitto_strerror(ret));
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return 1;
}
printf("publish: %s\n", res.c_str());
usleep(10000);
}
return 0;
}
运行结果:
全部评论