From ffc127f91cad039a79b9cd8e4b36f611042b1aa8 Mon Sep 17 00:00:00 2001 From: mlobstein Date: Fri, 10 Nov 2023 16:51:43 -0600 Subject: [PATCH] [tasmotaplug] Initial contribution (#15857) Signed-off-by: Michael Lobstein --- CODEOWNERS | 1 + bom/openhab-addons/pom.xml | 5 + .../org.openhab.binding.tasmotaplug/NOTICE | 13 ++ .../org.openhab.binding.tasmotaplug/README.md | 77 +++++++ .../org.openhab.binding.tasmotaplug/pom.xml | 17 ++ .../src/main/feature/feature.xml | 9 + .../internal/TasmotaPlugBindingConstants.java | 52 +++++ .../internal/TasmotaPlugConfiguration.java | 32 +++ .../internal/TasmotaPlugHandlerFactory.java | 64 ++++++ .../internal/handler/TasmotaPlugHandler.java | 202 ++++++++++++++++++ .../src/main/resources/OH-INF/addon/addon.xml | 11 + .../OH-INF/i18n/tasmotaplug.properties | 35 +++ .../resources/OH-INF/thing/thing-types.xml | 65 ++++++ bundles/pom.xml | 1 + 14 files changed, 584 insertions(+) create mode 100644 bundles/org.openhab.binding.tasmotaplug/NOTICE create mode 100644 bundles/org.openhab.binding.tasmotaplug/README.md create mode 100644 bundles/org.openhab.binding.tasmotaplug/pom.xml create mode 100644 bundles/org.openhab.binding.tasmotaplug/src/main/feature/feature.xml create mode 100644 bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugBindingConstants.java create mode 100644 bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugConfiguration.java create mode 100644 bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugHandlerFactory.java create mode 100644 bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/handler/TasmotaPlugHandler.java create mode 100644 bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/addon/addon.xml create mode 100644 bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/i18n/tasmotaplug.properties create mode 100644 bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/thing/thing-types.xml diff --git a/CODEOWNERS b/CODEOWNERS index 6f9aa3f0d9e..6d8ddc9c790 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -343,6 +343,7 @@ /bundles/org.openhab.binding.tado/ @dfrommi @andrewfg /bundles/org.openhab.binding.tankerkoenig/ @dolic @JueBag /bundles/org.openhab.binding.tapocontrol/ @wildcs +/bundles/org.openhab.binding.tasmotaplug/ @mlobstein /bundles/org.openhab.binding.telegram/ @ZzetT /bundles/org.openhab.binding.teleinfo/ @Nokyyz @olivierkeke /bundles/org.openhab.binding.tellstick/ @openhab/add-ons-maintainers diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index 95eba8ac828..9f322e518bc 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -1701,6 +1701,11 @@ org.openhab.binding.tapocontrol ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.tasmotaplug + ${project.version} + org.openhab.addons.bundles org.openhab.binding.telegram diff --git a/bundles/org.openhab.binding.tasmotaplug/NOTICE b/bundles/org.openhab.binding.tasmotaplug/NOTICE new file mode 100644 index 00000000000..38d625e3492 --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.tasmotaplug/README.md b/bundles/org.openhab.binding.tasmotaplug/README.md new file mode 100644 index 00000000000..9ef89d2d27f --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/README.md @@ -0,0 +1,77 @@ +# TasmotaPlug Binding + +This binding connects Tasmota flashed smart plugs with 1, 2, 3 or 4 relay channels to openHAB. +The plug must report the status of the relay via the url `http://$PLUG_IP/cm?cmnd=Power` in order for the binding to work. +See the [Tasmota Supported Devices Repository](https://templates.blakadder.com/plug.html) for a list of supported plugs. + +## Supported Things + +There is exactly one supported thing type, which represents any supported Tasmota smart plug. +It has the `plug` id. +Multiple Things can be added if more than one plug is to be controlled. + +## Discovery + +Discovery is not supported. All things must be added manually. + +## Thing Configuration + +At minimum, the host name must be specified. +The refresh interval and number of channels can be overridden from the default. + +| Parameter | Description | +|-------------|-----------------------------------------------------------------------------------------| +| hostName | The host name or IP address of the plug. Mandatory. | +| refresh | Overrides the refresh interval of the plug status. Optional, the default is 30 seconds. | +| numChannels | Number of channels on the Tasmota Plug (1-4). Optional, the default is 1 | +| username | Username for authentication with the Tasmota Plug. Default 'admin' | +| password | Password for authentication with the Tasmota Plug, if not supplied auth is disabled. | + +## Channels + +The number of channels depends of on the `numChannels` configuration parameter. +Channels above the number specified are automatically removed. +Therefore `numChannels` cannot be changed upward after Thing creation. +If the number of channels must be increased, delete the Thing and re-create it with the correct number. + +| Channel ID | Item Type | Description | +|------------|-----------|-----------------------------------------| +| power | Switch | Turns the smart plug relay #1 ON or OFF | +| power2 | Switch | Turns the smart plug relay #2 ON or OFF | +| power3 | Switch | Turns the smart plug relay #3 ON or OFF | +| power4 | Switch | Turns the smart plug relay #4 ON or OFF | + +## Full Example + +tasmotaplug.things: + +```java +tasmotaplug:plug:plug1 "Plug 1" [ hostName="192.168.10.1", refresh=30 ] +tasmotaplug:plug:plug2 "Plug 2" [ hostName="myplug2", refresh=30 ] +``` + +tasmotaplug.items: + +```java +Switch Plug1 "Plug 1 Power" { channel="tasmotaplug:plug:plug1:power" } + +Switch Plug2a "4ch Power 1" { channel="tasmotaplug:plug:plug2:power" } +Switch Plug2b "4ch Power 2" { channel="tasmotaplug:plug:plug2:power2" } +Switch Plug2c "4ch Power 3" { channel="tasmotaplug:plug:plug2:power3" } +Switch Plug2d "4ch Power 4" { channel="tasmotaplug:plug:plug2:power4" } +``` + +tasmotaplug.sitemap: + +```perl +sitemap tasmotaplug label="My Tasmota Plugs" { + Frame label="Plugs" { + Switch item=Plug1 + + Switch item=Plug2a + Switch item=Plug2b + Switch item=Plug2c + Switch item=Plug2d + } +} +``` diff --git a/bundles/org.openhab.binding.tasmotaplug/pom.xml b/bundles/org.openhab.binding.tasmotaplug/pom.xml new file mode 100644 index 00000000000..f6a4ab464c2 --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 4.1.0-SNAPSHOT + + + org.openhab.binding.tasmotaplug + + openHAB Add-ons :: Bundles :: Tasmota Plug Binding + + diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/feature/feature.xml b/bundles/org.openhab.binding.tasmotaplug/src/main/feature/feature.xml new file mode 100644 index 00000000000..21fbcfa4960 --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.tasmotaplug/${project.version} + + diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugBindingConstants.java b/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugBindingConstants.java new file mode 100644 index 00000000000..98539aa3953 --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugBindingConstants.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2023 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.tasmotaplug.internal; + +import java.util.List; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link TasmotaPlugBinding} class defines common constants, which are + * used across the whole binding. + * + * @author Michael Lobstein - Initial contribution + */ +@NonNullByDefault +public class TasmotaPlugBindingConstants { + public static final String BINDING_ID = "tasmotaplug"; + + public static final int DEFAULT_REFRESH_PERIOD_SEC = 30; + public static final int DEFAULT_NUM_CHANNELS = 1; + + public static final String CMD_URI = "/cm?cmnd=%s"; + public static final String CMD_URI_AUTH = "/cm?user=%s&password=%s&cmnd=%s"; + + public static final String ON = "ON"; + public static final String OFF = "OFF"; + public static final String BLANK = ""; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_PLUG = new ThingTypeUID(BINDING_ID, "plug"); + + // List of all Channel id's + public static final String POWER = "power"; + public static final String POWER2 = "power2"; + public static final String POWER3 = "power3"; + public static final String POWER4 = "power4"; + + public static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PLUG); + public static final List SUPPORTED_CHANNEL_IDS = List.of(POWER, POWER2, POWER3, POWER4); +} diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugConfiguration.java b/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugConfiguration.java new file mode 100644 index 00000000000..865091e4b06 --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugConfiguration.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2023 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.tasmotaplug.internal; + +import static org.openhab.binding.tasmotaplug.internal.TasmotaPlugBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link TasmotaPlugConfiguration} is the class used to match the + * thing configuration. + * + * @author Michael Lobstein - Initial contribution + */ +@NonNullByDefault +public class TasmotaPlugConfiguration { + public String hostName = BLANK; + public int refresh = DEFAULT_REFRESH_PERIOD_SEC; + public int numChannels = DEFAULT_NUM_CHANNELS; + public String username = BLANK; + public String password = BLANK; +} diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugHandlerFactory.java b/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugHandlerFactory.java new file mode 100644 index 00000000000..846933315f5 --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/TasmotaPlugHandlerFactory.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2010-2023 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.tasmotaplug.internal; + +import static org.openhab.binding.tasmotaplug.internal.TasmotaPlugBindingConstants.THING_TYPE_PLUG; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.openhab.binding.tasmotaplug.internal.handler.TasmotaPlugHandler; +import org.openhab.core.io.net.http.HttpClientFactory; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link TasmotaPlugHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Michael Lobstein - Initial contribution + */ +@NonNullByDefault +@Component(service = ThingHandlerFactory.class, configurationPid = "binding.tasmotaplug") +public class TasmotaPlugHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PLUG); + private final HttpClient httpClient; + + @Activate + public TasmotaPlugHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + if (THING_TYPE_PLUG.equals(thing.getThingTypeUID())) { + return new TasmotaPlugHandler(thing, httpClient); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/handler/TasmotaPlugHandler.java b/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/handler/TasmotaPlugHandler.java new file mode 100644 index 00000000000..b1223159c34 --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/src/main/java/org/openhab/binding/tasmotaplug/internal/handler/TasmotaPlugHandler.java @@ -0,0 +1,202 @@ +/** + * Copyright (c) 2010-2023 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.tasmotaplug.internal.handler; + +import static org.eclipse.jetty.http.HttpStatus.OK_200; +import static org.openhab.binding.tasmotaplug.internal.TasmotaPlugBindingConstants.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.IntStream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.openhab.binding.tasmotaplug.internal.TasmotaPlugConfiguration; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link TasmotaPlugHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Michael Lobstein - Initial contribution + */ +@NonNullByDefault +public class TasmotaPlugHandler extends BaseThingHandler { + private static final String PASSWORD_REGEX = "&password=(.*)&"; + private static final String PASSWORD_MASK = "&password=xxxx&"; + + private final Logger logger = LoggerFactory.getLogger(TasmotaPlugHandler.class); + private final HttpClient httpClient; + + private @Nullable ScheduledFuture refreshJob; + + private String plugHost = BLANK; + private int refreshPeriod = DEFAULT_REFRESH_PERIOD_SEC; + private int numChannels = DEFAULT_NUM_CHANNELS; + private boolean isAuth = false; + private String user = BLANK; + private String pass = BLANK; + + public TasmotaPlugHandler(Thing thing, HttpClient httpClient) { + super(thing); + this.httpClient = httpClient; + } + + @Override + public void initialize() { + logger.debug("Initializing TasmotaPlug handler."); + TasmotaPlugConfiguration config = getConfigAs(TasmotaPlugConfiguration.class); + + final String hostName = config.hostName; + final String username = config.username; + final String password = config.password; + refreshPeriod = config.refresh; + numChannels = config.numChannels; + + if (hostName.isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.configuration-error-hostname"); + return; + } + + if (!username.isBlank() && !password.isBlank()) { + isAuth = true; + user = username; + pass = password; + } + + plugHost = "http://" + hostName; + + // remove the channels we are not using + if (this.numChannels < SUPPORTED_CHANNEL_IDS.size()) { + List channels = new ArrayList<>(this.getThing().getChannels()); + + List channelsToRemove = IntStream.range(this.numChannels + 1, SUPPORTED_CHANNEL_IDS.size() + 1) + .boxed().toList(); + + channelsToRemove.forEach(channel -> { + channels.removeIf(c -> (c.getUID().getId().equals(POWER + channel))); + }); + updateThing(editThing().withChannels(channels).build()); + } + + updateStatus(ThingStatus.UNKNOWN); + startAutomaticRefresh(); + } + + @Override + public void dispose() { + logger.debug("Disposing the TasmotaPlug handler."); + + ScheduledFuture refreshJob = this.refreshJob; + if (refreshJob != null) { + refreshJob.cancel(true); + this.refreshJob = null; + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (channelUID.getId().contains(POWER)) { + if (command instanceof OnOffType) { + getCommand(channelUID.getId(), command); + } else { + updateChannelState(channelUID.getId()); + } + } else { + logger.warn("Unsupported command: {}", command.toString()); + } + } + + /** + * Start the job to periodically update the state of the plug + */ + private void startAutomaticRefresh() { + ScheduledFuture refreshJob = this.refreshJob; + if (refreshJob == null || refreshJob.isCancelled()) { + refreshJob = null; + this.refreshJob = scheduler.scheduleWithFixedDelay(() -> { + SUPPORTED_CHANNEL_IDS.stream().limit(numChannels).forEach(channelId -> { + updateChannelState(channelId); + }); + }, 0, refreshPeriod, TimeUnit.SECONDS); + } + } + + private void updateChannelState(String channelId) { + final String plugState = getCommand(channelId, null); + if (plugState.contains(ON)) { + updateState(channelId, OnOffType.ON); + } else if (plugState.contains(OFF)) { + updateState(channelId, OnOffType.OFF); + } + } + + private String getCommand(String channelId, @Nullable Command command) { + final String plugChannel = channelId.substring(0, 1).toUpperCase() + channelId.substring(1); + String url; + + if (isAuth) { + url = String.format(CMD_URI_AUTH, user, pass, plugChannel); + } else { + url = String.format(CMD_URI, plugChannel); + } + + if (command != null) { + url += "%20" + command; + } + + try { + logger.trace("Sending GET request to {}{}", plugHost, maskPassword(url)); + ContentResponse contentResponse = httpClient.GET(plugHost + url); + logger.trace("Response: {}", contentResponse.getContentAsString()); + + if (contentResponse.getStatus() != OK_200) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "@text/offline.communication-error.http-failure [\"" + contentResponse.getStatus() + "\"]"); + return BLANK; + } + + updateStatus(ThingStatus.ONLINE); + return contentResponse.getContentAsString(); + } catch (TimeoutException | ExecutionException e) { + logger.debug("Error executing Tasmota GET request: '{}{}', {}", plugHost, maskPassword(url), + e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + } catch (InterruptedException e) { + logger.debug("InterruptedException executing Tasmota GET request: '{}{}', {}", plugHost, maskPassword(url), + e.getMessage()); + Thread.currentThread().interrupt(); + } + return BLANK; + } + + private String maskPassword(String input) { + return isAuth ? input.replaceAll(PASSWORD_REGEX, PASSWORD_MASK) : input; + } +} diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/addon/addon.xml new file mode 100644 index 00000000000..f45da95755d --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/addon/addon.xml @@ -0,0 +1,11 @@ + + + + binding + Tasmota Plug Binding + Controls Wi-Fi Smart Plugs flashed with Tasmota + local + + diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/i18n/tasmotaplug.properties b/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/i18n/tasmotaplug.properties new file mode 100644 index 00000000000..c388401f098 --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/i18n/tasmotaplug.properties @@ -0,0 +1,35 @@ +# add-on + +addon.tasmotaplug.name = Tasmota Plug Binding +addon.tasmotaplug.description = Controls Wi-Fi Smart Plugs flashed with Tasmota + +# thing types + +thing-type.tasmotaplug.plug.label = Plug +thing-type.tasmotaplug.plug.description = Tasmota Smart Plug +thing-type.tasmotaplug.plug.channel.power.label = Power +thing-type.tasmotaplug.plug.channel.power.description = Controls the smart plug relay for the 1st channel +thing-type.tasmotaplug.plug.channel.power2.label = Power 2 +thing-type.tasmotaplug.plug.channel.power2.description = Controls the smart plug relay for the 2nd channel +thing-type.tasmotaplug.plug.channel.power3.label = Power 3 +thing-type.tasmotaplug.plug.channel.power3.description = Controls the smart plug relay for the 3rd channel +thing-type.tasmotaplug.plug.channel.power4.label = Power 4 +thing-type.tasmotaplug.plug.channel.power4.description = Controls the smart plug relay for the 4th channel + +# thing types config + +thing-type.config.tasmotaplug.plug.hostName.label = Plug Host Name/IP Address +thing-type.config.tasmotaplug.plug.hostName.description = Host name or IP address of the plug +thing-type.config.tasmotaplug.plug.numChannels.label = Number of Channels +thing-type.config.tasmotaplug.plug.numChannels.description = Number of channels on the Tasmota plug (1-4) default 1 +thing-type.config.tasmotaplug.plug.password.label = Password +thing-type.config.tasmotaplug.plug.password.description = Tasmota password +thing-type.config.tasmotaplug.plug.refresh.label = Refresh Interval +thing-type.config.tasmotaplug.plug.refresh.description = Specifies the refresh interval in seconds +thing-type.config.tasmotaplug.plug.username.label = Username +thing-type.config.tasmotaplug.plug.username.description = Tasmota username + +# thing status descriptions + +offline.communication-error.http-failure = Tasmota http response code was: {0} +offline.configuration-error-hostname = Plug hostname must be specified diff --git a/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 00000000000..1382b7cd44a --- /dev/null +++ b/bundles/org.openhab.binding.tasmotaplug/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,65 @@ + + + + + + + + Tasmota Smart Plug + + + + + + Controls the smart plug relay for the 1st channel + + + + Controls the smart plug relay for the 2nd channel + + + + Controls the smart plug relay for the 3rd channel + + + + Controls the smart plug relay for the 4th channel + + + + + + network-address + + Host name or IP address of the plug + + + + Specifies the refresh interval in seconds + 30 + + + + Number of channels on the Tasmota plug (1-4) default 1 + 1 + + + + Tasmota username + admin + true + + + password + + Tasmota password + true + + + + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index b58688b52db..e992b98ac4d 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -375,6 +375,7 @@ org.openhab.binding.tado org.openhab.binding.tankerkoenig org.openhab.binding.tapocontrol + org.openhab.binding.tasmotaplug org.openhab.binding.telegram org.openhab.binding.teleinfo org.openhab.binding.tellstick