]> git.basschouten.com Git - openhab-addons.git/blob
90501cb7927b73210fda3114b5128ba1f7265522
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.binding.unifi.internal.handler;
14
15 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_ENABLE_PARAMETER_MODE;
16 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_ENABLE_PARAMETER_MODE_AUTO;
17 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_ENABLE_PARAMETER_MODE_OFF;
18 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_ONLINE;
19 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_PORT_POE_CMD;
20 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_PORT_POE_CMD_POWER_CYCLE;
21 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_PORT_POE_CURRENT;
22 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_PORT_POE_ENABLE;
23 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_PORT_POE_MODE;
24 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_PORT_POE_POWER;
25 import static org.openhab.binding.unifi.internal.UniFiBindingConstants.CHANNEL_PORT_POE_VOLTAGE;
26 import static org.openhab.core.library.unit.MetricPrefix.MILLI;
27
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Objects;
31 import java.util.stream.Collectors;
32
33 import javax.measure.quantity.ElectricCurrent;
34 import javax.measure.quantity.ElectricPotential;
35 import javax.measure.quantity.Power;
36
37 import org.eclipse.jdt.annotation.NonNullByDefault;
38 import org.eclipse.jdt.annotation.Nullable;
39 import org.openhab.binding.unifi.internal.UniFiPoePortThingConfig;
40 import org.openhab.binding.unifi.internal.api.UniFiController;
41 import org.openhab.binding.unifi.internal.api.UniFiException;
42 import org.openhab.binding.unifi.internal.api.cache.UniFiControllerCache;
43 import org.openhab.binding.unifi.internal.api.dto.UnfiPortOverrideJsonElement;
44 import org.openhab.binding.unifi.internal.api.dto.UniFiDevice;
45 import org.openhab.binding.unifi.internal.api.dto.UniFiPortTable;
46 import org.openhab.binding.unifi.internal.api.dto.UniFiPortTuple;
47 import org.openhab.core.library.types.OnOffType;
48 import org.openhab.core.library.types.QuantityType;
49 import org.openhab.core.library.types.StringType;
50 import org.openhab.core.library.unit.Units;
51 import org.openhab.core.thing.ChannelUID;
52 import org.openhab.core.thing.Thing;
53 import org.openhab.core.thing.ThingStatus;
54 import org.openhab.core.thing.ThingStatusDetail;
55 import org.openhab.core.types.Command;
56 import org.openhab.core.types.State;
57 import org.openhab.core.types.UnDefType;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 /**
62  * A Power Over Ethernet (PoE) port on a UniFi switch.
63  *
64  * @author Hilbrand Bouwkamp - Initial contribution
65  */
66 @NonNullByDefault
67 public class UniFiPoePortThingHandler
68         extends UniFiBaseThingHandler<Map<Integer, UniFiPortTuple>, UniFiPoePortThingConfig> {
69
70     private final Logger logger = LoggerFactory.getLogger(UniFiPoePortThingHandler.class);
71
72     private UniFiPoePortThingConfig config = new UniFiPoePortThingConfig();
73     private String poeEnableMode = "";
74
75     public UniFiPoePortThingHandler(final Thing thing) {
76         super(thing);
77     }
78
79     @Override
80     protected boolean initialize(final UniFiPoePortThingConfig config) {
81         this.config = config;
82         if (!config.isValid()) {
83             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
84                     "@text/error.thing.poe.offline.configuration_error");
85             return false;
86         }
87         final String channelConfigPoeEnableMode = (String) getThing().getChannel(CHANNEL_PORT_POE_ENABLE)
88                 .getConfiguration().get(CHANNEL_ENABLE_PARAMETER_MODE);
89         poeEnableMode = channelConfigPoeEnableMode.isBlank() ? CHANNEL_ENABLE_PARAMETER_MODE_AUTO
90                 : channelConfigPoeEnableMode;
91         return true;
92     }
93
94     @Override
95     protected @Nullable Map<Integer, UniFiPortTuple> getEntity(final UniFiControllerCache cache) {
96         return cache.getSwitchPorts(config.getMacAddress());
97     }
98
99     @Override
100     protected State getChannelState(final Map<Integer, UniFiPortTuple> ports, final String channelId) {
101         final UniFiPortTuple portTuple = getPort(ports);
102
103         if (portTuple == null) {
104             return setOfflineOnNoPoEPortData();
105         }
106         final UniFiPortTable port = portTuple.getTable();
107
108         if (port == null) {
109             return setOfflineOnNoPoEPortData();
110         }
111         final State state;
112
113         switch (channelId) {
114             case CHANNEL_ONLINE:
115                 state = OnOffType.from(port.isUp());
116                 break;
117             case CHANNEL_PORT_POE_ENABLE:
118                 state = OnOffType.from(port.isPoeEnabled());
119                 break;
120             case CHANNEL_PORT_POE_MODE:
121                 state = StringType.valueOf(port.getPoeMode());
122                 break;
123             case CHANNEL_PORT_POE_POWER:
124                 state = new QuantityType<Power>(Double.valueOf(port.getPoePower()), Units.WATT);
125                 break;
126             case CHANNEL_PORT_POE_VOLTAGE:
127                 state = new QuantityType<ElectricPotential>(Double.valueOf(port.getPoeVoltage()), Units.VOLT);
128                 break;
129             case CHANNEL_PORT_POE_CURRENT:
130                 state = new QuantityType<ElectricCurrent>(Double.valueOf(port.getPoeCurrent()), MILLI(Units.AMPERE));
131                 break;
132             default:
133                 state = UnDefType.UNDEF;
134         }
135         return state;
136     }
137
138     private State setOfflineOnNoPoEPortData() {
139         if (getThing().getStatus() != ThingStatus.OFFLINE) {
140             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
141                     "@text/error.thing.poe.offline.nodata_error");
142         }
143         return UnDefType.NULL;
144     }
145
146     private @Nullable UniFiPortTuple getPort(final Map<Integer, UniFiPortTuple> ports) {
147         return ports.get(config.getPortNumber());
148     }
149
150     @Override
151     protected boolean handleCommand(final UniFiController controller, final Map<Integer, UniFiPortTuple> ports,
152             final ChannelUID channelUID, final Command command) throws UniFiException {
153         final String channelID = channelUID.getIdWithoutGroup();
154
155         switch (channelID) {
156             case CHANNEL_PORT_POE_ENABLE:
157                 if (command instanceof OnOffType) {
158                     return handleModeCommand(controller, ports, getPort(ports),
159                             OnOffType.ON == command ? poeEnableMode : CHANNEL_ENABLE_PARAMETER_MODE_OFF);
160                 }
161                 break;
162             case CHANNEL_PORT_POE_MODE:
163                 if (command instanceof StringType) {
164                     return handleModeCommand(controller, ports, getPort(ports), command.toFullString());
165                 }
166                 break;
167             case CHANNEL_PORT_POE_CMD:
168                 if (command instanceof StringType) {
169                     return handleCmd(controller, getPort(ports), command.toFullString());
170                 }
171             default:
172                 return false;
173         }
174         return false;
175     }
176
177     private boolean handleModeCommand(final UniFiController controller, final Map<Integer, UniFiPortTuple> ports,
178             final @Nullable UniFiPortTuple uniFiPortTuple, final String poeMode) throws UniFiException {
179         final UniFiDevice device = controller.getCache().getDevice(config.getMacAddress());
180
181         if (device == null || uniFiPortTuple == null) {
182             logger.info("Could not change the PoE port state for thing '{}': device {} or portToUpdate {} null",
183                     getThing().getUID(), device, uniFiPortTuple);
184         } else {
185             final List<UnfiPortOverrideJsonElement> updatedList = ports.entrySet().stream()
186                     .map(e -> e.getValue().getJsonElement()).filter(Objects::nonNull).collect(Collectors.toList());
187
188             updatedList.stream().filter(p -> p.getPortIdx() == uniFiPortTuple.getPortIdx()).findAny()
189                     .ifPresent(p -> p.setPoeMode(poeMode));
190             controller.poeMode(device, updatedList);
191             // No refresh because UniFi device takes some time to update. Therefore a refresh would only show the
192             // old state.
193         }
194         return true;
195     }
196
197     private boolean handleCmd(final UniFiController controller, @Nullable final UniFiPortTuple portToUpdate,
198             final String command) throws UniFiException {
199         final UniFiDevice device = controller.getCache().getDevice(config.getMacAddress());
200         if (device == null || portToUpdate == null) {
201             logger.info("Could not change the PoE port state for thing '{}': device {} or portToUpdate {} null",
202                     getThing().getUID(), device, portToUpdate);
203         } else {
204             if (CHANNEL_PORT_POE_CMD_POWER_CYCLE.equalsIgnoreCase(command.replaceAll("[- ]", ""))) {
205                 controller.poePowerCycle(device, portToUpdate.getPortIdx());
206             } else {
207                 logger.info("Unknown command '{}' given to PoE port for thing '{}': device {} or portToUpdate {} null",
208                         command, getThing().getUID(), device, portToUpdate);
209             }
210         }
211         return true;
212     }
213 }