Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Detect power change event / UPS state
QtWS25 Last Chance

Detect power change event / UPS state

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 3 Posters 1.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Cobra91151C Offline
    Cobra91151C Offline
    Cobra91151
    wrote on last edited by
    #1

    Hi! I want to detect when the system is on UPS or just power state changes.

    Something like this:

    enter image description here

    I tried to detect it using GetSystemPowerStatus function:

    Code:

        SYSTEM_POWER_STATUS powerStatus;
        bool powerStatusRes = GetSystemPowerStatus(&powerStatus);
    
        switch (powerStatus.ACLineStatus) {
            case 0:
                std::cout << "Offline" << std::endl;
                break;
            case 1:
                std::cout << "Online" << std::endl;
                break;
            case 255:
                std::cout << "Unknown status" << std::endl;
            default:
                std::cout << "Failed to detect the status" << std::endl;
        }
    
        switch (powerStatus.BatteryFlag) {
            case 1:
                std::cout << "High — the battery capacity is at more than 66 percent" << std::endl;
                break;
            case 2:
                std::cout << "Low — the battery capacity is at less than 33 percent" << std::endl;
                break;
            case 4:
                std::cout << "Critical — the battery capacity is at less than five percent" << std::endl;
                break;
            case 8:
                std::cout << "Charging" << std::endl;
                break;
            case 128:
                std::cout << "No system battery" << std::endl;
                break;
            case 255:
                std::cout << "Unknown status—unable to read the battery flag information" << std::endl;
                break;
            default:
                std::cout << "Failed to detect the battery flag" << std::endl;
        }
    

    But it returns powerStatus.ACLineStatus for UPS or AC as Online and for powerStatus.BatteryFlag - No system battery.

    Also I have tried to detect the UPS using GetPwrCapabilities function:

    Code:

    SYSTEM_POWER_CAPABILITIES SysPowerCapabilities = {0};
    
    if (!GetPwrCapabilities(&SysPowerCapabilities)){
        std::cout << "Failed to get System Power information!" << std::endl;
    }
    
    if (SysPowerCapabilities.UpsPresent) {
        std::cout << "UPS found" << std::endl;
    } else {
        std::cout << "UPS not found" << std::endl;
    }
    

    It returns - UPS not found (driver is not available for this UPS model).

    Now I'm trying to detect power changes by using the Qt nativeEvent function:

    bool Test::nativeEvent(const QByteArray &eventType, void *message, long *result)
    {
        Q_UNUSED(result);
        Q_UNUSED(eventType);
        MSG *msg = static_cast<MSG*>(message);
    
        if (msg->message == WM_POWERBROADCAST && msg->wParam == PBT_APMPOWERSTATUSCHANGE) {
            qDebug() << "Power changed!!!";
        }
    
        return false;
    }
    

    But nothing is printed to the console. Any ideas how to detect it? Thanks.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      If I understand correctly, you don't have the driver for your UPS. How can you expect Qt to catch any related events if your system can't handle the hardware ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      Cobra91151C 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi,

        If I understand correctly, you don't have the driver for your UPS. How can you expect Qt to catch any related events if your system can't handle the hardware ?

        Cobra91151C Offline
        Cobra91151C Offline
        Cobra91151
        wrote on last edited by
        #3

        @SGaist

        Yes, I don't have the driver for this UPS. So how other apps, for example ViewPower communicate with this UPS? Thanks.

        aha_1980A 1 Reply Last reply
        0
        • Cobra91151C Cobra91151

          @SGaist

          Yes, I don't have the driver for this UPS. So how other apps, for example ViewPower communicate with this UPS? Thanks.

          aha_1980A Offline
          aha_1980A Offline
          aha_1980
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @Cobra91151

          The best would be to ask the authors of ViewPower for that ;)

          Qt has to stay free or it will die.

          Cobra91151C 1 Reply Last reply
          1
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            There are likely generic APIs that the device has to answer to. Like you already did. They may be doing some polling.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            Cobra91151C 1 Reply Last reply
            1
            • SGaistS SGaist

              There are likely generic APIs that the device has to answer to. Like you already did. They may be doing some polling.

              Cobra91151C Offline
              Cobra91151C Offline
              Cobra91151
              wrote on last edited by Cobra91151
              #6

              @SGaist

              By enumerating all usb devices I got the Vendor and Product ID for the UPS. How about talking to the serial port, for example using QSerialPort class?

              aha_1980A 1 Reply Last reply
              0
              • aha_1980A aha_1980

                @Cobra91151

                The best would be to ask the authors of ViewPower for that ;)

                Cobra91151C Offline
                Cobra91151C Offline
                Cobra91151
                wrote on last edited by
                #7

                @aha_1980

                Great idea, but this project is deprecated.

                1 Reply Last reply
                0
                • Cobra91151C Cobra91151

                  @SGaist

                  By enumerating all usb devices I got the Vendor and Product ID for the UPS. How about talking to the serial port, for example using QSerialPort class?

                  aha_1980A Offline
                  aha_1980A Offline
                  aha_1980
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @Cobra91151 so now you need to find the documentation for the UPS. It should explain how to control it.

                  Qt has to stay free or it will die.

                  Cobra91151C 1 Reply Last reply
                  0
                  • aha_1980A aha_1980

                    @Cobra91151 so now you need to find the documentation for the UPS. It should explain how to control it.

                    Cobra91151C Offline
                    Cobra91151C Offline
                    Cobra91151
                    wrote on last edited by Cobra91151
                    #9

                    @aha_1980

                    No tech. documentation is available for this UPS. But I got some values from the net:

                     0x00840010 = UPS
                     0x00840012 = Battery
                     0x00840030 = Voltage
                     0x00840040 = ConfigVoltage
                     0x0084001a = Input
                     0x0084005a = AudibleAlarmControl
                     0x00840002 = PresentStatus
                     0x00850044 = Charging
                     0x00850045 = Discharging
                     0x008500d0 = ACPresent
                    

                    But these values could be different for my UPS model.

                    Also I succeeded with connecting to the UPS usb:

                    Code:

                        QString devicePath = "\\\\?\\HID#VID_....";
                        HANDLE fileHandle = CreateFileA(devicePath.toStdString().c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
                    
                        if (fileHandle != INVALID_HANDLE_VALUE) {
                            std::cout << "Success. Device opened for reading..." << std::endl;
                            OVERLAPPED overlapped = {};
                            uint8_t readBuffer[1024];
                            BOOL readDeviceRes = ReadFileEx(fileHandle, (LPVOID)readBuffer, sizeof(readBuffer), &overlapped, readCompleted);
                    
                            if (readDeviceRes) {
                                std::cout << "Success..." << std::endl;
                            } else {
                                std::cout << "Failed..." << std::endl;
                            }
                        } else {
                            std::cout << "Failed to open device for reading!" << std::endl;
                        }
                    
                        CloseHandle(fileHandle);
                    
                    void CALLBACK readCompleted(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
                    {
                        std::cout << "Test... " << dwNumberOfBytesTransfered << std::endl;
                    }
                    

                    When I start the app, it displays:

                    Success. Device opened for reading...
                    Success...

                    But ViewPower app displays that UPS connection has been lost, when I close my app, then the UPS connection has been established. This means that they also read the UPS data from a USB. Now I need to figure out how to get these values, read bytes.

                    1 Reply Last reply
                    0
                    • Cobra91151C Offline
                      Cobra91151C Offline
                      Cobra91151
                      wrote on last edited by
                      #10

                      I have found that I need to use the HID API to get some values for the UPS.

                      Updated code:

                         QString devicePath = "\\\\?\\HID#VID_....";
                         HANDLE fileHandle = CreateFileA(devicePath.toStdString().c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
                      
                         if (fileHandle != INVALID_HANDLE_VALUE) {
                             std::cout << "Success. Device opened for reading..." << std::endl;
                             PHIDP_PREPARSED_DATA preparsedData;
                             HIDP_CAPS capabilities;
                             HIDD_ATTRIBUTES attributes;
                             BOOL hidPreparsedRes = HidD_GetPreparsedData(fileHandle, &preparsedData);
                      
                             if (hidPreparsedRes) {
                                 if (HidD_GetAttributes(fileHandle, &attributes)) {
                                     std::cout << "Product ID: " << attributes.ProductID << std::endl;
                                     std::cout << "Size: " << attributes.Size << std::endl;
                                     std::cout << "Vendor ID: " << attributes.VendorID << std::endl;
                                     std::cout << "Version number: " << attributes.VersionNumber << std::endl;
                      
                                    if (HidP_GetCaps(preparsedData, &capabilities) == HIDP_STATUS_SUCCESS) {
                                        std::cout << "Caps: " << capabilities.NumberOutputValueCaps << std::endl;
                                    } else {
                                        std::cout << "Failed to return HID capabilities!" << std::endl;
                                    }
                                 } else {
                                    std::cout << "Failed to get HID attributes" << std::endl;
                                 }
                      
                                 std::cout << getLastErrorAsString() << std::endl;
                             } else {
                                 std::cout << "Failed to get preparsed data!" << std::endl;
                             }
                      
                             HidD_FreePreparsedData(preparsedData);
                         } else {
                             std::cout << "Failed to open device for reading!" << std::endl;
                         }
                      
                         CloseHandle(fileHandle);
                      

                      So now, it returns:

                      Success. Device opened for reading...
                      Product ID: 20833
                      Size: 12
                      Vendor ID: 1637
                      Version number: 2
                      Caps: 1

                      HIDP_CAPS structure has a lot of different values, the question is how to convert them to UPS values to check for power changes/UPS status? Thanks.

                      1 Reply Last reply
                      1

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved