Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
- [Manual Tuning](#1-manual-trial--error)
- [Ziegler–Nichols Method](#2-zieglernichols-method)
- [PID Calculation Frequency and Sample Time](#pid-calculation-frequency-and-sample-time)
- [More details and extended documentation]{#more-details-and-extended-documentation)
- [More details and extended documentation](#extended-documentation)
- [Example PID Graph](#example-pid-graph)
- [Support & Development](#support--development)
- [Service Actions](#service-actions)
Expand Down Expand Up @@ -180,10 +180,9 @@ This integration recalculates the PID output at a fixed, user-configurable inter

By using a single **Sample Time** for both scheduling and calculation—and understanding that each component tracks its own clock—you get predictable, evenly-spaced control updates while allowing Home Assistant’s event loop to manage timing drifts gracefully.```


---

## 📚 More details and extended documentation
## 📚 Extended documentation

The integration is based on simple-pid [https://pypi.org/project/simple-pid/](https://pypi.org/project/simple-pid/)

Expand Down
9 changes: 5 additions & 4 deletions custom_components/simple_pid_controller/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,10 @@ def __init__(
BasePIDEntity.__init__(self, hass, entry, key, name)

self._attr_entity_category = EntityCategory.DIAGNOSTIC
self._attr_entity_registry_enabled_default = False
# self._attr_entity_registry_enabled_default = False
self._attr_state_class = SensorStateClass.MEASUREMENT
self._key = key
self._handle = entry.runtime_data.handle

@property
def native_value(self):
Expand All @@ -212,9 +213,9 @@ def native_value(self):
error = input_value - setpoint

value = {
"p": contributions[0],
"i": contributions[1],
"d": contributions[2],
"pid_p_contrib": contributions[0],
"pid_i_contrib": contributions[1],
"pid_d_contrib": contributions[2],
"error": error,
}.get(self._key)
return round(value, 2) if value is not None else None
26 changes: 18 additions & 8 deletions tests/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,23 +50,33 @@ async def test_pid_contribution_native_value_rounding_and_none(hass, config_entr
handle.last_contributions = (0.1234, 1.9876, 2.5555)
coordinator = PIDDataCoordinator(hass, "test", lambda: 0, interval=1)

# Map contribution key to expected index
# Map contribution keys to expected values
mapping = [
("p", round(0.1234, 2)),
("i", round(1.9876, 2)),
("d", round(2.5555, 2)),
("pid_p_contrib", round(0.1234, 2)),
("pid_i_contrib", round(1.9876, 2)),
("pid_d_contrib", round(2.5555, 2)),
("error", -25),
("unknown_key", None), # Should return None
]

for key, expected in mapping:
sensor = PIDContributionSensor(
hass, config_entry, key, f"pid_{key}_contrib", coordinator
hass,
config_entry,
key,
f"sensor.{config_entry.entry_id}_{key}",
coordinator,
)
# Override internal handle to use test handle
sensor._handle = handle
sensor._handle = handle # inject mock handle
assert sensor.native_value == expected

# Unknown key should return None
sensor_none = PIDContributionSensor(
hass, config_entry, "x", "pid_x_contrib", coordinator
hass,
config_entry,
"x",
"sensor.{config_entry.entry_id}_pid_x_contrib",
coordinator,
)
sensor_none._handle = handle
assert sensor_none.native_value is None
Expand Down
Loading