2 * Copyright (c) 2010-2020 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.io.neeo.internal;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.HashSet;
18 import java.util.List;
20 import java.util.Objects;
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;
45 * The class will handle the conversion between a {@link Thing} and a {@link NeeoDevice}
47 * @author Tim Roberts - Initial Contribution
50 class OpenHabToDeviceConverter {
53 private final Logger logger = LoggerFactory.getLogger(OpenHabToDeviceConverter.class);
55 /** The service context */
56 private final ServiceContext context;
58 /** Whether to expose all items by default or not */
59 private final boolean exposeAll;
61 /** Whether to expose things by the NEEO binding by default or not */
62 private final boolean exposeNeeoBinding;
65 * Constructs the object from the give {@link ServiceContext}
67 * @param context the non-null service context
69 OpenHabToDeviceConverter(ServiceContext context) {
70 Objects.requireNonNull(context, "context cannot be null");
72 this.context = context;
74 exposeAll = context.isExposeAllThings();
75 exposeNeeoBinding = context.isExposeNeeoBinding();
79 * Convert the {@link Thing} to a {@link NeeoDevice}
81 * @param thing the non-null thing
82 * @return a potentially null neeo device
85 NeeoDevice convert(Thing thing) {
86 Objects.requireNonNull(thing, "thing cannot be null");
88 final List<NeeoDeviceChannel> channels = new ArrayList<>();
90 final ThingUID thingUID = thing.getUID();
91 final Set<String> existingLabels = new HashSet<>();
93 for (Channel channel : thing.getChannels()) {
94 final ChannelUID uid = channel.getUID();
96 if (channel.getKind() == ChannelKind.TRIGGER) {
98 NeeoDeviceChannel.from(channel, NeeoCapabilityType.BUTTON, ItemSubType.NONE, existingLabels));
100 final ChannelType channelType = context.getChannelTypeRegistry()
101 .getChannelType(channel.getChannelTypeUID());
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;
109 type = NeeoCapabilityType.guessType(channelType);
111 } else if (exposeAll) {
112 type = NeeoCapabilityType.guessType(channelType);
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));
125 if (channels.isEmpty()) {
126 logger.debug("No linked channels found for thing {} - ignoring", thing.getLabel());
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();
137 String manufacturer = properties.get("Manufacturer");
138 if (manufacturer == null || manufacturer.isEmpty()) {
139 manufacturer = "openHAB";
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"));
145 final NeeoDeviceTiming timing = new NeeoDeviceTiming(standbyDelay, switchDelay, shutDownDelay);
147 final String dc = properties.get("Device Capabilities");
148 final String[] deviceCapabilities = StringUtils.isEmpty(dc) ? new String[0] : StringUtils.split(dc, ',');
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(),
161 return new NeeoDevice(thing, channels, exposeAll ? NeeoUtil.guessType(thing) : NeeoDeviceType.EXCLUDE,
163 } catch (IllegalArgumentException e) {
164 logger.debug("NeeoDevice constructor threw an IAE - ignoring device: {} - {}", thing.getUID(),
172 * Helper method to parse a value to an Integer (or null if not a number)
174 * @param value a possibly null, possibly empty value to parse
175 * @return an Integer or null if not a number
178 private static Integer parseInteger(String value) {
179 if (StringUtils.isEmpty(value)) {
183 return Integer.parseInt(value);
184 } catch (NumberFormatException e) {
190 * Returns a {@link NeeoDeviceChannel} that represents the given itemname (or null if itemname is not found)
192 * @param itemName a possibly empty, possibly null item name
193 * @return a {@link NeeoDeviceChannel} representing the item name or null if not found
196 List<NeeoDeviceChannel> getNeeoDeviceChannel(String itemName) {
197 if (StringUtils.isEmpty(itemName)) {
202 final Item item = context.getItemRegistry().getItem(itemName);
203 return NeeoDeviceChannel.from(item, null, null, NeeoCapabilityType.EXCLUDE, new HashSet<>());
204 } catch (ItemNotFoundException e) {