diff --git a/components/cmdscheduler/cmd_scheduler.hpp b/components/cmdscheduler/cmd_scheduler.hpp index fe0e66a..4d467c5 100644 --- a/components/cmdscheduler/cmd_scheduler.hpp +++ b/components/cmdscheduler/cmd_scheduler.hpp @@ -4,6 +4,7 @@ #include "sdk/os/zos.hpp" #include "sdk\components\zprotocols\errorcode\errorcode.hpp" +#include "sdk\components\zprotocols\zcancmder_v2\api\api.hpp" namespace iflytop { using namespace std; diff --git a/components/cmdscheduler/cmd_scheduler_v2.cpp b/components/cmdscheduler/cmd_scheduler_v2.cpp new file mode 100644 index 0000000..5b3f2a3 --- /dev/null +++ b/components/cmdscheduler/cmd_scheduler_v2.cpp @@ -0,0 +1,189 @@ + +#include "cmd_scheduler_v2.hpp" + +#include +#include + +#include "sdk\components\zprotocols\errorcode\errorcode.hpp" +using namespace iflytop; + +#define TAG "CMD" + +void CmdSchedulerV2::registerCmd(const char* cmdname, const char* helpinfo, int paraNum, ICmdFunction_t cmdimpl) { + CMD cmdinfo; + cmdinfo.call_cmd = cmdimpl; + cmdinfo.help_info = helpinfo; + cmdinfo.npara = paraNum; + m_cmdMap[cmdname] = cmdinfo; +} + +void CmdSchedulerV2::regbasiccmd() { + this->registerCmd("help", "", 0, [this](int32_t paramN, const char* paraV[], ICmdParserACK* ack) { + ZLOGI(TAG, "cmdlist:"); + for (auto it = m_cmdMap.begin(); it != m_cmdMap.end(); it++) { + ZLOGI(TAG, " %s %s", it->first.c_str(), it->second.help_info.c_str()); + } + return (int32_t)0; + }); + this->registerCmd("sleep_ms", "(ms)", 1, [this](int32_t paramN, const char* paraV[], ICmdParserACK* ack) { + int ms = atoi(paraV[0]); + osDelay(ms); + return 0; + }); +} + +void CmdSchedulerV2::initialize(UART_HandleTypeDef* huart, uint32_t rxbufsize) { + m_rxbufsize = rxbufsize; + + m_uart = new ZUART(); + ZASSERT(m_uart != NULL); + + ZUART::cfg_t cfg; + cfg.huart = huart; + cfg.rxbuffersize = rxbufsize; + cfg.rxovertime_ms = 3; + cfg.name = "CmdSchedulerUart"; + + rxbuf = new char[rxbufsize + 1]; + ZASSERT(rxbuf != NULL); + + m_uart->initialize(&cfg); + ZASSERT(m_uart->startRxIt()); + m_uart->setrxcb([this](uint8_t* data, size_t len) { + if (m_dataisready) { + return; + } + memcpy(rxbuf, data, len); + rxbuf[len] = '\0'; + m_rxsize = len; + m_dataisready = true; + // on data ,in irq context + }); + regbasiccmd(); +} +// int32_t getAckInt32Val(int index) { +// int32_t getAckInt32Num() { + +void CmdSchedulerV2::schedule() { + ICmdParserACK ack; + + if (!m_dataisready) { + return; + } + for (int i = 0; i < m_rxsize; i++) { + if (rxbuf[i] == '\r' || rxbuf[i] == '\n') { + rxbuf[i] = '\0'; + } + } + for (int i = 0; i < m_rxsize; i++) { + if (rxbuf[i] != '\0') { + // ZLOGI(TAG, "docmd: %s", &rxbuf[i]); + printf("docmd: %s \n", &rxbuf[i]); + + int inext = strlen(&rxbuf[i]) + i; + memset(&ack, 0, sizeof(ack)); + callcmd(&rxbuf[i], &ack); + i = inext; + + if (ack.ecode != 0) { + break; + } + } + } + // if (m_rxsize != 1) { + // ZLOGI(TAG, "doscript:end"); + // } + m_dataisready = false; +} +void CmdSchedulerV2::dumpack(ICmdParserACK* ack) { + if (ack->ecode == 0) { + printf("\tok -> "); + if (ack->acktype == ack->kAckType_none) { + printf("\n"); + } else if (ack->acktype == ack->kAckType_int32) { + for (int i = 0; i < ack->getAckInt32Num(); i++) { + printf(" %d", ack->getAckInt32Val(i)); + } + printf("\n"); + } else if (ack->acktype == ack->kAckType_buf) { + for (int i = 0; i < ack->rawlen; i++) { + printf(" %02x", ack->rawdata[i]); + } + printf("\n"); + } else { + printf("\n"); + } + } else { + printf("\tfailed:%s(%d)\n", err::error2str(ack->ecode), ack->ecode); + } +} + +// void CmdSchedulerV2::tx(const char* data, int len) { m_uart->tx((uint8_t*)data, len); } +int32_t CmdSchedulerV2::callcmd(const char* cmd, ICmdParserACK* ack) { + int32_t argc = 0; + char* argv[10] = {0}; + memset(cmdcache, 0, sizeof(cmdcache)); + argc = 0; + memset(argv, 0, sizeof(argv)); + strcpy(cmdcache, cmd); + remove_note(cmdcache, strlen(cmdcache)); + prase_cmd(cmdcache, strlen(cmdcache), argc, argv); + if (argc == 0) { + return (int32_t)0; + } + + // printf("argc:%d\n", argc); + // for (size_t i = 0; i < argc; i++) { + // printf("argv[%d]:%s\n", i, argv[i]); + // } + /** + * @brief 在这里处理指令 + */ + auto cmder = m_cmdMap.find(string(argv[0])); + if (cmder != m_cmdMap.end()) { + if (cmder->second.npara != argc - 1) { + ack->ecode = err::kcmd_param_num_error; + return err::kcmd_param_num_error; + } + cmder->second.call_cmd((int32_t)(argc - 1), (const char**)(&argv[1]), ack); + return ack->ecode; + + } else { + ack->ecode = err::kcmd_not_found; + return err::kcmd_not_found; + } +} + +void CmdSchedulerV2::remove_note(char* input, int inputlen) { + bool detect_note = false; + for (int i = 0; i < inputlen; i++) { + if (!detect_note && input[i] == '#') { + detect_note = true; + } + if (detect_note) { + input[i] = 0; + } + } +} + +void CmdSchedulerV2::prase_cmd(char* input, int inputlen, int& argc, char* argv[]) { + for (int i = 0; input[i] == 0 || i < inputlen; i++) { + if (input[i] == ' ' || input[i] == '\r' || input[i] == '\n') { + input[i] = 0; + } + } + + int j = 0; + for (int 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; + } + } +} diff --git a/components/cmdscheduler/cmd_scheduler_v2.hpp b/components/cmdscheduler/cmd_scheduler_v2.hpp new file mode 100644 index 0000000..23be313 --- /dev/null +++ b/components/cmdscheduler/cmd_scheduler_v2.hpp @@ -0,0 +1,79 @@ +#pragma once +#include +#include + +#include "sdk/os/zos.hpp" +#include "sdk\components\zprotocols\errorcode\errorcode.hpp" +#include "sdk\components\zprotocols\zcancmder_v2\api\api.hpp" + +namespace iflytop { +using namespace std; + +class CmdSchedulerV2 : public ICmdParser { + public: + class CMD { + public: + ICmdFunction_t call_cmd; + string help_info; + int npara; + }; + + private: + map m_cmdMap; + + ZUART* m_uart; + char* rxbuf; + int32_t m_rxsize = 0; + + uint32_t m_rxbufsize; + + bool m_dataisready = false; + + char cmdcache[1024] = {0}; + + public: + void initialize(UART_HandleTypeDef* huart, uint32_t rxbufsize); + void registerCmd(const char* cmdname, const char* helpinfo, int paraNum, ICmdFunction_t cmdimpl); + // void tx(const char* data, int len); + void schedule(); + + private: + void regbasiccmd(); + int32_t callcmd(const char* cmd, ICmdParserACK* ack); + void prase_cmd(char* input, int inputlen, int& argc, char* argv[]); + void remove_note(char* input, int inputlen); + void dumpack(ICmdParserACK* ack); +}; +#if 0 + +#define DO_CMD(cond) \ + { \ + int32_t ret = cond; \ + if (ret != 0) { \ + return ret; \ + } \ + } +#define IMPL_CMD(cmd, ...) \ + DO_CMD(findmodule(con->getInt(1), &module)); \ + DO_CMD(module->cmd(__VA_ARGS__)); \ + return (int32_t)0; + +#define IMPL_READ_STATE(cmd, ...) \ + DO_CMD(findmodule(con->getInt(1), &module)); \ + DO_CMD(module->cmd(__VA_ARGS__)); \ + cmd_dump_ack(ack); \ + return (int32_t)0; + +#define REG_CMD___NO_ACK(prefix, cmd, para, npara, ...) /**/ \ + m_cmdScheduler->registerCmd(prefix #cmd, para, npara, [this](CmdSchedulerV2::Context* con) { /**/ \ + IMPL_CMD(cmd, __VA_ARGS__); /**/ \ + }); + +#define REG_CMD_WITH_ACK(prefix, cmd, para, npara, acktype, ...) /**/ \ + m_cmdScheduler->registerCmd(prefix #cmd, para, npara, [this](CmdSchedulerV2::Context* con) { /**/ \ + acktype ack; /**/ \ + IMPL_READ_STATE(cmd, __VA_ARGS__); /**/ \ + }); +#endif + +} // namespace iflytop \ No newline at end of file diff --git a/components/zprotocols/zcancmder_v2 b/components/zprotocols/zcancmder_v2 index 307d179..81e5d4c 160000 --- a/components/zprotocols/zcancmder_v2 +++ b/components/zprotocols/zcancmder_v2 @@ -1 +1 @@ -Subproject commit 307d17935801671e62bf07864b08b88499a712db +Subproject commit 81e5d4c18295ebc8e79e14a7ea072efe7fb62b4a