#include "stdafx.h"
#include "Interface_COM.h"
#include <setupapi.h>
#include "Windows.h"
#pragma comment (lib, "setupapi.lib")
#define MAX_LOADSTRING 100
// Глобальные переменные:
HINSTANCE hInst;                                // текущий экземпляр
WCHAR szTitle[MAX_LOADSTRING]=L"xxxxxxx";  // Текст строки заголовка
WCHAR szWindowClass[MAX_LOADSTRING];            // имя класса главного окна
// Отправить объявления функций, включенных в этот модуль кода:
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    // TODO: разместите код здесь.
    // Инициализация глобальных строк
   // LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_INTERFACE_COM, szWindowClass, MAX_LOADSTRING);
        HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_INTERFACE_COM));
        // главное окно
        WNDCLASSEXW wcex;
        wcex.cbSize = sizeof(WNDCLASSEX);
        wcex.style = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc = WndProc;
        wcex.cbClsExtra = 0;
        wcex.cbWndExtra = 0;
        wcex.hInstance = hInstance;
        wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INTERFACE_COM));
        wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
        wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_INTERFACE_COM);
        wcex.lpszClassName = szWindowClass;
        wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
        RegisterClassExW(&wcex);
        hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной
        HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
        if (!hWnd) return FALSE;
        // контролы
        HWND hWnd01 = CreateWindowEx(0, L"static", L"Voltage, V", WS_CHILD | WS_VISIBLE | ES_CENTER,
                10, 10, 80, 30, hWnd, (HMENU)10000, hInstance, NULL);
        HWND hWnd1 = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", L"xxx", WS_CHILD | WS_VISIBLE | ES_RIGHT,
                10, 40, 80, 30, hWnd, (HMENU)10001, hInstance, NULL);
        HWND hWnd02 = CreateWindowEx(0, L"static", L"Current, A", WS_CHILD | WS_VISIBLE | ES_CENTER,
                100, 10, 80, 30, hWnd, (HMENU)20000, hInstance, NULL);
        HWND hWnd2 = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", L"xxx", WS_CHILD | WS_VISIBLE | ES_RIGHT,
                100, 40, 80, 30, hWnd, (HMENU)20001, hInstance, NULL);
        HWND hWnd03 = CreateWindowEx(0, L"static", L"Torque, N m", WS_CHILD | WS_VISIBLE | ES_CENTER,
                190, 10, 80, 30, hWnd, (HMENU)30000, hInstance, NULL);
        HWND hWnd3 = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", L"xxx", WS_CHILD | WS_VISIBLE | ES_RIGHT,
                190, 40, 80, 30, hWnd, (HMENU)30001, hInstance, NULL);
        HWND hWnd04 = CreateWindowEx(0, L"static", L"Speed, Hz", WS_CHILD | WS_VISIBLE | ES_CENTER,
                280, 10, 80, 30, hWnd, (HMENU)40000, hInstance, NULL);
        HWND hWnd4 = CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", L"xxx", WS_CHILD | WS_VISIBLE | ES_RIGHT,
                280, 40, 80, 30, hWnd, (HMENU)40001, hInstance, NULL);
        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
        // открыть COM-порт
    DWORD i, iSize;                                           // число принятых байт
    char dev_name[1024]; unsigned char sReceivedChar[1024];   // приёмный буфер
        wchar_t str[1024], port_name[5] = L"COMx";
        HDEVINFO hDevInfo;
        SP_DEVINFO_DATA DeviceInfoData;
        SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
        GUID GUID_DEVCLASS_PORTS = {0x4d36e978, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18};
        HANDLE Com_File;
        DCB dcbSerialParams = { 0 };
        COMMTIMEOUTS CommTimeOuts = { 0xFFFFFFFF,0,0,0,0 };       // чтение и запись без задержек
        MSG msg;
CONNECT: 
        DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
        dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
        hDevInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_PORTS, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
        if (hDevInfo!= INVALID_HANDLE_VALUE)
        {
                i = 0;
                while (SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData))
                {
                        SetupDiGetDeviceRegistryPropertyA(hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, NULL, (UCHAR*)dev_name, sizeof(dev_name), NULL);
                        port_name[3] = dev_name[20]; dev_name[20] = 'x';
                        MessageBox(NULL, port_name, NULL, MB_OK);
                        if (strcmp(dev_name, "USB Serial Port (COMx)")) port_name[3] = 'x'; else  break;
                        i++;
                }
               SetupDiDestroyDeviceInfoList(hDevInfo);  
        }
   
        if (port_name[3] == 'x')
           if (MessageBox(NULL, L"Устройство не обнаружено", L"Подключение", MB_RETRYCANCEL) == IDRETRY) goto CONNECT;
           else return 0;
        
        Com_File = CreateFile(port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (Com_File == INVALID_HANDLE_VALUE) { MessageBox(NULL, L"Невозможно открыть последовательный порт", L"Error", MB_OK); return 0; }
        // настройка COM-порта
        if (!GetCommState(Com_File, &dcbSerialParams))
                MessageBox(NULL, L"getting state error\n", NULL, MB_OK);
        dcbSerialParams.BaudRate = CBR_9600;
        dcbSerialParams.ByteSize = 8;
        dcbSerialParams.StopBits = ONESTOPBIT;
        dcbSerialParams.Parity = NOPARITY;
        if (!SetCommState(Com_File, &dcbSerialParams))
                MessageBox(NULL, L"error setting serial port state\n", NULL, MB_OK);
        SetCommTimeouts(Com_File, &CommTimeOuts);
    
        PurgeComm(Com_File, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); // очистка буфера com-порта                                                                                                                                                               
        SetTimer(hWnd, 1, 20, NULL);                                                        // таймер, опрос каждый 20 мс
    // Цикл основного сообщения:
        while (GetMessage(&msg, nullptr, 0, 0))
        {               
                if (msg.message == WM_TIMER)
                {
                        if (!ReadFile(Com_File, sReceivedChar, 10, &iSize, 0))
                        {
                                SendMessage(hWnd1, WM_SETTEXT, 0, (LPARAM)L"xxx");
                                SendMessage(hWnd2, WM_SETTEXT, 0, (LPARAM)L"xxx");
                                SendMessage(hWnd3, WM_SETTEXT, 0, (LPARAM)L"xxx");
                                SendMessage(hWnd4, WM_SETTEXT, 0, (LPARAM)L"xxx");
                                if (MessageBox(NULL, L"Потеряна связь с устройством", L"Подключение", MB_RETRYCANCEL) == IDRETRY)
                                { CloseHandle(Com_File); port_name[3] = 'x'; goto CONNECT; }
                                else return 0;
                        }
                        else
                        {
                                if (iSize == 4)
                                {
                                        _itow_s(sReceivedChar[0], str, 10);
                                        SendMessage(hWnd1, WM_SETTEXT, 0, (LPARAM)str);
                                        _itow_s(sReceivedChar[1], str, 10);
                                        SendMessage(hWnd2, WM_SETTEXT, 0, (LPARAM)str);
                                        _itow_s(sReceivedChar[2], str, 10);
                                        SendMessage(hWnd3, WM_SETTEXT, 0, (LPARAM)str);
                                        _itow_s(sReceivedChar[3], str, 10);
                                        SendMessage(hWnd4, WM_SETTEXT, 0, (LPARAM)str);
                                }
                        }
                }
                if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
        CloseHandle(Com_File);
    return (int) msg.wParam;
}