diff --git a/src/iflytop/components/iflytop_front_end_service/iflytop_front_end_service.cpp b/src/iflytop/components/iflytop_front_end_service/iflytop_front_end_service.cpp index 32c5098..4214fdb 100644 --- a/src/iflytop/components/iflytop_front_end_service/iflytop_front_end_service.cpp +++ b/src/iflytop/components/iflytop_front_end_service/iflytop_front_end_service.cpp @@ -35,6 +35,13 @@ void IflytopFrontEndService::initialize(string ip) { ws->setOnMessageCallback([this, webSocket, connectionState](const ix::WebSocketMessagePtr& msg) {}); }); + m_udp.reset(new SimpleUDP()); + m_udp->initialize(19003); + m_udp->set_on_recv([this](struct sockaddr_in* from, char* data, size_t len) { + logger->info("recv udp data: {}", string(data, len)); + onUdpCmdMessage(from, data, len); + }); + m_initialized = true; } void IflytopFrontEndService::startListen() { @@ -143,8 +150,8 @@ void IflytopFrontEndService::processRxMessage(weak_ptr webSocket, con logger->error("m_iflytopWSService:onMessag,process rx json failed,exception:{},{}", e.what(), msgtext); if (command.find("need_receipt") == command.end() || command["need_receipt"]) { shared_ptr ws = webSocket.lock(); - receipt["ackcode"] = err::error_code_get_get_ecode(err::kcommon_error_code, err::kparse_json_err); - receipt["ackcodeInfo"] = err::error_code_get_desc(err::kcommon_error_code, err::kparse_json_err, e.what()); + receipt["ackcode"] = err::error_code_get_get_ecode(err::kce, err::kparse_json_err); + receipt["ackcodeInfo"] = err::error_code_get_desc(err::kce, err::kparse_json_err, e.what()); if (ws) ws->sendText(receipt.dump(1)); } diff --git a/src/iflytop/components/iflytop_front_end_service/iflytop_front_end_service.hpp b/src/iflytop/components/iflytop_front_end_service/iflytop_front_end_service.hpp index 581fce9..69b73a8 100644 --- a/src/iflytop/components/iflytop_front_end_service/iflytop_front_end_service.hpp +++ b/src/iflytop/components/iflytop_front_end_service/iflytop_front_end_service.hpp @@ -15,6 +15,7 @@ #include #include +#include "iflytop/components/simple_udp/simple_udp.hpp" #include "iflytop/core/basic/nod/nod.hpp" #include "iflytop/core/spdlogfactory/logger.hpp" /** @@ -46,12 +47,15 @@ class IflytopFrontEndService : public enable_shared_from_this webSocket, json& cmd, json& receipt)> onMessage; + nod::signal onUdpCmdMessage; + private: // // WebSocketServer的使用参考:http://192.168.1.3:3000/z3rd_lib/IXWebSocket/src/branch/master/docs/usage.md // shared_ptr m_server; shared_ptr m_report_server; + shared_ptr m_udp; bool m_initialized = false; public: @@ -61,6 +65,8 @@ class IflytopFrontEndService : public enable_shared_from_thissendto(from, data, len); } + private: void onMessageCallback(weak_ptr webSocket, shared_ptr connectionState, const ix::WebSocketMessagePtr& msg); void processRxMessage(weak_ptr webSocket, const ix::WebSocketMessagePtr& msg); diff --git a/src/iflytop/components/simple_udp/simple_udp.cpp b/src/iflytop/components/simple_udp/simple_udp.cpp new file mode 100644 index 0000000..e1430ae --- /dev/null +++ b/src/iflytop/components/simple_udp/simple_udp.cpp @@ -0,0 +1,55 @@ +#include "simple_udp.hpp" + + + +using namespace std; +using namespace iflytop; +using namespace core; + +void SimpleUDP::initialize(int port) { + // 建立一个UDP的socket + m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (m_socket == -1) { + logger->error("socket failed"); + return; + } + // 绑定地址信息 + + struct sockaddr_in servaddr; + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(m_socket, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { + logger->error("bind {} failed,", port); + return; + } + logger->info("bind {} success", port); + + m_thread.reset(new Thread("udpThread", [this]() { // + struct sockaddr_in peeraddr; + socklen_t peerlen; + while (true) { + memset(m_rxbuf, 0, sizeof(m_rxbuf)); + // 网络节点的信息,用来保存客户端的网络信息 + // sockaddr_in clientAddr; + memset(&peeraddr, 0, sizeof(sockaddr_in)); + int clientAddrLen = sizeof(sockaddr); + // 接收客户端发来的数据 + int ret = recvfrom(m_socket, m_rxbuf, sizeof(m_rxbuf), 0, (struct sockaddr *)&peeraddr, &peerlen); + // printf("Recv msg:%s from IP:[%s] Port:[%d]\n", m_rxbuf, inet_ntoa(m_context.clientAddr.sin_addr), ntohs(m_context.clientAddr.sin_port)); + // process_rx_cmd(m_rxbuf, ret); + // sendto(m_socket, "Hello World!", strlen("Hello World!"), 0, (sockaddr *)&m_context.clientAddr, clientAddrLen); + if (ret < 0) { + logger->error("recvfrom failed, {}", strerror(errno)); + continue; + } + if (m_on_recv) { + m_on_recv(&peeraddr, m_rxbuf, ret); + } + } + })); + return; +}; \ No newline at end of file diff --git a/src/iflytop/components/simple_udp/simple_udp.hpp b/src/iflytop/components/simple_udp/simple_udp.hpp new file mode 100644 index 0000000..c8c9978 --- /dev/null +++ b/src/iflytop/components/simple_udp/simple_udp.hpp @@ -0,0 +1,58 @@ +// +// Created by zwsd +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include /* See NOTES */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iflytop/core/core.hpp" +/** + * @brief + * + * service: SimpleUDP + * + * 监听事件: + * 依赖状态: + * 依赖服务: + * 作用: + * + */ + +namespace iflytop { +using namespace std; +using namespace core; +class SimpleUDP : public enable_shared_from_this { + ENABLE_LOGGER(SimpleUDP); + int m_socket = -1; + unique_ptr m_thread; + char m_rxbuf[1024]; + + typedef function on_recv_t; + + on_recv_t m_on_recv; + + public: + SimpleUDP(){}; + void initialize(int port); + void set_on_recv(on_recv_t on_recv) { m_on_recv = on_recv; } + void sendto(struct sockaddr_in* from, const char* data, size_t len) { ::sendto(m_socket, data, len, 0, (struct sockaddr*)from, sizeof(struct sockaddr_in)); } +}; +} // namespace iflytop \ No newline at end of file diff --git a/src/iflytop/components/zcanreceiver/zcanhost.cpp b/src/iflytop/components/zcanreceiver/zcanhost.cpp new file mode 100644 index 0000000..0ac3313 --- /dev/null +++ b/src/iflytop/components/zcanreceiver/zcanhost.cpp @@ -0,0 +1,158 @@ +#include "zcanhost.hpp" + +using namespace iflytop; +using namespace core; +using namespace zcr; + +#define zint16p(x) ((int16_t*)(x)) +#define zint32p(x) ((int32_t*)(x)) + +void ZCanHost::initialize(string can_if_name, int baudrate, bool enablLoopback) { + m_zcanReceiverHost = make_shared(); + m_zcanReceiverHost->initialize(can_if_name, baudrate, enablLoopback); +} + +static void prase_cmd(char* input, int inputlen, int& argc, char* argv[]) { + bool findcomment = false; + for (size_t i = 0; input[i] == 0 || i < inputlen; i++) { + if (input[i] == ' ' || input[i] == '\r' || input[i] == '\n' || input[i] == '\t') { + input[i] = 0; + } + + if (input[i] == '#') { + findcomment = true; + } + if (findcomment) { + input[i] = 0; + } + } + + int j = 0; + for (size_t i = 0; input[i] == 0 || i < inputlen; i++) { + if (input[i] != 0 && j == 0) { + argv[argc++] = &input[i]; + j = 1; + continue; + } + + if (input[i] == 0 && j == 1) { + j = 0; + continue; + } + } +} + +bool ZCanHost::execcmd(string cmd, string& retval) { + int argc = 0; + char* argv[10] = {0}; + char cmdcache[1024] = {0}; + // context.rawcmd = cmd; + strcpy(cmdcache, cmd.c_str()); + logger->info("do cmd:{}", cmdcache); + + for (size_t i = 0; i < cmd.size(); i++) { + if (cmdcache[i] == '#') { + cmdcache[i] = '\0'; + } + } + prase_cmd(cmdcache, strlen(cmdcache), argc, argv); + if (argc == 0) { + logger->error("cmd:{} prase error", cmd); + return false; + } + + if (m_cmdMap.find(string(argv[0])) != m_cmdMap.end()) { + return m_cmdMap.find(string(argv[0]))->second(argc, argv, retval); + } + logger->error("cmd:{} not found", argv[0]); + return false; +} + +/******************************************************************************* + * CMD * + *******************************************************************************/ +/** + * @brief 0-1000 Command support + */ +bool ZCanHost::ping(int board_id) { + shared_ptr cmd = make_shared(); + cmd->cmdid = 0; + cmd->subcmdid = 0; + cmd->data[0] = board_id; + cmd->len = 1; + auto rx = m_zcanReceiverHost->sendcmdblock(cmd, 100); + return rx != nullptr; +} + +int32_t ZCanHost::readio(int id, bool& value) { + shared_ptr cmd = make_shared(); + cmd->cmdid = 1; + cmd->subcmdid = 0; + cmd->data[0] = id; + cmd->len = 1; + auto rx = m_zcanReceiverHost->sendcmdblock(cmd, 100); + if (rx == nullptr) { + return err::zecode(err::knoack); + } + value = rx->data[1]; + return 0; +} +int32_t ZCanHost::writeio(int id, bool value) { + shared_ptr cmd = make_shared(); + cmd->cmdid = 2; + cmd->subcmdid = 0; + cmd->data[0] = id; + cmd->data[1] = value; + cmd->len = 2; + auto rx = m_zcanReceiverHost->sendcmdblock(cmd, 100); + if (rx == nullptr) { + return err::zecode(err::knoack); + } + return 0; +} +int32_t ZCanHost::readadc(int id, int& value) { + shared_ptr cmd = make_shared(); + cmd->cmdid = 3; + cmd->subcmdid = 0; + cmd->data[0] = id; + cmd->len = 1; + auto rx = m_zcanReceiverHost->sendcmdblock(cmd, 100); + if (rx == nullptr) { + return err::zecode(err::knoack); + } + value = *(int32_t*)(&rx->data[2]); + return 0; +} + +// 1004 +bool ZCanHost::pumpctrl_c1004(int sensorid, int16_t acc, int16_t rpm) { + shared_ptr cmd = make_shared(); + cmd->cmdid = 1004; + cmd->subcmdid = 0; + cmd->data[0] = sensorid; + *zint16p(&cmd->data[2]) = acc; + *zint16p(&cmd->data[4]) = rpm; + cmd->len = 6; + auto rx = m_zcanReceiverHost->sendcmdblock(cmd, 100); + return rx != nullptr; +} + +/** + * @brief 报警三色指示灯控制 + * + * @param sensorid + * @param r + * @param g + * @param b + * @param w + */ +bool ZCanHost::warning_light_ctrl_c1002(uint8_t sensorid, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { return false; } + +/** + * @brief 读取华成压力传感器数值 + * + * @param sensorid + * @param value + */ + +bool ZCanHost::huacheng_pressure_sensor_read_c1005(int sensorid, huacheng_pressure_sensor_read_c1005_t& value) { return false; } \ No newline at end of file diff --git a/src/iflytop/components/zcanreceiver/zcanhost.hpp b/src/iflytop/components/zcanreceiver/zcanhost.hpp new file mode 100644 index 0000000..f741a29 --- /dev/null +++ b/src/iflytop/components/zcanreceiver/zcanhost.hpp @@ -0,0 +1,70 @@ +// +// Created by zwsd +// + +#pragma once + +#include "cmd.hpp" +#include "iflytop/core/core.hpp" +#include "zcanreceiverhost.hpp" + +namespace iflytop { + +using namespace std; +using namespace zcr; +using namespace core; + +class ZCanHost { + ENABLE_LOGGER(ZCanHost); + + shared_ptr m_zcanReceiverHost; + + map> m_cmdMap; + + public: + void initialize(string can_if_name, int baudrate, bool enablLoopback); + bool execcmd(string cmd, string& retval); + + /******************************************************************************* + * CMD * + *******************************************************************************/ + /** + * @brief 0-1000 Command support + */ + bool ping(int board_id); + + int32_t readio(int id, bool& value); + int32_t writeio(int id, bool value); + int32_t readadc(int id, int& value); + + // 1004 + bool pumpctrl_c1004(int sensorid, int16_t acc, int16_t rpm); + + /** + * @brief 报警三色指示灯控制 + * + * @param sensorid + * @param r + * @param g + * @param b + * @param w + */ + bool warning_light_ctrl_c1002(uint8_t sensorid, uint8_t r, uint8_t g, uint8_t b, uint8_t w); + + /** + * @brief 读取华成压力传感器数值 + * + * @param sensorid + * @param value + */ + typedef struct { + uint8_t precision; // 0,1,2,3 + uint8_t unit; // 0-Mpa ,1-Kpa ,2-Pa ,3-Bar ,4-Mbar ,5-kg/cm2 ,6-psi ,7-mh2o ,8-mmh2o + uint16_t value; // value, realvalue = value / 10^precision unit + uint16_t zero; // 零点 + uint16_t full; // 满量程 + } huacheng_pressure_sensor_read_c1005_t; + bool huacheng_pressure_sensor_read_c1005(int sensorid, huacheng_pressure_sensor_read_c1005_t& value); +}; + +} // namespace iflytop \ No newline at end of file diff --git a/src/iflytop/components/zcanreceiver/zcanreceiverhost.cpp b/src/iflytop/components/zcanreceiver/zcanreceiverhost.cpp index 1f6344e..38e08ff 100644 --- a/src/iflytop/components/zcanreceiver/zcanreceiverhost.cpp +++ b/src/iflytop/components/zcanreceiver/zcanreceiverhost.cpp @@ -52,7 +52,15 @@ shared_ptr ZCanReceiverHost::sendcmdblock(shared_ptrpacketindex = packetindex; + + m_index++; + if (m_index == 0) { + m_index = 1; + } + if (m_index == UINT16_MAX) { + m_index = 1; + } + header->packetindex = m_index; header->cmdid = cmdid; header->subcmdid = subcmdid; header->packetType = 0x00; diff --git a/src/iflytop/components/zcanreceiver/zcanreceiverhost.hpp b/src/iflytop/components/zcanreceiver/zcanreceiverhost.hpp index a41b1f2..5ff56aa 100644 --- a/src/iflytop/components/zcanreceiver/zcanreceiverhost.hpp +++ b/src/iflytop/components/zcanreceiver/zcanreceiverhost.hpp @@ -20,10 +20,10 @@ using namespace core; class ZCanReceiverCMD { public: - uint16_t packetindex; - uint16_t cmdid; - uint8_t subcmdid; - uint8_t data[255 * 8]; + uint16_t packetindex = 0; + uint16_t cmdid = 0; + uint8_t subcmdid = 0; + uint8_t data[255 * 8] = {0}; size_t len; string toString() { return fmt::format("{}-{}:{} {}", packetindex, cmdid, subcmdid, StringUtils().bytesToString(data, len)); } @@ -57,6 +57,8 @@ class ZCanReceiverHost { onpacket_t m_onpacket; uint8_t m_deviceId = 1; + uint16_t m_index = 1; + shared_ptr m_socketCan; mutex m_txblocklock; diff --git a/src/iflytop/core/core.hpp b/src/iflytop/core/core.hpp index ab3da2b..e339a65 100644 --- a/src/iflytop/core/core.hpp +++ b/src/iflytop/core/core.hpp @@ -1,8 +1,21 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iflytop/core/basic/nlohmann/json.hpp" #include "iflytop/core/basic/nod/nod.hpp" +#include "iflytop/core/components/stringutils.hpp" #include "iflytop/core/components/timeutils.hpp" #include "iflytop/core/error/error_code.hpp" #include "iflytop/core/spdlogfactory/logger.hpp" #include "iflytop/core/thread/thread.hpp" -#include "iflytop/core/components/stringutils.hpp" diff --git a/src/iflytop/core/error/error_code.cpp b/src/iflytop/core/error/error_code.cpp index 875c8b6..292dcfc 100644 --- a/src/iflytop/core/error/error_code.cpp +++ b/src/iflytop/core/error/error_code.cpp @@ -6,9 +6,9 @@ namespace err { using namespace std; // static set ecode_desc_set = { -// {kcommon_error_code, kovertime, "overtime"}, -// {kcommon_error_code, kdevice_offline, "kdevice_offline"}, -// {kcommon_error_code, kpasswd_error, "kpasswd_error"}, +// {kce, kovertime, "overtime"}, +// {kce, kdevice_offline, "kdevice_offline"}, +// {kce, kpasswd_error, "kpasswd_error"}, // }; // kovertime @@ -18,13 +18,14 @@ using namespace std; // kpasswd_error // kuser_not_exist static vector ecode_desc_set = { - {kcommon_error_code, kovertime, "overtime"}, - {kcommon_error_code, kdevice_offline, "kdevice_offline"}, - {kcommon_error_code, kparse_json_err, "kparse_json_err"}, - {kcommon_error_code, kcatch_exception, "kcatch_exception"}, - {kcommon_error_code, kpasswd_error, "kpasswd_error"}, - {kcommon_error_code, kuser_not_exist, "kuser_not_exist"}, - {kcommon_error_code, kdb_operate_error, "kuser_not_exist"}, + {kce, kovertime, "overtime"}, + {kce, knoack, "noack"}, + {kce, kdevice_offline, "kdevice_offline"}, + {kce, kparse_json_err, "kparse_json_err"}, + {kce, kcatch_exception, "kcatch_exception"}, + {kce, kpasswd_error, "kpasswd_error"}, + {kce, kuser_not_exist, "kuser_not_exist"}, + {kce, kdb_operate_error, "kuser_not_exist"}, }; diff --git a/src/iflytop/core/error/error_code.hpp b/src/iflytop/core/error/error_code.hpp index 31ce7d5..de59acd 100644 --- a/src/iflytop/core/error/error_code.hpp +++ b/src/iflytop/core/error/error_code.hpp @@ -18,6 +18,7 @@ namespace err { using namespace std; typedef enum { kovertime = 1, + knoack, kdevice_offline, kparse_json_err, kcatch_exception, @@ -27,7 +28,7 @@ typedef enum { } common_error_code_t; typedef enum { - kcommon_error_code = 1, + kce = 1, // common error code } error_type_t; class error_code_desc_t { @@ -37,8 +38,16 @@ class error_code_desc_t { string desc; }; -int32_t error_code_get_get_ecode(error_type_t error_type, int sub_error_code); -string error_code_get_desc(error_type_t error_type, int sub_error_code, string extdes); +int32_t error_code_get_get_ecode(error_type_t error_type, int sub_error_code); +static inline int32_t zecode(error_type_t error_type, int sub_error_code) { return error_code_get_get_ecode(error_type, sub_error_code); } +static inline int32_t zecode(common_error_code_t sub_error_code) { return error_code_get_get_ecode(kce, sub_error_code); } + +string error_code_get_desc(error_type_t error_type, int sub_error_code, string extdes); +static inline string zecode_desc(int32_t ecode, string extdes) { + error_type_t error_type = (error_type_t)(ecode / 1000); + int sub_error_code = ecode % 1000; + return error_code_get_desc(error_type, sub_error_code, extdes); +} } // namespace err