Browse Source

update

master
zhaohe 2 years ago
parent
commit
4f96a211bd
  1. 12
      README.md
  2. 2
      iflytoplinuxsdk
  3. 283
      src/extapi_service.cpp
  4. 44
      src/extapi_service.hpp
  5. 1
      src/main_control_service.hpp

12
README.md

@ -13,3 +13,15 @@
``` ```
./build.sh ./build.sh
``` ```
```
ref:https://iflytop1.feishu.cn/wiki/FstowhghKitYuTkcmuIcQybanxh
测试指令
ws://192.168.8.10:19005
index mcmd scmd type moduleid
ping cmd : 0111 0100 00 00 6400
read_reg :
```

2
iflytoplinuxsdk

@ -1 +1 @@
Subproject commit 03155dec4fafabcb38546e6b328269043815a4af
Subproject commit 5b54eeda6ca2cee017f4d0871165c20306d7e276

283
src/extapi_service.cpp

@ -48,6 +48,15 @@ void ExtAPIService::initialize(string can_if_name, int baudrate, bool enablLoopb
m_zmodule_device_manager.reset(new ZModuleDeviceManager()); m_zmodule_device_manager.reset(new ZModuleDeviceManager());
m_zmodule_device_manager->initialize(m_zcan_receiver_master.get()); m_zmodule_device_manager->initialize(m_zcan_receiver_master.get());
// m_zmodule_device_manager->registerModule();
for (size_t i = 1; i < 1000; i++) {
m_proxys[i].initialize(i, m_zcan_receiver_master.get());
m_zmodule_device_manager->registerModule(&m_proxys[i]);
}
/**
* @brief CAN通用指令解析器
*/
m_zmodule_device_script_cmder_paser.reset(new ZModuleDeviceScriptCmderPaser()); m_zmodule_device_script_cmder_paser.reset(new ZModuleDeviceScriptCmderPaser());
m_zmodule_device_script_cmder_paser->initialize(this, m_zmodule_device_manager.get()); m_zmodule_device_script_cmder_paser->initialize(this, m_zmodule_device_manager.get());
@ -66,80 +75,173 @@ void ExtAPIService::initialize(string can_if_name, int baudrate, bool enablLoopb
m_iflytopwsService->startListen(); m_iflytopwsService->startListen();
#endif #endif
/*******************************************************************************
* *
*******************************************************************************/
/** /**
* @brief
*
* *
* protocol: websocket
* port : 19004
* descript:
*/ */
m_script_server.reset(new WebSocketServer(19004, "0.0.0.0")); m_script_server.reset(new WebSocketServer(19004, "0.0.0.0"));
m_script_server->setOnConnectionCallback([this](weak_ptr<WebSocket> webSocket, shared_ptr<ConnectionState> connectionState) { m_script_server->setOnConnectionCallback([this](weak_ptr<WebSocket> webSocket, shared_ptr<ConnectionState> connectionState) {
logger->info("Remote ip: {}", connectionState->getRemoteIp());
// on new client connected
logger->info("remote ip: {} connect to 19004", connectionState->getRemoteIp());
auto ws = webSocket.lock(); auto ws = webSocket.lock();
if (!ws) return; if (!ws) return;
ws->setOnMessageCallback([this, webSocket, connectionState](const ix::WebSocketMessagePtr &msg) {
processcmds(msg->str, [this, webSocket, connectionState](string cmd, ICmdParserACK *ack) { //
string ackstr;
if (ack->acktype == ICmdParserACK::kAckType_none) {
ackstr = fmt::format("{} -> ecode:{}({})\n", cmd, err::error2str(ack->ecode), ack->ecode);
} else if (ack->acktype == ICmdParserACK::kAckType_int32) {
ackstr = fmt::format("{} -> ecode:{}({})\n", cmd, err::error2str(ack->ecode), ack->ecode);
for (int32_t i = 0; i < ack->getAckInt32Num(); i++) {
ackstr += fmt::format(" ack[{}]{}\n", i, ack->getAckInt32Val(i));
}
} else if (ack->acktype == ICmdParserACK::kAckType_buf) {
ackstr = fmt::format("{} -> ecode:{}({})\n", cmd, err::error2str(ack->ecode), ack->ecode);
ackstr = fmt::format(" ackbuf :{}", StringUtils().bytesToString(ack->rawdata, ack->rawlen));
ackstr = fmt::format(" ackbufstr:{}", string((const char *)ack->rawdata));
ws->setOnMessageCallback([this, webSocket](const ix::WebSocketMessagePtr &msg) {
if (msg->type == ix::WebSocketMessageType::Message) {
script_server_on_message(webSocket, msg);
} }
}); });
}); });
});
m_script_server->listenAndStart();
/*******************************************************************************
* CAN透传服务 *
*******************************************************************************/
/** /**
* @brief CAN透传服务
*
* protocol: websocket
* port : 19005
* descript: CAN数据
*
*/ */
m_can_passthrough_server.reset(new WebSocketServer(19005, "0.0.0.0")); m_can_passthrough_server.reset(new WebSocketServer(19005, "0.0.0.0"));
m_can_passthrough_server->setOnConnectionCallback([this](weak_ptr<WebSocket> webSocket, shared_ptr<ConnectionState> connectionState) { m_can_passthrough_server->setOnConnectionCallback([this](weak_ptr<WebSocket> webSocket, shared_ptr<ConnectionState> connectionState) {
logger->info("m_can_passthrough_server on connect remote ip: {}", connectionState->getRemoteIp()); logger->info("m_can_passthrough_server on connect remote ip: {}", connectionState->getRemoteIp());
auto ws = webSocket.lock(); auto ws = webSocket.lock();
if (!ws) return; if (!ws) return;
ws->setOnMessageCallback([this, webSocket, connectionState](const ix::WebSocketMessagePtr &msg) {
// msg->binary;
if (msg->binary) {
logger->info("rx:{}({})", StringUtils().bytesToString(msg->str.data(), msg->wireSize), msg->wireSize);
m_zcan_receiver_master->sendraw((uint8_t *)msg->str.data(), msg->str.size());
} else {
logger->info("rx:{}({})", msg->str, msg->wireSize);
ws->setOnMessageCallback([this, webSocket](const ix::WebSocketMessagePtr &msg) {
if (msg->type == ix::WebSocketMessageType::Message) {
logger->info("down can bin -> {}({})", msg->str, msg->wireSize);
vector<uint8_t> rxbyte; vector<uint8_t> rxbyte;
StringUtils().hexStringToBytes(msg->str, "", rxbyte); StringUtils().hexStringToBytes(msg->str, "", rxbyte);
m_zcan_receiver_master->sendraw(rxbyte.data(), rxbyte.size()); m_zcan_receiver_master->sendraw(rxbyte.data(), rxbyte.size());
} }
}); });
}); });
m_can_passthrough_server->listenAndStart();
m_zcan_receiver_master->regPacketListener([this](int32_t fromboard, zcr_cmd_header_t *packet, int32_t datalen) { m_zcan_receiver_master->regPacketListener([this](int32_t fromboard, zcr_cmd_header_t *packet, int32_t datalen) {
auto clients = m_can_passthrough_server->getClients(); auto clients = m_can_passthrough_server->getClients();
string rx = StringUtils().bytesToString((uint8_t *)packet, datalen); string rx = StringUtils().bytesToString((uint8_t *)packet, datalen);
logger->info("tx:{}({})", rx, datalen);
logger->info("report can bin -< {}({})", rx, datalen);
for (auto &each : clients) { for (auto &each : clients) {
if (each) each->sendText(rx); if (each) each->sendText(rx);
} }
}); });
m_zmodule_device_manager->regOnRegValChangeEvent([this](int32_t moduleid, int32_t regadd, int32_t toval) { //
logger->info("on reg change: moduleid:{} REG({}) to {}", moduleid, regadd, toval);
/*******************************************************************************
* *
*******************************************************************************/
/**
* @brief
*/
m_zmodule_device_manager->regOnRegValChangeEvent([this](int32_t moduleid, int32_t regindex, int32_t oldval, int32_t toval) { //
logger->info("on reg change: moduleid:{} REG({}) {} to {}", moduleid, regindex, oldval, toval);
// m_script_server 上报事件
{
auto clients = m_script_server->getClients();
for (auto &each : clients) {
if (each) each->sendText(fmt::format("on reg change: moduleid:{} REG({}) {} to {}", moduleid, regindex, oldval, toval));
}
}
}); });
}; };
/*******************************************************************************
* m_script_server *
*******************************************************************************/
void ExtAPIService::script_server_on_message(weak_ptr<WebSocket> webSocket, const ix::WebSocketMessagePtr &msg) {
logger->info("script_server_on_message:\n{}", msg->str);
script_processer_processcmds(
msg->str,
/*******************************************************************************
* PRIVATE_FN_PROCESSER *
*******************************************************************************/
[this, webSocket](string cmd, int32_t paramN, const char **paraV, ICmdParserACK *ack) {
auto ws = webSocket.lock();
if (!ws) return;
/*******************************************************************************
* HELP *
*******************************************************************************/
if (cmd == "help") {
ack->ecode = 0;
string helpinfo;
helpinfo += fmt::format("cmdlist:\n");
for (auto it = m_cmdmap.begin(); it != m_cmdmap.end(); it++) {
// ws->sendText(fmt::format("\t{} {}", it->first, it->second.helpinfo));
helpinfo += fmt::format("\t{} {}\n", it->first, it->second.helpinfo);
}
ws->sendText(helpinfo);
return;
}
if (cmd == "app_scan_moudle") {
ack->ecode = 0;
string helpinfo;
helpinfo += fmt::format("cmdlist:\n");
for (auto it = m_cmdmap.begin(); it != m_cmdmap.end(); it++) {
// ws->sendText(fmt::format("\t{} {}", it->first, it->second.helpinfo));
helpinfo += fmt::format("\t{} {}\n", it->first, it->second.helpinfo);
}
ws->sendText(helpinfo);
return;
}
},
/*******************************************************************************
* ACK_PROCESSER *
*******************************************************************************/
[this, webSocket](string cmd, ICmdParserACK *ack) { //
logger->info("do {},{}({})", cmd, ack->ecode, err::error2str(ack->ecode));
string ackstr;
if (ack->acktype == ICmdParserACK::kAckType_none) {
ackstr += fmt::format("{} -> ecode:{}({})\n", cmd, err::error2str(ack->ecode), ack->ecode);
} else if (ack->acktype == ICmdParserACK::kAckType_int32) {
ackstr += fmt::format("{} -> ecode:{}({})\n", cmd, err::error2str(ack->ecode), ack->ecode);
for (int32_t i = 0; i < ack->getAckInt32Num(); i++) {
ackstr += fmt::format(" ack[{}]{}\n", i, ack->getAckInt32Val(i));
}
} else if (ack->acktype == ICmdParserACK::kAckType_buf) {
ackstr += fmt::format("{} -> ecode:{}({})\n", cmd, err::error2str(ack->ecode), ack->ecode);
ackstr += tools_dumpbuffer(ack->rawdata, ack->rawlen);
} else if (ack->acktype == ICmdParserACK::kAckType_str) {
ackstr += fmt::format("{} -> ecode:{}({})\n", cmd, err::error2str(ack->ecode), ack->ecode);
ackstr = fmt::format(" ackbufstr:{}", string((const char *)ack->rawdata));
}
auto ws = webSocket.lock();
if (ws) ws->sendText(ackstr);
});
}
void ExtAPIService::regfns() {
this->regCMD("", "", 2, [](int32_t paramN, const char **paraV, ICmdParserACK *ack) {
/**
* @brief who call me?
*/
});
}
/*******************************************************************************
* *
*******************************************************************************/
void ExtAPIService::regCMD(const char *cmdname, const char *helpinfo, int paraNum, ICmdFunction_t cmdimpl) { void ExtAPIService::regCMD(const char *cmdname, const char *helpinfo, int paraNum, ICmdFunction_t cmdimpl) {
cmd_container_t cmd_container; cmd_container_t cmd_container;
cmd_container.cmdname = cmdname; cmd_container.cmdname = cmdname;
cmd_container.helpinfo = helpinfo; cmd_container.helpinfo = helpinfo;
cmd_container.paraNum = paraNum; cmd_container.paraNum = paraNum;
cmd_container.cmdimpl = cmdimpl;
m_cmdmap[cmdname] = cmd_container; m_cmdmap[cmdname] = cmd_container;
} }
void ExtAPIService::processcmds(string script, function<void(string cmd, ICmdParserACK *ack)> ackprocesser) {
void ExtAPIService::script_processer_processcmds(string script, private_fn_processer_t private_fn_processer, ackprocesser_t ackprocesser) {
/** /**
* @brief * @brief
* script: * script:
@ -161,67 +263,138 @@ void ExtAPIService::processcmds(string script, function<void(string cmd, ICmdPar
for (int32_t i = 0; i < stringlen; i++) { for (int32_t i = 0; i < stringlen; i++) {
if (currentstr == nullptr) { if (currentstr == nullptr) {
if (strcache[i] != '\0') { if (strcache[i] != '\0') {
// logger->info("new cmd:{}", &strcache[i]);
currentstr = &strcache[i]; currentstr = &strcache[i];
cmdlines.push_back(currentstr);
} }
} else { } else {
if (strcache[i] == '\0') { if (strcache[i] == '\0') {
cmdlines.push_back(currentstr);
currentstr = nullptr; currentstr = nullptr;
} }
} }
} }
for (auto &cmdline : cmdlines) { for (auto &cmdline : cmdlines) {
ICmdParserACK ack = {0};
bool isnote = false;
callcmd(cmdline, &ack, isnote);
if (isnote) continue;
if (ackprocesser) ackprocesser(cmdline, &ack);
// bool isnote = false;
FnProcessContext cxt;
cxt.private_fn_processer = private_fn_processer;
cxt.ackprocesser = ackprocesser;
// logger->info("do {}", cmdline);
script_processer_callcmd(cmdline, cxt);
if (cxt.breakflag) break;
} }
free(strcache); free(strcache);
} }
void removenote(char *buf);
void ExtAPIService::callcmd(string cmd, ICmdParserACK *ack, bool &isnote) {
char *argv[10];
void ExtAPIService::script_processer_callcmd(string cmd, FnProcessContext &cxt) {
char *argv[30] = {0};
int32_t argc = 0; int32_t argc = 0;
char cmdcache[1024] = {0}; char cmdcache[1024] = {0};
strncmp(cmdcache, cmd.c_str(), 1023);
strncpy(cmdcache, cmd.c_str(), 1023);
// remove note // remove note
for (size_t i = 0; i < cmd.length(); i++) { for (size_t i = 0; i < cmd.length(); i++) {
if (cmdcache[i] == '#') { if (cmdcache[i] == '#') {
cmdcache[i] = '\0'; cmdcache[i] = '\0';
if (i == 0) { if (i == 0) {
isnote = true;
// is note return;
return; return;
} }
break; break;
} }
} }
char *p = strtok(cmdcache, " ");
while (p != NULL) {
argv[argc] = p;
argc++;
p = strtok(NULL, " ");
// logger->info("cmdcache:{}", cmdcache);
for (int32_t i = 0; i < cmd.length(); i++) {
if (cmdcache[i] == '\n' || cmdcache[i] == '\r' || cmdcache[i] == ' ' || cmdcache[i] == 127) {
cmdcache[i] = '\0';
}
}
int j = 0;
for (int i = 0; cmdcache[i] == 0 || i < cmd.length(); i++) {
if (cmdcache[i] != 0 && j == 0) {
argv[argc++] = &cmdcache[i];
j = 1;
continue;
}
if (cmdcache[i] == 0 && j == 1) {
j = 0;
continue;
}
}
logger->info("argc:{}", argc);
for (int i = 0; i < argc; i++) {
logger->info("argv[{}]:{}", i, argv[i]);
}
if (argc == 0) {
return;
} }
callcmd(argv[0], argc - 1, (const char **)(argv + 1), ack);
script_processer_callcmd(cxt, argv[0], argc - 1, (const char **)(argv + 1));
} }
void ExtAPIService::callcmd(string cmdname, int32_t paramN, const char **paraV, ICmdParserACK *ack) {
void ExtAPIService::script_processer_callcmd(FnProcessContext &cxt, string cmdname, int32_t paramN, const char **paraV) {
std::lock_guard<std::recursive_mutex> lock(m_cmdmaplock_); std::lock_guard<std::recursive_mutex> lock(m_cmdmaplock_);
auto it = m_cmdmap.find(cmdname); auto it = m_cmdmap.find(cmdname);
if (it == m_cmdmap.end()) {
ack->ecode = err::kcmd_not_found;
return;
}
logger->info("call cmd:{} paramN:{}", cmdname, paramN);
ICmdParserACK ack = {0};
if (it != m_cmdmap.end()) {
cmd_container_t cmd_container = it->second; cmd_container_t cmd_container = it->second;
if (cmd_container.paraNum != paramN) { if (cmd_container.paraNum != paramN) {
ack->ecode = err::kcmd_param_num_error;
ack.ecode = err::kcmd_param_num_error;
return; return;
} }
cmd_container.cmdimpl(paramN, paraV, ack);
if (cmd_container.cmdimpl) {
cmd_container.cmdimpl(paramN, paraV, &ack);
} else {
logger->info("cmd:{} not impl", cmdname);
}
} else {
ack.ecode = err::kcmd_not_found;
if (cxt.private_fn_processer) cxt.private_fn_processer(cmdname, paramN, paraV, &ack);
}
if (cxt.ackprocesser) cxt.ackprocesser(cmdname, &ack);
if (ack.ecode != err::ksucc) cxt.breakflag = true;
}
/*******************************************************************************
* TOOLS *
*******************************************************************************/
string ExtAPIService::tools_dumpbuffer(uint8_t *data, int32_t len) {
int32_t align = 32;
string ret;
for (int32_t i = 0; i < len;) {
for (int32_t j = 0; j < align; j++) {
if (i + j < len) {
ret += fmt::format("{:02X} ", data[i + j]);
} else {
ret += " ";
}
}
ret += "|";
for (int32_t j = 0; j < align; j++) {
if (i + j < len) {
if (isprint(data[i + j])) {
ret += fmt::format("{}", data[i + j]);
} else {
ret += ".";
}
} else {
ret += " ";
}
}
ret += "\n";
}
return ret;
} }

44
src/extapi_service.hpp

@ -30,9 +30,8 @@
// //
#include <mutex> #include <mutex>
#include "iflytop/components/zcanreceiver/zcanhost.hpp"
#include "iflytop/components/zcanreceiver/zcanreceiver_master.hpp" #include "iflytop/components/zcanreceiver/zcanreceiver_master.hpp"
#include "iflytoplinuxsdk/src/iflytop/zprotocols/protocol_proxy.hpp"
/** /**
* @brief * @brief
* *
@ -43,6 +42,7 @@
namespace iflytop { namespace iflytop {
using namespace std; using namespace std;
using namespace core; using namespace core;
class ExtAPIService : public ICmdParser { class ExtAPIService : public ICmdParser {
ENABLE_LOGGER(ExtAPIService); ENABLE_LOGGER(ExtAPIService);
@ -50,16 +50,19 @@ class ExtAPIService : public ICmdParser {
shared_ptr<RestfulServer> m_restfulServer; // 20000,20001 shared_ptr<RestfulServer> m_restfulServer; // 20000,20001
shared_ptr<IflytopFrontEndService> m_iflytopwsService; // 19001,19002 shared_ptr<IflytopFrontEndService> m_iflytopwsService; // 19001,19002
shared_ptr<ix::WebSocketServer> m_can_passthrough_server; // 19003 shared_ptr<ix::WebSocketServer> m_can_passthrough_server; // 19003
shared_ptr<ix::WebSocketServer> m_script_server; // 19004 shared_ptr<ix::WebSocketServer> m_script_server; // 19004
// shared_ptr<ix::WebSocketServer> m_event_report_server; // 19005
shared_ptr<ZcanReceiverMaster> m_zcan_receiver_master; shared_ptr<ZcanReceiverMaster> m_zcan_receiver_master;
shared_ptr<ZModuleDeviceManager> m_zmodule_device_manager; shared_ptr<ZModuleDeviceManager> m_zmodule_device_manager;
shared_ptr<ZModuleDeviceScriptCmderPaser> m_zmodule_device_script_cmder_paser; shared_ptr<ZModuleDeviceScriptCmderPaser> m_zmodule_device_script_cmder_paser;
ZIProtocolProxy m_proxys[1000];
// cmd // cmd
typedef function<void(string cmd, int32_t paramN, const char **paraV, ICmdParserACK *ack)> private_fn_processer_t;
typedef function<void(string cmd, ICmdParserACK *ack)> ackprocesser_t;
typedef struct { typedef struct {
string cmdname; string cmdname;
string helpinfo; string helpinfo;
@ -67,6 +70,13 @@ class ExtAPIService : public ICmdParser {
ICmdFunction_t cmdimpl; ICmdFunction_t cmdimpl;
} cmd_container_t; } cmd_container_t;
class FnProcessContext {
public:
private_fn_processer_t private_fn_processer = nullptr;
ackprocesser_t ackprocesser = nullptr;
bool breakflag = false;
};
map<string, cmd_container_t> m_cmdmap; map<string, cmd_container_t> m_cmdmap;
std::recursive_mutex m_cmdmaplock_; std::recursive_mutex m_cmdmaplock_;
@ -85,9 +95,29 @@ class ExtAPIService : public ICmdParser {
private: private:
void dosystem(string order); void dosystem(string order);
void processcmds(string script, function<void(string cmd, ICmdParserACK *ack)> ackprocesser);
void removenote(char *buf); void removenote(char *buf);
void callcmd(string cmd, ICmdParserACK *ack,bool &isnote);
void callcmd(string cmdname, int32_t paramN, const char **paraV, ICmdParserACK *ack);
/*******************************************************************************
* TOOLS *
*******************************************************************************/
string tools_dumpbuffer(uint8_t *data, int32_t len);
/*******************************************************************************
* m_script_server *
*******************************************************************************/
void script_server_on_message(weak_ptr<WebSocket> webSocket, const ix::WebSocketMessagePtr &msg);
/*******************************************************************************
* *
*******************************************************************************/
void script_processer_processcmds(string script, private_fn_processer_t private_fn_processer, ackprocesser_t ackprocesser);
void script_processer_callcmd(string cmd, FnProcessContext &cxt);
void script_processer_callcmd(FnProcessContext &cxt, string cmdname, int32_t paramN, const char **paraV);
/*******************************************************************************
* *
*******************************************************************************/
void regfns();
}; };
} // namespace iflytop } // namespace iflytop

1
src/main_control_service.hpp

@ -27,7 +27,6 @@
// //
#include "extapi_service.hpp" #include "extapi_service.hpp"
#include "iflytop/components/zcanreceiver/zcanhost.hpp"
/** /**
* @brief * @brief

Loading…
Cancel
Save