]> git.basschouten.com Git - openhab-addons.git/blob
2db1e195fa8e6ec6d43c221a59d711a72f4df863
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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 void 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     }
95
96     @Override
97     protected void refreshModels() {
98         fetchModels();
99         var wifiReg = this.wifiReg;
100         if (wifiReg != null) {
101             this.lastSeen = LocalDateTime.now();
102             this.online = true;
103             var cfg = this.config;
104             int considerContinuous = 180;
105             if (cfg != null) {
106                 considerContinuous = cfg.considerContinuous;
107             }
108             txByteRate.update(wifiReg.getTxBytes());
109             rxByteRate.update(wifiReg.getRxBytes());
110             txPacketRate.update(wifiReg.getTxPackets());
111             rxPacketRate.update(wifiReg.getRxPackets());
112             LocalDateTime uptimeStart = wifiReg.getUptimeStart();
113             continuousConnection = (uptimeStart != null)
114                     && LocalDateTime.now().isAfter(uptimeStart.plusSeconds(considerContinuous));
115         } else {
116             this.online = false;
117             this.continuousConnection = false;
118         }
119     }
120
121     @Override
122     protected void refreshChannel(ChannelUID channelUID) {
123         var wifiReg = this.wifiReg;
124
125         String channelID = channelUID.getIdWithoutGroup();
126         State oldState = currentState.getOrDefault(channelID, UnDefType.NULL);
127         State newState = oldState;
128
129         if (channelID.equals(CHANNEL_CONNECTED)) {
130             newState = StateUtil.boolContactOrNull(this.online);
131         } else if (channelID.equals(CHANNEL_LAST_SEEN)) {
132             newState = StateUtil.timeOrNull(lastSeen);
133         } else if (channelID.equals(CHANNEL_CONTINUOUS)) {
134             newState = StateUtil.boolContactOrNull(this.continuousConnection);
135         } else if (!this.online || wifiReg == null) {
136             newState = UnDefType.NULL;
137         } else {
138             switch (channelID) {
139                 case CHANNEL_NAME:
140                     newState = StateUtil.stringOrNull(wifiReg.getName());
141                     break;
142                 case CHANNEL_COMMENT:
143                     newState = StateUtil.stringOrNull(wifiReg.getComment());
144                     break;
145                 case CHANNEL_MAC:
146                     newState = StateUtil.stringOrNull(wifiReg.getMacAddress());
147                     break;
148                 case CHANNEL_INTERFACE:
149                     newState = StateUtil.stringOrNull(wifiReg.getInterfaceName());
150                     break;
151                 case CHANNEL_SSID:
152                     newState = StateUtil.stringOrNull(wifiReg.getSSID());
153                     break;
154                 case CHANNEL_UP_SINCE:
155                     newState = StateUtil.timeOrNull(wifiReg.getUptimeStart());
156                     break;
157                 case CHANNEL_TX_DATA_RATE:
158                     newState = StateUtil.qtyMegabitPerSecOrNull(txByteRate.getMegabitRate());
159                     break;
160                 case CHANNEL_RX_DATA_RATE:
161                     newState = StateUtil.qtyMegabitPerSecOrNull(rxByteRate.getMegabitRate());
162                     break;
163                 case CHANNEL_TX_PACKET_RATE:
164                     newState = StateUtil.floatOrNull(txPacketRate.getRate());
165                     break;
166                 case CHANNEL_RX_PACKET_RATE:
167                     newState = StateUtil.floatOrNull(rxPacketRate.getRate());
168                     break;
169                 case CHANNEL_TX_BYTES:
170                     newState = StateUtil.bigIntOrNull(wifiReg.getTxBytes());
171                     break;
172                 case CHANNEL_RX_BYTES:
173                     newState = StateUtil.bigIntOrNull(wifiReg.getRxBytes());
174                     break;
175                 case CHANNEL_TX_PACKETS:
176                     newState = StateUtil.bigIntOrNull(wifiReg.getTxPackets());
177                     break;
178                 case CHANNEL_RX_PACKETS:
179                     newState = StateUtil.bigIntOrNull(wifiReg.getRxPackets());
180                     break;
181                 default:
182                     newState = UnDefType.NULL;
183                     if (wifiReg instanceof RouterosWirelessRegistration) {
184                         newState = getWirelessRegistrationChannelState(channelID);
185                     } else if (wifiReg instanceof RouterosCapsmanRegistration) {
186                         newState = getCapsmanRegistrationChannelState(channelID);
187                     }
188             }
189         }
190
191         if (!newState.equals(oldState)) {
192             updateState(channelID, newState);
193             currentState.put(channelID, newState);
194         }
195     }
196
197     @SuppressWarnings("null")
198     protected State getCapsmanRegistrationChannelState(String channelID) {
199         if (this.wifiReg == null) {
200             return UnDefType.UNDEF;
201         }
202
203         RouterosCapsmanRegistration capsmanReg = (RouterosCapsmanRegistration) this.wifiReg;
204         switch (channelID) {
205             case CHANNEL_SIGNAL:
206                 return StateUtil.intOrNull(capsmanReg.getRxSignal());
207             default:
208                 return UnDefType.UNDEF;
209         }
210     }
211
212     @SuppressWarnings("null")
213     protected State getWirelessRegistrationChannelState(String channelID) {
214         if (this.wifiReg == null) {
215             return UnDefType.UNDEF;
216         }
217
218         RouterosWirelessRegistration wirelessReg = (RouterosWirelessRegistration) this.wifiReg;
219         switch (channelID) {
220             case CHANNEL_SIGNAL:
221                 return StateUtil.intOrNull(wirelessReg.getRxSignal());
222             default:
223                 return UnDefType.UNDEF;
224         }
225     }
226
227     @Override
228     protected void executeCommand(ChannelUID channelUID, Command command) {
229         if (!online) {
230             return;
231         }
232         logger.warn("Ignoring unsupported command = {} for channel = {}", command, channelUID);
233     }
234 }