From 5395f11892656d662ea43f076f566be10f3bcac0 Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 26 Sep 2024 10:58:55 +0800 Subject: [PATCH] Initial Commit --- AboutDlg.h | 34 +++ CacService.cpp | 213 ++++++++++++++++++ CacService.h | 70 ++++++ MQTTClient.cpp | 56 +++++ MQTTClient.h | 1 + MQTTClient.rc | 342 +++++++++++++++++++++++++++++ MQTTClient.sln | 31 +++ MQTTClient.vcxproj | 229 ++++++++++++++++++++ MQTTClient.vcxproj.filters | 58 +++++ MainFrm.h | 108 ++++++++++ OptionDlg.h | 73 +++++++ View.h | 431 +++++++++++++++++++++++++++++++++++++ res/MQTTClient.ico | Bin 0 -> 11502 bytes res/toolbar.bmp | Bin 0 -> 1078 bytes resource.h | 28 +++ stdafx.cpp | 25 +++ stdafx.h | 40 ++++ 17 files changed, 1739 insertions(+) create mode 100644 AboutDlg.h create mode 100644 CacService.cpp create mode 100644 CacService.h create mode 100644 MQTTClient.cpp create mode 100644 MQTTClient.h create mode 100644 MQTTClient.rc create mode 100644 MQTTClient.sln create mode 100644 MQTTClient.vcxproj create mode 100644 MQTTClient.vcxproj.filters create mode 100644 MainFrm.h create mode 100644 OptionDlg.h create mode 100644 View.h create mode 100644 res/MQTTClient.ico create mode 100644 res/toolbar.bmp create mode 100644 resource.h create mode 100644 stdafx.cpp create mode 100644 stdafx.h diff --git a/AboutDlg.h b/AboutDlg.h new file mode 100644 index 0000000..d39de81 --- /dev/null +++ b/AboutDlg.h @@ -0,0 +1,34 @@ +// aboutdlg.h : interface of the CAboutDlg class +// +///////////////////////////////////////////////////////////////////////////// + +#pragma once + +class CAboutDlg : public CDialogImpl +{ +public: + enum { IDD = IDD_ABOUTBOX }; + + BEGIN_MSG_MAP(CAboutDlg) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_ID_HANDLER(IDOK, OnCloseCmd) + COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) + END_MSG_MAP() + +// Handler prototypes (uncomment arguments if needed): +// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) +// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + CenterWindow(GetParent()); + return TRUE; + } + + LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + EndDialog(wID); + return 0; + } +}; diff --git a/CacService.cpp b/CacService.cpp new file mode 100644 index 0000000..b6f3924 --- /dev/null +++ b/CacService.cpp @@ -0,0 +1,213 @@ +#include "CacService.h" +#include +#include + +#include "Utils.h" + +#define KEEP_ALIVE 60 + +void CCacService::cac_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message) +{ + ((CCacService*)userdata)->MessageCallback(mosq, message); +} + +void CCacService::cac_connect_callback(struct mosquitto *mosq, void *userdata, int result) +{ + ((CCacService*)userdata)->ConnectCallback(mosq, result); +} + +void CCacService::cac_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos) +{ + ((CCacService*)userdata)->SubscribeCallback(mosq, mid, qos_count, granted_qos); +} + +void CCacService::cac_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str) +{ + ((CCacService*)userdata)->LogCallback(mosq, level, str); +} + +CCacService::CCacService() : m_session(true), m_mosq(NULL), m_conn(NULL) +{ +} + +CCacService::~CCacService() +{ + if (m_mosq != NULL) + { + mosquitto_destroy(m_mosq); + m_mosq = NULL; + } + if (m_conn != NULL) + { + delete m_conn; + } +} + +void CCacService::MessageCallback(struct mosquitto *mosq, const struct mosquitto_message *message) +{ + if (message->payloadlen) { + printf("%s %s", message->topic, (char *)(message->payload)); + } + else { + printf("%s (null)\n", message->topic); + } + fflush(stdout); +} + +void CCacService::ConnectCallback(struct mosquitto *mosq, int result) +{ + int i; + if (!result) + { + /* Subscribe to broker information topics on successful connect. */ + // mosquitto_subscribe(mosq, NULL, "GaiÒ¯:", 2); + } + else + { + fprintf(stderr, "Connect failed\n"); + } +} + +void CCacService::SubscribeCallback(struct mosquitto *mosq, int mid, int qos_count, const int *granted_qos) +{ + int i; + printf("Subscribed (mid: %d): %d", mid, granted_qos[0]); + for (i = 1; i < qos_count; i++) + { + printf(", %d", granted_qos[i]); + } + printf("\n"); +} + +void CCacService::LogCallback(struct mosquitto *mosq, int level, const char *str) +{ + /* Pring all log messages regardless of level. */ + printf("%s\n", str); +} + +void CCacService::MosquittoLoop() +{ + mosquitto_loop_forever(m_mosq, -1, 1); + int aa = 0; +} + +void CCacService::ExportLoop(CMySQLAdo* conn) +{ + while (1) + { + for (std::map::iterator it = m_syncTables.begin(); it != m_syncTables.end(); ++it) + { + Json::Value jonsObj = Json::objectValue; + jonsObj["AssetList"] = Json::arrayValue; + + m_conn->ProcessTable(it->second, jonsObj["AssetList"]); + + int mid = 0; + std::string data = CvtJSONToString(jonsObj); +#ifdef _DEBUG + std::cout << data << std::endl; + writeFile("D://testJson.txt", (const unsigned char *)data.c_str(), data.size()); +#endif + if (m_mosq != NULL) + { + int res = mosquitto_publish(m_mosq, &mid, "external/data", data.size(), (void *)(data.c_str()), SYNC_QOS_LEVEL_0, false); + if (res == MOSQ_ERR_SUCCESS) + { + // Update time + int aa = 0; + } + else + { + if (MOSQ_ERR_ERRNO == res) + { + int errorno = errno; + char* errmsg = strerror(errorno); + + int aa = 0; + } + int bbb = 0; + } + } + } + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } +} + + +bool CCacService::Start(const std::map& arguments) +{ + //create mosquitto client + m_mosq = mosquitto_new(NULL, m_session, NULL); + if (!m_mosq) + { + // printf("create client failed..\n"); + // mosquitto_lib_cleanup(); + return false; + } + // Callback + mosquitto_user_data_set(m_mosq, (void *)this); + // mosquitto_log_callback_set(mosq, cac_log_callback); + mosquitto_connect_callback_set(m_mosq, cac_connect_callback); + mosquitto_message_callback_set(m_mosq, cac_message_callback); + // mosquitto_subscribe_callback_set(mosq, cac_subscribe_callback); + // connect to server + std::string mqttServer = FindArgument(arguments, ARG_KEY_MQTT_HOST); + std::string mqttPort = FindArgument(arguments, ARG_KEY_MQTT_PORT); + + std::string mqttUser = FindArgument(arguments, ARG_KEY_MQTT_USER); + std::string mqttPwd = FindArgument(arguments, ARG_KEY_MQTT_PASSWORD); + + mqttPwd = "AliOS%1688"; + + std::string dbServer = FindArgument(arguments, ARG_KEY_DB_HOST); + unsigned short dbPort = 3306; // arguments["mqttport"]; + std::string dbName = FindArgument(arguments, ARG_KEY_DB_NAME); + // std::string dbName = FindArgument(arguments, ARG_KEY_DB_NAME); + std::string dbUser = FindArgument(arguments, ARG_KEY_DB_USER); + std::string dbPwd = FindArgument(arguments, ARG_KEY_DB_PASSWORD); + + mosquitto_username_pw_set(m_mosq, mqttUser.c_str(), mqttPwd.c_str()); + + if (mosquitto_connect(m_mosq, mqttServer.c_str(), atoi(mqttPort.c_str()), KEEP_ALIVE)) + { + mosquitto_destroy(m_mosq); + m_mosq = NULL; + fprintf(stderr, "Unable to connect.\n"); +#ifndef _DEBUG + return false; +#endif + } + + m_conn = new CMySQLAdo(); + if (!m_conn->Connect(dbServer, dbUser, dbPwd, dbName)) + { + return false; + } + + m_conn->loadSyncTables(SYNC_CLIENT_CAC_MQTT, m_syncTables); + + //Ñ­»·´¦ÀíÍøÂçÏûÏ¢ + // mosquitto_loop_forever(mosq, -1, 1); + if (m_mosq != NULL) + { + std::thread th1(std::mem_fun(&CCacService::MosquittoLoop), this); + m_mosqThread.swap(th1); + } + + std::thread th2(std::mem_fun(&CCacService::ExportLoop), this, m_conn); + m_exportThread.swap(th2); + + return true; +} + +void CCacService::Join() +{ + if (m_mosqThread.joinable()) m_mosqThread.join(); + if (m_exportThread.joinable()) m_exportThread.join(); +} + +// unsigned int CCacService::ProcessTable(const std::string& tableName, const CSyncRecord& syncRecord, const CSyncTableFields& syncTable) +// { +// return 0; +// } \ No newline at end of file diff --git a/CacService.h b/CacService.h new file mode 100644 index 0000000..e67cbc3 --- /dev/null +++ b/CacService.h @@ -0,0 +1,70 @@ +#ifndef __CAC_SERVICE__ +#define __CAC_SERVICE__ + + +#include +#include +#include "MySQLAdo.h" + +#define SYNC_CLIENT_CAC_MQTT 10 +#define SYNC_QOS_LEVEL_0 0 + +#define TOPIC_SENSOR "/xy/sensor/device/data/report" +#define TOPIC_SENSOR "/xy/evaluation/transformer/results" + +#define ARG_KEY_MQTT_HOST "mqtthost" +#define ARG_KEY_MQTT_PORT "mqttport" +#define ARG_KEY_MQTT_USER "mqttuser" +#define ARG_KEY_MQTT_PASSWORD "mqttpwd" +#define ARG_KEY_DB_HOST "dbhost" +#define ARG_KEY_DB_PORT "dbport" +#define ARG_KEY_DB_NAME "dbname" +#define ARG_KEY_DB_USER "dbuser" +#define ARG_KEY_DB_PASSWORD "dbpwd" + + +class CCacService +{ +public: + CCacService(); + ~CCacService(); + + bool Start(const std::map& arguments); + void Join(); + +protected: + static void cac_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message); + static void cac_connect_callback(struct mosquitto *mosq, void *userdata, int result); + static void cac_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos); + static void cac_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str); + + void MessageCallback(struct mosquitto *mosq, const struct mosquitto_message *message); + void ConnectCallback(struct mosquitto *mosq, int result); + void SubscribeCallback(struct mosquitto *mosq, int mid, int qos_count, const int *granted_qos); + void LogCallback(struct mosquitto *mosq, int level, const char *str); + + void MosquittoLoop(); + void ExportLoop(CMySQLAdo* conn); + + // unsigned int ProcessTable(const std::string& tableName, const CSyncRecord& syncRecord, const CSyncTableFields& syncTable); + +protected: + std::string m_dbHost; + std::string m_dbName; + std::string m_dbUser; + std::string m_dbPassword; + + bool m_session; + struct mosquitto* m_mosq; + std::thread m_mosqThread; + std::thread m_exportThread; + + std::map m_syncTables; + // std::vector m_syncRecords; + +}; + + +#endif // __CAC_SERVICE__ + + diff --git a/MQTTClient.cpp b/MQTTClient.cpp new file mode 100644 index 0000000..27a9a5f --- /dev/null +++ b/MQTTClient.cpp @@ -0,0 +1,56 @@ +// MQTTClient.cpp : main source file for MQTTClient.exe +// + +#include "stdafx.h" + +#include +#include +#include + +#include "resource.h" + +#include "OptionDlg.h" +#include "View.h" +#include "aboutdlg.h" +#include "MainFrm.h" + +CAppModule _Module; + +int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT) +{ + CMessageLoop theLoop; + _Module.AddMessageLoop(&theLoop); + + CMainFrame wndMain; + + if(wndMain.CreateEx() == NULL) + { + ATLTRACE(_T("Main window creation failed!\n")); + return 0; + } + + wndMain.ShowWindow(nCmdShow); + + int nRet = theLoop.Run(); + + _Module.RemoveMessageLoop(); + return nRet; +} + +int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) +{ + HRESULT hRes = ::CoInitialize(NULL); + ATLASSERT(SUCCEEDED(hRes)); + + AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls + + hRes = _Module.Init(NULL, hInstance); + ATLASSERT(SUCCEEDED(hRes)); + + int nRet = Run(lpstrCmdLine, nCmdShow); + + _Module.Term(); + ::CoUninitialize(); + + return nRet; +} diff --git a/MQTTClient.h b/MQTTClient.h new file mode 100644 index 0000000..9a70ff3 --- /dev/null +++ b/MQTTClient.h @@ -0,0 +1 @@ +// MQTTClient.h diff --git a/MQTTClient.rc b/MQTTClient.rc new file mode 100644 index 0000000..37f14e4 --- /dev/null +++ b/MQTTClient.rc @@ -0,0 +1,342 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "atlres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Chinese (Simplified, PRC) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED +#pragma code_page(936) + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "Ñ¡Ïî", ID_FILE_OPTIONS + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT + MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE + END + POPUP "&View" + BEGIN + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Help" + BEGIN + MENUITEM "&About MQTTClient", ID_APP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG 0, 0, 187, 102 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 9, "Segoe UI" +BEGIN + DEFPUSHBUTTON "OK",IDOK,130,81,50,14 + CTEXT "MQTTClient Application v1.0\n\n(c) Copyright 2024",IDC_STATIC,25,57,78,32 + ICON IDR_MAINFRAME,IDC_STATIC,55,26,18,20 + GROUPBOX "",IDC_STATIC,7,7,115,88 +END + +IDD_MQTTCLIENT_FORM DIALOGEX 0, 0, 371, 158 +STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +EXSTYLE WS_EX_CLIENTEDGE +FONT 9, "Segoe UI", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_TO_SEND,7,23,301,55,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL + COMBOBOX IDC_TOPICES,7,7,292,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "·¢ËÍ",IDC_SEND,314,7,50,14 + EDITTEXT IDC_TO_RECV,7,83,357,68,ES_MULTILINE | ES_AUTOHSCROLL | WS_VSCROLL + PUSHBUTTON "Çå¿Õ",IDC_CLEAR,314,65,50,14 +END + +IDD_OPTIONS_DLG DIALOGEX 0, 0, 310, 177 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,199,156,50,14 + PUSHBUTTON "Cancel",IDCANCEL,253,156,50,14 + EDITTEXT IDC_USERNAME,46,7,124,14,ES_AUTOHSCROLL + EDITTEXT IDC_PASSWORD,46,27,122,14,ES_AUTOHSCROLL + LTEXT "Óû§Ãû",IDC_STATIC,7,7,27,8 + LTEXT "ÃÜÂë",IDC_STATIC,9,29,18,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 180 + TOPMARGIN, 7 + BOTTOMMARGIN, 95 + END + + IDD_MQTTCLIENT_FORM, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 364 + TOPMARGIN, 7 + BOTTOMMARGIN, 151 + END + + IDD_OPTIONS_DLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 303 + TOPMARGIN, 7 + BOTTOMMARGIN, 170 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS +BEGIN + "N", ID_FILE_NEW, VIRTKEY, CONTROL + "O", ID_FILE_OPEN, VIRTKEY, CONTROL + "S", ID_FILE_SAVE, VIRTKEY, CONTROL + "P", ID_FILE_PRINT, VIRTKEY, CONTROL + VK_F6, ID_NEXT_PANE, VIRTKEY + VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,4 + PRODUCTVERSION 1,0,0,4 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "MQTTClient Module" + VALUE "FileVersion", "1.0.0.4" + VALUE "InternalName", "MQTTClient" + VALUE "LegalCopyright", "Copyright 2024" + VALUE "OriginalFilename", "MQTTClient.exe" + VALUE "ProductName", "MQTTClient Module" + VALUE "ProductVersion", "1.0.0.4" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_MQTTCLIENT_FORM AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_OPTIONS_DLG AFX_DIALOG_LAYOUT +BEGIN + 0 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDR_MAINFRAME "MQTTClient" +END + +STRINGTABLE +BEGIN + ID_FILE_NEW "Create a new document\nNew" + ID_FILE_OPEN "Open an existing document\nOpen" + ID_FILE_CLOSE "Close the active document\nClose" + ID_FILE_SAVE "Save the active document\nSave" + ID_FILE_SAVE_AS "Save the active document with a new name\nSave As" + ID_FILE_PAGE_SETUP "Change the printing options\nPage Setup" + ID_FILE_PRINT_SETUP "Change the printer and printing options\nPrint Setup" + ID_FILE_PRINT "Print the active document\nPrint" + ID_FILE_PRINT_PREVIEW "Display full pages\nPrint Preview" +END + +STRINGTABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright\nAbout" + ID_APP_EXIT "Quit the application; prompts to save documents\nExit" +END + +STRINGTABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane\nNext Pane" + ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane" +END + +STRINGTABLE +BEGIN + ID_WINDOW_NEW "Open another window for the active document\nNew Window" + ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window\nArrange Icons" + ID_WINDOW_CASCADE "Arrange windows so they overlap\nCascade Windows" + ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles\nTile Windows" + ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles\nTile Windows" + ID_WINDOW_SPLIT "Split the active window into panes\nSplit" +END + +STRINGTABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection\nErase" + ID_EDIT_CLEAR_ALL "Erase everything\nErase All" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut" + ID_EDIT_FIND "Find the specified text\nFind" + ID_EDIT_PASTE "Insert Clipboard contents\nPaste" + ID_EDIT_REPEAT "Repeat the last action\nRepeat" + ID_EDIT_REPLACE "Replace specific text with different text\nReplace" + ID_EDIT_SELECT_ALL "Select the entire document\nSelect All" + ID_EDIT_UNDO "Undo the last action\nUndo" + ID_EDIT_REDO "Redo the previously undone action\nRedo" +END + +STRINGTABLE +BEGIN + ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar" +END + +STRINGTABLE +BEGIN + ATL_IDS_SCSIZE "Change the window size" + ATL_IDS_SCMOVE "Change the window position" + ATL_IDS_SCMINIMIZE "Reduce the window to an icon" + ATL_IDS_SCMAXIMIZE "Enlarge the window to full size" + ATL_IDS_SCNEXTWINDOW "Switch to the next document window" + ATL_IDS_SCPREVWINDOW "Switch to the previous document window" + ATL_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE +BEGIN + ATL_IDS_SCRESTORE "Restore the window to normal size" + ATL_IDS_SCTASKLIST "Activate Task List" + ATL_IDS_MDICHILD "Activate this window" +END + +STRINGTABLE +BEGIN + ATL_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE +BEGIN + ATL_IDS_MRU_FILE "Open this document" +END + +#endif // Chinese (Simplified, PRC) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""atlres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\MQTTClient.ico" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + diff --git a/MQTTClient.sln b/MQTTClient.sln new file mode 100644 index 0000000..14560bf --- /dev/null +++ b/MQTTClient.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.34829.251 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MQTTClient", "MQTTClient.vcxproj", "{E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}.Debug|x64.ActiveCfg = Debug|x64 + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}.Debug|x64.Build.0 = Debug|x64 + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}.Debug|x86.ActiveCfg = Debug|Win32 + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}.Debug|x86.Build.0 = Debug|Win32 + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}.Release|x64.ActiveCfg = Release|x64 + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}.Release|x64.Build.0 = Release|x64 + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}.Release|x86.ActiveCfg = Release|Win32 + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A4FB8712-D169-4266-B3F6-060D6426A309} + EndGlobalSection +EndGlobal diff --git a/MQTTClient.vcxproj b/MQTTClient.vcxproj new file mode 100644 index 0000000..48d07ed --- /dev/null +++ b/MQTTClient.vcxproj @@ -0,0 +1,229 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {E4C7BDA2-EF45-4CAB-8542-DBF36D3624AB} + + + + Application + true + v141 + Unicode + + + Application + false + v141 + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + D:\Workspace\deps\include;C:\Program Files\mosquitto\devel;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\wtl\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + D:\Workspace\deps\x64\dbg;C:\Program Files\mosquitto\devel;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + + + false + + + false + D:\Workspace\deps\include;C:\Program Files\mosquitto\devel;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\wtl\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + D:\Workspace\deps\x64\rel;C:\Program Files\mosquitto\devel;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + + + + Use + Level3 + MultiThreadedDebug + EditAndContinue + EnableFastChecks + Disabled + WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) + + + Windows + true + + + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + _DEBUG;%(PreprocessorDefinitions) + + + false + Win32 + _DEBUG;%(PreprocessorDefinitions) + MQTTClient.h + MQTTClient_i.c + MQTTClient_p.c + true + $(IntDir)/MQTTClient.tlb + + + + + + Use + Level3 + MultiThreadedDebug + EditAndContinue + EnableFastChecks + Disabled + _WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) + + + Windows + true + + + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + _DEBUG;%(PreprocessorDefinitions) + + + false + _DEBUG;%(PreprocessorDefinitions) + MQTTClient.h + MQTTClient_i.c + MQTTClient_p.c + true + $(IntDir)/MQTTClient.tlb + + + + + + Use + Level3 + MultiThreaded + + + WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) + + + Windows + + + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + + + false + Win32 + NDEBUG;%(PreprocessorDefinitions) + MQTTClient.h + MQTTClient_i.c + MQTTClient_p.c + true + $(IntDir)/MQTTClient.tlb + + + + + + Use + Level3 + MultiThreaded + + + _WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) + + + Windows + + + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + + + false + NDEBUG;%(PreprocessorDefinitions) + MQTTClient.h + MQTTClient_i.c + MQTTClient_p.c + true + $(IntDir)/MQTTClient.tlb + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MQTTClient.vcxproj.filters b/MQTTClient.vcxproj.filters new file mode 100644 index 0000000..c0f3f84 --- /dev/null +++ b/MQTTClient.vcxproj.filters @@ -0,0 +1,58 @@ + + + + + {6fa2c6ca-dbc4-427c-9442-85781df4716f} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {aca95d59-80cb-4025-a126-688751e88e02} + h;hpp;hxx;hm;inl;inc + + + {3c2c911d-6a88-4ad3-9b1a-805d7a62a29d} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/MainFrm.h b/MainFrm.h new file mode 100644 index 0000000..d7c14f5 --- /dev/null +++ b/MainFrm.h @@ -0,0 +1,108 @@ +// MainFrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#pragma once + +class CMainFrame : + public CFrameWindowImpl, + public CUpdateUI, + public CMessageFilter, public CIdleHandler +{ +public: + DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME) + + CView m_view; + + virtual BOOL PreTranslateMessage(MSG* pMsg) + { + if(CFrameWindowImpl::PreTranslateMessage(pMsg)) + return TRUE; + + return m_view.PreTranslateMessage(pMsg); + } + + virtual BOOL OnIdle() + { + return FALSE; + } + + BEGIN_UPDATE_UI_MAP(CMainFrame) + UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP) + END_UPDATE_UI_MAP() + + BEGIN_MSG_MAP(CMainFrame) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit) + COMMAND_ID_HANDLER(ID_FILE_OPTIONS, OnFileOption) + COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar) + COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout) + CHAIN_MSG_MAP(CUpdateUI) + CHAIN_MSG_MAP(CFrameWindowImpl) + END_MSG_MAP() + +// Handler prototypes (uncomment arguments if needed): +// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) +// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + + CreateSimpleStatusBar(); + + m_hWndClient = m_view.Create(m_hWnd); + UISetCheck(ID_VIEW_STATUS_BAR, 1); + + // register object for message filtering and idle updates + CMessageLoop* pLoop = _Module.GetMessageLoop(); + ATLASSERT(pLoop != NULL); + pLoop->AddMessageFilter(this); + pLoop->AddIdleHandler(this); + + return 0; + } + + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + // unregister message filtering and idle updates + CMessageLoop* pLoop = _Module.GetMessageLoop(); + ATLASSERT(pLoop != NULL); + pLoop->RemoveMessageFilter(this); + pLoop->RemoveIdleHandler(this); + + bHandled = FALSE; + return 1; + } + + LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + PostMessage(WM_CLOSE); + return 0; + } + + LRESULT OnFileOption(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + COptionDlg dlg; + dlg.DoModal(); + + return 0; + } + + LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar); + ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE); + UISetCheck(ID_VIEW_STATUS_BAR, bVisible); + UpdateLayout(); + return 0; + } + + LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + CAboutDlg dlg; + dlg.DoModal(); + return 0; + } +}; diff --git a/OptionDlg.h b/OptionDlg.h new file mode 100644 index 0000000..22c8aaa --- /dev/null +++ b/OptionDlg.h @@ -0,0 +1,73 @@ +// aboutdlg.h : interface of the CAboutDlg class +// +///////////////////////////////////////////////////////////////////////////// + +#pragma once + +class COptionDlg : public CDialogImpl +{ +public: + enum { IDD = IDD_OPTIONS_DLG }; + + BEGIN_MSG_MAP(COptionDlg) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_ID_HANDLER(IDOK, OnCloseCmd) + COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) + END_MSG_MAP() + +// Handler prototypes (uncomment arguments if needed): +// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) +// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + CenterWindow(GetParent()); + + SetDlgItemText(IDC_USERNAME, TEXT("test")); + SetDlgItemText(IDC_PASSWORD, TEXT("123456")); + CRegKey key; + TCHAR buf[MAX_PATH] = { 0 }; + if (key.Open(HKEY_CURRENT_USER, TEXT("Software\\XYPower\\MQTTClient"), KEY_READ) == ERROR_SUCCESS) + { + ULONG bufLen = MAX_PATH; + if (key.QueryStringValue(TEXT("UserName"), buf, &bufLen) == ERROR_SUCCESS) + { + SetDlgItemText(IDC_USERNAME, buf); + } + + bufLen = MAX_PATH; + if (key.QueryStringValue(TEXT("Password"), buf, &bufLen) == ERROR_SUCCESS) + { + SetDlgItemText(IDC_PASSWORD, buf); + } + + key.Close(); + } + + return TRUE; + } + + LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) + { + if (wID == IDOK) + { + CRegKey key; + LSTATUS res = ERROR_SUCCESS; + if ((res = key.Create(HKEY_CURRENT_USER, TEXT("Software\\XYPower\\MQTTClient"))) == ERROR_SUCCESS) + { + CString buf; + GetDlgItemText(IDC_USERNAME, buf); + key.SetStringValue(TEXT("UserName"), buf); + + GetDlgItemText(IDC_PASSWORD, buf); + key.SetStringValue(TEXT("Password"), buf); + + key.Close(); + } + } + + EndDialog(wID); + return 0; + } +}; diff --git a/View.h b/View.h new file mode 100644 index 0000000..ae232cd --- /dev/null +++ b/View.h @@ -0,0 +1,431 @@ +// View.h : interface of the CView class +// +///////////////////////////////////////////////////////////////////////////// + +#pragma once + +#define SERVICES_COMMAND_TOPIC "/v1/devices/MSRDT-A/command" +#define SERVICES_RESPONSE_TOPIC "/v1/devices/MSRDT-A/commandResponse" +#define DEVICES_DATA_TOPIC "/v1/devices/MSRDT-A/datas" + +#define MQTT_SERVER "61.169.135.146" +#define MQTT_PORT 51001 +#define MQTT_USERNAME "test" +#define MQTT_PASSWORD "123456" + + +#define MQTT_KEEP_ALIVE 60 +#define SYNC_CLIENT_CAC_MQTT 10 +#define SYNC_QOS_LEVEL_0 0 + +#define WM_NEW_MSG (WM_USER + 2) + +class CView : public CDialogImpl, public CDialogResize +{ +public: + enum { IDD = IDD_MQTTCLIENT_FORM }; + + struct mosquitto *m_mosq; + bool m_session; + + std::thread m_mqttThread; + + CString m_userName; + CString m_password; + + BOOL PreTranslateMessage(MSG* pMsg) + { + return CWindow::IsDialogMessage(pMsg); + } + + BEGIN_DLGRESIZE_MAP(CView) + DLGRESIZE_CONTROL(IDC_SEND, DLSZ_MOVE_X) + DLGRESIZE_CONTROL(IDC_CLEAR, DLSZ_MOVE_X) + DLGRESIZE_CONTROL(IDC_TOPICES, DLSZ_SIZE_X) + DLGRESIZE_CONTROL(IDC_TO_SEND, DLSZ_SIZE_X) + DLGRESIZE_CONTROL(IDC_TO_RECV, DLSZ_SIZE_X | DLSZ_SIZE_Y) + END_DLGRESIZE_MAP() + + + BEGIN_MSG_MAP(CView) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(WM_NEW_MSG, OnNewMsgArrived) + + COMMAND_HANDLER(IDC_SEND, BN_CLICKED, OnSendCmd) + COMMAND_HANDLER(IDC_CLEAR, BN_CLICKED, OnClearCmd) + CHAIN_MSG_MAP(CDialogResize) + END_MSG_MAP() + +// Handler prototypes (uncomment arguments if needed): +// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) +// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) + + LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + DlgResize_Init(); + + m_userName = TEXT(MQTT_USERNAME); + m_password = TEXT(MQTT_PASSWORD); + LoadUserAndPassword(); + + CEdit edt = GetDlgItem(IDC_TO_RECV); + edt.SetLimitText(-1); + + CComboBox cmb = GetDlgItem(IDC_TOPICES); + cmb.AddString(TEXT(SERVICES_COMMAND_TOPIC)); + cmb.AddString(TEXT(SERVICES_RESPONSE_TOPIC)); + cmb.AddString(TEXT(DEVICES_DATA_TOPIC)); + + cmb.SetCurSel(0); + + m_mosq = NULL; + m_session = true; + + mosquitto_lib_init(); + + //create mosquitto client + const char * clientId = NULL; + m_mosq = mosquitto_new(clientId, m_session, NULL); + if (!m_mosq) + { + // printf("create client failed..\n"); + // mosquitto_lib_cleanup(); + return false; + } + // Callback + mosquitto_user_data_set(m_mosq, (void *)this); + // mosquitto_log_callback_set(mosq, cac_log_callback); + mosquitto_connect_callback_set(m_mosq, cac_connect_callback); + mosquitto_message_callback_set(m_mosq, cac_message_callback); + mosquitto_subscribe_callback_set(m_mosq, cac_subscribe_callback); + // connect to server + + + CW2A userName(CT2W(m_userName), CP_UTF8); + CW2A password(CT2W(m_password), CP_UTF8); + + mosquitto_username_pw_set(m_mosq, (LPCSTR)userName, (LPCSTR)password); + + if (mosquitto_connect(m_mosq, MQTT_SERVER, MQTT_PORT, MQTT_KEEP_ALIVE)) + { + mosquitto_destroy(m_mosq); + m_mosq = NULL; + fprintf(stderr, "Unable to connect.\n"); +#ifndef _DEBUG + return false; +#endif + } + + + /* Subscribe to broker information topics on successful connect. */ + std::thread th = std::thread(MQTTThreadProc, this); + m_mqttThread.swap(th); + + int mid = 0; + // mosquitto_subscribe(m_mosq, &mid, SERVICES_COMMAND_TOPIC, SYNC_QOS_LEVEL_0); + // mosquitto_subscribe(m_mosq, &mid, SERVICES_RESPONSE_TOPIC, SYNC_QOS_LEVEL_0); + // mosquitto_subscribe(m_mosq, &mid, DEVICES_DATA_TOPIC, SYNC_QOS_LEVEL_0); + + return TRUE; + } + + LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if (m_mosq != NULL) + { + int mid = 0; + mosquitto_unsubscribe(m_mosq, &mid, SERVICES_COMMAND_TOPIC); + mosquitto_unsubscribe(m_mosq, &mid, SERVICES_RESPONSE_TOPIC); + mosquitto_unsubscribe(m_mosq, &mid, DEVICES_DATA_TOPIC); + + mosquitto_disconnect(m_mosq); + + mosquitto_loop_stop(m_mosq, false); + if (m_mqttThread.joinable()) + { + m_mqttThread.join(); + } + mosquitto_destroy(m_mosq); + m_mosq = NULL; + } + + mosquitto_lib_cleanup(); + + return TRUE; + } + + LRESULT OnClearCmd(WORD /*wNotifyCode*/, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/) + { + CEdit edt = GetDlgItem(IDC_TO_RECV); + edt.SetWindowText(TEXT("")); + + return 1; + } + + LRESULT OnSendCmd(WORD /*wNotifyCode*/, WORD wID, HWND hWndCtl, BOOL& /*bHandled*/) + { + CString text; + CEdit edt = GetDlgItem(IDC_TO_SEND); + edt.GetWindowText(text); + if (text.GetLength() == 0) + { + return TRUE; + } + + CString topic; + CComboBox cmb = GetDlgItem(IDC_TOPICES); + cmb.GetWindowText(topic); + if (topic.GetLength() == 0) + { + return TRUE; + } + + CW2A utf8(CT2W(text), CP_UTF8); + + CW2A utf8Topic(CT2W(topic), CP_UTF8); + + int mid = 0; + int res = mosquitto_publish(m_mosq, &mid, utf8Topic, strlen((LPCSTR)utf8), (void *)((LPCSTR)utf8), SYNC_QOS_LEVEL_0, false); + if (res == MOSQ_ERR_SUCCESS) + { + // Update time + int aa = 0; + } + else + { + if (MOSQ_ERR_ERRNO == res) + { + int errorno = errno; + char* errmsg = strerror(errorno); + + int aa = 0; + } + int bbb = 0; + } + + return TRUE; + } + + LRESULT OnNewMsgArrived(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + LPTSTR pszMsg = (LPTSTR)lParam; + LPTSTR pszTopic = (LPTSTR)wParam; + + CString text; + CEdit edt = GetDlgItem(IDC_TO_RECV); + edt.GetWindowText(text); + + edt.AppendText(TEXT("\r\n")); + + if (pszTopic != NULL) + { + edt.AppendText(TEXT("\r\n")); + + edt.AppendText(FormatLocalTime()); + edt.AppendText(TEXT(" ")); + edt.AppendText(pszTopic); + + delete[] pszTopic; + } + + if (pszMsg != NULL) + { + edt.AppendText(TEXT("\r\n")); + edt.AppendText(pszMsg); + + delete[] pszMsg; + } + + return TRUE; + } + + int MQTTProc() + { + mosquitto_loop_forever(m_mosq, -1, 1); + return 0; + } + + static int MQTTThreadProc(CView *pThis); + static void cac_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message); + static void cac_connect_callback(struct mosquitto *mosq, void *userdata, int result); + static void cac_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos); + static void cac_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str); + + LPTSTR ConvertStr(const char* utf8) + { + CW2T str(CA2W(utf8, CP_UTF8)); + + size_t len = _tcslen((LPCTSTR)str); + TCHAR *pszT = new TCHAR[len + 1]; + pszT[len] = 0; + _tcscpy(pszT, (LPCTSTR)str); + + return pszT; + } + + void MessageCallback(struct mosquitto *mosq, const struct mosquitto_message *message) + { + if (message->payloadlen) { + + LPTSTR pszTopic = ConvertStr((char *)(message->topic)); + LPTSTR pszMsg = NULL; + bool isJson = false; + char* sz = (char *)message->payload; + if (sz[0] == '{') + { + Json::Value jsonObj; + Json::CharReaderBuilder builder; + std::unique_ptr reader(builder.newCharReader()); + + isJson = reader->parse(sz, sz + message->payloadlen, &jsonObj, NULL); + if (isJson) + { + Json::StreamWriterBuilder writeBuilder; + writeBuilder["indentation"] = " "; // assume default for comments is None + writeBuilder["emitUTF8"] = true; + std::string content = Json::writeString(writeBuilder, jsonObj); + + size_t pos = 0; + std::string replace = "\r\n"; + while ((pos = content.find('\n', pos)) != std::string::npos) + { + content.replace(pos, 1, replace); + pos += replace.length(); + } + + pszMsg = ConvertStr(content.c_str()); + } + } + if (pszMsg == NULL) + { + pszMsg = ConvertStr((char *)(message->payload)); + } + + ::PostMessage(m_hWnd, WM_NEW_MSG, (WPARAM)pszTopic, (LPARAM)pszMsg); + + } + else { + // LPTSTR pszMsg = ConvertStr((char *)(message->payload)); + LPTSTR pszTopic = ConvertStr((char *)(message->topic)); + + ::PostMessage(m_hWnd, WM_NEW_MSG, (WPARAM)pszTopic, 0); + } + // fflush(stdout); + } + + void ConnectCallback(struct mosquitto *mosq, int result) + { + int i; + if (!result) + { + /* Subscribe to broker information topics on successful connect. */ + // std::thread th = std::thread(MQTTThreadProc, this); + // m_mqttThread.swap(th); + + int mid = 0; + int res = 0; + char* subs[] = { SERVICES_COMMAND_TOPIC, SERVICES_RESPONSE_TOPIC, DEVICES_DATA_TOPIC}; + + res = mosquitto_subscribe_multiple(m_mosq, &mid, sizeof(subs) / sizeof(char *), subs, SYNC_QOS_LEVEL_0, 0, NULL); + if (res != MOSQ_ERR_SUCCESS) + { + int aa = 0; + } + + // res = mosquitto_subscribe(m_mosq, &mid, SERVICES_COMMAND_TOPIC, SYNC_QOS_LEVEL_0); + // res = mosquitto_subscribe(m_mosq, &mid, SERVICES_RESPONSE_TOPIC, SYNC_QOS_LEVEL_0); + // res = mosquitto_subscribe(m_mosq, &mid, DEVICES_DATA_TOPIC, SYNC_QOS_LEVEL_0); + if (res != MOSQ_ERR_SUCCESS) + { + int aa = 0; + } + } + else + { + fprintf(stderr, "Connect failed\n"); + } + } + + void SubscribeCallback(struct mosquitto *mosq, int mid, int qos_count, const int *granted_qos) + { + int i; + printf("Subscribed (mid: %d): %d", mid, granted_qos[0]); + for (i = 1; i < qos_count; i++) + { + printf(", %d", granted_qos[i]); + } + printf("\n"); + } + + void LogCallback(struct mosquitto *mosq, int level, const char *str) + { + /* Pring all log messages regardless of level. */ + printf("%s\n", str); + } + + + CString FormatLocalTime(time_t t = 0) + { + if (t == 0) + { + time(&t); + } + + struct std::tm* tp = localtime(&t); + CString str; + str.Format(TEXT("%02d-%02d %02d:%02d:%02d"), tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec); + return str; + } + + void LoadUserAndPassword() + { + TCHAR buf[MAX_PATH] = { 0 }; + CRegKey key; + if (key.Open(HKEY_CURRENT_USER, TEXT("Software\\XYPower\\MQTTClient"), KEY_READ) == ERROR_SUCCESS) + { + ULONG bufLen = MAX_PATH; + if (key.QueryStringValue(TEXT("UserName"), buf, &bufLen) == ERROR_SUCCESS) + { + m_userName = buf; + } + + bufLen = MAX_PATH; + if (key.QueryStringValue(TEXT("Password"), buf, &bufLen) == ERROR_SUCCESS) + { + m_password = buf; + } + + + key.Close(); + } + } + + +}; + +int CView::MQTTThreadProc(CView *pThis) +{ + return pThis->MQTTProc(); +} + +void CView::cac_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message) +{ + ((CView*)userdata)->MessageCallback(mosq, message); +} + +void CView::cac_connect_callback(struct mosquitto *mosq, void *userdata, int result) +{ + ((CView*)userdata)->ConnectCallback(mosq, result); +} + +void CView::cac_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos) +{ + ((CView*)userdata)->SubscribeCallback(mosq, mid, qos_count, granted_qos); +} + +void CView::cac_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str) +{ + ((CView*)userdata)->LogCallback(mosq, level, str); +} diff --git a/res/MQTTClient.ico b/res/MQTTClient.ico new file mode 100644 index 0000000000000000000000000000000000000000..7ce0295ee953658e7ecb40daba245179328ecda0 GIT binary patch literal 11502 zcmeHNJ8u&~5Z;g`1tMu8QKYaC1$3#XQ@WsoA3#Boh5{*~c7c#08bs~N6$J&zKzoIi zg4zYIKqN;BL6+qg#0dtDZ!`8V?5#&f&N+nH)jf7+XJ@|qX6}5qYh&ijyjfi}DCf-V&K`x z4bPwkJfkv%>uMRU2_%|vcL#_4T9h7-LmCFADQutOf}q3=8#QuGAi>PAZiUVI4(n4z ziB}dp92a;bU}TN!1T2|Cr-Y|pMX*K@p*mbQD@Dq1faJhY9GRt4!ozVv#dOR|DC^1+9 zJbX`)kRJu4>2>WDrpH4UE*;5dBPR?CJ2k`+o2O84GvcA)92a@voIJk?8$c3y(BLt3 z{2)p!bIS3H;~`=)K6Fb1!3k(=AN5H{j9v4EzLs zbO!X^kUz7>4`Mp2<>E?9-*DkqpI*?nDUzduL2tmLQxy0K{3!RMPENSLW|p7Dn6lzu zKQD}udzxpOmNa&4r)2F;`)t=K3)t7N^ExHgG~J@VIi>G)?T*{&E$EtKd+wP>(X=>C z1oKh{ud<+b81GP1&Z_g&ziW5gX8UqBoGtJqc+x(1k%h56_ssS&8QsT(b+=4QS(xS? z);AblM*FnXL6%_?zHr19@w|CP`$PyX88(Ml8U)p~$g%10|3~~VR2f;mC~)ZbA^^-S zDw7K7Sn`jTnaL)vG0+MD-K%uO%0a(|^)q{c>FrC+lht+nC$lL>1^beXWIgbcB8DEEF30FQS<5mz<~zm5s%LV__ESy8CF~hy|bKPQ_YKghbR?zmq{f# z!m%Ztfy8xjK7J>v7>PLC=m49CKvjO`Jei*DY=XZQcdDE32sY>W? z+q$0q;Lk94<-h>ySLJ5>d5o+dcn-+$Hecs|E2S{YH0QWDz#u)d ztn)jgN}O-_MK1iy5>*Yio6vvhG7~^Nfj*LO!yh;xnesG7%%Rx#eOCa-e)FQs z@O6IsIe?6!tbR+Du>lCTTWRWUpMYQSkE93cul$BpQ4!}i$ckr`$c%96^akJwJv_3Z VNN2{fSf+a%e{<`JEW&}neFKTHu(|*M literal 0 HcmV?d00001 diff --git a/resource.h b/resource.h new file mode 100644 index 0000000..0b35722 --- /dev/null +++ b/resource.h @@ -0,0 +1,28 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by MQTTClient.rc +// +#define IDD_ABOUTBOX 100 +#define IDR_MAINFRAME 128 +#define IDD_MQTTCLIENT_FORM 129 +#define IDD_OPTIONS_DLG 202 +#define IDC_TO_SEND 1000 +#define IDC_TO_RECV 1001 +#define IDC_SEND 1002 +#define IDC_CLEAR 1003 +#define IDC_TOPICES 1004 +#define IDC_EDIT1 1005 +#define IDC_USERNAME 1005 +#define IDC_PASSWORD 1006 +#define ID_FILE_OPTIONS 32775 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 204 +#define _APS_NEXT_COMMAND_VALUE 32776 +#define _APS_NEXT_CONTROL_VALUE 1007 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/stdafx.cpp b/stdafx.cpp new file mode 100644 index 0000000..2dffd8e --- /dev/null +++ b/stdafx.cpp @@ -0,0 +1,25 @@ +// stdafx.cpp : source file that includes just the standard includes +// MQTTClient.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + +#ifdef _WIN32 + +// #pragma comment(lib, "mariadbclient.lib") +#pragma comment(lib, "mosquitto.lib") +#pragma comment(lib, "jsoncpp.lib") +// #pragma comment(lib, "mariadbclient.lib" ) +#pragma comment(lib, "Secur32.lib") +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "Crypt32.lib") +#pragma comment(lib, "Shlwapi.lib") +#ifdef _DEBUG +#pragma comment(lib, "zlibd.lib") +#else +#pragma comment(lib, "zlib.lib") +#endif + + +#endif \ No newline at end of file diff --git a/stdafx.h b/stdafx.h new file mode 100644 index 0000000..0e44c3d --- /dev/null +++ b/stdafx.h @@ -0,0 +1,40 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +// Change these values to use different versions +#define WINVER 0x0601 +#define _WIN32_WINNT 0x0601 +#define _WIN32_IE 0x0700 +#define _RICHEDIT_VER 0x0500 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +extern CAppModule _Module; + +#include + +#if defined _M_IX86 + #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_IA64 + #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 + #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else + #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif