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