Total newbie at this stuff but I did a thing and I thought I’d share it with everyone.
I recently had an old fireplace redone and installed a Valor G4 gas powered insert. While the fireplace came with a 433mhz remote control, I wanted to control the fireplace into Home Assistant so I can tie it to automation and sensor monitoring (like put the thermostat in Eco mode when the fireplace is on, or rough calculate gas usage).
I read a number of different articles online about how people made their fireplace smart, going as far to clone their remote using RF receivers and but I wanted something simple and straight forward. I took a ESP8266 and ESPhome and created a configuration that allows me to directly control the fireplace.
This fireplace uses a Mertik Maxitrol fireplace starter that has a 5-pin port on the side of the fireplace that’s used by the wall switch you can buy separately. The wires here are (back to front): common, fire up, on/off, fire down, and a 5th pin with an unknown function (seemingly no voltage). I had hoped the 5th wire would signal if the fireplace was on or off, but that didn’t seem to be the case.
(left side of insert, fireplace control unit, 5pin control port center)
Closing the circuit on these wires has the following functions:
- On/Off - While the fireplace is off, closing the circuit for longer than 1 second starts the ignition sequence. While the unit is on, doing so will initiate a shutdown sequence. The ignition sequence is 30 seconds long, with 10 seconds of ‘beeps’, followed by 20 seconds where the pilot warms up and the valve fully opens. The shutdown immediate closes the input valve and closes the step motor.
- Up / Down - Closing the circuit causes the valve step motor to rotate open or close depending on which wire. On this unit, it takes about 9 seconds to go from completely closed to completely open (or vice versa).
By using a 5VDC 4 channel relay and a ESP8266, and a length of security wire, I was able to wire up a controller that I can control through Lovelace.
(Controller unpacked. This is now stuffed into a project box mounted inside a cabinet next to the fireplace.)
For the ESPhome configuration, I tried to keep keep as much of the tracking on the unit itself. Apologies for the spaghetti but it works.
esphome:
name: fireplace-control
comment: A controller for the fireplace.
platform: ESP8266
board: esp01_1m
on_boot:
then:
# explicitly set the control slider to 0
- number.set:
id: flame_control
value: 0
# set the status to reboot
- text_sensor.template.publish:
id: fireplace_status
state: 'reboot'
# Enable logging
logger:
# Enable Home Assistant API
api:
services:
# this is a debug service in case a state desync between the controller
# and the fireplace occurs. Doing this resets the controller state
# back to 'off' without a hard reset.
- service: controller_reset
then:
- switch.turn_off: fire_onoff
- switch.template.publish:
id: fireplace_ignition_switch
state: OFF
- text_sensor.template.publish:
id: fireplace_status
state: 'reseting'
- lambda: |-
id(fire_size) = 0;
id(fire_target) = id(fire_size);
- number.set:
id: flame_control
value: 0
- logger.log:
format: "Control Reset. Size: %i, Target: %i, Control: %i"
args: ['id(fire_size)', 'id(fire_target)', 'id(flame_control)']
- text_sensor.template.publish:
id: fireplace_status
state: 'reset'
# this service simply turns the fireplace on.
- service: fireplace_on
then:
- switch.turn_on: fireplace_ignition_switch
# this service simply turns the fireplace off.
- service: fireplace_off
then:
- switch.turn_off: fireplace_ignition_switch
# this service turns the fireplace down to idle.
- service: fireplace_idle
then:
- number.set:
id: flame_control
value: 0
# this service turns the fireplace all the way up.
- service: fireplace_max
then:
- number.set:
id: flame_control
value: 10
ota:
# your info here
wifi:
# your wifi info here
captive_portal:
globals:
# this variable holds the internally recognized flame height
- id: fire_size
type: int
restore_value: no
initial_value: "0"
# this variable holds the requested flame height
- id: fire_target
type: int
restore_value: no
initial_value: "0"
number:
# this creates a slider entity to control the flame height,
# and manages comparisons between current and requested height.
- platform: template
name: "Flame Control"
id: flame_control
step: 1
min_value: 0
max_value: 10
mode: slider
optimistic: true
on_value:
then:
- if: #the fireplace is on and the requested height is lower than current height
condition:
lambda: 'return (id(fireplace_status).state == "on") && ((id(fire_size) < x));'
then: # hold the switch while it turns down for the notch difference times 9/8's of a second
- lambda: 'id(fire_target) = x;'
- switch.turn_on: fire_up
- text_sensor.template.publish:
id: fireplace_status
state: 'increasing'
- logger.log:
format: "Flame Up Triggered. Target: %i Current: %i"
args: [ 'id(fire_target)', 'id(fire_size)' ]
- delay: !lambda "return abs(id(fire_size) - id(fire_target)) * 9 / 8 * 1000;"
- lambda: 'id(fire_size) = id(fire_target);'
- lambda: 'id(flame_control).state = id(fire_size);'
- switch.turn_off: fire_up
- text_sensor.template.publish:
id: fireplace_status
state: 'on'
- if: #the fireplace is on and the requested height is height than current height
condition:
lambda: 'return (id(fireplace_status).state == "on") && ((id(fire_size) > x));'
then: # hold the switch while it turns up for the notch difference times 9/8's of a second
- lambda: 'id(fire_target) = x;'
- switch.turn_on: fire_down
- text_sensor.template.publish:
id: fireplace_status
state: 'decreasing'
- logger.log:
format: "Flame Down Triggered. Target: %i Current: %i"
args: [ 'id(fire_target)', 'id(fire_size)' ]
- delay: !lambda "return abs(id(fire_size) - id(fire_target)) * 10 / 9 * 1000;"
- lambda: 'id(fire_size) = id(fire_target);'
- lambda: 'id(flame_control).state = id(fire_size);'
- switch.turn_off: fire_down
- text_sensor.template.publish:
id: fireplace_status
state: 'on'
switch:
- platform: gpio
pin: GPIO5 #D1, relay 1
name: "Fire Up"
restore_mode: ALWAYS_OFF
id: fire_up
internal: true
- platform: gpio
pin: GPIO4 #D2, relay 2
name: "Fire ON/OFF"
restore_mode: ALWAYS_OFF
id: fire_onoff
internal: true
- platform: gpio
pin: GPIO0 #D3, relay 3
restore_mode: ALWAYS_OFF
name: "Fire Down"
id: fire_down
internal: true
- platform: template
name: "Fireplace Ignition"
id: fireplace_ignition_switch
turn_on_action: # when toggled, perform the ignition sequence
- then:
- switch.turn_on: fire_onoff
- text_sensor.template.publish:
id: fireplace_status
state: 'initiating'
- delay: 2s #valor fireplace debounces 2s before reacting
- switch.turn_off: fire_onoff
- switch.template.publish:
id: fireplace_ignition_switch
state: ON
- text_sensor.template.publish:
id: fireplace_status
state: 'waiting on beeps'
- delay: 10s #waiting for beeps
- text_sensor.template.publish:
id: fireplace_status
state: 'pilot on'
- delay: 20s #waiting for full ignition
- lambda: |-
id(fire_size) = 10;
id(fire_target) = id(fire_size);
- number.set:
id: flame_control
value: 10
- text_sensor.template.publish:
id: fireplace_status
state: 'on'
- logger.log:
format: "Ignited. Current: %i"
args: ['id(fire_size)' ]
turn_off_action:
- then:
- switch.turn_on: fire_onoff
- delay: 2s
- switch.turn_off: fire_onoff
- text_sensor.template.publish:
id: fireplace_status
state: 'turning off'
- delay: 10s #waiting for turn down
- switch.template.publish:
id: fireplace_ignition_switch
state: OFF
- lambda: |-
id(fire_size) = 0;
id(fire_target) = id(fire_size);
- number.set:
id: flame_control
value: 0
- logger.log:
format: "Extinguished. Current: %i"
args: ['id(fire_size)' ]
- text_sensor.template.publish:
id: fireplace_status
state: 'off'
text_sensor: # this creates a text status to help track the controller state
- platform: template
name: "Fireplace Status"
id: fireplace_status
After hooking it up into HASS, I have three UI items I use to control my fireplace:
Limitations:
- If you turn on the fireplace using another means (ie the remote control), this controller won’t know that and will desync the states.
- Doesn’t current work with the wall switch (future planned support).
- The step motor math isn’t 100% accurate (but it’s close enough).
- Wish I had a better slider for the flame control.
This was a fun little project based on my experience making a custom sprinkler controller. Hope someone finds it useful!