From: Matthew Skinner Date: Fri, 18 Oct 2024 13:02:50 +0000 (+1100) Subject: [Mikrotik] Add support for RouterOS 7 devices and support internal radios with capsma... X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=5de7773c61af8adb647d883fc3c063e116aa4935;p=openhab-addons.git [Mikrotik] Add support for RouterOS 7 devices and support internal radios with capsman disabled (#17547) * Add support for API version 7 and AX wifi6 range of devices. Signed-off-by: Matthew Skinner --- diff --git a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/handler/MikrotikBaseThingHandler.java b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/handler/MikrotikBaseThingHandler.java index d83fb8fb16..9967bf45ef 100644 --- a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/handler/MikrotikBaseThingHandler.java +++ b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/handler/MikrotikBaseThingHandler.java @@ -12,8 +12,7 @@ */ package org.openhab.binding.mikrotik.internal.handler; -import static org.openhab.core.thing.ThingStatus.OFFLINE; -import static org.openhab.core.thing.ThingStatus.ONLINE; +import static org.openhab.core.thing.ThingStatus.*; import static org.openhab.core.thing.ThingStatusDetail.CONFIGURATION_ERROR; import static org.openhab.core.types.RefreshType.REFRESH; @@ -63,8 +62,6 @@ public abstract class MikrotikBaseThingHandler exten protected ExpiringCache refreshCache = new ExpiringCache<>(Duration.ofDays(1), () -> false); protected Map currentState = new HashMap<>(); - // public static boolean supportsThingType(ThingTypeUID thingTypeUID) <- in subclasses - public MikrotikBaseThingHandler(Thing thing) { super(thing); } diff --git a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/handler/MikrotikInterfaceThingHandler.java b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/handler/MikrotikInterfaceThingHandler.java index e951d679c0..f787d02959 100644 --- a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/handler/MikrotikInterfaceThingHandler.java +++ b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/handler/MikrotikInterfaceThingHandler.java @@ -12,8 +12,7 @@ */ package org.openhab.binding.mikrotik.internal.handler; -import static org.openhab.core.thing.ThingStatus.OFFLINE; -import static org.openhab.core.thing.ThingStatus.ONLINE; +import static org.openhab.core.thing.ThingStatus.*; import static org.openhab.core.thing.ThingStatusDetail.GONE; import java.math.BigDecimal; @@ -31,6 +30,7 @@ import org.openhab.binding.mikrotik.internal.model.RouterosL2TPSrvInterface; import org.openhab.binding.mikrotik.internal.model.RouterosLTEInterface; import org.openhab.binding.mikrotik.internal.model.RouterosPPPCliInterface; import org.openhab.binding.mikrotik.internal.model.RouterosPPPoECliInterface; +import org.openhab.binding.mikrotik.internal.model.RouterosWifiInterface; import org.openhab.binding.mikrotik.internal.model.RouterosWlanInterface; import org.openhab.binding.mikrotik.internal.util.RateCalculator; import org.openhab.binding.mikrotik.internal.util.StateUtil; @@ -184,6 +184,8 @@ public class MikrotikInterfaceThingHandler extends MikrotikBaseThingHandler { + logger.trace("Interface Details:{}", props.toString()); Optional ifaceOpt = createTypedInterface(props); if (ifaceOpt.isPresent()) { RouterosInterfaceBase iface = ifaceOpt.get(); @@ -215,12 +239,14 @@ public class RouterosDevice { } }); + // Checks if any new interfaces have been setup since last check Map> typedIfaceResponse = new HashMap<>(); for (String ifaceApiType : interfaceTypesToPoll) { String cmd = String.format(CMD_PRINT_IFACE_TYPE_TPL, ifaceApiType); if (ifaceApiType.compareTo("cap") == 0) { cmd = CMD_PRINT_CAPS_IFACES; } + logger.debug("Command used for updating the interfaces is:{}", cmd); connection.execute(cmd).forEach(propMap -> { String ifaceName = propMap.get(PROP_NAME_KEY); if (ifaceName != null) { @@ -235,24 +261,36 @@ public class RouterosDevice { for (RouterosInterfaceBase ifaceModel : interfaceCache) { // Enrich with detailed data - Map additionalIfaceProps = typedIfaceResponse.get(ifaceModel.getName()); if (additionalIfaceProps != null) { ifaceModel.mergeProps(additionalIfaceProps); } - // Get monitor data + // Get monitor data, runs if you have added an interface thing. if (ifaceModel.hasMonitor() && monitoredInterfaces.contains(ifaceModel.getName())) { String cmd = String.format(CMD_MONTOR_IFACE_MONITOR_TPL, ifaceModel.getApiType(), ifaceModel.getName()); + if (logger.isDebugEnabled()) { + logger.debug("Getting detailed data for Interface:{}, with command:{}", ifaceModel.getName(), cmd); + } List> monitorProps = connection.execute(cmd); ifaceModel.mergeProps(monitorProps.get(0)); } // Note SSIDs for non-CAPsMAN wireless clients String ifaceName = ifaceModel.getName(); - String ifaceSsid = ifaceModel.getProperty(PROP_SSID_KEY); + String ifaceSsid; + switch (ifaceModel.getApiType()) { + case "wifi": + ifaceSsid = ifaceModel.getProperty(PROP_CONFIG_SSID_KEY); + break; + case "caps": + case "wireless": + default: + ifaceSsid = ifaceModel.getProperty(PROP_SSID_KEY); + } if (ifaceName != null && ifaceSsid != null && !ifaceName.isBlank() && !ifaceSsid.isBlank()) { this.wlanSsid.put(ifaceName, ifaceSsid); } } + logger.debug("Found the following SSID's:{}", wlanSsid.toString()); } private void updateCapsmanRegistrations() throws MikrotikApiException { @@ -273,7 +311,6 @@ public class RouterosDevice { return; } List> response = conn.execute(CMD_PRINT_WIRELESS_REGS); - wirelessRegistrationCache.clear(); response.forEach(props -> { String wlanIfaceName = props.get("interface"); String wlanSsidName = wlanSsid.get(wlanIfaceName); @@ -285,6 +322,23 @@ public class RouterosDevice { }); } + private void updateWifiRegistrations() throws MikrotikApiException { + ApiConnection conn = this.connection; + if (conn == null) { + return; + } + List> response = conn.execute(CMD_PRINT_WIFI_REGS); + response.forEach(props -> { + String wlanIfaceName = props.get("interface"); + String wlanSsidName = wlanSsid.get(wlanIfaceName); + + if (wlanSsidName != null && wlanIfaceName != null && !wlanIfaceName.isBlank() && !wlanSsidName.isBlank()) { + props.put("configuration.ssid", wlanSsidName); + } + wirelessRegistrationCache.add(new RouterosWirelessRegistration(props)); + }); + } + private void updateResources() throws MikrotikApiException { ApiConnection conn = this.connection; if (conn == null) { diff --git a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosInterfaceType.java b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosInterfaceType.java index 18391d54bb..40fc26d235 100644 --- a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosInterfaceType.java +++ b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosInterfaceType.java @@ -26,9 +26,12 @@ public enum RouterosInterfaceType { ETHERNET("ether"), BRIDGE("bridge"), WLAN("wlan"), + WIFI("wifi"), CAP("cap"), PPP_CLIENT("ppp-out"), PPPOE_CLIENT("pppoe-out"), + VLAN("vlan"), + VETH("veth"), // docker containers create virtual ether ports L2TP_SERVER("l2tp-in"), L2TP_CLIENT("l2tp-out"), LTE("lte"); diff --git a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosWifiInterface.java b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosWifiInterface.java new file mode 100644 index 0000000000..707b9135b2 --- /dev/null +++ b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosWifiInterface.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.mikrotik.internal.model; + +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link RouterosWifiInterface} is a model class for `wifi` interface models having casting accessors for + * data that is specific to this network interface kind. Is a subclass of {@link RouterosInterfaceBase}. + * + * @author Matthew Skinner - Initial contribution + */ +@NonNullByDefault +public class RouterosWifiInterface extends RouterosWlanInterface { + + public RouterosWifiInterface(Map props) { + super(props); + } + + @Override + public RouterosInterfaceType getDesignedType() { + return RouterosInterfaceType.WIFI; + } + + @Override + public String getApiType() { + return "wifi"; + } + + @Override + public int getRegisteredClients() { + Integer registeredClients = getIntProp("registered-peers"); + return registeredClients == null ? 0 : registeredClients; + } + + @Override + public int getAuthorizedClients() { + Integer authedClients = getIntProp("authorized-peers"); + return authedClients == null ? 0 : authedClients; + } +} diff --git a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosWirelessRegistration.java b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosWirelessRegistration.java index 904c4c5851..4bb2dd66a4 100644 --- a/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosWirelessRegistration.java +++ b/bundles/org.openhab.binding.mikrotik/src/main/java/org/openhab/binding/mikrotik/internal/model/RouterosWirelessRegistration.java @@ -27,12 +27,29 @@ import org.openhab.binding.mikrotik.internal.util.Converter; */ @NonNullByDefault public class RouterosWirelessRegistration extends RouterosRegistrationBase { + public RouterosWirelessRegistration(Map props) { super(props); } public int getRxSignal() { - String signalValue = getProp("signal-strength", "0@hz").split("@")[0]; + String signalValue = getProp("signal", "0"); + if (signalValue.isEmpty()) { + signalValue = getProp("signal-strength", "0@hz").split("@")[0]; + } else { + int value = Integer.parseInt(signalValue); + if (value < -80) { + return 0; + } else if (value < -75) { + return 1; + } else if (value < -68) { + return 2; + } else if (value < -55) { + return 3; + } else { + return 4; + } + } return Integer.parseInt(signalValue); }