diff --git a/dep/zlinuxcomponents b/dep/zlinuxcomponents index 3be3c3e..c0d81c0 160000 --- a/dep/zlinuxcomponents +++ b/dep/zlinuxcomponents @@ -1 +1 @@ -Subproject commit 3be3c3ef0f52649cbc6e1b7d5fab7668d6b17edc +Subproject commit c0d81c03b27786308a632063f146ecb34f1f2aee diff --git a/src/configs/project_setting.hpp b/src/configs/project_setting.hpp new file mode 100644 index 0000000..0c527f6 --- /dev/null +++ b/src/configs/project_setting.hpp @@ -0,0 +1,9 @@ +#pragma once +#define LINUX_HARDWARE_ID (0x02) + +/******************************************************************************* + * LINUX_HARDWARE_REG * + *******************************************************************************/ + +#define REG_REBOOT_FLAG 0x0000 // 重启标识 +#define REG_EXCEPTION_FLAG 0x0100 // 异常标志位 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index da21b27..3a35a4b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,8 @@ #include "main.hpp" + +#include "service/can_service.hpp" +#include "service/iflytop_hardware_ws_service.hpp" + using namespace iflytop; using namespace core; using namespace std; @@ -64,10 +68,16 @@ int Main::main(int argc, char *argv[]) { if (!device_id.empty()) GET_SERVICE(GConfig)->set_deviceId(device_id); updateRootfs(); - /** - * @brief DeviceIOService初始化 - */ auto config = GET_SERVICE(GConfig); + + // 构造iflytophardwarews + BUILD_AND_REG_SERRVICE(IflytopWSService); + GET_SERVICE(IflytopWSService)->initialize(); + + // 构造CanService + BUILD_AND_REG_SERRVICE(CanService); + GET_SERVICE(CanService)->initialize(); + // 构造MainControlService BUILD_AND_REG_SERRVICE(MainControlService); GET_SERVICE(MainControlService)->initialize(); diff --git a/src/service/can_service.cpp b/src/service/can_service.cpp index 1949ea9..afa326c 100644 --- a/src/service/can_service.cpp +++ b/src/service/can_service.cpp @@ -50,14 +50,14 @@ void CanService::processIflytopRxPacket(shared_ptr frame) { onIflytopCanSubDevicePacket(icps_packet); } -void CanService::sendPacketToIflytopCanSubDevice(shared_ptr icps_packet) { +SocketCan::SocketCanError_t CanService::sendPacketToIflytopCanSubDevice(shared_ptr icps_packet, int overtime_ms) { auto frame = m_iflytopCanProtocolStack->createSocketCanFrame(icps_packet); if (!frame) { logger->error("createSocketCanFrame fail,{}", icps_packet->toString()); - return; - } - SocketCan::SocketCanError_t erro = m_socketCan->sendFrame(frame); - if (erro != SocketCan::SocketCanError_t::kSuccess) { - logger->error("sendFrame fail,{}", SocketCan::SocketCanError_t2Str(erro)); + return SocketCan::kErrorFrameFormat; } + return m_socketCan->sendFrame(frame, overtime_ms); + // if (erro != SocketCan::SocketCanError_t::kSuccess) { + // logger->error("sendFrame fail,{}", SocketCan::SocketCanError_t2Str(erro)); + // } } diff --git a/src/service/can_service.hpp b/src/service/can_service.hpp index 907deb5..6cc358b 100644 --- a/src/service/can_service.hpp +++ b/src/service/can_service.hpp @@ -48,7 +48,7 @@ class CanService : public enable_shared_from_this { void initialize(); void startListen(); - void sendPacketToIflytopCanSubDevice(shared_ptr packet); + SocketCan::SocketCanError_t sendPacketToIflytopCanSubDevice(shared_ptr icps_packet, int overtime_ms); private: void processRx(shared_ptr frame); diff --git a/src/service/iflytop_hardware_ws_service.cpp b/src/service/iflytop_hardware_ws_service.cpp index 0478dd6..f54ad6b 100644 --- a/src/service/iflytop_hardware_ws_service.cpp +++ b/src/service/iflytop_hardware_ws_service.cpp @@ -29,10 +29,19 @@ void IflytopWSService::initialize() { m_server->start(); m_server->wait(); } -void IflytopWSService::sendMessage(const string& message) {} +void IflytopWSService::sendMessage(const string& message) { + /** + * @brief 广播消息给所有连接的客户端 + */ + auto clients = m_server->getClients(); + for (auto& each : clients) { + if (each) { + each->sendText(message); + } + } +} -void IflytopWSService::onMessageCallback(weak_ptr webSocket, shared_ptr connectionState, - const ix::WebSocketMessagePtr& msg) { +void IflytopWSService::onMessageCallback(weak_ptr webSocket, shared_ptr connectionState, const ix::WebSocketMessagePtr& msg) { if (msg->type == ix::WebSocketMessageType::Open) { logger->info("New connection"); logger->info("id : {}", connectionState->getId()); diff --git a/src/service/main_control_service.cpp b/src/service/main_control_service.cpp index c514253..8ac977e 100644 --- a/src/service/main_control_service.cpp +++ b/src/service/main_control_service.cpp @@ -1,5 +1,6 @@ #include "main_control_service.hpp" +#include "configs/project_setting.hpp" #include "iflytopcpp/core/components/stringutils.hpp" #include "version.hpp" using namespace iflytop; @@ -23,11 +24,193 @@ class Trace { * ======================================================代码======================================================= * *********************************************************************************************************************/ +bool MainControlService::createIflytopHardwareWSPacket(shared_ptr packetin, json& jout) { + if (!packetin) return false; +#if 0 +{ + "channel":"can0", + "protocol":"iflytopCanProtocolStackV1", + "message": { + "attribute": "normal/gbroadcast/subbroadcast", + "priority": 4, //0->7,0最高 + "type": "w/r/receipt/report/set_auto_report/heart_packet", + "targetId": 128, // 128->255 + "sourceId": 1, // 默认为1 + "seq": 0, //0-65535, + "regAdd": 0, //0-65535 + "regValue": 100 // -2^31->2^31-1 + } +} +#endif + + if (packetin->getSourceId() == LINUX_HARDWARE_ID) { + jout["channel"] = "local"; + } else { + jout["channel"] = "can0"; + } + + jout["protocol"] = "iflytopCanProtocolStackV1"; + jout["message"]["attribute"] = packetin->getAttributeStr(); + jout["message"]["priority"] = packetin->getPriority(); + jout["message"]["type"] = packetin->getTypeStr(); + jout["message"]["targetId"] = packetin->getTargetId(); + jout["message"]["sourceId"] = packetin->getSourceId(); + jout["message"]["seq"] = packetin->getSeq(); + jout["message"]["regAdd"] = packetin->getRegAdd(); + jout["message"]["regValue"] = packetin->getRegValue(); + return true; +} + +bool MainControlService::createICPSPacket(json jin, shared_ptr& packetin) { // + shared_ptr packetout(new icps::Packet()); + if (jin["protocol"] != "iflytopCanProtocolStackV1") { + logger->error("create ICPSPacket failed, protocol not match,protocol:{}", jin["protocol"].get()); + return false; + } + + packetin->setAttributeByStr(jin["message"]["attribute"]); + packetin->setPriority(jin["message"]["priority"]); + packetin->setTypeByStr(jin["message"]["type"]); + packetin->setTargetId(jin["message"]["targetId"]); + packetin->setSourceId(jin["message"]["sourceId"]); + packetin->setSeq(jin["message"]["seq"]); + packetin->setRegAdd(jin["message"]["regAdd"]); + packetin->setRegValue(jin["message"]["regValue"]); + return true; +} + void MainControlService::initialize() { GET_TO_SERVICE(m_zconfig); - // GET_TO_SERVICE(m_commonVoiceProcesser); + GET_TO_SERVICE(m_iflytopWSService); + GET_TO_SERVICE(m_canService); + + localVirtualCanSlaveInitialize(); + websocketServerInitialize(); + /******************************************************************************* + * 真实的CAN设备衔接 * + *******************************************************************************/ + m_canService->onIflytopCanSubDevicePacket.connect([this](shared_ptr packet) { // + processCanMessageFromCanService(packet); + }); }; -void MainControlService::processReceiveMessage(fromwhere_t fromwhere, const json& in, json& receipt) { - logger->info("process receive message from {},{}", fromwhere2str(fromwhere), in.dump()); + +void MainControlService::websocketServerInitialize() { + /** + * @brief + * 对接下行消息 + */ + m_iflytopWSService->onMessage.connect([this](weak_ptr webSocket, const ix::WebSocketMessagePtr& msg) { + if (msg->binary) { + logger->warn("receive binary message,ignore"); + return; + } + string msgtext = msg->str; + try { + json message = json::parse(msgtext); + processIflytopWSMsg(message); + } catch (const std::exception& e) { + } + }); +} + +void MainControlService::localVirtualCanSlaveInitialize() { + m_localVirtualCanSlave.reset(new IflytopVirtualCanSlave()); + m_localVirtualCanSlave->initialize(LINUX_HARDWARE_ID); + m_localVirtualCanSlave->activeReg(REG_REBOOT_FLAG, icps::kw | icps::kr, 0); + m_localVirtualCanSlave->activeReg(REG_EXCEPTION_FLAG, icps::kw | icps::kr, 0); + m_localVirtualCanSlave->setOnHostRegisterReadEvent( // + [this](icps::Reg_t& reg, int32_t& value) { // + return icps::kSuccess; + }); + m_localVirtualCanSlave->setOnHostRegisterWriteEvent( // + [this](icps::Reg_t& reg, int32_t oldvalue, int32_t& newvalue) { // + return icps::kSuccess; + }); + m_localVirtualCanSlave->setOnRegisterValueAutoReportEvent( // + [this](icps::Reg_t& reg, int32_t& value) { // + return; + }); + m_localVirtualCanSlave->IflytopVirtualCanIF_setUpstream( // + [this](shared_ptr packet) { // + /** + * @brief + * 本地虚拟can上报消息给Websocket + */ + processCanMessageFromLocalCanService(packet); + return; + }); +} + +/******************************************************************************* + * 上行消息处理 * + *******************************************************************************/ + +/** + * @brief 处理从CanService接收到的上行消息 + * + * @param packet + */ +void MainControlService::processCanMessageFromCanService(shared_ptr packet) { + /** + * @brief 处理从can收到的消息 + */ + json uppacket; + bool suc = createIflytopHardwareWSPacket(packet, uppacket); + if (!suc) { + logger->error("{}|createIflytopHardwareWSPacket failed,packet:{}", __LINE__, packet->toString()); + return; + } + m_iflytopWSService->sendMessage(uppacket.dump()); +} +/** + * @brief 处理本地虚拟can的上行消息 + * + * @param packet + */ +void MainControlService::processCanMessageFromLocalCanService(shared_ptr packet) { + json uppacket; + bool suc = createIflytopHardwareWSPacket(packet, uppacket); + if (!suc) { + logger->error("{}|createIflytopHardwareWSPacket failed,packet:{}", __LINE__, packet->toString()); + return; + } + m_iflytopWSService->sendMessage(uppacket.dump()); +} +/******************************************************************************* + * 下行消息处理 * + *******************************************************************************/ +void MainControlService::processIflytopWSMsg(const json& in) { + /** + * @brief + * 路由消息到CAN,Local,或者其他服务 + * + * 1. 消息由json转换成packet + * 2. 根据地址陆游消息到CAN,Local,或者其他服务 + */ + shared_ptr packet; + createICPSPacket(in, packet); + if (packet == nullptr) { + logger->error("create ICPSPacket failed"); + return; + } + + if (packet->getTargetId() == LINUX_HARDWARE_ID) { + /** + * @brief + * 本地虚拟can设备 + */ + m_localVirtualCanSlave->IflytopVirtualCanIF_feedPacket(packet); + } else { + /** + * @brief + * 转发给can设备 + */ + SocketCan::SocketCanError_t error = m_canService->sendPacketToIflytopCanSubDevice(packet, 10); + if (error != SocketCan::SocketCanError_t::kSuccess) { + logger->error("sendPacketToIflytopCanSubDevice failed, error:{},({})", // + SocketCan::SocketCanError_t2Str(error), error); + IflytopCanProtocolStack().createErrorPacket(packet, icps::kOvertime); + } + } } diff --git a/src/service/main_control_service.hpp b/src/service/main_control_service.hpp index 130350a..602b57d 100644 --- a/src/service/main_control_service.hpp +++ b/src/service/main_control_service.hpp @@ -18,13 +18,15 @@ // #include "configs/gconfig.hpp" #include "zservice_container/zservice_container.hpp" -#include "zwebservice/zwebservice.hpp" // #include "configs/gconfig.hpp" #include "iflytopcpp/core/components/jobs/work_queue.hpp" #include "iflytopcpp/core/components/timer/simple_timer.hpp" +#include "service/can_service.hpp" +#include "service/iflytop_hardware_ws_service.hpp" #include "zlinuxcomponents/alsaplayer/smart_soundbox_player.hpp" +#include "zlinuxcomponents/iflytop_can_protocol_stack/iflytop_virtual_can_slave.hpp" /** * @brief @@ -44,7 +46,11 @@ using namespace core; class MainControlService : public enable_shared_from_this { ENABLE_LOGGER(MainControlService); - shared_ptr m_zconfig; + shared_ptr m_zconfig; + shared_ptr m_iflytopWSService; + shared_ptr m_canService; + + shared_ptr m_localVirtualCanSlave; typedef enum { kzwebService, @@ -57,7 +63,13 @@ class MainControlService : public enable_shared_from_this { } private: - void processReceiveMessage(fromwhere_t fromwhere, const json& in, json& receipt); + + void localVirtualCanSlaveInitialize(); + void websocketServerInitialize(); + + void processIflytopWSMsg(const json& in); + void processCanMessageFromCanService(shared_ptr packet); + void processCanMessageFromLocalCanService(shared_ptr packet); public: MainControlService(){}; @@ -73,5 +85,9 @@ class MainControlService : public enable_shared_from_this { * @brief 处理本次对话,一般接收完全部的ASR结果后,调用此函数 */ void triggerProcessConversationSession(); + + private: + bool createIflytopHardwareWSPacket(shared_ptr packetin, json& jout); + bool createICPSPacket(json jin, shared_ptr& packetin); }; } // namespace iflytop \ No newline at end of file