diff --git a/bundles/org.openhab.binding.openwebnet/README.md b/bundles/org.openhab.binding.openwebnet/README.md index ab2ce1779..472d37c18 100644 --- a/bundles/org.openhab.binding.openwebnet/README.md +++ b/bundles/org.openhab.binding.openwebnet/README.md @@ -137,6 +137,7 @@ For any manually added device, you must configure: - dry Contact or IR Interface `99`: add `3` before --> `where="399"` - energy meter F520/F521 numbered `1`: add `5` before --> `where="51"` - energy meter F522/F523 numbered `4`: add `7` before and `#0` after --> `where="74#0"` + - energy meter F520/F521 the `energyRefreshPeriod` configuration parameter sets the number of minutes (the minimum value is 30, the maximum value is 1440) between refreshes for energy totalizers (default: 30 minutes) --> `energyRefreshPeriod` = 35 - alarm zone `2` --> `where="2"` - example for Zigbee devices: `where=765432101#9`. The ID of the device (ADDR part) is usually written in hexadecimal on the device itself, for example `ID 0074CBB1`: convert to decimal (`7654321`) and add `01#9` at the end to obtain `where=765432101#9`. For 2-unit switch devices (`zb_on_off_switch2u`), last part should be `00#9`. @@ -208,15 +209,17 @@ OPEN command to execute: *5*8#134## ### Lighting, Automation, Basic/CEN/CEN+ Scenario Events, Dry Contact / IR Interfaces, Power and Aux channels -| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write | +| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write | |-----------------------------------------|---------------------------------------------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------|:-----------:| -| `switch` or `switch_01`/`02` for Zigbee | `bus_on_off_switch`, `zb_on_off_switch`, `zb_on_off_switch2u` | Switch | To switch the device `ON` and `OFF` | R/W | -| `brightness` | `bus_dimmer`, `zb_dimmer` | Dimmer | To adjust the brightness value (Percent, `ON`, `OFF`) | R/W | -| `shutter` | `bus_automation` | Rollershutter | To activate roller shutters (`UP`, `DOWN`, `STOP`, Percent - [see Shutter position](#shutter-position)) | R/W | -| `scenario`   | `bus_scenario_control` | String | Trigger channel for Basic scenario events [see possible values](#scenario-channels) | R (TRIGGER) | -| `button#X` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | String | Trigger channel for CEN/CEN+ scenario events [see possible values](#scenario-channels) | R (TRIGGER) | -| `sensor` | `bus_dry_contact_ir` | Switch | Indicates if a Dry Contact Interface is `ON`/`OFF`, or if an IR Sensor is detecting movement (`ON`), or not (`OFF`) | R | -| `power` | `bus_energy_meter` | Number:Power | The current active power usage from Energy Meter | R | +| `switch` or `switch_01`/`02` for Zigbee | `bus_on_off_switch`, `zb_on_off_switch`, `zb_on_off_switch2u` | Switch | To switch the device `ON` and `OFF` | R/W | +| `brightness` | `bus_dimmer`, `zb_dimmer` | Dimmer | To adjust the brightness value (Percent, `ON`, `OFF`) | R/W | +| `shutter` | `bus_automation` | Rollershutter | To activate roller shutters (`UP`, `DOWN`, `STOP`, Percent - [see Shutter position](#shutter-position)) | R/W | +| `scenario`   | `bus_scenario_control` | String | Trigger channel for Basic scenario events [see possible values](#scenario-channels) | R (TRIGGER) | +| `button#X` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | String | Trigger channel for CEN/CEN+ scenario events [see possible values](#scenario-channels) | R (TRIGGER) | +| `sensor` | `bus_dry_contact_ir` | Switch | Indicates if a Dry Contact Interface is `ON`/`OFF`, or if an IR Sensor is detecting movement (`ON`), or not (`OFF`) | R | +| `power` | `bus_energy_meter` | Number:Power | The current active power usage from Energy Meter | R | +| `energyToday` | `bus_energy_meter` | Number:Energy | Current day energy totalizer | R | +| `energyThisMonth` | `bus_energy_meter` | Number:Energy | Current month energy totalizer | R | | `aux` | `bus_aux` | String | Possible commands: `ON`, `OFF`, `TOGGLE`, `STOP`, `UP`, `DOWN`, `ENABLED`, `DISABLED`, `RESET_GEN`, `RESET_BI`, `RESET_TRI`. Only `ON` and `OFF` are supported for now | R/W | ### Alarm channels @@ -368,6 +371,10 @@ Rollershutter iLR_shutter "Shutter [%.0f %%]" (g Number:Power iCENTRAL_Ta "Power [%.0f %unit%]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Ta:power" } Number:Power iCENTRAL_Tb "Power [%.0f %unit%]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Tb:power" } +Number:Energy iCENTRAL_Ta_day "Energy Day [%.1f]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Ta:energyToday"} +Number:Energy iCENTRAL_Tb_day "Energy Day [%.1f]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Tb:energyToday"} +Number:Energy iCENTRAL_Ta_month "Energy Month [%.1f]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Ta:energyThisMonth"} +Number:Energy iCENTRAL_Tb_month "Energy Month [%.1f]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Tb:energyThisMonth"} // 99 zones thermo central unit Group gCentralUnit "Thermo Central Unit" @@ -434,8 +441,12 @@ sitemap openwebnet label="OpenWebNet Binding Example Sitemap" Frame label="Energy Meters" icon="energy" { - Default item=iCENTRAL_Ta label="General" icon="energy" valuecolor=[>3000="red"] - Default item=iCENTRAL_Tb label="Ground Floor" icon="energy" valuecolor=[>3000="red"] + Default item=iCENTRAL_Ta label="General" icon="energy" valuecolor=[>3000="red"] + Default item=iCENTRAL_Tb label="Ground Floor" icon="energy" valuecolor=[>3000="red"] + Default item=CENTRAL_Ta_day label="General Energy Today" icon="energy" valuecolor=[>3000="blue"] + Default item=CENTRAL_Tb_day label="Ground Floor Energy Today" icon="energy" valuecolor=[>3000="blue"] + Default item=CENTRAL_Ta_month label="General Energy This Month" icon="energy" valuecolor=[>3000="yellow"] + Default item=CENTRAL_Tb_month label="Ground Floor Energy This Month" icon="energy" valuecolor=[>3000="yellow"] } Frame label="Living Room Thermo" diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java index 69e696334..21328a417 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java @@ -157,6 +157,8 @@ public class OpenWebNetBindingConstants { public static final String CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL = "atLeastOneProbeManual"; // energy management public static final String CHANNEL_POWER = "power"; + public static final String CHANNEL_ENERGY_TOTALIZER_DAY = "energyToday"; + public static final String CHANNEL_ENERGY_TOTALIZER_MONTH = "energyThisMonth"; // scenario button channels public static final String CHANNEL_SCENARIO_BUTTON = "button#"; public static final String CHANNEL_TYPE_CEN_BUTTON_EVENT = "cenButtonEvent"; @@ -180,6 +182,7 @@ public class OpenWebNetBindingConstants { public static final String CONFIG_PROPERTY_SHUTTER_RUN = "shutterRun"; public static final String CONFIG_PROPERTY_SCENARIO_BUTTONS = "buttons"; public static final String CONFIG_PROPERTY_STANDALONE = "standAlone"; + public static final String CONFIG_PROPERTY_REFRESH_PERIOD = "energyRefreshPeriod"; // gw config properties public static final String CONFIG_PROPERTY_HOST = "host"; diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java index 8b7a03e4d..cdb3a638f 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java @@ -12,12 +12,15 @@ */ package org.openhab.binding.openwebnet.internal.handler; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_ENERGY_TOTALIZER_DAY; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_ENERGY_TOTALIZER_MONTH; import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_POWER; import java.util.Set; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import javax.measure.quantity.Energy; import javax.measure.quantity.Power; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -49,7 +52,7 @@ import org.slf4j.LoggerFactory; * device. It extends the abstract {@link OpenWebNetThingHandler}. * * @author Massimo Valla - Initial contribution - * @author Andrea Conte - Energy management + * @author Andrea Conte, Giovanni Fabiani - Energy management */ @NonNullByDefault public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { @@ -57,8 +60,11 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { private final Logger logger = LoggerFactory.getLogger(OpenWebNetEnergyHandler.class); public static final Set SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.ENERGY_MANAGEMENT_SUPPORTED_THING_TYPES; - public static final int ENERGY_SUBSCRIPTION_PERIOD = 10; // minutes - private @Nullable ScheduledFuture notificationSchedule; + private static final int POWER_SUBSCRIPTION_PERIOD = 10; // MINUTES + private int energyRefreshPeriod; // MINUTES + + private @Nullable ScheduledFuture powerSchedule; + private @Nullable ScheduledFuture energySchedule; public OpenWebNetEnergyHandler(Thing thing) { super(thing); @@ -69,6 +75,14 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { @Override public void initialize() { super.initialize(); + try { + Object refreshPeriodConfig = getConfig().get(OpenWebNetBindingConstants.CONFIG_PROPERTY_REFRESH_PERIOD); + energyRefreshPeriod = Integer.parseInt(refreshPeriodConfig.toString()); + } catch (NumberFormatException e) { + logger.debug("NumberFormatException caught while parsing OpenWebNetEnergyHandler configuration: {}", + e.getMessage()); + energyRefreshPeriod = 30; + } // In order to get data from the probe we must send a command over the bus, this could be done only when the // bridge is online. @@ -83,6 +97,7 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { if (gw != null && gw.isConnected()) { // bridge is online subscribeToActivePowerChanges(); + subscribeToEnergyTotalizer(); } } } @@ -94,26 +109,27 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { // subscribe the scheduler only after the bridge is online if (bridgeStatusInfo.getStatus().equals(ThingStatus.ONLINE)) { subscribeToActivePowerChanges(); + subscribeToEnergyTotalizer(); } } private void subscribeToActivePowerChanges() { - notificationSchedule = scheduler.scheduleWithFixedDelay(() -> { + powerSchedule = scheduler.scheduleWithFixedDelay(() -> { if (isFirstSchedulerLaunch) { logger.debug( "subscribeToActivePowerChanges() For WHERE={} subscribing to active power changes notification for the next {}min", - deviceWhere, ENERGY_SUBSCRIPTION_PERIOD); + deviceWhere, POWER_SUBSCRIPTION_PERIOD); } else { logger.debug( "subscribeToActivePowerChanges() Refreshing subscription for the next {}min for WHERE={} to active power changes notification", - ENERGY_SUBSCRIPTION_PERIOD, deviceWhere); + POWER_SUBSCRIPTION_PERIOD, deviceWhere); } Where w = deviceWhere; if (w == null) { logger.warn("subscribeToActivePowerChanges() WHERE=null. Skipping"); } else { try { - send(EnergyManagement.setActivePowerNotificationsTime(w.value(), ENERGY_SUBSCRIPTION_PERIOD)); + send(EnergyManagement.setActivePowerNotificationsTime(w.value(), POWER_SUBSCRIPTION_PERIOD)); isFirstSchedulerLaunch = false; } catch (Exception e) { if (isFirstSchedulerLaunch) { @@ -127,15 +143,40 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { } } } - }, 0, ENERGY_SUBSCRIPTION_PERIOD - 1, TimeUnit.MINUTES); + }, 0, POWER_SUBSCRIPTION_PERIOD - 1, TimeUnit.MINUTES); + } + + private void subscribeToEnergyTotalizer() { + Where w = deviceWhere; + if (w == null) { + logger.warn("subscribeToEnergyTotalizer() WHERE=null. Skipping"); + return; + } + energySchedule = scheduler.scheduleWithFixedDelay(() -> { + try { + send(EnergyManagement.requestCurrentDayTotalizer(w.value())); + send(EnergyManagement.requestCurrentMonthTotalizer(w.value())); + } catch (Exception e) { + logger.warn( + "subscribeToEnergyTotalizer() Could not subscribe to totalizers scheduler for WHERE={}. Exception={}", + w, e.getMessage()); + } + }, 0, energyRefreshPeriod, TimeUnit.MINUTES); } @Override public void dispose() { - if (notificationSchedule != null) { - ScheduledFuture ns = notificationSchedule; - ns.cancel(false); - logger.debug("dispose() scheduler stopped."); + ScheduledFuture sfp = powerSchedule; + if (sfp != null) { + sfp.cancel(false); + powerSchedule = null; + logger.debug("dispose() power scheduler stopped."); + } + ScheduledFuture sfe = energySchedule; + if (sfe != null) { + sfe.cancel(false); + energySchedule = null; + logger.debug("dispose() energy scheduler stopped."); } super.dispose(); } @@ -152,6 +193,8 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { if (w != null) { try { send(EnergyManagement.requestActivePower(w.value())); + send(EnergyManagement.requestCurrentDayTotalizer(w.value())); + send(EnergyManagement.requestCurrentMonthTotalizer(w.value())); } catch (OWNException e) { logger.debug("Exception while requesting state for channel {}: {} ", channel, e.getMessage()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); @@ -163,6 +206,8 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { protected void refreshDevice(boolean refreshAll) { logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID()); requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_POWER)); + requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_ENERGY_TOTALIZER_DAY)); + requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_ENERGY_TOTALIZER_MONTH)); } @Override @@ -187,6 +232,10 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { // fix: check for correct DIM (ActivePower / 113) if (msg.getDim().equals(EnergyManagement.DimEnergyMgmt.ACTIVE_POWER)) { updateActivePower(msg); + } else if (msg.getDim().equals(EnergyManagement.DimEnergyMgmt.PARTIAL_TOTALIZER_CURRENT_DAY)) { + updateCurrentDayTotalizer(msg); + } else if (msg.getDim().equals(EnergyManagement.DimEnergyMgmt.PARTIAL_TOTALIZER_CURRENT_MONTH)) { + updateCurrentMonthTotalizer(msg); } else { logger.debug("handleMessage() Ignoring message {} because it's not related to active power value.", msg); @@ -198,7 +247,6 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { * Updates energy power state based on an EnergyManagement message received from the OWN network * * @param msg the EnergyManagement message received - * @throws FrameException */ private void updateActivePower(BaseOpenMessage msg) { Integer activePower; @@ -208,6 +256,48 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { } catch (FrameException e) { logger.warn("FrameException on frame {}: {}", msg, e.getMessage()); updateState(CHANNEL_POWER, UnDefType.UNDEF); + } catch (NumberFormatException e) { + logger.warn("NumberFormatException on frame {}: {}", msg, e.getMessage()); + updateState(CHANNEL_POWER, UnDefType.UNDEF); + } + } + + /** + * Updates current day totalizer + * + * @param msg the EnergyManagement message received + */ + private void updateCurrentDayTotalizer(BaseOpenMessage msg) { + Double currentDayEnergy; + try { + currentDayEnergy = Double.parseDouble(msg.getDimValues()[0]) / 1000d; + updateState(CHANNEL_ENERGY_TOTALIZER_DAY, new QuantityType(currentDayEnergy, Units.KILOWATT_HOUR)); + } catch (FrameException e) { + logger.warn("FrameException on frame {}: {}", msg, e.getMessage()); + updateState(CHANNEL_ENERGY_TOTALIZER_DAY, UnDefType.UNDEF); + } catch (NumberFormatException e) { + logger.warn("NumberFormatException on frame {}: {}", msg, e.getMessage()); + updateState(CHANNEL_ENERGY_TOTALIZER_DAY, UnDefType.UNDEF); + } + } + + /** + * Updates current month totalizer + * + * @param msg the EnergyManagement message received + */ + private void updateCurrentMonthTotalizer(BaseOpenMessage msg) { + Double currentMonthEnergy; + try { + currentMonthEnergy = Double.parseDouble(msg.getDimValues()[0]) / 1000d; + updateState(CHANNEL_ENERGY_TOTALIZER_MONTH, + new QuantityType(currentMonthEnergy, Units.KILOWATT_HOUR)); + } catch (FrameException e) { + logger.warn("FrameException on frame {}: {}", msg, e.getMessage()); + updateState(CHANNEL_ENERGY_TOTALIZER_MONTH, UnDefType.UNDEF); + } catch (NumberFormatException e) { + logger.warn("NumberFormatException on frame {}: {}", msg, e.getMessage()); + updateState(CHANNEL_ENERGY_TOTALIZER_MONTH, UnDefType.UNDEF); } } } diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties index 54e20a79f..596ad7549 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties @@ -72,6 +72,8 @@ thing-type.config.openwebnet.bus_dimmer.where.label = OpenWebNet Address (where) thing-type.config.openwebnet.bus_dimmer.where.description = Example: A/PL address: A=1 PL=3 --> where="13". On local bus: where="13#4#01" thing-type.config.openwebnet.bus_dry_contact_ir.where.label = OpenWebNet Address (where) thing-type.config.openwebnet.bus_dry_contact_ir.where.description = A "3" must be added before the address. Automation Dry Contacts 3N with N=[1-201]; example N=60 --> where="360". Alarm Dry Contacts and IR sensors 3ZN with Zone Z=[1-9], N=[1-9]; example Z=4, N=5 --> where="345" +thing-type.config.openwebnet.bus_energy_meter.energyRefreshPeriod.label = Energy Totalizers Refresh Period +thing-type.config.openwebnet.bus_energy_meter.energyRefreshPeriod.description = Sets the number of minutes between refreshes for energy totalizers (default: 30 minutes) thing-type.config.openwebnet.bus_energy_meter.where.label = OpenWebNet Address (where) thing-type.config.openwebnet.bus_energy_meter.where.description = A "5" must be added before the energy meter address: 5N with N=[1-255]. Example energy meter "42" --> where="542" thing-type.config.openwebnet.bus_gateway.dateTimeSynch.label = Date Time Synchronisation @@ -185,6 +187,10 @@ channel-type.openwebnet.conditioningValves.state.option.OFF_SPEED_2 = Off speed channel-type.openwebnet.conditioningValves.state.option.OFF_SPEED_3 = Off speed 3 channel-type.openwebnet.dryContactIR.label = Sensor channel-type.openwebnet.dryContactIR.description = Dry Contact Interface or IR Interface sensor movement (read only) +channel-type.openwebnet.energyThisMonth.label = Energy This Month +channel-type.openwebnet.energyThisMonth.description = Total energy measured for this month +channel-type.openwebnet.energyToday.label = Energy Today +channel-type.openwebnet.energyToday.description = Total energy measured for today channel-type.openwebnet.failureDiscovered.label = Failure Discovered channel-type.openwebnet.failureDiscovered.description = Central Unit Failure Discovered (read only) channel-type.openwebnet.function.label = Thermo Function diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusEnergyMeter.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusEnergyMeter.xml index 4dbc8bc78..c6aab79e9 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusEnergyMeter.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusEnergyMeter.xml @@ -15,22 +15,29 @@ + + BTicino/Legrand BTI-F52x 1830 + 1 ownId - A "5" must be added before the energy meter address: 5N with N=[1-255]. Example energy meter "42" --> where="542" + + + Sets the number of minutes between refreshes for energy totalizers (default: 30 minutes) + 30 + diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml index d502160cb..1d0fba1a1 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml @@ -343,6 +343,22 @@ + + Number:Energy + + Total energy measured for this month + Energy + + + + + Number:Energy + + Total energy measured for today + Energy + + + trigger diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml index 900a8bd44..87a1a34d1 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml @@ -10,4 +10,14 @@ + + + + openwebnet:energyToday + + + openwebnet:energyThisMonth + + +