Skip to content

Fix: Incorrect Unit Scaling for Energy Capacity Fields (Off by Factor of 10) #70

@eman

Description

@eman

Description
The total_energy_capacity and available_energy_capacity fields in DeviceStatus are currently interpreted as raw Watt-hours (Wh). However, analysis of the reported values against the physics of water heating confirms that the device reports these values in units of 10 Wh (or cent-kilowatt-hours).
Currently, a fully heated 65-gallon tank reports a capacity of 1404.0, which the library interprets as 1.4 kWh. This is physically impossible for the given temperature delta.
Physics Verification
To verify the unit scale, we calculated the energy required to heat the specific tank volume:

  • Tank Volume: 65 gallons ($\approx$ 542 lbs of water)
  • Setpoint: 141°F
  • Assumed Inlet Temp: ~53°F (Standard groundwater temp)

Scenario A: Current Interpretation (1,404 Wh / 1.4 kWh)

$$1.4 \text{ kWh} \approx 4,777 \text{ BTU}$$
Using the specific heat formula ($Q = mc\Delta T$):

$$\Delta T = \frac{4,777 \text{ BTU}}{542 \text{ lbs}} \approx 8.8^{\circ}\text{F}$$
Result: 1.4 kWh is only enough to raise the water temperature by ~9°F. This contradicts the "Total Capacity" status of a hot tank.
Scenario B: Proposed Interpretation (14,040 Wh / 14.0 kWh)

$$14.04 \text{ kWh} \approx 47,906 \text{ BTU}$$

$$\Delta T = \frac{47,906 \text{ BTU}}{542 \text{ lbs}} \approx 88.4^{\circ}\text{F}$$
Result: An $88.4^{\circ}\text{F}$ rise from a $53^{\circ}\text{F}$ inlet results in a final temp of $\approx 141.4^{\circ}\text{F}$.
Conclusion: This matches the setpoint perfectly. The raw values are in units of 10 Wh.
Proposed Solution
We need to introduce a validator that multiplies the raw device value by 10 before storing it as a float.
1. Update src/nwp500/converters.py
Add a helper function to handle the multiplication.

Python

def mul_10(value: Any) -> float:
"""Multiply numeric value by 10.0.

Used for energy capacity fields where the device reports in 10Wh units,  
but we want to store standard Wh.  
"""  
if isinstance(value, (int, float)):  
    return float(value) \* 10.0  
return float(value)

2. Update src/nwp500/models.py
Apply a BeforeValidator to the energy capacity fields in the DeviceStatus model.

Python

from pydantic import BeforeValidator
from .converters import mul_10

# ... existing imports ...

# Define reusable type
TenWhToWh = Annotated[float, BeforeValidator(mul_10)]

class DeviceStatus(NavienBaseModel):
# ... existing fields ...

total_energy_capacity: TenWhToWh = Field(  
    description="Total energy capacity of the tank in Watt-hours",  
    json_schema_extra={  
        "unit_of_measurement": "Wh",  
        "device_class": "energy",  
    },  
)  
available_energy_capacity: TenWhToWh = Field(  
    description=(  
        "Available energy capacity - "  
        "remaining hot water energy available in Watt-hours"  
    ),  
    json\_schema\_extra={  
        "unit\_of\_measurement": "Wh",  
        "device\_class": "energy",  
    },  
)  

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions