Commit 17741475 authored by zhoutotong's avatar zhoutotong

first commit

parents
{
"files.associations": {
"chrono": "cpp",
"ostream": "cpp"
}
}
\ No newline at end of file
{
"files.associations": {
"array": "cpp",
"bitset": "cpp",
"string_view": "cpp",
"initializer_list": "cpp",
"utility": "cpp",
"__hash_table": "cpp",
"__split_buffer": "cpp",
"__tree": "cpp",
"deque": "cpp",
"map": "cpp",
"queue": "cpp",
"stack": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"chrono": "cpp",
"any": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"forward_list": "cpp",
"list": "cpp",
"set": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"fstream": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"semaphore": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"typeinfo": "cpp",
"valarray": "cpp"
}
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.5)
project(barrier_gate)
set(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS ON)
execute_process(COMMAND ${CMAKE_C_COMPILER} -march=native -Q -v
OUTPUT_VARIABLE COMPILER_INFO
ERROR_VARIABLE COMPILER_INFO)
string(REGEX MATCH "Target: ([^\n]+)" TARGET_ARCH ${COMPILER_INFO})
message("Detected architecture: ${CMAKE_MATCH_1}")
if (${CMAKE_MATCH_1} STREQUAL "aarch64-linux-gnu")
link_directories(
${CMAKE_CURRENT_SOURCE_DIR}/lib/aarch64
)
else()
link_directories(
${CMAKE_CURRENT_SOURCE_DIR}/lib/x86-64
)
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# 收集源文件
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRCS)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src/mqtt SRCS)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src/modbus SRCS)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src/uart SRCS)
add_executable(${PROJECT_NAME} ${SRCS})
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(${PROJECT_NAME}
${Coin_LIBRARIES}
pthread
mosquitto
)
{
"mqtt_server_ip": "192.168.9.198",
"mqtt_server_port": 1883,
"mqtt_server_user": "admin/waytous",
"mqtt_server_pwd": "2023",
"self_id": "1",
"uart": "/dev/ttyUSB0",
"report_topic": "waytous/barrier_gate/1",
"control_topic": "waytous/barrier_gate/1/control"
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
libmosquitto.so.1
\ No newline at end of file
libmosquitto.so.1
\ No newline at end of file
# traffic_light_control
## 0.deps
```sh
sudo apt install libprotobuf-dev protobuf-compiler
sudo apt install libmosquitto-dev
```
## 1.compile
```sh
mkdir build
cd build
cmake ..
make -j7
```
## 2.exec
```sh
cd build
./traffic_light_control ../test/config.json
```
## 3.config.json
```sh
"mqtt_server_ip": "192.168.9.30", //mqtt 服务器ip地址
"mqtt_server_port": 1883, //mqtt 服务器端口号
"mqtt_server_user": "test", //mqtt 用户名
"mqtt_server_pwd": "test", //mqtt 密码
"hdmap_topic": "/mqtt_msg_data_trans_traffic_light_layer", //订阅高精地图数据的topic
"traffic_control_topic": "/USR-M100/Control/Traffic", //下发给继电器的控制topic
"expand_size": 5, //继电器拓展的板个数
"offset_do_addr": 2, //继电器实际接线的偏移量
"lights":
[
//id: 地图给的值 do_addrs->colors: [对应到继电器的接口编号]
{"name": "light1", "id": 1, "type": "left", "do_addrs":[5, 6, 7], "colors":["red", "yellow", "green"]},
{"name": "light2", "id": 2, "type": "up", "do_addrs":[2, 3, 4], "colors":["red", "yellow", "green"]},
{"name": "light3", "id": 3, "type": "right", "do_addrs":[8, 9, 34], "colors":["red", "yellow", "green"]},
{"name": "light4", "id": 4, "type": "left", "do_addrs":[13, 14, 15], "colors":["red", "yellow", "green"]},
{"name": "light5", "id": 5, "type": "up", "do_addrs":[10, 11, 12], "colors":["red", "yellow", "green"]},
{"name": "light6", "id": 6, "type": "right", "do_addrs":[16, 17, 35], "colors":["red", "yellow", "green"]},
{"name": "light7", "id": 7, "type": "left", "do_addrs":[21, 22, 23], "colors":["red", "yellow", "green"]},
{"name": "light8", "id": 8, "type": "up", "do_addrs":[18, 19, 20], "colors":["red", "yellow", "green"]},
{"name": "light9", "id": 9, "type": "right", "do_addrs":[24, 25, 36], "colors":["red", "yellow", "green"]},
{"name": "light10", "id": 10, "type": "left", "do_addrs":[29, 30, 31], "colors":["red", "yellow", "green"]},
{"name": "light11", "id": 11, "type": "up", "do_addrs":[26, 27, 28], "colors":["red", "yellow", "green"]},
{"name": "light12", "id": 12, "type": "right", "do_addrs":[32, 33, 37], "colors":["red", "yellow", "green"]}
],
"modes":
[
{
"id": 0, //模式id
"lights": //12个灯的状态
[
{"id": 1, "color": "red"},
{"id": 2, "color": "green"},
{"id": 3, "color": "yellow"},
{"id": 4, "color": "black"},
{"id": 5, "color": "unkown"},
{"id": 6, "color": "green"},
{"id": 7, "color": "green"},
{"id": 8, "color": "green"},
{"id": 9, "color": "green"},
{"id": 10, "color": "green"},
{"id": 11, "color": "green"},
{"id": 12, "color": "green"}
]
},
{
"id": 1,
"lights":
[
{"id": 1, "color": "red"},
{"id": 2, "color": "green"},
{"id": 3, "color": "green"},
{"id": 4, "color": "green"},
{"id": 5, "color": "green"},
{"id": 6, "color": "green"},
{"id": 7, "color": "green"},
{"id": 8, "color": "green"},
{"id": 9, "color": "green"},
{"id": 10, "color": "green"},
{"id": 11, "color": "green"},
{"id": 12, "color": "green"}
]
}
]
```
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
#include "barrier_gate.hpp"
#include "modbus/crc16-modbus.hpp"
#include "3th-part/json.hpp"
#include <sstream>
#include <chrono>
#include <cstdint>
// const std::vector<const uint8_t> all_on {0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x8C, 0x3A};
// const std::vector<const uint8_t> all_off {};
uint64_t get_current_timestamp()
{
auto now = std::chrono::system_clock::now();
auto duration_since_epoch = now.time_since_epoch();
auto millis_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>(duration_since_epoch).count();
return static_cast<uint64_t>(millis_since_epoch);
}
void printf_hex(const std::vector<uint8_t>& data)
{
std::ostringstream ss;
for (auto& v : data) {
ss << "0x" << std::hex << (uint32_t)v << " ";
}
std::cout << ss.str() << std::endl;
}
BarrierGateControl::BarrierGateControl(nlohmann::json& config)
: self_id(config["self_id"])
, uart_name_(config["uart"])
, report_topic_(config["report_topic"])
, control_topic_(config["control_topic"])
{
init();
}
void BarrierGateControl::exec()
{
__m_running = true;
uint16_t gate_code = 0;
std::string barrier_gate_status = cvt_gate_status(GateState::OFF);
auto start = std::chrono::steady_clock::now();
while (__m_running) {
auto now = std::chrono::steady_clock::now();
// publish traffic light states once per second
if(std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count() > 1000)
{
std::cout << "--------------------------------------" << std::endl;
start = now;
// send read input status request to gate
{
std::cout << "read gate input status..." << std::endl;
std::vector<uint8_t> request_cmd = {0x01, 0x03, 0x06, 0x00, 0x00, 0x01};
auto crc = tools::crc16_modbus::crc16_code(request_cmd);
request_cmd.insert(request_cmd.end(), crc.begin(), crc.end());
std::cout << "send request status to gate: ";
printf_hex(request_cmd);
uart_->write(request_cmd.data(), request_cmd.size());
}
// publish barrier gate states
{
nlohmann::json j = nlohmann::json::object();
j.emplace("self_id", self_id);
j.emplace("relay_code", gate_code);
j.emplace("status", barrier_gate_status);
auto containts = j.dump();
mqtt_dataio::subscriber_basic::DataBuffer buffer;
buffer.resize(containts.size());
std::copy(containts.begin(), containts.end(), buffer.begin());
std::cout << "publish traffic light states: " << containts << std::endl;
__m_status_puber->publish(buffer);
}
}
// read data from uart port
uint8_t buffer[1024];
int len = uart_->read(buffer, sizeof(buffer));
if(len > 0)
{
for(int i = 0; i < len; i++)
{
std::cout << std::hex << (uint32_t)buffer[i] << " ";
}
std::cout << std::endl;
// check crc code
auto crc = tools::crc16_modbus::crc16_code(std::vector<uint8_t>(buffer, buffer + len - 2));
if(crc[0] == buffer[len - 2] && crc[1] == buffer[len - 1])
{
std::cout << "crc check ok!" << std::endl;
uint8_t func_code = buffer[1];
if(func_code == 0x03)
{
gate_code = (buffer[len - 4] << 8 | buffer[len - 3]);
barrier_gate_status = cvt_gate_status(gate_code);
std::cout << "gate code: " << (int)gate_code << ", barrier gate status: " << barrier_gate_status << std::endl;
}
else if(func_code == 0x0f)
{
// TODO: this is gate control command ack package.
}
else
{
std::cout << "unknown func code: " << (int)func_code << std::endl;
}
}
else
{
std::cerr << "check gate status failed, crc error: " << buffer[len - 2] << ", " << buffer[len - 1] << ", should be: " << crc[0] << ", " << crc[1] << std::endl;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
BarrierGateControl::~BarrierGateControl()
{
__m_running = false;
}
void BarrierGateControl::init()
{
uart_ = std::make_shared<awe::Uart>(uart_name_.c_str());
uart_->setOpt(9600, 8, 'N', 1);
// regist self to traffic light controller
nlohmann::json j = nlohmann::json::object();
j.emplace("self_id", self_id);
j.emplace("type", "traffic_light");
// publish traffic light status
__m_status_puber = std::make_shared<mqtt_dataio::publisher<mqtt_dataio::subscriber_basic::DataBuffer>>(report_topic_);
// subscribe control request
__m_control_suber = std::make_shared<mqtt_dataio::subscriber<mqtt_dataio::subscriber_basic::DataBuffer>>(control_topic_,
std::bind(&BarrierGateControl::on_control_request, this, std::placeholders::_1));
// on start up, do nothing
// current_gate_ = GateState::OFF;
// gate_control(0, current_gate_);
}
void BarrierGateControl::on_control_request(const mqtt_dataio::subscriber_basic::DataBuffer& msg)
{
std::string str;
str.resize(msg.size());
memcpy((void*)str.data(), msg.data(), msg.size());
nlohmann::json j = nlohmann::json::parse(str);
std::cout << "recv control request: " << j.dump() << std::endl;
if(j["id"] != self_id)
{
std::cerr << "invalid id: " << j["id"] << ", self id: " << self_id << ", ignore" << std::endl;
return;
}
std::string status = j["status"];
GateState gate = cvt_gate_status(status);
gate_control(0, gate);
std::cout << "change traffic light status from: " << cvt_gate_status(current_gate_) << " to " << cvt_gate_status(gate) << std::endl;
current_gate_ = gate;
}
void BarrierGateControl::gate_control(const int channel, const GateState gate)
{
std::vector<uint8_t> relay_cmd = {0x01, 0x06, 0x05, 0x05, 0x00, static_cast<uint8_t>(gate)};
auto pkg = tools::crc16_modbus::crc16_code(relay_cmd);
relay_cmd.insert(relay_cmd.end(), pkg.begin(), pkg.end());
std::cout << "send relay control cmd: ";
printf_hex(relay_cmd);
uart_->write(relay_cmd.data(), relay_cmd.size());
}
const BarrierGateControl::GateState BarrierGateControl::cvt_gate_status(const std::string& status)
{
// lower status string
std::string s = status;
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
if(s == "off")
{
return GateState::OFF;
}
else if(s == "on")
{
return GateState::ON;
}
else if(s == "pause")
{
return GateState::PAUSE;
}
return GateState::UNKNOWN;
}
const std::string BarrierGateControl::cvt_gate_status(const GateState& status)
{
switch(status)
{
case GateState::ON:
return "on";
case GateState::OFF:
return "off";
case GateState::PAUSE:
return "pause";
default:
return "unknown";
}
return "unknown";
}
const std::string BarrierGateControl::cvt_gate_status(const uint16_t& status)
{
switch(status)
{
case 1: return "initilized"; break;
case 2: return "opening"; break;
case 3: return "opened"; break;
case 4: return "closing"; break;
case 5: return "closed"; break;
case 6: return "close_blocked"; break;
case 7: return "open_blocked"; break;
case 8: return "stopping"; break;
case 9: return "studdy"; break;
case 10: return "system_reset"; break;
case 11: return "reset_needed"; break;
case 12: return "remote_always_on"; break;
default: return "unknown"; break;
}
return "unknown";
}
\ No newline at end of file
#pragma once
#include "mqtt/subcriber.hpp"
#include "mqtt/publisher.hpp"
#include "uart/uart.hpp"
#include "3th-part/json.hpp"
struct traffic_light_config
{
/* data */
uint16_t id;
std::string type;
std::vector<uint16_t> do_addr;
std::vector<std::string> color;
};
struct roadside_info_config
{
std::string id;
std::string topic;
double longitude;
double latitude;
double altitude;
uint32_t isLight;
};
struct traffic_light_status_config
{
/* data */
uint16_t id;
std::string color;
};
struct traffic_mode_config
{
uint16_t id;
std::vector<traffic_light_status_config> lights;
};
class BarrierGateControl
{
public:
BarrierGateControl(nlohmann::json& config);
~BarrierGateControl();
void exec();
enum GateState
{
UNKNOWN = 0,
ON = 1,
PAUSE = 2,
OFF = 3,
};
const GateState cvt_gate_status(const std::string& status);
const std::string cvt_gate_status(const GateState& status);
const std::string cvt_gate_status(const uint16_t& status);
void gate_control(const int channel, const GateState state);
private:
void init();
const std::string self_id;
const std::string uart_name_;
const std::string report_topic_;
const std::string control_topic_;
std::shared_ptr<awe::Uart> uart_;
GateState current_gate_;
std::shared_ptr<mqtt_dataio::publisher<mqtt_dataio::subscriber_basic::DataBuffer>> __m_status_puber;
std::shared_ptr<mqtt_dataio::subscriber<mqtt_dataio::subscriber_basic::DataBuffer>> __m_control_suber;
void on_control_request(const mqtt_dataio::subscriber_basic::DataBuffer& msg);
private:
bool __m_running;
uint8_t __m_expand_size;
uint16_t __m_offset_do_addr;
};
#include <iostream>
#include <fstream>
#include <sstream>
#include "3th-part/json.hpp"
#include "mqtt/mqtt_client.hpp"
#include "barrier_gate.hpp"
int main(int argc, char *argv[])
{
if (argc < 2)
{
std::cout << "please input config file, such as config.json" << std::endl;
return 0;
}
if(access(argv[1], F_OK) != 0)
{
std::cerr << "file not exist: " << argv[1] << std::endl;
return 0;
}
std::ifstream file(argv[1]);
if (!file)
{
std::cerr << "can't open file " << argv[1] << std::endl;
return 0;
}
std::ostringstream ss;
ss << file.rdbuf();
std::string content = ss.str();
if (content.empty())
{
std::cout << "config file is empty!" << std::endl;
}
else
{
try
{
nlohmann::json j = nlohmann::json::parse(content);
std::string ip = j["mqtt_server_ip"];
uint16_t port = j["mqtt_server_port"];
std::string user = j["mqtt_server_user"];
std::string pwd = j["mqtt_server_pwd"];
mqtt_dataio::client::ins().init(ip, port, user, pwd);
auto node = std::make_shared<BarrierGateControl>(j);
node->exec();
}
catch (const std::exception &e)
{
std::cerr << "catch exception: " << e.what() << '\n';
return -1;
}
}
return 0;
}
#pragma once
#include <stdint.h>
#include <vector>
namespace tools
{
static const uint8_t crcHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};
static const uint8_t crcLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
class crc16_modbus
{
private:
static uint16_t calc(const std::vector<uint8_t> &data)
{
uint8_t crchi = 0xFF;
uint8_t crclo = 0xFF;
uint16_t index = 0;
uint16_t len = data.size();
uint16_t i = 0;
while (len--)
{
uint16_t dataValue = data[i++];
index = crclo ^ dataValue;
crclo = crchi ^ crcHi[index];
crchi = crcLo[index];
}
return ((crchi << 8) | crclo);
}
public:
static std::vector<uint8_t> crc16_code(const std::vector<uint8_t> &data)
{
uint16_t _crc16_code = calc(data);
std::vector<uint8_t> ret;
uint8_t h_b = (_crc16_code >> 8) & 0xff;
uint8_t l_b = _crc16_code & 0xff;
ret.push_back(l_b);
ret.push_back(h_b);
return ret;
}
};
}
#pragma once
#include <vector>
#include <stdint.h>
namespace mqtt_dataio
{
class publisher_basic
{
public:
explicit publisher_basic(){};
virtual ~publisher_basic(){};
};
class subscriber_basic
{
public:
using DataBuffer = std::vector<uint8_t>;
explicit subscriber_basic(){};
virtual ~subscriber_basic(){};
virtual void on_message_arrival(const DataBuffer &){};
};
} // namespace mqtt_dataio
#include "mqtt_client.hpp"
namespace mqtt_dataio
{
bool client::__m_init = false;
struct mosquitto *client::__m_mosq = nullptr;
std::shared_ptr<std::thread> client::__m_thread = nullptr;
std::mutex client::__m_mtx;
std::map<std::string, mqtt_dataio::subscriber_basic *> client::__m_sub_list;
void client::init(const std::string &ip, const uint16_t &port, const std::string &user, const std::string &pwd)
{
if (__m_init)
return;
/* Required before calling other mosquitto functions */
mosquitto_lib_init();
/* Create a new client instance.
* id = NULL -> ask the broker to generate a client id for us
* clean session = true -> the broker should remove old sessions when we connect
* obj = NULL -> we aren't passing any of our private data for callbacks
*/
__m_mosq = mosquitto_new(nullptr, true, nullptr);
if (__m_mosq == nullptr)
{
std::cout << "Error: Out of memory." << std::endl;
return;
}
int rc;
rc = mosquitto_username_pw_set(__m_mosq, user.data(), pwd.data());
if (rc != MOSQ_ERR_SUCCESS)
{
std::cout << "Error: Problem setting username and password" << std::endl;
}
/* Configure callbacks. This should be done before connecting ideally. */
mosquitto_connect_callback_set(__m_mosq, &client::on_connect);
mosquitto_subscribe_callback_set(__m_mosq, &client::on_subscribe);
mosquitto_message_callback_set(__m_mosq, &client::on_message);
/* Connect to test.mosquitto.org on port 1883, with a keepalive of 60 seconds.
* This call makes the socket connection only, it does not complete the MQTT
* CONNECT/CONNACK flow, you should use mosquitto_loop_start() or
* mosquitto_loop_forever() for processing net traffic. */
rc = mosquitto_connect(__m_mosq, ip.data(), port, 60);
if (rc != MOSQ_ERR_SUCCESS)
{
mosquitto_destroy(__m_mosq);
std::cout << "Error: " << mosquitto_strerror(rc) << std::endl;
__m_init = false;
return;
}
__m_thread = std::make_shared<std::thread>([=]()
{ mosquitto_loop_forever(__m_mosq, -1, 1); });
__m_thread->detach();
{
std::lock_guard<std::mutex> lck(__m_mtx);
__m_init = true;
}
std::cout << "mqtt client init done, connecting to " << ip << ":" << port << std::endl;
}
void client::add_suber(const std::string &topic, mqtt_dataio::subscriber_basic *ptr)
{
{
std::lock_guard<std::mutex> lck(__m_mtx);
if (__m_sub_list.find(topic) == __m_sub_list.end())
{
__m_sub_list[topic] = ptr;
std::cout << "create mqtt_subcriber topic: " << topic << std::endl;
}
else
{
std::cout << "create mqtt_subcriber failed, had exist same topic: " << topic << std::endl;
}
}
int rc = mosquitto_subscribe(__m_mosq, NULL, topic.data(), 1);
if (rc != MOSQ_ERR_SUCCESS)
{
std::cout << "Error subscribing: " << mosquitto_strerror(rc) << std::endl;
/* We might as well disconnect if we were unable to subscribe */
// mosquitto_disconnect(__m_mosq);
}
}
void client::rm_suber(const std::string &topic)
{
{
std::lock_guard<std::mutex> lck(__m_mtx);
if (__m_sub_list.find(topic) != __m_sub_list.end())
{
__m_sub_list.erase(topic);
std::cout << "destroy mqtt_subcriber topic: " << topic << std::endl;
}
else
{
std::cout << "destroy mqtt_subcriber failed, not exist same topic: " << topic << std::endl;
}
}
}
void client::publish(const std::string &topic, const std::vector<uint8_t> &buff)
{
if (!__m_init)
return;
int rc = mosquitto_publish(__m_mosq, NULL, topic.data(), buff.size(), buff.data(), 1, false);
if (rc != MOSQ_ERR_SUCCESS)
{
std::cout << "Error publishing: " << mosquitto_strerror(rc) << std::endl;
}
}
client::~client()
{
mosquitto_disconnect(__m_mosq);
mosquitto_lib_cleanup();
__m_thread = nullptr;
{
std::lock_guard<std::mutex> lck(__m_mtx);
__m_sub_list.clear();
__m_init = false;
}
}
void client::on_connect(struct mosquitto *mosq, void *obj, int reason_code)
{
std::cout << "on_connect: " << mosquitto_connack_string(reason_code) << std::endl;
if (reason_code != 0)
{
/* If the connection fails for any reason, we don't want to keep on
* retrying in this example, so disconnect. Without this, the client
* will attempt to reconnect. */
// mosquitto_disconnect(mosq);
}
// /* Making subscriptions in the on_connect() callback means that if the
// * connection drops and is automatically resumed by the client, then the
// * subscriptions will be recreated when the client reconnects. */
// rc = mosquitto_subscribe(mosq, NULL, "example/temperature", 1);
// if(rc != MOSQ_ERR_SUCCESS){
// fprintf(stderr, "Error subscribing: %s\n", mosquitto_strerror(rc));
// /* We might as well disconnect if we were unable to subscribe */
// mosquitto_disconnect(mosq);
// }
}
/* Callback called when the broker sends a SUBACK in response to a SUBSCRIBE. */
void client::on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
{
int i;
bool have_subscription = false;
/* In this example we only subscribe to a single topic at once, but a
* SUBSCRIBE can contain many topics at once, so this is one way to check
* them all. */
for (i = 0; i < qos_count; i++)
{
std::cout << "on_subscribe: " << i << " :granted qos = " << granted_qos[i] << std::endl;
if (granted_qos[i] <= 2)
{
have_subscription = true;
}
}
if (have_subscription == false)
{
/* The broker rejected all of our subscriptions, we know we only sent
* the one SUBSCRIBE, so there is no point remaining connected. */
std::cout << "Error: All subscriptions rejected." << std::endl;
// mosquitto_disconnect(mosq);
}
}
void client::on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
{
std::string topic(msg->topic);
{
std::lock_guard<std::mutex> lck(__m_mtx);
for (auto &it : __m_sub_list)
{
if (it.first == topic)
{
std::vector<uint8_t> data;
data.resize(msg->payloadlen);
memcpy(data.data(), msg->payload, msg->payloadlen);
it.second->on_message_arrival(data);
}
}
}
}
}
\ No newline at end of file
#pragma once
#include "mqtt_basic.hpp"
#include <mosquitto.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <map>
#include <memory>
#include <functional>
#include <thread>
#include <mutex>
namespace mqtt_dataio
{
class client
{
public:
static client &ins()
{
static client ins;
return ins;
}
void init(const std::string &ip, const uint16_t &port, const std::string &user, const std::string &pwd);
void add_suber(const std::string &topic, mqtt_dataio::subscriber_basic *ptr);
void rm_suber(const std::string &topic);
void publish(const std::string &topic, const std::vector<uint8_t> &buff);
~client();
private:
client() = default;
static void on_connect(struct mosquitto *mosq, void *obj, int reason_code);
static void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos);
static void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg);
private:
static bool __m_init;
static struct mosquitto *__m_mosq;
static std::shared_ptr<std::thread> __m_thread;
static std::mutex __m_mtx;
static std::map<std::string, mqtt_dataio::subscriber_basic *> __m_sub_list;
};
}
\ No newline at end of file
#pragma once
#include "mqtt_basic.hpp"
#include "mqtt_client.hpp"
namespace mqtt_dataio
{
template <typename T>
class publisher : public publisher_basic
{
public:
publisher() = delete;
publisher(const publisher &) = delete;
publisher(const std::string &name)
: __m_name(name)
{
std::cout << "create publisher topic: " << __m_name << std::endl;
}
~publisher() override
{
std::cout << "destroy publisher topic: " << __m_name << std::endl;
}
void publish(const T &msg)
{
{
mqtt_dataio::client::ins().publish(__m_name, msg);
}
}
private:
const std::string __m_name;
};
}
#include "mqtt_basic.hpp"
#include "mqtt_client.hpp"
#include <string>
namespace mqtt_dataio
{
template <typename RT>
class subscriber : public subscriber_basic
{
public:
using DataCallback = std::function<void(const RT &)>;
public:
subscriber(const subscriber &) = delete;
subscriber &operator=(const subscriber &) = delete;
subscriber() = delete;
subscriber(const std::string &name, const DataCallback& cb)
: __m_name(name),
__m_cb(cb)
{
mqtt_dataio::client::ins().add_suber(__m_name, this);
}
~subscriber() override
{
mqtt_dataio::client::ins().rm_suber(__m_name);
}
void on_message_arrival(const DataBuffer &buff) override
{
if (__m_cb)
{
{
__m_cb(buff);
}
}
}
private:
std::string __m_name;
DataCallback __m_cb;
};
} // namespace mqtt_dataio
#include "uart.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <iostream>
static ssize_t uart_write(int __fd, const void *__buf, size_t __n)
{
return write(__fd, __buf, __n);
}
static ssize_t uart_read(int __fd, void *__buf, size_t __nbytes)
{
return read(__fd, __buf, __nbytes);
}
namespace awe
{
Uart::Uart(const char * dev) : fd(0)
{
char tty[64] = "";
strcat(tty, dev);
fd = open(tty, O_RDWR | O_NOCTTY);
//fd = open(tty, O_RDWR | O_NOCTTY | O_NDELAY);
// if (fd > 0) {
// printf("open %s!\n", tty);
// }
}
Uart::~Uart()
{
if (fd > 0)
close(fd);
}
int Uart::setOpt(uint64_t speed, int bits, char event, int stop)
{
if (fd < 0) {
return -1;
perror("Uart Init failed");
}
fcntl(fd, F_SETFL, 0);
struct termios newtio, oldtio;
if ( tcgetattr( fd, &oldtio ) != 0) {
perror("tcgetattr error");
return -1;
}
tcflush(fd, TCIOFLUSH);
bzero( &newtio, sizeof(newtio) );
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
newtio.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOE | IEXTEN);
newtio.c_oflag &= ~OPOST;
newtio.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | BRKINT | INPCK | ISTRIP);
newtio.c_cflag &= ~CRTSCTS;
switch ( bits ) {
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch (event) {
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E':
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
switch (speed) {
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
default:
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 19200:
cfsetispeed(&newtio, B19200);
cfsetospeed(&newtio, B19200);
break;
case 38400:
cfsetispeed(&newtio, B38400);
cfsetospeed(&newtio, B38400);
break;
case 57600:
cfsetispeed(&newtio, B57600);
cfsetospeed(&newtio, B57600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
case 230400:
cfsetispeed(&newtio, B230400);
cfsetospeed(&newtio, B230400);
break;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
break;
case 500000:
cfsetispeed(&newtio, B500000);
cfsetospeed(&newtio, B500000);
break;
case 576000:
cfsetispeed(&newtio, B576000);
cfsetospeed(&newtio, B576000);
break;
case 921600:
cfsetispeed(&newtio, B921600);
cfsetospeed(&newtio, B921600);
break;
case 1000000:
cfsetispeed(&newtio, B1000000);
cfsetospeed(&newtio, B1000000);
break;
case 1152000:
cfsetispeed(&newtio, B1152000);
cfsetospeed(&newtio, B1152000);
break;
case 1500000:
cfsetispeed(&newtio, B1500000);
cfsetospeed(&newtio, B1500000);
break;
case 2000000:
cfsetispeed(&newtio, B2000000);
cfsetospeed(&newtio, B2000000);
break;
case 2500000:
cfsetispeed(&newtio, B2500000);
cfsetospeed(&newtio, B2500000);
break;
case 3000000:
cfsetispeed(&newtio, B3000000);
cfsetospeed(&newtio, B3000000);
break;
case 3500000:
cfsetispeed(&newtio, B3500000);
cfsetospeed(&newtio, B3500000);
break;
case 4000000:
cfsetispeed(&newtio, B4000000);
cfsetospeed(&newtio, B4000000);
break;
}
if (stop == 1) {
newtio.c_cflag &= ~CSTOPB;
}
else if (stop == 2) {
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 5;
newtio.c_cc[VMIN] = 0;
if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
perror("set opt error");
return -1;
}
tcflush(fd, TCIFLUSH);
return 0;
}
int Uart::write(uint8_t * buf, size_t size)
{
if (fd < 0) {
return -1;
perror("Uart Init failed");
}
int ret = uart_write(fd, buf, size);
if (ret < 0) {
perror("uart write failed");
}
return ret;
}
int Uart::read(uint8_t * buf, size_t size)
{
if (fd < 0) {
return -1;
perror("Uart Init failed");
}
fd_set set;
struct timeval timeout;
FD_ZERO(&set);
FD_SET(fd, &set);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int ret = select(fd + 1, &set, NULL, NULL, &timeout);
if (ret > 0) {
ret = uart_read(fd, buf, size);
}
return ret;
}
int Uart::getFd()
{
return fd;
}
}
\ No newline at end of file
#pragma once
#include <iostream>
/*
usage:
Uart uart("ttyS1");
uart.SetOpt(115200, 8, 'N' 1);
*/
namespace awe
{
class Uart
{
public:
Uart(const char * dev);
~Uart();
/**
* @brief Set the Opt object
*
* @param speed : 4800/9600/19200/38400/57600/115200
* @param bits : 7/8
* @param event : O/E/N
* @param stop : 1/2
* @return int
*/
int setOpt(uint64_t speed, int bits, char event, int stop);
int write(uint8_t * buf, size_t size);
int read(uint8_t * buf, size_t size);
int getFd();
private:
int fd;
};
} // namespace awe
#/bin/env bash
# 计算当前目录
CURRENT_DIR=$(cd `dirname $0`; pwd)
if [ "$(id -u)" -ne 0 ]; then
SUDO="sudo"
fi
PKG_NAME="barrier_gate"
# 检查是否存在 aarch64-linux-gnu-gcc 和 aarch64-linux-gnu-g++ 不存在则安装
if ! which aarch64-linux-gnu-gcc > /dev/null 2>&1; then
$SUDO apt-get install -y gcc-aarch64-linux-gnu
fi
if ! which aarch64-linux-gnu-g++ > /dev/null 2>&1; then
$SUDO apt-get install -y g++-aarch64-linux-gnu
fi
build_target() {
AARCH=$1
# 进入 ${PKG_NAME} 目录,检查是否存在 build 目录,不存在则创建
echo ">> Build <${PKG_NAME}> Now..."
cd ${PKG_NAME}
if [ -d build ]; then
rm -rf build
fi
mkdir build && cd build
CC=${AARCH}-linux-gnu-gcc CXX=${AARCH}-linux-gnu-g++ cmake -DCMAKE_BUILD_TYPE=Release .. >> /dev/null
make -j4 >> /dev/null
cd ${CURRENT_DIR}
echo ">> Build <${PKG_NAME}> Done."
# 进行打包处理
if [ ! -d package ]; then
mkdir package
fi
echo ">> Pack <${PKG_NAME}> Now..."
if [ -d package/${PKG_NAME} ]; then
rm -rf package/${PKG_NAME}
fi
mkdir -p package/${PKG_NAME}-${AARCH}
cp -ra ${PKG_NAME}/build/${PKG_NAME} package/${PKG_NAME}-${AARCH}
cp -ra ${PKG_NAME}/lib/${AARCH}/* package/${PKG_NAME}-${AARCH}
cp -ra ${PKG_NAME}/config/config.json package/${PKG_NAME}-${AARCH}
cd package && tar -zvcf ${PKG_NAME}-${AARCH}.tar.gz ${PKG_NAME}-${AARCH} >> /dev/null && rm -rf ${PKG_NAME}-${AARCH} && cd - >> /dev/null
}
build_target aarch64
build_target x86_64
echo '>> Build Done.'
cd ${CURRENT_DIR}
ls -lh package
# 闸机控制
## 构建
```bash
./build.sh
```
构建完成后将产生 x86 和
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment