configs/sthome-ut3.yaml

1062 lines
34 KiB
YAML

external_components:
- source:
type: local
path: components # Path relative to this YAML file
components: [ rtq6056 ] #ads1115_int, tlc59208f_ext, ds3231, ac_voltage_sensor ] #, ads131m08 ]
packages:
- !include ./common/wifi.yaml
- !include common/canbus.yaml
- !include common/modbus.yaml
substitutions:
name: sthome-ut3
friendly_name: "sthome-ut3"
esphome:
name: "${name}"
friendly_name: "${friendly_name}"
includes:
- source # copies folder with files to relevant to be included in esphome compile
- <source/solar/cb_frame.h> # angle brackets ensure file is included above globals in main.cpp. Make sure to use include GUARDS in the file to prevent double inclusion
- <source/solar/cbf_store.h>
- <source/solar/cbf_pylon.h>
- <source/solar/cbf_store_pylon.h>
- <source/solar/cbf_sthome.h>
- <source/solar/cbf_store_sthome.h>
- <source/solar/cbf_cache.h>
globals:
- id: ctr
type: int
restore_value: no
initial_value: '0'
- id: geyser_relay_status
type: bool
restore_value: yes
initial_value: 'false'
- id: can_msgctr
type: int
restore_value: no
- id: can2_msgctr
type: int
restore_value: no
- id: last_battery_message_time
type: time_t
restore_value: no
- id: g_cb_cache # the cache is used to only accept a frame after it has been received a specified number of times within a specified period. this hopefully will iron out spurious corrupted frames
type: solar::cbf_cache
restore_value: no
- id: g_cb_request_queue
type: std::queue< std::set<uint32_t> >
restore_value: no
debug:
update_interval: 10s
esp32:
board: nodemcu-32s #esp32dev
cpu_frequency: 240MHz
framework:
type: esp-idf #arduino #
# Enable logging
logger:
level: DEBUG
initial_level: INFO
logs:
uart_debug: INFO # If set to DEBUG, logs raw UART data in hex format, with direction indication (RX/TX) and timestamp. Can be very verbose, so use with caution.
modbus: DEBUG
modbus_controller: INFO
light: INFO
output: INFO
canbus: DEBUG
canbus_mcp2515: DEBUG
sensor: INFO
rtq6056: INFO
# Enable Home Assistant API
api:
encryption:
key: "AIoquKPjpcHa2pcJ0aKxvtpM3mwgZuZhpCPtdVitP2Q="
ota:
- platform: esphome
password: "879012af7180c8700cee65fbf18704d1"
wifi:
manual_ip:
static_ip: 10.0.2.3
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${name} Fallback Hotspot"
password: "cGXb2DqkwaOr"
captive_portal:
#preferences:
# flash_write_interval: 30s
sun:
id: sun_sensor
latitude: !secret latitude
longitude: !secret longitude
time:
- platform: homeassistant
id: time_source
interval:
- interval: 30s
then:
- lambda: |-
id(canbus_send_heartbeat).execute();
# - interval: 1.707s
# then:
# - uart.write:
# data: "sthome3 heartbeat\r\n"
# int loopsec = id(ctr) % 10;
# id(ctr)++;
# ESP_LOGI("main_loop", "Loop sec: %d", loopsec);
# if (loopsec == 0) {
# id(zone1_light).turn_on().set_brightness(1).perform();
# } else {
# id(zone1_light).turn_off().perform();
# }
# if (loopsec == 1) {
# id(zone2_light).turn_on().set_brightness(1).perform();
# } else {
# id(zone2_light).turn_off().perform();
# }
# if (loopsec == 2) {
# id(zone3_light).turn_on().set_brightness(1).perform();
# } else {
# id(zone3_light).turn_off().perform();
# }
# if (loopsec == 3) {
# id(zone4_light).turn_on().set_brightness(1).perform();
# } else {
# id(zone4_light).turn_off().perform();
# }
# if (loopsec == 4) {
# id(zone5_light).turn_on().set_brightness(1).perform();
# } else {
# id(zone5_light).turn_off().perform();
# }
# if (loopsec == 5) {
# id(zone6_light).turn_on().set_brightness(1).perform();
# } else {
# id(zone6_light).turn_off().perform();
# }
# if (loopsec == 7) {
# id(lights_frontyard_relay).turn_on();
# } else {
# id(lights_frontyard_relay).turn_off();
# }
# if (loopsec == 8) {
# id(lights_backyard_relay).turn_on();
# } else {
# id(lights_backyard_relay).turn_off();
# }
# if (loopsec == 9) {
# id(alarm_zone4_relay).turn_on();
# } else {
# id(alarm_zone4_relay).turn_off();
# }
i2c:
- id: bus_a
sda: GPIO21
scl: GPIO22
scan: true
frequency: 200kHz
spi:
- id: spi_bus0
clk_pin: GPIO18
mosi_pin: GPIO23
miso_pin: GPIO19
interface: any
uart:
- id: sth_uart
tx_pin: GPIO17 # Tx1
rx_pin:
number: GPIO16 # Rx1
inverted: false
mode:
input: true
pullup: true
baud_rate: ${STHOME_ALARM_MODBUS_BAUD_RATE}
stop_bits: 1
parity: NONE
debug:
direction: BOTH
dummy_receiver: false
after:
delimiter: "\n"
sequence:
- lambda: UARTDebug::log_hex(direction, bytes, ',');
####################### MODBUS SERVER #############################################
modbus:
- id: modbus_server
uart_id: sth_uart
send_wait_time: 1200ms #250ms
disable_crc: false
role: server
modbus_controller:
- id: modbus_alarm_server
modbus_id: modbus_server
address: ${STHOME_ALARM_MODBUS_DEVICE_ADDRESS}
server_registers:
- address: ${STHOME_ALARM_MODBUS_REG_ALARM_STATUS}
value_type: S_DWORD_R
read_lambda: |-
uint16_t alarm_status = id(person_detected_switch).state ? 1 : 0;
alarm_status |= id(alarm_zone4_relay).state ? 2 : 0;
alarm_status |= id(lights_backyard_relay).state ? 4 : 0;
alarm_status |= id(lights_frontyard_relay).state ? 8 : 0;
alarm_status |= id(floodlight_test).state ? 16 : 0;
alarm_status |= id(night_time).state ? 32 : 0;
alarm_status |= id(zone1_triggered).state ? 64 : 0;
alarm_status |= id(zone2_triggered).state ? 128 : 0;
alarm_status |= id(zone3_triggered).state ? 256 : 0;
alarm_status |= id(zone4_triggered).state ? 512 : 0;
alarm_status |= id(zone5_triggered).state ? 1024 : 0;
alarm_status |= id(zone6_triggered).state ? 2048 : 0;
return alarm_status;
- address: ${STHOME_ALARM_MODBUS_REG_ALARM_SIGNAL}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(alarm_signal).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z1Z4_CURRENT}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z1z4_current_ma).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z2Z5_CURRENT}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z2z5_current_ma).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z3Z6_CURRENT}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z3z6_current_ma).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z1Z4_BUS_VOLTAGE}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z1z4_bus_voltage).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z2Z5_BUS_VOLTAGE}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z2z5_bus_voltage).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z3Z6_BUS_VOLTAGE}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z3z6_bus_voltage).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z1Z4_POWER}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z1z4_power).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z2Z5_POWER}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z2z5_power).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z3Z6_POWER}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z3z6_power).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z1Z4_SHUNT_VOLTAGE}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z1z4_shunt_voltage).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z2Z5_SHUNT_VOLTAGE}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z2z5_shunt_voltage).state;
- address: ${STHOME_ALARM_MODBUS_REG_Z3Z6_SHUNT_VOLTAGE}
value_type: FP32_R
read_lambda: |-
return ${STHOME_ALARM_MODBUS_FLOAT_SCALE} * id(z3z6_shunt_voltage).state;
############################ MODBUS CLIENT EXAMPLE #############################################
#modbus:
# - id: modbus_client
# uart_id: sth_uart
# send_wait_time: 250ms #1200ms #250ms
# disable_crc: false
# role: client
#
#modbus_controller:
# - id: modbus_alarm_client
# modbus_id: modbus_client
# address: 0x01
# allow_duplicate_commands: False
# command_throttle: 700ms #2022ms
# update_interval: 10s #305s
# offline_skip_updates: 2
# max_cmd_retries: 1
# setup_priority: -10
canbus:
- platform: mcp2515
cs_pin: GPIO32 # CBCS
spi_id: spi_bus0
id: canbus_sthome
mode: NORMAL
can_id: ${CB_CANBUS_ID03}
bit_rate: 500KBPS
on_frame:
- can_id: 0
can_id_mask: 0
then:
- lambda: |-
id(can_msgctr)++;
using namespace solar;
auto time_obj = id(time_source).now();
//ESP_LOGI("CB REC", "%s", id(time_source).now().strftime("%a %d %b %Y - %I:%M:%S %p"));
if(time_obj.is_valid()) {
if (can_id >= 0x380 && can_id < 0x3C0) {
auto cbitem = cbf_store_sthome(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
bool publish = id(g_cb_cache).additem(cbitem);
if(publish) {
ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
}
}
else {
auto cbitem = cbf_store_sthome(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
}
}
output:
- platform: ledc
pin:
number: GPIO14
inverted: false
id: zone1_led
frequency: 1000 Hz
- platform: ledc
pin:
number: GPIO12
inverted: false
id: zone2_led
frequency: 1000 Hz
- platform: ledc
pin:
number: GPIO13
inverted: false
id: zone3_led
frequency: 1000 Hz
- platform: ledc
pin:
number: GPIO4
inverted: false
id: zone4_led
frequency: 1000 Hz
- platform: ledc
pin:
number: GPIO2
inverted: false
id: zone5_led
frequency: 1000 Hz
- platform: ledc
pin:
number: GPIO15
inverted: false
id: zone6_led
frequency: 1000 Hz
light:
- platform: monochromatic
output: zone1_led
name: "Zone 1"
id: zone1_light
default_transition_length: 5ms
on_turn_on:
- lambda: |-
ESP_LOGV("zone", "Zone 1 on");
on_turn_off:
- lambda: |-
ESP_LOGV("zone", "Zone 1 off");
- platform: monochromatic
output: zone2_led
name: "Zone 2"
id: zone2_light
default_transition_length: 5ms
on_turn_on:
- lambda: |-
ESP_LOGV("zone", "Zone 2 on");
on_turn_off:
- lambda: |-
ESP_LOGV("zone", "Zone 2 off");
- platform: monochromatic
output: zone3_led
name: "Zone 3"
id: zone3_light
default_transition_length: 5ms
on_turn_on:
- lambda: |-
ESP_LOGV("zone", "Zone 3 on");
on_turn_off:
- lambda: |-
ESP_LOGV("zone", "Zone 3 off");
- platform: monochromatic
output: zone4_led
name: "Zone 4"
id: zone4_light
default_transition_length: 5ms
on_turn_on:
- lambda: |-
ESP_LOGV("zone", "Zone 4 on");
on_turn_off:
- lambda: |-
ESP_LOGV("zone", "Zone 4 off");
- platform: monochromatic
output: zone5_led
name: "Zone 5"
id: zone5_light
default_transition_length: 5ms
on_turn_on:
- lambda: |-
ESP_LOGV("zone", "Zone 5 on");
on_turn_off:
- lambda: |-
ESP_LOGV("zone", "Zone 5 off");
- platform: monochromatic
output: zone6_led
name: "Zone 6"
id: zone6_light
default_transition_length: 5ms
on_turn_on:
- lambda: |-
ESP_LOGV("zone", "Zone 6 on");
on_turn_off:
- lambda: |-
ESP_LOGV("zone", "Zone 6 off");
text_sensor:
- platform: debug
device:
name: "Device Info"
reset_reason:
name: "Reset Reason"
# human readable update text sensor from sensor:uptime
- platform: template
name: Uptime
id: uptime_human
icon: mdi:clock-start
update_interval: 10s
switch:
- platform: restart
name: "${name} Restart"
id: "restart_switch"
# if person detected, trigger zone4. If the alarm is armed, alarm_zone4_relay will cause the alarm to sound
# if alarm is not armed, alarm_zone4_relay will not have any effect and the alarm will not sound. However, we will still turn on the floodlights for both backyard and frontyard if it's night time or floodlight test mode is on.
# the person detected switch will be turned on by home-assistant automation when the person detection frigate sensor detects a person. We will use this switch to trigger the alarm and floodlights, and then turn it off after a short delay to reset the state for the next detection.
- platform: template
name: "Person Detected"
id: person_detected_switch
icon: "mdi:alarm-light-outline"
restore_mode: RESTORE_DEFAULT_OFF
turn_on_action:
- switch.turn_on: alarm_zone4_relay
- if:
condition:
or:
- binary_sensor.is_on: night_time
- binary_sensor.is_on: floodlight_test
then:
# if alarm is triggered and lights are enabled, turn on the floodlights for both backyard and frontyard
- switch.turn_on: lights_backyard_relay
- switch.turn_on: lights_frontyard_relay
- platform: gpio
pin:
number: GPIO25
inverted: true
id: alarm_zone4_relay
name: "Alarm Zone 4"
icon: "mdi:alarm-light-outline"
restore_mode: RESTORE_DEFAULT_OFF
on_turn_on:
- delay: 20s
- switch.turn_off: alarm_zone4_relay
- platform: gpio
pin:
number: GPIO26
inverted: true
id: lights_backyard_relay
name: "Floodlights Backyard"
icon: "mdi:light-flood-down"
restore_mode: RESTORE_DEFAULT_OFF
# the backyard floodlight auto turns off in 4min 14 sec. So we need to switch relay off just before or at this time
# TODO: remove or extend auto turn off to >= 10min
on_turn_on:
- delay: 250s
- switch.turn_off: lights_backyard_relay
- platform: gpio
pin:
number: GPIO27
inverted: true
id: lights_frontyard_relay
name: "Floodlights Frontyard"
icon: "mdi:light-flood-down"
restore_mode: RESTORE_DEFAULT_OFF
# the frontyard floodlight auto turns off in x sec. So we need to switch relay off just before or at this time
# TODO: remove or extend auto turn off to >= 10min
on_turn_on:
- delay: 250s
- switch.turn_off: lights_frontyard_relay
# define DIGITAL_D1 04
binary_sensor:
##### MODBUS CLIENT BINARY SENSORS ###
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_person_detected
# name: "MBC Person Detected"
# register_type: read
# address: 0x0001
# bitmask: 0x1
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_alarm_zone4_relay
# name: "MBC Alarm Zone 4 Relay"
# register_type: read
# address: 0x0001
# bitmask: 0x2
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_lights_backyard_relay
# name: "MBC Lights Backyard Relay"
# register_type: read
# address: 0x0001
# bitmask: 0x4
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_lights_frontyard_relay
# name: "MBC Lights Frontyard Relay"
# register_type: read
# address: 0x0001
# bitmask: 0x8
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_floodlight_test
# name: "MBC Floodlight Test"
# register_type: read
# address: 0x0001
# bitmask: 0x10
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_night_time
# name: "MBC Night Time"
# register_type: read
# address: 0x0001
# bitmask: 0x20
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_zone1_triggered
# name: "MBC Zone 1 Triggered"
# register_type: read
# address: 0x0001
# bitmask: 0x40
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_zone2_triggered
# name: "MBC Zone 2 Triggered"
# register_type: read
# address: 0x0001
# bitmask: 0x80
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_zone3_triggered
# name: "MBC Zone 3 Triggered"
# register_type: read
# address: 0x0001
# bitmask: 0x100
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_zone4_triggered
# name: "MBC Zone 4 Triggered"
# register_type: read
# address: 0x0001
# bitmask: 0x200
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_zone5_triggered
# name: "MBC Zone 5 Triggered"
# register_type: read
# address: 0x0001
# bitmask: 0x400
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_zone6_triggered
# name: "MBC Zone 6 Triggered"
# register_type: read
# address: 0x0001
# bitmask: 0x800
### END OF MODBUS CLIENT BINARY SENSORS ###
- platform: gpio
# device_class: light
id: floodlight_test
pin:
number: GPIO33
mode:
input: true
pullup: true
filters:
- delayed_off: 100ms
name: "Floodlights Test Mode"
icon: "mdi:lightbulb-on-outline"
- platform: template
name: "Night Time"
id: night_time
lambda: |-
// we will use the sun elevation to determine if the floodlights should be on or not. If the sun elevation is below -6 degrees, we will consider it as night time
return false; // debug
double sun_elevation = id(sun_sensor).elevation();
return (sun_elevation <= -6); // -6° = civil twilight, -12° = nautical twilight, -18° = astronomical twilight
- platform: template
name: "Zone 1 Triggered"
id: zone1_triggered
lambda: |-
// NB! LED will light up when zone is interrupted, so the logic is inverted. When the zone is not interrupted, there will be current flowing through the shunt and the LED will be off. When the zone is interrupted, there will be no current flowing through the shunt and the LED will be on. So we will use the current reading to determine if the zone is interrupted or not. We will also use the current reading to determine if both zones S1 and S4 are active or not, since they are on the same shunt and we can only get combined current for both zones.
// Using up to maximum of 13V supply, 2200ohm and 3300ohm resistors, we can get a maximum of around 10.91mA current through the shunt when both zones S1 and S4 are active, below 7.6mA and above 4.6mA when S1 is active and S4 is not active, and below 3.3mA when S1 is not active and S4 is active. So we can use 3.3mA as a threshold to determine if S1 is #active r not, and 7.6mA as a threshold to determine if S4 is active or not. If the current is below 3.3mA, we can assume that both zones are inactive and return false. If the #current is bove 7.6mA, we can assume that both zones are active and return true. If the current is between 3.3mA and 7.6mA, we can assume that only one of the zones is active #and return true or zone 1 and false for zone 4.
double current = id(z1z4_current_ma).state; // in mA
if (current >= 8) {
id(zone1_light).turn_on().set_brightness(1).perform();
return true; // Error condition, current is higher than expected. This could be a full short circuit done by burglar to bypass the shunt and make the alarm think that zone 1 is not active, so we will treat it as zone 1 being active to be safe. We can later add a separate binary sensor for short circuit detection if needed.
}
if (current > 4.5) {
id(zone1_light).turn_off().perform();
return false; // Zone 1 or both zones are inactive
}
id(zone1_light).turn_on().set_brightness(1).perform();
return true; // Zone 1 is active (either alone or with Zone 4)
- platform: template
name: "Zone 4 Triggered"
id: zone4_triggered
lambda: |-
double current = id(z1z4_current_ma).state; // in mA
if(current < 2) {
id(zone4_light).turn_on().set_brightness(1).perform();
return true; // both zones are active
}
if (current < 4.5) {
id(zone4_light).turn_off().perform();
return false; // Zone 4 is inactive, Zone 1 is active
}
if (current < 6) {
id(zone4_light).turn_on().set_brightness(1).perform();
return true; // Zone 4 is active, Zone 1 is inactive
}
if (current < 8){
id(zone4_light).turn_off().perform();
return false; // Zone 4 is inactive, Zone 1 is inactive
}
id(zone4_light).turn_on().set_brightness(1).perform();
return true; // Error case, current is higher than expected. This could be a full short circuit done by burglar to bypass the shunt and make the alarm think that zone 4 is not active, so we will treat it as zone 4 being active to be safe. We can later add a separate binary sensor for short circuit detection if needed.
- platform: template
name: "Zone 2 Triggered"
id: zone2_triggered
lambda: |-
double current = id(z2z5_current_ma).state; // in mA
if (current >= 8) {
id(zone2_light).turn_on().set_brightness(1).perform();
return true;
}
if (current > 4.5) {
id(zone2_light).turn_off().perform();
return false; // Zone 2 or both zones are inactive
}
id(zone2_light).turn_on().set_brightness(1).perform();
return true; // Zone 2 is active (either alone or with Zone 5)
- platform: template
name: "Zone 5 Triggered"
id: zone5_triggered
lambda: |-
double current = id(z2z5_current_ma).state; // in mA
if(current < 2) {
id(zone5_light).turn_on().set_brightness(1).perform();
return true; // both zones are active
}
if (current < 4.5) {
id(zone5_light).turn_off().perform();
return false; // Zone 5 is inactive, Zone 2 is active
}
if (current < 6) {
id(zone5_light).turn_on().set_brightness(1).perform();
return true; // Zone 5 is active, Zone 2 is inactive
}
if (current < 8){
id(zone5_light).turn_off().perform();
return false; // Zone 5 is inactive, Zone 2 is inactive
}
id(zone5_light).turn_on().set_brightness(1).perform();
return true; // Error case
- platform: template
name: "Zone 3 Triggered"
id: zone3_triggered
lambda: |-
double current = id(z3z6_current_ma).state; // in mA
if (current >= 8) {
id(zone3_light).turn_on().set_brightness(1).perform();
return true;
}
if (current > 4.5) {
id(zone3_light).turn_off().perform();
return false; // Zone 3 or both zones are inactive
}
id(zone3_light).turn_on().set_brightness(1).perform();
return true; // Zone 3 is active (either alone or with Zone 6)
- platform: template
name: "Zone 6 Triggered"
id: zone6_triggered
lambda: |-
double current = id(z3z6_current_ma).state; // in mA
if(current < 2) {
id(zone6_light).turn_on().set_brightness(1).perform();
return true; // both zones are active
}
if (current < 4.5) {
id(zone6_light).turn_off().perform();
return false; // Zone 6 is inactive, Zone 3 is active
}
if (current < 6) {
id(zone6_light).turn_on().set_brightness(1).perform();
return true; // Zone 6 is active, Zone 3 is inactive
}
if (current < 8){
id(zone6_light).turn_off().perform();
return false; // Zone 6 is inactive, Zone 3 is inactive
}
id(zone6_light).turn_on().set_brightness(1).perform();
return true; // Error case
sensor:
#### MODBUS CLIENT SENSORS ###
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z1z4_current
# name: "MBC Z1Z4 Current"
# address: 0x0002
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "mA"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z2z5_current
# name: "MBC Z2Z5 Current"
# address: 0x0006
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "mA"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z3z6_current
# name: "MBC Z3Z6 Current"
# address: 0x000A
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "mA"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z1z4_bus_voltage
# name: "MBC Z1Z4 Bus Voltage"
# address: 0x000E
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "V"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z2z5_bus_voltage
# name: "MBC Z2Z5 Bus Voltage"
# address: 0x0012
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "V"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z3z6_bus_voltage
# name: "MBC Z3Z6 Bus Voltage"
# address: 0x0016
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "V"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z1z4_power
# name: "MBC Z1Z4 Power"
# address: 0x001A
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "W"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z2z5_power
# name: "MBC Z2Z5 Power"
# address: 0x001E
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "W"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z3z6_power
# name: "MBC Z3Z6 Power"
# address: 0x0022
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "W"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z1z4_shunt_voltage
# name: "MBC Z1Z4 Shunt Voltage"
# address: 0x0026
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "V"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z2z5_shunt_voltage
# name: "MBC Z2Z5 Shunt Voltage"
# address: 0x002A
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "V"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_z3z6_shunt_voltage
# name: "MBC Z3Z6 Shunt Voltage"
# address: 0x002E
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "V"
# lambda: |-
# return x / 1024.0;
#
# - platform: modbus_controller
# modbus_controller_id: modbus_alarm_client
# id: mbc_alarm_signal
# name: "MBC Alarm Signal"
# address: 0x0032
# register_type: holding
# value_type: S_WORD
# register_count: 4
# unit_of_measurement: "V"
# lambda: |-
# return x / 1024.0;
### END OF MODBUS CLIENT SENSORS ###
- platform: rtq6056
address: 0x40
id: adc_z1z4 # Zone S1 and S4 are on the same shunt, so we can only get combined current for both zones. We will use this sensor for both zones and then split the readings in the template binary_sensor
shunt_resistance: 5 ohm
max_current: 16mA
# adc time used for both, Bus Voltage and Shunt Voltage
adc_time: 140us
adc_averaging: 16
update_interval: 1s
current:
id: z1z4_current
power:
name: "Z1_Z4 Power"
id: z1z4_power
bus_voltage:
name: "Z1_Z4 Bus Voltage"
id: z1z4_bus_voltage
shunt_voltage:
name: "Z1_Z4 Shunt Voltage"
id: z1z4_shunt_voltage
- platform: template
name: "Z1_Z4 Current"
id: z1z4_current_ma
unit_of_measurement: "mA"
accuracy_decimals: 3
lambda: |-
return 1000 * id(z1z4_current).state;
- platform: rtq6056
address: 0x41
id: adc_z2z5 # Zone S2 and S5 are on the same shunt, so we can only get combined current for both zones. We will use this sensor for both zones and then split the readings in the template binary_sensor
shunt_resistance: 5.5 ohm
max_current: 16mA
# adc time used for both, Bus Voltage and Shunt Voltage
adc_time: 140us
adc_averaging: 16
update_interval: 1s
current:
id: z2z5_current
power:
name: "Z2_Z5 Power"
id: z2z5_power
bus_voltage:
name: "Z2_Z5 Bus Voltage"
id: z2z5_bus_voltage
shunt_voltage:
name: "Z2_Z5 Shunt Voltage"
id: z2z5_shunt_voltage
- platform: template
name: "Z2_Z5 Current"
id: z2z5_current_ma
unit_of_measurement: "mA"
accuracy_decimals: 3
lambda: |-
return 1000 * id(z2z5_current).state;
- platform: rtq6056
address: 0x42
id: adc_z3z6 # Zone S3 and S6 are on the same shunt, so we can only get combined current for both zones. We will use this sensor for both zones and then split the readings in the template binary_sensor
shunt_resistance: 5 ohm
max_current: 16mA
# adc time used for both, Bus Voltage and Shunt Voltage
adc_time: 140us
adc_averaging: 16
update_interval: 1s
current:
id: z3z6_current
power:
name: "Z3_Z6 Power"
id: z3z6_power
bus_voltage:
name: "Z3_Z6 Bus Voltage"
id: z3z6_bus_voltage
shunt_voltage:
name: "Z3_Z6 Shunt Voltage"
id: z3z6_shunt_voltage
- platform: template
name: "Z3_Z6 Current"
id: z3z6_current_ma
unit_of_measurement: "mA"
accuracy_decimals: 3
lambda: |-
return 1000 * id(z3z6_current).state;
- platform: adc
pin: 39
name: "Alarm Signal"
id: alarm_signal
update_interval: 2000ms
attenuation: 12db
sampling_mode: avg
filters:
- lambda:
if (x >= 3.11) {
return x * 1.60256;
} else if (x <= 0.25) {
return 0;
} else {
return x * 1.51;
}
on_value:
then:
# alarm is sounding when the signal is above 1.5V, so we can use this threshold to determine if the alarm is triggered or not. If the alarm is triggered by external trigger, we will turn on the floodlights for both backyard and frontyard, whether it is night time or not. The floodlights will be turned on for 4min 14 sec, which is the auto turn off time of the floodlights, so we don't need to worry about turning them off manually.
lambda: |-
if (id(alarm_signal).state > 1.5) {
id(lights_frontyard_relay).turn_on();
id(lights_backyard_relay).turn_on();
}
# human readable uptime sensor output to the text sensor above
- platform: uptime
name: Uptime in Days
id: uptime_sensor_days
update_interval: 10s
on_raw_value:
then:
- text_sensor.template.publish:
id: uptime_human
state: !lambda |-
int seconds = round(id(uptime_sensor_days).raw_state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
auto days_str = std::to_string(days);
auto hours_str = std::to_string(hours);
auto minutes_str = std::to_string(minutes);
auto seconds_str = std::to_string(seconds);
return (
(days ? days_str + "d " : "") +
(hours ? hours_str + "h " : "") +
(minutes ? minutes_str + "m " : "") +
(seconds_str + "s")
).c_str();
script:
- id: canbus_send_heartbeat
then:
lambda: |-
using namespace solar;
std::vector<uint8_t> x(cbf_sthome::heartbeat.begin(), cbf_sthome::heartbeat.end());
id(g_cb_cache).send_frame(id(canbus_sthome), cbf_sthome::CB_CANBUS_ID03, x);