A and B directly to ESP Tx and Rx without this?:
What to connect to Tx, A or B?
I just purchased the NB114 just because this post. Can you please show the internal settings of the NB114? Thanks.
Now that I have everything set, can’t find an RJ9 cable
Just for community awareness, I have wrote a fork that is now working very well for my Juntek. I have mine on a RPi, and works on both Bluteooth and RS485.
However, I can REALLY recommend you go through the RS485, as Bluteooth is plain bad (random value broadcast, no consistency, constant disconnect issues).
The RS485 however is accurate, consistent and easy.
I used one of those USB to RS485 from Amazon for about $10. It then pushes the data to MQQT.
Project and details available on the github : GitHub - AnalogThinker/junctek_monitor: A Python program to pull Juntek Battery Monitor Data over BT or RS485 and post on MQTT
Hello everyone!
I’ve recently developed an application that can read data from Junctek devices and transmit it over a port. The real-time data is stored as JSON and can be viewed through a visual dashboard available at this link: Junctek Monitoring Dashboard. This link shows my own battery online.
The system ultimately saves the data in a JSON file, making it potentially integrable with Home Assistant or other home automation systems. That integration is my next step.
As for the hardware connection, I used an RS485 cable that I had to fabricate myself – apologies for the DIY nature, but it was the quickest solution. Since I didn’t have an RJ9 connector available, I ended up using an old telephone cord which I modified to fit.
I will continue to develop and refine this project, and I’m excited to see how it can be expanded and integrated into more complex systems. Your feedback and suggestions are very welcome!
Looking forward to your thoughts and any advice you might have.
I’ve been checking your post out, and also been looking for ways to integrate python into HA. I know you have yo place the files into certain folders, but calling the results of the sensors is my issue. I’ve been using HA for 2 month now and I’m a NooB.
You don’t have to call the sensor’s results. Your sensor values will be pushed.
This is how MQTT works. Make sure your HA has the Mosquito MQTT add-on installed, running and configured (check tutorials if need to). Then as soon as MQTT gets sensor published, it will detect a new device and you will have a notification from HA on what to do with those.
As for my github scripts, I did not install anything on the HAOS, I am using a RPi with the USB-RS485 on the same network, that’s where it all happens, then it publishes to MQTT.
How did you connect the KG-F to your RPi with USB to RS485? Can you share a picture?
As straight forward as it can be: I did connect the adapter in the RPi USB port.
And the KG-F connects to the RS485 side of the adapter.
Maaan, I have an RS485 to USB adapter in a drawer for the last 4 years and never thought of using it for this. . Thanks for the tip.
Note: Also remember that the Juntek does NOT play well with both the Display and the RS485 connected at the same time. If you need to do any adjustment on the device, disconnect the RS485 first, then connect the display. Same when done, disconnect the display first then connect the RS485 back.
I have not wasted time diving into the why, probably an address conflict, but we get what we pay for. And truly, it has been doing a great job for my HA integration so far that I don’t need the display anymore.
I have spent lot of time researching, and so on how da hell connect this device with ESP32… read all topics and so on… All of them talked about RS485, and so on so i bougth it but it did not had automatic flow control… in short here is “my” ESP HOME component GitHub - Tommixoft/esphome-junctek_kgf: Component for esphome to read status from a Junctek KG-F coulometer battery monitor via UART with NO rs485 modules.
Have all possible sensors from this device DONT NEED any rs485. So just connect your ESP32 rx tx ground to 4pin connector on Junctek. Install this component via ESPHOME. And here you go. All sensors in your HA (or not all if you dont need some you can remove them from esp config)
PS. Monitor have to be connected! This integration only READ data not write so monitor should stay connected. So you have best of both worlds, local monitor on battery pack and data in HA.
@Tommixoft
It seems so far the easiest and cleanest solution. One thing is missing in descriptions is pins used for RX TX. No voltage dividers?
I suppose A= RX B=TX or it is other way around? I might be wrong but isn’t rs485 pins 5V level?
I think I will try to connect Esp32 board inside the junctek box.
Well, it’s alive…
Level of RS485 is at 3.3V so no divider needed.
I used ESP32 C3 super mini, since there was no easy way to route wires to RJ10 port solder points in main box, I used display enclosure to put esp module.
Thanks to @Tommixoft for hard part with code! With this it is really easy and clean way to integrate Junctek to HA
One note on config, for loging I had to comment out baud_rate, it is not allowing to leave 0
The other thing is values with Battery Ah Charged Total and Battery Ah Used Total in Ah is wrong. It should be Energy Charged Total KW and Energy Discharged Total.
Numbers are correct just for example it is showing 50.5Ah but it should be something like 505W or 0.505KW
Hello,
I tired different solutions (informations are quite incomplete and contradictory), but the only one that worked for me is to use Tasmota SerialBridge (connecting directly EPS32 GPIOs to battery monitor).
No way to use EspHome.
I have also display connected.
Used a NodeMCU ESP32 (AZ-Delivery):
RS485 Link connections (without any RS485 adapter, just TTL):
On Tasmota:
Configured Baudrate, limiting MQTT publish messages rates (skip 26 messages), removing non ASCII chars
Backlog SBaudRate 115200; SetOption35 26; SerialDelimiter 128
10:42:39.680 CMD: Backlog SBaudRate 115200; SetOption35 26; SerialDelimiter 128
10:42:39.706 MQT: stat/Junctek_Monitor/RESULT = {"SBaudrate":115200}
10:42:39.933 MQT: stat/Junctek_Monitor/RESULT = {"SetOption35":26}
10:42:40.131 MQT: stat/Junctek_Monitor/RESULT = {"SerialDelimiter":128}
10:42:42.100 MQT: tele/Junctek_Monitor/RESULT = {"SSerialReceived":":r51=1,227,0,0,0,0,0,255,0,30,2800,100,100,100,0,0,1,100,0,0,0,20,20,255,0,0,0,15,"}
10:42:45.601 MQT: tele/Junctek_Monitor/RESULT = {"SSerialReceived":":R51=1,"}
10:42:48.982 MQT: tele/Junctek_Monitor/RESULT = {"SSerialReceived":":r50=1,87,5379,3793,104422,16683359,17074841,999999,121,0,99,1,274,100,241109,110504,"}
10:42:52.470 MQT: tele/Junctek_Monitor/RESULT = {"SSerialReceived":":R50=1,"}
10:42:55.615 MQT: tele/Junctek_Monitor/RESULT = {"SSerialReceived":":r51=1,227,0,0,0,0,0,255,0,30,2800,100,100,100,0,0,1,100,0,0,0,20,20,255,0,0,0,15,"}
10:42:59.120 MQT: tele/Junctek_Monitor/RESULT = {"SSerialReceived":":R51=1,"}
10:43:02.500 MQT: tele/Junctek_Monitor/RESULT = {"SSerialReceived":":r50=1,55,5379,3821,104570,16683359,17075638,999999,121,0,99,1,275,100,241109,110518,"}
Then on HomeAssistant I split values using automations and publish new MQTT messages for each record 50 value (only if checksum matches):
alias: Battery Monitor split data 50
description: "Split JuncTek message r50 record (live measures)"
triggers:
- trigger: mqtt
topic: tele/Junctek_Monitor/RESULT
payload: "True"
value_template: "{{ value_json.SSerialReceived.split('=')[0] == ':r50'}}"
variables:
split_values: "{{ trigger.payload_json.SSerialReceived.split('=')[1].split(',')[:16] }}"
item:
- id
- checksum
- voltage
- current
- remaining_capacity
- discharging_energy
- charge_energy
- operational
- temperature
- function
- output_status
- direction
- remaining_time
- time_adjustment
- date
- time
check_sum: >-
{% set ns=namespace(sum0=0) %}
{% for i in range(2, 16) %}
{% set ns.sum0 = ns.sum0 + int(split_values[i]) %}
{% endfor %}
{% set cs = ns.sum0 % 255 + 1 %}
{% if int(cs) == int(split_values[1]) %}
{{ cs }}
{% endif %}
conditions:
- condition: template
value_template: "{{ check_sum == int(split_values[1]) }}"
actions:
- repeat:
count: "{{ item | length }}"
sequence:
- data:
topic: tele/bm/{{item[repeat.index-1]}}
payload: "{{split_values[repeat.index-1]}}"
retain: true
action: mqtt.publish
mode: single
and a message for record 51 (total capacity)
alias: Battery Monitor split data 51
description: "Split JuncTek message r51 record (settings values)"
triggers:
- trigger: mqtt
topic: tele/Junctek_Monitor/RESULT
payload: "True"
value_template: "{{ value_json.SSerialReceived.split('=')[0] == ':r51'}}"
variables:
split_values: "{{ trigger.payload_json.SSerialReceived.split('=')[1].split(',')[:28] }}"
check_sum: >-
{% set x = trigger.payload_json.SSerialReceived.split('=')[1].split(',')[:28] %}
{% set ns=namespace(sum0=0) %}
{% for i in range(2, 28) %}
{% set ns.sum0 = ns.sum0 + int(x[i]) %}
{% endfor %}
{% set cs = ns.sum0 % 255 + 1 %}
{% if int(cs) == int(x[1]) %}
{{ cs }}
{% endif %}
conditions:
- condition: template
value_template: "{{ check_sum == int(split_values[1]) }}"
actions:
- action: mqtt.publish
metadata: {}
data:
evaluate_payload: false
qos: 0
retain: true
topic: tele/bm/capacity
payload: "{{ split_values[10] }}"
mode: single
Then create sensors from MQTT
- sensor:
- name: "Voltage"
unique_id: junctek_kh140f_voltage
state_topic: "tele/bm/voltage"
value_template: "{{ (value | float() / 100) | round(1) }}"
unit_of_measurement: "V"
device_class: voltage
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Current"
unique_id: junctek_kh140f_current
state_topic: "tele/bm/current"
value_template: |-
{% set ns=namespace(fact = 1) %}
{% if is_state('binary_sensor.battery_monitor_discharging', 'on') %}
{% set ns.fact = -1 %}
{% endif %}
{{ ns.fact * (value | float() / 100)|round(1) }}
unit_of_measurement: "A"
device_class: current
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Remaining Capcity"
unique_id: junctek_kh140f_remaining_capacity
state_topic: "tele/bm/remaining_capacity"
value_template: "{{ (value | float() / 1000) | round(1) }}"
unit_of_measurement: "Ah"
device_class: energy_storage
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Discharge Energy"
unique_id: junctek_kh140f_discharging_energy
state_topic: "tele/bm/discharging_energy"
value_template: |-
{{ (value | float() / 100000)|round(2) }}
unit_of_measurement: "kWh"
device_class: energy
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Charge Energy"
unique_id: junctek_kh140f_charge_energy
state_topic: "tele/bm/charge_energy"
value_template: |-
{{ (value | float() / 100000)|round(2) }}
unit_of_measurement: "kWh"
device_class: energy
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Temperature"
unique_id: junctek_kh140f_temperature
state_topic: "tele/bm/temperature"
value_template: |-
{{ (value | int) - 100 }}
unit_of_measurement: "°C"
device_class: temperature
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Output Status"
unique_id: junctek_kh140f_output_status
state_topic: "tele/bm/output_status"
value_template: |-
{% set status_code = (value | int) %}
{{ { 0: 'ON',
1: 'OVP',
2: 'OCP',
3: 'LVP',
4: 'NCP',
5: 'OPP',
6: 'OTP',
99: 'OFF'}.get(status_code|int(0), 'unknown') }}
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Power"
unique_id: junctek_kh140f_power
state_topic: "tele/bm/current"
value_template: |-
{% set volt = states('sensor.battery_monitor_voltage', rounded=False, with_unit=False)|float %}
{% set amp = states('sensor.battery_monitor_current', rounded=False, with_unit=False)|float %}
{{ (volt * amp) | round(2) }}
unit_of_measurement: "W"
device_class: power
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "SoC"
unique_id: junctek_kh140f_soc
state_topic: "tele/bm/remaining_capacity"
value_template: |-
{% set capacity = (states('sensor.battery_monitor_total_capacity', rounded=False, with_unit=False) | float) %}
{% set remain = (states('sensor.battery_monitor_remaining_capacity', rounded=False, with_unit=False) | float) %}
{% if remain <= capacity %}
{% set soc = ((remain / capacity) * 100) | round(2) %}
{{ soc }}
{% endif %}
unit_of_measurement: "%"
device_class: battery
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Remaining Time"
unique_id: junctek_kh140f_remaining_time
state_topic: "tele/bm/remaining_time"
value_template: |-
{{ (value | float() / 60) | round(2) }}
unit_of_measurement: "h"
device_class: duration
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Total Capacity"
unique_id: junctek_kh140f_total_capacity
state_topic: "tele/bm/capacity"
value_template: |-
{{ ((value | int / 10) | int) }}
unit_of_measurement: "Ah"
device_class: energy_storage
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- binary_sensor:
- name: "Charging"
unique_id: junctek_kh140f_charging
state_topic: "tele/bm/direction"
value_template: |-
{% set direction = (value | int) %}
{% if direction == 1 %}
{{ "ON" }}
{% else %}
{{ "OFF" }}
{% endif %}
payload_on: "ON"
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
- name: "Discharging"
unique_id: junctek_kh140f_discharging
state_topic: "tele/bm/direction"
value_template: |-
{% set direction = (value | int) %}
{% if direction == 1 %}
{{ "OFF" }}
{% else %}
{{ "ON" }}
{% endif %}
payload_on: "ON"
device:
name: "Battery Monitor"
identifiers: "239400662"
manufacturer: Junctek
model: "KH140F"
I will try @Tommixoft solution too
EDIT:
I tried @Tommixoft solution, it works more or less.
For KHF devices data is a little bit different.
And as said by @incar there are some wrong unit of measure used (Ah instead of kWh, etc) for charging/discharging energy and power.
I forked project and made some adjustements
GitHub junctek_khf
Thanks @pongo I will try your version. Not that it is very important but is there any chance and way to expand functionality for output status state. Currently 0 or 99 is not that easy readable.
Sure, I will try to put map to something more meaningful
Great!
How did you get 16 sensors? I still have 13 using your version.
Sensor converted in a text_sensor.
Energy Today are 2 meters configured on HA.
Uptime is
- platform: uptime
name: "${name} Uptime"
id: ${device_id}_uptime_sensor
I also updated yaml exmaple
substitutions:
name: "junctek-kh140f"
device_name: ${name}
device_id: junctek_kh140f
friendly_name: "Junctek KH140F"
device_description: "Monitor Junctek KH140F SmartShunt via RS485 Link in TTL mode"
esphome:
name: ${name}
friendly_name: ${friendly_name}
comment: ${device_description}
external_components:
- source: github://gianfrdp/esphome-junctek_khf@junctek_khf
components: [ junctek_khf ]
esp32:
board: esp32dev
framework:
type: arduino
uart:
tx_pin: GPIO17
rx_pin: GPIO16
id: uart_junctek
baud_rate: 115200
junctek_khf:
id: junctek_id
address: 1
invert_current: false
update_stats_interval: 5000 # 5 seconds
update_settings_interval: 30000 # 30 seconds
uart_id: uart_junctek
sensor:
- platform: junctek_khf
junctek_id: junctek_id
voltage:
name: "${name} Voltage"
id: ${device_id}_voltage
current:
name: "${name} Current"
id: ${device_id}_current
battery_level:
name: "${name} SoC"
id: ${device_id}_battery_level
power:
name: "${name} Power"
id: ${device_id}_power
amp_hour_remain:
name: "${name} Remaining Capacity"
id: ${device_id}_remaining_capacity
battery_capacity:
name: "${name} Total Capacity"
id: ${device_id}_battery_capacity
energy_charged:
name: "${name} Charging Energy"
id: ${device_id}_charging_energy
energy_discharged:
name: "${name} Discharging Energy"
id: ${device_id}_discharging_energy
temperature:
name: "${name} Temperature"
id: ${device_id}_temperature
remaining_time:
name: "${name} Remaining Time"
id: ${device_id}_remaining_time
charging_power:
name: "${name} Charging Power"
id: ${device_id}_charging_power
discharging_power:
name: "${name} Discharging Power"
id: ${device_id}_discharging_power
text_sensor:
- platform: junctek_khf
junctek_id: junctek_id
output_status:
name: "${name} Output Status"
id: ${device_id}_output_status
I’m going to add also other setting sensors