I'm working on a speech recognition program in C# and I've compiled a few lines of code that speaks back the current battery level when I say "battery level".
if (e.Result.Text.ToLower() == "battery level")
{
System.Management.ManagementClass wmi = new System.Management.ManagementClass("Win32_Battery");
var allBatteries = wmi.GetInstances();
String estimatedChargeRemaining = String.Empty;
foreach (var battery in allBatteries)
{
estimatedChargeRemaining = Convert.ToString(battery["EstimatedChargeRemaining"]);
}
JARVIS.Speak("The Power Level Is At: " + estimatedChargeRemaining + "% sir");
return;
}
Within that I want to create another if statement to alert me if the battery level has dropped below 25%. How can this be done? I'm guessing it will be something like "if estimatedChargeRemaining < 25 then JARVIS.Speak("Warning, Battery level has dropped below 25%") but I'm not quite sure.
I'm not sure what format battery["EstimatedChargeRemaining"] returns but it seems you can convert it to an int instead of a string.
int batteryLevel = Convert.ToInt32(battery["EstimatedChargeRemaining"]);
if(batteryLevel < 25)
JARVIS.Speak("Warning, Battery level has dropped below 25%");
You can then use that batteryLevel variable later on
JARVIS.Speak("The Power Level Is At: " + batteryLevel.ToString() + "% sir");
Not sure if it's intended but your foreach loop means that you'll only get the battery information of the last value in allBatteries. All the previous values will be overwritten.
Edit for comment (you should add error handling)
if (e.Result.Text.ToLower() == "battery level")
{
System.Management.ManagementClass wmi = new System.Management.ManagementClass("Win32_Battery");
var allBatteries = wmi.GetInstances();
//String estimatedChargeRemaining = String.Empty;
int batteryLevel = 0;
foreach (var battery in allBatteries)
{
batteryLevel = Convert.ToInt32(battery["EstimatedChargeRemaining"]);
}
if(batteryLevel < 25)
JARVIS.Speak("Warning, Battery level has dropped below 25%");
else //Guessing you want else
JARVIS.Speak("The Power Level Is At: " + batteryLevel.ToString() + "% sir");
return;
}
Related
I have been using stopwatch in one of my DevExpress based application. I have created a FlaUI based test case that initiates the keyboard, enters a value and then moves to the next column. Now, there are like 20+ columns in a row in the DevExpress grid I am using. While I try to run that test case 5 times to come to a baseline timing, I am seeing too much different results.
I am pasting an extract of my current code here:
public bool CreateNewGdistVoyageForPerformanceTesting(IEnumerable<GdistBenchVoyageParameters> gdistparameters,
string gridAutomationId)
{
var watch = System.Diagnostics.Stopwatch
.StartNew(); //This line of code is being used to monitor the time taken by each Keyboard operation
long TotalTimeConsumed = 0;
int MaxAllowedTime = 0;
int HasTimeExceeded = 0;
bool TimeHasNotExceeded = true;
watch.Start();
_logger.Info("Creating a new GDIST Voyage");
TabItem ParentControl = VoyageEditorTabControl.SelectedTabItem;
var CurrentSelectedTab = VoyageEditorTabControl.SelectedTabItemIndex;
var ParentGrid = VoyageEditorTabControl.TabItems[CurrentSelectedTab]
.FindFirstDescendant(cf => cf.ByAutomationId(gridAutomationId)).AsGrid();
_controlAction.Highlight(ParentGrid);
var Pattern = ParentGrid.Patterns.Grid;
var RowCount = Pattern.Pattern.RowCount;
var ColumnCount = Pattern.Pattern.ColumnCount;
_logger.Info("======================================================================================");
if (ParentGrid.AutomationId.Equals("ParentGridControl"))
{
_logger.Info($"Performance Testing on GDIST's View Main Grid :{gridAutomationId}");
_logger.Info($"Current Grid Row count is: {RowCount}");
_logger.Info("Creating a new voyage for GDIST Bench");
}
else
{
_logger.Info($"Performance Testing on GDIST's Similar Voyages Panel Grid: {gridAutomationId}");
_logger.Info($"Current Grid Row count is: {RowCount}");
_logger.Info("Editing an existing voyage for GDIST Bench's Similar Voyages Panel");
}
for (int i = 0; i < ColumnCount; i++)
{
var cell = ParentGrid.Patterns.Grid.Pattern.GetItem(ParentGrid.RowCount - 1, i);
if (cell == null)
{
_logger.Warning("No Columns found with matching Automation Ids");
break;
}
if (cell.AutomationId.Equals("Vessel"))
{
MaxAllowedTime = 1500;
gdistparameters.ToList().ForEach(voyageDetailsField =>
{
if (voyageDetailsField.VesselId != null)
{
_logger.Info("Adding Data in Vessel ID ");
cell.Focus();
cell.Click();
_logger.Info($"Entered value is:{voyageDetailsField.VesselId}");
watch.Stop(); // trying this to ensure the watch dummy run to remove JIT noise
if (!watch.IsRunning)
{
watch.Restart(); //starting the watch
}
Keyboard.Type(voyageDetailsField.VesselId.Trim());
watch.Stop();
Keyboard.Press(VirtualKeyShort.TAB);
// _controlAction.WaitFor(new TimeSpan(0, 0, 2));
Wait.UntilInputIsProcessed();
_logger.Info($"Execution Time: {watch.ElapsedMilliseconds} ms");
if (watch.ElapsedMilliseconds > MaxAllowedTime)
{
HasTimeExceeded++;
_logger.Warning($"The data entry time has exceeded beyond the fixed value by {watch.ElapsedMilliseconds - MaxAllowedTime} ms");
}
TotalTimeConsumed = TotalTimeConsumed + watch.ElapsedMilliseconds;
}
});
TotalTimeConsumed = TotalTimeConsumed + watch.ElapsedMilliseconds;
}
if (cell.AutomationId.Equals("LoadDate")) //Load Date
{
MaxAllowedTime = 500;
gdistparameters.ToList().ForEach(voyageDetailsField =>
{
// _logger.Info("Adding data into the Load Date field");
if (voyageDetailsField.LoadDate != null)
{
_logger.Info("Adding Data in Load Date ");
cell.Focus();
cell.Click();
_logger.Info($"Entered value is:{voyageDetailsField.LoadDate}");
watch.Stop(); // trying this to ensure the watch dummy run to remove JIT noise
if (!watch.IsRunning)
{
watch.Restart(); //starting the watch
}
Keyboard.Type(voyageDetailsField.LoadDate.Trim());
watch.Stop();
Keyboard.Press(VirtualKeyShort.TAB);
// _controlAction.WaitFor(new TimeSpan(0, 0, 2));
Wait.UntilInputIsProcessed();
_logger.Info($"Execution Time: {watch.ElapsedMilliseconds} ms");
if (watch.ElapsedMilliseconds > MaxAllowedTime)
{
HasTimeExceeded++;
_logger.Warning(
$"The data entry time has exceeded beyond the fixed value by {watch.ElapsedMilliseconds - MaxAllowedTime} ms");
}
TotalTimeConsumed = TotalTimeConsumed + watch.ElapsedMilliseconds;
}
});
TotalTimeConsumed = TotalTimeConsumed + watch.ElapsedMilliseconds;
}
The timings that I have been observing via the logger functionality is below.
I have run this on multiple PCs, multiple environments but the results are very different. The 5th run is actually taking a lot in every single case.
Note also that all the data that is being entered in populated when the application loads so network latency shouldn't be a problem here.
Moreover, I read that StopWatch comes with a lot of JIT noise, and yes, I had experienced it every time it was running for the first time, so I have already given it a false start in my code.
This test is a performance test and requires benchmarking. We can decide on the benchmarking with such big difference in the numbers.
I'm trying to get CPU and network usage information from a process.In my example, I will use the process chromeHere is how im calling the method using an IEnumerable<String>
foreach (string p in GetProcessStatistics(new string[] { "chrome" }))
{
Console.WriteLine(p);
}
And here is the method.
private static IEnumerable<String> GetProcessStatistics(String[] processesTosearch)
{
Process[] processList = Process.GetProcesses();
foreach (string process in processesTosearch)
{
foreach (Process p in processList)
{
if (p.ProcessName == process)
{
StringBuilder sb = new StringBuilder();
PerformanceCounter CPUperformanceCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
double cpuData = CPUperformanceCounter.NextValue();
PerformanceCounter NETWORKperformanceCounter = new PerformanceCounter("Process", "IO Data Operations/Sec", p.ProcessName);
double networkData = NETWORKperformanceCounter.NextValue();
sb.AppendLine("ID: " + p.Id.ToString());
sb.AppendLine("NAME: " + p.ProcessName);
sb.AppendLine("CPU USAGE: " + cpuData);
sb.AppendLine("RAM USAGE: " + ConvertToReadableSize(p.PrivateMemorySize64));
sb.AppendLine("NETWORK USAGE: " + networkData);
yield return sb.ToString();
}
}
}
}
And here is the output of one of the results
ID: 17624
NAME: chrome
CPU USAGE: 0
RAM USAGE: 23.2MB
NETWORK USAGE: 0
When I look at Performance Monitor, the cpu and network values are not 0, however in the console, they are.I understand from some research that the values will never be perfect, but why are they showing 0 in the console application and not on performance monitor?
You'll need at least two reads for every counter, at least a second apart to get a usable reading.
Rearrange as needed but you would need to do something like this:
private static IEnumerable<String> GetProcessStatistics(String[] processesTosearch)
{
Process[] processList = Process.GetProcesses();
foreach (string process in processesTosearch)
{
foreach (Process p in processList)
{
if (p.ProcessName == process)
{
StringBuilder sb = new StringBuilder();
PerformanceCounter CPUperformanceCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
PerformanceCounter NETWORKperformanceCounter = new PerformanceCounter("Process", "IO Data Operations/Sec", p.ProcessName);
// set a baseline
CPUperformanceCounter.NextValue();
NETWORKperformanceCounter.NextValue();
Thread.Sleep(1000);
double cpuData = CPUperformanceCounter.NextValue();
double networkData = NETWORKperformanceCounter.NextValue();
sb.AppendLine("ID: " + p.Id.ToString());
sb.AppendLine("NAME: " + p.ProcessName);
sb.AppendLine("CPU USAGE: " + cpuData);
sb.AppendLine("RAM USAGE: " + ConvertToReadableSize(p.PrivateMemorySize64));
sb.AppendLine("NETWORK USAGE: " + networkData);
yield return sb.ToString();
}
}
}
}
I like Jeff's solution, but for me I wanted an average. There were a couple problems getting CPU utilization that seemed like there should be an easy package to solve but I didn't see one.
The first is of course that a value of 0 on the first request is useless. Since you already know that the first response is 0, why doesn't the function just take that into account and return the true .NextValue()?
The second problem is that an instantaneous reading may be wildly inacurrate when trying to make decisions on what resources your app may have available to it since it could be spiking, or between spikes.
My solution was to do a for loop that cycles through and gives you an average for the past few seconds. you can adjust the counter to make it shorter or longer (as long as it is more than 2).
public static float ProcessorUtilization;
public static float GetAverageCPU()
{
PerformanceCounter cpuCounter = new PerformanceCounter("Process", "% Processor Time", Process.GetCurrentProcess().ProcessName);
for (int i = 0; i < 11; ++i)
{
ProcessorUtilization += (cpuCounter.NextValue() / Environment.ProcessorCount);
}
// Remember the first value is 0, so we don't want to average that in.
Console.Writeline(ProcessorUtilization / 10);
return ProcessorUtilization / 10;
}
I'm using this code to get cpu temperature, but I'm getting 'not supported' instead of the temperature.
public static string getCpuTemperature()
{
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\WMI",
"SELECT * FROM MSAcpi_ThermalZoneTemperature");
//Win32_TemperatureProbe
foreach (ManagementObject queryObj in searcher.Get())
{
double temp = Convert.ToDouble(queryObj["CurrentTemperature"].ToString());
double temp_critical = Convert.ToDouble(queryObj["CriticalTripPoint"].ToString());
double temp_cel = (temp / 10 - 273.15);
double temp_critical_cel = temp_critical / 10 - 273.15;
return temp_cel.ToString() + " _ " + temp_critical_cel.ToString();
}
}
catch (ManagementException e)
{
//MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
return e.Message.ToString();
}
return "";
}
I've googled the problem and have seen many answers for this including,
- the motherboard doesn't support this feature
- run VS with administration right
etc...
but none of them are true, because programs like OpenHardwareMonitor and SpeedFan show the temperature of cpu and gpu, Hdd temperature, cpu fan speed, and all other informations.
I want to know how do they do that? how is that I get 'not supported' message and these programs don't.
This is not a complete answer but hopefully it helps.
After perusing the code at https://code.google.com/p/open-hardware-monitor/source/browse/trunk/, I can't fully understand this code without downloading it all and investigating further.
The magic seems to happen here,
public override void Update() {
base.Update();
for (int i = 0; i < coreTemperatures.Length; i++) {
uint eax, edx;
// if reading is valid
if (Ring0.RdmsrTx(IA32_THERM_STATUS_MSR, out eax, out edx,
1UL << cpuid[i][0].Thread) && (eax & 0x80000000) != 0)
{
// get the dist from tjMax from bits 22:16
float deltaT = ((eax & 0x007F0000) >> 16);
float tjMax = coreTemperatures[i].Parameters[0].Value;
float tSlope = coreTemperatures[i].Parameters[1].Value;
coreTemperatures[i].Value = tjMax - tSlope * deltaT;
} else {
coreTemperatures[i].Value = null;
}
}
...
This code extracts the temperature data from the result of Ring0.RdmsrTx.
I believe Ring0 is a C implementation of a ring buffer, the code of which is in the repository here. This reads the Model Specific Register data from the CPU driver.
There is more detail in this question.
Easiest way would be probably to find a tool that can output the information you need in machine-readable way and then process that output. SpeedFan logs temperature to logs, you could just read the latest reading from the logs.
I realize this might not be an ideal solution, but it is the only universal. Querying CPU temperature in a Windows system is not an easy task.
I'm probably very late to answer this, but just in case someone stumbles upon this in the future, here's the way I did it:
public string getCPUTemp()
{
UpdateVisitor updateVisitor = new UpdateVisitor();
Computer computer = new Computer();
computer.Open();
computer.CPUEnabled = true;
computer.Accept(updateVisitor);
string res = "";
for (int i = 0; i < computer.Hardware.Length; i++)
{
if (computer.Hardware[i].HardwareType == HardwareType.CPU)
{
for (int j = 0; j < computer.Hardware[i].Sensors.Length; j++)
{
if (computer.Hardware[i].Sensors[j].SensorType == SensorType.Temperature) res = String.Concat(res, (computer.Hardware[i].Sensors[j].Name + ": " + computer.Hardware[i].Sensors[j].Value.ToString() + "ÂșC" + "\r"));
if (computer.Hardware[i].Sensors[j].Value.ToString() == "") { res = ""; return res; }
}
}
}
It worked perfectly with me (even though it didn't work for the GPU part). You just have to download OpenHardwareMonitor (https://openhardwaremonitor.org/), then add the reference to the OpenHardwareMonitorLib.dll which is in the \openhardwaremonitor\Bin\Debug folder, then add "using OpenHardwareMonitor.Hardware;" at the top.
Hope it can still help someone even if not OP!
In my application, I am gathering data regarding the performance of system, where I need to find
% Free Space
% Disk Time
% Disk Read Time
% Disk Write Time
% Idle Time
% Usage
% Usage Peak
using below function;
private void CollectnPopulatePerfCounters()
{
try
{
foreach (var pc in System.Diagnostics.PerformanceCounterCategory.GetCategories())
{
if (pc.CategoryName == "LogicalDisk" || pc.CategoryName == "Paging File" || pc.CategoryName == "ProcessorPerformance")
{
try
{
foreach (var insta in pc.GetInstanceNames())
{
try
{
foreach (PerformanceCounter cntr in pc.GetCounters(insta))
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\amit.txt", true))
{
sw.WriteLine("--------------------------------------------------------------------");
sw.WriteLine("Category Name : " + pc.CategoryName);
sw.WriteLine("Counter Name : " + cntr.CounterName);
sw.WriteLine("Explain Text : " + cntr.CounterHelp);
sw.WriteLine("Instance Name: " + cntr.InstanceName);
sw.WriteLine("Value : " + Convert.ToString(cntr.RawValue)); //TODO:
sw.WriteLine("Counter Type : " + cntr.CounterType);
sw.WriteLine("--------------------------------------------------------------------");
}
}
}
catch (Exception) { }
}
}
catch (Exception) { }
}
}
}
catch (Exception) { }
}
When the code is executed the data is generated. While observing I found that the value against the above mentioned list [i.e. % free space, % disk time etc.] is not in correct form.
On my machine the value for
% Disk Read Time = 44553438000 for C Drive
% Usage Peak = 48386 for \??\C:\pagefile.sys
actually the value should be in the percent form [i.e within the range of 0 to 100 %]
Is there any way to get the exact value for all these except [% free Space for which I have calculated].
Or
Does anyone know how to calculate for rest of all headers.
Use following
sw.WriteLine("Value : " + Convert.ToString(Math.Round(cntr.NextValue(),2)) + "%");
More info at:
Why the cpu performance counter kept reporting 0% cpu usage?
All the best!
Don't forget to vote :-D
My program reads in multiple files that contain time/value pairs sampled at different rates. I'm trying to use the file with the highest sample rate as the time scale for all sampled rates and output one master file with the unique time values from the highest sample rate file.
Each file contains time/values pairs like:
1,58
1.5,90
2,154
2.5,34
Here is my code so far:
public void ReadAndWrite(string[] fileNames)
{
var stopwatch = Stopwatch.StartNew();
List<StreamReader> readers = fileNames.Select(f => new StreamReader(f)).ToList();
try
{
using (StreamWriter writer = new StreamWriter(tbxOutputFile.Text))
{
string line = null;
// For each measurement in max measurements
for (int measNum = 0; measNum < numOfRows; measNum++)
{
// For each file's reader
for (int i = 0; i < readers.Count; i++)
{
// If line contains something, then add it to line
if ((line = readers[i].ReadLine()) != null)
{
// Process line and then write it to file
line = ProcessLine(line);
writer.Write(line);
}
else
{
writer.Write("");
}
// If it's not the last column, add delimiter
if (i < readers.Count - 1)
writer.Write(",");
}
writer.WriteLine();
// Update labels
int val = ((measNum + 1) * 100) / numOfRows;
string newText = Convert.ToString("Progress: " + val + "% " + " " + "Measurement #: " + (measNum + 1)
+ " out of " + numOfRows); // running on worker thread
this.Invoke((MethodInvoker)delegate
{
// runs on UI thread
lblStatus.Text = newText;
progressBar1.Value = val;
});
}
}
}
catch (Exception)
{
throw;
}
finally
{
foreach (var reader in readers)
{
reader.Close();
}
}
MessageBox.Show("File successfully created! " + '\n' + "Elapsed time: " +
(stopwatch.ElapsedMilliseconds/1000) + " seconds", "Processing Complete");
}
I came up with the pseudo code below (currentTime is the time from each file and uniqueTime is from an array that reads in each time from the highest sampled file):
// if time value from individual file is same as uniqueTime
if currentTime == uniqueTime
{
valueToWrite = curr_value // write the current value
}
else // currentTime is not same as uniqueTime
{
valueToWrite = prev_value // write the previous value
}
timeToWrite = uniqueTime // always write the uniqueTime
What is the best way to execute this pseudo code to make a unique time reference for all the various sample rates? Sorry if my question is confusing, I can elaborate more if need be.
To be clear about this, you do not want the values at the specific time they occurred, but you want to display one value for each source at each timepoint that the highest sampled source has?
That should be pretty straightforward. In pseudocode:
foreach (ValuePair val in highSampleRateValues) {
var aggregatedTimePointData;
aggregatedTimePointData.Add(val.Time, val.Value);
foreach (ValuePair val2 in lowSampleRateValues) {
var value = DetermineLatestEntryBackwardFrom(val.Time);
aggregatedTimePointData.Add(value);
}
}
This way, the sample rate of the higher density sampled signal serves as a clock, but you will have inaccuracies since the values from the other sources are only close, but not exactly on the timepoint of their recording. If you want those inaccuracies reduced, choose a higher sample rate and do the same thing. You can get as close to the actual timepoints as you want.