]> git.basschouten.com Git - openhab-addons.git/commitdiff
[systeminfo] Add CPU frequency channels (#16012)
authorMark Herwege <mherwege@users.noreply.github.com>
Mon, 18 Mar 2024 10:58:54 +0000 (11:58 +0100)
committerGitHub <noreply@github.com>
Mon, 18 Mar 2024 10:58:54 +0000 (11:58 +0100)
Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
bundles/org.openhab.binding.systeminfo/README.md
bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/SysteminfoBindingConstants.java
bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/SysteminfoThingTypeProvider.java
bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/handler/SysteminfoHandler.java
bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/OSHISysteminfo.java
bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java
bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/thing/channels.xml
bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/thing/computer.xml
bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/update/update.xml [new file with mode: 0644]
itests/org.openhab.binding.systeminfo.tests/pom.xml
itests/org.openhab.binding.systeminfo.tests/src/main/java/org/openhab/binding/systeminfo/test/SysteminfoOSGiTest.java

index 43754d94637711884c7e5a6cb1b5c267f1dc3286..2e2921a69b58e1ac452958ee504fbc558ab1412c 100644 (file)
@@ -3,7 +3,7 @@
 The system information binding provides operating system and hardware information including:
 
 - 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 swap memory;
 - 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)
   - **channel** `name, remainingCapacity, remainingTime`
 - **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`
-  - **channel** `cpuTemp, cpuVoltage, fanSpeed`
+  - **channel** `cpuTemp, cpuVoltage, fanSpeed `(deviceIndex)
 - **group** `network` (deviceIndex)
   - **channel** `ip, mac, networkDisplayName, networkName, packetsSent, packetsReceived, dataSent, dataReceived`
 - **group** `currentProcess`
@@ -92,7 +92,7 @@ The groups marked with "(deviceIndex)" may have device index attached to the Cha
 - deviceIndex ::= number >= 0
 - (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)
 - deviceIndex ::= number >= 0
@@ -119,6 +119,8 @@ The binding introduces the following channels:
 | 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 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    |
 | uptime             | System uptime (time after start) in minutes                      | Number:Time         | Medium           | True     |
 | 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
 
 - 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
 
@@ -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.
 
-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).
+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!
-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.
 
@@ -209,6 +212,8 @@ 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: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 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" }
@@ -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" }
 
 /* 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_Total     "Total"               <none>          { channel="systeminfo:computer:work:memory#total" }
 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*/
 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" }
 Number Current_process_threads     "Threads"             <none>          { channel="systeminfo:computer:work:currentProcess#threads" }
 String Current_process_path        "Path"                <none>          { channel="systeminfo:computer:work:currentProcess#path" }
 
 /* Process information*/
 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" }
 Number Process_threads             "Threads"             <none>          { channel="systeminfo:computer:work:process#threads" }
 String Process_path                "Path"                <none>          { channel="systeminfo:computer:work:process#path" }
@@ -290,6 +295,8 @@ sitemap systeminfo label="Systeminfo" {
     Frame label="CPU Information" {
         Default item=CPU_Name
         Default item=CPU_Description
+        Default item=CPU_MaxFreq
+        Default item=CPU_Freq
         Default item=CPU_Load1
         Default item=CPU_Load5
         Default item=CPU_Load15
index 67d328fc4fa474d6a1f0d9d4d5d74fcaa6aeed7c..ebe6c7ac83dea763c56cbfe3cb8db32cfb681db8 100644 (file)
@@ -21,6 +21,7 @@ import org.openhab.core.thing.ThingTypeUID;
  *
  * @author Svilen Valkanov - Initial contribution
  * @author Mark Herwege - Add dynamic creation of extra channels
+ * @author Mark Herwege - Processor frequency channels
  */
 @NonNullByDefault
 public class SysteminfoBindingConstants {
@@ -278,6 +279,16 @@ public class SysteminfoBindingConstants {
      */
     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
      */
index e54806436c26ad62a301b9b312d87a1ae72737d9..20ab103161b7624fbb86761826e859632775ffe6 100644 (file)
@@ -230,10 +230,15 @@ public class SysteminfoThingTypeProvider extends AbstractStorageBasedTypeProvide
         ChannelBuilder builder = ChannelBuilder.create(channelUID).withType(channelTypeUID)
                 .withConfiguration(baseChannel.getConfiguration());
         builder.withLabel(channelType.getLabel() + " " + index);
+        builder.withDefaultTags(channelType.getTags());
         String description = channelType.getDescription();
         if (description != null) {
             builder.withDescription(description);
         }
+        String itemType = channelType.getItemType();
+        if (itemType != null) {
+            builder.withAcceptedItemType(itemType);
+        }
         return builder.build();
     }
 
index bdd27979fb3416a8c83d133a3993ff77148c39b2..3454ee999fe0c6521030f60fe1421b05d98cbd7b 100644 (file)
@@ -63,6 +63,7 @@ import org.slf4j.LoggerFactory;
  * @author Lyubomir Papzov - Separate the creation of the systeminfo object and its initialization
  * @author Wouter Born - Add null annotations
  * @author Mark Herwege - Add dynamic creation of extra channels
+ * @author Mark Herwege - Processor frequency channels
  */
 @NonNullByDefault
 public class SysteminfoHandler extends BaseThingHandler {
@@ -258,6 +259,7 @@ public class SysteminfoHandler extends BaseThingHandler {
 
         List<Channel> newChannels = new ArrayList<>();
         newChannels.addAll(createChannels(thingUID, CHANNEL_SENSORS_FAN_SPEED, systeminfo.getFanCount()));
+        newChannels.addAll(createChannels(thingUID, CHANNEL_CPU_FREQ, systeminfo.getCpuLogicalCores().intValue()));
         if (!newChannels.isEmpty()) {
             logger.debug("Creating additional channels");
             newChannels.addAll(0, thing.getChannels());
@@ -482,6 +484,12 @@ public class SysteminfoHandler extends BaseThingHandler {
                 case CHANNEL_SENSORS_FAN_SPEED:
                     state = systeminfo.getSensorsFanSpeed(deviceIndex);
                     break;
+                case CHANNEL_CPU_MAXFREQ:
+                    state = systeminfo.getCpuMaxFreq();
+                    break;
+                case CHANNEL_CPU_FREQ:
+                    state = systeminfo.getCpuFreq(deviceIndex);
+                    break;
                 case CHANNEL_CPU_LOAD:
                     PercentType cpuLoad = cpuLoadCache.getValue();
                     state = (cpuLoad != null) ? new QuantityType<>(cpuLoad, Units.PERCENT) : null;
index da186971fa65f698b445b58a9ceb7befe89c8ff8..2277d59e26ceda8928f7d1213afdfdc9400fafd2 100644 (file)
@@ -19,6 +19,7 @@ import java.util.List;
 import java.util.Map;
 
 import javax.measure.quantity.ElectricPotential;
+import javax.measure.quantity.Frequency;
 import javax.measure.quantity.Temperature;
 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 Mark Herwege - Add dynamic creation of extra channels
  * @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>
  */
@@ -197,6 +199,18 @@ public class OSHISysteminfo implements SysteminfoInterface {
         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
     public QuantityType<DataAmount> getMemoryTotal() {
         long totalMemory = memory.getTotal();
index 819df7cfbdde1b232bb35d0c98da01791c58da8e..8873ee3243eb428a7df8d9b9229621621aa6d909 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.binding.systeminfo.internal.model;
 
 import javax.measure.quantity.ElectricPotential;
+import javax.measure.quantity.Frequency;
 import javax.measure.quantity.Temperature;
 import javax.measure.quantity.Time;
 
@@ -31,6 +32,7 @@ import org.openhab.core.library.types.StringType;
  * @author Wouter Born - Add null annotations
  * @author Mark Herwege - Add dynamic creation of extra channels
  * @author Mark Herwege - Use units of measure
+ * @author Mark Herwege - Processor frequency channels
  */
 @NonNullByDefault
 public interface SysteminfoInterface {
@@ -80,6 +82,18 @@ public interface SysteminfoInterface {
      */
     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.
      *
index 193a734d0d45b3143ebf1ef1e02292d59abf8fe2..51d58e338de0f75ec2fea667876ffd9595976256 100644 (file)
                <channels>
                        <channel id="name" typeId="name"/>
                        <channel id="description" typeId="description"/>
+                       <channel id="maxfreq" typeId="maxfreq"/>
+                       <channel id="freq" typeId="freq"/>
                        <channel id="load" typeId="load"/>
                        <channel id="load1" typeId="loadAverage"/>
                        <channel id="load5" typeId="loadAverage"/>
                <config-description-ref uri="channel-type:systeminfo:mediumpriority"/>
        </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">
                <item-type>Number:Dimensionless</item-type>
                <label>Load</label>
index 31c543de77c9b5238580f8db79cac479120e53ef..3ebafc35a7f7d93e3c89861b848fc2976d064c93 100644 (file)
@@ -26,6 +26,8 @@
                </channel-groups>
 
                <properties>
+                       <property name="thingTypeVersion">1</property>
+
                        <property name="CPU Logical Cores">Not available</property>
                        <property name="CPU Physical Cores">Not available</property>
                        <property name="OS Manufacturer">Not available</property>
diff --git a/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/update/update.xml b/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/update/update.xml
new file mode 100644 (file)
index 0000000..cd2e148
--- /dev/null
@@ -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>
index a4e9cabdbeec89c4596e0687360e7d094f9030eb..6ac85988a25030de3d20df59ebc7a5792eab66e3 100644 (file)
@@ -33,7 +33,7 @@
     <dependency>
       <groupId>com.github.oshi</groupId>
       <artifactId>oshi-core</artifactId>
-      <version>6.2.2</version>
+      <version>6.4.8</version>
       <exclusions>
         <exclusion>
           <groupId>org.slf4j</groupId>
index 4025c3150e9870e1e74da03a62ea4578aa6557ff..0c8394732d3aa43ed1e292401942c7140fa8d992 100644 (file)
@@ -13,7 +13,6 @@
 package org.openhab.binding.systeminfo.test;
 
 import static java.lang.Thread.sleep;
-import static java.util.stream.Collectors.toList;
 import static org.hamcrest.CoreMatchers.*;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -23,8 +22,10 @@ import java.math.BigDecimal;
 import java.net.UnknownHostException;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 
 import javax.measure.quantity.ElectricPotential;
+import javax.measure.quantity.Frequency;
 import javax.measure.quantity.Temperature;
 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,
  *         but mock data will be used instead, avoiding potential errors from the OS queries.
  * @author Wouter Born - Migrate Groovy to Java tests
+ * @author Mark Herwege - Processor frequency channels
  */
 @NonNullByDefault
 @ExtendWith(MockitoExtension.class)
 @MockitoSettings(strictness = Strictness.LENIENT)
 public class SysteminfoOSGiTest extends JavaOSGiTest {
+
     private static final String DEFAULT_TEST_THING_NAME = "work";
     private static final String DEFAULT_TEST_ITEM_NAME = "test";
     private static final String DEFAULT_CHANNEL_TEST_PRIORITY = "High";
@@ -126,16 +129,17 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
     private @NonNullByDefault({}) ManagedThingProvider managedThingProvider;
     private @NonNullByDefault({}) ManagedItemChannelLinkProvider itemChannelLinkProvider;
     private @NonNullByDefault({}) UnitProvider unitProvider;
+    private @NonNullByDefault({}) VolatileStorageService volatileStorageService;
 
     @BeforeEach
     public void setUp() {
-        VolatileStorageService volatileStorageService = new VolatileStorageService();
+        volatileStorageService = new VolatileStorageService();
         registerService(volatileStorageService);
 
         // 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
-        lenient().when(mockedSystemInfo.getCpuLogicalCores()).thenReturn(new DecimalType(2));
-        lenient().when(mockedSystemInfo.getCpuPhysicalCores()).thenReturn(new DecimalType(2));
+        lenient().when(mockedSystemInfo.getCpuLogicalCores()).thenReturn(new DecimalType(1));
+        lenient().when(mockedSystemInfo.getCpuPhysicalCores()).thenReturn(new DecimalType(1));
         lenient().when(mockedSystemInfo.getOsFamily()).thenReturn(new StringType("Mock OS"));
         lenient().when(mockedSystemInfo.getOsManufacturer()).thenReturn(new StringType("Mock OS Manufacturer"));
         lenient().when(mockedSystemInfo.getOsVersion()).thenReturn(new StringType("Mock Os Version"));
@@ -164,11 +168,6 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
             systeminfoHandlerFactory.bindSystemInfo(mockedSystemInfo);
         }
 
-        waitForAssert(() -> {
-            systeminfoHandlerFactory = getService(ThingHandlerFactory.class, SysteminfoHandlerFactory.class);
-            assertThat(systeminfoHandlerFactory, is(notNullValue()));
-        });
-
         waitForAssert(() -> {
             thingRegistry = getService(ThingRegistry.class);
             assertThat(thingRegistry, is(notNullValue()));
@@ -199,13 +198,14 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
     public void tearDown() {
         Thing thing = systeminfoThing;
         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());
             assertThat("The systeminfo thing cannot be deleted", removedThing, is(notNullValue()));
             waitForAssert(() -> {
                 ThingHandler systemInfoHandler = thing.getHandler();
                 assertThat(systemInfoHandler, is(nullValue()));
             });
+            managedThingProvider.remove(thing.getUID());
         }
 
         if (testItem != null) {
@@ -213,6 +213,7 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
         }
 
         unregisterService(mockedSystemInfo);
+        unregisterService(volatileStorageService);
     }
 
     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)
                 .withKind(ChannelKind.STATE).withConfiguration(channelConfig).build();
 
-        Thing thing = ThingBuilder.create(thingTypeUID, thingUID).withConfiguration(thingConfiguration)
-                .withChannel(channel).build();
+        ThingBuilder thingBuilder = ThingBuilder.create(thingTypeUID, thingUID).withConfiguration(thingConfiguration)
+                .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;
 
         managedThingProvider.add(thing);
@@ -399,6 +404,30 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
         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
     public void assertChannelCpuLoadIsUpdated() {
         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD;
@@ -997,8 +1026,7 @@ public class SysteminfoOSGiTest extends JavaOSGiTest {
         }
 
         waitForAssert(() -> {
-            List<DiscoveryResult> results = inbox.stream().filter(InboxPredicates.forThingUID(computerUID))
-                    .collect(toList());
+            List<DiscoveryResult> results = inbox.stream().filter(InboxPredicates.forThingUID(computerUID)).toList();
             assertFalse(results.isEmpty(), "No Thing with UID " + computerUID.getAsString() + " in inbox");
         });