]> git.basschouten.com Git - openhab-addons.git/blob
b1abc54cae6b65aeca763e58f215ce1f1d061467
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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             String neeoType = properties.get("Type");
134             if (neeoType == null || neeoType.isEmpty()) {
135                 neeoType = NeeoDeviceType.ACCESSOIRE.toString();
136             }
137             String manufacturer = properties.get("Manufacturer");
138             if (manufacturer == null || manufacturer.isEmpty()) {
139                 manufacturer = "openHAB";
140             }
141             final Integer standbyDelay = parseInteger(properties.getOrDefault("Standby Command Delay", "0"));
142             final Integer switchDelay = parseInteger(properties.getOrDefault("Source Switch Delay", "0"));
143             final Integer shutDownDelay = parseInteger(properties.getOrDefault("Shutdown Delay", "0"));
144
145             final NeeoDeviceTiming timing = new NeeoDeviceTiming(standbyDelay, switchDelay, shutDownDelay);
146
147             final String dc = properties.get("Device Capabilities");
148             final String[] deviceCapabilities = StringUtils.isEmpty(dc) ? new String[0] : StringUtils.split(dc, ',');
149
150             try {
151                 return new NeeoDevice(new NeeoThingUID(thing.getUID()), 0,
152                         exposeNeeoBinding ? NeeoDeviceType.parse(neeoType) : NeeoDeviceType.EXCLUDE, manufacturer,
153                         thing.getLabel(), channels, timing, Arrays.asList(deviceCapabilities), null, null);
154             } catch (IllegalArgumentException e) {
155                 logger.debug("NeeoDevice constructor threw an IAE - ignoring device: {} - {}", thing.getUID(),
156                         e.getMessage(), e);
157                 return null;
158             }
159         } else {
160             try {
161                 return new NeeoDevice(thing, channels, exposeAll ? NeeoUtil.guessType(thing) : NeeoDeviceType.EXCLUDE,
162                         null);
163             } catch (IllegalArgumentException e) {
164                 logger.debug("NeeoDevice constructor threw an IAE - ignoring device: {} - {}", thing.getUID(),
165                         e.getMessage(), e);
166                 return null;
167             }
168         }
169     }
170
171     /**
172      * Helper method to parse a value to an Integer (or null if not a number)
173      *
174      * @param value a possibly null, possibly empty value to parse
175      * @return an Integer or null if not a number
176      */
177     @Nullable
178     private static Integer parseInteger(String value) {
179         if (StringUtils.isEmpty(value)) {
180             return null;
181         }
182         try {
183             return Integer.parseInt(value);
184         } catch (NumberFormatException e) {
185             return null;
186         }
187     }
188
189     /**
190      * Returns a {@link NeeoDeviceChannel} that represents the given itemname (or null if itemname is not found)
191      *
192      * @param itemName a possibly empty, possibly null item name
193      * @return a {@link NeeoDeviceChannel} representing the item name or null if not found
194      */
195     @Nullable
196     List<NeeoDeviceChannel> getNeeoDeviceChannel(String itemName) {
197         if (StringUtils.isEmpty(itemName)) {
198             return null;
199         }
200
201         try {
202             final Item item = context.getItemRegistry().getItem(itemName);
203             return NeeoDeviceChannel.from(item, null, null, NeeoCapabilityType.EXCLUDE, new HashSet<>());
204         } catch (ItemNotFoundException e) {
205             return null;
206         }
207     }
208 }