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 0000000..7ce0295 Binary files /dev/null and b/res/MQTTClient.ico differ diff --git a/res/toolbar.bmp b/res/toolbar.bmp new file mode 100644 index 0000000..60f7a16 Binary files /dev/null and b/res/toolbar.bmp differ 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