]> git.basschouten.com Git - openhab-addons.git/commitdiff
[speedtest] Add timestamp and result image channel, update thing description (#15278)
authorMikeTheTux <44850211+MikeTheTux@users.noreply.github.com>
Thu, 19 Oct 2023 20:22:47 +0000 (22:22 +0200)
committerGitHub <noreply@github.com>
Thu, 19 Oct 2023 20:22:47 +0000 (22:22 +0200)
* added timestamp channel, updated thing description
* added resultImage

---------

Signed-off-by: Michael Weger <weger.michael@gmx.net>
bundles/org.openhab.binding.speedtest/README.md
bundles/org.openhab.binding.speedtest/src/main/java/org/openhab/binding/speedtest/internal/SpeedtestBindingConstants.java
bundles/org.openhab.binding.speedtest/src/main/java/org/openhab/binding/speedtest/internal/SpeedtestHandler.java
bundles/org.openhab.binding.speedtest/src/main/java/org/openhab/binding/speedtest/internal/SpeedtestHandlerFactory.java
bundles/org.openhab.binding.speedtest/src/main/resources/OH-INF/i18n/speedtest.properties
bundles/org.openhab.binding.speedtest/src/main/resources/OH-INF/thing/thing-types.xml
bundles/org.openhab.binding.speedtest/src/main/resources/OH-INF/update/instructions.xml [new file with mode: 0644]

index 733cff9e26d3497c687814abdfb0ff692e3b3560..5f84faa23fb6cac5df46f85ce71ff35e8e7af6bd 100644 (file)
@@ -76,6 +76,7 @@ Ensure that the user that openHAB is running with, has the permissions to access
 | Channel               | Type                      | Description                                                       |
 |-----------------------|---------------------------|-------------------------------------------------------------------|
 | `server`              | `String`                  | The remote server that the Speedtest was run against              |
+| `timestamp`           | `DateTime`                | Timestamp of the Speedtest run                                    |
 | `pingJitter`          | `Number:Time`             | Ping Jitter - the variation in the response time                  |
 | `pingLatency`         | `Number:Time`             | Ping Latency - the reaction time of your internet connection      |
 | `downloadBandwidth`   | `Number:DataTransferRate` | Download bandwidth, e.g. in Mbit/s                                |
@@ -88,6 +89,7 @@ Ensure that the user that openHAB is running with, has the permissions to access
 | `interfaceInternalIp` | `String`                  | IP address of the internal interface that was used for the test   |
 | `interfaceExternalIp` | `String`                  | IP address of the external interface that was used for the test   |
 | `resultUrl`           | `String`                  | The URL to the Speedtest results in HTML on the Ookla webserver   |
+| `resultImage`         | `Image `                  | The Speedtest results as image                                    |
 | `triggerTest`         | `Switch`                  | Trigger in order to run Speedtest manually                        |
 
 ## Full Example
@@ -102,6 +104,7 @@ Thing   speedtest:speedtest:myspeedtest   "Ookla Speedtest"    [ execPath="/usr/
 
 ```java
 String                    Speedtest_Server                "Server"                { channel="speedtest:speedtest:myspeedtest:server" }
+DateTime                  Speedtest_Timestamp             "Timestamp"             { channel="speedtest:speedtest:myspeedtest:timestamp" }
 Number:Time               Speedtest_Ping_Jitter           "Ping Jitter"           { channel="speedtest:speedtest:myspeedtest:pingJitter" }
 Number:Time               Speedtest_Ping_Latency          "Ping Latency"          { channel="speedtest:speedtest:myspeedtest:pingLatency" }
 Number:DataTransferRate   Speedtest_Download_Bandwith     "Download Bandwith"     { channel="speedtest:speedtest:myspeedtest:downloadBandwidth" }
@@ -114,5 +117,6 @@ String                    Speedtest_ISP                   "ISP"
 String                    Speedtest_Interface_InternalIP  "Internal IP Address"   { channel="speedtest:speedtest:myspeedtest:interfaceInternalIp" }
 String                    Speedtest_Interface_ExternalIP  "External IP Address"   { channel="speedtest:speedtest:myspeedtest:interfaceExternalIp" }
 String                    Speedtest_ResultURL             "Result URL"            { channel="speedtest:speedtest:myspeedtest:resultUrl" }
+Image                     Speedtest_ResultImage           "Result Image"          { channel="speedtest:speedtest:myspeedtest:resultImage" }
 Switch                    Speedtest_TriggerTest           "Trigger Test"          { channel="speedtest:speedtest:myspeedtest:triggerTest" }
 ```
index cc9a9a364b94f5d8ca94e239437cd84b5825de4b..b365943d9ab3c615590f1b7c13229a429c086770 100644 (file)
@@ -40,6 +40,7 @@ public class SpeedtestBindingConstants {
 
     // Channels
     public static final String SERVER = "server";
+    public static final String TIMESTAMP = "timestamp";
     public static final String PING_JITTER = "pingJitter";
     public static final String PING_LATENCY = "pingLatency";
     public static final String DOWNLOAD_BANDWIDTH = "downloadBandwidth";
@@ -52,6 +53,7 @@ public class SpeedtestBindingConstants {
     public static final String INTERFACE_INTERNALIP = "interfaceInternalIp";
     public static final String INTERFACE_EXTERNALIP = "interfaceExternalIp";
     public static final String RESULT_URL = "resultUrl";
+    public static final String RESULT_IMAGE = "resultImage";
     public static final String TRIGGER_TEST = "triggerTest";
 
     public static final String PROPERTY_SERVER_LIST1 = "Server List 1";
@@ -65,7 +67,7 @@ public class SpeedtestBindingConstants {
     public static final String PROPERTY_SERVER_LIST9 = "Server List 9";
     public static final String PROPERTY_SERVER_LIST10 = "Server List 10";
 
-    public static final Set<String> SUPPORTED_CHANNEL_IDS = Set.of(SERVER, PING_JITTER, PING_LATENCY,
+    public static final Set<String> SUPPORTED_CHANNEL_IDS = Set.of(SERVER, TIMESTAMP, PING_JITTER, PING_LATENCY,
             DOWNLOAD_BANDWIDTH, DOWNLOAD_BYTES, DOWNLOAD_ELAPSED, UPLOAD_BANDWIDTH, UPLOAD_BYTES, UPLOAD_ELAPSED, ISP,
-            INTERFACE_INTERNALIP, INTERFACE_EXTERNALIP, RESULT_URL);
+            INTERFACE_INTERNALIP, INTERFACE_EXTERNALIP, RESULT_URL, RESULT_IMAGE, TRIGGER_TEST);
 }
index 6c43ef3cffaddf7d932a5884a59863c7f9d86292..d87d6fd6c633761f4a21890752d0d738bdcee6ec 100644 (file)
@@ -17,6 +17,8 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeParseException;
 import java.util.Arrays;
 import java.util.Map;
 import java.util.concurrent.ScheduledFuture;
@@ -27,8 +29,12 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.speedtest.internal.dto.ResultContainer;
 import org.openhab.binding.speedtest.internal.dto.ResultsContainerServerList;
+import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.core.io.net.http.HttpUtil;
+import org.openhab.core.library.types.DateTimeType;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.types.RawType;
 import org.openhab.core.library.types.StringType;
 import org.openhab.core.library.unit.Units;
 import org.openhab.core.thing.ChannelUID;
@@ -39,6 +45,7 @@ import org.openhab.core.thing.binding.BaseThingHandler;
 import org.openhab.core.types.Command;
 import org.openhab.core.types.RefreshType;
 import org.openhab.core.types.State;
+import org.openhab.core.types.UnDefType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -58,6 +65,7 @@ public class SpeedtestHandler extends BaseThingHandler {
     private static Runtime rt = Runtime.getRuntime();
     private long pollingInterval = 60;
     private String serverID = "";
+    private final TimeZoneProvider timeZoneProvider;
 
     private @Nullable ScheduledFuture<?> pollingJob;
     public volatile boolean isRunning = false;
@@ -69,19 +77,21 @@ public class SpeedtestHandler extends BaseThingHandler {
     private static volatile OS os = OS.NOT_SET;
     private static final Object LOCK = new Object();
 
-    private String pingJitter = "";
-    private String pingLatency = "";
-    private String downloadBandwidth = "";
-    private String downloadBytes = "";
-    private String downloadElapsed = "";
-    private String uploadBandwidth = "";
-    private String uploadBytes = "";
-    private String uploadElapsed = "";
+    private State pingJitter = UnDefType.NULL;
+    private State pingLatency = UnDefType.NULL;
+    private State downloadBandwidth = UnDefType.NULL;
+    private State downloadBytes = UnDefType.NULL;
+    private State downloadElapsed = UnDefType.NULL;
+    private State uploadBandwidth = UnDefType.NULL;
+    private State uploadBytes = UnDefType.NULL;
+    private State uploadElapsed = UnDefType.NULL;
     private String isp = "";
     private String interfaceInternalIp = "";
     private String interfaceExternalIp = "";
     private String resultUrl = "";
+    private State resultImage = UnDefType.NULL;
     private String server = "";
+    private State timestamp = UnDefType.NULL;
 
     /**
      * Contains information about which operating system openHAB is running on.
@@ -95,8 +105,9 @@ public class SpeedtestHandler extends BaseThingHandler {
         NOT_SET
     }
 
-    public SpeedtestHandler(Thing thing) {
+    public SpeedtestHandler(Thing thing, TimeZoneProvider timeZoneProvider) {
         super(thing);
+        this.timeZoneProvider = timeZoneProvider;
     }
 
     @Override
@@ -286,18 +297,85 @@ public class SpeedtestHandler extends BaseThingHandler {
                 ResultContainer.class);
         if (tmpCont != null) {
             if ("result".equals(tmpCont.getType())) {
-                pingJitter = tmpCont.getPing().getJitter();
-                pingLatency = tmpCont.getPing().getLatency();
-                downloadBandwidth = tmpCont.getDownload().getBandwidth();
-                downloadBytes = tmpCont.getDownload().getBytes();
-                downloadElapsed = tmpCont.getDownload().getElapsed();
-                uploadBandwidth = tmpCont.getUpload().getBandwidth();
-                uploadBytes = tmpCont.getUpload().getBytes();
-                uploadElapsed = tmpCont.getUpload().getElapsed();
+                try {
+                    // timestamp format: "2023-07-20T19:34:54Z"
+                    ZonedDateTime zonedDateTime = ZonedDateTime.parse(tmpCont.getTimestamp())
+                            .withZoneSameInstant(timeZoneProvider.getTimeZone());
+                    timestamp = new DateTimeType(zonedDateTime);
+                } catch (DateTimeParseException e) {
+                    timestamp = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
+                try {
+                    pingJitter = new QuantityType<>(Double.parseDouble(tmpCont.getPing().getJitter()) / 1000.0,
+                            Units.SECOND);
+                } catch (NumberFormatException e) {
+                    pingJitter = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
+                try {
+                    pingLatency = new QuantityType<>(Double.parseDouble(tmpCont.getPing().getLatency()) / 1000.0,
+                            Units.SECOND);
+                } catch (NumberFormatException e) {
+                    pingLatency = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
+                try {
+                    downloadBandwidth = new QuantityType<>(
+                            Double.parseDouble(tmpCont.getDownload().getBandwidth()) / 125000.0,
+                            Units.MEGABIT_PER_SECOND);
+                } catch (NumberFormatException e) {
+                    downloadBandwidth = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
+                try {
+                    downloadBytes = new QuantityType<>(Double.parseDouble(tmpCont.getDownload().getBytes()),
+                            Units.BYTE);
+                } catch (NumberFormatException e) {
+                    downloadBytes = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
+                try {
+                    downloadElapsed = new QuantityType<>(
+                            Double.parseDouble(tmpCont.getDownload().getElapsed()) / 1000.0, Units.SECOND);
+                } catch (NumberFormatException e) {
+                    downloadElapsed = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
+                try {
+                    uploadBandwidth = new QuantityType<>(
+                            Double.parseDouble(tmpCont.getUpload().getBandwidth()) / 125000.0,
+                            Units.MEGABIT_PER_SECOND);
+                } catch (NumberFormatException e) {
+                    uploadBandwidth = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
+                try {
+                    uploadBytes = new QuantityType<>(Double.parseDouble(tmpCont.getUpload().getBytes()), Units.BYTE);
+                } catch (NumberFormatException e) {
+                    uploadBytes = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
+                try {
+                    uploadElapsed = new QuantityType<>(Double.parseDouble(tmpCont.getUpload().getElapsed()) / 1000.0,
+                            Units.SECOND);
+                } catch (NumberFormatException e) {
+                    uploadElapsed = UnDefType.NULL;
+                    logger.debug("Exception: {}", e.getMessage());
+                }
                 isp = tmpCont.getIsp();
                 interfaceInternalIp = tmpCont.getInterface().getInternalIp();
                 interfaceExternalIp = tmpCont.getInterface().getExternalIp();
                 resultUrl = tmpCont.getResult().getUrl();
+                String url = String.valueOf(resultUrl) + ".png";
+                logger.debug("Downloading result image from: {}", url);
+                RawType image = HttpUtil.downloadImage(url);
+                if (image != null) {
+                    resultImage = image;
+                } else {
+                    resultImage = UnDefType.NULL;
+                }
+
                 server = tmpCont.getServer().getName() + " (" + tmpCont.getServer().getId().toString() + ") "
                         + tmpCont.getServer().getLocation();
                 updateChannels();
@@ -332,45 +410,53 @@ public class SpeedtestHandler extends BaseThingHandler {
     private void updateChannels() {
         logger.debug("Updating channels");
 
-        State newState = new QuantityType<>(Double.parseDouble(pingJitter) / 1000.0, Units.SECOND);
-        logger.debug("pingJitter: {}", newState);
-        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.PING_JITTER), newState);
+        logger.debug("timestamp: {}", timestamp);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.TIMESTAMP), timestamp);
 
-        newState = new QuantityType<>(Double.parseDouble(pingLatency) / 1000.0, Units.SECOND);
-        logger.debug("pingLatency: {}", newState);
-        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.PING_LATENCY), newState);
+        logger.debug("pingJitter: {}", pingJitter);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.PING_JITTER), pingJitter);
 
-        newState = new QuantityType<>(Double.parseDouble(downloadBandwidth) / 125000.0, Units.MEGABIT_PER_SECOND);
-        logger.debug("downloadBandwidth: {}", newState);
-        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.DOWNLOAD_BANDWIDTH), newState);
+        logger.debug("pingLatency: {}", pingLatency);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.PING_LATENCY), pingLatency);
 
-        newState = new QuantityType<>(Double.parseDouble(downloadBytes), Units.BYTE);
-        logger.debug("downloadBytes: {}", newState);
-        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.DOWNLOAD_BYTES), newState);
+        logger.debug("downloadBandwidth: {}", downloadBandwidth);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.DOWNLOAD_BANDWIDTH),
+                downloadBandwidth);
 
-        newState = new QuantityType<>(Double.parseDouble(downloadElapsed) / 1000.0, Units.SECOND);
-        logger.debug("downloadElapsed: {}", newState);
-        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.DOWNLOAD_ELAPSED), newState);
+        logger.debug("downloadBytes: {}", downloadBytes);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.DOWNLOAD_BYTES), downloadBytes);
 
-        newState = new QuantityType<>(Double.parseDouble(uploadBandwidth) / 125000.0, Units.MEGABIT_PER_SECOND);
-        logger.debug("uploadBandwidth: {}", newState);
-        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.UPLOAD_BANDWIDTH), newState);
+        logger.debug("downloadElapsed: {}", downloadElapsed);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.DOWNLOAD_ELAPSED), downloadElapsed);
 
-        newState = new QuantityType<>(Double.parseDouble(uploadBytes), Units.BYTE);
-        logger.debug("uploadBytes: {}", newState);
-        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.UPLOAD_BYTES), newState);
+        logger.debug("uploadBandwidth: {}", uploadBandwidth);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.UPLOAD_BANDWIDTH), uploadBandwidth);
 
-        newState = new QuantityType<>(Double.parseDouble(uploadElapsed) / 1000.0, Units.SECOND);
-        logger.debug("uploadElapsed: {}", newState);
-        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.UPLOAD_ELAPSED), newState);
+        logger.debug("uploadBytes: {}", uploadBytes);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.UPLOAD_BYTES), uploadBytes);
 
+        logger.debug("uploadElapsed: {}", uploadElapsed);
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.UPLOAD_ELAPSED), uploadElapsed);
+
+        logger.debug("interfaceExternalIp: {}", interfaceExternalIp);
         updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.INTERFACE_EXTERNALIP),
                 new StringType(interfaceExternalIp));
+
+        logger.debug("interfaceInternalIp: {}", interfaceInternalIp);
         updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.INTERFACE_INTERNALIP),
                 new StringType(interfaceInternalIp));
+
+        logger.debug("isp: {}", isp);
         updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.ISP), new StringType(isp));
+
+        logger.debug("resultUrl: {}", resultUrl);
         updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.RESULT_URL),
                 new StringType(resultUrl));
+
+        logger.debug("resultImage: <RawType>");
+        updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.RESULT_IMAGE), resultImage);
+
+        logger.debug("server: {}", server);
         updateState(new ChannelUID(getThing().getUID(), SpeedtestBindingConstants.SERVER), new StringType(server));
     }
 
index 87024fe7f4cd690d4255b2d7a34f83016ee97ba5..388461c9b9e06e3eb958c6d1336c798d53863352 100644 (file)
@@ -19,12 +19,15 @@ import java.util.Set;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.i18n.TimeZoneProvider;
 import org.openhab.core.thing.Thing;
 import org.openhab.core.thing.ThingTypeUID;
 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
 import org.openhab.core.thing.binding.ThingHandler;
 import org.openhab.core.thing.binding.ThingHandlerFactory;
+import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
 
 /**
  * The {@link SpeedtestHandlerFactory} is responsible for creating things and thing
@@ -37,6 +40,12 @@ import org.osgi.service.component.annotations.Component;
 public class SpeedtestHandlerFactory extends BaseThingHandlerFactory {
 
     private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_SPEEDTEST);
+    private final TimeZoneProvider timeZoneProvider;
+
+    @Activate
+    public SpeedtestHandlerFactory(final @Reference TimeZoneProvider timeZoneProvider) {
+        this.timeZoneProvider = timeZoneProvider;
+    }
 
     @Override
     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
@@ -48,7 +57,7 @@ public class SpeedtestHandlerFactory extends BaseThingHandlerFactory {
         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
 
         if (THING_TYPE_SPEEDTEST.equals(thingTypeUID)) {
-            return new SpeedtestHandler(thing);
+            return new SpeedtestHandler(thing, timeZoneProvider);
         }
 
         return null;
index 4ab1de8187886e28db4f2f2a0c3f1a39a3e50ee7..03d72a3bf0c29dc45c1b5cb2944af0687c8b2652 100644 (file)
@@ -5,8 +5,8 @@ addon.speedtest.description = Binding for Ookla Speedtest (https://www.speedtest
 
 # thing types
 
-thing-type.speedtest.speedtest.label = Speedtest Binding
-thing-type.speedtest.speedtest.description = Binding for Ookla Speedtest (https://www.speedtest.net/)
+thing-type.speedtest.speedtest.label = Ookla Speedtest
+thing-type.speedtest.speedtest.description = Ookla Speedtest (https://www.speedtest.net/)
 
 # thing types config
 
@@ -43,10 +43,14 @@ channel-type.speedtest.pingJitter.label = Ping Jitter
 channel-type.speedtest.pingJitter.description = Ping Jitter - the variation in the response time
 channel-type.speedtest.pingLatency.label = Ping Latency
 channel-type.speedtest.pingLatency.description = Ping Latency - the reaction time of your internet connection
+channel-type.speedtest.resultImage.label = Result Image
+channel-type.speedtest.resultImage.description = The Speedtest results as image
 channel-type.speedtest.resultUrl.label = Result URL
 channel-type.speedtest.resultUrl.description = The URL to the Speedtest results in HTML on the Ookla webserver
 channel-type.speedtest.server.label = Server
 channel-type.speedtest.server.description = The remote server that the Speedtest was run against
+channel-type.speedtest.timestamp.label = Timestamp
+channel-type.speedtest.timestamp.description = Timestamp of the Speedtest run
 channel-type.speedtest.triggerTest.label = Trigger Test
 channel-type.speedtest.triggerTest.description = Trigger in order to run Speedtest manually
 channel-type.speedtest.uploadBandwidth.label = Upload Bandwidth
index bf2162555ab3ae9a08cd8f7af8d965f2032e3a72..8c09222917a50b3e54b854d5b591e23028474550 100644 (file)
@@ -5,10 +5,11 @@
        xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
 
        <thing-type id="speedtest">
-               <label>Speedtest Binding</label>
-               <description>Binding for Ookla Speedtest (https://www.speedtest.net/)</description>
+               <label>Ookla Speedtest</label>
+               <description>Ookla Speedtest (https://www.speedtest.net/)</description>
                <channels>
                        <channel id="server" typeId="server"/>
+                       <channel id="timestamp" typeId="timestamp"/>
 
                        <channel id="pingJitter" typeId="pingJitter"/>
                        <channel id="pingLatency" typeId="pingLatency"/>
@@ -27,6 +28,7 @@
                        <channel id="interfaceExternalIp" typeId="interfaceExternalIp"/>
 
                        <channel id="resultUrl" typeId="resultUrl"/>
+                       <channel id="resultImage" typeId="resultImage"/>
 
                        <channel id="triggerTest" typeId="triggerTest"/>
                </channels>
@@ -41,6 +43,7 @@
                        <property name="Server List 8"></property>
                        <property name="Server List 9"></property>
                        <property name="Server List 10"></property>
+                       <property name="thingTypeVersion">1</property>
                </properties>
                <config-description>
                        <parameter-group name="config-info">
                <description>The remote server that the Speedtest was run against</description>
                <state readOnly="true"></state>
        </channel-type>
+       <channel-type id="timestamp" advanced="true">
+               <item-type>DateTime</item-type>
+               <label>Timestamp</label>
+               <description>Timestamp of the Speedtest run</description>
+               <state readOnly="true" pattern="%1$tF %1$tH:%1$tM:%1$tS"></state>
+       </channel-type>
        <channel-type id="pingJitter" advanced="true">
                <item-type>Number:Time</item-type>
                <label>Ping Jitter</label>
                <description>The URL to the Speedtest results in HTML on the Ookla webserver</description>
                <state readOnly="true"></state>
        </channel-type>
+       <channel-type id="resultImage">
+               <item-type>Image</item-type>
+               <label>Result Image</label>
+               <description>The Speedtest results as image</description>
+               <state readOnly="true"></state>
+       </channel-type>
        <channel-type id="triggerTest" advanced="true">
                <item-type>Switch</item-type>
                <label>Trigger Test</label>
diff --git a/bundles/org.openhab.binding.speedtest/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.speedtest/src/main/resources/OH-INF/update/instructions.xml
new file mode 100644 (file)
index 0000000..0e105de
--- /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="speedtest:speedtest">
+               <instruction-set targetVersion="1">
+                       <add-channel id="timestamp">
+                               <type>speedtest:timestamp</type>
+                       </add-channel>
+                       <add-channel id="resultImage">
+                               <type>speedtest:resultImage</type>
+                       </add-channel>
+               </instruction-set>
+       </thing-type>
+
+</update:update-descriptions>