Trying to convert kb/s sent to Mb/s sent

Did you do a config check before restarting?

Were there any errors?

Also, never reboot. Restarting the HA application is sufficient. In fact there is a Reload template Entities service you can use instead of restarting, but make sure it passes the config check first.

I didn’t check the config before restarting but normally if there are any errors these appear in the Log which shows no issues. Doing a config check now and it says “Configuration valid!”. So not sure why this wouldn’t be working.

What’s the Reload template for entities as this would be useful.

Wait. That template sensor definition should be under sensors: not default_config:

Or if you have a line like this in your configuration.yaml file:

sensor: !include sensors.yaml

Then it should be in your sensors.yaml file.

@tom_l thank you do much for your help its much appreciated. This has now worked. I am now seeing MB rather than B. On to the next issue. Looking at this more it appears to be a running total rather than a daily total. Need to look how I can get daily totals

That would be a task for the utility meter integration:

utility_meter:
  kb_sent_per_day:
    source: sensor.bytes_sent
    cycle: daily
1 Like

Wow that looks a whole lot simpler than the code I have found here:

Update

I have tested Utility Meter and asked it to reset hourly ( to see if it works) but as you can see nothing has reset to 0 so doesn’t look to work. But then I am not 100% sure how correct these figures are given my total download has not moved for a long time though states it was updated 4 minutes ago.

Thank you so much for tagging me in this! I was just logging into the forum to try to grab my old solution after a data loss of my past HA instance, and this may make things way easier if it works.

I’m trying to use that component to replace what @wideboys182 linked to, but it’s not loading all the services in the docs page, it’s only loading the utility_meter.calibrate service, are the docs just out of date or should I report that as a bug?

You need to configure a tariff for some of the services to be enabled.

Ohh, okay. I was expecting to be able to use the .reset to reset the cycle early. Didn’t realize it required tariffs. Not even sure what tariffs are :sweat_smile:

Just a way to split up the meter into separate sensors. For example you may be charged different rates for peak and off peak power. You can set the active tariff with a time triggered automation and the utility meter starts incrementing that sensor.

1 Like

Just wanted to cheat a little and get some info from those who already have this working.

So @forte did you get this working in the end with totals for week, month and year?

Just to understand.

Its the one template

  - platform: template
    sensors:
      bytes_received:
        friendly_name: "MB Received"
        unit_of_measurement: 'MB/s'
        value_template: "{ (states('sensor.rbr50_gateway_kib_s_received') | int / 1024) | round(1) | float }}"
      bytes_sent:
        friendly_name: "MB Sent"
        unit_of_measurement: 'MB/s'
        value_template: "{ (states('sensor.rbr50_gateway_kib_s_sent') | int / 1024) | round(1) | float }}"

Then using the utility meter in the config.yaml as the counter with different time increments will give you the total downloads/ uploads for that cycle?

utility_meter:
  kb_sent_per_day:
    source: sensor.bytes_sent
    cycle: weekly
  kb_rcv_per_day:
    source: sensor.bytes_received
    cycle: weekly

And this way you dont need to worry about the byte counter conversions at all yeah?

EDIT***

Getting there!

How do I get it to show me GB though @wideboys182 ?

Thanks!

EDIT 2

So this got me a little closer:

  - platform: template
    sensors:
      gb_received:
        friendly_name: "GB Received"
        unit_of_measurement: "GB"
        value_template: "{{ (states('sensor.rbr50_gateway_b_received') | filesizeformat(GB)) }}"
      gb_sent:
        friendly_name: "GB Sent"
        unit_of_measurement: "GB"
        value_template: "{{ (states('sensor.rbr50_gateway_b_sent') | filesizeformat(GB)) }}"

Which is giving me this;

image

So that seems to be working (is the _b_sent sensor a daily total?)

Then I have this set up under utility meter

utility_meter:
    gb_sent_per_day:
      source: sensor.gb_sent
      cycle: daily
    gb_rcv_per_day:
      source: sensor.gb_received
      cycle: daily

But its not giving me a count yet? (though its showing the unit of measure)

image

So I was sent here by Google through forte’s original post, and it’s helped me figure out exactly how to set this up. Wanted to post up here with my entire process cuz I think it could help the next guy (or girl) understand why a lot of this works the way it does, and how to make it all work out well.

So, starting from the beginning, we have the following outputs from your DDWRT or UPnP router:

sensor.[router]_b_received
sensor.[router]_b_sent
sensor.[router]_kib_s_received
sensor.[router]_kib_s_sent

(note that [router] will be variable depending on what you have, and I’m also ignoring the outputs for packets)

The important things here are that sensor.[router]_b_received and sensor.[router]_b_sent are measured in “B” for “Bytes”, and sensor.[router]_kib_s_received and sensor.[router]_kib_s_sent are measured in “KiB”, meaning kibibytes. Not kilobytes. Kibibytes are based on powers of two, kilobytes on powers of ten. This is key.

So, the issue here is that we want to calculate total data received and sent, but both b_received and sent reset when they go above around 4,000,000,000. We also want the measurement in something more sensible then bytes.

Now, considering that the router is outputting the speed in KiB, I decided the obvious choice for total data is GiB, or Gibibytes, because computers. One GiB is equal to 10243 bytes. Therefore, we simply divide the output from b_received and sent by 10243, or 1073741824. I also rounded to three decimal places, because I wanted to:

sensor:
  - platform: template
    sensors:
      gib_received:
        friendly_name: "GiB Received"
        value_template: "{{ ((float(states('sensor.[router]_b_received')) / 1073741824) | round(3)) }}"
        unit_of_measurement: "GiB"
      gib_sent:
        friendly_name: "GiB Sent"
        value_template: "{{ ((float(states('sensor.[router]_b_sent')) / 1073741824) | round(3)) }}"
        unit_of_measurement: "GiB"

This actually caused an interesting discovery for me: both _b_received and sent don’t reset at some random point above 4,000,000,000; they actually reset at near
4,294,967,296, which is 4 GiB. It’s likely that it actually resets at 4,294,967,295, one byte below 4 GiB, because that would be hex FFFF FFFF, a sensible place to cut off. The rollover to hex 1 0000 0000 is why it keeps resetting. The more you knowwwww~

Now, if you wanted to convert it to gigabytes instead of gibibytes, simply change “1073741824” above to “1000000000”. Then you’ll have your boring power of 10 gigabytes.

So, now that it’s in a sensible measurement, we throw it into the above mentioned utility meter integration:

utility_meter:
  gib_sent_per_period:
    source: sensor.gib_sent
    name: GiB Sent / Month
    cycle: monthly
  gib_received_per_period:
    source: sensor.gib_received
    name: GiB Received / Month
    cycle: monthly

And that should work perfectly; it does for me! Change “monthly” to whatever you want, based on the integration documentation.

The other question here is how to convert from your router output to a different speed metric. In my case, my router outputs sensor.[router]_kib_s_received and sensor.[router]_kib_s_sent. Again, these are kibibytes, not kilobytes. That said, at the very top of this post, Rdoull says they have router_kbyte_sec_received / sent; I’m assuming that kbyte_sec means that Rdoull’s metrics are indeed in kilobytes and not kibibytes, so what I’m saying below mostly doesn’t apply. To answer their question directly, converting from KB/s to MB/s is easy; divide by 1000 and you’re done.

The worst thing you can do is confuse a KiB for a KB or vice versa. They are different metrics, and are often mistaken. To convert accurately from kibibytes to megabytes, you first multiply by 1024 to get the amount in bytes, then divide by 1,000,000 to get megabytes.

For me, I want the speed in megabits per second (Mbps), since that is what most internet speeds are quoted in. One megabit is one million bits, not bytes; 1 byte is 8 bits. Therefore, to convert from kibibytes to megabits accurately, we want to multiply by 8192 to get the number of bits, and then divide by 1,000,000 to get megabits:

sensor:
  - platform: template
    sensors:
      mbps_received:
        friendly_name: "Mbps Received"
        value_template: "{{ (((float(states('sensor.[router]_kib_s_received')) * 8192) / 1000000) | round(3)) }}"
        unit_of_measurement: "Mbps"
      mbps_sent:
        friendly_name: "Mbps Sent"
        value_template: "{{ (((float(states('sensor.[router]_kib_s_sent')) * 8192) / 1000000) | round(3)) }}"
        unit_of_measurement: "Mbps"

Again, I decided to round to 3 decimal places. To convert to a different metric, keep in mind what your router is outputting, then convert it based on that. To get megabytes/sec from KiB/s, as mentioned, multiply by 1024 then divide by 1,000,000.

And yes, to be clear, there are other ways to convert the numbers using built in functions, but those ways don’t explain the full reason why you’re doing it; they just do it. My way does the conversion manually for explanation’s sake, but also works fine as a final answer.

Aaaand that’s that. Hopefully this helps the next person who comes along and finds these threads.

9 Likes

Thanks @Techdisk, your post helped me correct my template sensors but unfortunately i receive new errors in the log:

  • TemplateError(‘TypeError: unsupported operand type(s) for /: ‘str’ and ‘int’’) while processing template ‘Template(“{{ ((float(states(‘sensor.freebox_download_speed’)) / 125) | round(3)) }}”)’ for attribute ‘_attr_state’ in entity ‘sensor.freebox_download_speed_mb’
  • TemplateError(‘TypeError: unsupported operand type(s) for /: ‘str’ and ‘int’’) while processing template ‘Template(“{{ ((float(states(‘sensor.freebox_upload_speed’)) / 125) | round(3)) }}”)’ for attribute ‘_attr_state’ in entity ‘sensor.freebox_upload_speed_mb’

Do you have the same problem ?

It’s because your template is attempting to divide the sensor’s value (a string) by 125 (an integer) and then converting the result to a float value. Effectively, it is using the float filter incorrectly (it should be used to convert the string value to float before dividing it by 125).

Change your

        value_template: "{{ (states('sensor.freebox_download_speed') | float / 125) | round(3) }}"
        value_template: "{{ (states('sensor.freebox_upload_speed') | float / 125) | round(3) }}"
1 Like

Thank you @123, the error is gone !

Nicely done. Thank you for posting. Just what I needed :grinning:

I found that sometimes the values returned by the integration are “unknown” and therefore you are getting lots of “TemplateError” in the core log file

To fix this issue I have modified all the templates to test if the the returned values are unknown.
for example:

mbps_received:
        friendly_name: "Mbps Received"
        value_template: >-
          {% if is_state('sensor.orange_livebox_kib_s_received', 'unknown') %}
            unknown
          {% else %}
            {{ (((float(states('sensor.orange_livebox_kib_s_received')) * 8192) / 1000000) | round(3)) }}
          {% endif %}
        unit_of_measurement: "Mbps"
2 Likes

Thank you for this, works well!

Nicely explained and clear! What I did was using my modem packet counts sent and received, adding these, and converting it to data downloaded and uploaded. From there I am using a utility meter to track monthly usage.