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
2 changes: 1 addition & 1 deletion docs/DEVICE_STATUS_FIELDS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ This document lists the fields found in the ``status`` object of device status m
- integer
- °F
- Target superheat value - the desired temperature difference ensuring complete refrigerant vaporization.
- ``raw / 10.0``
- ``(raw / 10) * 9/5 + 32`` (decicelsius to Fahrenheit)
* - ``compUse``
- bool
- None
Expand Down
39 changes: 39 additions & 0 deletions docs/ENERGY_MONITORING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,45 @@ Total upper electric heater runtime in minutes -
``heater2RunningMinuteTotal`` (int): Total lower electric heater runtime
in minutes

Historical Energy Usage
-----------------------

Request detailed daily energy usage data for specific months:

.. code:: python

from nwp500 import NavienMqttClient, EnergyUsageResponse

def on_energy_usage(energy: EnergyUsageResponse):
print(f"Total Usage: {energy.total.total_usage} Wh")
print(f"Heat Pump: {energy.total.heat_pump_percentage:.1f}%")
print(f"Electric: {energy.total.heat_element_percentage:.1f}%")

# Daily breakdown
for day in energy.daily:
print(f"Day {day.day}: {day.total_usage} Wh")

# Subscribe to energy usage responses
await mqtt_client.subscribe_energy_usage(device, on_energy_usage)

# Request energy usage for September 2025
await mqtt_client.request_energy_usage(device, year=2025, months=[9])

# Request multiple months
await mqtt_client.request_energy_usage(device, year=2025, months=[7, 8, 9])

**Key Methods:**

- ``request_energy_usage(device, year, months)``: Request historical data
- ``subscribe_energy_usage(device, callback)``: Subscribe to energy usage responses

**Response Fields:**

- ``total.total_usage`` (int): Total energy consumption in Wh
- ``total.heat_pump_percentage`` (float): Percentage from heat pump
- ``total.heat_element_percentage`` (float): Percentage from electric heaters
- ``daily`` (list): Daily breakdown of usage per day

Energy Capacity
---------------

Expand Down
218 changes: 214 additions & 4 deletions docs/MQTT_CLIENT.rst
Original file line number Diff line number Diff line change
Expand Up @@ -396,32 +396,128 @@ Publish a message to an MQTT topic.
Device Command Methods
^^^^^^^^^^^^^^^^^^^^^^

Complete MQTT API Reference
''''''''''''''''''''''''''''

This section provides a comprehensive reference of all available MQTT client methods for requesting data and controlling devices.

**Request Methods & Corresponding Subscriptions**

+------------------------------------+---------------------------------------+----------------------------------------+
| Request Method | Subscribe Method | Response Type |
+====================================+=======================================+========================================+
| ``request_device_status()`` | ``subscribe_device_status()`` | ``DeviceStatus`` object |
+------------------------------------+---------------------------------------+----------------------------------------+
| ``request_device_info()`` | ``subscribe_device_feature()`` | ``DeviceFeature`` object |
+------------------------------------+---------------------------------------+----------------------------------------+
| ``request_energy_usage()`` | ``subscribe_energy_usage()`` | ``EnergyUsageResponse`` object |
+------------------------------------+---------------------------------------+----------------------------------------+
| ``set_power()`` | ``subscribe_device_status()`` | Updated ``DeviceStatus`` |
+------------------------------------+---------------------------------------+----------------------------------------+
| ``set_dhw_mode()`` | ``subscribe_device_status()`` | Updated ``DeviceStatus`` |
+------------------------------------+---------------------------------------+----------------------------------------+
| ``set_dhw_temperature()`` | ``subscribe_device_status()`` | Updated ``DeviceStatus`` |
+------------------------------------+---------------------------------------+----------------------------------------+
| ``set_dhw_temperature_display()`` | ``subscribe_device_status()`` | Updated ``DeviceStatus`` |
+------------------------------------+---------------------------------------+----------------------------------------+

**Generic Subscriptions**

+------------------------------------+---------------------------------------+----------------------------------------+
| Method | Purpose | Response Type |
+====================================+=======================================+========================================+
| ``subscribe_device()`` | Subscribe to all device messages | Raw ``dict`` (all message types) |
+------------------------------------+---------------------------------------+----------------------------------------+
| ``subscribe()`` | Subscribe to any MQTT topic | Raw ``dict`` |
+------------------------------------+---------------------------------------+----------------------------------------+

request_device_status()
'''''''''''''''''''''''

.. code:: python

await mqtt_client.request_device_status(device: Device) -> int

Request current device status.
Request current device status including temperatures, operation mode, power consumption, and error codes.

**Command:** ``16777219``

**Topic:** ``cmd/{device_type}/navilink-{device_id}/st``

**Response:** Subscribe with ``subscribe_device_status()`` to receive ``DeviceStatus`` objects

**Example:**

.. code:: python

def on_status(status: DeviceStatus):
print(f"Water Temp: {status.dhwTemperature}°F")
print(f"Mode: {status.operationMode}")
print(f"Power: {status.currentInstPower}W")

await mqtt_client.subscribe_device_status(device, on_status)
await mqtt_client.request_device_status(device)

request_device_info()
'''''''''''''''''''''

.. code:: python

await mqtt_client.request_device_info(device: Device) -> int

Request device information.
Request device information including firmware version, serial number, temperature limits, and capabilities.

**Command:** ``16777217``

**Topic:** ``cmd/{device_type}/navilink-{device_id}/st/did``

**Response:** Subscribe with ``subscribe_device_feature()`` to receive ``DeviceFeature`` objects

**Example:**

.. code:: python

def on_feature(feature: DeviceFeature):
print(f"Firmware: {feature.controllerSwVersion}")
print(f"Serial: {feature.controllerSerialNumber}")
print(f"Temp Range: {feature.dhwTemperatureMin}-{feature.dhwTemperatureMax}°F")

await mqtt_client.subscribe_device_feature(device, on_feature)
await mqtt_client.request_device_info(device)

request_energy_usage()
''''''''''''''''''''''

.. code:: python

await mqtt_client.request_energy_usage(device: Device, year: int, months: list[int]) -> int

Request historical daily energy usage data for specified month(s). Returns heat pump and electric heating element consumption with daily breakdown.

**Command:** ``16777225``

**Topic:** ``cmd/{device_type}/navilink-{device_id}/st/energy-usage-daily-query/rd``

**Response:** Subscribe with ``subscribe_energy_usage()`` to receive ``EnergyUsageResponse`` objects

**Parameters:**

- ``year``: Year to query (e.g., 2025)
- ``months``: List of months to query (1-12). Can request multiple months.

**Example:**

.. code:: python

def on_energy(energy: EnergyUsageResponse):
print(f"Total Usage: {energy.total.total_usage} Wh")
print(f"Heat Pump: {energy.total.heat_pump_percentage:.1f}%")
for day in energy.daily:
print(f"Day {day.day}: {day.total_usage} Wh")

await mqtt_client.subscribe_energy_usage(device, on_energy)
await mqtt_client.request_energy_usage(device, year=2025, months=[9])

set_power()
'''''''''''

Expand All @@ -435,6 +531,8 @@ Turn device on or off.

**Mode:** ``power-on`` or ``power-off``

**Response:** Device status is updated; subscribe with ``subscribe_device_status()`` to see changes

set_dhw_mode()
''''''''''''''

Expand All @@ -456,6 +554,8 @@ Set DHW (Domestic Hot Water) operation mode. This sets the ``dhwOperationSetting
* ``4``: High Demand (faster recovery - Hybrid: Boost)
* ``5``: Vacation (suspend heating for 0-99 days)

**Response:** Device status is updated; subscribe with ``subscribe_device_status()`` to see changes

**Important:** Setting the mode updates ``dhwOperationSetting`` but does not immediately change ``operationMode``. The ``operationMode`` field reflects the device's current operational state and changes automatically when the device starts/stops heating. See :doc:`DEVICE_STATUS_FIELDS` for details on the relationship between these fields.

set_dhw_temperature()
Expand All @@ -465,13 +565,44 @@ set_dhw_temperature()

await mqtt_client.set_dhw_temperature(device: Device, temperature: int) -> int

Set DHW target temperature.
Set DHW target temperature using the **MESSAGE value** (20°F lower than display).

**Command:** ``33554433``

**Mode:** ``dhw-temperature``

**Parameters:** - ``temperature``: Target temperature in Fahrenheit
**Parameters:**

- ``temperature``: Target temperature in Fahrenheit (message value, not display value)

**Response:** Device status is updated; subscribe with ``subscribe_device_status()`` to see changes

**Important:** The temperature in the message is 20°F lower than what displays on the device/app:

- Message value 120°F → Display shows 140°F
- Message value 130°F → Display shows 150°F

set_dhw_temperature_display()
''''''''''''''''''''''''''''''

.. code:: python

await mqtt_client.set_dhw_temperature_display(device: Device, display_temperature: int) -> int

Set DHW target temperature using the **DISPLAY value** (what you see on device/app). This is a convenience method that automatically converts display temperature to message value.

**Parameters:**

- ``display_temperature``: Target temperature as shown on display/app (Fahrenheit)

**Response:** Device status is updated; subscribe with ``subscribe_device_status()`` to see changes

**Example:**

.. code:: python

# Set display temperature to 140°F (sends 120°F in message)
await mqtt_client.set_dhw_temperature_display(device, 140)

signal_app_connection()
'''''''''''''''''''''''
Expand All @@ -484,6 +615,85 @@ Signal that the app has connected.

**Topic:** ``evt/{device_type}/navilink-{device_id}/app-connection``

Subscription Methods
''''''''''''''''''''

subscribe_device_status()
.........................

.. code:: python

await mqtt_client.subscribe_device_status(
device: Device,
callback: Callable[[DeviceStatus], None]
) -> int

Subscribe to device status messages with automatic parsing into ``DeviceStatus`` objects. Use this after calling ``request_device_status()`` or any control commands to receive updates.

**Emits Events:**

- ``status_received``: Every status update (DeviceStatus)
- ``temperature_changed``: Temperature changed (old_temp, new_temp)
- ``mode_changed``: Operation mode changed (old_mode, new_mode)
- ``power_changed``: Power consumption changed (old_power, new_power)
- ``heating_started``: Device started heating (status)
- ``heating_stopped``: Device stopped heating (status)
- ``error_detected``: Error code detected (error_code, status)
- ``error_cleared``: Error code cleared (error_code)

subscribe_device_feature()
..........................

.. code:: python

await mqtt_client.subscribe_device_feature(
device: Device,
callback: Callable[[DeviceFeature], None]
) -> int

Subscribe to device feature/info messages with automatic parsing into ``DeviceFeature`` objects. Use this after calling ``request_device_info()`` to receive device capabilities and firmware info.

**Emits Events:**

- ``feature_received``: Feature/info received (DeviceFeature)

subscribe_energy_usage()
........................

.. code:: python

await mqtt_client.subscribe_energy_usage(
device: Device,
callback: Callable[[EnergyUsageResponse], None]
) -> int

Subscribe to energy usage query responses with automatic parsing into ``EnergyUsageResponse`` objects. Use this after calling ``request_energy_usage()`` to receive historical energy data.

subscribe_device()
..................

.. code:: python

await mqtt_client.subscribe_device(
device: Device,
callback: Callable[[str, dict], None]
) -> int

Subscribe to all messages from a device (no parsing). Receives all message types as raw dictionaries. Use the specific subscription methods above for automatic parsing.

subscribe()
...........

.. code:: python

await mqtt_client.subscribe(
topic: str,
callback: Callable[[str, dict], None],
qos: mqtt.QoS = mqtt.QoS.AT_LEAST_ONCE
) -> int

Subscribe to any MQTT topic. Supports wildcards (``#``, ``+``). Receives raw dictionary messages.

Periodic Request Methods (Optional)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
2 changes: 1 addition & 1 deletion src/nwp500/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,6 @@ def from_dict(cls, data: dict):

# Convert fields with 'raw / 10.0' formula (non-temperature fields)
div_10_fields = [
"targetSuperHeat",
"currentInletTemperature",
"currentDhwFlowRate",
"hpUpperOnDiffTempSetting",
Expand Down Expand Up @@ -414,6 +413,7 @@ def from_dict(cls, data: dict):
"evaporatorTemperature",
"ambientTemperature",
"currentSuperHeat",
"targetSuperHeat",
]
for field_name in heat_pump_temp_fields:
if field_name in converted_data:
Expand Down