mirror of
https://github.com/CeeWeasel/fresh-home.git
synced 2026-08-09 18:40:14 -04:00
240 lines
8.5 KiB
YAML
240 lines
8.5 KiB
YAML
substitutions:
|
|
# Calibrate Trigger Percentile
|
|
# This controls how the trigger threshold is set during calibration. During calibration, the unoccupied and occupied
|
|
# pressure values are determined. This is the percentage of the difference between those values required to trigger
|
|
# the "occupied" state.
|
|
# - 0.75 Requires 75% of the occupied pressure to trigger (DEFAULT)
|
|
# - 0.50 Set trigger exactly in the middle of unoccupied and occupied pressures
|
|
# - 0.25 More sensitive, likely to be triggered by partner
|
|
trigger_percentile: '0.75'
|
|
|
|
# Window Averaging Samples
|
|
# Add a sliding window moving average to the incoming sensor samples. This specifies the number of samples to average
|
|
# over. Each sample is 1/2 second.
|
|
# - 1 Don't perform averaging
|
|
# - 5 Average over 5 samples (2.5 seconds) (DEFAULT)
|
|
# - 10 Average over 10 samples (5 seconds)
|
|
averaging_window_samples: '5'
|
|
|
|
# Fast Sensor Delay
|
|
# This controls how long the "Fast" sensor must register "unoccupied" or "occupied" before reporting. Averaging or
|
|
# delay is encouraged to prevent frequent false negatives as you shift in bed.
|
|
# - 2s Same response as standard sensor
|
|
# - 500ms Good starting point for getting speed without too many false negatives
|
|
# - 0ms No delay (DEFAULT)
|
|
fast_delayed_on: '0ms'
|
|
fast_delayed_off: '0ms'
|
|
|
|
# Standard Sensor Delay
|
|
# This controls how long the standard sensor must register "unoccupied" or "occupied" before reporting. Averaging or
|
|
# delay is enocuraged to ensure stability.
|
|
standard_delayed_on: '0s'
|
|
standard_delayed_off: '1s'
|
|
|
|
# Slow Sensor Delay
|
|
# This controls how long the "Slow" sensor must register "unoccupied" or "occupied" before reporting. Averaging or
|
|
# delay is encouraged to ensure stability.
|
|
slow_delayed_on: '2s'
|
|
slow_delayed_off: '5s'
|
|
|
|
# Reporting Delta
|
|
# The sensor must change by this amount before an update is sent (or the reporting_interval_max has been hit)
|
|
# - 10.0 Only report very large changes
|
|
# - 1.0 Relatively sensitive with much less reporting (DEFAULT)
|
|
# - 0.1 Very sensitive, will report frequently
|
|
reporting_delta: '1.0'
|
|
|
|
# Reporting Interval (Max)
|
|
# The max amount of time between sensor reports (even if the value hasn't changed)
|
|
reporting_interval_max: '180s'
|
|
|
|
# Linear Calibration Points
|
|
# Change the linear calibration points for the FSR sensor. These values correspond with the raw pulses per minute from
|
|
# the pulse_counter. Only mess with this if you know what you're doing. In standard mode (Full Range = False), the
|
|
# sensor is linearly calibrated between calibrate_0 (0%) and calibreate_100 (100%). When Full Range = True,
|
|
# calibrate_0 is set to 0.
|
|
calibrate_100: '408000'
|
|
calibrate_0: '276000'
|
|
|
|
binary_sensor:
|
|
- platform: template
|
|
name: Bed Occupied ${sensor_name} (Fast)
|
|
id: bed_occupied_${sensor_id}_fast
|
|
device_class: occupancy
|
|
icon: mdi:speedometer
|
|
disabled_by_default: true
|
|
filters:
|
|
- delayed_on: ${fast_delayed_on}
|
|
- delayed_off: ${fast_delayed_off}
|
|
lambda: return id(bed_sensor_${sensor_id}).state > id(val_trigger_${sensor_id}).state;
|
|
|
|
- platform: template
|
|
name: Bed Occupied ${sensor_name} (Normal)
|
|
id: bed_occupied_${sensor_id}_normal
|
|
device_class: occupancy
|
|
icon: mdi:speedometer-medium
|
|
disabled_by_default: true
|
|
filters:
|
|
- delayed_on: ${standard_delayed_on}
|
|
- delayed_off: ${standard_delayed_off}
|
|
lambda: return id(bed_sensor_${sensor_id}).state > id(val_trigger_${sensor_id}).state;
|
|
|
|
- platform: template
|
|
id: bed_occupied_${sensor_id}_slow
|
|
name: Bed Occupied ${sensor_name} (Slow)
|
|
device_class: occupancy
|
|
icon: mdi:speedometer-slow
|
|
disabled_by_default: true
|
|
filters:
|
|
- delayed_on: ${slow_delayed_on}
|
|
- delayed_off: ${slow_delayed_off}
|
|
lambda: return id(bed_sensor_${sensor_id}).state > id(val_trigger_${sensor_id}).state;
|
|
|
|
- platform: template
|
|
name: Bed Occupied ${sensor_name}
|
|
id: bed_occupied_${sensor_id}
|
|
device_class: occupancy
|
|
icon: mdi:bed
|
|
lambda: |- # Sensor response is user tunable via "Response Speed"
|
|
if (id(response_speed).state == "Fast") {
|
|
return id(bed_occupied_${sensor_id}_fast).state;
|
|
} else if (id(response_speed).state == "Slow") {
|
|
return id(bed_occupied_${sensor_id}_slow).state;
|
|
} else {
|
|
return id(bed_occupied_${sensor_id}_normal).state;
|
|
}
|
|
|
|
sensor:
|
|
- platform: pulse_counter
|
|
pin: ${sensor_gpio}
|
|
name: ${sensor_name} Pressure
|
|
id: bed_sensor_${sensor_id}
|
|
update_interval: 0.5s
|
|
unit_of_measurement: '%'
|
|
icon: mdi:gauge
|
|
filters:
|
|
- lambda: |- # scale pulses/minute to 0%->100%
|
|
float cal_0 = id(full_range).state ? 0 : ${calibrate_0};
|
|
|
|
float val = (x - cal_0) * 100;
|
|
float range = ${calibrate_100} - cal_0;
|
|
|
|
return val/range;
|
|
- clamp:
|
|
min_value: 0
|
|
- sliding_window_moving_average:
|
|
window_size: ${averaging_window_samples}
|
|
send_every: 1
|
|
- or:
|
|
- delta: ${reporting_delta} # only send if sensor changes by `reporting_delta` (eliminate sensor noise)
|
|
- throttle: ${reporting_interval_max} # but still update every `reporting_interval_max`
|
|
- platform: copy
|
|
source_id: bed_sensor_${sensor_id}
|
|
name: Calibrated ${sensor_name} Pressure
|
|
id: bed_sensor_${sensor_id}_calibrated
|
|
icon: mdi:scale-balance
|
|
disabled_by_default: true
|
|
filters:
|
|
- lambda: |- # scale between val_unoccupied and val_occupied
|
|
float cal_0 = id(val_unoccupied_${sensor_id}).state;
|
|
float cal_100 = id(val_occupied_${sensor_id}).state;
|
|
|
|
float val = (x - cal_0) * 100;
|
|
float range = cal_100 - cal_0;
|
|
|
|
return val/range;
|
|
- clamp:
|
|
max_value: 100
|
|
min_value: 0
|
|
|
|
number:
|
|
- platform: template
|
|
name: ${sensor_name} Unoccupied Pressure
|
|
id: val_unoccupied_${sensor_id}
|
|
icon: mdi:gauge-empty
|
|
unit_of_measurement: '%'
|
|
entity_category: diagnostic
|
|
optimistic: true
|
|
restore_value: true
|
|
initial_value: 0
|
|
min_value: 0
|
|
max_value: 120
|
|
step: 1.0
|
|
mode: box
|
|
on_value:
|
|
then:
|
|
- lambda: |- # Update trigger
|
|
id(update_trigger_${sensor_id})->execute();
|
|
- platform: template
|
|
name: ${sensor_name} Occupied Pressure
|
|
id: val_occupied_${sensor_id}
|
|
icon: mdi:gauge-full
|
|
unit_of_measurement: '%'
|
|
entity_category: diagnostic
|
|
optimistic: true
|
|
restore_value: true
|
|
initial_value: 100
|
|
min_value: 0
|
|
max_value: 120
|
|
step: 1.0
|
|
mode: box
|
|
on_value:
|
|
then:
|
|
- lambda: |- # Update trigger
|
|
id(update_trigger_${sensor_id})->execute();
|
|
- platform: template
|
|
name: ${sensor_name} Trigger Pressure
|
|
id: val_trigger_${sensor_id}
|
|
optimistic: true
|
|
restore_value: true
|
|
initial_value: 50
|
|
min_value: 0
|
|
max_value: 120
|
|
step: 1.0
|
|
mode: box
|
|
icon: mdi:gauge
|
|
unit_of_measurement: '%'
|
|
entity_category: config
|
|
|
|
button:
|
|
- platform: template
|
|
name: Calibrate ${sensor_name} Unoccupied
|
|
id: calibration_${sensor_id}_set_unoccupied
|
|
icon: mdi:bed-empty
|
|
entity_category: config
|
|
on_press:
|
|
then:
|
|
- number.set:
|
|
id: val_unoccupied_${sensor_id}
|
|
# round to 2 decimal places
|
|
value: !lambda return round(id(bed_sensor_${sensor_id}).state * 100)/100.0;
|
|
- platform: template
|
|
name: Calibrate ${sensor_name} Occupied
|
|
id: calibration_${sensor_id}_set_occupied
|
|
icon: mdi:bed
|
|
entity_category: config
|
|
on_press:
|
|
then:
|
|
- number.set:
|
|
id: val_occupied_${sensor_id}
|
|
# round to 2 decimal places
|
|
value: !lambda return round(id(bed_sensor_${sensor_id}).state * 100)/100.0;
|
|
|
|
script:
|
|
- id: update_trigger_${sensor_id}
|
|
mode: queued
|
|
then:
|
|
- lambda: |- # Set trigger to x% of difference between min/max
|
|
float unoccupied_pressure = id(val_unoccupied_${sensor_id}).state;
|
|
float occupied_pressure = id(val_occupied_${sensor_id}).state;
|
|
|
|
// calculate new trigger value
|
|
float trigger_pressure = unoccupied_pressure + ((occupied_pressure - unoccupied_pressure) * float(${trigger_percentile}));
|
|
|
|
// round to 2 decimal places
|
|
trigger_pressure = round(trigger_pressure * 100)/100.0;
|
|
|
|
// set value
|
|
auto call = id(val_trigger_${sensor_id}).make_call();
|
|
call.set_value(trigger_pressure);
|
|
call.perform(); |