This toolbar widget provides a framework to capture win32 WM_POWER events, leverage them to draw a graph of UPS state and optionally shutdown/suspend or hibernate the system.
Update - December 2021: For those interested, this project was used (independently) as the foundation for a .NET Core 3.1 Console/Windows service that can be found on Github at https://github.com/zrasco/hidupsresponder.
Introduction
A client wanted an app to monitor and log the UPS for an embedded Windows controller.
This toolbar widget provides a framework to capture win32 WM_POWER
events, leverage them to draw a graph of UPS state and optionally shutdown/suspend or hibernate the system.
The app is very simple and should be a good framework for other, related projects.
Background
As provided to our client, the application does more than as described here, however the additional functions were client specific and not pertinent.
When looking for a similar project, I found pieces, but nothing specific. As such, this project derives from projects by maharishi_b and lcady.
Using the Code
The app builds to a toolbar app that runs all the time and monitors Windows power events. At each event, the app logs the event to a CSV log file and if the AC goes offline, the app pops up and shows a graph of the UPS capacity and the time left in mins.
All these features depend on your UPS being plugged in and supporting the standard Windows HID power device profile.
During normal operations, the app may be viewed using the toolbar context menu (right click on the toolbar icon). Using 'show' will bring up the normal operations window:
This shows that the UPS is online with 100% battery capacity. The 'High' at the bottom is the Windows power systems determination of the battery capacity. Full scale for the battery capacity is 100%.
When the AC line is lost, the main screen will popup and display the power status:
This shows that the AC is now offline with 67% battery capacity remaining. The system still regards this capacity as 'High'. Now that the AC is offline, the time remaining becomes relevant and is shown in red. Full scale for the time remaining is hard coded as 60mins.
After restoring power, the time remaining is no longer relevant and the system begins re-charging the battery:
Each event that occurs, is logged to the log.csv file in the directory from which PowerMonitor
was started. The format is as follows:
Each event is logged by time, date and event type. Details of the event follow as per the system power status structure:
[StructLayout(LayoutKind.Sequential)]
public class SystemPowerStatus
{
public ACLineStatus ACLineStatus;
public BatteryFlag BatteryFlag;
public Byte BatteryLifePercent;
public Byte Reserved1;
public Int32 BatteryLifeTime;
public Int32 BatteryFullLifeTime;
Most of the code is self explanatory. The strip chart is probably the most interesting - it is an evolution of lcady's strip chart. I am in the process of making it a general purpose strip chart class, but for now, it is something of a simple hack.
I like the fact that this class draws to a BMP and then blits the BMP into a picture view. It means the chart construction is mostly independent of the viewing process and can be offloaded to other threads. This is particularly pertinent when doing data acquisition via potentially slow devices.
Points of Interest
It is exceptionally hard to map battery capacity to time left. UPS are getting better, but they mostly use battery voltage and this is a very poor indicator, especially when the battery is old, has been cycled a lot or has been recently cycled.
Time left is only an indicator and actions you take should be based on your own analysis of data collected during AC outages and recharge times.
History
- 30th November, 2011: Initial version
- 2nd December, 2021: Article updated