2 * Copyright (c) 2010-2023 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.pushsafer.internal.handler;
15 import static org.openhab.binding.pushsafer.internal.PushsaferBindingConstants.*;
17 import java.util.Collection;
18 import java.util.List;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.eclipse.jetty.client.HttpClient;
24 import org.openhab.binding.pushsafer.internal.actions.PushsaferActions;
25 import org.openhab.binding.pushsafer.internal.config.PushsaferAccountConfiguration;
26 import org.openhab.binding.pushsafer.internal.config.PushsaferConfigOptionProvider;
27 import org.openhab.binding.pushsafer.internal.connection.PushsaferAPIConnection;
28 import org.openhab.binding.pushsafer.internal.connection.PushsaferCommunicationException;
29 import org.openhab.binding.pushsafer.internal.connection.PushsaferConfigurationException;
30 import org.openhab.binding.pushsafer.internal.connection.PushsaferMessageBuilder;
31 import org.openhab.binding.pushsafer.internal.dto.Icon;
32 import org.openhab.binding.pushsafer.internal.dto.Sound;
33 import org.openhab.core.thing.ChannelUID;
34 import org.openhab.core.thing.Thing;
35 import org.openhab.core.thing.ThingStatus;
36 import org.openhab.core.thing.ThingStatusDetail;
37 import org.openhab.core.thing.binding.BaseThingHandler;
38 import org.openhab.core.thing.binding.ThingHandlerService;
39 import org.openhab.core.types.Command;
42 * The {@link PushsaferAccountHandler} is responsible for handling commands, which are sent to one of the channels.
44 * @author Kevin Siml - Initial contribution, forked from Christoph Weitkamp
47 public class PushsaferAccountHandler extends BaseThingHandler {
49 private static final Collection<Class<? extends ThingHandlerService>> SUPPORTED_THING_ACTIONS = Set
50 .of(PushsaferActions.class, PushsaferConfigOptionProvider.class);
52 private final HttpClient httpClient;
54 private PushsaferAccountConfiguration config = new PushsaferAccountConfiguration();
55 private @Nullable PushsaferAPIConnection connection;
57 public PushsaferAccountHandler(Thing thing, HttpClient httpClient) {
59 this.httpClient = httpClient;
63 public void handleCommand(ChannelUID channelUID, Command command) {
68 public void initialize() {
69 config = getConfigAs(PushsaferAccountConfiguration.class);
71 boolean configValid = true;
72 final String apikey = config.apikey;
73 if (apikey == null || apikey.isEmpty()) {
74 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
75 "@text/offline.conf-error-missing-apikey");
78 final String user = config.user;
79 if (user == null || user.isEmpty()) {
80 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
81 "@text/offline.conf-error-missing-user");
86 updateStatus(ThingStatus.UNKNOWN);
88 connection = new PushsaferAPIConnection(httpClient, config);
89 scheduler.submit(this::asyncValidateUser);
94 public Collection<Class<? extends ThingHandlerService>> getServices() {
95 return SUPPORTED_THING_ACTIONS;
99 * Retrieves the list of current sounds and their descriptions from the Pushsafer API.
101 * @return a list of {@link Sound}s
103 public List<Sound> getSounds() {
105 return connection != null ? connection.getSounds() : List.of();
106 } catch (PushsaferCommunicationException e) {
107 // do nothing, causing exception is already logged
108 } catch (PushsaferConfigurationException e) {
109 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
115 * Retrieves the list of current icons from the Pushsafer API.
117 * @return a list of {@link Icon}s
119 public List<Icon> getIcons() {
121 return connection != null ? connection.getIcons() : List.of();
122 } catch (PushsaferCommunicationException e) {
123 // do nothing, causing exception is already logged
124 } catch (PushsaferConfigurationException e) {
125 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
131 * Returns a preconfigured {@link PushsaferMessageBuilder}.
133 * @param message the message
134 * @return a {@link PushsaferMessageBuilder} instance
136 public PushsaferMessageBuilder getDefaultPushsaferMessageBuilder(String message)
137 throws PushsaferConfigurationException {
138 PushsaferMessageBuilder builder = PushsaferMessageBuilder.getInstance(config.apikey, config.device)
139 .withMessage(message) //
140 .withTitle(config.title) //
141 .withRetry(config.retry) //
142 .withExpire(config.expire);
143 // specify format if defined
144 switch (config.format) {
145 case PushsaferMessageBuilder.MESSAGE_KEY_HTML:
146 builder.withHtmlFormatting();
148 case PushsaferMessageBuilder.MESSAGE_KEY_MONOSPACE:
149 builder.withMonospaceFormatting();
153 // add sound if defined
154 if (!DEFAULT_SOUND.equals(config.sound)) {
155 builder.withSound(config.sound);
157 // add icon if defined
158 if (!DEFAULT_ICON.equals(config.icon)) {
159 builder.withIcon(config.icon);
161 // add color if defined
162 if (!DEFAULT_COLOR.equals(config.color)) {
163 builder.withColor(config.color);
165 // add vibration if defined
166 if (!DEFAULT_VIBRATION.equals(config.vibration)) {
167 builder.withVibration(config.vibration);
169 // add url if defined
170 if (!DEFAULT_URL.equals(config.url)) {
171 builder.withUrl(config.url);
173 // add urlTitle if defined
174 if (!DEFAULT_URLTITLE.equals(config.urlTitle)) {
175 builder.withUrlTitle(config.urlTitle);
177 // add confirm if defined
178 if (DEFAULT_CONFIRM != config.confirm) {
179 builder.withConfirm(config.confirm);
181 // add answer if defined
182 if (DEFAULT_ANSWER != config.answer) {
183 builder.withAnswer(config.answer);
185 // add time2live if defined
186 if (DEFAULT_TIME2LIVE != config.time2live) {
187 builder.withTime2live(config.time2live);
192 public boolean sendPushsaferMessage(PushsaferMessageBuilder messageBuilder) {
193 if (connection != null) {
195 return connection.sendPushsaferMessage(messageBuilder);
196 } catch (PushsaferCommunicationException e) {
197 // do nothing, causing exception is already logged
198 } catch (PushsaferConfigurationException e) {
199 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
203 throw new IllegalArgumentException("PushsaferAPIConnection is null!");
207 public String sendPushsaferPriorityMessage(PushsaferMessageBuilder messageBuilder) {
208 if (connection != null) {
210 return connection.sendPushsaferPriorityMessage(messageBuilder);
211 } catch (PushsaferCommunicationException e) {
212 // do nothing, causing exception is already logged
213 } catch (PushsaferConfigurationException e) {
214 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
218 throw new IllegalArgumentException("PushsaferAPIConnection is null!");
222 public boolean cancelPushsaferPriorityMessage(String receipt) {
223 if (connection != null) {
225 return connection.cancelPushsaferPriorityMessage(receipt);
226 } catch (PushsaferCommunicationException e) {
227 // do nothing, causing exception is already logged
228 } catch (PushsaferConfigurationException e) {
229 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
233 throw new IllegalArgumentException("PushsaferAPIConnection is null!");
237 @SuppressWarnings("null")
238 private void asyncValidateUser() {
240 connection.validateUser();
241 updateStatus(ThingStatus.ONLINE);
242 } catch (PushsaferCommunicationException | PushsaferConfigurationException e) {
243 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());