**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)
* **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)
| 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 |
- **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.
/* 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" }
<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>
<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>
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;
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);
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;
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);
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;
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;
/**
@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];
}
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}
*
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;
}
@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;
}
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;
/**
*/
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.
*
* @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
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
<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"/>
</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>
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)',\
<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>
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;
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;
// 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);