Home Assistant + Tasmota (Wemos mini R1) + Battery meter KG140F

Hi, i have gotten a d1 mini reading the data from the shunt, but when i add the lines:

mqtt:

  • name: D1_mini_1
    topic: tele/D1_mini_1/RESULT

To my config yaml file, i get this error when checking the config yaml file before i boot: (the topic name in my tasmota config is D1_mini_1). Do i need a ‘full topic’?

Invalid config for [mqtt]: expected dictionary for dictionary value @ data[‘mqtt’]. Got [OrderedDict([(‘name’, ‘D1_mini_1’), (‘topic’, ‘tele/D1_mini_1/RESULT’)])]. (See /config/configuration.yaml, line 198).

Any ideas?

For example, i have the lines in tasmota console:

18:10:31.823 MQT: tele/D1_mini_1/RESULT = {“SerialReceived”:":R50=1,\n:r50=1,87,2669,200,268391,98603,387360,0,129,0,99,0,8420,1000,\r\n:R51=1,\n:r51=1,143,0,0,0,0,0,100,0,0,2800,100,100,100,0,1,1,\r\n"}

Mine is done differently. Try this.

template:
  - trigger:
      - platform: mqtt
        topic: tele/D1_mini_1/RESULT
    sensor:
      - name: Freezer Battery Temperature
        unit_of_measurement: "°C"
        state: "{{ (trigger.payload.split(',')[9] | float-100) }}"

Thanks, trying how you say, unfortunately nothing shows up, and i now get this in the logs:

Logger: homeassistant.config
Source: config.py:982
First occurred: 8:21:48 PM (3 occurrences)
Last logged: 8:23:50 PM

Invalid config for [template]: [trigger] is an invalid option for [template]. Check: template->sensor->3->trigger. (See /config/configuration.yaml, line 183).
Invalid config for [template]: [trigger] is an invalid option for [template]. Check: template->sensor->3->trigger. (See /config/configuration.yaml, line 180).

Any ideas whay? Thanks again :+1::+1:

Post your yaml config. I am not an expert but let me see if I can help

Hi, thanks for offering your time :blush: (scroll to the bottom, the rest of the yaml it for my inverter, that all works fine…)

default_config:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

# Text to speech
tts:
  - platform: google_translate

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.30.33.0/24
    


modbus:
  - name: epever
    type: rtuovertcp
    host: 192.168.0.188
    port: 8088
    delay: 5
    timeout: 10
    close_comm_on_error: false
    retry_on_empty: true
    retries: 20
    sensors:
      # Utility
      - name: "Grid Voltage"
        unit_of_measurement: V
        slave: 10
        address: 0x3500
        input_type: input
        scale: 0.01
        precision: 2      
      - name: "Grid Current"
        unit_of_measurement: A
        slave: 10
        address: 0x3501
        input_type: input
        scale: 0.01
        precision: 2  
      - name: "Grid State"
        # 0:Normal, 1:Low input; 2:High input, 3: No connected
        slave: 10
        address: 0x3511
        input_type: input
      - name: "Grid Total"
        unit_of_measurement: kWh
        slave: 10
        address: 0x350F
        input_type: input
        scale: 0.01
        precision: 2
        data_type: int32
        swap: word
        count: 2
      # PV Array
      - name: "PV Voltage"
        unit_of_measurement: V
        slave: 10
        address: 0x3549
        input_type: input
        scale: 0.01
        precision: 2   
      - name: "PV Current"
        unit_of_measurement: A
        slave: 10
        address: 0x354A
        input_type: input
        scale: 0.01
        precision: 2
      - name: "PV Power"
        unit_of_measurement: W
        slave: 10
        address: 0x354B
        input_type: input
        scale: 0.01
        precision: 2
        data_type: int32
        swap: word
        count: 2
      - name: "PV Total"
        unit_of_measurement: kWh
        slave: 10
        address: 0x3557
        input_type: input
        scale: 0.01
        precision: 2
        data_type: int32
        swap: word
        count: 2
      # Load
      - name: "Load Voltage"
        unit_of_measurement: V
        slave: 10
        address: 0x3521
        input_type: input
        scale: 0.01
        precision: 2      
      - name: "Load Current"
        unit_of_measurement: A
        slave: 10
        address: 0x3522
        input_type: input
        scale: 0.01
        precision: 2   
      - name: "Load Total"
        unit_of_measurement: kWh
        slave: 10
        address: 0x3530
        input_type: input
        scale: 0.01
        precision: 2
        data_type: int32
        swap: word
        count: 2
      # Battery
      - name: "Battery Voltage"
        unit_of_measurement: V
        slave: 10
        address: 0x3580
        input_type: input
        scale: 0.01
        precision: 2      
      - name: "Battery Current"
        unit_of_measurement: A
        slave: 10
        address: 0x3581
        input_type: input
        scale: 0.01
        precision: 2   
      - name: "Battery Capacity"
        unit_of_measurement: "%"
        slave: 10
        address: 0x3586
        input_type: input
        scale: 1
      - name: "Battery Temp"
        #ElectricChrgBatteryTemp 
        unit_of_measurement: "°C"
        slave: 10
        address: 0x3512
        input_type: input
        scale: 0.01
      - name: "Battery State"
        # 0:Normal, 1:Overvoltage, 2:Undervoltage, 3:Undervoltage Disconnect, 4:Fault 
        slave: 10
        address: 0x3589
        input_type: input
      - name: "Charging Mode"
        # 1:Solar Priority, 2:Utility & Solar, 3:Solar
        slave: 10
        address: 0x9607
        input_type: holding
      - name: "Inverter Mode"
        # 0:Inverter priority, 1:Utility Priority
        slave: 10
        address: 0x9608
        input_type: holding
      - name: "Inverter Temp"
        #LoadHeatSink2Temp 
        unit_of_measurement: "°C"
        slave: 10
        address: 0x3533
        input_type: input
        scale: 0.01
       
       
        
        
        
template:
  sensor:
    - name: "Grid Power"
      unit_of_measurement: W
      device_class: power
      state: "{{((states('sensor.grid_current')| float(0) * states('sensor.grid_voltage')| float(0))) | round(2) }}"
      
    - name: "Power into batt"
      state: "{{ states('sensor.grid_power') | float + states('sensor.pv_power') | float }}"
      unit_of_measurement: W
      device_class: power
        
    - name: "House Load"
      unit_of_measurement: W
      device_class: power
      state: "{{((states('sensor.load_current')| float(0) * states('sensor.load_voltage')| float(0))) | round(2) }}"

    - trigger:
       - platform: mqtt
         topic: tele/D1_mini_1/RESULT

   

sensor:
  - platform: integration
    source: sensor.house_load
    name: energy_used
    unit_prefix: k
    round: 2

Also, when adding - trigger: - platform: mqtt topic: tele/D1_mini_1/RESULT
then sensors grid_power and house_load stop working also… Causing some kind of problem with the template i think?

see if this works. I put trigger before the sensor.

template:
  - trigger:
      - platform: mqtt
        topic: tele/D1_mini_1/RESULT
    sensor:
      - name: "Grid Power"
        unit_of_measurement: W
        device_class: power
        state: "{{((states('sensor.grid_current')| float(0) * states('sensor.grid_voltage')| float(0))) | round(2) }}"       
      - name: "Power into batt"
        state: "{{ states('sensor.grid_power') | float + states('sensor.pv_power') | float }}"
        unit_of_measurement: W
        device_class: power         
      - name: "House Load"
        unit_of_measurement: W
        device_class: power
        state: "{{((states('sensor.load_current')| float(0) * states('sensor.load_voltage')| float(0))) | round(2) }}"

Thanks very much, if also been having a bit of help on another thread i made, and is working now :+1::+1::+1::+1:

Pasted some more lines from giro above to test, but needs some editing as wrong values for current and capacity


# Loads default set of integrations. Do not remove.
default_config:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

# Text to speech
tts:
  - platform: google_translate

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.30.33.0/24
    


modbus:
  - name: epever
    type: rtuovertcp
    host: 192.168.0.188
    port: 8088
    delay: 5
    timeout: 10
    close_comm_on_error: false
    retry_on_empty: true
    retries: 20
    sensors:
      # Utility
      - name: "Grid Voltage"
        unit_of_measurement: V
        slave: 10
        address: 0x3500
        input_type: input
        scale: 0.01
        precision: 2      
      - name: "Grid Current"
        unit_of_measurement: A
        slave: 10
        address: 0x3501
        input_type: input
        scale: 0.01
        precision: 2  
      - name: "Grid State"
        # 0:Normal, 1:Low input; 2:High input, 3: No connected
        slave: 10
        address: 0x3511
        input_type: input
      - name: "Grid Total"
        unit_of_measurement: kWh
        slave: 10
        address: 0x350F
        input_type: input
        scale: 0.01
        precision: 2
        data_type: int32
        swap: word
        count: 2
      # PV Array
      - name: "PV Voltage"
        unit_of_measurement: V
        slave: 10
        address: 0x3549
        input_type: input
        scale: 0.01
        precision: 2   
      - name: "PV Current"
        unit_of_measurement: A
        slave: 10
        address: 0x354A
        input_type: input
        scale: 0.01
        precision: 2
      - name: "PV Power"
        unit_of_measurement: W
        slave: 10
        address: 0x354B
        input_type: input
        scale: 0.01
        precision: 2
        data_type: int32
        swap: word
        count: 2
      - name: "PV Total"
        unit_of_measurement: kWh
        slave: 10
        address: 0x3557
        input_type: input
        scale: 0.01
        precision: 2
        data_type: int32
        swap: word
        count: 2
      # Load
      - name: "Load Voltage"
        unit_of_measurement: V
        slave: 10
        address: 0x3521
        input_type: input
        scale: 0.01
        precision: 2      
      - name: "Load Current"
        unit_of_measurement: A
        slave: 10
        address: 0x3522
        input_type: input
        scale: 0.01
        precision: 2   
      - name: "Load Total"
        unit_of_measurement: kWh
        slave: 10
        address: 0x3530
        input_type: input
        scale: 0.01
        precision: 2
        data_type: int32
        swap: word
        count: 2
      # Battery
      - name: "Battery Voltage"
        unit_of_measurement: V
        slave: 10
        address: 0x3580
        input_type: input
        scale: 0.01
        precision: 2      
      - name: "Battery Current"
        unit_of_measurement: A
        slave: 10
        address: 0x3581
        input_type: input
        scale: 0.01
        precision: 2   
      - name: "Battery Capacity"
        unit_of_measurement: "%"
        slave: 10
        address: 0x3586
        input_type: input
        scale: 1
      - name: "Battery Temp"
        #ElectricChrgBatteryTemp 
        unit_of_measurement: "°C"
        slave: 10
        address: 0x3512
        input_type: input
        scale: 0.01
      - name: "Battery State"
        # 0:Normal, 1:Overvoltage, 2:Undervoltage, 3:Undervoltage Disconnect, 4:Fault 
        slave: 10
        address: 0x3589
        input_type: input
      - name: "Charging Mode"
        # 1:Solar Priority, 2:Utility & Solar, 3:Solar
        slave: 10
        address: 0x9607
        input_type: holding
      - name: "Inverter Mode"
        # 0:Inverter priority, 1:Utility Priority
        slave: 10
        address: 0x9608
        input_type: holding
      - name: "Inverter Temp"
        #LoadHeatSink2Temp 
        unit_of_measurement: "°C"
        slave: 10
        address: 0x3533
        input_type: input
        scale: 0.01
       
       
        
        
        
template:
- sensor:
    - name: "Grid Power"
      unit_of_measurement: W
      device_class: power
      state: "{{((states('sensor.grid_current')| float(0) * states('sensor.grid_voltage')| float(0))) | round(2) }}"
      
    - name: "Power into batt"
      state: "{{ states('sensor.grid_power') | float + states('sensor.pv_power') | float }}"
      unit_of_measurement: W
      device_class: power
        
    - name: "House Load"
      unit_of_measurement: W
      device_class: power
      state: "{{((states('sensor.load_current')| float(0) * states('sensor.load_voltage')| float(0))) | round(2) }}"
    
- trigger:
  - platform: mqtt
    topic: tele/D1_mini_1/RESULT
      
  sensor:
    - name: Temperatura
      unit_of_measurement: "°C"
      state: "{{ (trigger.payload.split(',')[9] | float-100) }}"
    - name: Tensione
      unit_of_measurement: "V"
      state: "{{ (trigger.payload.split(',')[3] | float/100) }}"
    - name: Corrent
      unit_of_measurement: "A"
      state: "{{ (trigger.payload.split(',')[4] | float/100) }}"
    - name: Potenza
      unit_of_measurement: "W"
      state: "{{ (trigger.payload.split(',')[6] | float/100) }}"
    - name: Capacità
      unit_of_measurement: "%"
      state: "{{ (trigger.payload.split(',')[5] | float/11000*100) }}"
    - name: Consumato
      unit_of_measurement: "kWh"
      state: "{{ (trigger.payload.split(',')[6] | float/10000) }}"  
      

sensor:
  - platform: integration
    source: sensor.house_load
    name: energy_used
    unit_prefix: k
    round: 2
      
      ```

I used the info provided by OP and this thread to link my Juntek 100A shunt to Home assistant.
I appreciate this, it feels good to have this info visible without having to reach for my phone or walk to the display.

I was able to link the state of charge and I’ll paste my code in case others can use it.
My code has all the sections of r50 because I wanted to monitor the values to see the info it carried
This code goes in the configuration.yaml (putting this down as it stumped me when I found the thread as a newb)

One thing I’m stumped on as this is my first HA project, is the value for the AMPS being used is sent as a positive number even when the amps are being drawn.

I found the value that corresponds to the negative and positive switch.
It’s down the string at section [12], it returns a 0 if the amps are negative and it returns a 1 if the amps are positive.
Can anyone suggest a code that will watch the section at [12] and if it is 1 do nothing but if it is 0 it would take the value and subtract the value x 2.

var pos/neg
var amps
if [12] = 1
do nothing
if [12] = 0
pos/neg = amps - (amps + amps)

or a conversion trick to reverse polarity of an sensor value.
I’m new to HA code

template:
  - trigger:
      - platform: mqtt
        topic: tele/D1_mini_1/RESULT

    sensor:
      - name: SOCX
        unit_of_measurement: "%"
        state: "{{ (trigger.payload.split(',')[2] | float/11000*100) }}"
      - name: Voltage
        unit_of_measurement: "V"
        state: "{{ (trigger.payload.split(',')[3] | float/100) }}"
      - name: Current
        unit_of_measurement: "A"
        state: "{{ (trigger.payload.split(',')[4] | float/100) }}"
      - name: Amp Hours Remaining
        unit_of_measurement: "AH"
        state: "{{ (trigger.payload.split(',')[5] | float/1000) }}"
      - name: Battery Remaining
        unique_id: 0000420000-1
        unit_of_measurement: "%"
        state: "{{ (trigger.payload.split(',')[5] | float/10/400) }}"
      - name: Total Power Used
        unit_of_measurement: "AH"
        state: "{{ (trigger.payload.split(',')[6] | float/1000) }}"
      - name: Elec. Consumption
        unit_of_measurement: "kW-h"
        state: "{{ (trigger.payload.split(',')[7] | float/100000) }}"
      - name: Total kW-h
        unit_of_measurement: "kW-h"
        state: "{{ (trigger.payload.split(',')[8] | float/10000) }}"
      - name: Temperature
        unit_of_measurement: "°C"
        state: "{{ (trigger.payload.split(',')[9] | float-100) }}"
      - name: VoltageXX
        unit_of_measurement: "V"
        state: "{{ (trigger.payload.split(',')[10] | float/100) }}"
      - name: CurrentXX
        unit_of_measurement: "A"
        state: "{{ (trigger.payload.split(',')[11] | float/100) }}"
      - name: pos/neg
        state: "{{ (trigger.payload.split(',')[12]) }}"
      - name: Battery Life AH
        unit_of_measurement: "AH"
        state: "{{ (trigger.payload.split(',')[13] | float/10) }}"
      - name: Internal Resistance
        unit_of_measurement: "m-Ohm"
        state: "{{ (trigger.payload.split(',')[14] | float/100) }}"

Hi, my Tasmota consolle doesn’t show 11:27:23.727 MQT: tele/BatteryMonitor/RESULT = same as others. Did I miss something?

Hope you did not miss this

Rule1 on System#Boot do RuleTimer1 10 endon on Rules#Timer=1 do backlog SerialSend :R50=1,2,1,; RuleTimer1 10 endon

Rule1 1

Check also the connection between KG140F and your Wemos mini (or whatever you use)

Hi Giro,
can you please suggest a RS485 converter? Or send some detail (chip name and input and ouput connection) and a picture of your?
I buyed a rs485 to TTL but it doesn’t seem to be correct for this job.
Thank you very much.

Lucio

Hi,
I’m a noob in home assistant but i want to contribute with this community.
After reading the documentation about the KG140F DC 0-120V 100A and compare it with the information of this thread I got the following information:

The communication channel give me the following:
My shunt has this values:

r50=2,215,2056,200,5408,4592,9437,14353,134,0,0,0,162,30682

Explanation:


position    Description
1           2 represents the communication address;
2           215 represents the checksum;
3           2056 represents the voltage of 20.56V;
4           200 represents current 2.00A;
5           5408 represents the remaining battery capacity is 5.408Ah;
6           4593 means the cumulative capacity is 4.593Ah;
7           9437 represents the watt-hour is 0.09437kw.h;
8           14353 represents the running time of 14353s;
9           134 represents the ambient temperature is 34℃;
10          0 means the function is pending;
11          0 means the output status is ON; (0-ON, 1-OVP, 2-OCP, 3-LVP, 4-NCP, 5-OPP, 6-OTP, 255-OFF)
12          0 represents the direction of current, and the current is forward current; (0-forward, 1-reverse)
13          162 means battery life is 162 minutes;
14          30682 represents the internal resistance of the battery is 306.82mΩ.

Decoding:

                                HA position split
Address(1,2,3,4,5,6,....)               1
Checksum:153,		                    2
Voltage(V)(2056->20.56)                 3   
CurrentAmpere(A)(200->2.0)              4
RemainingAh(Ah)(5408->5.408)            5
ElapsedAH(Ah)			                6   
AccumulatedChargingCapacity(Kwh)	    7
RunningTimeSeconds,				        8
Temperature(ºC)(134->34ºc->134-100)     9
pending 		                        10
OutputStatus(alarms)                    11
CurrentDirection(0/1)                   12
BatteryLifeMinutes      	            13
ohm(30682->306.82->30682/100)           14

After struggling my head with the sensors, templates and so on, i finished with the following package(yaml file): pck_enrgyconsum_battery_control.yaml

input_number:
  number_ampere_preset:
    name: Number-Ampere-preset
    icon: mdi:battery-high
    min: 0
    max: 360
    initial: 127.5
    step: 0.1
    mode: box
    unit_of_measurement: Ah


template:
  - trigger:
      - platform: mqtt
        topic: tele/tasmota_03-ESP32-Shunt-PowerBank/RESULT
    sensor:
      - name: KG140F-01-Address
        # unit_of_measurement: ""
        state: "{{ (trigger.payload.split(',')[1] | float) }}"

      - name: KG140F-01-Checksum
        # unit_of_measurement: "V"
        state: "{{ (trigger.payload.split(',')[2] | float) }}"

      - name: KG140F-01-Voltage
        unit_of_measurement: "V"
        state: "{{ (trigger.payload.split(',')[3] | float/100) }}"  

      - name: KG140F-01-CurrentAmpere
        unit_of_measurement: "Ah"
        state: "{{ (trigger.payload.split(',')[4] | float/100) }}"

      - name: KG140F-01-RemainingAh
        unit_of_measurement: "Ah"
        state: "{{ (trigger.payload.split(',')[5] | float/1000) }}"

      - name: KG140F-01-ElapsedAH
        unit_of_measurement: "Ah"
        state: "{{ (trigger.payload.split(',')[6] | float/1000) }}"

      - name: KG140F-01-AccumChrgCapacity
        unit_of_measurement: "Kwh"
        state: "{{ (trigger.payload.split(',')[7] | float/100000) }}"        

      - name: KG140F-01-RunningTimeSeconds
        unit_of_measurement: "s"
        state: "{{ (trigger.payload.split(',')[8] | float) }}"

      - name: KG140F-01-RunningTimeHours
        unit_of_measurement: "h"
        state: "{{ (trigger.payload.split(',')[8] | float/60/60) }}"        

      - name: KG140F-01-Temperature
        unit_of_measurement: "ºC"
        state: "{{ (trigger.payload.split(',')[9] | float-100) }}"        

      - name: KG140F-01-Pending
        # unit_of_measurement: ""
        state: "{{ (trigger.payload.split(',')[10] | float) }}"

      - name: KG140F-01-OutputStatus
        # unit_of_measurement: ""
        state: "{{ (trigger.payload.split(',')[11] | float) }}"

      - name: KG140F-01-CurrentDirection
        # unit_of_measurement: ""
        state: "{{ (trigger.payload.split(',')[12] | float) }}"        

      - name: KG140F-01-BatteryLifeMinutes
        unit_of_measurement: "min"
        state: "{{ (trigger.payload.split(',')[13] | float) }}"

      - name: KG140F-01-BatteryLifeHours
        unit_of_measurement: "h"
        state: "{{ (trigger.payload.split(',')[13] | float/60) }}"

      - name: KG140F-01-Ohm      
        unit_of_measurement: "mΩ"
        state: "{{ (trigger.payload.split(',')[14] | float/100) }}"


sensor:
# Calculate current power
  - platform: template
    sensors:
      kg140f_01_currentpower:
        value_template: >
            {% set t = states('sensor.kg140f_01_currentdirection') | float(0) %}
            {% if t == 0 %}
              {{ '%0.1f' | format ( -1 |float * 
                                    ( 
                                      states('sensor.kg140f_01_voltage') | float * 
                                      states('sensor.kg140f_01_currentampere') | float 
                                    )
                                  )
              }}
            {% elif t == 1 %}
              {{ '%0.1f' | format 
                              ( 
                                states('sensor.kg140f_01_voltage') | float * 
                                states('sensor.kg140f_01_currentampere') | float 
                              )
              }}
            {% else %}
              {{ '%0.1f' | format 
                              ( 
                                states('sensor.kg140f_01_voltage') | float * 
                                states('sensor.kg140f_01_currentampere') | float 
                              )
              }}              
            {% endif %}           
        unit_of_measurement: 'W'
        friendly_name: KG140F-01 Current Power
      
      kg140f_01_ampereconsumption:
        value_template: >
            {% set t = states('sensor.kg140f_01_currentdirection') | float(0) %}
            {% if t == 0 %}
              {{ '%0.1f' | format ( -1 |float * states('sensor.kg140f_01_currentampere') | float ) }}
            {% elif t == 1 %}
              {{states('sensor.kg140f_01_currentampere')|float }}
            {% else %}
              {{states('sensor.kg140f_01_currentampere')|float }}
            {% endif %}          
        unit_of_measurement: 'Ah'
        friendly_name: KG140F-01 Ampere Consumption

      kg140f_01_battery_level:
        value_template: >
          {{ '%0.1f' | format
                        (
                          (states('sensor.kg140f_01_remainingah') | float * 100 ) /
                          states('input_number.number_ampere_preset') | float
                        )
          }}       
        unit_of_measurement: '%'
        friendly_name: KG140F-01 Battery Level

The only thing that is not working for me, is the tasmota rule, despite whatever i put in the rule, the transmission to the HA is every second… I bought some D1 mini, just for check if the problem is the ESP32 or not.

Rule1 on System#Boot do RuleTimer1 10 endon on Rules#Timer=1 do backlog SerialSend :R50=1,2,1,; RuleTimer1 10 endon

Rule1 1

So the dashboard is:
When the shunt detect the negative current:

When the shunt detect the positive current(charging):

Thanks a lot to all of you for your knowledge
Luis.

Thank you all for this. Seems perfect for RV use also!