]> git.basschouten.com Git - openhab-addons.git/commitdiff
[radiothermostat] Add job to set thermostat clock automatically from the binding...
authormlobstein <michael.lobstein@gmail.com>
Mon, 7 Jun 2021 18:58:19 +0000 (13:58 -0500)
committerGitHub <noreply@github.com>
Mon, 7 Jun 2021 18:58:19 +0000 (20:58 +0200)
* add thermostat clock sync job

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
bundles/org.openhab.binding.radiothermostat/README.md
bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/RadioThermostatBindingConstants.java
bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/RadioThermostatConfiguration.java
bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/handler/RadioThermostatHandler.java
bundles/org.openhab.binding.radiothermostat/src/main/resources/OH-INF/thing/thing-types.xml

index e5244c0de7aca9a712cbc8c4a21e992bba1b9475..0babb2ce3e39ee0b14510348b1b84cfc4611fec3 100644 (file)
@@ -42,6 +42,7 @@ The thing has a few configuration parameters:
 | isCT80          | Flag to enable additional features only available on the CT80 thermostat. Optional, the default is false.                                                                                                                                                       |
 | disableLogs     | Disable retrieval of run-time logs from the thermostat. Optional, the default is false.                                                                                                                                                                         |
 | setpointMode    | Controls temporary or absolute setpoint mode. In "temporary" mode the thermostat will temporarily maintain the given setpoint, returning to its program after a time. In "absolute" mode the thermostat will ignore its program maintaining the given setpoint. |
+| clockSync       | Flag to enable the binding to sync the internal clock on the thermostat to match the openHAB host's system clock. Use if the thermostat is not setup to connect to the manufacturer's cloud server. Sync occurs at binding startup and every hour thereafter.   |
 
 ## Channels
 
index daf02d99e749f212dd335ca7a73edf5064b66a2e..8566bab20043e3c68f0339faab03cfc7220d6880 100644 (file)
@@ -40,6 +40,7 @@ public class RadioThermostatBindingConstants {
     public static final String LOCAL = "local";
     public static final String PROPERTY_IP = "hostName";
     public static final String PROPERTY_ISCT80 = "isCT80";
+    public static final String JSON_TIME = "{\"day\":%s,\"hour\":%s,\"minute\":%s}";
 
     public static final String KEY_ERROR = "error";
 
@@ -48,6 +49,7 @@ public class RadioThermostatBindingConstants {
     public static final String RUNTIME_RESOURCE = "tstat/datalog";
     public static final String HUMIDITY_RESOURCE = "tstat/humidity";
     public static final String REMOTE_TEMP_RESOURCE = "tstat/remote_temp";
+    public static final String TIME_RESOURCE = "tstat/time";
 
     // List of all Thing Type UIDs
     public static final ThingTypeUID THING_TYPE_RTHERM = new ThingTypeUID(BINDING_ID, "rtherm");
index 9269991217ea4b728d2bc7f7d64258ae51626984..203fccb2b22e4c5859d97b18d7c268e45ca9359b 100644 (file)
@@ -28,5 +28,6 @@ public class RadioThermostatConfiguration {
     public @Nullable Integer logRefresh;
     public boolean isCT80 = false;
     public boolean disableLogs = false;
+    public boolean clockSync = false;
     public String setpointMode = "temporary";
 }
index 6ab451829938d778aa2842487f5d1d34736f365c..698efe76ef8fc6cdebf428ae01eedbdaa46e861f 100644 (file)
@@ -19,6 +19,7 @@ import java.text.NumberFormat;
 import java.text.ParseException;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -86,11 +87,13 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
 
     private @Nullable ScheduledFuture<?> refreshJob;
     private @Nullable ScheduledFuture<?> logRefreshJob;
+    private @Nullable ScheduledFuture<?> clockSyncJob;
 
     private int refreshPeriod = DEFAULT_REFRESH_PERIOD;
     private int logRefreshPeriod = DEFAULT_LOG_REFRESH_PERIOD;
     private boolean isCT80 = false;
     private boolean disableLogs = false;
+    private boolean clockSync = false;
     private String setpointCmdKeyPrefix = "t_";
 
     public RadioThermostatHandler(Thing thing, RadioThermostatStateDescriptionProvider stateDescriptionProvider,
@@ -111,8 +114,9 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
         final Integer logRefresh = config.logRefresh;
         this.isCT80 = config.isCT80;
         this.disableLogs = config.disableLogs;
+        this.clockSync = config.clockSync;
 
-        if (hostName == null || hostName.equals("")) {
+        if (hostName == null || "".equals(hostName)) {
             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
                     "Thermostat Host Name must be specified");
             return;
@@ -145,12 +149,18 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
             channels.removeIf(c -> (c.getUID().getId().equals(PROGRAM_MODE)));
             updateThing(editThing().withChannels(channels).build());
         }
+
+        updateStatus(ThingStatus.UNKNOWN);
+
         startAutomaticRefresh();
+
         if (!this.disableLogs || this.isCT80) {
             startAutomaticLogRefresh();
         }
 
-        updateStatus(ThingStatus.UNKNOWN);
+        if (this.clockSync) {
+            scheduleClockSyncJob();
+        }
     }
 
     @Override
@@ -174,6 +184,35 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
         }
     }
 
+    /**
+     * Schedule the clock sync job
+     */
+    private void scheduleClockSyncJob() {
+        ScheduledFuture<?> clockSyncJob = this.clockSyncJob;
+        if (clockSyncJob == null || clockSyncJob.isCancelled()) {
+            clockSyncJob = null;
+            this.clockSyncJob = scheduler.scheduleWithFixedDelay(this::syncThermostatClock, 1, 60, TimeUnit.MINUTES);
+        }
+    }
+
+    /**
+     * Sync the thermostat's clock with the host system clock
+     */
+    private void syncThermostatClock() {
+        Calendar c = Calendar.getInstance();
+
+        // The thermostat week starts as Monday = 0, subtract 2 since in standard DoW Monday = 2
+        int thermDayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 2;
+        // Sunday will be -1, so add 7 to make it 6
+        if (thermDayOfWeek < 0) {
+            thermDayOfWeek += 7;
+        }
+
+        connector.sendCommand(null, null,
+                String.format(JSON_TIME, thermDayOfWeek, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE)),
+                TIME_RESOURCE);
+    }
+
     /**
      * Start the job to periodically update humidity and runtime date from the thermostat
      */
@@ -214,6 +253,12 @@ public class RadioThermostatHandler extends BaseThingHandler implements RadioThe
             logRefreshJob.cancel(true);
             this.logRefreshJob = null;
         }
+
+        ScheduledFuture<?> clockSyncJob = this.clockSyncJob;
+        if (clockSyncJob != null) {
+            clockSyncJob.cancel(true);
+            this.clockSyncJob = null;
+        }
     }
 
     public void handleRawCommand(@Nullable String rawCommand) {
index a33622dbdc557e38347178f0c9a03aa198ee93bd..247f643c04e268e7ac24537c65cebef4e3903486 100644 (file)
                                        <option value="temporary">Temporary</option>
                                </options>
                        </parameter>
-
+                       <parameter name="clockSync" type="boolean">
+                               <label>Enable Thermostat Clock Sync</label>
+                               <description>Optional Flag to snyc the thermostat's clock with the host system clock</description>
+                               <default>false</default>
+                       </parameter>
                </config-description>
        </thing-type>