]> git.basschouten.com Git - openhab-addons.git/commitdiff
[OmniLink] Fix daylight savings when setting date/time (#12546)
authorEthan Dye <mrtops03@gmail.com>
Mon, 18 Apr 2022 20:07:58 +0000 (14:07 -0600)
committerGitHub <noreply@github.com>
Mon, 18 Apr 2022 20:07:58 +0000 (22:07 +0200)
* Fix daylight savings when setting date/time
* Use an action to set date/time
* Add default time zone detection and i18n

Signed-off-by: Ethan Dye <mrtops03@gmail.com>
bundles/org.openhab.binding.omnilink/README.md
bundles/org.openhab.binding.omnilink/src/main/java/org/openhab/binding/omnilink/internal/OmnilinkHandlerFactory.java
bundles/org.openhab.binding.omnilink/src/main/java/org/openhab/binding/omnilink/internal/action/OmnilinkActions.java [new file with mode: 0644]
bundles/org.openhab.binding.omnilink/src/main/java/org/openhab/binding/omnilink/internal/handler/OmnilinkBridgeHandler.java
bundles/org.openhab.binding.omnilink/src/main/resources/OH-INF/i18n/omnilink.properties
bundles/org.openhab.binding.omnilink/src/main/resources/OH-INF/thing/bridge.xml

index 3a74f665ff8e63eb7a261ae512231843da230fe3..cdced42aabd7f9e4d7bdad4b944ff3810d9bbb8c 100644 (file)
@@ -8,7 +8,6 @@ It connects to many other devices through serial ports or wired contacts and exp
 
 The OmniPro/Lumina controller acts as a "bridge" for accessing other connected devices.
 
-
 | Omni type                  | Hardware Type                                    | Things                            |
 |:---------------------------|:-------------------------------------------------|:----------------------------------|
 | Controller                 | Omni (Pro II, IIe, LTe), Lumina                  | `controller` (omni, lumina)       |
@@ -26,7 +25,6 @@ The OmniPro/Lumina controller acts as a "bridge" for accessing other connected d
 | Access Control Reader Lock | Leviton Access Control Reader                    | `lock`                            |
 
 
-
 ## Discovery
 
 ### Controller
@@ -56,77 +54,76 @@ The devices are identified by the device number that the OmniLink bridge assigns
 
 The devices support some of the following channels:
 
-| Channel Type ID             | Item Type            | Description                                                                          | Thing types supporting this channel                 |
-|-----------------------------|----------------------|--------------------------------------------------------------------------------------|-----------------------------------------------------|
-| `activate_keypad_emergency` | Number               | Activate a burglary, fire, or auxiliary keypad emergency alarm on Omni based models. | `area`                                              |
-| `alarm_burglary`            | Switch               | Indicates if a burglary alarm is active.                                             | `area`                                              |
-| `alarm_fire`                | Switch               | Indicates if a fire alarm is active.                                                 | `area`                                              |
-| `alarm_gas`                 | Switch               | Indicates if a gas alarm is active.                                                  | `area`                                              |
-| `alarm_auxiliary`           | Switch               | Indicates if a auxiliary alarm is active.                                            | `area`                                              |
-| `alarm_freeze`              | Switch               | Indicates if a freeze alarm is active.                                               | `area`                                              |
-| `alarm_water`               | Switch               | Indicates if a water alarm is active.                                                | `area`                                              |
-| `alarm_duress`              | Switch               | Indicates if a duress alarm is active.                                               | `area`                                              |
-| `alarm_temperature`         | Switch               | Indicates if a temperature alarm is active.                                          | `area`                                              |
-| `mode`                      | Number               | Represents the area security mode.                                                   | `area`, `lumina_area`                               |
-| `disarm`                    | String               | Send a 4 digit user code to disarm the system.                                       | `area`                                              |
-| `day`                       | String               | Send a 4 digit user code to arm the system to day.                                   | `area`                                              |
-| `night`                     | String               | Send a 4 digit user code to arm the system to night.                                 | `area`                                              |
-| `away`                      | String               | Send a 4 digit user code to arm the system to away.                                  | `area`                                              |
-| `vacation`                  | String               | Send a 4 digit user code to arm the system to vacation.                              | `area`                                              |
-| `day_instant`               | String               | Send a 4 digit user code to arm the system to day instant.                           | `area`                                              |
-| `night_delayed`             | String               | Send a 4 digit user code to arm the system to night delayed.                         | `area`                                              |
-| `home`                      | String               | Send a 4 digit user code to set the system to home.                                  | `lumina_area`                                       |
-| `sleep`                     | String               | Send a 4 digit user code to set the system to sleep.                                 | `lumina_area`                                       |
-| `away`                      | String               | Send a 4 digit user code to set the system to away.                                  | `lumina_area`                                       |
-| `vacation`                  | String               | Send a 4 digit user code to set the system to vacation.                              | `lumina_area`                                       |
-| `party`                     | String               | Send a 4 digit user code to set the system to party.                                 | `lumina_area`                                       |
-| `special`                   | String               | Send a 4 digit user code to set the system to special.                               | `lumina_area`                                       |
-| `source_text_{1,2,3,4,5,6}` | String               | A line of metadata from this audio source.                                           | `audio_source`                                      |
-| `polling`                   | Switch               | Enable or disable polling of this audio source.                                      | `audio_source`                                      |
-| `zone_power`                | Switch               | Power status of this audio zone.                                                     | `audio_zone`                                        |
-| `zone_mute`                 | Switch               | Mute status of this audio zone.                                                      | `audio_zone`                                        |
-| `zone_volume`               | Dimmer               | Volume level of this audio zone.                                                     | `audio_zone`                                        |
-| `zone_source`               | Number               | Source for this audio zone.                                                          | `audio_zone`                                        |
-| `zone_control`              | Player               | Control the audio zone, e.g. start/stop/next/previous.                               | `audio_zone`                                        |
-| `system_date`               | DateTime             | Set controller date/time.                                                            | `controller`                                        |
-| `last_log`                  | String               | Last log message on the controller, represented in JSON.                             | `controller`                                        |
-| `enable_disable_beeper`     | Switch               | Enable/Disable the beeper for this/all console(s).                                   | `controller`, `console`                             |
-| `beep`                      | Switch               | Send a beep command to this/all console(s).                                          | `controller`, `console`                             |
-| `press`                     | Switch               | Sends a button event to the controller.                                              | `button`                                            |
-| `low_setpoint`              | Number               | The current low setpoint for this humidity/temperature sensor.                       | `temp_sensor`, `humidity_sensor`                    |
-| `high_setpoint`             | Number               | The current high setpoint for this humidity/temperature sensor.                      | `temp_sensor`, `humidity_sensor`                    |
-| `temperature`               | Number:Temperature   | The current temperature at this thermostat/temperature sensor.                       | `thermostat`, `temp_sensor`                         |
-| `humidity`                  | Number:Dimensionless | The current relative humidity at this thermostat/humidity sensor.                    | `thermostat`, `humidity_sensor`                     |
-| `freeze_alarm`              | Contact              | Closed when freeze alarm is triggered by this thermostat.                            | `thermostat`                                        |
-| `comm_failure`              | Contact              | Closed during a communications failure with this thermostat.                         | `thermostat`                                        |
-| `outdoor_temperature`       | Number:Temperature   | The current outdoor temperature detected by this thermostat.                         | `thermostat`                                        |
-| `heat_setpoint`             | Number:Temperature   | The current low/heating setpoint of this thermostat.                                 | `thermostat`                                        |
-| `cool_setpoint`             | Number:Temperature   | The current high/cooling setpoint of this thermostat.                                | `thermostat`                                        |
-| `humidify_setpoint`         | Number:Dimensionless | The current low/humidify setpoint for this thermostat.                               | `thermostat`                                        |
-| `dehumidify_setpoint`       | Number:Dimensionless | The current high/dehumidify setpoint for this thermostat.                            | `thermostat`                                        |
-| `system_mode`               | Number               | The current system mode of this thermostat.                                          | `thermostat`                                        |
-| `fan_mode`                  | Number               | The current fan mode of this thermostat.                                             | `thermostat`                                        |
-| `hold_status`               | Number               | The current hold status of this thermostat.                                          | `thermostat`                                        |
-| `status`                    | Number               | The current numeric status of this thermostat.                                       | `thermostat`                                        |
-| `level`                     | Dimmer               | Increase/Decrease the level of this unit/dimmable unit/UPB unit.                     | `unit`, `dimmable`, `upb`                           |
-| `switch`                    | Switch               | Turn this unit/dimmable unit/flag/output/room on/off.                                | `unit`, `dimmable`, `upb`, `flag`, `output`, `room` |
-| `on_for_seconds`            | Number               | Turn on this unit for a specified number of seconds.                                 | `unit`, `dimmable`, `upb`, `flag`, `output`         |
-| `off_for_seconds`           | Number               | Turn off this unit for a specified number of seconds.                                | `unit`, `dimmable`, `upb`, `flag`, `output`         |
-| `on_for_minutes`            | Number               | Turn on this unit for a specified number of minutes.                                 | `unit`, `dimmable`, `upb`, `flag`, `output`         |
-| `off_for_minutes`           | Number               | Turn off this unit for a specified number of minutes.                                | `unit`, `dimmable`, `upb`, `flag`, `output`         |
-| `on_for_hours`              | Number               | Turn on this unit for a specified number of hours.                                   | `unit`, `dimmable`, `upb`, `flag`, `output`         |
-| `off_for_hours`             | Number               | Turn off this unit for a specified number of hours.                                  | `unit`, `dimmable`, `upb`, `flag`, `output`         |
-| `upb_status`                | String               | Send a UPB status request message for this UPB unit to the controller.               | `upb`                                               |
-| `value`                     | Number               | Numeric value of this flag.                                                          | `flag`                                              |
-| `scene_{a,b,c,d}`           | Switch               | Turn this scene on/off.                                                              | `room`                                              |
-| `state`                     | Number               | The current state of this room.                                                      | `room`                                              |
-| `contact`                   | Contact              | Contact state information of this zone.                                              | `zone`                                              |
-| `current_condition`         | Number               | Current condition of this zone.                                                      | `zone`                                              |
-| `latched_alarm_status`      | Number               | Latched alarm status of this zone.                                                   | `zone`                                              |
-| `arming_status`             | Number               | Arming status of this zone.                                                          | `zone`                                              |
-| `bypass`                    | String               | Send a 4 digit user code to bypass this zone.                                        | `zone`                                              |
-| `restore`                   | String               | Send a 4 digit user code to restore this zone.                                       | `zone`                                              |
-
+| Channel Type ID             | Item Type            | Description                                                                                  | Thing types supporting this channel                 |
+|-----------------------------|----------------------|----------------------------------------------------------------------------------------------|-----------------------------------------------------|
+| `activate_keypad_emergency` | Number               | Activate a burglary, fire, or auxiliary keypad emergency alarm on Omni based models.         | `area`                                              |
+| `alarm_burglary`            | Switch               | Indicates if a burglary alarm is active.                                                     | `area`                                              |
+| `alarm_fire`                | Switch               | Indicates if a fire alarm is active.                                                         | `area`                                              |
+| `alarm_gas`                 | Switch               | Indicates if a gas alarm is active.                                                          | `area`                                              |
+| `alarm_auxiliary`           | Switch               | Indicates if a auxiliary alarm is active.                                                    | `area`                                              |
+| `alarm_freeze`              | Switch               | Indicates if a freeze alarm is active.                                                       | `area`                                              |
+| `alarm_water`               | Switch               | Indicates if a water alarm is active.                                                        | `area`                                              |
+| `alarm_duress`              | Switch               | Indicates if a duress alarm is active.                                                       | `area`                                              |
+| `alarm_temperature`         | Switch               | Indicates if a temperature alarm is active.                                                  | `area`                                              |
+| `mode`                      | Number               | Represents the area security mode.                                                           | `area`, `lumina_area`                               |
+| `disarm`                    | String               | Send a 4 digit user code to disarm the system.                                               | `area`                                              |
+| `day`                       | String               | Send a 4 digit user code to arm the system to day.                                           | `area`                                              |
+| `night`                     | String               | Send a 4 digit user code to arm the system to night.                                         | `area`                                              |
+| `away`                      | String               | Send a 4 digit user code to arm the system to away.                                          | `area`                                              |
+| `vacation`                  | String               | Send a 4 digit user code to arm the system to vacation.                                      | `area`                                              |
+| `day_instant`               | String               | Send a 4 digit user code to arm the system to day instant.                                   | `area`                                              |
+| `night_delayed`             | String               | Send a 4 digit user code to arm the system to night delayed.                                 | `area`                                              |
+| `home`                      | String               | Send a 4 digit user code to set the system to home.                                          | `lumina_area`                                       |
+| `sleep`                     | String               | Send a 4 digit user code to set the system to sleep.                                         | `lumina_area`                                       |
+| `away`                      | String               | Send a 4 digit user code to set the system to away.                                          | `lumina_area`                                       |
+| `vacation`                  | String               | Send a 4 digit user code to set the system to vacation.                                      | `lumina_area`                                       |
+| `party`                     | String               | Send a 4 digit user code to set the system to party.                                         | `lumina_area`                                       |
+| `special`                   | String               | Send a 4 digit user code to set the system to special.                                       | `lumina_area`                                       |
+| `source_text_{1,2,3,4,5,6}` | String               | A line of metadata from this audio source.                                                   | `audio_source`                                      |
+| `polling`                   | Switch               | Enable or disable polling of this audio source.                                              | `audio_source`                                      |
+| `zone_power`                | Switch               | Power status of this audio zone.                                                             | `audio_zone`                                        |
+| `zone_mute`                 | Switch               | Mute status of this audio zone.                                                              | `audio_zone`                                        |
+| `zone_volume`               | Dimmer               | Volume level of this audio zone.                                                             | `audio_zone`                                        |
+| `zone_source`               | Number               | Source for this audio zone.                                                                  | `audio_zone`                                        |
+| `zone_control`              | Player               | Control the audio zone, e.g. start/stop/next/previous.                                       | `audio_zone`                                        |
+| `system_date`               | DateTime             | Controller date/time. See [Rule Actions](#rule-actions) for how to set controller date/time. | `controller`                                        |
+| `last_log`                  | String               | Last log message on the controller, represented in JSON.                                     | `controller`                                        |
+| `enable_disable_beeper`     | Switch               | Enable/Disable the beeper for this/all console(s).                                           | `controller`, `console`                             |
+| `beep`                      | Switch               | Send a beep command to this/all console(s).                                                  | `controller`, `console`                             |
+| `press`                     | Switch               | Sends a button event to the controller.                                                      | `button`                                            |
+| `low_setpoint`              | Number               | The current low setpoint for this humidity/temperature sensor.                               | `temp_sensor`, `humidity_sensor`                    |
+| `high_setpoint`             | Number               | The current high setpoint for this humidity/temperature sensor.                              | `temp_sensor`, `humidity_sensor`                    |
+| `temperature`               | Number:Temperature   | The current temperature at this thermostat/temperature sensor.                               | `thermostat`, `temp_sensor`                         |
+| `humidity`                  | Number:Dimensionless | The current relative humidity at this thermostat/humidity sensor.                            | `thermostat`, `humidity_sensor`                     |
+| `freeze_alarm`              | Contact              | Closed when freeze alarm is triggered by this thermostat.                                    | `thermostat`                                        |
+| `comm_failure`              | Contact              | Closed during a communications failure with this thermostat.                                 | `thermostat`                                        |
+| `outdoor_temperature`       | Number:Temperature   | The current outdoor temperature detected by this thermostat.                                 | `thermostat`                                        |
+| `heat_setpoint`             | Number:Temperature   | The current low/heating setpoint of this thermostat.                                         | `thermostat`                                        |
+| `cool_setpoint`             | Number:Temperature   | The current high/cooling setpoint of this thermostat.                                        | `thermostat`                                        |
+| `humidify_setpoint`         | Number:Dimensionless | The current low/humidify setpoint for this thermostat.                                       | `thermostat`                                        |
+| `dehumidify_setpoint`       | Number:Dimensionless | The current high/dehumidify setpoint for this thermostat.                                    | `thermostat`                                        |
+| `system_mode`               | Number               | The current system mode of this thermostat.                                                  | `thermostat`                                        |
+| `fan_mode`                  | Number               | The current fan mode of this thermostat.                                                     | `thermostat`                                        |
+| `hold_status`               | Number               | The current hold status of this thermostat.                                                  | `thermostat`                                        |
+| `status`                    | Number               | The current numeric status of this thermostat.                                               | `thermostat`                                        |
+| `level`                     | Dimmer               | Increase/Decrease the level of this unit/dimmable unit/UPB unit.                             | `unit`, `dimmable`, `upb`                           |
+| `switch`                    | Switch               | Turn this unit/dimmable unit/flag/output/room on/off.                                        | `unit`, `dimmable`, `upb`, `flag`, `output`, `room` |
+| `on_for_seconds`            | Number               | Turn on this unit for a specified number of seconds.                                         | `unit`, `dimmable`, `upb`, `flag`, `output`         |
+| `off_for_seconds`           | Number               | Turn off this unit for a specified number of seconds.                                        | `unit`, `dimmable`, `upb`, `flag`, `output`         |
+| `on_for_minutes`            | Number               | Turn on this unit for a specified number of minutes.                                         | `unit`, `dimmable`, `upb`, `flag`, `output`         |
+| `off_for_minutes`           | Number               | Turn off this unit for a specified number of minutes.                                        | `unit`, `dimmable`, `upb`, `flag`, `output`         |
+| `on_for_hours`              | Number               | Turn on this unit for a specified number of hours.                                           | `unit`, `dimmable`, `upb`, `flag`, `output`         |
+| `off_for_hours`             | Number               | Turn off this unit for a specified number of hours.                                          | `unit`, `dimmable`, `upb`, `flag`, `output`         |
+| `upb_status`                | String               | Send a UPB status request message for this UPB unit to the controller.                       | `upb`                                               |
+| `value`                     | Number               | Numeric value of this flag.                                                                  | `flag`                                              |
+| `scene_{a,b,c,d}`           | Switch               | Turn this scene on/off.                                                                      | `room`                                              |
+| `state`                     | Number               | The current state of this room.                                                              | `room`                                              |
+| `contact`                   | Contact              | Contact state information of this zone.                                                      | `zone`                                              |
+| `current_condition`         | Number               | Current condition of this zone.                                                              | `zone`                                              |
+| `latched_alarm_status`      | Number               | Latched alarm status of this zone.                                                           | `zone`                                              |
+| `arming_status`             | Number               | Arming status of this zone.                                                                  | `zone`                                              |
+| `bypass`                    | String               | Send a 4 digit user code to bypass this zone.                                                | `zone`                                              |
+| `restore`                   | String               | Send a 4 digit user code to restore this zone.                                               | `zone`                                              |
 
 ### Trigger Channels
 
@@ -146,6 +143,55 @@ The devices support some of the following trigger channels:
 | `activated_event`             | Event sent when a button is activated.                                               | `button`                            |
 | `switch_press_event`          | Event sent when an ALC, UPB, Radio RA, or Starlite switch is pressed.                | `dimmable`, `upb`                   |
 
+## Rule Actions
+
+This binding includes a rule action, which allows synchronizing the controller time to match the openHAB system time with a user specified zone.
+There is a separate instance for each contoller, which can be retrieved through:
+
+:::: tabs
+
+::: tab JavaScript
+
+``` javascript
+var omnilinkActions = actions.get("omnilink", "omnilink:controller:home");
+```
+
+:::
+
+::: tab DSL
+
+``` php
+val omnilinkActions = getActions("omnilink", "omnilink:controller:home")
+
+```
+
+:::
+
+::::
+
+where the first parameter always has to be `omnilink` and the second is the full Thing UID of the controller that should be used.
+Once this action instance is retrieved, you can invoke the `synchronizeControllerTime(String zone)` method on it:
+
+:::: tabs
+
+::: tab JavaScript
+
+``` javascript
+omnilinkAction.synchronizeControllerTime("America/Denver");
+```
+
+:::
+
+::: tab DSL
+
+``` php
+omnilinkAction.synchronizeControllerTime("America/Denver")
+
+```
+
+:::
+
+::::
 
 ## Full Example
 
@@ -308,14 +354,3 @@ DateTime   OmniProTime   "Last Time Update [%1$ta %1$tR]"   <time>   {channel="o
 14=Arming night delay
 =Unknown
 ```
-
-### Example `omnilink.rules`
-
-```
-rule "Update OmniPro Time"
-when
-  Time cron "0 0 0/1 1/1 * ? *"
-then
-  OmniProTime.sendCommand( new DateTimeType() )
-end
-```
index ba766bedf18fed5660c08b99cf2a0e4d0195f03c..6510d228ca1cd8436ce2f03f0185135e4c37a1da 100644 (file)
@@ -16,6 +16,7 @@ import static org.openhab.binding.omnilink.internal.OmnilinkBindingConstants.*;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.omnilink.internal.action.OmnilinkActions;
 import org.openhab.binding.omnilink.internal.handler.AudioSourceHandler;
 import org.openhab.binding.omnilink.internal.handler.AudioZoneHandler;
 import org.openhab.binding.omnilink.internal.handler.ButtonHandler;
@@ -34,13 +35,16 @@ import org.openhab.binding.omnilink.internal.handler.units.FlagHandler;
 import org.openhab.binding.omnilink.internal.handler.units.OutputHandler;
 import org.openhab.binding.omnilink.internal.handler.units.UpbRoomHandler;
 import org.openhab.binding.omnilink.internal.handler.units.dimmable.UpbUnitHandler;
+import org.openhab.core.i18n.TimeZoneProvider;
 import org.openhab.core.thing.Bridge;
 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 OmnilinkHandlerFactory} is responsible for creating things and thing
@@ -53,6 +57,11 @@ import org.osgi.service.component.annotations.Component;
 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.omnilink")
 public class OmnilinkHandlerFactory extends BaseThingHandlerFactory {
 
+    @Activate
+    public OmnilinkHandlerFactory(final @Reference TimeZoneProvider timeZoneProvider) {
+        OmnilinkActions.setTimeZoneProvider(timeZoneProvider);
+    }
+
     @Override
     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
         return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
diff --git a/bundles/org.openhab.binding.omnilink/src/main/java/org/openhab/binding/omnilink/internal/action/OmnilinkActions.java b/bundles/org.openhab.binding.omnilink/src/main/java/org/openhab/binding/omnilink/internal/action/OmnilinkActions.java
new file mode 100644 (file)
index 0000000..31e0a9d
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) 2010-2022 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.omnilink.internal.action;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Optional;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.omnilink.internal.handler.OmnilinkBridgeHandler;
+import org.openhab.core.automation.annotation.ActionInput;
+import org.openhab.core.automation.annotation.RuleAction;
+import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.core.thing.binding.ThingActions;
+import org.openhab.core.thing.binding.ThingActionsScope;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is the action handler service for the synchronizeControllerTime action.
+ *
+ * @author Ethan Dye - Initial contribution
+ */
+@ThingActionsScope(name = "omnilink")
+@NonNullByDefault
+public class OmnilinkActions implements ThingActions {
+    private final Logger logger = LoggerFactory.getLogger(OmnilinkActions.class);
+    public static Optional<TimeZoneProvider> timeZoneProvider = Optional.empty();
+    private @Nullable OmnilinkBridgeHandler handler;
+
+    @Override
+    public void setThingHandler(@Nullable ThingHandler handler) {
+        if (handler instanceof OmnilinkBridgeHandler) {
+            this.handler = (OmnilinkBridgeHandler) handler;
+        }
+    }
+
+    @Override
+    public @Nullable ThingHandler getThingHandler() {
+        return handler;
+    }
+
+    @RuleAction(label = "@text/actionLabel", description = "@text/actionDesc")
+    public void synchronizeControllerTime(
+            @ActionInput(name = "zone", label = "@text/actionInputZoneLabel", description = "@text/actionInputZoneDesc") @Nullable String zone) {
+        OmnilinkBridgeHandler actionsHandler = handler;
+        if (actionsHandler == null) {
+            logger.debug("Action service ThingHandler is null!");
+        } else {
+            ZonedDateTime zdt;
+            if (ZoneId.getAvailableZoneIds().contains(zone)) {
+                zdt = ZonedDateTime.now(ZoneId.of(zone));
+            } else {
+                logger.debug("Time zone provided invalid, using system default!");
+                if (timeZoneProvider.isPresent()) {
+                    zdt = ZonedDateTime.now(timeZoneProvider.get().getTimeZone());
+                } else {
+                    zdt = ZonedDateTime.now(ZoneId.systemDefault());
+                }
+            }
+            actionsHandler.synchronizeControllerTime(zdt);
+        }
+    }
+
+    public static void synchronizeSystemTime(ThingActions actions, @Nullable String zone) {
+        ((OmnilinkActions) actions).synchronizeControllerTime(zone);
+    }
+
+    public static void setTimeZoneProvider(TimeZoneProvider tzp) {
+        timeZoneProvider = Optional.of(tzp);
+    }
+}
index 206a5d60231a604987c97a9c5feeaec4fd18d123..7832b8a41679d9586301454b08f3bbf6265ca4db 100644 (file)
@@ -18,9 +18,9 @@ import java.io.IOException;
 import java.net.UnknownHostException;
 import java.time.ZonedDateTime;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
@@ -29,6 +29,7 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.omnilink.internal.AudioPlayer;
 import org.openhab.binding.omnilink.internal.SystemType;
 import org.openhab.binding.omnilink.internal.TemperatureFormat;
+import org.openhab.binding.omnilink.internal.action.OmnilinkActions;
 import org.openhab.binding.omnilink.internal.config.OmnilinkBridgeConfig;
 import org.openhab.binding.omnilink.internal.discovery.OmnilinkDiscoveryService;
 import org.openhab.binding.omnilink.internal.exceptions.BridgeOfflineException;
@@ -105,7 +106,7 @@ public class OmnilinkBridgeHandler extends BaseBridgeHandler implements Notifica
 
     @Override
     public Collection<Class<? extends ThingHandlerService>> getServices() {
-        return Collections.singleton(OmnilinkDiscoveryService.class);
+        return Set.of(OmnilinkDiscoveryService.class, OmnilinkActions.class);
     }
 
     public void sendOmnilinkCommand(final int message, final int param1, final int param2)
@@ -158,6 +159,17 @@ public class OmnilinkBridgeHandler extends BaseBridgeHandler implements Notifica
         }
     }
 
+    public void synchronizeControllerTime(ZonedDateTime zdt) {
+        boolean inDaylightSavings = zdt.getZone().getRules().isDaylightSavings(zdt.toInstant());
+        try {
+            getOmniConnection().setTimeCommand(zdt.getYear() - 2000, zdt.getMonthValue(), zdt.getDayOfMonth(),
+                    zdt.getDayOfWeek().getValue(), zdt.getHour(), zdt.getMinute(), inDaylightSavings);
+        } catch (IOException | OmniNotConnectedException | OmniInvalidResponseException
+                | OmniUnknownMessageTypeException e) {
+            logger.debug("Could not send set date time command to OmniLink Controller: {}", e.getMessage());
+        }
+    }
+
     private SystemFeatures reqSystemFeatures()
             throws OmniInvalidResponseException, OmniUnknownMessageTypeException, BridgeOfflineException {
         try {
@@ -178,22 +190,6 @@ public class OmnilinkBridgeHandler extends BaseBridgeHandler implements Notifica
         }
 
         switch (channelUID.getId()) {
-            case CHANNEL_SYSTEM_DATE:
-                if (command instanceof DateTimeType) {
-                    ZonedDateTime zdt = ((DateTimeType) command).getZonedDateTime();
-                    boolean inDaylightSavings = zdt.getZone().getRules().isDaylightSavings(zdt.toInstant());
-                    try {
-                        getOmniConnection().setTimeCommand(zdt.getYear() - 2000, zdt.getMonthValue(),
-                                zdt.getDayOfMonth(), zdt.getDayOfWeek().getValue(), zdt.getHour(), zdt.getMinute(),
-                                inDaylightSavings);
-                    } catch (IOException | OmniNotConnectedException | OmniInvalidResponseException
-                            | OmniUnknownMessageTypeException e) {
-                        logger.debug("Could not send Set Time command to OmniLink Controller: {}", e.getMessage());
-                    }
-                } else {
-                    logger.debug("Invalid command: {}, must be DateTimeType", command);
-                }
-                break;
             case CHANNEL_CONSOLE_ENABLE_DISABLE_BEEPER:
                 if (command instanceof StringType) {
                     try {
@@ -485,7 +481,7 @@ public class OmnilinkBridgeHandler extends BaseBridgeHandler implements Notifica
             OmniUnknownMessageTypeException {
         SystemStatus status = getOmniConnection().reqSystemStatus();
         logger.debug("Received system status: {}", status);
-        // Let's update system time
+        // Update controller's reported time
         String dateString = new StringBuilder().append(2000 + status.getYear()).append("-")
                 .append(String.format("%02d", status.getMonth())).append("-")
                 .append(String.format("%02d", status.getDay())).append("T")
index 7447554c43ccb222963b7d17d740a6d7c694cf11..d96696757d46c6e216f1df4cc082b220f6544e32 100644 (file)
@@ -246,9 +246,9 @@ channel-type.omnilink.sensor_temperature.label = Temperature
 channel-type.omnilink.sensor_temperature.description = The current temperature at this temperature sensor.
 channel-type.omnilink.switch_press_event.label = Switch Press Event
 channel-type.omnilink.switch_press_event.description = Event sent when an ALC, UPB, Radio RA, or Starlite switch is pressed.
-channel-type.omnilink.sysDate.label = Date/Time
-channel-type.omnilink.sysDate.description = Set controller date/time.
-channel-type.omnilink.sysDate.state.pattern = %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS
+channel-type.omnilink.system_date.label = Date/Time
+channel-type.omnilink.system_date.description = Controller date/time.
+channel-type.omnilink.system_date.state.pattern = %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS
 channel-type.omnilink.thermostat_comm_failure.label = Thermostat Communications Failure
 channel-type.omnilink.thermostat_comm_failure.description = Closed during a communications failure with this thermostat.
 channel-type.omnilink.thermostat_cool_setpoint.label = Cool SetPoint
@@ -318,3 +318,10 @@ channel-type.omnilink.zone_latched_alarm_status.state.option.1 = Tripped
 channel-type.omnilink.zone_latched_alarm_status.state.option.2 = Reset, but previously tripped
 channel-type.omnilink.zone_restore.label = Restore Zone
 channel-type.omnilink.zone_restore.description = Send a 4 digit user code to restore this zone.
+
+# thing actions
+
+actionInputZoneLabel = Time zone
+actionInputZoneDesc = The time zone of the controller, provided in the "America/Denver" format.
+actionLabel = Synchronize controller Date/Time
+actionDesc = Synchronizes the Date/Time and DST flag of the controller with openHAB's system time.
index 8c26f4491ebfb933736bcd7bc9c26ed38e7101f6..37777886328d058875661820cdb7851ad8fbc1a6 100644 (file)
@@ -58,9 +58,9 @@
        <channel-type id="system_date">
                <item-type>DateTime</item-type>
                <label>Date/Time</label>
-               <description>Set controller date/time.</description>
+               <description>Controller date/time.</description>
                <category>Time</category>
-               <state pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
+               <state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
        </channel-type>
 
        <channel-type id="last_log">