]> git.basschouten.com Git - openhab-addons.git/blob
5d9738817bb51c6a64a3fa2f9bfd31555bfef4ea
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.io.neeo.internal;
14
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Objects;
21 import java.util.Set;
22
23 import org.apache.commons.lang.StringUtils;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.core.items.Item;
27 import org.openhab.core.items.ItemNotFoundException;
28 import org.openhab.core.thing.Channel;
29 import org.openhab.core.thing.ChannelUID;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingUID;
32 import org.openhab.core.thing.type.ChannelKind;
33 import org.openhab.core.thing.type.ChannelType;
34 import org.openhab.io.neeo.internal.models.ItemSubType;
35 import org.openhab.io.neeo.internal.models.NeeoCapabilityType;
36 import org.openhab.io.neeo.internal.models.NeeoDevice;
37 import org.openhab.io.neeo.internal.models.NeeoDeviceChannel;
38 import org.openhab.io.neeo.internal.models.NeeoDeviceTiming;
39 import org.openhab.io.neeo.internal.models.NeeoDeviceType;
40 import org.openhab.io.neeo.internal.models.NeeoThingUID;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 /**
45  * The class will handle the conversion between a {@link Thing} and a {@link NeeoDevice}
46  *
47  * @author Tim Roberts - Initial Contribution
48  */
49 @NonNullByDefault
50 class OpenHabToDeviceConverter {
51
52     /** The logger */
53     private final Logger logger = LoggerFactory.getLogger(OpenHabToDeviceConverter.class);
54
55     /** The service context */
56     private final ServiceContext context;
57
58     /** Whether to expose all items by default or not */
59     private final boolean exposeAll;
60
61     /** Whether to expose things by the NEEO binding by default or not */
62     private final boolean exposeNeeoBinding;
63
64     /**
65      * Constructs the object from the give {@link ServiceContext}
66      *
67      * @param context the non-null service context
68      */
69     OpenHabToDeviceConverter(ServiceContext context) {
70         Objects.requireNonNull(context, "context cannot be null");
71
72         this.context = context;
73
74         exposeAll = context.isExposeAllThings();
75         exposeNeeoBinding = context.isExposeNeeoBinding();
76     }
77
78     /**
79      * Convert the {@link Thing} to a {@link NeeoDevice}
80      *
81      * @param thing the non-null thing
82      * @return a potentially null neeo device
83      */
84     @Nullable
85     NeeoDevice convert(Thing thing) {
86         Objects.requireNonNull(thing, "thing cannot be null");
87
88         final List<NeeoDeviceChannel> channels = new ArrayList<>();
89
90         final ThingUID thingUID = thing.getUID();
91         final Set<String> existingLabels = new HashSet<>();
92
93         for (Channel channel : thing.getChannels()) {
94             final ChannelUID uid = channel.getUID();
95
96             if (channel.getKind() == ChannelKind.TRIGGER) {
97                 channels.addAll(
98                         NeeoDeviceChannel.from(channel, NeeoCapabilityType.BUTTON, ItemSubType.NONE, existingLabels));
99             } else {
100                 final ChannelType channelType = context.getChannelTypeRegistry()
101                         .getChannelType(channel.getChannelTypeUID());
102
103                 NeeoCapabilityType type = NeeoCapabilityType.EXCLUDE;
104                 if (StringUtils.equalsIgnoreCase(NeeoConstants.NEEOBINDING_BINDING_ID, thingUID.getBindingId())) {
105                     if (StringUtils.startsWithIgnoreCase(thingUID.getAsString(), NeeoConstants.NEEOBINDING_DEVICE_ID)) {
106                         // all device channels are currently macros - so buttons are appropriate
107                         type = NeeoCapabilityType.BUTTON;
108                     } else {
109                         type = NeeoCapabilityType.guessType(channelType);
110                     }
111                 } else if (exposeAll) {
112                     type = NeeoCapabilityType.guessType(channelType);
113                 }
114
115                 final Set<Item> linkedItems = context.getItemChannelLinkRegistry().getLinkedItems(uid);
116                 if (linkedItems != null) {
117                     for (Item item : linkedItems) {
118                         channels.addAll(NeeoDeviceChannel.from(item, channel, channelType, type, existingLabels));
119                     }
120                 }
121             }
122
123         }
124
125         if (channels.isEmpty()) {
126             logger.debug("No linked channels found for thing {} - ignoring", thing.getLabel());
127             return null;
128         }
129
130         if (StringUtils.equalsIgnoreCase(NeeoConstants.NEEOBINDING_BINDING_ID, thing.getUID().getBindingId())) {
131             final Map<String, String> properties = thing.getProperties();
132             /** The following properties have matches in org.openhab.binding.neeo.NeeoDeviceHandler.java */
133             final String neeoType = StringUtils.isEmpty(properties.get("Type")) ? NeeoDeviceType.ACCESSOIRE.toString()
134                     : properties.get("Type");
135             final String manufacturer = StringUtils.isEmpty(properties.get("Manufacturer")) ? "openHAB"
136                     : properties.get("Manufacturer");
137
138             final Integer standbyDelay = parseInteger(properties.getOrDefault("Standby Command Delay", "0"));
139             final Integer switchDelay = parseInteger(properties.getOrDefault("Source Switch Delay", "0"));
140             final Integer shutDownDelay = parseInteger(properties.getOrDefault("Shutdown Delay", "0"));
141
142             final NeeoDeviceTiming timing = new NeeoDeviceTiming(standbyDelay, switchDelay, shutDownDelay);
143
144             final String dc = properties.get("Device Capabilities");
145             final String[] deviceCapabilities = StringUtils.isEmpty(dc) ? new String[0] : StringUtils.split(dc, ',');
146
147             try {
148                 return new NeeoDevice(new NeeoThingUID(thing.getUID()), 0,
149                         exposeNeeoBinding ? NeeoDeviceType.parse(neeoType) : NeeoDeviceType.EXCLUDE, manufacturer,
150                         thing.getLabel(), channels, timing, Arrays.asList(deviceCapabilities), null, null);
151             } catch (IllegalArgumentException e) {
152                 logger.debug("NeeoDevice constructor threw an IAE - ignoring device: {} - {}", thing.getUID(),
153                         e.getMessage(), e);
154                 return null;
155             }
156         } else {
157             try {
158                 return new NeeoDevice(thing, channels, exposeAll ? NeeoUtil.guessType(thing) : NeeoDeviceType.EXCLUDE,
159                         null);
160             } catch (IllegalArgumentException e) {
161                 logger.debug("NeeoDevice constructor threw an IAE - ignoring device: {} - {}", thing.getUID(),
162                         e.getMessage(), e);
163                 return null;
164             }
165         }
166     }
167
168     /**
169      * Helper method to parse a value to an Integer (or null if not a number)
170      *
171      * @param value a possibly null, possibly empty value to parse
172      * @return an Integer or null if not a number
173      */
174     @Nullable
175     private static Integer parseInteger(String value) {
176         if (StringUtils.isEmpty(value)) {
177             return null;
178         }
179         try {
180             return Integer.parseInt(value);
181         } catch (NumberFormatException e) {
182             return null;
183         }
184     }
185
186     /**
187      * Returns a {@link NeeoDeviceChannel} that represents the given itemname (or null if itemname is not found)
188      *
189      * @param itemName a possibly empty, possibly null item name
190      * @return a {@link NeeoDeviceChannel} representing the item name or null if not found
191      */
192     @Nullable
193     List<NeeoDeviceChannel> getNeeoDeviceChannel(String itemName) {
194         if (StringUtils.isEmpty(itemName)) {
195             return null;
196         }
197
198         try {
199             final Item item = context.getItemRegistry().getItem(itemName);
200             return NeeoDeviceChannel.from(item, null, null, NeeoCapabilityType.EXCLUDE, new HashSet<>());
201         } catch (ItemNotFoundException e) {
202             return null;
203         }
204     }
205 }