I have a Navien Hot Water Heater, that uses RS-485 to communicate. What I am trying to build is an ESP32 Interface for this unit, and have quite a bit of it working. I am hoping to find that help here and allow me to finish out the last few items that will make this complete!. In a thread here, contains most of the details.
Below is my current Configuration and a snip from the subsequent web page it produces.
I am confident there are better/more efficient ways to produce this, but with my basic knowledge of cutting and pasting code together, I have managed to stumble my way along to get here. I am open to any and all help you and provide!
Thanks!
# Include basic info in all ESP Home Configs
# Basic Info Includes
# logger:
# wifi:
# ap:
# web_server:
# captive_portal:
# button: to restart the device
<<: !include .base1.yaml
esphome:
name: navien
friendly_name: Navien Water Heater
includes:
- uart_read_line_sensor.h
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
level: NONE #makes uart stream available in esphome logstream
baud_rate: 0 #disable logging over uart
# Enable Home Assistant API
api:
encryption:
key: "redacted"
ota:
password: "redacted"
substitutions:
comment: "redacted"
friendly_name: Navien Water Heater
globals:
- id: byte_timer
type: int
initial_value: "1"
interval:
- interval: 5s
then:
- lambda: |-
id(byte_timer) = (id(byte_timer) + 1);
if (id(byte_timer) > 25) {
id(byte_timer) = 1;
}
# Example configuration entry
uart:
id: uart_bus
tx_pin: 1
rx_pin: 3
baud_rate: 19200
data_bits: 8
stop_bits: 1
parity: NONE
debug:
direction: BOTH
dummy_receiver: false
after:
delimiter: "\n"
sequence:
- lambda: |-
UARTDebug::log_string(direction, bytes);
//looking at this string f7 05 50 50 90 22 42
//where the 22 represents water information to follow
//and in the same byte if the number is 34 it is
//representative of gas information
if (bytes[0] == 247 && bytes[5] == 34) {
//id(uart_byte0).publish_state(bytes[0]);
//id(uart_byte1).publish_state(bytes[1]);
//id(uart_byte2).publish_state(bytes[2]);
//id(uart_byte3).publish_state(bytes[3]);
//id(uart_byte4).publish_state(bytes[4]);
//id(uart_byte5).publish_state(bytes[5]);
//id(uart_byte6).publish_state(bytes[6]);
//id(uart_byte7).publish_state(bytes[7]);
//id(uart_byte8).publish_state(bytes[8]);
//id(uart_byte9).publish_state(bytes[9]);
//id(uart_byte10).publish_state(bytes[10]);
id(set_temp).publish_state(((bytes[11]/2)*9/5) + 32);
id(outlet_temp).publish_state(((bytes[12]/2)*9/5) + 32);
id(inlet_temp).publish_state(((bytes[13]/2)*9/5) + 32);
//id(uart_byte14).publish_state(bytes[14]);
//id(uart_byte15).publish_state(bytes[15]);
//id(uart_byte16).publish_state(bytes[16]);
//id(uart_byte17).publish_state(bytes[17]);
id(water_flow).publish_state((bytes[18]/10)* 0.2642);
//id(uart_byte19).publish_state(bytes[19]);
//id(uart_byte20).publish_state(bytes[20]);
//id(uart_byte21).publish_state(bytes[21]);
//id(uart_byte22).publish_state(bytes[22]);
//id(uart_byte23).publish_state(bytes[23]);
//id(uart_byte24).publish_state(bytes[24]);
} else if (bytes[0] == 247 && bytes[5] == 42) {
id(low_byte_kcal).publish_state(bytes[22]);
id(high_byte_kcal).publish_state(bytes[23]);
id(total_gas_use).publish_state((bytes[24]/10)*0.3508);
} else (bytes[0] != 247); {
}
# Example configuration entry
switch:
- platform: template
name: "HW Heater On/Off"
id: navien_switch
restore_mode: ALWAYS_ON
lambda: |-
if ((id(navien_switch).state) != (id(navien_switch).state)) {
return true;
} else {
return false;
}
turn_on_action:
- uart.write: !lambda
return {0xf7, 0x05, 0x0f, 0x50, 0x10, 0x0c, 0x4f, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce};
id(navien_switch).publish_state(true);
turn_off_action:
- uart.write: !lambda
return {0xf7, 0x05, 0x0f, 0x50, 0x10, 0x0c, 0x4f, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa};
id(navien_switch).publish_state(false);
text_sensor:
- platform: custom
lambda: |-
auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));
App.register_component(my_custom_sensor);
return {my_custom_sensor};
text_sensors:
id: "uart_readline"
text:
- platform: template
name: "Temp Set - Write"
optimistic: true
min_length: 0
max_length: 5
mode: text
on_value:
then:
- sensor.template.publish:
id: num_from_text
state: !lambda |-
auto n = parse_number<float>(x);
return n.has_value() ? n.value() : NAN;
sensor:
# - platform: template
# name: "Byte 0"
# id: uart_byte0
# - platform: template
# name: "Byte 1"
# id: uart_byte1
# - platform: template
# name: "Byte 2"
# id: uart_byte2
# - platform: template
# name: "Byte 3"
# id: uart_byte3
# - platform: template
# name: "Byte 4"
# id: uart_byte4
# - platform: template
# name: "Byte 5"
# id: uart_byte5
# - platform: template
# name: "Byte 6"
# id: uart_byte6
# - platform: template
# name: "Byte 7"
# id: uart_byte7
# - platform: template
# name: "Byte 8"
# id: uart_byte8
# - platform: template
# name: "Byte 9"
# id: uart_byte9
# - platform: template
# name: "Byte 10"
# id: uart_byte10
- platform: template
name: "Temp Set - Read"
id: set_temp
unit_of_measurement: °F
- platform: template
name: "Temp Outlet"
id: outlet_temp
unit_of_measurement: °F
accuracy_decimals: 2
- platform: template
name: "Temp Inlet"
id: inlet_temp
unit_of_measurement: °F
# - platform: template
# name: "Byte 14"
# id: uart_byte14
# - platform: template
# name: "Byte 15"
# id: uart_byte15
# - platform: template
# name: "Byte 16"
# id: uart_byte16
# - platform: template
# name: "Byte 17"
# id: uart_byte17
- platform: template
name: "Water Flow"
id: water_flow
unit_of_measurement: GPM
# - platform: template
# name: "Byte 19"
# id: uart_byte19
# - platform: template
# name: "Byte 20"
# id: uart_byte20
# - platform: template
# name: "Byte 21"
# id: uart_byte21
# - platform: template
# name: "Byte 22"
# id: uart_byte22
# - platform: template
# name: "Byte 23"
# id: uart_byte23
# - platform: template
# name: "Byte 24"
# id: uart_byte24
- platform: template
name: "Total Gas Use"
id: total_gas_use
unit_of_measurement: therms
accuracy_decimals: 2
- platform: template
name: "kCal Low Byte"
id: low_byte_kcal
unit_of_measurement: kCal
- platform: template
name: "kCal High Byte"
id: high_byte_kcal
unit_of_measurement: kCal
- platform: template
id: num_from_text
name: "Temp Set - Write"
internal: True
I’m struggling with a few things that I could use some tips on.
- When using the switch I created in ESPHome to turn on/off the Heater, ideally I’d like the switch to set it’s position based on the current status of the unit, then if the switch changes - send the appropriate command. Last, I’d like to know that the command was received and that it has gone into that mode.
- Similar question regarding the setpoint. In my config, I created a second “write” setpoint to try and begin configuring this function - but I’m not sure where to go from here.
In both of those cases, I’d like to have a single value/entity show on the ESPHome web page or entity in HA.
Any and all feedback is appreciated if you see something else here that would make this project better!