mirror of
https://github.com/CeeWeasel/fresh-home.git
synced 2026-08-09 18:40:14 -04:00
Cleanup and prepping for bed presence
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
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();
|
||||
Reference in New Issue
Block a user