Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OmniLink] Fix daylight savings when setting date/time #12546

Merged
merged 9 commits into from
Apr 18, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions bundles/org.openhab.binding.omnilink/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,10 @@ DateTime OmniProTime "Last Time Update [%1$ta %1$tR]" <time> {channel="o
=Unknown
```

### Example `omnilink.rules`
### Example EMCAScript rule

```
rule "Update OmniPro Time"
when
Time cron "0 0 0/1 1/1 * ? *"
then
OmniProTime.sendCommand( new DateTimeType() )
end
``` javascript
var omnilinkAction = actions.get("omnilink", "omnilink:controller:home");

omnilinkAction.setDateTime("America/Denver");
jlaur marked this conversation as resolved.
Show resolved Hide resolved
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* 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 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.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This is the action handler service for the set_date action.
ecdye marked this conversation as resolved.
Show resolved Hide resolved
*
* @author Ethan Dye - Initial contribution
*/
@ThingActionsScope(name = "omnilink")
@NonNullByDefault
public class OmnilinkActions implements ThingActions {
private final Logger logger = LoggerFactory.getLogger(OmnilinkActions.class);
private final TimeZoneProvider timeZoneProvider;
private @Nullable OmnilinkBridgeHandler handler;

public OmnilinkActions(final @Reference TimeZoneProvider timeZoneProvider) {
this.timeZoneProvider = timeZoneProvider;
}

@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")
ecdye marked this conversation as resolved.
Show resolved Hide resolved
public void setDateTime(
jlaur marked this conversation as resolved.
Show resolved Hide resolved
@ActionInput(name = "zone", label = "@text/actionInputZoneLabel", description = "@text/actionInputZoneDesc") @Nullable String zone) {
OmnilinkBridgeHandler actionsHandler = handler;
ZonedDateTime zdt;
if (zone != null) {
zdt = ZonedDateTime.now(ZoneId.of(zone));
ecdye marked this conversation as resolved.
Show resolved Hide resolved
} else {
zdt = ZonedDateTime.now(timeZoneProvider.getTimeZone());
}
if (actionsHandler == null) {
ecdye marked this conversation as resolved.
Show resolved Hide resolved
logger.info("Action service ThingHandler is null!");
} else {
actionsHandler.setDateTime(zdt);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@
import java.util.Optional;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.NonNullByDefault;
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;
Expand Down Expand Up @@ -105,7 +108,8 @@ public OmnilinkBridgeHandler(Bridge bridge) {

@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singleton(OmnilinkDiscoveryService.class);
return Collections.unmodifiableSet(
Stream.of(OmnilinkDiscoveryService.class, OmnilinkActions.class).collect(Collectors.toSet()));
ecdye marked this conversation as resolved.
Show resolved Hide resolved
}

public void sendOmnilinkCommand(final int message, final int param1, final int param2)
Expand Down Expand Up @@ -158,6 +162,17 @@ public SystemFormats reqSystemFormats()
}
}

public void setDateTime(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 {
Expand All @@ -178,22 +193,6 @@ public void handleCommand(ChannelUID channelUID, Command command) {
}

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 {
Expand Down Expand Up @@ -485,7 +484,7 @@ private void getSystemStatus() throws IOException, OmniNotConnectedException, Om
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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 = Set the Date/Time of the controller
actionDesc = Sets the current Date/Time of the controller to the correct value, including daylight savings.
jlaur marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down