Xcel Energy ITron Gen 5 Riva

I’ve learned a few things. I might have cracked this, but I have to wait 2 hours.

  1. You can choose what sensors end up in your energy panel by going to settings->dashboards->energy and clicking on Add Consumption in the Grid Consumption area on the left.

screenshot-2023-04-26-1682539045

  1. When I did that with my command line sensor, it doesn’t show up. There is a not-very-helpful help message that says this:

Which links to here: Expected data source not listed - Home Assistant

Interestingly, the command line sensor also doesn’t show up in developer tools->statistics.

  1. I have device_class: energy, state_class: total (I tried total_increasing too), and unit_of_measurement: "kWh". These don’t show up in the developer tools->states:

  1. My guess is that has something to do with the command line sensor. In fact, in the template sensor description, it says:

Templating is a powerful feature that allows you to control information going into and out of the system. It is used for:

  1. So that is what I did. I added a template sensor that just copies the sensor from the command line version and adds the correct statistics:
template:
  - sensor:
      - name: Grid Energy
        unique_id: template_grid_energy
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total
        state: >
          {{ states('sensor.xcel_meter_consumption') | float }}

This new sensor (sensor.grid_energy) shows up in the statistics, and in the list in the Settings->Dashboards->Energy->Add Consumption menu. :tada:.

  1. Update: This solution, to add the classes to the sensor worked for me as well:
    Xcel Energy ITron Gen 5 Riva - #186 by mcblok

And, I have spent long enough typing this out, that the result is in the energy dashboard!

Alright. Now I just need to sit back and watch my data. I am already enjoying seeing things like my oven’s energy use, and the furnace’s and the “background” levels. They are all higher than I expected.

Thanks for everyone who poked and prodded at this to get a solution. Let’s see how long it lasts before the API breaks :smiley:

2 Likes

Yeah I think I’ve tried every browser known to man at this point, and the xcel app.

My smart meter usage doesn’t even show up on my Xcel account, so I think there’s a bigger Xcel issue with my account that’s leading to this problem.

1 Like

You can do this without creating another sensor. Just add the following in configuration.yaml:

homeassistant:
  customize:
    sensor.smart_meter_consumption:
      device_class: energy
      state_class: total_increasing
1 Like

Did anyone else lose their command line sensor in the latest HA update (2023.5.0)? It no longer writes data, but I still get a positive connection in the terminal using the curl command.

Edit: FIXED. See post 188. Had a bad path for the openssl.config that didn’t catch up with me until the latest upgrade.

1 Like

Whew, that made me nervious. But I just upgraded and mine is still working.

What curl command are you using on the terminal? Did you see my note about about using /config instead of /root/config to get the cert files correct in the command line sensor?

This did work for me. I am not sure how to do this in an included file, or why it wouldn’t work when added to the command line sensor itself. But this does work. Thank you.

EDIT: FIXED

Apparently I had an extra non-existent path in my openssl.conf. Looks like it didn’t catch up with me until the 2023.5.0 update. I deleted the /xcelcerts/ part of my path and works fine again.


Yeah, the only thing that changed was the upgrade. Odd.

# CLI Sensor for Xcel Meter
sensor:
  - platform: command_line
    unique_id: xcel_meter_power
    name: "Smart Electric Meter Power"
    command: "OPENSSL_CONF=/config/xcelcerts/xcel-openssl.conf /usr/bin/curl --ciphers ECDHE-ECDSA-AES128-CCM8 --insecure --url https://192.168.20.54:8081/upt/1/mr/1/r --cert /config/xcel-cert.pem --key /config/xcel-key.pem 2>&1 | grep -o '<value>.*</value>' | grep -Eo '[0-9]+'"
    unit_of_measurement: "W"
    device_class: 'power'
    scan_interval: 5
    command_timeout: 5

  - platform: command_line
    unique_id: xcel_meter_consumption
    name: "Smart Electric Meter Consumption"
    command: "OPENSSL_CONF=/config/xcelcerts/xcel-openssl.conf /usr/bin/curl --ciphers ECDHE-ECDSA-AES128-CCM8 --insecure --url https://192.168.20.54:8081/upt/1/mr/3/r --cert /config/xcel-cert.pem --key /config/xcel-key.pem 2>&1 | grep -o '<value>.*</value>' | grep -Eo '[0-9]+'"
    unit_of_measurement: "kWh"
    value_template: "{{ value | multiply(0.001) | round(3)}}"
    device_class: 'energy'
    state_class: 'total_increasing'
    scan_interval: 5
    command_timeout: 5

openssl config:

openssl_conf = openssl_init

[openssl_init]
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
Options = UnsafeLegacyRenegotiation

This is all I’m seeing in the logs:

Logger: homeassistant.components.command_line.utils
Source: components/command_line/utils.py:54
Integration: command_line (documentation, issues)
First occurred: 11:33:21 (38 occurrences)
Last logged: 11:36:22
Command failed (with return code 1): OPENSSL_CONF=/config/xcelcerts/xcel-openssl.conf /usr/bin/curl --ciphers ECDHE-ECDSA-AES128-CCM8 --insecure --url https://192.168.20.54:8081/upt/1/mr/1/r --cert /config/xcel-cert.pem --key /config/xcel-key.pem 2>&1 | grep -o ‘.’ | grep -Eo ‘[0-9]+’
Command failed (with return code 1): OPENSSL_CONF=/config/xcelcerts/xcel-openssl.conf /usr/bin/curl --ciphers ECDHE-ECDSA-AES128-CCM8 --insecure --url https://192.168.20.54:8081/upt/1/mr/3/r --cert /config/xcel-cert.pem --key /config/xcel-key.pem 2>&1 | grep -o '.
’ | grep -Eo ‘[0-9]+’

1 Like

Was following along with this thread once I got my new Xcel iTron meter as well - thank you for the fantastic information and links; it got me pointed in the right direction. I don’t have Home Assistant set up (yet), but I leveraged the GitHub - zaknye/xcel_itron2mqtt: Broadcast your Xcel smart meter to MQTT project posted earlier in the thread and created a bit of a Frankenstein project that connects the meter to MQTT to Prometheus for analysis in Grafana. If anyone is just getting started with their xcel meter and wants to analyze their data, it might be worth checking out

It’s super rough around the edges (feedback is VERY welcome), but I know that I’m super excited to get real-time electrical use monitoring so hopefully it’ll help someone else out as well. I have additional SolarEdge monitoring as well that I plan to merge into this repo in the near future.

4 Likes

The integration was working fine until yesterday when I suddenly got the following error:

curl: (35) error:0A000412:SSL routines::sslv3 alert bad certificate

Anyone seen this error?

Removed the device, recreated the certs, added the device again, and now it works. Hope this is not a monthly exercise…

It get’s a little complicated with 3 tier on-demand pricing and different summer/winter pricing. I had to set up quite a few automations, Node-Red flows, helpers, and template sensors but I was able to get it fully automated to calculate montly electric bill taking into account the 3 tier pricing and it will automatically update the rates when they change from summer to winter.

My finished dashboard looks like this:
image

Monthly power costs is only on/mid/off peak energy cost. The “This Month Electric Bill” takes all of that into account along with the other fees and costs that are based on usage.

Energy dashboard shows that it does accurately capture the 3 tier pricing:

I’ve checked it against Xcel’s site and it is spot on.

Mostlychris video on YT covers it it pretty good detail on how to set up most of that. I went a bit further with holidays and adding in the other monthly costs.

1 Like

If it isn’t too much work, can you tell us what automations you did? The values and the times, specifically?

I’m guessing you made an input helper to store the value. Then a boolean to save the summer/winter status. And then an automation that run twice a day to set the cost based on the summer/winter boolean?

I can post up the details tonight. It was quite a bit so I’ll have to think back on the order I did everything.

I’ll try to be as detailed as possible here with my current set up. This is assuming you already have your meter sensors set up as described earlier in this thread. I have 2 set up: 1 for instantaneous usage and 1 for total kWh usage.

Set up Time of Use Helpers
I am billed for on, off, and mid peak usage.

Go to Settings > Devices & Services > Helpers and select Create Helper. Then select Utility Meter.

First helper will be what I called Xcel Meter. For the sensor, you want to select the total kWh usage sensor. I’m billed monthly on the 16th so for the reset cycle I select monthly and for offset days I use 16. For supported tarrifs, since I have 3 I typed in On Peak, Off Peak, and Mid Peak. HA will create new helpers for these 3 tarrifs. I turned periodic resetting off since this value is always increasing and I left Delta Values off since mine are absolute values. Once you create that helper, HA will create select helper and 3 sensor time of use helpers.

The next helper is total power consumption and it’s set up exactly like the one above except leave tarriffs blank.

Since the on peak and mid peak rates differ in summer and winter, I had to add 2 input_number helpers that will be used to set the rate depending on the time of the year. I set the minimum to whatever the lowest possible rate for that time of use is and the maximum to the highest possible cost. Unit of measurement is USD/kWh and for step size I used 0.00001. I show the Node Red flow I used later to set this number automatically.

At this point you should have a select helper, 3 time of use helpers (or whatever number you set up), a total power consumption helper, and 2 time of use rate number helpers.



Set up Energy Meter
Reboot HA before starting if the sensors arent showing up.

Go to your energy dashboard and under Grid consumption select Add Consumption. You’ll have to do this for each time of use helper. So for me, I added 3: on peak, off peak, and mid peak.

My off peak rate is the same all year so for that one I just entered in the static price that I got my Xcel’s rate schedule.

For on peak and mid peak, those rates are different in summer and winter so for those 2 I selected to use an entity with current price and for the entity I selected the number helper I created for each.

Automations

Before I create the automations to set which time of use to use, I need to set up 2 other automations for holidays. For this one, I looked in Xcel’s rate schedule and found which holidays they observe and on those days we will be using off peak pricing no matter what day of the week it is. So create an Holiday input boolean helper first. Then for the 1st automation (I called it Turn Holiday On), I want to create one that will turn that input boolen on if it is a holiday. Trigger is fixed time at 0:00:00. There are 10 holidays so for Conditions I used an Or condition and set up template conditions for each holiday. For example, New Years Day:

  - condition: template
    value_template: >
      {% set n = now() %}
      {{ n.year == 2023 and n.month == 1 and n.day == 1  }}

And the Action is to use Input boolean: Turn On service with the input_boolean.holidays as the target.

Then I created a Turn off Holiday automation that is the same as the turn on automation except that the Conditions are a Not condition.

Now I create 3 automations that will set the select sensor to either on, off, or mid peak depending on the time of day.

Off peak is set up with a fixed time trigger at 7pm. For the action, Service is set to Select: Select; target is set to select.xcel_meter; and Option is set to Off Peak.

Mid peak is set up with a fixed time trigger at 1pm but it has an And condition and they are that the holiday input boolean is off and a time condition with only weekdays selected. In other words, the automation will only set select.xcel_meter to mid peak if it’s not a holiday and it is Monday - Friday. All other times, this automation will not run.

On peak is set up the same as mid peak except the trigger time is 3pm.

So for automations we have this:
image

Node Red
I mentioned earlier that on and mid peak pricing changes depending on the time of the year. To handle this, I set up a Node Red flow that will set the input_number entity to the correct price. That looks like this:

Big Timer for winter TOU is set to include special day Oct 1st. That’s when Xcel changes to Winter prices. And summer TOU is set to include special day June 1st.

The call service is set up like this:

At this point, everything is pretty much automated. The TOU will automatically change at the correct time of day and remain on off peak pricing during weekends and holidays.

But I wanted to be able to display the current day energy cost and monthly energy cost. To do that, you have to create a few more helpers. You’ll need monthly and daily utility meter helpers for each TOU. These are set up much like the total consumption helper we created earlier except for the input sensor you’ll want to select sensor.xcel_meter_mid_peak_cost (may differ depending on your naming convention). But these are sensors that HA automatically created when you set up the Energy dashboard. These are set up with periodic reseting turned on. For the monthly ones you’ll use the same offset days as the previous ones you created and tarriffs will be left blank. For the daily ones, the reset cycle will be set to daily and offset is zero.

Now that we have daily and monthly sensors set up for each TOU, we can create template sensors to calculate total monthly costs. And for these I’m just going to copy/paste from my sensors.yaml file. It’s pretty self explanatory. Monthly energy cost is just adding up the 3 monthly helpers we just created. Same with daily energy costs. The GRSA E, EGCRR, and electric adjustments and fees that are defined in the Xcel Rate Schedule and are based on monthly kWh usage. For those I’m using the total power consumption sensor that we created that keeps track of monthly kWh usage and I’m multiplying that by the rate from the rate schedule. Billed electric costs is summing all of those plus the fixed base rate of $7.94.

#Template sensor to get monthly energy cost
    edgewood_total_energy_cost:
      unique_id: edgewood_total_energy_cost
      friendly_name: "Edgewood Total Energy Cost"
      value_template: "{{ (states('sensor.monthly_on_peak_cost') | float + states('sensor.monthly_mid_peak_cost') | float + states('sensor.monthly_off_peak_cost') | float) | round(2) }}"
      unit_of_measurement: "$"
      
#Template sensor to get daily energy cost
    edgewood_daily_energy_cost:
      unique_id: edgewood_daily_energy_cost
      friendly_name: "Edgewood Daily Energy Cost"
      value_template: "{{ (states('sensor.daily_on_peak_cost') | float + states('sensor.daily_mid_peak_cost') | float + states('sensor.daily_off_peak_cost') | float) | round(2) }}"
      unit_of_measurement: "$"
  
#Template sensor for GRSA E
    edgewood_grsa_e_cost:
      unique_id: edgewood_grsa_e_cost
      friendly_name: "GRSA E Cost"
      value_template: "{{ ((states('sensor.total_power_consumption') | float * 0.01271) | float) | round(2) }}"
      unit_of_measurement: "$"

#Template sensor for EGCRR
    edgewood_egcrr_cost:
      unique_id: edgewood_egcrr_cost
      friendly_name: "EGCRR Cost"
      value_template: "{{ ((states('sensor.total_power_consumption') | float * 0.002390) | float) | round(2) }}"
      unit_of_measurement: "$"

#Template sensor for Electric Adjustments
    edgewood_elec_adj_cost:
      unique_id: edgewood_elec_adj_cost
      friendly_name: "Electric Adjustment Cost"
      value_template: "{{ ((states('sensor.edgewood_total_energy_cost') | float * 0.5222) | float) | round(2) }}"
      unit_of_measurement: "$"

#Template sensor for Billed Electric Cost
    edgewood_billed_elec_cost:
      unique_id: edgewood_billed_elec_cost
      friendly_name: "Billed Electric Cost"
      value_template: "{{ (states('sensor.edgewood_total_energy_cost') | float + states('sensor.edgewood_egcrr_cost') | float + states('sensor.edgewood_grsa_e_cost')  | float + states('sensor.edgewood_elec_adj_cost') | float + 7.94 | float) | round(2) }}"
      unit_of_measurement: "$"

I think I covered everything. I did this over a couple days so it’s possible I got something out of order as I was typing it out now but it should be close enough to get you going.

2 Likes

This new meter is giving me fits! I have everything set up and can get data from the device, but it regularly shuts down the port for varying long periods of time. I am in the Denver area and understand that meters deployed here still have metering agent version 1. In this version there are only 3 values to be retrieved: 1 - Instantaneous Demand, 2 - Current Summation Received and 3 - Current Summation Delivered. If the customer does not have solar then Reading #2 will remain at 0 and Reading #1 will always be a positive value. I do have solar, so my code for Reading #1 also retrieves the sign of the value.

- platform: command_line
  unique_id: xcel_meter_power
  name: "Smart Electric Meter Power"
  command: "OPENSSL_CONF=/config/xcelcerts/openssl.conf /usr/bin/curl --ciphers ECDHE-ECDSA-AES128-CCM8 --insecure --url https://192.168.0.12:8081/upt/1/mr/1/r --cert /config/xcelcerts/cert.pem --key /config/xcelcerts/key.pem 2>&1 | grep -o '<value>.*</value>' | grep -Eo '[-]?[0-9]+'"
  unit_of_measurement: "W"
  value_template: "{{ float(value) if is_number(value_json) }}"
  scan_interval: 31536000
  command_timeout: 16

- platform: command_line
  unique_id: xcel_meter_production
  name: "Solar Meter"
  command: "OPENSSL_CONF=/config/xcelcerts/openssl.conf /usr/bin/curl --ciphers ECDHE-ECDSA-AES128-CCM8 --insecure --url https://192.168.0.12:8081/upt/1/mr/2/r --cert /config/xcelcerts/cert.pem --key /config/xcelcerts/key.pem 2>&1 | grep -o '<value>.*</value>' | grep -Eo '[0-9]+'"
  unit_of_measurement: "kWh"
  value_template: "{{ float(value) | multiply(0.001) | round(3) if is_number(value) }}"
  scan_interval: 31536000
  command_timeout: 16

- platform: command_line
  unique_id: xcel_meter_consumption
  name: "Net Meter"
  command: "OPENSSL_CONF=/config/xcelcerts/openssl.conf /usr/bin/curl --ciphers ECDHE-ECDSA-AES128-CCM8 --insecure --url https://192.168.0.12:8081/upt/1/mr/3/r --cert /config/xcelcerts/cert.pem --key /config/xcelcerts/key.pem 2>&1 | grep -o '<value>.*</value>' | grep -Eo '[0-9]+'"
  unit_of_measurement: "kWh"
  value_template: "{{ float(value) | multiply(0.001) | round(3) if is_number(value) }}"
  scan_interval: 31536000
  command_timeout: 16

The scan intervals are high because I needed to trigger the polling commands as an automation to easily disable them when they fail. I currently have Readings #1 & #3 being polled at 10 minute intervals and Reading #2 at 12 minute intervals only between sunrise and sunset. Even paring back the polling frequency has not resulted in long term data gathering stability. I have never had the queries running for 24 hours without the port being shut down by the meter.

Are others successfully doing continuous reading on this meter? If so, what scan interval is working and is your cURL command significantly different from mine? I am failing to understand why this data connection is so touchy and if it is just me experiencing this problem. Thanks in advance for any insight!

I’m also in the Denver area and havent had any issues with it stopping receiving data. My scan intervals are set at 5 and command timeout also at 5.

My curl command is the same as you have.

Only difference I have is I dont use a value template for reading #1 and for reading #3 my value template is:

  value_template: "{{ value | multiply(0.001) | round(3)}}"

I’ve been up and running since Apr 20 and hasnt missed any data yet.

1 Like

Whoa! I didn’t know you could do that! I don’t have solar, but finding an inverter that works locally with HA was a big concern. If the meter just does it for me, then I can avoid that pain.

I haven’t noticed any missing data for a while. My timeout is 16 and my scan interval is 180 (so 3 mins). Is it possible your automation is triggering too quickly sometimes?

I also have these if statements in the value templates:

    # For instant power consumption
    value_template: "{{ float(value) if is_number(value_json) }}"
    # For total consumption
    value_template: "{{ float(value) | multiply(0.001) | round(3) if is_number(value) }}"
1 Like

This is an excellent writeup and there are many more steps than I thought there would be.

Can you change the TOU input numbers from an automation instead of using node red? I don’t have NR installed ATM.

There are quite a few tricks in the billing, it seems. And some extra tricks to get HA to do the multiplication correctly. Glad you figured it out. I will have some time in a few weeks to try it.

You might consider making a new post, so it doesn’t get buried as the 195th comment here. It is really good info.

Quick link to the TOU pricing numbers. I assume these are the values you used?

https://co.my.xcelenergy.com/s/billing-payment/residential-rates/time-of-use-pricing

You could probably use an automation to change the TOU pricing. It was just easier for me to use Node Red. I use it for most all of my automations and just more comfortable using it over the HA automations.

I used the actual rates which are out to 5 decimal places rather than the rounded values.

2 Likes

I finally got a successful response back from the meter after hours of no response. This query was sent manually from a different RPi4 than my HassOS RPi. I wanted to see what the complete transaction looked like, not just the grepped meter value. I checked that I used the correct command to generate my key and cert files. Does anybody who is familiar with this kind of input see anything wrong that would upset the meter agent and cause it to close the port?

root@192:~# OPENSSL_CONF=openssl.conf curl --ciphers ECDHE-ECDSA-AES128-CCM8 --insecure -v --url https://192.168.0.12:8081/upt/1/mr/1/r --cert cert.pem --key key.pem
*   Trying 192.168.0.12:8081...
* Connected to 192.168.0.12 (192.168.0.12) port 8081 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ECDHE-ECDSA-AES128-CCM8
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-CCM8
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: [NONE]
*  start date: Mar 17 01:53:09 2023 GMT
*  expire date: Dec 31 23:59:00 9999 GMT
*  issuer: C=US; O=Itron; CN=IEEE 2030.5 MICA; serialNumber=7
*  SSL certificate verify result: self-signed certificate in certificate chain (19), continuing anyway.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /upt/1/mr/1/r HTTP/1.1
> Host: 192.168.0.12:8081
> User-Agent: curl/7.81.0
> Accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Thu, 25 May 2023 22:22:09 GMT
< Content-Length: 252
< Content-Type: application/sep+xml
<
<Reading
     xmlns="urn:ieee:std:2030.5:ns"
     href="/upt/1/mr/1/r">
    <qualityFlags>01</qualityFlags>
    <timePeriod>
        <duration>1</duration>
        <start>1685053328</start>
    </timePeriod>
    <value>567</value>
</Reading>
* Connection #0 to host 192.168.0.12 left intact

In order to hopefully add something of value as well, I want to post what I found regarding reading the actual meter display:


TL Index is the smaller numbers displayed at the top left. Symbols in parentheses are the small icons displayed at the bottom)

1 Like