Rainforest Automation EMU-2 (Energy Component)

@kngzen this is great. I think I have fix and I will test it tomorrow when my system is generating energy. I will report back.

Thanks

@kngzen @BrianHanifin

Add this after line 133 around the InstantaneousDemand section in sensor.py

demand = -(demand & 0x80000000) | (demand & 0x7fffffff)

It is working accurately for meā€¦let me know if this doesnā€™t resolves your issue.

Cheers

1 Like

I just applied it directly to the line below where the demand variable is assigned. I will let you know after I run it for a bit. Thank you!

  if xmlTree.tag == 'InstantaneousDemand':
      demand = int(xmlTree.find('Demand').text, 16)
      demand = -(demand & 0x80000000) | (demand & 0x7fffffff)
1 Like

Iā€™m not 100% sure, but I think this is working! The numbers are definitely more sane than before. It is even showing some negative numbers during the brightest part of the day (yay solar). Thank you.

1 Like

Thanks for the fix for negative numbers, works great.

Separately, has anyone experienced the component randomly stopping? For me the component stops collecting data from the EMU-2 seemly at random. Sometimes it happens after a week, sometimes after a few hours. The data is still streaming because when I do a dump of /dev/ttyACM1 (the EMU-2 port for me) it is still getting data every 15 seconds or so. Just not getting into HA. A restart of HA gets it going again.

This is great!
Thank you!

ā€¦think thereā€™s any way to get the data off of the pins in the battery compartment to put an esp8266 in there and get data over wifi??

Got this working - thanks everyone for the work on this!!

@jrhorrisberger - looking at the graphs you shared - I really like your dashboard. What is the comed smart price you show? I have the comed integration but only have the 5 min and hourly. Also how did you get the predicted comed price in there?

Anyone have any guidance on how to calculate the kWh used throughout the day? It doesnā€™t look like we get the meter reading into HA. Perhaps I can calculate it based on the instantaneous?

Hi @adant,

The ā€œComed Smart Priceā€ is something I made up to better (at least I think) predict what the actual end hour price will be (this helps me make sure big power users are off from the beginning of the hour). Weighting more towards the 5min/predicted price at the beginning of the hour, and more towards the hour average near the end (using predicted to help as well). Uses Appdaemon to create a sensor:

Apps.yaml:

ComedSmartPrice:
  module: fileName
  class: ComedSmartPricing
  entity_5min: sensor.comed_5_minute_price
  entity_hourAvg: sensor.comed_current_hour_average_price
  entity_predicted: sensor.comed_predicted_price
  entity_outputName: sensor.comed_smart_pricing

Script:

class ComedSmartPricing (hass.Hass):
  def initialize(self):
    self.listen_state(self.UpdateState, self.args["entity_5min"]) 

    self.UpdateState("VOID", "VOID", "VOID", "VOID", "VOID")

#########################################################################
  def UpdateState(self, entity, attribute, old, new, kwargs): 

    pFiveMin = float(self.get_state(self.args["entity_5min"]))
    pAverage = float(self.get_state(self.args["entity_hourAvg"]))
    try:
      pPredicted = float(self.get_state(self.args["entity_predicted"]))
    except:
      pPredicted = (pFiveMin + pAverage) / 2

    pMax = max(pFiveMin, pPredicted, pAverage)

    minute = self.time().minute

    priceFiveMinPredicted =  (((pFiveMin + pPredicted + pAverage) / 3) + pMax) / 2

    pAverageBias = minute / 60
    price = (priceFiveMinPredicted * (1 - pAverageBias)) + (pAverage * pAverageBias)

    roundedPrice = round(price, 3)

    self.set_state(self.args["entity_outputName"], state = roundedPrice, attributes = {
        "unit_of_measurement": "c",
        "friendly_name": "Comed Smart Pricing"})

The predicted price can be gotten by using the scrape sensor

Sensor.yaml

- platform: scrape
  resource: 'https://hourlypricing.comed.com/rrtp/ServletFeed?type=instantpredicted'
  select: '.price'
  scan_interval: 300
  unit_of_measurement: c
  name: Comed Predicted Price
  value_template: '{{ value.split("Ā¢")[0] }}'

The EMU-2 does provide the meter reading, and there is a merge request to add the meter reading on the github, but I never merged it. ā€“ https://github.com/jrhorrisberger/home-assistant/pull/3 ā€“ I think you might also be able to use the https://www.home-assistant.io/integrations/utility_meter/ integration (Iā€™ve not messed with it though)

this is great! Thanks much for the info. Now onto implementing this in my setup!

Thank you very much for this integration! I just got the EMU-2 and things appear to be working fine. Iā€™ve got the basic sensor, along with the utility meter sensor set up so I can track current and monthly usage.

One questionā€¦has anyone been able to gather pricing info off of this unit? Or is there a way to calculate it based on the provided data? Iā€™m on a tiered plan.

EDIT: Looks like utility_meter doesnā€™t work with this sensor. The numbers Iā€™m getting for total kWh are way too high.

Also, shouldnā€™t the sensor reading be in kW and not kWh?

EDIT2:

Saw the merge requests and changed the code to get things working. So now Iā€™m getting data for total usage, but it appears to be from the meter was first installed. Trying to figure out a way to use this data to extrapolate daily and monthly usage.

Just wanted to provide an update.

Utility Meter works with this component. You need to manually make the code changes in the PR so cumulative usage gets tracked. Then you create a sensor based off that attribute in HA. Then you create the Utility Meter sensor and point it to the sensor you just created.

For the life of me, I canā€™t figure out these next steps. Got the PR version of the script updated, but I have no clue on adding these sensors. Any chance you can paste in a config example? Thanks!

Ok, I think I have this working, but still not 100% sure if this is the right way. Hereā€™s what I added:

  - platform: template
    sensors: 
      energy_meter:
        friendly_name: "Cumulative kWh"
        unit_of_measurement: 'kWh'
        value_template: "{{ state_attr('sensor.rainforest_energy_monitoring_unit','Cumulative kWh') }}"

utility_meter:
  total_hourly_energy: 
    source: sensor.energy_meter 
    cycle: hourly 
  total_daily_energy: 
    source: sensor.energy_meter 
    cycle: daily 
  total_monthly_energy: 
    source: sensor.energy_meter 
    cycle: monthly

@nocturne1

That looks correct. Is it working for you? Basically the numbers will be off until the next cycle. So, you have to wait until the next hour for hourly, next day for daily, next month for monthly, etc, etc.

Yeah, looks like itā€™s working. Now I gotta figure out how to actually make use of that - keeping track of each day.

Also, for some reason, I just canā€™t get it to read pricing data from my meter. Might need to just hardcode itā€¦

Thank you so very much to Brian for putting so much work into this.

Iā€™ve been extending this custom component out to take advantage of some features of the EMU-2 and also make a little bit more data available in home assistant and incorporated some bug fixes within this thread.

1: Fixed negative demand bug
2: Created new custom price input that will set the price on the EMU-2 (input_number.rainforest_tariff_current_rate)
3: Changed to ā€œNet kWhā€
4: Added ā€œDelivered kWhā€
5: Added ā€œReceived kWhā€

You can find the code on my github https://github.com/damienheiser/home-assistant/blob/998458ecf422a1b48435076685e8a98309a5a0a9/custom_components/rainforest/sensor.py

3 Likes

Very cool! Your repo just replaced @jrhorrisbergerā€™s in HACS for me. I like your additions.

Are ā€œDeliveredā€ kilowatts the amount delivered by the power company? So ā€œReceivedā€ would be the amount my solar panels are generating? Or did I get those backwardsā€¦ or not right at all?

You got the descriptions right!

Delivered: The amount of energy in kWh that your power utility has Delivered
Received: The amount of energy in kWh that you have generated in excess of your use and has been Received by the power company

These terms are from the EMU-2 technical documentation.

2 Likes

jrhorrisbergerā€¦ Thanks John for the idea. The python script stop working with the latest 2 HASS updates so I create a template based on your algorithm.

  • platform: template
    sensors:
    my_smart_pricing:
    friendly_name: ā€œMy Smart Pricing Calcā€
    unit_of_measurement: ā€˜cā€™
    value_template: >-
    {%- if states(ā€˜sensor.comed_5_minute_priceā€™) != ā€˜unknownā€™ and states(ā€˜sensor.comed_current_hour_average_priceā€™) != ā€˜unknownā€™ and states(ā€˜sensor.comed_predicted_priceā€™) != ā€˜unknownā€™ and states(ā€˜sensor.my_smart_pricingā€™) !=ā€˜unknownā€™ %}
    {%- set lcomed_5_minute_price = states(ā€˜sensor.comed_5_minute_priceā€™) | float %}
    {%- set lcomed_current_hour_average_price = states(ā€˜sensor.comed_current_hour_average_priceā€™) | float %}
    {%- set lcomed_predicted_price = states(ā€˜sensor.comed_predicted_priceā€™) | float %}
    {%- set lcomed_smart_price = states(ā€˜sensor.my_smart_pricingā€™) | float %}
    {%- set lpMax = max(lcomed_5_minute_price, lcomed_predicted_price, lcomed_current_hour_average_price) | float %}
    {%- set lAvgBias = ( float(now().minute) / 60 ) | float %}
    {%- set lprice5minpredicted = ((( lcomed_5_minute_price + lcomed_predicted_price + lcomed_current_hour_average_price) / 3 ) + lpMax ) / 2 | float %}
    {{ ((lprice5minpredicted * ( 1 - lAvgBias)) + ( lcomed_current_hour_average_price * lAvgBias ) ) | float | round(2) }}
    {%- else %}
    0
    {%- endif %}

Cut and Paste didnā€™t conserve my formatting so you will need to make it YAML compliantā€¦