Skip to content

Commit 0f2e8cd

Browse files
committed
first commit
0 parents  commit 0f2e8cd

21 files changed

+477
-0
lines changed

.gitignore

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
*.sdf
2+
*.ilk
3+
*.pdb
4+
*.iobj
5+
*.obj
6+
*.pch
7+
*.ipdb
8+
*.aps
9+
*.vcxproj*
10+
*.opendb
11+
12+
.vs
13+
ipch
14+
x64/Debug
15+
ledControl/x64/**

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
The Acer ac100 is a cool little server that fits on any desk. It has 8 LED indicators, 4 harddrive LEDs and 4 status LEDs. However Acer's software does not seem to be making use of them. It would be nice to put then to full use. So I wrote this little program.
2+
3+
HDD LEDs
4+
This program will change the color of each HDD's LED based on activity. Green indicates idle, amber inidcates light avitivity and red inidcates heavy acitivty. Refresh time(33ms) and data R/W threshold can be changed in code. You should change the HDD drive letter in HDDStatus.h.
5+
6+
CPU LED
7+
The (i) iniformation LED will flash and change color based on CPU load and temperature. When the CPU is idle, it will stay solid. When CPU load is > 5%, it will flash and the flash frequency will increase as CPU load increases. The color of this LED will change from green to amber(55 C) to red(75 C) as CPU temperature increases.
8+
9+
10+
To use this, you must install CoreTemp for getting CPU info. http://www.alcpu.com/CoreTemp/
11+
You can have this program start automatically during bootup by adding LedStartupInit.bat to Task scheduler with trigger on "At log on of any user". Remeber to open it up and edit the paths to fit your system.

ledControl.sln

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 14
4+
VisualStudioVersion = 14.0.23107.0
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ledControl", "ledControl\ledControl.vcxproj", "{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|x64 = Debug|x64
11+
Debug|x86 = Debug|x86
12+
Release|x64 = Release|x64
13+
Release|x86 = Release|x86
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}.Debug|x64.ActiveCfg = Debug|x64
17+
{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}.Debug|x64.Build.0 = Debug|x64
18+
{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}.Debug|x86.ActiveCfg = Debug|Win32
19+
{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}.Debug|x86.Build.0 = Debug|Win32
20+
{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}.Release|x64.ActiveCfg = Release|x64
21+
{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}.Release|x64.Build.0 = Release|x64
22+
{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}.Release|x86.ActiveCfg = Release|Win32
23+
{10CF73D7-3AF3-4805-BF24-7607E12F9BCA}.Release|x86.Build.0 = Release|Win32
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
EndGlobal

ledControl/CPUStatus.cpp

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include "stdafx.h"
2+
#include <math.h>
3+
#include "CPUStatus.h"
4+
#include "ledControl.h"
5+
6+
typedef bool (WINAPI *pfnGetCoreTempInfo)(CORE_TEMP_SHARED_DATA *pData);
7+
pfnGetCoreTempInfo GetCoreTempInfo;
8+
9+
//Stock example from CoreTemp SDK. For debugging
10+
void PrintCPUCoreInfo(CORE_TEMP_SHARED_DATA *CoreTempData) {
11+
//Print caption.
12+
printf("Core Temp shared memory reader:\n\n");
13+
ULONG index = 0;
14+
char tempType = CoreTempData->ucFahrenheit ? 'F' : 'C';
15+
//Now print the output.
16+
printf("CPU Name: %s\n", CoreTempData->sCPUName);
17+
printf("CPU Speed: %.2fMHz (%.2f x %.2f)\n", CoreTempData->fCPUSpeed, CoreTempData->fFSBSpeed, CoreTempData->fMultipier);
18+
printf("CPU VID: %.4fv\n", CoreTempData->fVID);
19+
printf("Physical CPUs: %d\n", CoreTempData->uiCPUCnt);
20+
printf("Cores per CPU: %d\n", CoreTempData->uiCoreCnt);
21+
for (UINT i = 0; i < CoreTempData->uiCPUCnt; i++)
22+
{
23+
printf("CPU #%d\n", i);
24+
printf("Tj.Max: %d%c\n", CoreTempData->uiTjMax[i], tempType);
25+
for (UINT g = 0; g < CoreTempData->uiCoreCnt; g++)
26+
{
27+
index = g + (i * CoreTempData->uiCoreCnt);
28+
if (CoreTempData->ucDeltaToTjMax)
29+
{
30+
printf("Core #%d: %.2f%c to TjMax, %d%% Load\n",
31+
index, CoreTempData->fTemp[index], tempType, CoreTempData->uiLoad[index]);
32+
}
33+
else
34+
{
35+
printf("Core #%d: %.2f%c, %d%% Load\n",
36+
index, CoreTempData->fTemp[index], tempType, CoreTempData->uiLoad[index]);
37+
}
38+
}
39+
}
40+
}
41+
42+
void UpdateStatusLED() {
43+
CORE_TEMP_SHARED_DATA CoreTempData;
44+
LEDColorState color;
45+
float CPUtemp;
46+
UINT CPUload;
47+
UINT sleepTime;
48+
UINT flashCount;
49+
while (1)
50+
{
51+
//First refresh CPU info
52+
if (!GetCoreTempInfo(&CoreTempData)) {
53+
ControlLed(SL_LED_STATUS, ST_LED, LED_OFF);
54+
Sleep(RETRY_GETCPUINFO_INTERVAL);
55+
continue;
56+
}
57+
color = LED_GREEN;
58+
//My I3-2120 has 2 cores
59+
CPUtemp = ((CoreTempData.fTemp[0]) + (CoreTempData.fTemp[1])) / 2;
60+
CPUload = ((CoreTempData.uiLoad[0]) + (CoreTempData.uiLoad[1])) / 2;
61+
//Set status LED color based on CPU temp
62+
if (CPUtemp > CPU_TEMP_RED)
63+
color = LED_RED;
64+
else if (CPUtemp > CPU_TEMP_ORANGE)
65+
color = LED_ORANGE;
66+
ControlLed(SL_LED_STATUS, ST_LED, color);
67+
68+
//Flash status LED based on CPU load, the higher the load, the higher flashing frequency
69+
//No flash if load < 5
70+
if (CPUload < 5) {
71+
Sleep(UPDATE_INTERVAL_CPU);
72+
continue;
73+
}
74+
//flash the current color (%load ^ 1.1 / 10) times per second
75+
flashCount = (CPUload > 8) ? (pow(CPUload, 1.1) / 10) : 1;
76+
sleepTime = UPDATE_INTERVAL_CPU / (flashCount * 2);
77+
for (int i = 0; i < flashCount; i++) {
78+
ControlLed(SL_LED_STATUS, ST_LED, LED_OFF);
79+
Sleep(sleepTime);
80+
ControlLed(SL_LED_STATUS, ST_LED, color);
81+
Sleep(sleepTime);
82+
}
83+
}
84+
}
85+
86+
void GetCPUInfoInit()
87+
{
88+
HMODULE hCT;
89+
CORE_TEMP_SHARED_DATA CoreTempData;
90+
memset(&CoreTempData, 0, sizeof(CORE_TEMP_SHARED_DATA));
91+
92+
hCT = LoadLibrary(L"CoreTemp.dll");
93+
if (!hCT)
94+
MessageBox(NULL, L"Could not locate CoreTemp.dll", L"Error", MB_OK | MB_ICONEXCLAMATION);
95+
GetCoreTempInfo = (pfnGetCoreTempInfo)GetProcAddress(hCT, "fnGetCoreTempInfoAlt");
96+
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)UpdateStatusLED, NULL, NULL, NULL);
97+
}

ledControl/CPUStatus.h

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
#include "GetCoreTempInfo.h"
3+
4+
#define RETRY_GETCPUINFO_INTERVAL 50
5+
#define UPDATE_INTERVAL_CPU 1000
6+
#define CPU_TEMP_ORANGE 55
7+
#define CPU_TEMP_RED 75
8+
9+
void GetCPUInfoInit();

ledControl/GetCoreTempInfo.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#pragma once
2+
3+
#ifdef GETCORETEMPINFO_EXPORTS
4+
#define GETCORETEMPINFO_API __declspec(dllexport)
5+
#else
6+
#define GETCORETEMPINFO_API __declspec(dllimport)
7+
#endif
8+
9+
typedef struct core_temp_shared_data
10+
{
11+
unsigned int uiLoad[256];
12+
unsigned int uiTjMax[128];
13+
unsigned int uiCoreCnt;
14+
unsigned int uiCPUCnt;
15+
float fTemp[256];
16+
float fVID;
17+
float fCPUSpeed;
18+
float fFSBSpeed;
19+
float fMultipier;
20+
char sCPUName[100];
21+
unsigned char ucFahrenheit;
22+
unsigned char ucDeltaToTjMax;
23+
}CORE_TEMP_SHARED_DATA,*PCORE_TEMP_SHARED_DATA,**PPCORE_TEMP_SHARED_DATA;
24+
25+
bool GETCORETEMPINFO_API fnGetCoreTempInfo(CORE_TEMP_SHARED_DATA *&pData);
26+
bool WINAPI fnGetCoreTempInfoAlt(CORE_TEMP_SHARED_DATA *pData);
27+
28+
#define UNKNOWN_EXCEPTION 0x20000000
29+
30+
class GETCORETEMPINFO_API CoreTempProxy
31+
{
32+
public:
33+
CoreTempProxy(void);
34+
virtual ~CoreTempProxy(void);
35+
36+
UINT GetCoreLoad(int Index) const;
37+
UINT GetTjMax(int Index) const;
38+
UINT GetCoreCount() const;
39+
UINT GetCPUCount() const;
40+
float GetTemp(int Index) const;
41+
float GetVID() const;
42+
float GetCPUSpeed() const;
43+
float GetFSBSpeed() const;
44+
float GetMultiplier() const;
45+
LPCSTR GetCPUName() const;
46+
bool IsFahrenheit() const;
47+
bool IsDistanceToTjMax() const;
48+
const CORE_TEMP_SHARED_DATA &GetDataStruct() const;
49+
50+
bool GetData();
51+
DWORD GetDllError() const { return GetLastError(); }
52+
LPCWSTR GetErrorMessage();
53+
private:
54+
55+
CORE_TEMP_SHARED_DATA m_pCoreTempData;
56+
WCHAR m_ErrorMessage[100];
57+
};

ledControl/HDDStatus.cpp

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "stdafx.h"
2+
#include "HDDStatus.h"
3+
#include <pdh.h>
4+
#include "ledControl.h"
5+
6+
#pragma comment(lib, "pdh.lib")
7+
8+
void UpdateHDDLED(tag_sensor_location sl, double bytesPerSec) {
9+
LEDColorState color = LED_GREEN;
10+
if (bytesPerSec > BYTES_RATE_RED)
11+
color = LED_RED;
12+
else if (bytesPerSec > BYTES_RATE_ORANGE)
13+
color = LED_ORANGE;
14+
ControlLed(sl, ST_LED_INT_HDD, color);
15+
}
16+
17+
int GetHDDInfoInit(){
18+
HQUERY hQuery = NULL;
19+
PDH_STATUS pdhStatus;
20+
HCOUNTER hCounterDisk0, hCounterDisk1, hCounterDisk2, hCounterDisk3;
21+
// Open a query object.
22+
pdhStatus = PdhOpenQuery(NULL, 0, &hQuery);
23+
if (pdhStatus != ERROR_SUCCESS)
24+
return MessageBox(NULL, L"PdhOpenQuery failed.", L"Error", MB_OK | MB_ICONEXCLAMATION);
25+
// Get HDD activity data. My machine's second drive bay is empty.
26+
PDH_STATUS pdhStatus0 = PdhAddCounter(hQuery, COUNTER_PATH_DISK0, 0, &hCounterDisk0);
27+
PDH_STATUS pdhStatus1 = PdhAddCounter(hQuery, COUNTER_PATH_DISK1, 0, &hCounterDisk1);
28+
PDH_STATUS pdhStatus2 = PdhAddCounter(hQuery, COUNTER_PATH_DISK2, 0, &hCounterDisk2);
29+
PDH_STATUS pdhStatus3 = PdhAddCounter(hQuery, COUNTER_PATH_DISK3, 0, &hCounterDisk3);
30+
if (pdhStatus0 != ERROR_SUCCESS || pdhStatus1 != ERROR_SUCCESS || pdhStatus2 != ERROR_SUCCESS || pdhStatus3 != ERROR_SUCCESS)
31+
return MessageBox(NULL, L"PdhAddCounter failed.", L"Error", MB_OK|MB_ICONEXCLAMATION);
32+
pdhStatus = PdhCollectQueryData(hQuery);
33+
// Infinite loop for HDD activity data query
34+
for (;;){
35+
ULONG CounterType;
36+
PDH_FMT_COUNTERVALUE DisplayValue;
37+
38+
pdhStatus = PdhCollectQueryData(hQuery);
39+
pdhStatus = PdhGetFormattedCounterValue(hCounterDisk3, PDH_FMT_DOUBLE, &CounterType, &DisplayValue);
40+
if (pdhStatus == ERROR_SUCCESS)
41+
UpdateHDDLED(SL_LED_HDD_3, DisplayValue.doubleValue);
42+
pdhStatus = PdhGetFormattedCounterValue(hCounterDisk2, PDH_FMT_DOUBLE, &CounterType, &DisplayValue);
43+
if (pdhStatus == ERROR_SUCCESS)
44+
UpdateHDDLED(SL_LED_HDD_2, DisplayValue.doubleValue);
45+
pdhStatus = PdhGetFormattedCounterValue(hCounterDisk1, PDH_FMT_DOUBLE, &CounterType, &DisplayValue);
46+
if (pdhStatus == ERROR_SUCCESS)
47+
UpdateHDDLED(SL_LED_HDD_1, DisplayValue.doubleValue);
48+
pdhStatus = PdhGetFormattedCounterValue(hCounterDisk0, PDH_FMT_DOUBLE, &CounterType, &DisplayValue);
49+
if (pdhStatus == ERROR_SUCCESS)
50+
UpdateHDDLED(SL_LED_HDD_0, DisplayValue.doubleValue);
51+
Sleep(UPDATE_INTERVAL_HDD);
52+
}
53+
}
54+

ledControl/HDDStatus.h

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
CONST PWSTR COUNTER_PATH_DISK0 = L"\\PhysicalDisk(0 E:)\\Disk Bytes/sec";
4+
CONST PWSTR COUNTER_PATH_DISK1 = L"\\PhysicalDisk(1 D:)\\Disk Bytes/sec";
5+
CONST PWSTR COUNTER_PATH_DISK2 = L"\\PhysicalDisk(2 W:)\\Disk Bytes/sec";
6+
CONST PWSTR COUNTER_PATH_DISK3 = L"\\PhysicalDisk(3 C:)\\Disk Bytes/sec";
7+
8+
#define UPDATE_INTERVAL_HDD 33
9+
#define BYTES_RATE_RED 51200000
10+
#define BYTES_RATE_ORANGE 1280000
11+
12+
int GetHDDInfoInit();
Binary file not shown.

ledControl/LedStartupInit.bat

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
taskkill /im "Core Temp.exe" /f /t
2+
taskkill /im "ledControl.exe" /f /t
3+
start "" "C:\Program Files\Core Temp\Core Temp.exe"
4+
start "" "C:\Users\acer\Documents\Visual Studio 2015\Projects\ledControl\x64\Release\ledControl.exe"

ledControl/ReadMe.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
The Acer ac100 is a cool little server that fits on any desk. It has 8 LED indicators, 4 harddrive LEDs and 4 status LEDs. However Acer's software does not seem to be making use of them. It would be nice to put then to full use. So I wrote this little program.
2+
3+
HDD LEDs
4+
This program will change the color of each HDD's LED based on activity. Green indicates idle, amber inidcates light avitivity and red inidcates heavy acitivty. Refresh time(33ms) and data R/W threshold can be changed in code. You should change the HDD drive letter in HDDStatus.h.
5+
6+
CPU LED
7+
The (i) iniformation LED will flash and change color based on CPU load and temperature. When the CPU is idle, it will stay solid. When CPU load is > 5%, it will flash and the flash frequency will increase as CPU load increases. The color of this LED will change from green to amber(55 C) to red(75 C) as CPU temperature increases.
8+
9+
10+
To use this, you must install CoreTemp for getting CPU info. http://www.alcpu.com/CoreTemp/
11+
You can have this program start automatically during bootup by adding LedStartupInit.bat to Task scheduler with trigger on "At log on of any user". Remeber to open it up and edit the paths to fit your system.

ledControl/ledControl.cpp

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// ledControl.cpp : Defines the entry point for the console application.
2+
//
3+
4+
#include "stdafx.h"
5+
#include "ledControl.h"
6+
#include "CPUStatus.h"
7+
#include "HDDStatus.h"
8+
9+
typedef HANDLE(*pfn_wha_open)();
10+
typedef QWORD(*pfn_wha_close)(HANDLE handle);
11+
typedef QWORD(*pfn_wha_SensorObjectCreate)(HANDLE handle, tag_sensor_type ss_type, tag_sensor_location ss_location, tag_sensor_info &ss_info);
12+
typedef QWORD(*pfn_wha_SensorObjectDestroy)(HANDLE handle, tag_sensor_info &ss_info);
13+
typedef QWORD(*pfn_wha_GetSensorInformation)(HANDLE handle, tag_sensor_info &ss_info);
14+
typedef QWORD(*pfn_wha_SetSensorStatus)(HANDLE handle, tag_sensor_info &ss_info);
15+
16+
pfn_wha_open wha_open = 0;
17+
pfn_wha_SensorObjectCreate wha_SensorObjectCreate = 0;
18+
pfn_wha_SensorObjectDestroy wha_SensorObjectDestroy = 0;
19+
pfn_wha_GetSensorInformation wha_GetSensorInformation = 0;
20+
pfn_wha_SetSensorStatus wha_SetSensorStatus = 0;
21+
22+
void GetDLLAPI(HMODULE WNASDLL_BASE) {
23+
wha_open = (pfn_wha_open)GetProcAddress(WNASDLL_BASE, "wha_open");
24+
wha_SensorObjectCreate = (pfn_wha_SensorObjectCreate)GetProcAddress(WNASDLL_BASE, "wha_SensorObjectCreate");
25+
wha_SensorObjectDestroy = (pfn_wha_SensorObjectDestroy)GetProcAddress(WNASDLL_BASE, "wha_SensorObjectDestroy");
26+
wha_GetSensorInformation = (pfn_wha_GetSensorInformation)GetProcAddress(WNASDLL_BASE, "wha_GetSensorInformation");
27+
wha_SetSensorStatus = (pfn_wha_SetSensorStatus)GetProcAddress(WNASDLL_BASE, "wha_SetSensorStatus");
28+
}
29+
30+
HANDLE hLed;
31+
void ControlLed(tag_sensor_location sl, tag_sensor_type st, LEDColorState color) {
32+
tag_sensor_info ss_info;
33+
ss_info.ss_location = sl;
34+
ss_info.ss_type = st;
35+
ss_info.ss_status = color;
36+
wha_SetSensorStatus(hLed, ss_info);
37+
}
38+
39+
int main() {
40+
//Close all other instances
41+
DWORD pID = GetProcessId(GetCurrentProcess());
42+
char cmd[256] = { 0 };
43+
sprintf(cmd, "taskkill /im ledControl.exe /FI \"pid NE %d\" /f /t", pID);
44+
system(cmd);
45+
//Hide the console window
46+
FreeConsole();
47+
//Load the LED driver interface DLL to control LED
48+
HMODULE WNASDLL_BASE = LoadLibraryA("WNASDLLATL.dll");
49+
if (!WNASDLL_BASE)
50+
return MessageBox(NULL, L"Could not locate WNASDLLATL.dll", L"Fatal error", MB_OK | MB_ICONEXCLAMATION);
51+
GetDLLAPI(WNASDLL_BASE);
52+
hLed = wha_open();
53+
ControlLed(SL_LED_POWER_STATUS, ST_LED, LED_GREEN);
54+
if (!hLed)
55+
return MessageBox(NULL, L"Could not open wha handle", L"Fatal error", MB_OK | MB_ICONEXCLAMATION);
56+
//Start HDD and CPU monitoring routines
57+
GetCPUInfoInit();
58+
GetHDDInfoInit();
59+
return 0;
60+
}

0 commit comments

Comments
 (0)