Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tasmotaplug] Add energy monitor channels #16494

Merged
merged 2 commits into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 42 additions & 9 deletions bundles/org.openhab.binding.tasmotaplug/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# 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.
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.
The energy monitoring channels can be used if the plug reports energy status via the url `http://$PLUG_IP/cm?cmnd=Status%2010`.
See the [Tasmota Supported Devices Repository](https://templates.blakadder.com/plug.html) for a list of supported plugs.

## Supported Things
Expand Down Expand Up @@ -34,12 +35,22 @@ 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 |
| 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 |
| voltage | Number:ElectricPotential | Channel for output voltage measurement |
| current | Number:ElectricCurrent | Channel for output current measurement |
| watts | Number:Power | Channel for output power measurement |
| volt-ampere | Number:Power | Channel for output VA measurement |
| volt-ampere-reactive | Number:Power | Channel for output VAr measurement |
| power-factor | Number:Dimensionless | Channel for output power factor measurement |
| energy-today | Number:Energy | Channel for output energy today measurement |
| energy-yesterday | Number:Energy | Channel for output energy yesterday measurement |
| energy-total | Number:Energy | Channel for output energy total measurement |
| energy-total-start | DateTime | Channel for output energy total start date/time |

## Full Example

Expand All @@ -53,7 +64,17 @@ tasmotaplug:plug:plug2 "Plug 2" [ hostName="myplug2", refresh=30 ]
tasmotaplug.items:

```java
Switch Plug1 "Plug 1 Power" { channel="tasmotaplug:plug:plug1:power" }
Switch Plug1 "Plug 1 Power" { channel="tasmotaplug:plug:plug1:power" }
Number:ElectricPotential Voltage { channel="tasmotaplug:plug:plug1:voltage" }
Number:ElectricCurrent Current { channel="tasmotaplug:plug:plug1:current" }
Number:Power Watts { channel="tasmotaplug:plug:plug1:watts" }
Number:Power VoltAmpere { channel="tasmotaplug:plug:plug1:volt-ampere" }
Number:Power VoltAmpereReactive { channel="tasmotaplug:plug:plug1:volt-ampere-reactive" }
Number PowerFactor { channel="tasmotaplug:plug:plug1:power-factor" }
Number:Energy EnergyToday { channel="tasmotaplug:plug:plug1:energy-today" }
Number:Energy EnergyYesterday { channel="tasmotaplug:plug:plug1:energy-yesterday" }
Number:Energy EnergyTotal { channel="tasmotaplug:plug:plug1:energy-total" }
DateTime EnergyTotalStart "Total Start [%s]" { channel="tasmotaplug:plug:plug1:energy-total-start" }

Switch Plug2a "4ch Power 1" { channel="tasmotaplug:plug:plug2:power" }
Switch Plug2b "4ch Power 2" { channel="tasmotaplug:plug:plug2:power2" }
Expand All @@ -68,6 +89,18 @@ sitemap tasmotaplug label="My Tasmota Plugs" {
Frame label="Plugs" {
Switch item=Plug1

// Energy monitoring
Text item=Voltage
Text item=Current
Text item=Watts
Text item=VoltAmpere
Text item=VoltAmpereReactive
Text item=PowerFactor
Text item=EnergyToday
Text item=EnergyYesterday
Text item=EnergyTotal
Text item=EnergyTotalStart

Switch item=Plug2a
Switch item=Plug2b
Switch item=Plug2c
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/**
* 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.tasmotaplug.dto;

import com.google.gson.annotations.SerializedName;

/**
* The {@link TasmotaDTO} is responsible for storing
* all of the JSON data objects retrieved from the Tasmota plug
*
* @author Michael Lobstein - Initial contribution
*/
public class TasmotaDTO {

@SerializedName("StatusSNS")
private TasmotaStatus status = new TasmotaStatus();

public TasmotaDTO() {
}

public TasmotaStatus getStatus() {
return status;
}

public void setStatus(TasmotaStatus status) {
this.status = status;
}

public class TasmotaStatus {

@SerializedName("Time")
private String time = "";

@SerializedName("ENERGY")
private Energy energy = new Energy();

public TasmotaStatus() {
}

public String getTime() {
return time;
}

public void setTime(String time) {
this.time = time;
}

public Energy getEnergy() {
return energy;
}

public void setEnergy(Energy energy) {
this.energy = energy;
}
}

public class Energy {

@SerializedName("Voltage")
private Integer voltage = 0;

@SerializedName("Current")
private Double current = 0d;

@SerializedName("Power")
private Integer activePower = 0;

@SerializedName("ApparentPower")
private Integer apparentPower = 0;

@SerializedName("ReactivePower")
private Integer reactivePower = 0;

@SerializedName("Factor")
private Double powerFactor = 0d;

@SerializedName("Today")
private Double energyToday = 0d;

@SerializedName("Yesterday")
private Double energyYesterday = 0d;

@SerializedName("Total")
private Double energyTotal = 0d;

@SerializedName("TotalStartTime")
private String energyTotalStart = "";

public Energy() {
}

public Integer getVoltage() {
return voltage;
}

public void setVoltage(Integer voltage) {
this.voltage = voltage;
}

public Double getCurrent() {
return current;
}

public void setCurrent(Double current) {
this.current = current;
}

public Integer getActivePower() {
return activePower;
}

public void setActivePower(Integer activePower) {
this.activePower = activePower;
}

public Integer getApparentPower() {
return apparentPower;
}

public void setApparentPower(Integer apparentPower) {
this.apparentPower = apparentPower;
}

public Integer getReactivePower() {
return reactivePower;
}

public void setReactivePower(Integer reactivePower) {
this.reactivePower = reactivePower;
}

public Double getPowerFactor() {
return powerFactor;
}

public void setPowerFactor(Double powerFactor) {
this.powerFactor = powerFactor;
}

public Double getEnergyToday() {
return energyToday;
}

public void setEnergyToday(Double energyToday) {
this.energyToday = energyToday;
}

public Double getEnergyYesterday() {
return energyYesterday;
}

public void setEnergyYesterday(Double energyYesterday) {
this.energyYesterday = energyYesterday;
}

public Double getEnergyTotal() {
return energyTotal;
}

public void setEnergyTotal(Double energyTotal) {
this.energyTotal = energyTotal;
}

public String getEnergyTotalStart() {
return energyTotalStart;
}

public void setEnergyTotalStart(String energyTotalStart) {
this.energyTotalStart = energyTotalStart;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class TasmotaPlugBindingConstants {
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 STATUS = "Status";
public static final String STATUS_CMD = "10";
public static final String ON = "ON";
public static final String OFF = "OFF";
public static final String BLANK = "";
Expand All @@ -46,7 +48,19 @@ public class TasmotaPlugBindingConstants {
public static final String POWER2 = "power2";
public static final String POWER3 = "power3";
public static final String POWER4 = "power4";
public static final String VOLTAGE = "voltage";
public static final String CURRENT = "current";
public static final String WATTS = "watts";
public static final String VOLT_AMPERE = "volt-ampere";
public static final String VOLT_AMPERE_REACTIVE = "volt-ampere-reactive";
public static final String POWER_FACTOR = "power-factor";
public static final String ENERGY_TODAY = "energy-today";
public static final String ENERGY_YESTERDAY = "energy-yesterday";
public static final String ENERGY_TOTAL = "energy-total";
public static final String ENERGY_TOTAL_START = "energy-total-start";

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PLUG);
public static final List<String> SUPPORTED_CHANNEL_IDS = List.of(POWER, POWER2, POWER3, POWER4);
public static final List<String> CONTROL_CHANNEL_IDS = List.of(POWER, POWER2, POWER3, POWER4);
public static final List<String> ENERGY_CHANNEL_IDS = List.of(VOLTAGE, CURRENT, WATTS, VOLT_AMPERE,
VOLT_AMPERE_REACTIVE, POWER_FACTOR, ENERGY_TODAY, ENERGY_YESTERDAY, ENERGY_TOTAL, ENERGY_TOTAL_START);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
*/
package org.openhab.binding.tasmotaplug.internal;

import static org.openhab.binding.tasmotaplug.internal.TasmotaPlugBindingConstants.THING_TYPE_PLUG;

import java.util.Set;
import static org.openhab.binding.tasmotaplug.internal.TasmotaPlugBindingConstants.SUPPORTED_THING_TYPES_UIDS;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
Expand All @@ -39,8 +37,6 @@
@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.tasmotaplug")
public class TasmotaPlugHandlerFactory extends BaseThingHandlerFactory {

private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PLUG);
private final HttpClient httpClient;

@Activate
Expand All @@ -55,7 +51,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {

@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
if (THING_TYPE_PLUG.equals(thing.getThingTypeUID())) {
if (SUPPORTED_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
return new TasmotaPlugHandler(thing, httpClient);
}

Expand Down