Browse Source

修改: CMakeLists.txt
修改: framework/core/include/UtilBase.hpp
修改: framework/request/include/Notices.h
修改: lib/libgsd_modules.so
修改: lib/libgsd_plugins.so
修改: modules/Expel/include/DevicePlayerV3.hpp
修改: modules/Expel/include/DevicePlayerV4.hpp
修改: modules/Expel/include/Expel.hpp
修改: modules/Expel/src/DevicePlayerV4.cpp
修改: modules/Expel/src/Expel.cpp
修改: modules/HttpServer/include/HttpServer.hpp
修改: modules/HttpServer/src/HttpServer.cpp
修改: modules/Monitor/include/Monitor.hpp
修改: modules/Monitor/src/Monitor.cpp
修改: modules/TCPClient/src/TCPClient.cpp
修改: modules/config/src/config.cpp
修改: plugins/CMakeLists.txt
修改: plugins/ExpelPlugin/include/ExpelPlugin.hpp
修改: plugins/ExpelPlugin/src/ExpelPlugin.cpp
修改: plugins/HttpPlugin/include/HttpPlugin.hpp
修改: plugins/HttpPlugin/src/HttpPlugin.cpp
修改: plugins/MonitorPlugin/include/MonitorPlugin.hpp
修改: plugins/MonitorPlugin/src/MonitorPlugin.cpp
修改: source/CMakeLists.txt
修改: source/UserApp/include/UserApp.hpp
修改: source/UserApp/src/UserApp.cpp
修改: source/src/main.cpp

Your Name 2 years ago
parent
commit
ca15b5d33b

+ 0 - 2
CMakeLists.txt

@@ -8,7 +8,6 @@ project(gsd C CXX)
 set(CMAKE_BUILD_TYPE Debug)
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
 
-
 add_compile_options(-DRELEASE)
 
 # --[ Options
@@ -27,6 +26,5 @@ if(build_source)
   add_subdirectory(source)
 endif()
 
-
 # ---[ install
 set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")  #set runtime path

+ 22 - 0
framework/core/include/UtilBase.hpp

@@ -181,6 +181,28 @@ namespace gsd{
     };
 
     /**
+     * @brief ContorlTcplBase
+     * 
+     */    
+    class ContorlTcplBase: public ContorlGear{
+    protected:
+        std::string serverIP;
+        int port;
+
+    public:
+        ContorlTcplBase(){};
+        ~ContorlTcplBase(){};
+
+        void setServerIP(std::string _serverIP){
+            serverIP = _serverIP;
+        }
+        
+        void setPort(int _port){
+            this->port = _port;
+        }
+    };
+
+    /**
      * @brief ModuleBase
      * 
      */    

+ 2 - 1
framework/request/include/Notices.h

@@ -4,7 +4,7 @@
  * @Autor: lishengyin
  * @Date: 2022-02-16 09:36:50
  * @LastEditors: lishengyin
- * @LastEditTime: 2022-05-11 10:22:06
+ * @LastEditTime: 2022-08-24 14:24:00
  */
 #ifndef __NOTICES_H_
 #define __NOTICES_H_
@@ -19,5 +19,6 @@
 #define NOTICE_REQUESTTIMEOUT "NOTICE_REQUESTTIMEOUT"
 #define NOTICE_LOGINNETTY "NOTICE_LOGINNETTY"
 #define NOTICE_DISCONNECT "NOTICE_DISCONNECT"
+#define NOTICE_DESTROY "NOTICE_DESTROY"
 
 #endif

BIN
lib/libgsd_modules.so


BIN
lib/libgsd_plugins.so


+ 1 - 1
modules/Expel/include/DevicePlayerV3.hpp

@@ -23,7 +23,7 @@ namespace gsd{
     public:
         DevicePlayerV3(): ContorlHttplBase(){
             this->DeviceInfo = "深圳机场派尔云控制协议";
-            this->tool = DeviceTools::serial;
+            this->tool = DeviceTools::http;
         }
 
         ~DevicePlayerV3() {}

+ 105 - 0
modules/Expel/include/DevicePlayerV4.hpp

@@ -2,7 +2,112 @@
 #define _DEVICEGASV4_HPP_
 
 #include "UtilBase.hpp"
+#include "Util/logger.h"
 
+#include "requests.hpp"
+
+namespace gsd
+{
+    class DevicePlayerV4: public ContorlTcplBase
+    {
+    private:
+        enum RECV_STEP{
+            STEP_HEAD_1 = 0,
+            STEP_HEAD_2 = 1,
+            STEP_TYPE = 2,
+            STEP_DEVID = 3,
+            STEP_COM = 4, 
+            STEP_ACK = 5
+        };
+
+        typedef struct {
+            uint8_t dataCount;
+            uint8_t dataLength;
+            uint8_t dataCheckSum;
+            uint8_t data[6];
+            enum RECV_STEP step = STEP_HEAD_1;
+        }ExpelComm;
+
+        ExpelComm _comm;
+
+    public:
+        DevicePlayerV4(): ContorlTcplBase(){
+            this->DeviceInfo = "赛为智能驱鸟器协议";
+            this->tool = DeviceTools::tcp;
+        }
+        ~DevicePlayerV4(){}
+
+        // 电压
+        float voltage = 0;
+        // 气压
+        float pressure = 0;
+        // 状态
+        int state = 0;
+        // 纬度
+        float latitude = 0;
+        // 经度
+        float longitude = 0;
+
+
+        static unsigned char check(unsigned char *pSendBuf,unsigned char num);
+
+        static void serialization(const ControlerMsg gasControl,char *data);
+
+
+        bool deserialization()
+        {
+            return true;
+        }
+
+        bool Consumer(uint8_t *data, int len, int &msg_id);
+
+        bool deserialization(const uint8_t *data, int len, int &msg_id);
+
+        /**
+         * @description: 打开
+         * @param {int} deivceId
+         * @return {*}
+         */    
+        int8_t Open(std::string DeviceId, uint8_t* data, int& length);
+
+        /**
+         * @description: 关闭
+         * @param {int} deivceId
+         * @return {*}
+         */    
+        int8_t Close(std::string DeviceId, uint8_t* data, int& length);
+        /**
+         * @description: 开炮
+         * @param {int} deivceId
+         * @return {*}
+         */    
+        int8_t Fire(std::string DeviceId, uint8_t* data, int& length);
+
+        /**
+         * @description: 状态
+         * @param {int} deivceId
+         * @return {*}
+         */    
+        int8_t Status(std::string DeviceId, uint8_t* data, int& length);
+
+        /**
+         * @description: 判定msg是否为status
+         * @param {int} &msg_id
+         * @return {*}
+         */    
+        bool getStatusMsg(int &msg_id){
+            return true;
+        }
+    
+        /**
+         * @description: 构建设备信息
+         * @param {SendDevice&} sendDevice
+         * @return {*}
+         */    
+        void BuildDeviceInfo(SendDevice& sendDevice);
+    };
+    
+} // namespace gsd
 
 
 

+ 12 - 2
modules/Expel/include/Expel.hpp

@@ -6,6 +6,8 @@
 #include <condition_variable>
 #include <future>
 #include "Util/logger.h"
+#include "Util/NoticeCenter.h"
+#include "Network/TcpClient.h"
 #include "requests.hpp"
 #include "ExpelDevice.h"
 #include "httplib.h"
@@ -35,6 +37,7 @@ namespace gsd{
     {
     private:
         Expel(): ModuleBase(){
+            this->pool = std::make_shared<ThreadPool>(1,ThreadPool::PRIORITY_HIGHEST, false);
             InfoL;
         }
 
@@ -64,6 +67,14 @@ namespace gsd{
         void Destroy();
 
         /**
+         * @description: HttpControler的控制接口
+         * @param {int} commandCode
+         * @param {ExpelDevice} expelDevice
+         * @return {*}
+         */        
+        void HttpControler(int commandCode, ExpelDevice expelDevice);
+
+        /**
          * @description: 设备命令的回调函数
          * @param {NettyServerResultMsg<RecDeviceCommand>} &nettyServerResultMsg
          * @return {*}
@@ -174,8 +185,7 @@ namespace gsd{
     
     protected:
         mutex m_mutex;
-
-        
+        std::shared_ptr<ThreadPool> pool = nullptr;
     };
 };
 

+ 189 - 0
modules/Expel/src/DevicePlayerV4.cpp

@@ -0,0 +1,189 @@
+#include "DevicePlayerV4.hpp"
+
+namespace gsd
+{  
+    #define DEVICEGASV3_DATA_HEAD          (0XC5AB) // 数据头
+    #define DEVICEGASV3_DATA_DEVTYPE       (0x05)  // 设备类型
+    #define DEVICEGASV3_COMMAND_PLAY_NOW       3
+    #define DEVICEGASV3_COMMAND_PAUSE          4
+    #define DEVICEGASV3_COMMAND_STOP           5
+    #define DEVICEGASV3_COMMAND_NEXT           6
+    #define DEVICEGASV3_COMMAND_UP             7
+    #define DEVICEGASV3_COMMAND_SET_VOLUME     14
+    #define DEVICEGASV3_COMMAND_PLAY_SET       15
+
+    /**
+     * @description: check
+     * @param {unsigned char} *pSendBuf
+     * @param {unsigned char} num
+     * @return {*}
+     */    
+    unsigned char DevicePlayerV4::check(unsigned char *pSendBuf,unsigned char num){
+        char bylrc = 0,i = 0;
+        for(i = 0; i < num; i++){
+            bylrc += pSendBuf[i];
+        }
+        return (bylrc & 0x00ff);
+    }
+    
+    /**
+     * @description: 
+     * @param {GasV1Control} gasV1Control
+     * @param {char} *data
+     * @return {*}
+     */    
+    void DevicePlayerV4::serialization(const ControlerMsg gasControl,char *data){
+        data[0] = 0XC5;
+        data[1] = 0XAB;
+        data[2] = DEVICEGASV3_DATA_DEVTYPE;
+        data[3] = gasControl.deviceId;
+        data[4] = gasControl.msgId;
+        data[5] = 0;
+        data[6] = 0;
+        data[7] = 0;
+        data[8] = 0;
+        data[9] = check((unsigned char *)(data + 2), 7);
+     }
+
+    
+    /**
+     * @description: Consumer
+     * @param {uint8_t} *data
+     * @param {int} len
+     * @param {int} &msg_id
+     * @return {*}
+     */    
+    bool DevicePlayerV4::Consumer(uint8_t *data, int len, int &msg_id){
+        bool ReceiveSuccessful = false;
+        for (int i = 0; i < len; i++)
+        {
+            switch(_comm.step){
+                case STEP_HEAD_1:
+                    if(data[i] == 0xAB){
+                        _comm.data[0] = 0xAB;
+                        _comm.step = STEP_HEAD_2;
+                    }
+                    break;
+                case STEP_HEAD_2:
+                    if(data[i] == 0xC5){
+                        _comm.data[1] = 0xC5;
+                        _comm.step = STEP_TYPE;
+                    }
+                    break;
+                case STEP_TYPE:
+                    _comm.data[2] = data[i];
+                    _comm.step = STEP_DEVID;
+                    break; 
+                case STEP_DEVID:
+                    _comm.data[3] = data[i];
+                    _comm.step = STEP_COM;
+                    break;
+                case STEP_COM:
+                    _comm.data[4] = data[i];
+                    _comm.step = STEP_ACK;
+                    break;
+                case STEP_ACK:
+                    _comm.data[5] = data[i];
+                    _comm.step = STEP_HEAD_1;
+                    ReceiveSuccessful = true;
+                    _comm.dataCount = 6;
+                    break;
+                default:
+                    _comm.step = STEP_HEAD_1;
+                    break;   
+            }
+        }
+        if(!ReceiveSuccessful) return false;
+        return deserialization(_comm.data, _comm.dataCount, msg_id);
+    }
+
+    /**
+     * @description: deserialization
+     * @param {uint8_t} *data
+     * @param {int} len
+     * @param {int} &msg_id
+     * @return {*}
+     */    
+    bool DevicePlayerV4::deserialization(const uint8_t *data, int len, int &msg_id){
+        if(len == 6 && data[5] == 0x01){
+            this->deviceId = data[3];
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @description: BuildDeviceInfo
+     * @param {SendDevice&} sendDevice
+     * @return {*}
+     */    
+    void DevicePlayerV4::BuildDeviceInfo(SendDevice& sendDevice){
+        sendDevice.deviceId = atoi(this->getDeviceId().c_str());
+        sendDevice.commandCode = "1";
+        sendDevice.status = 1;
+        sendDevice.workStatus = 1;
+        sendDevice.powerStatus = 1;
+        sendDevice.batteryStatus = 1;
+        sendDevice.num  = 0;
+        sendDevice.oxyPressure  = 0;
+        sendDevice.gasPressure  = 0;
+        sendDevice.remark = "";
+        sendDevice.attr1 = std::to_string(this->voltage);     // 电压
+        sendDevice.attr2 = std::to_string(this->pressure);     // 声压
+    }
+
+    /**
+     * @description: 打开
+     * @param {int} deivceId
+     * @return {*}
+     */    
+    int8_t DevicePlayerV4::Open(std::string DeviceId, uint8_t* data, int& length){
+        ControlerMsg gasControl;
+        gasControl.deviceId = atoi(DeviceId.c_str());
+        gasControl.msgId = DEVICEGASV3_COMMAND_PLAY_NOW;
+        gasControl.data = 0x00;
+        length = 10;
+        serialization(gasControl, (char *)data);
+        return 0;
+    }
+
+
+    /**
+     * @description: 关闭
+     * @param {int} deivceId
+     * @return {*}
+     */    
+    int8_t DevicePlayerV4::Close(std::string DeviceId, uint8_t* data, int& length){
+        ControlerMsg gasControl;
+        gasControl.deviceId = atoi(DeviceId.c_str());
+        gasControl.msgId = DEVICEGASV3_COMMAND_STOP;
+        gasControl.data = 0x00;
+        length = 10;
+        serialization(gasControl, (char *)data);
+        return 0;
+    }
+
+    /**
+     * @description: 开炮
+     * @param {int} deivceId
+     * @return {*}
+     */    
+    int8_t DevicePlayerV4::Fire(std::string DeviceId, uint8_t* data, int& length){
+        ControlerMsg gasControl;
+        gasControl.deviceId = atoi(DeviceId.c_str());
+        gasControl.msgId = DEVICEGASV3_COMMAND_PLAY_NOW;
+        gasControl.data = 0x00;
+        length = 10;
+        serialization(gasControl, (char *)data);
+        return 0;
+    }
+
+    /**
+     * @description: 状态
+     * @param {int} deivceId
+     * @return {*}
+     */    
+    int8_t DevicePlayerV4::Status(std::string DeviceId, uint8_t* data, int& length){
+        return 0;
+    }
+} // namespace gsd

+ 146 - 32
modules/Expel/src/Expel.cpp

@@ -1,7 +1,77 @@
 #include "Expel.hpp"
+#include "Shell.h"
 
 namespace gsd
 {
+    class ExpelClient: public TcpClient {
+    public:
+        typedef std::shared_ptr<ExpelClient> Ptr;
+        ExpelClient():TcpClient() {
+        }
+        ~ExpelClient(){
+        }
+
+        /**
+         * @description: setDeviceControl
+         * @param {shared_ptr<deviceBase>} DeviceControl
+         * @return {*}
+         */    
+        void setDeviceControl(std::shared_ptr<ContorlGear> 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)){
+                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<SendDevice> nettyClientResultMsg;
+                deviceControl->BuildDeviceInfo(sendDevice);
+                time(&timestamp);
+                sendDevice.msgTime = ctime(&timestamp);
+                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);
+            }
+        }
+        virtual void onFlush() override{
+            //发送阻塞后,缓存清空事件
+            DebugL;
+        }
+        virtual void onErr(const SockException &ex) override{
+            //断开连接事件,一般是EOF
+            WarnL << ex.what();
+        }
+        virtual void onManager() override{
+        }
+    private:
+        int _nTick = 0;
+        std::shared_ptr<ContorlGear> deviceControl  = nullptr;
+        BufferRaw::Ptr buffer = nullptr;
+    };
+
     /**
      * @description: 获取Ptr
      * @return {*}
@@ -13,6 +83,41 @@ namespace gsd
     }
 
     /**
+     * @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<RecDeviceCommand>} &nettyServerResultMsg
      * @param {ExpelDevice} expelDevice
@@ -92,9 +197,10 @@ namespace gsd
             std::dynamic_pointer_cast<DevicePlayerV3>(deviceControl)->setServerIP(expelDevice.ServerIp);
             break;
 
-        // case DeviceGasV3:
-        //     deviceControl = std::make_shared<deviceGasV3>();
-        //     break;
+        case DeviceType::DevicePlayerV4:
+            deviceControl = std::make_shared<DevicePlayerV4>();
+            std::dynamic_pointer_cast<DevicePlayerV4>(deviceControl)->setServerIP(config::getPtr()->payServerIP);
+            break;
         }
 
         return deviceControl;
@@ -108,6 +214,7 @@ namespace gsd
     int32_t Expel::Open(ExpelDevice& expelDevice){
         std::shared_ptr<ContorlGear> deviceControl = nullptr;
         deviceControl = getControl(expelDevice);
+        if(deviceControl == nullptr) return -1;
         uint8_t data[1024];
         memset(data, 0, sizeof(data));
         int length = 0;
@@ -129,6 +236,7 @@ namespace gsd
     int32_t Expel::Close(ExpelDevice& expelDevice){
         std::shared_ptr<ContorlGear> deviceControl = nullptr;
         deviceControl = getControl(expelDevice);
+        if(deviceControl == nullptr) return -1;
         uint8_t data[1024];
         memset(data, 0, sizeof(data));
         int length = 0;
@@ -149,6 +257,7 @@ namespace gsd
     int32_t Expel::Fire(ExpelDevice& expelDevice){
         std::shared_ptr<ContorlGear> deviceControl = nullptr;
         deviceControl = getControl(expelDevice);
+        if(deviceControl == nullptr) return -1;
         uint8_t data[1024];
         memset(data, 0, sizeof(data));
         int length = 0;
@@ -170,6 +279,7 @@ namespace gsd
     int32_t Expel::Status(ExpelDevice& expelDevice){
         std::shared_ptr<ContorlGear> deviceControl = nullptr;
         deviceControl = getControl(expelDevice);
+        if(deviceControl == nullptr) return -1;
         uint8_t data[1024];
         memset(data, 0, sizeof(data));
         int length = 0;
@@ -210,9 +320,11 @@ namespace gsd
      * @return {*}
      */
     int32_t Expel::Control(std::shared_ptr<ContorlGear>& deviceControl, ExpelDevice& expelDevice, uint8_t* data, int& length, int type){
+        static ExpelClient::Ptr client(new ExpelClient());
         std::lock_guard<mutex> gurad(m_mutex);
         deviceControl->setDeviceId(expelDevice.DeviceId);
         if(deviceControl->getDeviceTool() == ContorlGear::DeviceTools::serial){
+            DebugL;
             CSerialPort ser;
             config::Ptr m_config = config::getPtr();
             if(m_config->debug) DebugL << "Serial control data:" << bytesToHexString(data, length) << endl;
@@ -230,6 +342,7 @@ namespace gsd
             ser.close();
             return 0;
        }else if(deviceControl->getDeviceTool() == ContorlGear::DeviceTools::http){
+            DebugL;
             std::string serviceIP = "";
             if(config::getPtr()->getApp() == "gsd_SZX"){
                 serviceIP = config::getPtr()->payServerIP;
@@ -258,6 +371,18 @@ namespace gsd
                 ErrorL << "HTTP Service unavailable:" << err << endl;
                 return -1;
             }
+        }else if(deviceControl->getDeviceTool() == ContorlGear::DeviceTools::tcp){
+            if(expelDevice.ServerIp == ""){
+                ErrorL << "The device IP address is empty" << endl;
+                return -1;
+            }
+            client->setDeviceControl(deviceControl);
+            if(!client->alive()) client->startConnect(expelDevice.ServerIp, config::getPtr()->ExpelPort);
+            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;
     }
@@ -299,7 +424,6 @@ namespace gsd
                         nettyClientResultMsg.setDataType(NettyClientCommandEnum().device_info);
                         nettyClientResultMsg.setData(sendDevice);
                         nettyClientResultMsg.objectToJson(json);
-
                         NoticeCenter::Instance().emitEvent(NOTICE_DEVICEINFO, requestId ,json);
                     }
                     break;
@@ -323,16 +447,12 @@ namespace gsd
             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;
-            //     if(expelDevice.deviceType == 4) expelDevice.deviceToken = tcp;
-            //     else if(expelDevice.deviceType == 3) expelDevice.deviceToken = http;
-            //     else expelDevice.deviceToken = serial;  
-
-            //     this->Open(expelDevice);
-            // }
+            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;
     }
@@ -349,15 +469,12 @@ namespace gsd
             }
         }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;
-            //     if(expelDevice.deviceType == 4) expelDevice.deviceToken = tcp;
-            //     else if(expelDevice.deviceType == 3) expelDevice.deviceToken = http;
-            //     else expelDevice.deviceToken = serial;   
-            //     this->Close(expelDevice);
-            // }
+            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;
     }
@@ -374,15 +491,12 @@ namespace gsd
             }
         }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;
-            //     if(expelDevice.deviceType == 4) expelDevice.deviceToken = tcp;
-            //     else if(expelDevice.deviceType == 3) expelDevice.deviceToken = http;
-            //     else expelDevice.deviceToken = serial;     
-            //     this->Fire(expelDevice);
-            // }
+            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;
     }

+ 30 - 1
modules/HttpServer/include/HttpServer.hpp

@@ -4,11 +4,13 @@
 #include <iostream>
 #include "UtilBase.hpp"
 #include "Util/logger.h"
+#include <httplib.h>
+#include "config.hpp"
+#include "Expel.hpp"
 
 using namespace std;
 using namespace toolkit;
 
-// TODO
 namespace gsd{
 
     class HttpServer: public ModuleBase
@@ -18,7 +20,34 @@ namespace gsd{
             InfoL;
         }
     public:
+        using Ptr = std::shared_ptr<HttpServer>;
+
+        /**
+         * @description: CreateNew
+         * @return {*}
+         */        
+        static std::shared_ptr<HttpServer> CreateNew();
+
         ~HttpServer(){}
+
+        /**
+         * @description: Init
+         * @return {*}
+         */        
+        virtual bool Init();
+
+        /**
+         * @description: Destroy
+         * @return {*}
+         */        
+        virtual void Destroy();
+
+    protected:
+
+        /**
+         * @brief 服务
+         */        
+        std::shared_ptr<httplib::Server> m_server = nullptr;
     };
 }
 

+ 60 - 7
modules/HttpServer/src/HttpServer.cpp

@@ -1,13 +1,66 @@
-#ifndef __HTTPSERVER_HPP_
-#define __HTTPSERVER_HPP_
+#include "HttpServer.hpp"
 
-#include <iostream>
-
-namespace std
+namespace gsd
 {
-    
+
+    /**
+     * @description: CreateNew
+     * @return {*}
+     */    
+    std::shared_ptr<HttpServer> HttpServer::CreateNew(){
+        return std::shared_ptr<HttpServer>(new HttpServer);
+    }
+
+    /**
+     * @description: 初始化
+     * @return {*}
+     */    
+    bool HttpServer::Init(){
+        if(this->m_server == nullptr){
+            this->m_server = std::make_shared<httplib::Server>();
+        }
+
+        // GET
+        this->m_server->Get("/api/v1/version", [](const httplib::Request& req, httplib::Response& res){
+            res.set_content("version:" + config::getPtr()->getVersion(), "text/plain");
+        });
+
+        // Get
+        this->m_server->Get("/api/v1/expeldev", [](const httplib::Request& req, httplib::Response& res){
+            if(!req.has_param("DeviceID") || !req.has_param("command") || !req.has_param("type")){
+                res.set_content("Periodic incomplete", "text/plain");
+                return;
+            }
+            ExpelDevice expelDevice;
+            expelDevice.DeviceId = req.get_param_value("DeviceID");
+            expelDevice.deviceType  = (DeviceType)std::atoi(req.get_param_value("type").c_str());
+            int command = std::atoi(req.get_param_value("command").c_str());
+            Expel::getPtr()->HttpControler(command, expelDevice);
+            res.set_content("OK", "text/plain");
+        });
+
+        // Get
+        this->m_server->Get("/api/v1/help", [](const httplib::Request& req, httplib::Response& res){
+            std::string str = "usage : \r\n      http://" + config::getPtr()->localIP + ":9980" + "/[interface] \r\n" \
+                            "interface: \r\n version: http://" + config::getPtr()->localIP + ":9980" + "/api/v1/version \r\n   params: null\r\n" \
+                            "interface: \r\n expeldev: http://"+ config::getPtr()->localIP + ":9980" + "/api/v1/expeldev?DeviceID={?}&command={?}&type={?} \r\n    params(DeviceID), " \
+                            "command(Control type 1-open 2-close 3-fire 4-status), type(Equipment type 0-PKX 1-LHW 2-SZX 3-SZX 4-HFE)";
+            res.set_content(str, "text/plain");
+        });
+
+        this->m_server->listen("0.0.0.0", 9980);
+
+        return true;
+    }
+
+    /**
+     * @description: Destroy
+     * @return {*}
+     */    
+    void HttpServer::Destroy(){
+        this->m_server->stop();
+    }
 } // namespace std
 
 
 
-#endif

+ 1 - 0
modules/Monitor/include/Monitor.hpp

@@ -5,6 +5,7 @@
 #include "Util/logger.h"
 #include "kafka_comsumer.h"
 #include "requests.hpp"
+#include "InfineFilter.hpp"
 
 using namespace std;
 using namespace toolkit;

+ 12 - 16
modules/Monitor/src/Monitor.cpp

@@ -40,21 +40,18 @@ namespace gsd
         cnstreamInferData->Objects.clear();
         // 数据转换(TODO 优化) 
         if(cnstreamInferData->jsonToObject(json)){
-            // TODO 过滤器
-            // InfineFilter::Ptr infineFilter = InfineFilter::getPtr();
-            // config::Ptr m_config = config::getPtr();
-
-            // infineFilter->bboxSize = m_config->bboxSize;
-            // // 设置
-            // infineFilter->setSensitivity(m_config->sensitivity);
-            // infineFilter->setInterval(m_config->interval);
-            // infineFilter->setTimeOut(m_config->TimeOut);
-
-            // if(infineFilter != nullptr) {
-            //     if(infineFilter->judgementResult(cnstreamInferData) != OK){
-            //         return false;
-            //     }
-            // }
+            InfineFilter::Ptr infineFilter = InfineFilter::getPtr();
+            config::Ptr m_config = config::getPtr();
+            infineFilter->bboxSize = m_config->bboxSize;
+            // 设置
+            infineFilter->setFilterLevel(m_config->filterLevel);
+            infineFilter->setInterval(m_config->interval);
+            infineFilter->setTimeOut(m_config->TimeOut);
+            if(infineFilter != nullptr) {
+                if(infineFilter->judgementResult(cnstreamInferData) != 0){
+                    return false;
+                }
+            }
             // 解析数据成功
             rapidjson::StringBuffer buffer;
             rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
@@ -90,7 +87,6 @@ namespace gsd
             result->VideoPath = cnstreamInferData->videoPath;
             return true;
         }
-
         return false;
     }
 

+ 3 - 2
modules/TCPClient/src/TCPClient.cpp

@@ -4,7 +4,7 @@
  * @Autor: lishengyin
  * @Date: 2021-09-14 09:12:25
  * @LastEditors: lishengyin
- * @LastEditTime: 2022-08-23 14:45:58
+ * @LastEditTime: 2022-08-24 17:36:36
  */
 #include "TCPClient.hpp"
 
@@ -21,6 +21,7 @@
 #include <thread>
 #include <queue>
 #include <future>
+#include "config.hpp"
 
 namespace gsd{
     /**
@@ -32,7 +33,7 @@ namespace gsd{
     void TCPClient::onConnect(const SockException &ex){
         //连接结果事件
         InfoL << (ex ?  ex.what() : "success, local_ip:") << get_local_ip();
-        //config::getPtr()->localIP = get_local_ip();
+        config::getPtr()->localIP = get_local_ip();
         NoticeCenter::Instance().emitEvent(NOTICE_CONNECTNETTY);
     }
 

+ 10 - 6
modules/config/src/config.cpp

@@ -4,7 +4,7 @@
  * @Autor: lishengyin
  * @Date: 2022-03-07 11:52:23
  * @LastEditors: lishengyin
- * @LastEditTime: 2022-08-23 16:02:50
+ * @LastEditTime: 2022-08-24 10:18:38
  */
 #include "config.hpp"
 #include "Shell.h"
@@ -68,6 +68,7 @@ bool config::Update(){
     
      // 同步数据
     this->getBasicConfig();
+
     if(config::getPtr()->LowVersion){
         int count = m_ini.getIntValue("Device", "count", ret);
         DeviceIds.clear();
@@ -136,9 +137,12 @@ std::string config::getApp(){
  * @return {*}
  */
 bool config::getBasicConfig(){
+    static bool save = false;
     static shared_ptr<httplib::Client> httpClient = nullptr;
-    if(httpClient == nullptr) httpClient = std::make_shared<httplib::Client>(this->Spug_IP, this->Spug_Port);
-
+    if(httpClient == nullptr){
+        httpClient = std::make_shared<httplib::Client>(this->Spug_IP, this->Spug_Port);
+        save = true;
+    }
     httplib::Params params;
     params.emplace("apiKey", this->apiKey);
     params.emplace("app", this->app + "_app");
@@ -178,6 +182,7 @@ bool config::getBasicConfig(){
 
                     if(basicConfig.com_port != "") this->comPort = basicConfig.com_port;
 
+                    if(!save) return false;
                     // 写入并保存
                     int ret;
                     ret = m_ini.setValue("web", "wed_ip", this->NettyIP);
@@ -193,7 +198,8 @@ bool config::getBasicConfig(){
                     m_ini.setValue("Mysql", "mysql_port", std::to_string(this->mysql_port));
                     m_ini.setValue("vpn", "vpn_ip", this->vpnIP);
                     m_ini.save();
-                    return true;
+                    save = false;
+                    return true;    
                 }else{
                     WarnL << "Parsing failure" << endl;
                 }
@@ -282,5 +288,3 @@ void config::getHistoryVideo(vector<std::string>& result){
 
 
 
-
-

+ 1 - 0
plugins/CMakeLists.txt

@@ -36,6 +36,7 @@ include_directories(${GSD_ROOT_DIR}/modules/HttpClient/include)
 include_directories(${GSD_ROOT_DIR}/modules/InfineFilter/include)
 include_directories(${GSD_ROOT_DIR}/modules/Monitor/include)
 include_directories(${GSD_ROOT_DIR}/modules/TCPClient/include)
+include_directories(${GSD_ROOT_DIR}/modules/HttpServer/include)
 include_directories(${GSD_ROOT_DIR}/modules/config/include)
 
 

+ 1 - 0
plugins/ExpelPlugin/include/ExpelPlugin.hpp

@@ -94,6 +94,7 @@ namespace gsd
         Socket::Ptr sockerUdp = nullptr;
         mutex m_mutex;
         bool m_DevPowerState = false;
+        Timer::Ptr timer0 = nullptr;
     };
 } // namespace gsd
 

+ 6 - 4
plugins/ExpelPlugin/src/ExpelPlugin.cpp

@@ -18,6 +18,10 @@ namespace gsd
      * @return {*}
      */    
     bool ExpelPlugin::StartTask(){
+        // timer
+        // if(this->timer0 == nullptr) this->timer0 = std::make_shared<Timer>(10.0f, [&](){
+        //     return true;
+        // }, nullptr);
 
         return true;
     }   
@@ -36,7 +40,7 @@ namespace gsd
      * @return {*}
      */    
     void ExpelPlugin::Destroy(){
-
+        
     }
 
     /**
@@ -50,15 +54,14 @@ namespace gsd
             return false;
         }
 
+        this->sockerUdp->bindUdpSock(7777);
         // 数据接收
         this->sockerUdp->setOnRead([&](const Buffer::Ptr &buf, struct sockaddr *addr , int){
             this->UdpRecData(buf);
         });
-
         return true;
     }
 
-    
     /**
      * @description: UDP数据接收
      * @param {Ptr} &buf
@@ -69,7 +72,6 @@ namespace gsd
         string json = buf->toString();
         std::shared_ptr<CNStreamInferData> cnstreamInferData = nullptr;
         cnstreamInferData = std::make_shared<CNStreamInferData>();
-        DebugL << json << endl;
         if(cnstreamInferData->jsonToObject(json)){
             vector<vector<std::string>> result;
             SqlWriter sqlSelete("SELECT DeviceId,DeviceToken,DeviceType, \

+ 2 - 1
plugins/HttpPlugin/include/HttpPlugin.hpp

@@ -6,6 +6,7 @@
 #include "Util/logger.h"
 #include "config.hpp"
 #include "HttpClient.hpp"
+#include "HttpServer.hpp"
 #include "requests.hpp"
 #include "ExpelDevice.h"
 #include "InfineFilter.hpp"
@@ -69,7 +70,7 @@ namespace gsd
 
     protected:  
         std::shared_ptr<HttpClient> m_httpClient = nullptr;
-
+        std::shared_ptr<HttpServer> m_HttpServer = nullptr;
         // timer
         Timer::Ptr timer0;
     };

+ 8 - 0
plugins/HttpPlugin/src/HttpPlugin.cpp

@@ -27,6 +27,10 @@ namespace gsd
         }else{
             WarnL << "Netty login failed. Procedure" << endl;
         }
+
+        if(this->m_HttpServer == nullptr){
+            this->m_HttpServer = HttpServer::CreateNew();
+        }
         return true;
     }
 
@@ -51,6 +55,9 @@ namespace gsd
             }
             return true;
         }, nullptr);
+
+        this->m_HttpServer->Init();
+        
         return true;
     }
 
@@ -60,6 +67,7 @@ namespace gsd
      */    
     void HttpPlugin::Destroy(){
         InfoL;
+        this->m_HttpServer->Destroy();
     }
 
     /**

+ 0 - 7
plugins/MonitorPlugin/include/MonitorPlugin.hpp

@@ -73,13 +73,6 @@ namespace gsd
         */
         bool SaveVideoRecord(HistoryVideo& historyVideo);
 
-        /**
-        * @description: 发送请求
-        * @param {CNStreamInferData Ptr} data
-        * @return {*}
-        */
-        bool sendRequest(CNStreamInferData::Ptr data);
-
     private:
         std::shared_ptr<Monitor> monitor = nullptr;
         std::shared_ptr<ThreadPool> pool = nullptr;

+ 6 - 114
plugins/MonitorPlugin/src/MonitorPlugin.cpp

@@ -21,7 +21,6 @@ namespace gsd
             return false;
         }
         this->pool = std::make_shared<ThreadPool>(1,ThreadPool::PRIORITY_HIGHEST, false);
-
         return true;
     }
 
@@ -60,9 +59,11 @@ namespace gsd
         // 发送鸟情数据至后端  
         SendBird sendBird;
         sendBird.birdImageBase64 = "";
-        if(!config::getPtr()->debug){
+
+        #ifndef DEBUG
             sendBird.birdImageBase64 = result->ImageBase64;
-        }
+        #endif
+
         sendBird.birdNum = result->Num;
         sendBird.birdType = (NettyClientCommandEnum().bird_info);
 
@@ -95,126 +96,17 @@ namespace gsd
 
         if(TcpPlugin::getPtr()->Alive()){
             TcpPlugin::getPtr()->sendRequest(RequestId, NettyClientCommandEnum().bird_info, json, [&, sql](int status,std::string pbuf){
-                if(!config::getPtr()->LowVersion){
+                #ifndef DEBUG
                     if(status == 200) return;
                     SqlWriter insert(sql.c_str());
                     vector<vector<std::string>> ret;
                     insert << ret;
-                }
+                #endif
             });
         }
     }
 
     /**
-     * @description: 构建请求
-    * @param {CNStreamInferData::Ptr} data
-    * @return {*}
-    */
-    bool MonitorPlugin::sendRequest(CNStreamInferData::Ptr data){
-        FrameInferData::Ptr result = std::make_shared<FrameInferData>();
-        InfineFilter::Ptr infineFilter = InfineFilter::getPtr();
-        config::Ptr m_config = config::getPtr();
-        if(!config::getPtr()->debug){
-            infineFilter->bboxSize = m_config->bboxSize;
-            // 设置
-            infineFilter->setFilterLevel(m_config->filterLevel);
-            infineFilter->setInterval(m_config->interval);
-            infineFilter->setTimeOut(m_config->TimeOut);
-            if(infineFilter != nullptr) {
-                if(infineFilter->judgementResult(data) != OK){
-                    return false;
-                }
-            }
-        }
-        
-        rapidjson::StringBuffer buffer;
-        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
-        writer.StartArray();
-        for(auto &obj : data->Objects)
-        {
-            writer.StartObject();
-            writer.Key("x");
-            writer.Double(obj.BBox.x * 1920);
-            writer.Key("y");
-            writer.Double(obj.BBox.y * 1080);
-            writer.Key("width");
-            writer.Double(obj.BBox.w * 1920);
-            writer.Key("height");
-            writer.Double(obj.BBox.h * 1080);
-            writer.EndObject();
-        }
-        writer.EndArray();
-        // 获取时间
-        char ctime[80];
-        time_t rawtime;
-        struct tm *info;
-        time(&rawtime);
-        info = localtime(&rawtime);
-        strftime(ctime, 80, "%Y-%m-%d %H:%M:%S", info);
-        result->ClassId = 1;
-        result->ImageBase64 = data->ImageBase64;
-        result->Remark = buffer.GetString();
-        result->Num = data->Objects.size();
-        result->WarningTime = ctime;
-        result->VideoPath = data->videoPath;
-        if(result->Num == 0) return false;
-        
-        if(!TcpPlugin::getPtr()->Alive()){
-            result->uuid = uuid::generate();
-            std::string sql = result->ObjectToSql();
-            SqlWriter insert(sql.c_str());
-            vector<vector<std::string>> ret;
-            insert << ret;
-            return true;
-        }
-        // 发送鸟情数据至后端  
-        SendBird sendBird;
-        sendBird.birdImageBase64 = "";
-        if(!config::getPtr()->debug){
-            sendBird.birdImageBase64 = result->ImageBase64;
-        }
-        sendBird.birdNum = result->Num;
-        sendBird.birdType = (NettyClientCommandEnum().bird_info);
-        sendBird.deviceUuid = "";
-
-        if(!config::getPtr()->LowVersion) sendBird.deviceUuid = config::getPtr()->getSimCode();
-        else sendBird.deviceUuid = config::getPtr()->vpnIP;
-        
-        sendBird.degree = 2;
-        sendBird.remark = result->Remark;
-        sendBird.heightRange = "0";
-        sendBird.warningTime = result->WarningTime;
-        sendBird.attr4 = result->VideoPath;
-        sendBird.attr5 = "";
-        HistoryVideo historyVideo;
-        historyVideo.fileName = result->VideoPath;
-        historyVideo.UpdateTime = result->WarningTime;
-        this->SaveVideoRecord(historyVideo);
-
-        NettyClientResultMsg <SendBird> nettyClientResultMsg;
-        std::string RequestId = uuid::generate();
-        result->uuid = RequestId;
-        nettyClientResultMsg.setRequestId(RequestId);
-        nettyClientResultMsg.setData(sendBird);
-        nettyClientResultMsg.setDataType((NettyClientCommandEnum().bird_info));
-        std::string json;
-        nettyClientResultMsg.objectToJson(json);
-        json += "\r\n";
-        std::string sql = result->ObjectToSql();
-        if(TcpPlugin::getPtr()->Alive()){
-            TcpPlugin::getPtr()->sendRequest(RequestId, NettyClientCommandEnum().bird_info, json, [&, sql](int status,std::string pbuf){
-                if(!config::getPtr()->debug){
-                    if(status == 200) return;
-                    SqlWriter insert(sql.c_str());
-                    vector<vector<std::string>> ret;
-                    insert << ret;
-                }
-            });
-        }else ErrorL;
-        return true;
-    }
-
-    /**
      * @description: 
      * @param {Ptr&} result
      * @return {*}

+ 3 - 2
source/CMakeLists.txt

@@ -42,6 +42,7 @@ include_directories(${CNSTREAM_ROOT_DIR}/3rdparty/)
 # ---[ modules include dirs
 include_directories(${CNSTREAM_ROOT_DIR}/modules/Expel/include)
 include_directories(${CNSTREAM_ROOT_DIR}/modules/HttpClient/include)
+include_directories(${CNSTREAM_ROOT_DIR}/modules/HttpServer/include)
 include_directories(${CNSTREAM_ROOT_DIR}/modules/InfineFilter/include)
 include_directories(${CNSTREAM_ROOT_DIR}/modules/Monitor/include)
 include_directories(${CNSTREAM_ROOT_DIR}/modules/TCPClient/include)
@@ -61,5 +62,5 @@ aux_source_directory(${CNSTREAM_ROOT_DIR}/source/UserApp/src userApps)
 # ---[ add targets
 # set(EXECUTABLE_OUTPUT_PATH ${SOURCE_ROOT_DIR}/bin)
 
-add_executable(main ${srcs} ${userApps} ${3RDPARTY_LIBS})
-target_link_libraries(main gsd_core gsd_modules gsd_plugins pthread dl)
+add_executable(gsd ${srcs} ${userApps} ${3RDPARTY_LIBS})
+target_link_libraries(gsd gsd_core gsd_modules gsd_plugins pthread dl)

+ 1 - 0
source/UserApp/include/UserApp.hpp

@@ -70,6 +70,7 @@ namespace gsd
         TcpPlugin::Ptr m_TcpPlugin = nullptr;
         ExpelPlugin::Ptr m_ExpelPlugin = nullptr;
         MonitorPlugin::Ptr m_MonitorPlugin = nullptr;
+        Timer::Ptr timer0 = nullptr;
     };
 } // namespace gsd
 

+ 22 - 3
source/UserApp/src/UserApp.cpp

@@ -64,6 +64,13 @@ namespace gsd
             ErrorL << "MonitorPlugin init failed" << endl;
             return false;
         }
+
+        // 释放资源
+        NoticeCenter::Instance().addListener(0, NOTICE_DESTROY,
+            [&](){
+            this->Destroy();
+        });
+
         return true;
     }
 
@@ -73,12 +80,24 @@ namespace gsd
      */    
     bool UserApp::StartTask(){
         InfoL;
-        // HTTP启动任务
-        this->m_HttpPlugin->StartTask();
+        
+        // 更新配置
+        if(this->timer0 == nullptr){
+            this->timer0 = std::make_shared<Timer>(10.0f, [&](){
+                config::getPtr()->Update();
+                return true;
+            }, nullptr);
+        }
+  
         // TCP启动任务
         this->m_TcpPlugin->StartTask();
+        // Expel启动任务
+        this->m_ExpelPlugin->StartTask();
         // Monitor启动任务
         this->m_MonitorPlugin->StartTask();
+        // HTTP启动任务
+        this->m_HttpPlugin->StartTask();
+        
         return true;
     }  
     
@@ -89,8 +108,8 @@ namespace gsd
      */        
     void UserApp::Destroy(){
         this->m_MonitorPlugin->Destroy();
-        this->m_HttpPlugin->Destroy();
         this->m_TcpPlugin->Destroy();
+        this->m_HttpPlugin->Destroy();
     }
 
     /**

+ 5 - 3
source/src/main.cpp

@@ -13,7 +13,10 @@ using namespace std;
 int main(int argc, char* argv[]){
 
     static semaphore sem;
-    signal(SIGINT, [](int) { sem.post(); });// 设置退出信号
+    signal(SIGINT, [](int) { 
+        sem.post(); 
+        NoticeCenter::Instance().emitEvent(NOTICE_DESTROY);
+    });// 设置退出信号
 
     //设置日志
 	Logger::Instance().add(std::make_shared<ConsoleChannel>());
@@ -36,10 +39,9 @@ int main(int argc, char* argv[]){
     // 启动任务
     app->StartTask();
     
-    sem.wait();
-
     InfoL << "app Destroy" << endl;
 
     app->Destroy();
+
     return 0;
 }