]> git.basschouten.com Git - openhab-addons.git/blob
20aec9d57f326cb79e0bda0b0fec92f79ac63644
[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.binding.mikrotik.internal.handler;
14
15 import static org.openhab.binding.mikrotik.internal.MikrotikBindingConstants.*;
16
17 import java.math.BigDecimal;
18 import java.time.LocalDateTime;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.mikrotik.internal.MikrotikBindingConstants;
23 import org.openhab.binding.mikrotik.internal.config.WirelessClientThingConfig;
24 import org.openhab.binding.mikrotik.internal.model.RouterosCapsmanRegistration;
25 import org.openhab.binding.mikrotik.internal.model.RouterosDevice;
26 import org.openhab.binding.mikrotik.internal.model.RouterosRegistrationBase;
27 import org.openhab.binding.mikrotik.internal.model.RouterosWirelessRegistration;
28 import org.openhab.binding.mikrotik.internal.util.RateCalculator;
29 import org.openhab.binding.mikrotik.internal.util.StateUtil;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingTypeUID;
33 import org.openhab.core.types.Command;
34 import org.openhab.core.types.State;
35 import org.openhab.core.types.UnDefType;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * The {@link MikrotikWirelessClientThingHandler} is a {@link MikrotikBaseThingHandler} subclass that wraps shared
41  * functionality for all wireless clients listed either in CAPsMAN or Wireless RouterOS sections.
42  * It is responsible for handling commands, which are sent to one of the channels and emit channel updates whenever
43  * required.
44  *
45  * @author Oleg Vivtash - Initial contribution
46  */
47 @NonNullByDefault
48 public class MikrotikWirelessClientThingHandler extends MikrotikBaseThingHandler<WirelessClientThingConfig> {
49     private final Logger logger = LoggerFactory.getLogger(MikrotikWirelessClientThingHandler.class);
50
51     private @Nullable RouterosRegistrationBase wifiReg;
52
53     private boolean online = false;
54     private boolean continuousConnection = false;
55     private @Nullable LocalDateTime lastSeen;
56
57     private final RateCalculator txByteRate = new RateCalculator(BigDecimal.ZERO);
58     private final RateCalculator rxByteRate = new RateCalculator(BigDecimal.ZERO);
59     private final RateCalculator txPacketRate = new RateCalculator(BigDecimal.ZERO);
60     private final RateCalculator rxPacketRate = new RateCalculator(BigDecimal.ZERO);
61
62     public static boolean supportsThingType(ThingTypeUID thingTypeUID) {
63         return MikrotikBindingConstants.THING_TYPE_WIRELESS_CLIENT.equals(thingTypeUID);
64     }
65
66     public MikrotikWirelessClientThingHandler(Thing thing) {
67         super(thing);
68     }
69
70     private boolean fetchModels() {
71         var cfg = this.config;
72         if (cfg != null) {
73             RouterosDevice routeros = getRouterOs();
74
75             RouterosWirelessRegistration wifiRegistration = null;
76             if (routeros != null) {
77                 wifiRegistration = routeros.findWirelessRegistration(cfg.mac);
78             }
79             this.wifiReg = wifiRegistration;
80             if (wifiRegistration != null && !cfg.ssid.isBlank()
81                     && !cfg.ssid.equalsIgnoreCase(wifiRegistration.getSSID())) {
82                 this.wifiReg = null;
83             }
84
85             if (this.wifiReg == null && routeros != null) {
86                 // try looking in capsman when there is no wirelessRegistration
87                 RouterosCapsmanRegistration capsmanReg = routeros.findCapsmanRegistration(cfg.mac);
88                 this.wifiReg = capsmanReg;
89                 if (capsmanReg != null && !cfg.ssid.isBlank() && !cfg.ssid.equalsIgnoreCase(capsmanReg.getSSID())) {
90                     this.wifiReg = null;
91                 }
92             }
93         }
94         return this.wifiReg != null;
95     }
96
97     @Override
98     protected void refreshModels() {
99         this.online = fetchModels();
100         if (online) {
101             lastSeen = LocalDateTime.now();
102         } else {
103             continuousConnection = false;
104         }
105         var wifiReg = this.wifiReg;
106         if (wifiReg != null) {
107             var cfg = this.config;
108             int considerContinuous = 180;
109             if (cfg != null) {
110                 considerContinuous = cfg.considerContinuous;
111             }
112             txByteRate.update(wifiReg.getTxBytes());
113             rxByteRate.update(wifiReg.getRxBytes());
114             txPacketRate.update(wifiReg.getTxPackets());
115             rxPacketRate.update(wifiReg.getRxPackets());
116             LocalDateTime uptimeStart = wifiReg.getUptimeStart();
117             continuousConnection = (uptimeStart != null)
118                     && LocalDateTime.now().isAfter(uptimeStart.plusSeconds(considerContinuous));
119         }
120     }
121
122     @Override
123     protected void refreshChannel(ChannelUID channelUID) {
124         var wifiReg = this.wifiReg;
125         if (wifiReg == null) {
126             logger.warn("wifiReg is null in refreshChannel({})", channelUID);
127             return;
128         }
129
130         String channelID = channelUID.getIdWithoutGroup();
131         State oldState = currentState.getOrDefault(channelID, UnDefType.NULL);
132         State newState = oldState;
133
134         if (channelID.equals(CHANNEL_CONNECTED)) {
135             newState = StateUtil.boolOrNull(online);
136         } else if (channelID.equals(CHANNEL_LAST_SEEN)) {
137             newState = StateUtil.timeOrNull(lastSeen);
138         } else if (channelID.equals(CHANNEL_CONTINUOUS)) {
139             newState = StateUtil.boolOrNull(continuousConnection);
140         } else if (!online) {
141             newState = UnDefType.NULL;
142         } else {
143             switch (channelID) {
144                 case CHANNEL_NAME:
145                     newState = StateUtil.stringOrNull(wifiReg.getName());
146                     break;
147                 case CHANNEL_COMMENT:
148                     newState = StateUtil.stringOrNull(wifiReg.getComment());
149                     break;
150                 case CHANNEL_MAC:
151                     newState = StateUtil.stringOrNull(wifiReg.getMacAddress());
152                     break;
153                 case CHANNEL_INTERFACE:
154                     newState = StateUtil.stringOrNull(wifiReg.getInterfaceName());
155                     break;
156                 case CHANNEL_SSID:
157                     newState = StateUtil.stringOrNull(wifiReg.getSSID());
158                     break;
159                 case CHANNEL_UP_SINCE:
160                     newState = StateUtil.timeOrNull(wifiReg.getUptimeStart());
161                     break;
162                 case CHANNEL_TX_DATA_RATE:
163                     newState = StateUtil.qtyMegabitPerSecOrNull(txByteRate.getMegabitRate());
164                     break;
165                 case CHANNEL_RX_DATA_RATE:
166                     newState = StateUtil.qtyMegabitPerSecOrNull(rxByteRate.getMegabitRate());
167                     break;
168                 case CHANNEL_TX_PACKET_RATE:
169                     newState = StateUtil.floatOrNull(txPacketRate.getRate());
170                     break;
171                 case CHANNEL_RX_PACKET_RATE:
172                     newState = StateUtil.floatOrNull(rxPacketRate.getRate());
173                     break;
174                 case CHANNEL_TX_BYTES:
175                     newState = StateUtil.bigIntOrNull(wifiReg.getTxBytes());
176                     break;
177                 case CHANNEL_RX_BYTES:
178                     newState = StateUtil.bigIntOrNull(wifiReg.getRxBytes());
179                     break;
180                 case CHANNEL_TX_PACKETS:
181                     newState = StateUtil.bigIntOrNull(wifiReg.getTxPackets());
182                     break;
183                 case CHANNEL_RX_PACKETS:
184                     newState = StateUtil.bigIntOrNull(wifiReg.getRxPackets());
185                     break;
186                 default:
187                     newState = UnDefType.NULL;
188                     if (wifiReg instanceof RouterosWirelessRegistration) {
189                         newState = getWirelessRegistrationChannelState(channelID);
190                     } else if (wifiReg instanceof RouterosCapsmanRegistration) {
191                         newState = getCapsmanRegistrationChannelState(channelID);
192                     }
193             }
194         }
195
196         if (!newState.equals(oldState)) {
197             updateState(channelID, newState);
198             currentState.put(channelID, newState);
199         }
200     }
201
202     @SuppressWarnings("null")
203     protected State getCapsmanRegistrationChannelState(String channelID) {
204         if (this.wifiReg == null) {
205             return UnDefType.UNDEF;
206         }
207
208         RouterosCapsmanRegistration capsmanReg = (RouterosCapsmanRegistration) this.wifiReg;
209         switch (channelID) {
210             case CHANNEL_SIGNAL:
211                 return StateUtil.intOrNull(capsmanReg.getRxSignal());
212             default:
213                 return UnDefType.UNDEF;
214         }
215     }
216
217     @SuppressWarnings("null")
218     protected State getWirelessRegistrationChannelState(String channelID) {
219         if (this.wifiReg == null) {
220             return UnDefType.UNDEF;
221         }
222
223         RouterosWirelessRegistration wirelessReg = (RouterosWirelessRegistration) this.wifiReg;
224         switch (channelID) {
225             case CHANNEL_SIGNAL:
226                 return StateUtil.intOrNull(wirelessReg.getRxSignal());
227             default:
228                 return UnDefType.UNDEF;
229         }
230     }
231
232     @Override
233     protected void executeCommand(ChannelUID channelUID, Command command) {
234         if (!online) {
235             return;
236         }
237         logger.warn("Ignoring unsupported command = {} for channel = {}", command, channelUID);
238     }
239 }