diff --git a/homeassistant/util/unit_conversion.py b/homeassistant/util/unit_conversion.py index bf8bdadc084..322410f61ec 100644 --- a/homeassistant/util/unit_conversion.py +++ b/homeassistant/util/unit_conversion.py @@ -91,6 +91,17 @@ _GALLON_TO_CUBIC_METER = 231 * pow(_IN_TO_M, 3) # US gallon is 231 cubic inches _FLUID_OUNCE_TO_CUBIC_METER = _GALLON_TO_CUBIC_METER / 128 # 128 fl. oz. in a US gallon _CUBIC_FOOT_TO_CUBIC_METER = pow(_FOOT_TO_M, 3) +# Gas concentration conversion constants +_IDEAL_GAS_CONSTANT = 8.31446261815324 # m3⋅Pa⋅K⁻¹⋅mol⁻¹ +# Ambient constants based on European Commission recommendations (20 °C and 1013mb) +_AMBIENT_TEMPERATURE = 293.15 # K (20 °C) +_AMBIENT_PRESSURE = 101325 # Pa (1 atm) +_AMBIENT_IDEAL_GAS_MOLAR_VOLUME = ( # m3⋅mol⁻¹ + _IDEAL_GAS_CONSTANT * _AMBIENT_TEMPERATURE / _AMBIENT_PRESSURE +) +# Molar masses in g⋅mol⁻¹ +_CARBON_MONOXIDE_MOLAR_MASS = 28.01 + class BaseUnitConverter: """Define the format of a conversion utility.""" @@ -169,14 +180,17 @@ class BaseUnitConverter: class CarbonMonoxideConcentrationConverter(BaseUnitConverter): - """Convert carbon monoxide ratio to mass per volume.""" + """Convert carbon monoxide ratio to mass per volume. + + Using ambient temperature of 20°C and pressure of 1 ATM. + """ UNIT_CLASS = "carbon_monoxide" _UNIT_CONVERSION: dict[str | None, float] = { - CONCENTRATION_PARTS_PER_MILLION: 1, - # concentration (mg/m3) = 0.0409 x concentration (ppm) x molar mass - # Carbon monoxide molar mass: 28.01 g/mol - CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER: 0.0409 * 28.01, + CONCENTRATION_PARTS_PER_MILLION: 1e6, + CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER: ( + _CARBON_MONOXIDE_MOLAR_MASS / _AMBIENT_IDEAL_GAS_MOLAR_VOLUME * 1e3 + ), } VALID_UNITS = { CONCENTRATION_PARTS_PER_MILLION, diff --git a/tests/components/sensor/test_recorder.py b/tests/components/sensor/test_recorder.py index cc5a3d85445..4d857376efe 100644 --- a/tests/components/sensor/test_recorder.py +++ b/tests/components/sensor/test_recorder.py @@ -3626,7 +3626,7 @@ async def test_compile_hourly_statistics_changing_units_3( 13.050847, -10, 30, - 1.145609, + 1.16441, ), ( "carbon_monoxide", @@ -3636,7 +3636,7 @@ async def test_compile_hourly_statistics_changing_units_3( 13.050847, -10, 30, - 1 / 1.145609, + 1 / 1.16441, ), (None, "%", None, "unitless", 13.050847, -10, 30, 0.01), (None, "W", "kW", "power", 13.050847, -10, 30, 0.001), diff --git a/tests/util/test_unit_conversion.py b/tests/util/test_unit_conversion.py index e648a3c8878..824d9708f7f 100644 --- a/tests/util/test_unit_conversion.py +++ b/tests/util/test_unit_conversion.py @@ -119,7 +119,7 @@ _GET_UNIT_RATIO: dict[type[BaseUnitConverter], tuple[str | None, str | None, flo CarbonMonoxideConcentrationConverter: ( CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER, CONCENTRATION_PARTS_PER_MILLION, - 1.145609, + 1.16441, ), ConductivityConverter: ( UnitOfConductivity.MICROSIEMENS_PER_CM, @@ -291,13 +291,13 @@ _CONVERTED_VALUE: dict[ ( 1, CONCENTRATION_PARTS_PER_MILLION, - 1.145609, + 1.16441, CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER, ), ( 120, CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER, - 104.74778, + 103.05655, CONCENTRATION_PARTS_PER_MILLION, ), ],