mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[systeminfo] Add CPU frequency channels (#16012)
Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
This commit is contained in:
parent
afa65f251d
commit
08f210e5d8
@ -3,7 +3,7 @@
|
|||||||
The system information binding provides operating system and hardware information including:
|
The system information binding provides operating system and hardware information including:
|
||||||
|
|
||||||
- Operating system name, version and manufacturer;
|
- Operating system name, version and manufacturer;
|
||||||
- CPU average load for last 1, 5, 15 minutes, name, description, number of physical and logical cores, running threads number, system uptime;
|
- CPU average load for last 1, 5, 15 minutes, name, description, number of physical and logical cores, running threads number, system uptime, max frequency and frequency by logical core;
|
||||||
- Free, total and available memory;
|
- Free, total and available memory;
|
||||||
- Free, total and available swap memory;
|
- Free, total and available swap memory;
|
||||||
- Hard drive name, model and serial number;
|
- Hard drive name, model and serial number;
|
||||||
@ -76,9 +76,9 @@ In the list below, you can find, how are channel group and channels id`s related
|
|||||||
- **group** `battery` (deviceIndex)
|
- **group** `battery` (deviceIndex)
|
||||||
- **channel** `name, remainingCapacity, remainingTime`
|
- **channel** `name, remainingCapacity, remainingTime`
|
||||||
- **group** `cpu`
|
- **group** `cpu`
|
||||||
- **channel** `name, description, load, load1, load5, load15, uptime, threads`
|
- **channel** `name, description, maxfreq, freq `(deviceIndex)`, load, load1, load5, load15, uptime, threads`
|
||||||
- **group** `sensors`
|
- **group** `sensors`
|
||||||
- **channel** `cpuTemp, cpuVoltage, fanSpeed`
|
- **channel** `cpuTemp, cpuVoltage, fanSpeed `(deviceIndex)
|
||||||
- **group** `network` (deviceIndex)
|
- **group** `network` (deviceIndex)
|
||||||
- **channel** `ip, mac, networkDisplayName, networkName, packetsSent, packetsReceived, dataSent, dataReceived`
|
- **channel** `ip, mac, networkDisplayName, networkName, packetsSent, packetsReceived, dataSent, dataReceived`
|
||||||
- **group** `currentProcess`
|
- **group** `currentProcess`
|
||||||
@ -92,7 +92,7 @@ The groups marked with "(deviceIndex)" may have device index attached to the Cha
|
|||||||
- deviceIndex ::= number >= 0
|
- deviceIndex ::= number >= 0
|
||||||
- (e.g. _storage1#available_)
|
- (e.g. _storage1#available_)
|
||||||
|
|
||||||
The `fanSpeed` channel in the `sensors` group may have a device index attached to the Channel.
|
The channels marked with "(deviceIndex)" may have a device index attached to the Channel.
|
||||||
|
|
||||||
- channel ::= channel_group & # channel_id & (deviceIndex)
|
- channel ::= channel_group & # channel_id & (deviceIndex)
|
||||||
- deviceIndex ::= number >= 0
|
- deviceIndex ::= number >= 0
|
||||||
@ -119,6 +119,8 @@ The binding introduces the following channels:
|
|||||||
| load5 | Load for the last 5 minutes | Number | Medium | True |
|
| load5 | Load for the last 5 minutes | Number | Medium | True |
|
||||||
| load15 | Load for the last 15 minutes | Number | Medium | True |
|
| load15 | Load for the last 15 minutes | Number | Medium | True |
|
||||||
| threads | Number of threads currently running or for the process | Number | Medium | True |
|
| threads | Number of threads currently running or for the process | Number | Medium | True |
|
||||||
|
| maxfreq | CPU maximum frequency | Number:Frequency | Low | True |
|
||||||
|
| freq | Logical processor frequency | Number:Frequency | High | True |
|
||||||
| path | The full path of the process | String | Low | False |
|
| path | The full path of the process | String | Low | False |
|
||||||
| uptime | System uptime (time after start) in minutes | Number:Time | Medium | True |
|
| uptime | System uptime (time after start) in minutes | Number:Time | Medium | True |
|
||||||
| name | Name of the device or process | String | Low | False |
|
| name | Name of the device or process | String | Low | False |
|
||||||
@ -172,6 +174,7 @@ Parameter PID has a default value 0 - this is the PID of the System Idle process
|
|||||||
## Known issues and workarounds
|
## Known issues and workarounds
|
||||||
|
|
||||||
- Temperature readings are not well supported on standard Windows systems, run [OpenHardwareMonitor.exe](https://openhardwaremonitor.org) for the binding to get more reliable readings.
|
- Temperature readings are not well supported on standard Windows systems, run [OpenHardwareMonitor.exe](https://openhardwaremonitor.org) for the binding to get more reliable readings.
|
||||||
|
- CPU frequency readings are not available on some OS versions.
|
||||||
|
|
||||||
## Reporting issues
|
## Reporting issues
|
||||||
|
|
||||||
@ -179,9 +182,9 @@ As already mentioned this binding depends heavily on the [OSHI](https://github.c
|
|||||||
|
|
||||||
Take a look at the console for an ERROR log message.
|
Take a look at the console for an ERROR log message.
|
||||||
|
|
||||||
If you find an issue with a support for a specific hardware or software architecture please take a look at the [OSHI issues](https://github.com/oshi/oshi/issues).
|
If you find an issue with support for a specific hardware or software architecture please take a look at the [OSHI issues](https://github.com/oshi/oshi/issues).
|
||||||
Your problem might have be already reported and solved!
|
Your problem might have be already reported and solved!
|
||||||
Feel free to open a new issue there with the log message and the and information about your software or hardware configuration.
|
Feel free to open a new issue there with the log message and the information about your software or hardware configuration.
|
||||||
|
|
||||||
For a general problem with the binding report the issue directly to openHAB.
|
For a general problem with the binding report the issue directly to openHAB.
|
||||||
|
|
||||||
@ -209,6 +212,8 @@ Number Network_PacketsReceived "Packets received" <returnpipe> { chann
|
|||||||
/* CPU information*/
|
/* CPU information*/
|
||||||
String CPU_Name "Name" <none> { channel="systeminfo:computer:work:cpu#name" }
|
String CPU_Name "Name" <none> { channel="systeminfo:computer:work:cpu#name" }
|
||||||
String CPU_Description "Description" <none> { channel="systeminfo:computer:work:cpu#description" }
|
String CPU_Description "Description" <none> { channel="systeminfo:computer:work:cpu#description" }
|
||||||
|
Number:Frequency CPU_MaxFreq "CPU Max Frequency" <none> { channel="systeminfo:computer:work:cpu#maxfreq" }
|
||||||
|
Number:Frequency CPU_Freq "CPU Frequency" <none> { channel="systeminfo:computer:work:cpu#freq" }
|
||||||
Number:Dimensionless CPU_Load "CPU Load" <none> { channel="systeminfo:computer:work:cpu#load" }
|
Number:Dimensionless 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_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_Load5 "Load (5 min)" <none> { channel="systeminfo:computer:work:cpu#load5" }
|
||||||
@ -232,7 +237,7 @@ Number:Dimensionless Storage_Available_Percent "Available (%)" <none> { chann
|
|||||||
Number:Dimensionless Storage_Used_Percent "Used (%)" <none> { channel="systeminfo:computer:work:storage#usedPercent" }
|
Number:Dimensionless Storage_Used_Percent "Used (%)" <none> { channel="systeminfo:computer:work:storage#usedPercent" }
|
||||||
|
|
||||||
/* Memory information*/
|
/* Memory information*/
|
||||||
Number Memory_Available "Available" <none> { channel="systeminfo:computer:work:memory#available" }
|
Number:DataAmount Memory_Available "Available" <none> { channel="systeminfo:computer:work:memory#available" }
|
||||||
Number:DataAmount Memory_Used "Used" <none> { channel="systeminfo:computer:work:memory#used" }
|
Number:DataAmount Memory_Used "Used" <none> { channel="systeminfo:computer:work:memory#used" }
|
||||||
Number:DataAmount Memory_Total "Total" <none> { channel="systeminfo:computer:work:memory#total" }
|
Number:DataAmount Memory_Total "Total" <none> { channel="systeminfo:computer:work:memory#total" }
|
||||||
Number:Dimensionless Memory_Available_Percent "Available (%)" <none> { channel="systeminfo:computer:work:memory#availablePercent" }
|
Number:Dimensionless Memory_Available_Percent "Available (%)" <none> { channel="systeminfo:computer:work:memory#availablePercent" }
|
||||||
@ -260,14 +265,14 @@ Number Sensor_FanSpeed "Fan speed" <fan> { chann
|
|||||||
|
|
||||||
/* Current process information*/
|
/* Current process information*/
|
||||||
Number:Dimensionless Current_process_load "Load" <none> { channel="systeminfo:computer:work:currentProcess#load" }
|
Number:Dimensionless Current_process_load "Load" <none> { channel="systeminfo:computer:work:currentProcess#load" }
|
||||||
Number:Dimensionless Current_process_used "Used" <none> { channel="systeminfo:computer:work:currentProcess#used" }
|
Number:DataAmount Current_process_used "Used" <none> { channel="systeminfo:computer:work:currentProcess#used" }
|
||||||
String Current_process_name "Name" <none> { channel="systeminfo:computer:work:currentProcess#name" }
|
String Current_process_name "Name" <none> { channel="systeminfo:computer:work:currentProcess#name" }
|
||||||
Number Current_process_threads "Threads" <none> { channel="systeminfo:computer:work:currentProcess#threads" }
|
Number Current_process_threads "Threads" <none> { channel="systeminfo:computer:work:currentProcess#threads" }
|
||||||
String Current_process_path "Path" <none> { channel="systeminfo:computer:work:currentProcess#path" }
|
String Current_process_path "Path" <none> { channel="systeminfo:computer:work:currentProcess#path" }
|
||||||
|
|
||||||
/* Process information*/
|
/* Process information*/
|
||||||
Number:Dimensionless Process_load "Load" <none> { channel="systeminfo:computer:work:process#load" }
|
Number:Dimensionless Process_load "Load" <none> { channel="systeminfo:computer:work:process#load" }
|
||||||
Number:Dimensionless Process_used "Used" <none> { channel="systeminfo:computer:work:process#used" }
|
Number:DataAmount Process_used "Used" <none> { channel="systeminfo:computer:work:process#used" }
|
||||||
String Process_name "Name" <none> { channel="systeminfo:computer:work:process#name" }
|
String Process_name "Name" <none> { channel="systeminfo:computer:work:process#name" }
|
||||||
Number Process_threads "Threads" <none> { channel="systeminfo:computer:work:process#threads" }
|
Number Process_threads "Threads" <none> { channel="systeminfo:computer:work:process#threads" }
|
||||||
String Process_path "Path" <none> { channel="systeminfo:computer:work:process#path" }
|
String Process_path "Path" <none> { channel="systeminfo:computer:work:process#path" }
|
||||||
@ -290,6 +295,8 @@ sitemap systeminfo label="Systeminfo" {
|
|||||||
Frame label="CPU Information" {
|
Frame label="CPU Information" {
|
||||||
Default item=CPU_Name
|
Default item=CPU_Name
|
||||||
Default item=CPU_Description
|
Default item=CPU_Description
|
||||||
|
Default item=CPU_MaxFreq
|
||||||
|
Default item=CPU_Freq
|
||||||
Default item=CPU_Load1
|
Default item=CPU_Load1
|
||||||
Default item=CPU_Load5
|
Default item=CPU_Load5
|
||||||
Default item=CPU_Load15
|
Default item=CPU_Load15
|
||||||
|
@ -21,6 +21,7 @@ import org.openhab.core.thing.ThingTypeUID;
|
|||||||
*
|
*
|
||||||
* @author Svilen Valkanov - Initial contribution
|
* @author Svilen Valkanov - Initial contribution
|
||||||
* @author Mark Herwege - Add dynamic creation of extra channels
|
* @author Mark Herwege - Add dynamic creation of extra channels
|
||||||
|
* @author Mark Herwege - Processor frequency channels
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SysteminfoBindingConstants {
|
public class SysteminfoBindingConstants {
|
||||||
@ -278,6 +279,16 @@ public class SysteminfoBindingConstants {
|
|||||||
*/
|
*/
|
||||||
public static final String CHANNEL_CPU_DESCRIPTION = "cpu#description";
|
public static final String CHANNEL_CPU_DESCRIPTION = "cpu#description";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum frequency of the CPU
|
||||||
|
*/
|
||||||
|
public static final String CHANNEL_CPU_MAXFREQ = "cpu#maxfreq";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frequency of the CPU
|
||||||
|
*/
|
||||||
|
public static final String CHANNEL_CPU_FREQ = "cpu#freq";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Average recent CPU load
|
* Average recent CPU load
|
||||||
*/
|
*/
|
||||||
|
@ -230,10 +230,15 @@ public class SysteminfoThingTypeProvider extends AbstractStorageBasedTypeProvide
|
|||||||
ChannelBuilder builder = ChannelBuilder.create(channelUID).withType(channelTypeUID)
|
ChannelBuilder builder = ChannelBuilder.create(channelUID).withType(channelTypeUID)
|
||||||
.withConfiguration(baseChannel.getConfiguration());
|
.withConfiguration(baseChannel.getConfiguration());
|
||||||
builder.withLabel(channelType.getLabel() + " " + index);
|
builder.withLabel(channelType.getLabel() + " " + index);
|
||||||
|
builder.withDefaultTags(channelType.getTags());
|
||||||
String description = channelType.getDescription();
|
String description = channelType.getDescription();
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
builder.withDescription(description);
|
builder.withDescription(description);
|
||||||
}
|
}
|
||||||
|
String itemType = channelType.getItemType();
|
||||||
|
if (itemType != null) {
|
||||||
|
builder.withAcceptedItemType(itemType);
|
||||||
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
* @author Lyubomir Papzov - Separate the creation of the systeminfo object and its initialization
|
* @author Lyubomir Papzov - Separate the creation of the systeminfo object and its initialization
|
||||||
* @author Wouter Born - Add null annotations
|
* @author Wouter Born - Add null annotations
|
||||||
* @author Mark Herwege - Add dynamic creation of extra channels
|
* @author Mark Herwege - Add dynamic creation of extra channels
|
||||||
|
* @author Mark Herwege - Processor frequency channels
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class SysteminfoHandler extends BaseThingHandler {
|
public class SysteminfoHandler extends BaseThingHandler {
|
||||||
@ -258,6 +259,7 @@ public class SysteminfoHandler extends BaseThingHandler {
|
|||||||
|
|
||||||
List<Channel> newChannels = new ArrayList<>();
|
List<Channel> newChannels = new ArrayList<>();
|
||||||
newChannels.addAll(createChannels(thingUID, CHANNEL_SENSORS_FAN_SPEED, systeminfo.getFanCount()));
|
newChannels.addAll(createChannels(thingUID, CHANNEL_SENSORS_FAN_SPEED, systeminfo.getFanCount()));
|
||||||
|
newChannels.addAll(createChannels(thingUID, CHANNEL_CPU_FREQ, systeminfo.getCpuLogicalCores().intValue()));
|
||||||
if (!newChannels.isEmpty()) {
|
if (!newChannels.isEmpty()) {
|
||||||
logger.debug("Creating additional channels");
|
logger.debug("Creating additional channels");
|
||||||
newChannels.addAll(0, thing.getChannels());
|
newChannels.addAll(0, thing.getChannels());
|
||||||
@ -482,6 +484,12 @@ public class SysteminfoHandler extends BaseThingHandler {
|
|||||||
case CHANNEL_SENSORS_FAN_SPEED:
|
case CHANNEL_SENSORS_FAN_SPEED:
|
||||||
state = systeminfo.getSensorsFanSpeed(deviceIndex);
|
state = systeminfo.getSensorsFanSpeed(deviceIndex);
|
||||||
break;
|
break;
|
||||||
|
case CHANNEL_CPU_MAXFREQ:
|
||||||
|
state = systeminfo.getCpuMaxFreq();
|
||||||
|
break;
|
||||||
|
case CHANNEL_CPU_FREQ:
|
||||||
|
state = systeminfo.getCpuFreq(deviceIndex);
|
||||||
|
break;
|
||||||
case CHANNEL_CPU_LOAD:
|
case CHANNEL_CPU_LOAD:
|
||||||
PercentType cpuLoad = cpuLoadCache.getValue();
|
PercentType cpuLoad = cpuLoadCache.getValue();
|
||||||
state = (cpuLoad != null) ? new QuantityType<>(cpuLoad, Units.PERCENT) : null;
|
state = (cpuLoad != null) ? new QuantityType<>(cpuLoad, Units.PERCENT) : null;
|
||||||
|
@ -19,6 +19,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.measure.quantity.ElectricPotential;
|
import javax.measure.quantity.ElectricPotential;
|
||||||
|
import javax.measure.quantity.Frequency;
|
||||||
import javax.measure.quantity.Temperature;
|
import javax.measure.quantity.Temperature;
|
||||||
import javax.measure.quantity.Time;
|
import javax.measure.quantity.Time;
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ import oshi.util.EdidUtil;
|
|||||||
* @author Wouter Born - Update to OSHI 4.0.0 and add null annotations
|
* @author Wouter Born - Update to OSHI 4.0.0 and add null annotations
|
||||||
* @author Mark Herwege - Add dynamic creation of extra channels
|
* @author Mark Herwege - Add dynamic creation of extra channels
|
||||||
* @author Mark Herwege - Use units of measure
|
* @author Mark Herwege - Use units of measure
|
||||||
|
* @author Mark Herwege - Processor frequency channels
|
||||||
*
|
*
|
||||||
* @see <a href="https://github.com/oshi/oshi">OSHI GitHub repository</a>
|
* @see <a href="https://github.com/oshi/oshi">OSHI GitHub repository</a>
|
||||||
*/
|
*/
|
||||||
@ -197,6 +199,18 @@ public class OSHISysteminfo implements SysteminfoInterface {
|
|||||||
return new DecimalType(physicalProcessorCount);
|
return new DecimalType(physicalProcessorCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable QuantityType<Frequency> getCpuMaxFreq() {
|
||||||
|
long maxFreq = cpu.getMaxFreq();
|
||||||
|
return maxFreq >= 0 ? new QuantityType<>(maxFreq, Units.HERTZ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable QuantityType<Frequency> getCpuFreq(int logicalProcessorIndex) {
|
||||||
|
long freq = cpu.getCurrentFreq()[logicalProcessorIndex];
|
||||||
|
return freq >= 0 ? new QuantityType<>(freq, Units.HERTZ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QuantityType<DataAmount> getMemoryTotal() {
|
public QuantityType<DataAmount> getMemoryTotal() {
|
||||||
long totalMemory = memory.getTotal();
|
long totalMemory = memory.getTotal();
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
package org.openhab.binding.systeminfo.internal.model;
|
package org.openhab.binding.systeminfo.internal.model;
|
||||||
|
|
||||||
import javax.measure.quantity.ElectricPotential;
|
import javax.measure.quantity.ElectricPotential;
|
||||||
|
import javax.measure.quantity.Frequency;
|
||||||
import javax.measure.quantity.Temperature;
|
import javax.measure.quantity.Temperature;
|
||||||
import javax.measure.quantity.Time;
|
import javax.measure.quantity.Time;
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ import org.openhab.core.library.types.StringType;
|
|||||||
* @author Wouter Born - Add null annotations
|
* @author Wouter Born - Add null annotations
|
||||||
* @author Mark Herwege - Add dynamic creation of extra channels
|
* @author Mark Herwege - Add dynamic creation of extra channels
|
||||||
* @author Mark Herwege - Use units of measure
|
* @author Mark Herwege - Use units of measure
|
||||||
|
* @author Mark Herwege - Processor frequency channels
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public interface SysteminfoInterface {
|
public interface SysteminfoInterface {
|
||||||
@ -80,6 +82,18 @@ public interface SysteminfoInterface {
|
|||||||
*/
|
*/
|
||||||
DecimalType getCpuPhysicalCores();
|
DecimalType getCpuPhysicalCores();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum CPU frequency of the processor.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
QuantityType<Frequency> getCpuMaxFreq();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current CPU frequency of a logical processor.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
QuantityType<Frequency> getCpuFreq(int logicalProcessorIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the system cpu load.
|
* Returns the system cpu load.
|
||||||
*
|
*
|
||||||
|
@ -107,6 +107,8 @@
|
|||||||
<channels>
|
<channels>
|
||||||
<channel id="name" typeId="name"/>
|
<channel id="name" typeId="name"/>
|
||||||
<channel id="description" typeId="description"/>
|
<channel id="description" typeId="description"/>
|
||||||
|
<channel id="maxfreq" typeId="maxfreq"/>
|
||||||
|
<channel id="freq" typeId="freq"/>
|
||||||
<channel id="load" typeId="load"/>
|
<channel id="load" typeId="load"/>
|
||||||
<channel id="load1" typeId="loadAverage"/>
|
<channel id="load1" typeId="loadAverage"/>
|
||||||
<channel id="load5" typeId="loadAverage"/>
|
<channel id="load5" typeId="loadAverage"/>
|
||||||
@ -308,6 +310,22 @@
|
|||||||
<config-description-ref uri="channel-type:systeminfo:mediumpriority"/>
|
<config-description-ref uri="channel-type:systeminfo:mediumpriority"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="maxfreq" advanced="true">
|
||||||
|
<item-type>Number:Frequency</item-type>
|
||||||
|
<label>Maximum Frequency</label>
|
||||||
|
<description>CPU maximum frequency</description>
|
||||||
|
<state readOnly="true" pattern="%.0f MHz"/>
|
||||||
|
<config-description-ref uri="channel-type:systeminfo:lowpriority"/>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
<channel-type id="freq" advanced="true">
|
||||||
|
<item-type>Number:Frequency</item-type>
|
||||||
|
<label>Current Frequency</label>
|
||||||
|
<description>Logical processor frequency</description>
|
||||||
|
<state readOnly="true" pattern="%.0f MHz"/>
|
||||||
|
<config-description-ref uri="channel-type:systeminfo:highpriority"/>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
<channel-type id="load">
|
<channel-type id="load">
|
||||||
<item-type>Number:Dimensionless</item-type>
|
<item-type>Number:Dimensionless</item-type>
|
||||||
<label>Load</label>
|
<label>Load</label>
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
</channel-groups>
|
</channel-groups>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<property name="thingTypeVersion">1</property>
|
||||||
|
|
||||||
<property name="CPU Logical Cores">Not available</property>
|
<property name="CPU Logical Cores">Not available</property>
|
||||||
<property name="CPU Physical Cores">Not available</property>
|
<property name="CPU Physical Cores">Not available</property>
|
||||||
<property name="OS Manufacturer">Not available</property>
|
<property name="OS Manufacturer">Not available</property>
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
|
||||||
|
|
||||||
|
<thing-type uid="systeminfo:computer">
|
||||||
|
<instruction-set targetVersion="1">
|
||||||
|
<add-channel id="maxfreq" groupIds="cpu">
|
||||||
|
<type>systeminfo:maxfreq</type>
|
||||||
|
</add-channel>
|
||||||
|
<add-channel id="freq" groupIds="cpu">
|
||||||
|
<type>systeminfo:freq</type>
|
||||||
|
</add-channel>
|
||||||
|
</instruction-set>
|
||||||
|
</thing-type>
|
||||||
|
|
||||||
|
</update:update-descriptions>
|
@ -33,7 +33,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.oshi</groupId>
|
<groupId>com.github.oshi</groupId>
|
||||||
<artifactId>oshi-core</artifactId>
|
<artifactId>oshi-core</artifactId>
|
||||||
<version>6.2.2</version>
|
<version>6.4.8</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
package org.openhab.binding.systeminfo.test;
|
package org.openhab.binding.systeminfo.test;
|
||||||
|
|
||||||
import static java.lang.Thread.sleep;
|
import static java.lang.Thread.sleep;
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
@ -23,8 +22,10 @@ import java.math.BigDecimal;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.measure.quantity.ElectricPotential;
|
import javax.measure.quantity.ElectricPotential;
|
||||||
|
import javax.measure.quantity.Frequency;
|
||||||
import javax.measure.quantity.Temperature;
|
import javax.measure.quantity.Temperature;
|
||||||
import javax.measure.quantity.Time;
|
import javax.measure.quantity.Time;
|
||||||
|
|
||||||
@ -93,11 +94,13 @@ import org.openhab.core.types.UnDefType;
|
|||||||
* @author Lyubomir Papazov - Created a mock systeminfo object. This way, access to the user's OS will not be required,
|
* @author Lyubomir Papazov - Created a mock systeminfo object. This way, access to the user's OS will not be required,
|
||||||
* but mock data will be used instead, avoiding potential errors from the OS queries.
|
* but mock data will be used instead, avoiding potential errors from the OS queries.
|
||||||
* @author Wouter Born - Migrate Groovy to Java tests
|
* @author Wouter Born - Migrate Groovy to Java tests
|
||||||
|
* @author Mark Herwege - Processor frequency channels
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||||
public class SysteminfoOSGiTest extends JavaOSGiTest {
|
public class SysteminfoOSGiTest extends JavaOSGiTest {
|
||||||
|
|
||||||
private static final String DEFAULT_TEST_THING_NAME = "work";
|
private static final String DEFAULT_TEST_THING_NAME = "work";
|
||||||
private static final String DEFAULT_TEST_ITEM_NAME = "test";
|
private static final String DEFAULT_TEST_ITEM_NAME = "test";
|
||||||
private static final String DEFAULT_CHANNEL_TEST_PRIORITY = "High";
|
private static final String DEFAULT_CHANNEL_TEST_PRIORITY = "High";
|
||||||
@ -126,16 +129,17 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
|||||||
private @NonNullByDefault({}) ManagedThingProvider managedThingProvider;
|
private @NonNullByDefault({}) ManagedThingProvider managedThingProvider;
|
||||||
private @NonNullByDefault({}) ManagedItemChannelLinkProvider itemChannelLinkProvider;
|
private @NonNullByDefault({}) ManagedItemChannelLinkProvider itemChannelLinkProvider;
|
||||||
private @NonNullByDefault({}) UnitProvider unitProvider;
|
private @NonNullByDefault({}) UnitProvider unitProvider;
|
||||||
|
private @NonNullByDefault({}) VolatileStorageService volatileStorageService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
VolatileStorageService volatileStorageService = new VolatileStorageService();
|
volatileStorageService = new VolatileStorageService();
|
||||||
registerService(volatileStorageService);
|
registerService(volatileStorageService);
|
||||||
|
|
||||||
// Preparing the mock with OS properties, that are used in the initialize method of SysteminfoHandler
|
// Preparing the mock with OS properties, that are used in the initialize method of SysteminfoHandler
|
||||||
// Make this lenient because the assertInvalidThingConfigurationValuesAreHandled test does not require them
|
// Make this lenient because the assertInvalidThingConfigurationValuesAreHandled test does not require them
|
||||||
lenient().when(mockedSystemInfo.getCpuLogicalCores()).thenReturn(new DecimalType(2));
|
lenient().when(mockedSystemInfo.getCpuLogicalCores()).thenReturn(new DecimalType(1));
|
||||||
lenient().when(mockedSystemInfo.getCpuPhysicalCores()).thenReturn(new DecimalType(2));
|
lenient().when(mockedSystemInfo.getCpuPhysicalCores()).thenReturn(new DecimalType(1));
|
||||||
lenient().when(mockedSystemInfo.getOsFamily()).thenReturn(new StringType("Mock OS"));
|
lenient().when(mockedSystemInfo.getOsFamily()).thenReturn(new StringType("Mock OS"));
|
||||||
lenient().when(mockedSystemInfo.getOsManufacturer()).thenReturn(new StringType("Mock OS Manufacturer"));
|
lenient().when(mockedSystemInfo.getOsManufacturer()).thenReturn(new StringType("Mock OS Manufacturer"));
|
||||||
lenient().when(mockedSystemInfo.getOsVersion()).thenReturn(new StringType("Mock Os Version"));
|
lenient().when(mockedSystemInfo.getOsVersion()).thenReturn(new StringType("Mock Os Version"));
|
||||||
@ -164,11 +168,6 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
|||||||
systeminfoHandlerFactory.bindSystemInfo(mockedSystemInfo);
|
systeminfoHandlerFactory.bindSystemInfo(mockedSystemInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForAssert(() -> {
|
|
||||||
systeminfoHandlerFactory = getService(ThingHandlerFactory.class, SysteminfoHandlerFactory.class);
|
|
||||||
assertThat(systeminfoHandlerFactory, is(notNullValue()));
|
|
||||||
});
|
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
thingRegistry = getService(ThingRegistry.class);
|
thingRegistry = getService(ThingRegistry.class);
|
||||||
assertThat(thingRegistry, is(notNullValue()));
|
assertThat(thingRegistry, is(notNullValue()));
|
||||||
@ -199,13 +198,14 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
|||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
Thing thing = systeminfoThing;
|
Thing thing = systeminfoThing;
|
||||||
if (thing != null) {
|
if (thing != null) {
|
||||||
// Remove the systeminfo thing. The handler will be also disposed automatically
|
// Remove the systeminfo thing. The handler will also be disposed automatically
|
||||||
Thing removedThing = thingRegistry.forceRemove(thing.getUID());
|
Thing removedThing = thingRegistry.forceRemove(thing.getUID());
|
||||||
assertThat("The systeminfo thing cannot be deleted", removedThing, is(notNullValue()));
|
assertThat("The systeminfo thing cannot be deleted", removedThing, is(notNullValue()));
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
ThingHandler systemInfoHandler = thing.getHandler();
|
ThingHandler systemInfoHandler = thing.getHandler();
|
||||||
assertThat(systemInfoHandler, is(nullValue()));
|
assertThat(systemInfoHandler, is(nullValue()));
|
||||||
});
|
});
|
||||||
|
managedThingProvider.remove(thing.getUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (testItem != null) {
|
if (testItem != null) {
|
||||||
@ -213,6 +213,7 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unregisterService(mockedSystemInfo);
|
unregisterService(mockedSystemInfo);
|
||||||
|
unregisterService(volatileStorageService);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeThingWithChannelAndPID(String channelID, String acceptedItemType, int pid) {
|
private void initializeThingWithChannelAndPID(String channelID, String acceptedItemType, int pid) {
|
||||||
@ -275,8 +276,12 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
|||||||
Channel channel = ChannelBuilder.create(channelUID, acceptedItemType).withType(channelTypeUID)
|
Channel channel = ChannelBuilder.create(channelUID, acceptedItemType).withType(channelTypeUID)
|
||||||
.withKind(ChannelKind.STATE).withConfiguration(channelConfig).build();
|
.withKind(ChannelKind.STATE).withConfiguration(channelConfig).build();
|
||||||
|
|
||||||
Thing thing = ThingBuilder.create(thingTypeUID, thingUID).withConfiguration(thingConfiguration)
|
ThingBuilder thingBuilder = ThingBuilder.create(thingTypeUID, thingUID).withConfiguration(thingConfiguration)
|
||||||
.withChannel(channel).build();
|
.withChannel(channel);
|
||||||
|
// Make sure the thingTypeVersion matches the highest version in the update instructions of the binding to avoid
|
||||||
|
// new channels being added and the thing not initializing
|
||||||
|
thingBuilder = thingBuilder.withProperties(Map.of("thingTypeVersion", "1"));
|
||||||
|
Thing thing = thingBuilder.build();
|
||||||
systeminfoThing = thing;
|
systeminfoThing = thing;
|
||||||
|
|
||||||
managedThingProvider.add(thing);
|
managedThingProvider.add(thing);
|
||||||
@ -399,6 +404,30 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
|||||||
assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, UnDefType.UNDEF);
|
assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, UnDefType.UNDEF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void assertChannelCpuMaxFreq() {
|
||||||
|
String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_MAXFREQ;
|
||||||
|
String acceptedItemType = "Number:Frequency";
|
||||||
|
|
||||||
|
QuantityType<Frequency> mockedCpuMaxFreqValue = new QuantityType<>(2500, Units.HERTZ);
|
||||||
|
when(mockedSystemInfo.getCpuMaxFreq()).thenReturn(mockedCpuMaxFreqValue);
|
||||||
|
|
||||||
|
initializeThingWithChannel(channnelID, acceptedItemType);
|
||||||
|
assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuMaxFreqValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void assertChannelCpuFreq() {
|
||||||
|
String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_FREQ;
|
||||||
|
String acceptedItemType = "Number:Frequency";
|
||||||
|
|
||||||
|
QuantityType<Frequency> mockedCpuFreqValue = new QuantityType<>(2500, Units.HERTZ);
|
||||||
|
when(mockedSystemInfo.getCpuFreq(0)).thenReturn(mockedCpuFreqValue);
|
||||||
|
|
||||||
|
initializeThingWithChannel(channnelID, acceptedItemType);
|
||||||
|
assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuFreqValue);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void assertChannelCpuLoadIsUpdated() {
|
public void assertChannelCpuLoadIsUpdated() {
|
||||||
String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD;
|
String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD;
|
||||||
@ -997,8 +1026,7 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
List<DiscoveryResult> results = inbox.stream().filter(InboxPredicates.forThingUID(computerUID))
|
List<DiscoveryResult> results = inbox.stream().filter(InboxPredicates.forThingUID(computerUID)).toList();
|
||||||
.collect(toList());
|
|
||||||
assertFalse(results.isEmpty(), "No Thing with UID " + computerUID.getAsString() + " in inbox");
|
assertFalse(results.isEmpty(), "No Thing with UID " + computerUID.getAsString() + " in inbox");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user