diff --git a/CODEOWNERS b/CODEOWNERS index a82897a8b9633..7c798cf0bf194 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -102,6 +102,7 @@ /bundles/org.openhab.binding.enocean/ @fruggy83 /bundles/org.openhab.binding.enphase/ @Hilbrand /bundles/org.openhab.binding.enturno/ @klocsson +/bundles/org.openhab.binding.ephemeris/ @clinique /bundles/org.openhab.binding.epsonprojector/ @mlobstein /bundles/org.openhab.binding.etherrain/ @dfad1469 /bundles/org.openhab.binding.evcc/ @florian-h05 diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index 71a3e8dc36a1f..4feefb764119d 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -501,6 +501,11 @@ org.openhab.binding.enturno ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.ephemeris + ${project.version} + org.openhab.addons.bundles org.openhab.binding.epsonprojector diff --git a/bundles/org.openhab.binding.ephemeris/NOTICE b/bundles/org.openhab.binding.ephemeris/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.ephemeris/README.md b/bundles/org.openhab.binding.ephemeris/README.md new file mode 100644 index 0000000000000..238e9056f17ec --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/README.md @@ -0,0 +1,105 @@ +# Ephemeris Binding + +The Ephemeris Binding makes the bridge with Ephemeris core actions. +It provides access to Ephemeris data via Items without requiring usage of a scripting language. + +The binding will search your Jollyday event definition files in the sub folder `/misc/ephemeris` located in the configuration folder of openHAB (e.g. for a linux system : /etc/openhab/misc/ephemeris/) + +## Supported Things + +The binding handles the following Things: + +* default holiday data (`holiday`) +* custom holiday file (`custom`) +* daysets (`dayset`) +* weekend (`weekend`) + +## Discovery + +The binding discovers `weekend` and `holiday` things. + +## Binding Configuration + +There is no configuration at binding level. + +## Thing Configuration + + +### `custom` Thing Configuration + +| Name | Type | Description | Default | Required | Advanced | +|-----------------|---------|---------------------------------------------------|---------|----------|----------| +| fileName | text | Name of the XML file in the configuration folder | N/A | yes | no | + +The file has to use the syntax described here : https://www.openhab.org/docs/configuration/actions.html#custom-bank-holidays + +### `dayset` Thing Configuration + +| Name | Type | Description | Default | Required | Advanced | +|-----------------|---------|---------------------------|---------|----------|----------| +| name | text | Name of the dayset used | N/A | yes | no | + + +## Channels + +### `weekend` Channels + +| Name | Type | Description | +|----------|--------|---------------------------------------------------------------| +| today | Switch | Set to ON if today is a weekend day, OFF in the other case | +| tomorrow | Switch | Set to ON if tomorrow is a weekend day, OFF in the other case | + +### `dayset` Channels + +| Name | Type | Description | +|----------|--------|---------------------------------------------------------------------| +| today | Switch | Set to ON if today is in the given dayset, OFF in the other case | +| tomorrow | Switch | Set to ON if tomorrow is in the given dayset, OFF in the other case | + +### `holiday` Channels + +| Name | Type | Description | +|------------------|-------------|------------------------------------------------| +| title-today | String | Name of today's holiday if any, NULL otherwise | +| holiday-today | Switch | Set to ON if today is a holiday | +| holiday-tomorrow | Switch | Set to ON if tomorrow is a holiday | +| next-title | String | Name of the next coming holiday | +| next-start | DateTime | Start date of the next coming holiday | +| days-remaining | Number:Time | Remaining days until next holiday | + +### `custom` Channels + +| Name | Type | Description | +|----------------|-------------|----------------------------------------| +| title-today | String | Title of the currently present event | +| event-today | Switch | Set to ON if an event exists today | +| event-tomorrow | Switch | Set to ON if an event exists tomorrow | +| next-title | String | Title of the next starting event | +| next-start | DateTime | Start date of the next coming event | +| days-remaining | Number:Time | Remaining days until next event | + +## Full Example + +### Thing Configuration + +```java +Thing ephemeris:holiday:local "Holidays" +Thing ephemeris:weekend:local "Week-end" +Thing ephemeris:custom:events "Event" [fileName="events.xml"] +``` + +### Item Configuration + +```java +String ToD_Event_Current "Event Today" (gEvents) {channel="ephemeris:custom:events:title-today"} +String ToD_Event_Next "Event Next" (gEvents) {channel="ephemeris:custom:events:next-title"} +Number:Time ToD_Event_Next_Left "Event In" (gEvents) ["Measurement","Duration"] {channel="ephemeris:custom:events:days-remaining", unit="day"} + +Switch ToD_Week_End_Current "Week-End" (gWeekEnd) {channel="ephemeris:weekend:local:today"} +Switch ToD_Week_End_Tomorrow "Week-End Tomorrow" (gWeekEnd) {channel="ephemeris:weekend:local:tomorrow"} + +String ToD_Holiday_Current "Holiday Today" (gHoliday) {channel="ephemeris:holiday:local:title-today"} +String ToD_Holiday_Next "Holiday Next" (gHoliday) {channel="ephemeris:holiday:local:next-title"} +Number:Time ToD_Holiday_Next_Left "Holiday In" (gHoliday) ["Measurement","Duration"] {channel="ephemeris:holiday:local:days-remaining", unit="day"} + +``` diff --git a/bundles/org.openhab.binding.ephemeris/pom.xml b/bundles/org.openhab.binding.ephemeris/pom.xml new file mode 100644 index 0000000000000..f8c582d38b0f9 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 4.2.0-SNAPSHOT + + + org.openhab.binding.ephemeris + + openHAB Add-ons :: Bundles :: Ephemeris Binding + + diff --git a/bundles/org.openhab.binding.ephemeris/src/main/feature/feature.xml b/bundles/org.openhab.binding.ephemeris/src/main/feature/feature.xml new file mode 100644 index 0000000000000..0d647a0847776 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.ephemeris/${project.version} + + diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisBindingConstants.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisBindingConstants.java new file mode 100644 index 0000000000000..4e2c7af9399bb --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisBindingConstants.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal; + +import java.io.File; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.OpenHAB; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link EphemerisBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class EphemerisBindingConstants { + + public static final String BINDING_ID = "ephemeris"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_CUSTOM = new ThingTypeUID(BINDING_ID, "custom"); + public static final ThingTypeUID THING_TYPE_HOLIDAY = new ThingTypeUID(BINDING_ID, "holiday"); + public static final ThingTypeUID THING_TYPE_DAYSET = new ThingTypeUID(BINDING_ID, "dayset"); + public static final ThingTypeUID THING_TYPE_WEEKEND = new ThingTypeUID(BINDING_ID, "weekend"); + + // List of all Channel ids + public static final String CHANNEL_CURRENT_EVENT = "title-today"; + public static final String CHANNEL_NEXT_EVENT = "next-title"; + public static final String CHANNEL_NEXT_START = "next-start"; + public static final String CHANNEL_NEXT_REMAINING = "days-remaining"; + public static final String CHANNEL_TODAY = "today"; + public static final String CHANNEL_TOMORROW = "tomorrow"; + public static final String CHANNEL_HOLIDAY_TODAY = "holiday-today"; + public static final String CHANNEL_HOLIDAY_TOMORROW = "holiday-tomorrow"; + public static final String CHANNEL_EVENT_TODAY = "event-today"; + public static final String CHANNEL_EVENT_TOMORROW = "event-tomorrow"; + + // Folder for xml storage eg: /etc/openhab/misc/ephemeris + public static final String BINDING_DATA_PATH = "%s%smisc%s%s".formatted(OpenHAB.getConfigFolder(), File.separator, + File.separator, BINDING_ID); +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisException.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisException.java new file mode 100644 index 0000000000000..67cab6f75a71c --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisException.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingStatusDetail; + +/** + * Exception raised by Ephemeris Handlers + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class EphemerisException extends Exception { + private static final long serialVersionUID = -8813754360966576513L; + private final ThingStatusDetail statusDetail; + + public EphemerisException(String message, ThingStatusDetail statusDetail) { + super(message); + this.statusDetail = statusDetail; + } + + public ThingStatusDetail getStatusDetail() { + return statusDetail; + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisHandlerFactory.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisHandlerFactory.java new file mode 100644 index 0000000000000..695c677208e1b --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/EphemerisHandlerFactory.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal; + +import static org.openhab.binding.ephemeris.internal.EphemerisBindingConstants.*; + +import java.io.File; +import java.time.ZoneId; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.ephemeris.internal.handler.CustomHandler; +import org.openhab.binding.ephemeris.internal.handler.DaysetHandler; +import org.openhab.binding.ephemeris.internal.handler.HolidayHandler; +import org.openhab.binding.ephemeris.internal.handler.WeekendHandler; +import org.openhab.binding.ephemeris.internal.providers.EphemerisDescriptionProvider; +import org.openhab.core.ephemeris.EphemerisManager; +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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EphemerisHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.ephemeris", service = ThingHandlerFactory.class) +public class EphemerisHandlerFactory extends BaseThingHandlerFactory { + private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_CUSTOM, THING_TYPE_HOLIDAY, + THING_TYPE_DAYSET, THING_TYPE_WEEKEND); + + private final Logger logger = LoggerFactory.getLogger(EphemerisHandlerFactory.class); + private final EphemerisManager ephemerisManager; + private final ZoneId zoneId; + private final EphemerisDescriptionProvider descriptionProvider; + + @Activate + public EphemerisHandlerFactory(final @Reference EphemerisManager ephemerisManager, + final @Reference TimeZoneProvider timeZoneProvider, + final @Reference EphemerisDescriptionProvider descriptionProvider) { + this.ephemerisManager = ephemerisManager; + this.zoneId = timeZoneProvider.getTimeZone(); + this.descriptionProvider = descriptionProvider; + File folder = new File(BINDING_DATA_PATH); + if (!folder.exists()) { + logger.info("Please, create the folder '{}' to store your custom Jollyday definition files.", + BINDING_DATA_PATH); + } + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_CUSTOM.equals(thingTypeUID)) { + return new CustomHandler(thing, ephemerisManager, zoneId); + } else if (THING_TYPE_HOLIDAY.equals(thingTypeUID)) { + return new HolidayHandler(thing, ephemerisManager, zoneId, descriptionProvider); + } else if (THING_TYPE_DAYSET.equals(thingTypeUID)) { + return new DaysetHandler(thing, ephemerisManager, zoneId); + } else if (THING_TYPE_WEEKEND.equals(thingTypeUID)) { + return new WeekendHandler(thing, ephemerisManager, zoneId); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/configuration/DaysetConfiguration.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/configuration/DaysetConfiguration.java new file mode 100644 index 0000000000000..71d5538f73430 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/configuration/DaysetConfiguration.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link DaysetConfiguration} class contains fields mapping Dayset Thing configuration parameters. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class DaysetConfiguration { + public String name = ""; +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/configuration/FileConfiguration.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/configuration/FileConfiguration.java new file mode 100644 index 0000000000000..7773f3f94dc2d --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/configuration/FileConfiguration.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link FileConfiguration} class contains fields mapping File Thing configuration parameters. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class FileConfiguration { + public String fileName = ""; +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/discovery/EphemerisDiscoveryService.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/discovery/EphemerisDiscoveryService.java new file mode 100644 index 0000000000000..152a80244d76b --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/discovery/EphemerisDiscoveryService.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.discovery; + +import static org.openhab.binding.ephemeris.internal.EphemerisBindingConstants.*; + +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.config.discovery.AbstractDiscoveryService; +import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.config.discovery.DiscoveryService; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; +import org.openhab.core.thing.ThingUID; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EphemerisDiscoveryService} creates default available Ephemeris Things. + * + * @author Gaël L'hopital - Initial Contribution + */ +@NonNullByDefault +@Component(service = DiscoveryService.class, configurationPid = "discovery.ephemeris") +public class EphemerisDiscoveryService extends AbstractDiscoveryService { + private static final int DISCOVER_TIMEOUT_SECONDS = 2; + private static final String LOCAL = "local"; + private static final ThingUID HOLIDAY_THING = new ThingUID(THING_TYPE_HOLIDAY, LOCAL); + private static final ThingUID WEEKEND_THING = new ThingUID(THING_TYPE_WEEKEND, LOCAL); + + private final Logger logger = LoggerFactory.getLogger(EphemerisDiscoveryService.class); + + private Optional> discoveryJob = Optional.empty(); + + @Activate + public EphemerisDiscoveryService(final @Reference LocaleProvider localeProvider, + final @Reference TranslationProvider i18nProvider, @Nullable Map configProperties) { + super(Set.of(THING_TYPE_HOLIDAY, THING_TYPE_WEEKEND), DISCOVER_TIMEOUT_SECONDS, true); + this.localeProvider = localeProvider; + this.i18nProvider = i18nProvider; + activate(configProperties); + } + + @Override + protected void startScan() { + logger.debug("Starting Ephemeris discovery scan"); + createResults(); + } + + @Override + protected void startBackgroundDiscovery() { + discoveryJob = Optional.of(scheduler.schedule(this::createResults, 2, TimeUnit.SECONDS)); + } + + @Override + protected void stopBackgroundDiscovery() { + logger.debug("Stopping Ephemeris device background discovery"); + discoveryJob.ifPresent(job -> job.cancel(true)); + discoveryJob = Optional.empty(); + } + + public void createResults() { + thingDiscovered(DiscoveryResultBuilder.create(HOLIDAY_THING).build()); + thingDiscovered(DiscoveryResultBuilder.create(WEEKEND_THING).build()); + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/BaseEphemerisHandler.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/BaseEphemerisHandler.java new file mode 100644 index 0000000000000..d4019ac50f674 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/BaseEphemerisHandler.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.handler; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Optional; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.ephemeris.internal.EphemerisException; +import org.openhab.core.ephemeris.EphemerisManager; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link BaseEphemerisHandler} is the base class for Ephemeris Things. It takes care of + * update logic and update scheduling once a day. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public abstract class BaseEphemerisHandler extends BaseThingHandler { + private static final int REFRESH_FIRST_HOUR_OF_DAY = 0; + private static final int REFRESH_FIRST_MINUTE_OF_DAY = 1; + + private final Logger logger = LoggerFactory.getLogger(BaseEphemerisHandler.class); + private final ZoneId zoneId; + private Optional> refreshJob = Optional.empty(); + + protected final EphemerisManager ephemeris; + + public BaseEphemerisHandler(Thing thing, EphemerisManager ephemerisManager, ZoneId zoneId) { + super(thing); + this.zoneId = zoneId; + this.ephemeris = ephemerisManager; + } + + @Override + public void initialize() { + updateStatus(ThingStatus.UNKNOWN); + refreshJob = Optional.of(scheduler.schedule(this::updateData, 1, TimeUnit.SECONDS)); + } + + @Override + public void dispose() { + refreshJob.ifPresent(job -> job.cancel(true)); + refreshJob = Optional.empty(); + super.dispose(); + } + + private void updateData() { + ZonedDateTime now = ZonedDateTime.now().withZoneSameLocal(zoneId); + + logger.debug("Updating {} channels", getThing().getUID()); + try { + internalUpdate(now.truncatedTo(ChronoUnit.DAYS)); + + updateStatus(ThingStatus.ONLINE); + ZonedDateTime nextUpdate = now.plusDays(1).withHour(REFRESH_FIRST_HOUR_OF_DAY) + .withMinute(REFRESH_FIRST_MINUTE_OF_DAY).truncatedTo(ChronoUnit.MINUTES); + long delay = ChronoUnit.MINUTES.between(now, nextUpdate); + logger.debug("Scheduling next {} update in {} minutes", getThing().getUID(), delay); + refreshJob = Optional.of(scheduler.schedule(this::updateData, delay, TimeUnit.MINUTES)); + } catch (EphemerisException e) { + updateStatus(ThingStatus.OFFLINE, e.getStatusDetail(), e.getMessage()); + } + } + + protected abstract void internalUpdate(ZonedDateTime today) throws EphemerisException; + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (RefreshType.REFRESH.equals(command)) { + updateData(); + } + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/CustomHandler.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/CustomHandler.java new file mode 100644 index 0000000000000..b204f96fe6822 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/CustomHandler.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.handler; + +import static org.openhab.binding.ephemeris.internal.EphemerisBindingConstants.*; + +import java.io.File; +import java.io.FileNotFoundException; +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.ephemeris.internal.EphemerisException; +import org.openhab.binding.ephemeris.internal.configuration.FileConfiguration; +import org.openhab.core.ephemeris.EphemerisManager; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; + +/** + * The {@link CustomHandler} delivers user defined Jollyday definition events. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class CustomHandler extends JollydayHandler { + private Optional definitionFile = Optional.empty(); + + public CustomHandler(Thing thing, EphemerisManager ephemerisManager, ZoneId zoneId) { + super(thing, ephemerisManager, zoneId); + } + + @Override + public void initialize() { + String fileName = getConfigAs(FileConfiguration.class).fileName; + + if (fileName.isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "'fileName' can not be blank or empty"); + return; + } + + File file = new File(BINDING_DATA_PATH, fileName); + if (!file.exists()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Missing file: %s".formatted(file.getAbsolutePath())); + return; + } + + definitionFile = Optional.of(file); + super.initialize(); + } + + @Override + protected void internalUpdate(ZonedDateTime today) throws EphemerisException { + String event = getEvent(today); + updateState(CHANNEL_EVENT_TODAY, OnOffType.from(event != null)); + + event = getEvent(today.plusDays(1)); + updateState(CHANNEL_EVENT_TOMORROW, OnOffType.from(event != null)); + + super.internalUpdate(today); + } + + @Override + protected @Nullable String getEvent(ZonedDateTime day) throws EphemerisException { + String path = definitionFile.get().getAbsolutePath(); + try { + return ephemeris.getBankHolidayName(day, path); + } catch (IllegalStateException e) { + throw new EphemerisException("Incorrect syntax", ThingStatusDetail.NONE); + } catch (FileNotFoundException e) { + throw new EphemerisException("File is absent: " + path, ThingStatusDetail.CONFIGURATION_ERROR); + } + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/DaysetHandler.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/DaysetHandler.java new file mode 100644 index 0000000000000..343a31adfe57e --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/DaysetHandler.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.handler; + +import static org.openhab.binding.ephemeris.internal.EphemerisBindingConstants.*; + +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.ephemeris.internal.EphemerisException; +import org.openhab.binding.ephemeris.internal.configuration.DaysetConfiguration; +import org.openhab.core.ephemeris.EphemerisManager; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Thing; + +/** + * The {@link DaysetHandler} delivers system default dayset data. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class DaysetHandler extends BaseEphemerisHandler { + private String dayset = ""; + + public DaysetHandler(Thing thing, EphemerisManager ephemerisManager, ZoneId zoneId) { + super(thing, ephemerisManager, zoneId); + } + + @Override + public void initialize() { + DaysetConfiguration config = getConfigAs(DaysetConfiguration.class); + dayset = config.name; + super.initialize(); + } + + @Override + protected void internalUpdate(ZonedDateTime today) throws EphemerisException { + updateState(CHANNEL_TODAY, OnOffType.from(ephemeris.isInDayset(dayset, today))); + updateState(CHANNEL_TOMORROW, OnOffType.from(ephemeris.isInDayset(dayset, today.plusDays(1)))); + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/HolidayHandler.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/HolidayHandler.java new file mode 100644 index 0000000000000..83e546e10ec50 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/HolidayHandler.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.handler; + +import static org.openhab.binding.ephemeris.internal.EphemerisBindingConstants.*; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.ephemeris.internal.EphemerisException; +import org.openhab.binding.ephemeris.internal.providers.EphemerisDescriptionProvider; +import org.openhab.core.ephemeris.EphemerisManager; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.types.StateOption; + +/** + * The {@link HolidayHandler} delivers system default Holidays data. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class HolidayHandler extends JollydayHandler { + + public HolidayHandler(Thing thing, EphemerisManager ephemerisManager, ZoneId zoneId, + EphemerisDescriptionProvider descriptionProvider) { + super(thing, ephemerisManager, zoneId); + + // Search all holidays in the coming year, using a map to avoid duplicates + Map events = new HashMap<>(); + ZonedDateTime now = ZonedDateTime.now(); + // Scans 13 monthes to be sure to catch mobile holidays + for (int offset = 0; offset < 398; offset++) { + String event = getEvent(now.plusDays(offset)); + if (event != null) { + String description = ephemeris.getHolidayDescription(event); + events.put(event, new StateOption(event, description == null ? event : description)); + } + } + + // Set descriptions for these events + List stateOptions = events.values().stream().toList(); + descriptionProvider.setStateOptions(new ChannelUID(thing.getUID(), CHANNEL_CURRENT_EVENT), stateOptions); + descriptionProvider.setStateOptions(new ChannelUID(thing.getUID(), CHANNEL_NEXT_EVENT), stateOptions); + } + + @Override + protected void internalUpdate(ZonedDateTime today) throws EphemerisException { + updateState(CHANNEL_HOLIDAY_TODAY, OnOffType.from(getEvent(today) != null)); + updateState(CHANNEL_HOLIDAY_TOMORROW, OnOffType.from(getEvent(today.plusDays(1)) != null)); + super.internalUpdate(today); + } + + @Override + protected @Nullable String getEvent(ZonedDateTime day) { + return ephemeris.getBankHolidayName(day); + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/JollydayHandler.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/JollydayHandler.java new file mode 100644 index 0000000000000..8f5cee527778d --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/JollydayHandler.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.handler; + +import static org.openhab.binding.ephemeris.internal.EphemerisBindingConstants.*; + +import java.time.Duration; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.ephemeris.internal.EphemerisException; +import org.openhab.core.ephemeris.EphemerisManager; +import org.openhab.core.library.types.DateTimeType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.Thing; +import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; + +/** + * The {@link JollydayHandler} handles common parts for Jollyday file based events + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public abstract class JollydayHandler extends BaseEphemerisHandler { + + public JollydayHandler(Thing thing, EphemerisManager ephemerisManager, ZoneId zoneId) { + super(thing, ephemerisManager, zoneId); + } + + @Override + protected void internalUpdate(ZonedDateTime today) throws EphemerisException { + String todayEvent = getEvent(today); + updateState(CHANNEL_CURRENT_EVENT, toStringType(todayEvent)); + + String nextEvent = null; + ZonedDateTime nextDay = today; + + for (int offset = 1; offset < 366 && (nextEvent == null || nextEvent.isEmpty()); offset++) { + nextDay = today.plusDays(offset); + nextEvent = getEvent(nextDay); + } + + updateState(CHANNEL_NEXT_EVENT, toStringType(nextEvent)); + updateState(CHANNEL_NEXT_REMAINING, + nextEvent != null ? new QuantityType<>(Duration.between(today, nextDay).toDays(), Units.DAY) + : UnDefType.UNDEF); + updateState(CHANNEL_NEXT_START, nextEvent != null ? new DateTimeType(nextDay) : UnDefType.UNDEF); + } + + protected abstract @Nullable String getEvent(ZonedDateTime day) throws EphemerisException; + + protected State toStringType(@Nullable String event) { + return event == null || event.isEmpty() ? UnDefType.NULL : new StringType(event); + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/WeekendHandler.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/WeekendHandler.java new file mode 100644 index 0000000000000..a2a5aea2d48ee --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/handler/WeekendHandler.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.handler; + +import static org.openhab.binding.ephemeris.internal.EphemerisBindingConstants.*; + +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.ephemeris.internal.EphemerisException; +import org.openhab.core.ephemeris.EphemerisManager; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Thing; + +/** + * The {@link WeekendHandler} delivers system default Weekend data. + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class WeekendHandler extends BaseEphemerisHandler { + + public WeekendHandler(Thing thing, EphemerisManager ephemerisManager, ZoneId zoneId) { + super(thing, ephemerisManager, zoneId); + } + + @Override + protected void internalUpdate(ZonedDateTime today) throws EphemerisException { + updateState(CHANNEL_TODAY, OnOffType.from(ephemeris.isWeekend(today))); + updateState(CHANNEL_TOMORROW, OnOffType.from(ephemeris.isWeekend(today.plusDays(1)))); + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/providers/EphemerisDescriptionProvider.java b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/providers/EphemerisDescriptionProvider.java new file mode 100644 index 0000000000000..f249faa739b97 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/java/org/openhab/binding/ephemeris/internal/providers/EphemerisDescriptionProvider.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2024 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.ephemeris.internal.providers; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.events.EventPublisher; +import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider; +import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService; +import org.openhab.core.thing.link.ItemChannelLinkRegistry; +import org.openhab.core.thing.type.DynamicStateDescriptionProvider; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * Dynamic provider of state options while leaving other state description fields as original. + * + * @author Gaël L'hopital - Initial contribution + */ +@Component(service = { DynamicStateDescriptionProvider.class, EphemerisDescriptionProvider.class }) +@NonNullByDefault +public class EphemerisDescriptionProvider extends BaseDynamicStateDescriptionProvider { + + @Activate + public EphemerisDescriptionProvider(final @Reference EventPublisher eventPublisher, // + final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, // + final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) { + this.eventPublisher = eventPublisher; + this.itemChannelLinkRegistry = itemChannelLinkRegistry; + this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService; + } +} diff --git a/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/addon/addon.xml new file mode 100644 index 0000000000000..a4173aa28456f --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/addon/addon.xml @@ -0,0 +1,11 @@ + + + + binding + Ephemeris Binding + The Ephemeris Binding makes Ephemeris core actions accessible to Items + none + + diff --git a/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/i18n/ephemeris.properties b/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/i18n/ephemeris.properties new file mode 100644 index 0000000000000..d64ac7268dfba --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/i18n/ephemeris.properties @@ -0,0 +1,86 @@ +# add-on + +addon.ephemeris.name = Ephemeris Binding +addon.ephemeris.description = The Ephemeris Binding makes Ephemeris core actions accessible to Items + +# thing types + +thing-type.ephemeris.custom.label = Custom Jollyday File +thing-type.ephemeris.custom.description = Events defined in a Jollyday file +thing-type.ephemeris.custom.channel.event-today.label = Event Today +thing-type.ephemeris.custom.channel.event-today.description = Set to ON if an event exists today +thing-type.ephemeris.custom.channel.event-tomorrow.label = Event Tomorrow +thing-type.ephemeris.custom.channel.event-tomorrow.description = Set to ON if an event exists tomorrow +thing-type.ephemeris.dayset.label = Dayset +thing-type.ephemeris.dayset.description = Events based on a given dayset +thing-type.ephemeris.dayset.channel.today.label = Today in Dayset +thing-type.ephemeris.dayset.channel.today.description = Set to ON if today is in the given dayset, OFF in the other case +thing-type.ephemeris.dayset.channel.tomorrow.label = Tomorrow in Dayset +thing-type.ephemeris.dayset.channel.tomorrow.description = Set to ON if tomorrow is in the given dayset, OFF in the other case +thing-type.ephemeris.holiday.label = Ephemeris Holidays +thing-type.ephemeris.holiday.description = Holidays based on system default Ephemeris configuration +thing-type.ephemeris.holiday.channel.holiday-today.label = Holiday Today +thing-type.ephemeris.holiday.channel.holiday-today.description = Set to ON if today is a holiday +thing-type.ephemeris.holiday.channel.holiday-tomorrow.label = Holiday Tomorrow +thing-type.ephemeris.holiday.channel.holiday-tomorrow.description = Set to ON if tomorrow is a holiday +thing-type.ephemeris.holiday.channel.next-title.description = Name of the next coming holiday +thing-type.ephemeris.holiday.channel.title-today.description = Name of today's holiday if any, NULL otherwise +thing-type.ephemeris.weekend.label = Weekend +thing-type.ephemeris.weekend.description = Events based on the system default week-end dayset +thing-type.ephemeris.weekend.channel.today.label = Weekend Today +thing-type.ephemeris.weekend.channel.today.description = Set to ON if today is a weekend day, OFF in the other case +thing-type.ephemeris.weekend.channel.tomorrow.label = Weekend Tomorrow +thing-type.ephemeris.weekend.channel.tomorrow.description = Set to ON if tomorrow is a weekend day, OFF in the other case + +# thing types config + +thing-type.config.ephemeris.custom.fileName.label = File Name +thing-type.config.ephemeris.custom.fileName.description = Name of a Jollyday XML file in the configuration folder. +thing-type.config.ephemeris.dayset.name.label = Name +thing-type.config.ephemeris.dayset.name.description = Name of the dayset. + +# channel types + +channel-type.ephemeris.days-remaining.label = Remaining Days +channel-type.ephemeris.days-remaining.description = Remaining days until next event +channel-type.ephemeris.event-current-title.label = Current Event Title +channel-type.ephemeris.event-current-title.description = Title of the currently present event +channel-type.ephemeris.event-next-start.label = Next Event Start +channel-type.ephemeris.event-next-start.description = Start date of the next coming event +channel-type.ephemeris.event-next-start.state.pattern = %1$tY-%1$tm-%1$td +channel-type.ephemeris.event-next-title.label = Next Event Title +channel-type.ephemeris.event-next-title.description = Title of the next starting event +channel-type.ephemeris.in-dayset.label = In Dayset + +# channel types + +channel-type.ephemeris.in-dayset.description = Set to ON if the day is in the dayset, OFF in the other case + +# thing types + +thing-type.ephemeris.file.label = Ephemeris File +thing-type.ephemeris.file.description = Events defined in a Jollyday file +thing-type.ephemeris.file.channel.event-today.label = Event Today +thing-type.ephemeris.file.channel.event-today.description = Set to ON if an event exists today +thing-type.ephemeris.file.channel.event-tomorrow.label = Event Tomorrow +thing-type.ephemeris.file.channel.event-tomorrow.description = Set to ON if an event exists tomorrow + +# thing types config + +thing-type.config.ephemeris.file.fileName.label = File Name +thing-type.config.ephemeris.file.fileName.description = Name of a Jollyday XML file in the binding folder. + +# channel types + +channel-type.ephemeris.remaining-days.label = Remaining Days +channel-type.ephemeris.remaining-days.description = Days until next event + +# thing types + +thing-type.ephemeris.default.label = Ephemeris +thing-type.ephemeris.default.description = Events based on system default Ephemeris configuration + +# discovery result + +discovery.ephemeris.holiday.local.label = Local Holiday +discovery.ephemeris.weekend.local.label = Local Weekend diff --git a/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..b0bb17f433029 --- /dev/null +++ b/bundles/org.openhab.binding.ephemeris/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,133 @@ + + + + + + Events defined in a Jollyday file + + + + + + Set to ON if an event exists today + + + + Set to ON if an event exists tomorrow + + + + + + + + + + Name of a Jollyday XML file in the configuration folder. + + + + + + + + Holidays based on system default Ephemeris configuration + + + + Name of today's holiday if any, NULL otherwise + + + + Set to ON if today is a holiday + + + + Set to ON if tomorrow is a holiday + + + Name of the next coming holiday + + + + + + + + + Events based on a given dayset + + + + + Set to ON if today is in the given dayset, OFF in the other case + + + + Set to ON if tomorrow is in the given dayset, OFF in the other case + + + + + + + Name of the dayset. + + + + + + + + Events based on the system default weekend dayset + + + + + Set to ON if today is a weekend day, OFF in the other case + + + + Set to ON if tomorrow is a weekend day, OFF in the other case + + + + + + Switch + + + + + + String + + Title of the currently present event + + + + + String + + Title of the next starting event + + + + + DateTime + + Start date of the next coming event + + + + + Number:Time + + Remaining days until next event + + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index 2c9f08d17a928..4dd01018775dd 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -134,6 +134,7 @@ org.openhab.binding.enocean org.openhab.binding.enphase org.openhab.binding.enturno + org.openhab.binding.ephemeris org.openhab.binding.epsonprojector org.openhab.binding.etherrain org.openhab.binding.evcc