mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[systeminfo] Add CPU load channel, update dependencies (#13292)
* Add CPU load channel, update dependencies * use PercentType, correct process CPU load * Add and fix test Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
This commit is contained in:
parent
55e27c8c12
commit
909d390581
@ -65,7 +65,7 @@ In the list below, you can find, how are channel group and channels id`s related
|
||||
**thing** `computer`
|
||||
|
||||
* **group** `memory`
|
||||
* **channel** `available, total, used, availablePercent, usedPercent`
|
||||
* **channel** `available, total, used, availablePercent, usedPercent, usedHeapPercent, availableHeap`
|
||||
* **group** `swap`
|
||||
* **channel** `available, total, used, availablePercent, usedPercent`
|
||||
* **group** `storage` (deviceIndex)
|
||||
@ -77,7 +77,7 @@ In the list below, you can find, how are channel group and channels id`s related
|
||||
* **group** `battery` (deviceIndex)
|
||||
* **channel** `name, remainingCapacity, remainingTime`
|
||||
* **group** `cpu`
|
||||
* **channel** `name, description, load1, load5, load15, uptime`
|
||||
* **channel** `name, description, load, load1, load5, load15, uptime, threads`
|
||||
* **group** `sensors`
|
||||
* **channel** `cpuTemp, cpuVoltage, fanSpeed`
|
||||
* **group** `network` (deviceIndex)
|
||||
@ -104,12 +104,14 @@ The binding introduces the following channels:
|
||||
|
||||
| Channel ID | Channel Description | Supported item type | Default priority | Advanced |
|
||||
|--------------------|------------------------------------------------------------------|---------------------|------------------|----------|
|
||||
| load | CPU Load (total or by process) in % | Number:Dimensionless| High | False |
|
||||
| load1 | Load for the last 1 minute | Number | Medium | True |
|
||||
| load5 | Load for the last 5 minutes | Number | Medium | True |
|
||||
| load15 | Load for the last 15 minutes | Number | Medium | True |
|
||||
| threads | Number of threads currently running | Number | Medium | True |
|
||||
| threads | Number of threads currently running or for the process | Number | Medium | True |
|
||||
| path | The full path of the process | String | Low | False |
|
||||
| uptime | System uptime (time after start) in minutes | Number | Medium | True |
|
||||
| name | Name of the device | String | Low | False |
|
||||
| name | Name of the device or process | String | Low | False |
|
||||
| available | Available size in MB | Number | High | False |
|
||||
| used | Used size in MB | Number | High | False |
|
||||
| total | Total size in MB | Number | Low | False |
|
||||
@ -148,6 +150,9 @@ It has the following options:
|
||||
- **Medium**
|
||||
- **Low**
|
||||
|
||||
The ''load'' channel will update total or by process CPU load at the frequency defined by the priority update interval, by default high priority, every second.
|
||||
The value corresponds to the average CPU load over the interval.
|
||||
|
||||
Channels from group ''process'' have additional configuration parameter - PID (Process identifier).
|
||||
This parameter is used as 'deviceIndex' and defines which process is tracked from the channel.
|
||||
This makes the channels from this groups very flexible - they can change its PID dynamically.
|
||||
@ -190,6 +195,7 @@ Number Network_PacketsReceived "Packets received" <returnpipe> { chann
|
||||
/* CPU information*/
|
||||
String CPU_Name "Name" <none> { channel="systeminfo:computer:work:cpu#name" }
|
||||
String CPU_Description "Description" <none> { channel="systeminfo:computer:work:cpu#description" }
|
||||
Number CPU_Load "CPU Load" <none> { channel="systeminfo:computer:work:cpu#load" }
|
||||
Number CPU_Load1 "Load (1 min)" <none> { channel="systeminfo:computer:work:cpu#load1" }
|
||||
Number CPU_Load5 "Load (5 min)" <none> { channel="systeminfo:computer:work:cpu#load5" }
|
||||
Number CPU_Load15 "Load (15 min)" <none> { channel="systeminfo:computer:work:cpu#load15" }
|
||||
|
@ -22,20 +22,26 @@
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
<version>5.9.0</version>
|
||||
<version>5.12.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>5.9.0</version>
|
||||
<version>5.12.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>5.8.2</version>
|
||||
<version>6.2.2</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
<feature name="openhab-binding-systeminfo" description="System Info Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle dependency="true">mvn:net.java.dev.jna/jna/5.9.0</bundle>
|
||||
<bundle dependency="true">mvn:net.java.dev.jna/jna-platform/5.9.0</bundle>
|
||||
<bundle dependency="true">mvn:com.github.oshi/oshi-core/5.8.2</bundle>
|
||||
<bundle dependency="true">mvn:net.java.dev.jna/jna/5.12.1</bundle>
|
||||
<bundle dependency="true">mvn:net.java.dev.jna/jna-platform/5.12.1</bundle>
|
||||
<bundle dependency="true">mvn:com.github.oshi/oshi-core/6.2.2</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.systeminfo/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
|
@ -28,7 +28,7 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.systeminfo.internal.model.DeviceNotFoundException;
|
||||
import org.openhab.binding.systeminfo.internal.model.SysteminfoInterface;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.Channel;
|
||||
@ -294,8 +294,8 @@ public class SysteminfoHandler extends BaseThingHandler {
|
||||
state = new QuantityType<>(Runtime.getRuntime().freeMemory(), Units.BYTE);
|
||||
break;
|
||||
case CHANNEL_MEMORY_USED_HEAP_PERCENT:
|
||||
state = new DecimalType((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
|
||||
* 100 / Runtime.getRuntime().maxMemory());
|
||||
state = new QuantityType<>((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
|
||||
* 100 / Runtime.getRuntime().maxMemory(), Units.PERCENT);
|
||||
break;
|
||||
case CHANNEL_DISPLAY_INFORMATION:
|
||||
state = systeminfo.getDisplayInformation(deviceIndex);
|
||||
@ -318,6 +318,10 @@ public class SysteminfoHandler extends BaseThingHandler {
|
||||
case CHANNEL_SENSORS_FAN_SPEED:
|
||||
state = systeminfo.getSensorsFanSpeed(deviceIndex);
|
||||
break;
|
||||
case CHANNEL_CPU_LOAD:
|
||||
PercentType cpuLoad = systeminfo.getSystemCpuLoad();
|
||||
state = (cpuLoad != null) ? new QuantityType<>(cpuLoad, Units.PERCENT) : null;
|
||||
break;
|
||||
case CHANNEL_CPU_LOAD_1:
|
||||
state = systeminfo.getCpuLoad1();
|
||||
break;
|
||||
@ -427,7 +431,8 @@ public class SysteminfoHandler extends BaseThingHandler {
|
||||
state = systeminfo.getNetworkPacketsSent(deviceIndex);
|
||||
break;
|
||||
case CHANNEL_PROCESS_LOAD:
|
||||
state = systeminfo.getProcessCpuUsage(deviceIndex);
|
||||
PercentType processLoad = systeminfo.getProcessCpuUsage(deviceIndex);
|
||||
state = (processLoad != null) ? new QuantityType<>(processLoad, Units.PERCENT) : null;
|
||||
break;
|
||||
case CHANNEL_PROCESS_MEMORY:
|
||||
state = systeminfo.getProcessMemoryUsage(deviceIndex);
|
||||
|
@ -14,11 +14,14 @@ package org.openhab.binding.systeminfo.internal.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
@ -74,6 +77,12 @@ public class OSHISysteminfo implements SysteminfoInterface {
|
||||
private @NonNullByDefault({}) List<PowerSource> powerSources;
|
||||
private @NonNullByDefault({}) List<HWDiskStore> drives;
|
||||
|
||||
// Array containing cpu tick info to calculate CPU load, according to oshi doc:
|
||||
// 8 long values representing time spent in User, Nice, System, Idle, IOwait, IRQ, SoftIRQ, and Steal states
|
||||
private long[] ticks = new long[8];
|
||||
// Map containing previous process state to calculate load by process
|
||||
private Map<Integer, OSProcess> processTicks = new HashMap<>();
|
||||
|
||||
public static final int PRECISION_AFTER_DECIMAL_SIGN = 1;
|
||||
|
||||
/**
|
||||
@ -338,7 +347,7 @@ public class OSHISysteminfo implements SysteminfoInterface {
|
||||
@Override
|
||||
public @Nullable DecimalType getSensorsFanSpeed(int index) throws DeviceNotFoundException {
|
||||
int[] fanSpeeds = sensors.getFanSpeeds();
|
||||
int speed = 0;// 0 means unable to measure speed
|
||||
int speed = 0; // 0 means unable to measure speed
|
||||
if (index < fanSpeeds.length) {
|
||||
speed = fanSpeeds[index];
|
||||
}
|
||||
@ -485,6 +494,14 @@ public class OSHISysteminfo implements SysteminfoInterface {
|
||||
return timeInMinutes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PercentType getSystemCpuLoad() {
|
||||
PercentType load = (ticks[0] > 0) ? new PercentType(getPercentsValue(cpu.getSystemCpuLoadBetweenTicks(ticks)))
|
||||
: null;
|
||||
ticks = cpu.getSystemCpuLoadTicks();
|
||||
return load;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -518,10 +535,10 @@ public class OSHISysteminfo implements SysteminfoInterface {
|
||||
return avarageCpuLoad.signum() == -1 ? null : new DecimalType(avarageCpuLoad);
|
||||
}
|
||||
|
||||
private BigDecimal getAvarageCpuLoad(int timeInMunutes) {
|
||||
private BigDecimal getAvarageCpuLoad(int timeInMinutes) {
|
||||
// This parameter is specified in OSHI Javadoc
|
||||
int index;
|
||||
switch (timeInMunutes) {
|
||||
switch (timeInMinutes) {
|
||||
case 1:
|
||||
index = 0;
|
||||
break;
|
||||
@ -603,12 +620,14 @@ public class OSHISysteminfo implements SysteminfoInterface {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable DecimalType getProcessCpuUsage(int pid) throws DeviceNotFoundException {
|
||||
public @Nullable PercentType getProcessCpuUsage(int pid) throws DeviceNotFoundException {
|
||||
if (pid > 0) {
|
||||
OSProcess process = getProcess(pid);
|
||||
double cpuUsageRaw = (process.getKernelTime() + process.getUserTime()) / process.getUpTime();
|
||||
BigDecimal cpuUsage = getPercentsValue(cpuUsageRaw);
|
||||
return new DecimalType(cpuUsage);
|
||||
PercentType load = (processTicks.containsKey(pid))
|
||||
? new PercentType(getPercentsValue(process.getProcessCpuLoadBetweenTicks(processTicks.get(pid))))
|
||||
: null;
|
||||
processTicks.put(pid, process);
|
||||
return load;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ package org.openhab.binding.systeminfo.internal.model;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
|
||||
/**
|
||||
@ -71,6 +72,13 @@ public interface SysteminfoInterface {
|
||||
*/
|
||||
public DecimalType getCpuPhysicalCores();
|
||||
|
||||
/**
|
||||
* Returns the system cpu load.
|
||||
*
|
||||
* @return the system cpu load between 0 and 1 or null, if no information is available
|
||||
*/
|
||||
public @Nullable PercentType getSystemCpuLoad();
|
||||
|
||||
/**
|
||||
* Returns the system load average for the last minute.
|
||||
*
|
||||
@ -411,7 +419,7 @@ public interface SysteminfoInterface {
|
||||
* @return - percentage value /0-100/
|
||||
* @throws DeviceNotFoundException - thrown if process with this PID can not be found
|
||||
*/
|
||||
public @Nullable DecimalType getProcessCpuUsage(int pid) throws DeviceNotFoundException;
|
||||
public @Nullable PercentType getProcessCpuUsage(int pid) throws DeviceNotFoundException;
|
||||
|
||||
/**
|
||||
* Returns the size of RAM memory only usage of the process
|
||||
|
@ -62,6 +62,8 @@ channel-type.systeminfo.information.label = Display Information
|
||||
channel-type.systeminfo.information.description = Product, manufacturer, SN, width and height of the display in cm
|
||||
channel-type.systeminfo.ip.label = IP Address
|
||||
channel-type.systeminfo.ip.description = Host IP address of the network
|
||||
channel-type.systeminfo.cpuLoad.label = CPU Load
|
||||
channel-type.systeminfo.cpuLoad.description = CPU load in percent
|
||||
channel-type.systeminfo.loadAverage.label = Load Average
|
||||
channel-type.systeminfo.loadAverage.description = Load as a number of processes for the last 1,5 or 15 minutes
|
||||
channel-type.systeminfo.load_process.label = Load
|
||||
|
@ -107,6 +107,7 @@
|
||||
<channels>
|
||||
<channel id="name" typeId="name"/>
|
||||
<channel id="description" typeId="description"/>
|
||||
<channel id="load" typeId="cpuLoad"/>
|
||||
<channel id="load1" typeId="loadAverage"/>
|
||||
<channel id="load5" typeId="loadAverage"/>
|
||||
<channel id="load15" typeId="loadAverage"/>
|
||||
@ -288,13 +289,21 @@
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="load_process">
|
||||
<item-type>Number</item-type>
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Load</label>
|
||||
<description>Load in percent</description>
|
||||
<state readOnly="true" pattern="%.1f %%"/>
|
||||
<config-description-ref uri="channel-type:systeminfo:highpriority_process"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="cpuLoad">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>CPU Load</label>
|
||||
<description>CPU load in percent</description>
|
||||
<state readOnly="true" pattern="%.1f %%"/>
|
||||
<config-description-ref uri="channel-type:systeminfo:highpriority"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="loadAverage" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Load Average</label>
|
||||
|
@ -34,8 +34,8 @@ Fragment-Host: org.openhab.binding.systeminfo
|
||||
org.jsr-305;version='[3.0.2,3.0.3)',\
|
||||
tech.units.indriya;version='[2.1.2,2.1.3)',\
|
||||
uom-lib-common;version='[2.1.0,2.1.1)',\
|
||||
com.sun.jna;version='[5.9.0,5.9.1)',\
|
||||
com.sun.jna.platform;version='[5.9.0,5.9.1)',\
|
||||
com.sun.jna;version='[5.12.1,5.12.2)',\
|
||||
com.sun.jna.platform;version='[5.12.1,5.12.2)',\
|
||||
si-units;version='[2.1.0,2.1.1)',\
|
||||
si.uom.si-quantity;version='[2.1.0,2.1.1)',\
|
||||
junit-jupiter-api;version='[5.8.1,5.8.2)',\
|
||||
|
@ -23,17 +23,17 @@
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
<version>5.9.0</version>
|
||||
<version>5.12.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>5.9.0</version>
|
||||
<version>5.12.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>5.8.2</version>
|
||||
<version>6.2.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
@ -45,6 +45,7 @@ import org.openhab.core.items.ItemRegistry;
|
||||
import org.openhab.core.library.items.NumberItem;
|
||||
import org.openhab.core.library.items.StringItem;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.test.java.JavaOSGiTest;
|
||||
import org.openhab.core.test.storage.VolatileStorageService;
|
||||
@ -346,6 +347,18 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
||||
assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, UnDefType.UNDEF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertChannelCpuLoadIsUpdated() {
|
||||
String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD;
|
||||
String acceptedItemType = "Number";
|
||||
|
||||
PercentType mockedCpuLoadValue = new PercentType(9);
|
||||
when(mockedSystemInfo.getSystemCpuLoad()).thenReturn(mockedCpuLoadValue);
|
||||
|
||||
initializeThingWithChannel(channnelID, acceptedItemType);
|
||||
assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuLoadValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertChannelCpuLoad1IsUpdated() {
|
||||
String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD_1;
|
||||
@ -1007,7 +1020,7 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
||||
// The pid of the System idle process in Windows
|
||||
int pid = 0;
|
||||
|
||||
DecimalType mockedProcessLoad = new DecimalType(3);
|
||||
PercentType mockedProcessLoad = new PercentType(3);
|
||||
when(mockedSystemInfo.getProcessCpuUsage(pid)).thenReturn(mockedProcessLoad);
|
||||
|
||||
initializeThingWithChannelAndPID(channnelID, acceptedItemType, pid);
|
||||
|
Loading…
Reference in New Issue
Block a user