diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4dc8b7..a7bb5d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,15 @@
All notable changes to the HAPSIC Controller are documented here.
Versions follow [Semantic Versioning](https://semver.org/).
+## [Unreleased]
+
+### Fixed
+- **Mission Control dashboard load failure**: Wrapped `dashboards/mission-control.yaml` as a full Lovelace dashboard config with `views:` so it can be pasted directly into Home Assistant's raw configuration editor as documented.
+- **Panel view card count**: Moved the History graph into the main vertical stack so the panel view has exactly one card, matching current Home Assistant panel view requirements.
+- **Boiler curve rendering**: Added a safe JSON fallback for `input_text.hapsic_boiler_curve` so an empty or invalid helper value cannot break the markdown card.
+- **Structure Velocity chart**: Kept the dashboard on the intended stable `sensor.hapsic_structure_velocity` MQTT contract; the missing entity must be provided by the Home Assistant `hapsic_sensors.yaml` package.
+- **Open-source dashboard privacy**: Removed site-specific text and external deployment entities from `dashboards/mission-control.yaml`; the public dashboard now uses only the generic HAPSIC entity contract.
+
## [v2.6.1] — 2026-05-02
### Fixed
diff --git a/README.md b/README.md
index 0e46022..235339c 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ HAPSIC solves this with math.
## Dashboard
-HAPSIC ships with a **Mission Control** dashboard for monitoring the physics engine, duct safety, and moisture balance in real time.
+HAPSIC ships with a generic **Mission Control** dashboard for monitoring the physics engine, duct safety, and moisture balance in real time. It uses only HAPSIC contract entities and intentionally excludes site-specific sensors, locations, rooms, vendors, and personal Home Assistant helpers.
**Prerequisites** (install via HACS → Frontend):
- [Mushroom Cards](https://github.com/piitaya/lovelace-mushroom)
@@ -39,6 +39,15 @@ HAPSIC ships with a **Mission Control** dashboard for monitoring the physics eng
3. Paste the contents of [`dashboards/mission-control.yaml`](dashboards/mission-control.yaml)
4. Save
+Personal production dashboards should live in your own Home Assistant config repository. Keep local-only entities, room names, vendor hardware, and location-specific context out of this open-source dashboard.
+
+**Dashboard entity contract:**
+- State and faults: `sensor.hapsic_fsm_state`, `sensor.hapsic_fault_reason`, `sensor.hapsic_boil_status`
+- User inputs/storage: `input_number.target_dew_point`, `input_number.humidifier_max_capacity`, `input_number.hapsic_chi_ema`, `input_text.hapsic_boiler_curve`
+- Physics and control: `sensor.hapsic_steam_voltage`, `sensor.hapsic_steam_mass`, `sensor.hapsic_ventilation_loss`, `sensor.hapsic_net_flux`, `sensor.hapsic_structure_velocity`, `sensor.hapsic_room_deficit`, `sensor.hapsic_target_duct_dp`, `sensor.hapsic_max_achievable_dp`, `sensor.hapsic_is_target_infeasible`
+- Psychrometrics and duct safety: `sensor.hapsic_room_dew_point`, `sensor.hapsic_room_average_temp`, `sensor.hapsic_room_average_rh`, `sensor.hapsic_pre_steam_dp`, `sensor.hapsic_duct_dp`, `sensor.hapsic_cleansed_supply_temp`, `sensor.hapsic_cleansed_supply_rh`, `sensor.hapsic_cleansed_post_steam_temp`, `sensor.hapsic_cleansed_post_steam_rh`, `sensor.hapsic_supply_flow`, `sensor.hapsic_cleansed_airflow`
+- Health: `sensor.hapsic_chi_instant`, `sensor.hapsic_health_measured_steam`, `sensor.hapsic_health_production_efficiency`
+
## Notification Blueprints
HAPSIC includes three Blueprint automations for proactive system monitoring. Each can be imported with one click:
diff --git a/dashboards/mission-control.yaml b/dashboards/mission-control.yaml
index 2dd524c..0c4e9a7 100644
--- a/dashboards/mission-control.yaml
+++ b/dashboards/mission-control.yaml
@@ -1,504 +1,508 @@
-type: panel
-path: humidifier2
-title: Humidifier2
-cards:
- - type: vertical-stack
+title: HAPSIC Mission Control
+views:
+ - type: panel
+ path: humidifier2
+ title: Humidifier2
cards:
- - type: custom:mushroom-title-card
- title: HAPSIC Mission Control
- subtitle: >-
- Amarillo, TX • {{ states('sensor.hapsic_fsm_state') | upper }} • {{
- states('sensor.gw1200b_absolute_pressure') }} kPa
- - type: conditional
- conditions:
- - condition: state
- entity: sensor.hapsic_fsm_state
- state: FAULT
- card:
- type: vertical-stack
- cards:
- - type: tile
- entity: sensor.hapsic_fault_reason
- name: FAULT ACTIVE
- icon: mdi:alert-octagon
- color: red
- - type: markdown
- content: |
- ### 🛑 Logic Lockout Active
- The controller has entered safety shutdown.
- **Reason:** {{ states('sensor.hapsic_fault_reason') }}
- - type: conditional
- conditions:
- - condition: state
- entity: sensor.hapsic_fsm_state
- state: FAULT
- - condition: state
- entity: sensor.hapsic_fault_reason
- state: Economizer Bypass Active
- card:
- type: tile
- entity: sensor.zehnder_comfoair_q_a4cb9c_bypass_state
- name: FREE COOLING ACTIVE (YIELDING)
- icon: mdi:snowflake-thermometer
- color: cyan
- - type: horizontal-stack
+ - type: vertical-stack
cards:
- - type: tile
- entity: input_number.target_dew_point
- name: Target Dew Point
- icon: mdi:thermometer-water
- color: deep-purple
- - type: tile
- entity: sensor.hapsic_steam_voltage
- name: Output V
- icon: mdi:flash-auto
- color: >-
- {% if states('sensor.hapsic_steam_voltage')|float > 0 %} orange {%
- else %} grey {% endif %}
- - type: tile
- entity: input_number.humidifier_max_capacity
- name: Capacity
- icon: mdi:kettle-steam
- color: cyan
- - type: grid
- columns: 2
- square: false
- cards:
- - type: gauge
- entity: sensor.hapsic_steam_mass
- name: Injection Rate
- unit: lbs/hr
- min: 0
- max: 6
- needle: true
- severity:
- green: 0
- yellow: 4
- red: 5.5
- - type: vertical-stack
+ - type: custom:mushroom-title-card
+ title: HAPSIC Mission Control
+ subtitle: >-
+ {{ states('sensor.hapsic_fsm_state') | upper }} • Target {{
+ states('input_number.target_dew_point') }} °F DP • {{
+ states('sensor.hapsic_fault_reason') }}
+ - type: conditional
+ conditions:
+ - condition: state
+ entity: sensor.hapsic_fsm_state
+ state: FAULT
+ card:
+ type: vertical-stack
+ cards:
+ - type: tile
+ entity: sensor.hapsic_fault_reason
+ name: FAULT ACTIVE
+ icon: mdi:alert-octagon
+ color: red
+ - type: markdown
+ content: |
+ ### 🛑 Logic Lockout Active
+ The controller has entered safety shutdown.
+ **Reason:** {{ states('sensor.hapsic_fault_reason') }}
+ - type: conditional
+ conditions:
+ - condition: state
+ entity: sensor.hapsic_fsm_state
+ state: FAULT
+ - condition: state
+ entity: sensor.hapsic_fault_reason
+ state: Economizer Bypass Active
+ card:
+ type: markdown
+ content: >
+ ### Economizer Bypass Active
+
+ HAPSIC is yielding because the controller reported an economizer
+ bypass fault state.
+ - type: horizontal-stack
+ cards:
+ - type: tile
+ entity: input_number.target_dew_point
+ name: Target Dew Point
+ icon: mdi:thermometer-water
+ color: deep-purple
+ - type: tile
+ entity: sensor.hapsic_steam_voltage
+ name: Output V
+ icon: mdi:flash-auto
+ color: >-
+ {% if states('sensor.hapsic_steam_voltage')|float(0) > 0 %} orange {%
+ else %} grey {% endif %}
+ - type: tile
+ entity: input_number.humidifier_max_capacity
+ name: Capacity
+ icon: mdi:kettle-steam
+ color: cyan
+ - type: grid
+ columns: 2
+ square: false
cards:
- type: gauge
- entity: sensor.hapsic_chi_instant
- name: Canister Health
- unit: "%"
+ entity: sensor.hapsic_steam_mass
+ name: Injection Rate
+ unit: lbs/hr
min: 0
- max: 120
+ max: 6
needle: true
severity:
- red: 50
- yellow: 70
- green: 90
- - type: markdown
- content: >
-
Boiler State: {{
- states('sensor.hapsic_boil_status') }}
- - type: heading
- heading: Boiler Health & Characterization
- heading_style: title
- - type: grid
- columns: 4
- square: false
- cards:
- - type: tile
- entity: sensor.hapsic_steam_mass
- name: Commanded Steam
- icon: mdi:gauge-empty
- color: >-
- {% set val = states('sensor.hapsic_steam_mass')|float(0) %}
- {% if val > 0 %} blue {% else %} grey {% endif %}
- state_content: state
- - type: tile
- entity: sensor.hapsic_health_measured_steam
- name: Actual Steam
- icon: mdi:gauge-full
- color: >-
- {% set val = states('sensor.hapsic_health_measured_steam')|float(0) %}
- {% if val > 0 %} green {% else %} grey {% endif %}
- state_content: state
- - type: tile
- entity: sensor.hapsic_health_production_efficiency
- name: Efficiency
- icon: mdi:percent-circle
- color: >-
- {% set val = states('sensor.hapsic_health_production_efficiency')|float(0) %}
- {% if val > 90 %} green {% elif val > 60 %} orange
- {% elif val > 0 %} red {% else %} grey {% endif %}
- state_content: state
- - type: tile
- entity: sensor.hapsic_boil_status
- name: Boiler State
- icon: >-
- {% if states('sensor.hapsic_boil_status') == 'BOILING' %}
- mdi:fire {% else %} mdi:snowflake {% endif %}
- color: >-
- {% if states('sensor.hapsic_boil_status') == 'BOILING' %}
- red {% else %} grey {% endif %}
- - type: custom:apexcharts-card
- header:
- show: true
- title: "Steam Output \u2014 Commanded vs Actual (lbs/hr)"
- show_states: true
- colorize_states: true
- graph_span: 12h
- series:
- - entity: sensor.hapsic_steam_mass
- name: Commanded
- stroke_width: 2
- color: "#42a5f5"
- curve: stepline
- show:
- in_header: true
- - entity: sensor.hapsic_health_measured_steam
- name: Actual
- stroke_width: 2
- color: "#66bb6a"
- curve: smooth
- show:
- in_header: true
- - entity: input_number.humidifier_max_capacity
- name: Effective Max
- stroke_width: 1
- color: "#ef5350"
- opacity: 0.4
- curve: stepline
- show:
- in_header: false
- yaxis:
- - min: 0
- decimals: 2
- - type: custom:apexcharts-card
- header:
- show: true
- title: Production Efficiency (%)
- show_states: true
- colorize_states: true
- graph_span: 12h
- experimental:
- color_threshold: true
- series:
- - entity: sensor.hapsic_health_production_efficiency
- name: Efficiency
- stroke_width: 2
- curve: smooth
- show:
- in_header: true
- color_threshold:
- - value: 0
- color: "#f44336"
- - value: 60
- color: "#ff9800"
- - value: 90
- color: "#4caf50"
- yaxis:
- - min: 0
- max: 120
- decimals: 0
- - type: markdown
- title: Boiler Curve (Learned)
- content: >
- {% set curve = states('input_text.hapsic_boiler_curve') %}
+ green: 0
+ yellow: 4
+ red: 5.5
+ - type: vertical-stack
+ cards:
+ - type: gauge
+ entity: sensor.hapsic_chi_instant
+ name: Canister Health
+ unit: "%"
+ min: 0
+ max: 120
+ needle: true
+ severity:
+ red: 50
+ yellow: 70
+ green: 90
+ - type: markdown
+ content: >
+ Boiler State: {{
+ states('sensor.hapsic_boil_status') }}
+ - type: heading
+ heading: Boiler Health & Characterization
+ heading_style: title
+ - type: grid
+ columns: 4
+ square: false
+ cards:
+ - type: tile
+ entity: sensor.hapsic_steam_mass
+ name: Commanded Steam
+ icon: mdi:gauge-empty
+ color: >-
+ {% set val = states('sensor.hapsic_steam_mass')|float(0) %}
+ {% if val > 0 %} blue {% else %} grey {% endif %}
+ state_content: state
+ - type: tile
+ entity: sensor.hapsic_health_measured_steam
+ name: Actual Steam
+ icon: mdi:gauge-full
+ color: >-
+ {% set val = states('sensor.hapsic_health_measured_steam')|float(0) %}
+ {% if val > 0 %} green {% else %} grey {% endif %}
+ state_content: state
+ - type: tile
+ entity: sensor.hapsic_health_production_efficiency
+ name: Efficiency
+ icon: mdi:percent-circle
+ color: >-
+ {% set val = states('sensor.hapsic_health_production_efficiency')|float(0) %}
+ {% if val > 90 %} green {% elif val > 60 %} orange
+ {% elif val > 0 %} red {% else %} grey {% endif %}
+ state_content: state
+ - type: tile
+ entity: sensor.hapsic_boil_status
+ name: Boiler State
+ icon: >-
+ {% if states('sensor.hapsic_boil_status') == 'BOILING' %}
+ mdi:fire {% else %} mdi:snowflake {% endif %}
+ color: >-
+ {% if states('sensor.hapsic_boil_status') == 'BOILING' %}
+ red {% else %} grey {% endif %}
+ - type: custom:apexcharts-card
+ header:
+ show: true
+ title: "Steam Output \u2014 Commanded vs Actual (lbs/hr)"
+ show_states: true
+ colorize_states: true
+ graph_span: 12h
+ series:
+ - entity: sensor.hapsic_steam_mass
+ name: Commanded
+ stroke_width: 2
+ color: "#42a5f5"
+ curve: stepline
+ show:
+ in_header: true
+ - entity: sensor.hapsic_health_measured_steam
+ name: Actual
+ stroke_width: 2
+ color: "#66bb6a"
+ curve: smooth
+ show:
+ in_header: true
+ - entity: input_number.humidifier_max_capacity
+ name: Effective Max
+ stroke_width: 1
+ color: "#ef5350"
+ opacity: 0.4
+ curve: stepline
+ show:
+ in_header: false
+ yaxis:
+ - min: 0
+ decimals: 2
+ - type: custom:apexcharts-card
+ header:
+ show: true
+ title: Production Efficiency (%)
+ show_states: true
+ colorize_states: true
+ graph_span: 12h
+ experimental:
+ color_threshold: true
+ series:
+ - entity: sensor.hapsic_health_production_efficiency
+ name: Efficiency
+ stroke_width: 2
+ curve: smooth
+ show:
+ in_header: true
+ color_threshold:
+ - value: 0
+ color: "#f44336"
+ - value: 60
+ color: "#ff9800"
+ - value: 90
+ color: "#4caf50"
+ yaxis:
+ - min: 0
+ max: 120
+ decimals: 0
+ - type: markdown
+ title: Boiler Curve (Learned)
+ content: >
+ {% set curve = states('input_text.hapsic_boiler_curve') %}
- {% set bins = curve | from_json if curve not in ['unknown','unavailable'] else [0,0,0,0] %}
+ {% set bins = curve | from_json([0,0,0,0]) %}
- | Voltage Band | 0-2.5V | 2.5-5V | 5-7.5V | 7.5-10V |
+ | Voltage Band | 0-2.5V | 2.5-5V | 5-7.5V | 7.5-10V |
- | :---: | :---: | :---: | :---: | :---: |
+ | :---: | :---: | :---: | :---: | :---: |
- | **Capacity** | {{ '%.2f'|format(bins[0]) }} | {{ '%.2f'|format(bins[1]) }} | {{ '%.2f'|format(bins[2]) }} | {{ '%.2f'|format(bins[3]) }} |
+ | **Capacity** | {{ '%.2f'|format(bins[0]) }} | {{ '%.2f'|format(bins[1]) }} | {{ '%.2f'|format(bins[2]) }} | {{ '%.2f'|format(bins[3]) }} |
- | **Bar** | {{ '█' * ((bins[0]*10)|int) }} | {{ '█' * ((bins[1]*10)|int) }} | {{ '█' * ((bins[2]*10)|int) }} | {{ '█' * ((bins[3]*10)|int) }} |
- - type: custom:apexcharts-card
- header:
- show: true
- title: "Canister Health (\u03C7 Ratio)"
- show_states: true
- colorize_states: true
- graph_span: 12h
- experimental:
- color_threshold: true
- series:
- - entity: sensor.hapsic_chi_instant
- name: "\u03C7 Instant"
- stroke_width: 1
- opacity: 0.6
- show:
- in_header: true
- color_threshold:
- - value: 0
- color: "#f44336"
- - value: 70
- color: "#ff9800"
- - value: 90
- color: "#4caf50"
- - entity: input_number.hapsic_chi_ema
- name: "\u03C7 EMA (48h)"
- stroke_width: 2
- color: "#9b59b6"
- curve: smooth
- show:
- in_header: true
- yaxis:
- - min: 0
- max: 120
- decimals: 0
- - type: heading
- heading: Physics Engine (Decoupled)
- heading_style: title
- - type: entities
- title: State Vector
- show_header_toggle: false
- entities:
- - entity: sensor.hapsic_room_dew_point
- name: Actual Dew Point (Goal Metric)
- icon: mdi:water-thermometer
- - entity: sensor.hapsic_room_average_temp
- name: Actual Temp
- - entity: sensor.hapsic_room_average_rh
- name: Actual RH
- - entity: sensor.hapsic_cleansed_supply_temp
- name: Supply Temp (T_sup)
- - entity: sensor.hapsic_cleansed_supply_rh
- name: Supply RH (Baseline)
- - entity: sensor.hapsic_supply_flow
- name: Airflow Mass (m3/h)
- icon: mdi:fan
- - type: heading
- heading: Duct Safety Monitor
- heading_style: title
- - type: grid
- columns: 2
- square: false
- cards:
+ | **Bar** | {{ '█' * ((bins[0]*10)|int) }} | {{ '█' * ((bins[1]*10)|int) }} | {{ '█' * ((bins[2]*10)|int) }} | {{ '█' * ((bins[3]*10)|int) }} |
+ - type: custom:apexcharts-card
+ header:
+ show: true
+ title: "Canister Health (\u03C7 Ratio)"
+ show_states: true
+ colorize_states: true
+ graph_span: 12h
+ experimental:
+ color_threshold: true
+ series:
+ - entity: sensor.hapsic_chi_instant
+ name: "\u03C7 Instant"
+ stroke_width: 1
+ opacity: 0.6
+ show:
+ in_header: true
+ color_threshold:
+ - value: 0
+ color: "#f44336"
+ - value: 70
+ color: "#ff9800"
+ - value: 90
+ color: "#4caf50"
+ - entity: input_number.hapsic_chi_ema
+ name: "\u03C7 EMA (48h)"
+ stroke_width: 2
+ color: "#9b59b6"
+ curve: smooth
+ show:
+ in_header: true
+ yaxis:
+ - min: 0
+ max: 120
+ decimals: 0
+ - type: heading
+ heading: Physics Engine (Decoupled)
+ heading_style: title
- type: entities
- title: Pre-Steam (Supply)
+ title: State Vector
show_header_toggle: false
entities:
+ - entity: sensor.hapsic_room_dew_point
+ name: Actual Dew Point (Goal Metric)
+ icon: mdi:water-thermometer
+ - entity: sensor.hapsic_room_average_temp
+ name: Actual Temp
+ - entity: sensor.hapsic_room_average_rh
+ name: Actual RH
- entity: sensor.hapsic_cleansed_supply_temp
- name: Temp
- icon: mdi:thermometer-chevron-down
+ name: Supply Temp (T_sup)
- entity: sensor.hapsic_cleansed_supply_rh
- name: Humidity
- icon: mdi:water-minus
- - type: entities
- title: Post-Steam (Duct)
- show_header_toggle: false
- entities:
- - entity: sensor.hapsic_duct_temp
- name: Temp
- icon: mdi:thermometer-chevron-up
- - entity: sensor.hapsic_duct_rh
- name: Humidity
- icon: mdi:water-plus
- card_mod:
- style: |
- :host {
- --paper-item-icon-color:
- {% if states(config.entity)|float(0) > 85 %} red
- {% elif states(config.entity)|float(0) > 80 %} orange
- {% else %} green {% endif %};
- }
- - type: gauge
- entity: sensor.hapsic_duct_rh
- name: Duct Saturation Safety
- unit: "%"
- min: 0
- max: 100
- needle: true
- severity:
- green: 0
- yellow: 80
- red: 90
- - type: heading
- heading: Moisture Balance Engine
- heading_style: title
- - type: custom:apexcharts-card
- header:
- show: true
- title: 1. ENGINE EFFORT
- show_states: true
- colorize_states: true
- experimental:
- color_threshold: true
- series:
- - entity: sensor.hapsic_steam_voltage
- name: Steam Output
- stroke_width: 2
- show:
- in_header: true
- color_threshold:
- - value: 0
- color: "#4caf50"
- - value: 9.5
- color: "#f44336"
- yaxis:
- - min: 0
- max: 10
- decimals: 1
- graph_span: 2h
- - type: custom:apexcharts-card
- header:
- show: true
- title: 2. WORK DONE (Lift)
- show_states: true
- colorize_states: true
- graph_span: 2h
- series:
- - entity: sensor.hapsic_target_duct_dp
- name: PID Request
- color: "#9b59b6"
- stroke_width: 2
- curve: stepline
- - entity: sensor.hapsic_duct_dp
- name: Actual Discharge
- color: "#ff9800"
- type: area
- opacity: 0.5
- stroke_width: 2
- - entity: sensor.hapsic_pre_steam_dp
- name: Baseline Intake
- color: "#2196f3"
- stroke_width: 2
- now:
- show: true
- label: Current
- - type: custom:apexcharts-card
- header:
- show: true
- title: 3. STRUCTURE VELOCITY
- show_states: true
- colorize_states: true
- graph_span: 2h
- experimental:
- color_threshold: true
- series:
- - entity: sensor.hapsic_structure_velocity
- name: Climb Rate
- type: area
- opacity: 0.3
- stroke_width: 2
- show:
- in_header: true
- color_threshold:
- - value: -10
- color: "#9e9e9e"
- - value: 0
- color: "#9c27b0"
- yaxis:
- - min: -1
- max: 1
- decimals: 2
- - type: markdown
- title: Mass Balance Tracker
- content: >
- | Metric | Value | Impact |
+ name: Supply RH (Baseline)
+ - entity: sensor.hapsic_supply_flow
+ name: Airflow Mass (m3/h)
+ icon: mdi:fan
+ - type: heading
+ heading: Duct Safety Monitor
+ heading_style: title
+ - type: grid
+ columns: 2
+ square: false
+ cards:
+ - type: entities
+ title: Pre-Steam (Supply)
+ show_header_toggle: false
+ entities:
+ - entity: sensor.hapsic_cleansed_supply_temp
+ name: Temp
+ icon: mdi:thermometer-chevron-down
+ - entity: sensor.hapsic_cleansed_supply_rh
+ name: Humidity
+ icon: mdi:water-minus
+ - type: entities
+ title: Post-Steam (Duct)
+ show_header_toggle: false
+ entities:
+ - entity: sensor.hapsic_cleansed_post_steam_temp
+ name: Temp
+ icon: mdi:thermometer-chevron-up
+ - entity: sensor.hapsic_cleansed_post_steam_rh
+ name: Humidity
+ icon: mdi:water-plus
+ card_mod:
+ style: |
+ :host {
+ --paper-item-icon-color:
+ {% if states(config.entity)|float(0) > 85 %} red
+ {% elif states(config.entity)|float(0) > 80 %} orange
+ {% else %} green {% endif %};
+ }
+ - type: gauge
+ entity: sensor.hapsic_cleansed_post_steam_rh
+ name: Duct Saturation Safety
+ unit: "%"
+ min: 0
+ max: 100
+ needle: true
+ severity:
+ green: 0
+ yellow: 80
+ red: 90
+ - type: heading
+ heading: Moisture Balance Engine
+ heading_style: title
+ - type: custom:apexcharts-card
+ header:
+ show: true
+ title: 1. ENGINE EFFORT
+ show_states: true
+ colorize_states: true
+ experimental:
+ color_threshold: true
+ series:
+ - entity: sensor.hapsic_steam_voltage
+ name: Steam Output
+ stroke_width: 2
+ show:
+ in_header: true
+ color_threshold:
+ - value: 0
+ color: "#4caf50"
+ - value: 9.5
+ color: "#f44336"
+ yaxis:
+ - min: 0
+ max: 10
+ decimals: 1
+ graph_span: 2h
+ - type: custom:apexcharts-card
+ header:
+ show: true
+ title: 2. WORK DONE (Lift)
+ show_states: true
+ colorize_states: true
+ graph_span: 2h
+ series:
+ - entity: sensor.hapsic_target_duct_dp
+ name: PID Request
+ color: "#9b59b6"
+ stroke_width: 2
+ curve: stepline
+ - entity: sensor.hapsic_duct_dp
+ name: Actual Discharge
+ color: "#ff9800"
+ type: area
+ opacity: 0.5
+ stroke_width: 2
+ - entity: sensor.hapsic_pre_steam_dp
+ name: Baseline Intake
+ color: "#2196f3"
+ stroke_width: 2
+ now:
+ show: true
+ label: Current
+ - type: custom:apexcharts-card
+ header:
+ show: true
+ title: 3. STRUCTURE VELOCITY
+ show_states: true
+ colorize_states: true
+ graph_span: 2h
+ experimental:
+ color_threshold: true
+ series:
+ - entity: sensor.hapsic_structure_velocity
+ name: Climb Rate
+ type: area
+ opacity: 0.3
+ stroke_width: 2
+ show:
+ in_header: true
+ color_threshold:
+ - value: -10
+ color: "#9e9e9e"
+ - value: 0
+ color: "#9c27b0"
+ yaxis:
+ - min: -1
+ max: 1
+ decimals: 2
+ - type: markdown
+ title: Mass Balance Tracker
+ content: >
+ | Metric | Value | Impact |
- | :--- | :--- | :--- |
+ | :--- | :--- | :--- |
- | **Injection** | `{{ states('sensor.hapsic_steam_mass') }} lbs/hr` |
- Wetting ⬆️ |
+ | **Injection** | `{{ states('sensor.hapsic_steam_mass') }} lbs/hr` |
+ Wetting ⬆️ |
- | **Ventilation** | `{{ states('sensor.hapsic_ventilation_loss') }}
- lbs/hr` | Drying ⬇️ |
+ | **Ventilation** | `{{ states('sensor.hapsic_ventilation_loss') }}
+ lbs/hr` | Drying ⬇️ |
- | **NET FLUX** | **{{ states('sensor.hapsic_net_flux') }} lbs/hr** |
- **{{ 'CHARGING' if states('sensor.hapsic_net_flux')|float(0) > 0 else
- 'DRAINING' }}** |
- - type: custom:power-flow-card-plus
- title: HAPSIC Physics Engine
- entities:
- solar:
- entity: sensor.hapsic_steam_mass
- name: Steam Input
- color: "#3498db"
- unit_of_measurement: lbs/hr
- battery:
- name: Net Flux
- entity:
- consumption: sensor.hapsic_net_flux
- production: sensor.hapsic_net_flux
- color_icon: true
- color_circle: true
- unit_of_measurement: lbs/hr
- label_consumption: Draining
- label_production: Charging
- home:
- name: Vent Loss
- entity: sensor.hapsic_ventilation_loss
- color_icon: true
- unit_of_measurement: lbs/hr
- dashboard_link: /energy
- display_zero_lines: true
- use_new_flow_rate_model: true
- min_flow_rate: 0.1
- decimals: 2
- watt_threshold: 10000
- - type: heading
- heading: Control Strategy (Loop A)
- heading_style: title
- - type: grid
- columns: 3
- square: false
- cards:
- - type: tile
- entity: sensor.hapsic_room_deficit
- name: Deficit
- icon: mdi:arrow-collapse-down
- color: >-
- {% set val = states('sensor.hapsic_room_deficit')|float(0) %} {%
- if val < -0.5 %} blue {% elif val < 0.5 %} green {% elif val <
- 2.0 %} orange {% else %} red {% endif %}
- state_content: state
- - type: tile
- entity: sensor.hapsic_target_duct_dp
- name: Duct Request
- icon: mdi:target
- color: deep-purple
- state_content: state
- - type: tile
- entity: sensor.hapsic_max_achievable_dp
- name: Feasibility Limit
- icon: mdi:speedometer
- color: >-
- {% if states('sensor.hapsic_is_target_infeasible') == 'True' %}
- red {% else %} green {% endif %}
- state_content: state
- - type: custom:apexcharts-card
- header:
- show: true
- title: Target vs. Actual Dew Point
- show_states: true
- colorize_states: true
- graph_span: 6h
- series:
- - entity: sensor.hapsic_room_dew_point
- name: Actual Dew Point
- color: "#2196f3"
- stroke_width: 2
- curve: smooth
- - entity: input_number.target_dew_point
- name: Target Dew Point
- color: "#9b59b6"
- stroke_width: 2
- curve: stepline
- - entity: sensor.hapsic_max_achievable_dp
- name: Physical Limit
- color: "#f44336"
- stroke_width: 2
- type: area
- opacity: 0.1
- - title: History
- type: history-graph
- hours_to_show: 12
- entities:
- - sensor.hapsic_pre_steam_dp
- - sensor.hapsic_cleansed_airflow
- - input_number.hapsic_chi_ema
- - sensor.hapsic_duct_dp
- - sensor.hapsic_target_duct_dp
- - sensor.hapsic_max_achievable_dp
- - sensor.hapsic_chi_instant
- - sensor.hapsic_room_dew_point
- - input_number.target_dew_point
- - sensor.hapsic_steam_voltage
+ | **NET FLUX** | **{{ states('sensor.hapsic_net_flux') }} lbs/hr** |
+ **{{ 'CHARGING' if states('sensor.hapsic_net_flux')|float(0) > 0 else
+ 'DRAINING' }}** |
+ - type: custom:power-flow-card-plus
+ title: HAPSIC Physics Engine
+ entities:
+ solar:
+ entity: sensor.hapsic_steam_mass
+ name: Steam Input
+ color: "#3498db"
+ unit_of_measurement: lbs/hr
+ battery:
+ name: Net Flux
+ entity:
+ consumption: sensor.hapsic_net_flux
+ production: sensor.hapsic_net_flux
+ color_icon: true
+ color_circle: true
+ unit_of_measurement: lbs/hr
+ label_consumption: Draining
+ label_production: Charging
+ home:
+ name: Vent Loss
+ entity: sensor.hapsic_ventilation_loss
+ color_icon: true
+ unit_of_measurement: lbs/hr
+ dashboard_link: /energy
+ display_zero_lines: true
+ use_new_flow_rate_model: true
+ min_flow_rate: 0.1
+ decimals: 2
+ watt_threshold: 10000
+ - type: heading
+ heading: Control Strategy (Loop A)
+ heading_style: title
+ - type: grid
+ columns: 3
+ square: false
+ cards:
+ - type: tile
+ entity: sensor.hapsic_room_deficit
+ name: Deficit
+ icon: mdi:arrow-collapse-down
+ color: >-
+ {% set val = states('sensor.hapsic_room_deficit')|float(0) %} {%
+ if val < -0.5 %} blue {% elif val < 0.5 %} green {% elif val <
+ 2.0 %} orange {% else %} red {% endif %}
+ state_content: state
+ - type: tile
+ entity: sensor.hapsic_target_duct_dp
+ name: Duct Request
+ icon: mdi:target
+ color: deep-purple
+ state_content: state
+ - type: tile
+ entity: sensor.hapsic_max_achievable_dp
+ name: Feasibility Limit
+ icon: mdi:speedometer
+ color: >-
+ {% if states('sensor.hapsic_is_target_infeasible') == 'True' %}
+ red {% else %} green {% endif %}
+ state_content: state
+ - type: custom:apexcharts-card
+ header:
+ show: true
+ title: Target vs. Actual Dew Point
+ show_states: true
+ colorize_states: true
+ graph_span: 6h
+ series:
+ - entity: sensor.hapsic_room_dew_point
+ name: Actual Dew Point
+ color: "#2196f3"
+ stroke_width: 2
+ curve: smooth
+ - entity: input_number.target_dew_point
+ name: Target Dew Point
+ color: "#9b59b6"
+ stroke_width: 2
+ curve: stepline
+ - entity: sensor.hapsic_max_achievable_dp
+ name: Physical Limit
+ color: "#f44336"
+ stroke_width: 2
+ type: area
+ opacity: 0.1
+ - title: History
+ type: history-graph
+ hours_to_show: 12
+ entities:
+ - sensor.hapsic_pre_steam_dp
+ - sensor.hapsic_cleansed_airflow
+ - input_number.hapsic_chi_ema
+ - sensor.hapsic_duct_dp
+ - sensor.hapsic_target_duct_dp
+ - sensor.hapsic_max_achievable_dp
+ - sensor.hapsic_chi_instant
+ - sensor.hapsic_room_dew_point
+ - input_number.target_dew_point
+ - sensor.hapsic_steam_voltage