1062 lines
34 KiB
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); |