2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.solarforecast.internal.actions;
15 import java.time.Instant;
16 import java.time.LocalDate;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Optional;
21 import javax.measure.MetricPrefix;
22 import javax.measure.quantity.Energy;
23 import javax.measure.quantity.Power;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.openhab.binding.solarforecast.internal.utils.Utils;
28 import org.openhab.core.automation.annotation.ActionInput;
29 import org.openhab.core.automation.annotation.RuleAction;
30 import org.openhab.core.library.types.QuantityType;
31 import org.openhab.core.library.unit.Units;
32 import org.openhab.core.thing.binding.ThingActions;
33 import org.openhab.core.thing.binding.ThingActionsScope;
34 import org.openhab.core.thing.binding.ThingHandler;
35 import org.openhab.core.types.State;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 * Actions to query forecast objects
42 * @author Bernd Weymann - Initial contribution
44 @ThingActionsScope(name = "solarforecast")
46 public class SolarForecastActions implements ThingActions {
47 private final Logger logger = LoggerFactory.getLogger(SolarForecastActions.class);
48 private Optional<ThingHandler> thingHandler = Optional.empty();
50 @RuleAction(label = "@text/actionDayLabel", description = "@text/actionDayDesc")
51 public QuantityType<Energy> getDay(
52 @ActionInput(name = "localDate", label = "@text/actionInputDayLabel", description = "@text/actionInputDayDesc") LocalDate localDate,
54 if (thingHandler.isPresent()) {
55 List<SolarForecast> l = ((SolarForecastProvider) thingHandler.get()).getSolarForecasts();
57 QuantityType<Energy> measure = QuantityType.valueOf(0, Units.KILOWATT_HOUR);
58 for (Iterator<SolarForecast> iterator = l.iterator(); iterator.hasNext();) {
59 SolarForecast solarForecast = iterator.next();
60 QuantityType<Energy> qt = solarForecast.getDay(localDate, args);
61 if (qt.floatValue() >= 0) {
62 measure = measure.add(qt);
64 // break in case of failure getting values to avoid ambiguous values
65 logger.debug("Ambiguous measure {} found for {}", qt, localDate);
66 return Utils.getEnergyState(-1);
71 logger.debug("No forecasts found for {}", localDate);
72 return Utils.getEnergyState(-1);
75 logger.trace("Handler missing");
76 return Utils.getEnergyState(-1);
80 @RuleAction(label = "@text/actionPowerLabel", description = "@text/actionPowerDesc")
81 public QuantityType<Power> getPower(
82 @ActionInput(name = "timestamp", label = "@text/actionInputDateTimeLabel", description = "@text/actionInputDateTimeDesc") Instant timestamp,
84 if (thingHandler.isPresent()) {
85 List<SolarForecast> l = ((SolarForecastProvider) thingHandler.get()).getSolarForecasts();
87 QuantityType<Power> measure = QuantityType.valueOf(0, MetricPrefix.KILO(Units.WATT));
88 for (Iterator<SolarForecast> iterator = l.iterator(); iterator.hasNext();) {
89 SolarForecast solarForecast = iterator.next();
90 QuantityType<Power> qt = solarForecast.getPower(timestamp, args);
91 if (qt.floatValue() >= 0) {
92 measure = measure.add(qt);
94 // break in case of failure getting values to avoid ambiguous values
95 logger.debug("Ambiguous measure {} found for {}", qt, timestamp);
96 return Utils.getPowerState(-1);
101 logger.debug("No forecasts found for {}", timestamp);
102 return Utils.getPowerState(-1);
105 logger.trace("Handler missing");
106 return Utils.getPowerState(-1);
110 @RuleAction(label = "@text/actionEnergyLabel", description = "@text/actionEnergyDesc")
111 public QuantityType<Energy> getEnergy(
112 @ActionInput(name = "start", label = "@text/actionInputDateTimeBeginLabel", description = "@text/actionInputDateTimeBeginDesc") Instant start,
113 @ActionInput(name = "end", label = "@text/actionInputDateTimeEndLabel", description = "@text/actionInputDateTimeEndDesc") Instant end,
115 if (thingHandler.isPresent()) {
116 List<SolarForecast> l = ((SolarForecastProvider) thingHandler.get()).getSolarForecasts();
118 QuantityType<Energy> measure = QuantityType.valueOf(0, Units.KILOWATT_HOUR);
119 for (Iterator<SolarForecast> iterator = l.iterator(); iterator.hasNext();) {
120 SolarForecast solarForecast = iterator.next();
121 QuantityType<Energy> qt = solarForecast.getEnergy(start, end, args);
122 if (qt.floatValue() >= 0) {
123 measure = measure.add(qt);
125 // break in case of failure getting values to avoid ambiguous values
126 logger.debug("Ambiguous measure {} found between {} and {}", qt, start, end);
127 return Utils.getEnergyState(-1);
132 logger.debug("No forecasts found for between {} and {}", start, end);
133 return Utils.getEnergyState(-1);
136 logger.trace("Handler missing");
137 return Utils.getEnergyState(-1);
141 @RuleAction(label = "@text/actionForecastBeginLabel", description = "@text/actionForecastBeginDesc")
142 public Instant getForecastBegin() {
143 if (thingHandler.isPresent()) {
144 List<SolarForecast> forecastObjectList = ((SolarForecastProvider) thingHandler.get()).getSolarForecasts();
145 return Utils.getCommonStartTime(forecastObjectList);
147 logger.trace("Handler missing - return invalid date MAX");
152 @RuleAction(label = "@text/actionForecastEndLabel", description = "@text/actionForecastEndDesc")
153 public Instant getForecastEnd() {
154 if (thingHandler.isPresent()) {
155 List<SolarForecast> forecastObjectList = ((SolarForecastProvider) thingHandler.get()).getSolarForecasts();
156 return Utils.getCommonEndTime(forecastObjectList);
158 logger.trace("Handler missing - return invalid date MIN");
163 @RuleAction(label = "@text/actionTriggerUpdateLabel", description = "@text/actionTriggerUpdateDesc")
164 public void triggerUpdate() {
165 if (thingHandler.isPresent()) {
166 List<SolarForecast> forecastObjectList = ((SolarForecastProvider) thingHandler.get()).getSolarForecasts();
167 forecastObjectList.forEach(forecast -> {
168 forecast.triggerUpdate();
171 logger.trace("Handler missing");
175 public static State getDay(ThingActions actions, LocalDate ld, String... args) {
176 return ((SolarForecastActions) actions).getDay(ld, args);
179 public static State getPower(ThingActions actions, Instant dateTime, String... args) {
180 return ((SolarForecastActions) actions).getPower(dateTime, args);
183 public static State getEnergy(ThingActions actions, Instant begin, Instant end, String... args) {
184 return ((SolarForecastActions) actions).getEnergy(begin, end, args);
187 public static Instant getForecastBegin(ThingActions actions) {
188 return ((SolarForecastActions) actions).getForecastBegin();
191 public static Instant getForecastEnd(ThingActions actions) {
192 return ((SolarForecastActions) actions).getForecastEnd();
195 public static void triggerUpdate(ThingActions actions) {
196 ((SolarForecastActions) actions).triggerUpdate();
200 public void setThingHandler(ThingHandler handler) {
201 thingHandler = Optional.of(handler);
205 public @Nullable ThingHandler getThingHandler() {
206 if (thingHandler.isPresent()) {
207 return thingHandler.get();