#include "Expel.hpp" #include "Shell.h" namespace gsd { class ExpelClient: public TcpClient { public: int id = 0; bool flag = false; typedef std::shared_ptr Ptr; ExpelClient():TcpClient() { } ~ExpelClient(){ } /** * @description: setDeviceControl * @param {shared_ptr} DeviceControl * @return {*} */ void setDeviceControl(std::shared_ptr DeviceControl){ this->deviceControl = DeviceControl; } /** * @description: setSendBuf * @param {Ptr} Buffer * @return {*} */ void setSendBuf(const BufferRaw::Ptr Buffer){ buffer = Buffer; } protected: virtual void onConnect(const SockException &ex) override{ //连接结果事件 if(buffer != nullptr) this->send(buffer); } virtual void onRecv(const Buffer::Ptr &pBuf) override{ int msg = 0; if(this->deviceControl == nullptr) return; if(this->deviceControl->Consumer((uint8_t *)pBuf->data(), (int)pBuf->size(), msg)){ flag = true; if(config::getPtr()->debug) DebugL << "deviceId[" << deviceControl->getDeviceId() << "] Device response is succeed" << endl; if(config::getPtr()->debug) DebugL << "REV:" << Expel::bytesToHexString((uint8_t *)pBuf->data(), (int)pBuf->size()) << endl; std::string json; SendDevice sendDevice; time_t timestamp; NettyClientResultMsg nettyClientResultMsg; this->id = std::atoi(deviceControl->getDeviceId().c_str()); if(deviceControl->getDeviceId() == "0") deviceControl->setDeviceId("3"); deviceControl->BuildDeviceInfo(sendDevice); time(×tamp); sendDevice.msgTime = ctime(×tamp); std::string requestId; requestId = uuid::generate(); nettyClientResultMsg.setRequestId(requestId); nettyClientResultMsg.setDataType(NettyClientCommandEnum().device_info); nettyClientResultMsg.setData(sendDevice); nettyClientResultMsg.objectToJson(json); if(config::getPtr()->debug) DebugL << json << endl; NoticeCenter::Instance().emitEvent(NOTICE_DEVICEINFO, requestId ,json); } } virtual void onFlush() override{ //发送阻塞后,缓存清空事件 DebugL; } virtual void onErr(const SockException &ex) override{ //断开连接事件,一般是EOF WarnL << ex.what(); flag = false; } virtual void onManager() override{ static int num = 0; if(num < 5 ) { num++; return; } num = 0; if(!flag) return; std::string json; SendDevice sendDevice; time_t timestamp; NettyClientResultMsg nettyClientResultMsg; if(this->id == 0) deviceControl->setDeviceId("3"); deviceControl->BuildDeviceInfo(sendDevice); time(×tamp); sendDevice.msgTime = ctime(×tamp); std::string requestId; requestId = uuid::generate(); nettyClientResultMsg.setRequestId(requestId); nettyClientResultMsg.setDataType(NettyClientCommandEnum().device_info); nettyClientResultMsg.setData(sendDevice); nettyClientResultMsg.objectToJson(json); NoticeCenter::Instance().emitEvent(NOTICE_DEVICEINFO, requestId ,json); } private: int _nTick = 0; std::shared_ptr deviceControl = nullptr; BufferRaw::Ptr buffer = nullptr; }; /** * @description: 获取Ptr * @return {*} */ std::shared_ptr Expel::getPtr(){ static shared_ptr expel_ = nullptr; if(expel_ == nullptr) expel_= std::shared_ptr(new Expel); return expel_; } /** * @description: HttpControler http的控制接口 * @param {int} commandCode * @param {ExpelDevice} expelDevice * @return {*} */ void Expel::HttpControler(int commandCode, ExpelDevice expelDevice){ this->pool->async([this, commandCode, expelDevice](){ ExpelDevice expel = expelDevice; switch (commandCode) { // 查询 case 1: this->Status(expel); break; // 开启电源 case 2: this->Open(expel); break; // 关闭电源 case 3: this->Close(expel); break; // 开炮 case 4: this->Fire(expel); break; default: break; } }); this->pool->start(); } /** * @description: sendDeviceMsgCallback * @param {NettyServerResultMsg} &nettyServerResultMsg * @param {ExpelDevice} expelDevice * @return {*} */ void Expel::sendDeviceMsgCallback(NettyServerResultMsg &nettyServerResultMsg, ExpelDevice expelDevice){ RecDeviceCommand recDeviceCommand; recDeviceCommand = nettyServerResultMsg.getData(); std::string deviceId = to_string(recDeviceCommand.getDeviceId()); int commandCode = atoi(recDeviceCommand.getCommandCode().c_str()); switch (commandCode) { // 查询 case 1: this->Status(expelDevice); break; // 开启电源 case 2: this->Open(expelDevice); break; // 关闭电源 case 3: this->Close(expelDevice); break; // 开炮 case 4: this->Fire(expelDevice); break; case 18: this->Open(expelDevice); break; case 19: this->Close(expelDevice); break; default: break; } } /** * @description: 初始化 * @return {*} */ bool Expel::Init(){ InfoL; return true; } /** * @description: 初始化 * @return {*} */ void Expel::Destroy(){ InfoL; } /** * @description: 获取控制器 * @param {*} * @return {*} */ std::shared_ptr Expel::getControl(ExpelDevice& expelDevice){ static std::shared_ptr deviceControl = nullptr; switch (expelDevice.deviceType) { case DeviceType::DevicePlayerV1: deviceControl = std::make_shared(); break; case DeviceType::DevicePlayerV2: deviceControl = std::make_shared(); break; case DeviceType::DeviceGasV1: deviceControl = std::make_shared(); break; case DeviceType::DevicePlayerV3: deviceControl = std::make_shared(); std::dynamic_pointer_cast(deviceControl)->setServerCname(expelDevice.ServerCname); std::dynamic_pointer_cast(deviceControl)->setServerCpwd(expelDevice.ServerCpwd); std::dynamic_pointer_cast(deviceControl)->setServerIP(expelDevice.ServerIp); break; case DeviceType::DevicePlayerV4: deviceControl = std::make_shared(); std::dynamic_pointer_cast(deviceControl)->setServerIP(config::getPtr()->payServerIP); break; case DeviceType::DeviceGasV2: deviceControl = std::make_shared(); break; case DeviceType::DevicePlayerV5: deviceControl = std::make_shared(); break; } deviceControl->setTypeId(expelDevice.deviceType); return deviceControl; } /** * @description: 打开设备 * @param {int} deivceId * @return {*} */ int32_t Expel::Open(ExpelDevice& expelDevice){ std::shared_ptr deviceControl = nullptr; deviceControl = getControl(expelDevice); if(deviceControl == nullptr) return -1; uint8_t data[1024]; memset(data, 0, sizeof(data)); int length = 0; std::string deviceId = expelDevice.DeviceId; deviceControl->setDeviceId(deviceId); if(config::getPtr()->debug) InfoL << "DeviceId:" << deviceId << ", deviceType:" << expelDevice.deviceType << endl; // 获取指令 if(deviceControl != nullptr && deviceControl->Open(deviceId, data, length) == 0){ return Control(deviceControl, expelDevice, data, length, 2); } return -1; } /** * @description: 关闭设备 * @param {int} deivceId * @return {*} */ int32_t Expel::Close(ExpelDevice& expelDevice){ std::shared_ptr deviceControl = nullptr; deviceControl = getControl(expelDevice); if(deviceControl == nullptr) return -1; uint8_t data[1024]; memset(data, 0, sizeof(data)); int length = 0; std::string deviceId = expelDevice.DeviceId; if(config::getPtr()->debug) InfoL << "DeviceId:" << deviceId << ", deviceType:" << expelDevice.deviceType << endl; // 获取指令 if(deviceControl != nullptr && deviceControl->Close(deviceId, data, length) == 0){ return Control(deviceControl, expelDevice, data, length, 3); } return -1; } /** * @description: 开火 * @param {int} deivceId * @return {*} */ int32_t Expel::Fire(ExpelDevice& expelDevice){ std::shared_ptr deviceControl = nullptr; deviceControl = getControl(expelDevice); if(deviceControl == nullptr) return -1; uint8_t data[1024]; memset(data, 0, sizeof(data)); int length = 0; std::string deviceId = expelDevice.DeviceId; if(config::getPtr()->debug) InfoL << "DeviceId:" << deviceId << ", deviceType:" << expelDevice.deviceType << endl; // 获取指令 if(deviceControl != nullptr && deviceControl->Fire(deviceId, data, length) == 0){ return Control(deviceControl, expelDevice, data, length, 4); } return -1; } /** * @description: 状态 * @param {int} deviceId * @param {string&} json * @return {*} */ int32_t Expel::Status(ExpelDevice& expelDevice){ std::shared_ptr deviceControl = nullptr; deviceControl = getControl(expelDevice); if(deviceControl == nullptr) return -1; uint8_t data[1024]; memset(data, 0, sizeof(data)); int length = 0; std::string deviceId = expelDevice.DeviceId; if(config::getPtr()->debug) InfoL << "DeviceId:" << deviceId << ", deviceType:" << expelDevice.deviceType << endl; // 获取指令 if(deviceControl != nullptr && deviceControl->Status(deviceId, data, length) == 0){ return Control(deviceControl, expelDevice, data, length, 1); } return -1; } /** * @description: 数组转换为16进制字符串 * @param {uint8_t*} bytes * @param {int} length * @return {*} */ std::string Expel::bytesToHexString(const uint8_t* bytes,const int length) { if (bytes == NULL) { return ""; } std::string buff; const int len = length; for (int j = 0; j < len; j++) { int high = bytes[j]/16, low = bytes[j]%16; buff += (high<10) ? ('0' + high) : ('a' + high - 10); buff += (low<10) ? ('0' + low) : ('a' + low - 10); buff += " "; } return buff; } /** * @description: control * @param {*} * @return {*} */ int32_t Expel::Control(std::shared_ptr& deviceControl, ExpelDevice& expelDevice, uint8_t* data, int& length, int type){ static ExpelClient::Ptr client(new ExpelClient()); std::lock_guard gurad(m_mutex); deviceControl->setDeviceId(expelDevice.DeviceId); if(deviceControl->getDeviceTool() == ContorlGear::DeviceTools::serial){ CSerialPort ser; config::Ptr m_config = config::getPtr(); if(m_config->debug) DebugL << "Serial control data:" << bytesToHexString(data, length) << endl; ser.init(m_config->comPort.c_str()); ser.setBaudRate(std::dynamic_pointer_cast(deviceControl)->getBaudRate()); if(!ser.open()){ ErrorL << "Open port falied!"; return -1; } if(ser.writeData((const char*)data, length) != length){ WarnL << "Control command failed" << endl; return -1; } this->SerialReceive(ser, deviceControl); ser.close(); return 0; }else if(deviceControl->getDeviceTool() == ContorlGear::DeviceTools::http){ std::string serviceIP = ""; if(deviceControl->getTypeId() == DeviceType::DeviceGasV2 || deviceControl->getTypeId() == DeviceType::DevicePlayerV3){ serviceIP = config::getPtr()->payServerIP; } else{ serviceIP = expelDevice.ServerIp; } if(serviceIP == ""){ ErrorL << "The device IP address is empty" << endl; return -1; } httplib::Client cli(serviceIP, config::getPtr()->ExpelPort); std::string json; json = (char*)data; if(json != ""){ DebugL << "Http control data:" << json << endl; } if(deviceControl->getTypeId() == DeviceType::DevicePlayerV3){ if (auto res = cli.Post(std::dynamic_pointer_cast(deviceControl)->getUrl().c_str(), json, "application/json")) { if (res->status == 200) { // DebugL << res->body << endl; return 0; }else { WarnL << res->body << endl; return -1; } } else { auto err = res.error(); ErrorL << "HTTP Service unavailable:" << err << endl; return -1; } }else if(deviceControl->getTypeId() == DeviceType::DeviceGasV2){ auto parms = std::dynamic_pointer_cast(deviceControl)->getParms(); auto headers = std::dynamic_pointer_cast(deviceControl)->getHeaders(); std::string url = std::dynamic_pointer_cast(deviceControl)->getUrl(); if(url == "") return 1; if(auto res = cli.Get(url.c_str(), parms, headers)){ if (res->status == 200) { DebugL << res->body << endl; return 0; }else { WarnL << res->body << endl; return -1; } }else{ auto err = res.error(); ErrorL << "HTTP Service unavailable:" << err << endl; return -1; } } }else if(deviceControl->getDeviceTool() == ContorlGear::DeviceTools::tcp){ if(config::getPtr()->payServerIP_tcp == ""){ ErrorL << "The device IP address is empty" << endl; return -1; } client->setDeviceControl(deviceControl); if(!client->alive()) client->startConnect(config::getPtr()->payServerIP_tcp, config::getPtr()->payServerPort_tcp); if(config::getPtr()->debug) DebugL << "Serial control data:" << bytesToHexString(data, length) << endl; auto buf = BufferRaw::create(); buf->assign((char*)data, length); client->setSendBuf(buf); if(client->alive()) client->send(buf); } else return -1; } /** * @description: 串口数据接收 * @param {*} * @return {*} */ bool Expel::SerialReceive(CSerialPort& ser, std::shared_ptr& deviceControl){ if(ser.isOpened()){ Ticker ticker0; uint8_t buffer[1024]; memset(buffer, 0, sizeof(buffer)); config::Ptr m_config = config::getPtr(); while (true) { if(ticker0.elapsedTime() >= 2000){ WarnL << "deviceId[" << deviceControl->getDeviceId() << "] Control instruction timeout" << endl; break; } int len = ser.readAllData((char *)(buffer)); if(len == 0) continue; int msg_id; if(deviceControl->Consumer(buffer, len, msg_id)){ if(m_config->debug) DebugL << "deviceId[" << deviceControl->getDeviceId() << "] Device response is succeed" << endl; if(m_config->debug) DebugL << "REV:" << bytesToHexString(buffer, len) << endl; if(deviceControl->getStatusMsg(msg_id)){ std::string json; SendDevice sendDevice; time_t timestamp; NettyClientResultMsg nettyClientResultMsg; deviceControl->BuildDeviceInfo(sendDevice); time(×tamp); sendDevice.msgTime = ctime(×tamp); std::string requestId; requestId = uuid::generate(); nettyClientResultMsg.setRequestId(requestId); nettyClientResultMsg.setDataType(NettyClientCommandEnum().device_info); nettyClientResultMsg.setData(sendDevice); nettyClientResultMsg.objectToJson(json); NoticeCenter::Instance().emitEvent(NOTICE_DEVICEINFO, requestId ,json); } break; } } } return true; } /** * @description: 全部打开 * @param {*} * @return {*} */ int32_t Expel::AllOpen(){ if(!config::getPtr()->LowVersion){ for (auto iter = m_deviceLists.begin(); iter != m_deviceLists.end(); iter++){ this->Open(*iter); } }else{ if(config::getPtr()->DeviceIds.empty()){ return 0; } for(auto iter = config::getPtr()->DeviceIds.begin(); iter != config::getPtr()->DeviceIds.end(); iter++){ ExpelDevice expelDevice; expelDevice.DeviceId = std::to_string(*iter); expelDevice.deviceType = (enum DeviceType)config::getPtr()->deviceType; this->Open(expelDevice); } } return 0; } /** * @description: * @param {*} * @return {*} */ int32_t Expel::AllClose(){ if(!config::getPtr()->LowVersion){ for (auto iter = m_deviceLists.begin(); iter != m_deviceLists.end(); iter++){ this->Close(*iter); } }else{ if(config::getPtr()->DeviceIds.empty()) return 0; for(auto iter = config::getPtr()->DeviceIds.begin(); iter != config::getPtr()->DeviceIds.end(); iter++){ ExpelDevice expelDevice; expelDevice.DeviceId = std::to_string(*iter); expelDevice.deviceType = (enum DeviceType)config::getPtr()->deviceType; this->Close(expelDevice); } } return 0; } /** * @description: 全部开炮 * @param {*} * @return {*} */ int32_t Expel::AllFire(){ if(!config::getPtr()->LowVersion){ for (auto iter = m_deviceLists.begin(); iter != m_deviceLists.end(); iter++){ this->Fire(*iter); } }else{ if(config::getPtr()->DeviceIds.empty()) return 0; for(auto iter = config::getPtr()->DeviceIds.begin(); iter != config::getPtr()->DeviceIds.end(); iter++){ ExpelDevice expelDevice; expelDevice.DeviceId = std::to_string(*iter); expelDevice.deviceType = (enum DeviceType)config::getPtr()->deviceType; this->Fire(expelDevice); } } return 0; } /** * @description: 获取设备列表 * @param {*} * @return {*} */ int32_t Expel::UpdateDeviceList(vector>& datas){ if(datas.empty()) { this->m_deviceLists.clear(); return 0; } this->m_deviceLists.clear(); for(auto &line: datas){ ExpelDevice expelDevice; expelDevice.DeviceId = line[0]; expelDevice.deviceType = (enum DeviceType)atoi(line[2].c_str()); expelDevice.ServerIp = line[3]; expelDevice.ServerCname = line[4]; expelDevice.ServerCpwd = line[5]; this->m_deviceLists.push_back(expelDevice); } return 0; } /** * @description: 获取驱鸟设备数量 * @param {*} * @return {int32_t} */ int32_t Expel::getExpelSize(){ if(!config::getPtr()->LowVersion){ return m_deviceLists.size(); }else{ return config::getPtr()->DeviceIds.size(); } } /** * @description: getExpelInfo * @return {*} */ std::string Expel::getExpelInfo(){ std::string info; rapidjson::StringBuffer strBuf; rapidjson::Writer writer(strBuf); if(!config::getPtr()->LowVersion){ writer.StartObject(); writer.Key("Num"); writer.Int(m_deviceLists.size()); writer.Key("datas"); writer.StartArray(); for(auto iter = m_deviceLists.begin(); iter != m_deviceLists.end(); iter++){ writer.StartObject(); writer.Key("DeviceId"); writer.String(iter->DeviceId.c_str()); writer.Key("DeviceType"); writer.Int(iter->deviceType); writer.Key("DeviceTools"); writer.Int(iter->tool); writer.EndObject(); } writer.EndArray(); writer.EndObject(); info = strBuf.GetString(); }else{ writer.StartObject(); writer.Key("Num"); writer.Int(config::getPtr()->DeviceIds.size()); } return info; } } // namespace gsd