Extracting specific characters from a String to use as automated number inputs

Hello all.

I’m looking for assistance on a specific issue that I can’t solve. Have searched through as many time-themed threads as I can find but now need to ask for help.

I have a cascade of templates which calculate the amount of time I need to charge my Solar batteries by overnight (eco7 tariff). The method I use here is to use sensors and a calculation to assess how many kWh the batteries should charge by, also with a minimum charge amount of 0 and maximum of 9 (the usable capacity of the batteries). A template then converts this to a decimal number of hours, which another template converts to Hours and Minutes. A bit long winded, but here is the code:

  - sensor:
      - name: "soc_usable_kwh"
        unit_of_measurement: 'kWh'
        device_class: energy
        state: "{{(((states('sensor.solinv_battery_soc')| float(0) - 15) / 10)) | round(2) }}"
  - sensor:
      - name: "soc_plus24hrs"
        unit_of_measurement: 'kWh'
        device_class: energy
        state: "{{((states('sensor.soc_usable_kwh')| float(0) + states('sensor.solcast_forecast_today')| float(0) - states('input_number.expected_consumption')| float(0))) | round(2) }}"
  - sensor:
      - name: "soc_required_charge"
        unit_of_measurement: 'kWh'
        device_class: energy
        state: "{{((states('input_number.target_usable_soc')| float(0) - states('sensor.soc_plus24hrs')| float(0))) | round(2) }}"
  - sensor:
      - name: "soc_required_charge_min_zero"
        unit_of_measurement: 'kWh'
        device_class: energy
        state: "{{ [ states('sensor.soc_required_charge')|float(0), 0.0 ] | max }}"
  - sensor:
      - name: "soc_required_charge_min_zero_max_nine"
        unit_of_measurement: 'kWh'
        device_class: energy
        state: "{{ [ states('sensor.soc_required_charge_min_zero')|float(0), 9.0 ] | min}}"
  - sensor:
      - name: "soc_charge_time_decimal"
        state: "{{((states('sensor.soc_required_charge_min_zero_max_nine')| float(0) / 1.3)) | round(2) }}"
  - sensor:
      - name: "soc_charge_end_time_decimal"
        state: "{{((states('sensor.soc_charge_time_decimal')| float(0) + states('input_number.gmt_bst')| float(0))) | round(2) }}"
  - sensor:
      - name: "soc_charge_time_hhmm"
        unique_id: "soc_charge_time_hhmm"
        state: >
           {% set hours = states('sensor.soc_charge_time_decimal') | float %}
           {% set minutes = ((hours % 1) * 60) | int %}
           {% set hours = (hours - (hours % 1)) | int %}
           {{ '%02i:%02i'%(hours, minutes) }}    
  - sensor:
      - name: "soc_charge_end_time_hhmm"
        unique_id: "soc_charge_end_time_hhmm"
        state: >
           {% set hours = states('sensor.soc_charge_end_time_decimal') | float %}
           {% set minutes = ((hours % 1) * 60) | int %}
           {% set hours = (hours - (hours % 1)) | int %}
           {{ '%02i:%02i'%(hours, minutes) }}      

What I’m most interested in is the ‘soc_charge_end_time_hhmm’, and I’m left with a String output in the format HH:MM. So as an example the charge end time of 4.15am is output 04:15.

The integration that I use to talk to the batteries is Solax Modbus, and the battery charge end time is set on there on two separate number inputs - one for Hours and one for Minutes. See here to see how that appears on my dashboard:

Picture1

The problem I’m facing is that I need to split the ‘soc_charge_end_time_hhmm’ output string into two discreet values, which I then apply in an automation to set the charge end times in Solax Modbus. In my example of 04:15, I’ll need to take the 04 to set the hours, and the 15 to set the minutes. They must be done separately which is a bit of a headache, and I can see no way of using a calculated timestamp to set them both in one go.

For info, there is also a button to update the inverter with these times after they’ve been set on the dashboard, which I’ll also automate after a few seconds delay.

I’ve tried as many different methods as I can find but nothing that works yet. If anyone has any suggestions on how to achieve this, I’ll be most grateful.

Cheers,
Jev

I won’t delve into the need for all of those sensors but the template to split the time value would be:

for the hour value:

{{ states('soc_charge_end_time_hhmm').split(':')[0] }}

for the minute value:

{{ states('soc_charge_end_time_hhmm').split(':')[1] }}

Hi Finity,

I see, you’ve really helped me here. I’d be here an hour to explain why there’s so many sensors haha.

Copying your code into the Template editor comes up with an error, but I’ve re-jigged it a bit and this is now working in the Template editor:

{{ states.sensor.soc_charge_end_time_hhmm.state.split(":")[0] }}
{{ states.sensor.soc_charge_end_time_hhmm.state.split(":")[1] }}

Do you know where those numbers will then appear if I paste this code into my config.yaml? I’m used to making sensor templates and then finding them as entities but I’m not sure how to identify these once added to config.

Thanks so much for your help
Jev

Make 2 sensors🤪 one for each. can see you have that well covered.

1 Like

Now jig it back.

https://www.home-assistant.io/docs/configuration/templating/#states

Only this time include the sensor domain.

for the hour value:

{{ states('sensor.soc_charge_end_time_hhmm').split(':')[0] }}
            ^^^
            |||

Likewise for the minute value:

{{ states('sensor.soc_charge_end_time_hhmm').split(':')[1] }}
1 Like

Jigged back, thanks for going back and for the heads up on that warning.

It’s all in and working now, including the automation to charge. I know this might be a long-winded way of going about it, but I’m doing my best with limited knowledge on coding. You’ve been so helpful in getting me sorted, thanks so much I really appreciate it.

yup, too quick on typing it out.

This project has involved building hardware too, and this was the final step (aside from some dashboard housekeeping).

Legend.

1 Like

If the number of hours never exceeds 24, then all of this:

        state: >
           {% set hours = states('sensor.soc_charge_end_time_decimal') | float %}
           {% set minutes = ((hours % 1) * 60) | int %}
           {% set hours = (hours - (hours % 1)) | int %}
           {{ '%02i:%02i'%(hours, minutes) }}

can be done like this:

        state: >
           {{ (states('sensor.soc_charge_end_time_decimal') | float(0) * 3600)
             | timestamp_custom('%H:%M', false) }}

Instead of splitting the two values, hours and minutes, out of ‘sensor.soc_charge_end_time_hhmm’, I suggest you get them directly from ‘sensor.soc_charge_end_time_decimal’ (same caveat applies as stated above).

Hour

{{ (states('sensor.soc_charge_end_time_decimal') | float(0) * 3600)
  | timestamp_custom('%H', false) }}

Minute

{{ (states('sensor.soc_charge_end_time_decimal') | float(0) * 3600)
  | timestamp_custom('%M', false) }}
1 Like

Fantastic, your suggestions are much appreciated - I’ve implemented them and it has tidied up my code nicely. I’m not a coder, so am very much learning as I go and this has been super useful :slight_smile:

As an aside, do you know a way of doing the opposite thing - to take two entity output numbers and combine them into an HH:MM time format? So using the example above, one entity is 04 and one is 15, how would we write something to create “04:15”?

Cheers
Jev

1 Like

Disregard, I got it

          {{ states('number.solinv_timed_charge_start_hours') | round(0) }}:{{ states('number.solinv_timed_charge_start_minutes') | round(0) }}