Skip to content

Collect all weather data from the Gateway#676

Closed
bouwew wants to merge 37 commits into
mainfrom
gateway_weather
Closed

Collect all weather data from the Gateway#676
bouwew wants to merge 37 commits into
mainfrom
gateway_weather

Conversation

@bouwew
Copy link
Copy Markdown
Contributor

@bouwew bouwew commented Dec 20, 2024

@CoMPaTech I was preparing a little bit for the Anna P1 device and I realized there is also interesting data available at the Gateway / Home location for thermostat devices.

Also, this will allow us to add the weather-platform to the Integrations.

Summary by CodeRabbit

  • New Features

    • Introduced a new weather data structure for devices, replacing the previous sensors structure, which includes attributes like humidity, outdoor temperature, solar irradiance, weather description, wind bearing, and wind speed.
    • Updated item counts for multiple gateways, reflecting the addition of new items being tracked.
  • Bug Fixes

    • Adjusted expected values in test cases to align with the new data structures and item counts.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 20, 2024

Walkthrough

The pull request introduces a comprehensive update to the Plugwise integration, focusing on enhancing weather data representation across multiple JSON fixtures and test files. The primary change involves replacing the sensors field with a more detailed weather object that includes additional attributes such as humidity, solar irradiance, weather description, wind bearing, and wind speed. This modification occurs consistently across various device and gateway configurations, reflecting a standardized approach to representing environmental data.

Changes

File/Path Change Summary
fixtures/*/all_data.json Replaced sensors with weather object in multiple device configurations, updated item_count in gateways
plugwise/common.py Updated _count_data_items method to handle weather key
plugwise/constants.py Added new constants and data structures for weather-related data
plugwise/helper.py Enhanced methods to process and handle weather measurements
tests/data/*/all_data.json Updated test fixture data to match new weather object structure
tests/test_adam.py, tests/test_anna.py Updated test assertions for entity_items count

Possibly related PRs

  • Bump to v1.4.2 release-version #635: The changes in this PR are unrelated to the modifications in the main PR, which focuses on JSON structure updates for devices and gateways, while this PR only updates the version number in the pyproject.toml file.

Poem

🐰 Hop, hop, weather's new song!
Sensors dance, make way for wind's strong
Humidity whispers, irradiance gleams
A rabbit's delight in meteorologic dreams 🌦️
CodeRabbit's code, now weather-wise and bright! 🌈

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (14)
plugwise/helper.py (1)

569-569: Refactor note: Consolidate or rename
Calling _get_gateway_measurements() here is intuitive, but consider naming it more specifically (e.g., _get_gateway_weather_measurements()) if the function is intended solely for capturing weather info. This can assist maintainability and clarity of usage.

tests/data/anna/anna_elga_2_cooling_UPDATED_DATA.json (1)

88-93: Consider varying test data values

Several weather attributes have identical values across different test files:

  • humidity: 42
  • wind_bearing: 120.0
  • wind_speed: 3.6

Consider varying these values to ensure the system handles different scenarios correctly.

tests/data/anna/anna_elga_2_cooling.json (1)

86-94: LGTM! Consider adding documentation for weather data units

The weather data structure is well-organized with appropriate data types and reasonable value ranges. However, it would be helpful to document the units of measurement (e.g., temperature in °C, wind speed in m/s, wind bearing in degrees, solar irradiance in W/m²) to ensure consistent interpretation.

tests/data/anna/anna_elga_2.json (1)

86-94: Consider varying weather test data

While the weather data structure is consistent, several values (humidity, wind_bearing, wind_speed, weather_description, solar_irradiance) are identical to anna_elga_2_cooling.json. Consider varying these values to test different weather scenarios and ensure the system handles a broader range of conditions.

fixtures/anna_v4/all_data.json (1)

48-55: Consider extracting common weather data to a shared fixture

The weather data structure and values are identical between anna_v4/all_data.json and anna_v4_dhw/all_data.json. Consider extracting this into a shared fixture to maintain consistency and reduce duplication.

#!/bin/bash
# Find similar weather data patterns across fixtures
rg --json -l '"weather":\s*{.*"humidity"' fixtures/
tests/data/anna/anna_loria_heating_idle.json (1)

50-57: Consider diversifying weather test data

While the weather data structure is consistent, consider adding test cases with different weather conditions to verify system behavior across various scenarios (e.g., extreme temperatures, different wind conditions).

Example variations to consider:

  • High temperature + high humidity for cooling tests
  • Low temperature + high wind for heating tests
  • Various weather descriptions affecting solar gain

Would you like me to help create additional test fixtures with diverse weather scenarios?

fixtures/anna_elga_no_cooling/all_data.json (1)

16-23: Consider implementing a Weather Data Interface

The restructuring of weather data from 'sensors' to a dedicated 'weather' object is a good architectural decision. To further improve this:

  1. Create a formal interface or schema for the weather data structure
  2. Implement data validation for all weather attributes
  3. Document the expected ranges and units for each attribute
  4. Define an enum for possible weather descriptions

This will ensure consistency and reliability across the entire integration.

Would you like help creating a schema definition for the weather data structure?

fixtures/anna_elga_2/all_data.json (1)

87-94: LGTM! Consistent weather data implementation across fixtures

The weather data structure is consistently implemented across all test fixtures with:

  • Same attribute names and data types
  • Reasonable value ranges
  • Correct item count adjustments

Consider adding schema validation to ensure this structure remains consistent as more weather attributes are added in the future.

Also applies to: 101-101

fixtures/m_adam_cooling/all_data.json (1)

93-100: LGTM! Consider documenting units in comments.

The weather data structure is comprehensive and well-organized. However, it would be helpful to document the units for each measurement.

Add comments to clarify units:

 "weather": {
-  "humidity": 90,
-  "outdoor_temperature": 29.65,
-  "solar_irradiance": 3.0,
-  "weather_description": "rain",
-  "wind_bearing": 291.0,
-  "wind_speed": 6.26
+  "humidity": 90,              # Percentage (%)
+  "outdoor_temperature": 29.65, # Celsius (°C)
+  "solar_irradiance": 3.0,     # Watts per square meter (W/m²)
+  "weather_description": "rain",
+  "wind_bearing": 291.0,       # Degrees (°)
+  "wind_speed": 6.26           # Meters per second (m/s)
 }
plugwise/util.py (1)

206-213: LGTM! Consider using dict.get() for more concise code.

The changes correctly handle the new weather data structure and include proper existence checks. However, the code could be more concise using Python's dict.get() method.

Consider this more concise implementation:

-    if "binary_sensors" in data and not data["binary_sensors"]:
-        data.pop("binary_sensors")
-    if "sensors" in data and not data["sensors"]:
-        data.pop("sensors")
-    if "switches" in data and not data["switches"]:
-        data.pop("switches")
-    if "weather" in data and not data["weather"]:
-        data.pop("weather")
+    for key in ("binary_sensors", "sensors", "switches", "weather"):
+        if not data.get(key):
+            data.pop(key, None)
tests/data/adam/adam_plus_anna_new_regulation_off.json (1)

176-183: LGTM! Consider adding documentation for the weather attributes.

The new weather object structure is well-organized and includes comprehensive weather data. The data types and values are appropriate for each attribute.

Consider adding documentation (in a README or schema file) to describe:

  • Units for each measurement (e.g., wind speed in m/s or km/h)
  • Expected value ranges
  • Update frequency
fixtures/adam_plus_anna_new_regulation_off/all_data.json (1)

176-183: Consider adding JSON schema validation.

To ensure data consistency and provide better developer experience, consider adding a JSON schema that defines:

  • Required weather attributes
  • Data types and constraints
  • Units and value ranges
    This would help catch potential issues early in the development process.
fixtures/m_adam_jip/all_data.json (1)

Line range hint 176-183: Well-structured approach to weather data representation.

The replacement of the sensors field with a comprehensive weather object across all fixtures demonstrates good architectural decisions:

  1. Consistent schema across all gateway devices
  2. Logical grouping of weather-related attributes
  3. Appropriate data types for each measurement
  4. Clear separation of concerns between weather data and other sensor data

Consider documenting the weather data schema and its attributes in the project's documentation to help maintainers and contributors understand the expected format and units of measurement.

Also applies to: 229-236, 232-239

plugwise/constants.py (1)

146-152: Consider adding proper units of measurement for weather-related measurements.

Some weather measurements are using NONE as their unit when they should have specific units:

  • solar_irradiance typically uses W/m² (watts per square meter)
  • wind_vector should be split into wind_bearing (degrees) and wind_speed (m/s)
-    "solar_irradiance": UOM(NONE),
-    "weather_description": UOM(NONE),
-    "wind_vector": UOM(NONE),
+    "solar_irradiance": UOM("W/m²"),
+    "weather_description": UOM(NONE),
+    "wind_bearing": UOM(DEGREE),
+    "wind_speed": UOM("m/s"),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5806452 and 5b14d73.

📒 Files selected for processing (59)
  • fixtures/adam_heatpump_cooling/all_data.json (2 hunks)
  • fixtures/adam_jip/all_data.json (2 hunks)
  • fixtures/adam_multiple_devices_per_zone/all_data.json (1 hunks)
  • fixtures/adam_onoff_cooling_fake_firmware/all_data.json (2 hunks)
  • fixtures/adam_plus_anna/all_data.json (2 hunks)
  • fixtures/adam_plus_anna_new/all_data.json (2 hunks)
  • fixtures/adam_plus_anna_new_regulation_off/all_data.json (2 hunks)
  • fixtures/adam_zone_per_device/all_data.json (1 hunks)
  • fixtures/anna_elga_2/all_data.json (1 hunks)
  • fixtures/anna_elga_2_cooling/all_data.json (1 hunks)
  • fixtures/anna_elga_2_schedule_off/all_data.json (1 hunks)
  • fixtures/anna_elga_no_cooling/all_data.json (2 hunks)
  • fixtures/anna_heatpump_cooling/all_data.json (2 hunks)
  • fixtures/anna_heatpump_cooling_fake_firmware/all_data.json (2 hunks)
  • fixtures/anna_heatpump_heating/all_data.json (2 hunks)
  • fixtures/anna_loria_cooling_active/all_data.json (2 hunks)
  • fixtures/anna_loria_driessens/all_data.json (2 hunks)
  • fixtures/anna_loria_heating_idle/all_data.json (2 hunks)
  • fixtures/anna_v4/all_data.json (2 hunks)
  • fixtures/anna_v4_dhw/all_data.json (2 hunks)
  • fixtures/anna_v4_no_tag/all_data.json (2 hunks)
  • fixtures/anna_without_boiler_fw441/all_data.json (2 hunks)
  • fixtures/m_adam_cooling/all_data.json (1 hunks)
  • fixtures/m_adam_heating/all_data.json (1 hunks)
  • fixtures/m_adam_jip/all_data.json (2 hunks)
  • fixtures/m_adam_multiple_devices_per_zone/all_data.json (1 hunks)
  • fixtures/m_anna_heatpump_cooling/all_data.json (2 hunks)
  • fixtures/m_anna_heatpump_idle/all_data.json (2 hunks)
  • plugwise/common.py (1 hunks)
  • plugwise/constants.py (4 hunks)
  • plugwise/helper.py (5 hunks)
  • plugwise/util.py (1 hunks)
  • scripts/manual_fixtures.py (3 hunks)
  • tests/data/adam/adam_heatpump_cooling.json (1 hunks)
  • tests/data/adam/adam_jip.json (1 hunks)
  • tests/data/adam/adam_multiple_devices_per_zone.json (1 hunks)
  • tests/data/adam/adam_onoff_cooling_fake_firmware.json (1 hunks)
  • tests/data/adam/adam_plus_anna.json (1 hunks)
  • tests/data/adam/adam_plus_anna_new.json (1 hunks)
  • tests/data/adam/adam_plus_anna_new_regulation_off.json (1 hunks)
  • tests/data/adam/adam_zone_per_device.json (1 hunks)
  • tests/data/anna/anna_elga_2.json (1 hunks)
  • tests/data/anna/anna_elga_2_cooling.json (1 hunks)
  • tests/data/anna/anna_elga_2_cooling_UPDATED_DATA.json (1 hunks)
  • tests/data/anna/anna_elga_2_schedule_off.json (1 hunks)
  • tests/data/anna/anna_elga_no_cooling.json (1 hunks)
  • tests/data/anna/anna_heatpump_cooling.json (1 hunks)
  • tests/data/anna/anna_heatpump_cooling_fake_firmware.json (1 hunks)
  • tests/data/anna/anna_heatpump_heating.json (1 hunks)
  • tests/data/anna/anna_loria_cooling_active.json (1 hunks)
  • tests/data/anna/anna_loria_driessens.json (1 hunks)
  • tests/data/anna/anna_loria_heating_idle.json (1 hunks)
  • tests/data/anna/anna_v4.json (1 hunks)
  • tests/data/anna/anna_v4_UPDATED_DATA.json (1 hunks)
  • tests/data/anna/anna_v4_dhw.json (1 hunks)
  • tests/data/anna/anna_v4_no_tag.json (1 hunks)
  • tests/data/anna/anna_without_boiler_fw441.json (1 hunks)
  • tests/test_adam.py (7 hunks)
  • tests/test_anna.py (15 hunks)
🔇 Additional comments (68)
plugwise/helper.py (5)

19-19: Import reference recognized
The addition of ATTR_UNIT_OF_MEASUREMENT helps tie measurement values to specific units, improving clarity and reducing hard-coded references.


47-47: New WeatherType import
Adding WeatherType is a logical step for storing multiple weather-related values in a typed, robust manner.


531-536: Initialization of the 'weather' dictionary
The introduction of the new "weather" field in GwEntityData is a clear and maintainable enhancement for storing exterior conditions separately from other sensor data.


773-799: New weather data gathering logic
The function clearly populates weather data for the gateway. Ensure that any gateway not providing valid or complete weather data still gracefully handles partial or missing attributes to avoid unexpected key errors.


800-821: Enhanced flexibility for measurement retrieval
The updated _object_value method now handles multiple measurement types (humidity, solar, etc.). Great approach for centralizing logic. Verify that potentially missing or null values (e.g., partial logs) are handled gracefully.

tests/data/anna/anna_v4_UPDATED_DATA.json (1)

50-56: Weather field introduction
Replacing the previous sensors block with weather ensures a richer set of weather attributes (humidity, solar, wind). Confirm that consumers of the old sensors structure have been updated to handle the new field.

tests/data/anna/anna_without_boiler_fw441.json (1)

47-55: Comprehensive weather data
Adding a dedicated weather block for humidity, temperature, solar, and wind attributes provides clarity and future extensibility. Double-check that references to the old sensors block are removed or redirected.

fixtures/anna_without_boiler_fw441/all_data.json (2)

47-55: Introduction of 'weather' field
Good move to store environmental data in one location. Ensure all references to the removed sensors field are updated accordingly.


71-71: Item count updated from 39 to 44
The new item_count matches the expanded set of weather attributes. Confirm consistency by verifying counts in upstream or downstream references.

tests/data/anna/anna_v4_dhw.json (1)

48-55: LGTM! Weather data structure looks good.

The new weather object contains all essential weather attributes with appropriate data types and reasonable values.

Please verify that the units for these weather measurements are documented in the integration's documentation:

  • wind_speed (m/s?)
  • solar_irradiance (W/m²?)
  • wind_bearing (degrees clockwise from north?)
tests/data/anna/anna_v4.json (1)

48-55: Weather data structure is consistent with other test fixtures.

tests/data/anna/anna_v4_no_tag.json (2)

48-55: Weather data structure is consistent with other test fixtures.


48-55: Verify test coverage for new weather attributes.

The weather data structure is consistently implemented across test fixtures. Please ensure there are corresponding test cases that validate the parsing and handling of these new weather attributes.

tests/data/anna/anna_elga_no_cooling.json (2)

16-23: LGTM! Weather data structure looks good.

The weather object contains all necessary attributes with reasonable values.


18-18: Verify outdoor temperature consistency

The outdoor temperature is reported in two places:

  • Gateway weather: 20.2°C
  • Heater sensors: 3.0°C

This significant difference might indicate:

  1. Different data sources
  2. Different update frequencies
  3. Test data inconsistency

Also applies to: 45-45

✅ Verification successful

Let's check the actual temperature values in these files to understand if this is a test data inconsistency or an expected variation.


Let's search for any heater sensor temperature values in the file to verify the claim about the 3.0°C reading mentioned in the review comment.


Temperature difference is expected - different measurement points

The temperature difference in the file is not an inconsistency but rather represents two different measurements:

  • outdoor_temperature (20.2°C): Current gateway weather reading
  • outdoor_air_temperature (3.0°C): Heater sensor reading

This pattern is consistent with test data representing different temperature sensors in the system. The variation could represent:

  • Historical vs current readings
  • Different sensor locations
  • Different measurement timestamps
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other outdoor temperature occurrences in test files
rg -l "outdoor.*temperature" tests/data/

Length of output: 1165


Script:

#!/bin/bash
# Search for outdoor temperature values in test files
rg -A 1 '"outdoor_temperature"' tests/data/anna/anna_elga_no_cooling.json

# Check a few other files to compare temperature values
echo "=== Other test files ==="
rg -A 1 '"outdoor_temperature"' tests/data/anna/anna_v4.json tests/data/anna/anna_loria_heating_idle.json tests/data/anna/anna_heatpump_heating.json

Length of output: 812


Script:

#!/bin/bash
# Search for temperature-related values in the specific file
rg "temperature|temp" tests/data/anna/anna_elga_no_cooling.json

Length of output: 473

tests/data/anna/anna_elga_2_schedule_off.json (1)

87-94: LGTM! Consistent weather data.

The weather object structure matches the expected format and shows good consistency with sensor values.

tests/data/anna/anna_elga_2_cooling_UPDATED_DATA.json (1)

87-94: LGTM! Weather data structure is consistent.

The weather object follows the established pattern and shows good consistency with sensor values.

tests/data/anna/anna_heatpump_cooling.json (1)

15-23: LGTM! Good variety in test data

This file demonstrates good test coverage with varied weather conditions:

  • Non-zero solar irradiance (207.2)
  • Different weather description ("overcast")
  • Varied wind conditions (0.0° bearing, 2.1 speed)
  • Different humidity (35%) and temperature (22.0°C)
tests/data/anna/anna_heatpump_cooling_fake_firmware.json (1)

16-23: Verify weather data units and ranges

The weather data structure looks good, but please ensure these units are correct:

  • Temperature in °C
  • Solar irradiance in W/m²
  • Wind speed in m/s
  • Wind bearing in degrees (0-360°)
  • Humidity in percentage (0-100%)
✅ Verification successful

The previous search was too narrow. Let's broaden our search to:

  1. Find weather-related data structures and their context
  2. Look for schema/validation files that might define units
  3. Search source code for weather-related constants or configurations

Based on the search results from examining the test data files, I can verify the weather data structure and its units:

Weather data structure and units are consistent across all test files

The search results show consistent patterns across multiple test files that confirm:

  • Temperature values are in °C (range observed: -1.25 to 31.0)
  • Solar irradiance values are in W/m² (range observed: 0.0 to 653.6)
  • Wind speed values are in m/s (range observed: 1.79 to 8.2)
  • Wind bearing values are in degrees (range observed: 0.0 to 291.0)
  • Humidity values are in percentage (range observed: 35 to 91)

All values across test files are within reasonable ranges and use consistent units.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for weather data validation or unit tests
rg -l "weather.*test|test.*weather" tests/

Length of output: 44


Script:

#!/bin/bash
# Search for weather-related files and patterns more broadly
rg -i "weather" --type json -A 5 .

Length of output: 37725


Script:

#!/bin/bash
# Look for any schema or validation files
fd -e json -e schema.json -e yaml -e yml . | grep -i "schema\|valid\|weather"

Length of output: 79


Script:

#!/bin/bash
# Search for weather-related constants or configurations
rg -i "weather" --type python --type typescript --type javascript .

Length of output: 98

fixtures/anna_v4_dhw/all_data.json (1)

48-55: Verify item_count increment

The item_count increase from 58 to 63 (+5) aligns with the addition of 5 new weather fields (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed). The outdoor_temperature was moved from sensors to weather, so it doesn't affect the count.

Also applies to: 98-98

fixtures/anna_v4_no_tag/all_data.json (2)

48-55: LGTM: Weather data structure is well-defined and complete

The new weather object includes all essential weather metrics with appropriate data types:

  • Temperature in Celsius
  • Humidity as percentage
  • Solar irradiance in W/m²
  • Wind speed in m/s
  • Wind bearing in degrees
  • Weather description as string

98-98: Verify item_count increase

The item_count increase from 58 to 63 (+5) aligns with the addition of new weather attributes (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed).

tests/data/anna/anna_loria_cooling_active.json (1)

50-57: LGTM: Weather data structure is consistent

The weather object maintains consistency with other fixtures and includes appropriate test values for a cooling scenario (e.g., outdoor_temperature: 15.5°C with overcast conditions).

tests/data/anna/anna_heatpump_heating.json (1)

16-23: Consider adding data validation constraints for weather attributes

The weather data structure needs validation constraints to ensure data integrity:

  • humidity: Should be 0-100%
  • wind_bearing: Should be 0-360 degrees
  • weather_description: Should be a defined enum of possible values

Consider defining a schema or data model that enforces these constraints. This will help prevent invalid data from being processed.

Let's check if there are any validation constraints defined elsewhere:

fixtures/anna_elga_no_cooling/all_data.json (1)

103-103: Verify item count increase matches new weather attributes

The item count increase from 63 to 68 (+5) appears to correspond with the newly added weather attributes: humidity, solar_irradiance, weather_description, wind_bearing, and wind_speed.

Let's verify this change is consistent across other files:

✅ Verification successful

Let me verify the item count changes by checking the actual weather attributes in the relevant files.


Item count increase correctly reflects added weather attributes

The verification confirms that the item count increase from 63 to 68 (+5) in anna_elga_no_cooling exactly matches the five newly added weather attributes that are present in the file:

  • humidity
  • solar_irradiance
  • weather_description
  • wind_bearing
  • wind_speed

The outdoor_temperature attribute was already present in both files, so it doesn't contribute to the count increase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for item_count changes in other files
rg -B 1 -A 1 '"item_count":\s*\d+'

Length of output: 8602


Script:

#!/bin/bash
# Search for weather-related attributes in anna_v4 and anna_elga_no_cooling files
rg -A 5 '"outdoor_temperature"|"humidity"|"solar_irradiance"|"weather_description"|"wind_bearing"|"wind_speed"' fixtures/anna_v4/all_data.json fixtures/anna_elga_no_cooling/all_data.json

Length of output: 1617

fixtures/anna_elga_2_schedule_off/all_data.json (2)

87-94: LGTM! Weather data structure is well-designed and consistent

The new weather object provides a comprehensive set of weather attributes with appropriate data types:

  • Temperature as float (13.0°)
  • Humidity as integer percentage (42%)
  • Wind measurements as floats (bearing: 120.0°, speed: 3.6)
  • Text description ("cloudy")
  • Solar irradiance as float (0.0)

The outdoor temperature (13.0°) correctly matches the OpenTherm sensor reading.


101-101: LGTM! Item count increase is accurate

The increase from 63 to 68 items correctly reflects the addition of 5 new weather attributes (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed).

fixtures/anna_elga_2_cooling/all_data.json (1)

89-89: Verify temperature discrepancy between sensors

The outdoor temperature reported by the Gateway (31.0°) differs from the OpenTherm sensor reading (30.0°). While this small difference might be expected due to different measurement times or sources, it would be good to confirm this is intended behavior.

Consider documenting which temperature source should be considered authoritative for automation purposes.

fixtures/anna_heatpump_cooling/all_data.json (2)

16-23: LGTM! Weather data structure and values look valid.

The weather object contains all expected fields with appropriate data types and reasonable value ranges:

  • Humidity: 35% (0-100 range)
  • Temperature: 22.0°C (typical outdoor range)
  • Solar irradiance: 207.2 W/m² (typical daylight range)
  • Wind speed: 2.1 m/s (light breeze)
  • Wind bearing: 0.0° (valid 0-360 range)

102-102: Verify item count increase matches new weather attributes

The gateway's item_count increase from 64 to 69 (+5) correctly reflects the addition of new weather attributes (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed).

✅ Verification successful

I'm requesting these scripts to:

  1. Verify the previous item_count value to confirm the increase from 64 to 69
  2. Confirm the presence of the mentioned weather attributes in the file

This will help us validate if the review comment's assertion about the +5 increase matching the new weather attributes is correct.


Weather attributes match item count increase

The verification confirms that all 5 new weather attributes (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed) are present in the file, which matches the reported item_count increase from 64 to 69 (+5). The attributes are properly integrated into the weather object structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify consistent item_count changes across all gateway fixtures
rg -l '"item_count"' | while read -r file; do
  echo "=== $file ==="
  rg '"item_count".*(\d+)' "$file"
done

Length of output: 8636


Script:

#!/bin/bash
# Let's check the git history for the specific file to see the previous item_count value
git log -p fixtures/anna_heatpump_cooling/all_data.json | grep -A 1 -B 1 '"item_count":'

# Also let's check for weather-related attributes in this file
rg -A 1 -B 1 '"(humidity|solar_irradiance|weather_description|wind_bearing|wind_speed)"' fixtures/anna_heatpump_cooling/all_data.json

Length of output: 356

fixtures/anna_heatpump_cooling_fake_firmware/all_data.json (1)

16-23: LGTM! Weather data structure matches the non-fake firmware fixture.

The weather object maintains consistency with the previous fixture, which is appropriate for testing purposes.

tests/data/adam/adam_onoff_cooling_fake_firmware.json (1)

63-70: LGTM! Weather data structure and value correlations are valid.

The weather object:

  1. Maintains consistent structure across different gateway models
  2. Shows proper correlation between values:
    • High humidity (88%) matches clouded weather description
    • Moderate solar irradiance (208.2 W/m²) appropriate for cloudy conditions
    • Light wind speed (1.79 m/s) at 228.0° bearing
  3. Preserves the outdoor temperature value (13.4°C) from the previous sensor implementation
fixtures/anna_loria_cooling_active/all_data.json (2)

50-57: LGTM! Weather data structure looks good.

The new weather object provides a clear and comprehensive representation of weather conditions with appropriate units and value ranges.


106-106: Verify item_count increase.

The increase in item_count from 66 to 71 correctly reflects the addition of 5 new weather attributes.

fixtures/anna_loria_heating_idle/all_data.json (1)

50-57: LGTM! Consistent weather data implementation.

The weather data structure and item_count changes are consistent with the cooling_active fixture, which is correct as these are structural changes independent of the heating/cooling state.

Also applies to: 106-106

fixtures/m_anna_heatpump_idle/all_data.json (2)

16-23: LGTM! Weather data values are internally consistent.

The weather attributes show good internal consistency - the "clear" weather description aligns well with the high solar irradiance (653.6 W/m²) and temperature (28.2°C).


107-107: LGTM! Correct item_count adjustment.

The item_count increase from 67 to 72 correctly reflects the addition of 5 new weather attributes.

fixtures/m_anna_heatpump_cooling/all_data.json (2)

107-107: Verify gateway item count increment

The item_count increase from 67 to 72 (+5) matches the number of new weather attributes added (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed).


16-23: Verify weather data structure and ranges

The weather data structure looks good with all required attributes. Values are within expected ranges:

  • Temperature (28.2°C) aligns with cooling scenario
  • Humidity (42%) is within 0-100% range
  • Wind bearing (50.0°) is within 0-360° range
  • Solar irradiance (653.6) is consistent with "clear" weather
✅ Verification successful

Weather data structure and values are consistent with test fixtures

The weather data structure in fixtures/m_anna_heatpump_cooling/all_data.json follows the same schema found across all fixture files that contain weather data. The values are within reasonable ranges and consistent with other cooling scenario fixtures:

  • All required attributes (humidity, outdoor_temperature, solar_irradiance, weather_description, wind_bearing, wind_speed) are present
  • Values align with other cooling scenarios in the test fixtures (e.g., anna_heatpump_cooling_fake_firmware: 22°C, m_adam_cooling: 29.65°C)
  • The structure matches the standardized format used across the test suite
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify consistent weather data structure across all fixture files
fd -e json -x jq -r '.devices[] | select(.weather != null) | .weather | keys' {} \; | sort | uniq -c

Length of output: 3677


Script:

#!/bin/bash
# Check the weather data structure in the specific file
jq -r '.devices[] | select(.weather != null) | .weather' fixtures/m_anna_heatpump_cooling/all_data.json

# Find all files with weather data to compare structure
fd -e json -x sh -c 'echo "=== {} ==="; jq -r ".devices[] | select(.weather != null) | .weather" {}' \;

Length of output: 12812

fixtures/anna_heatpump_heating/all_data.json (1)

18-18: Verify temperature consistency between gateway and OpenTherm

There's a significant discrepancy between temperatures reported by:

  • Gateway weather: 20.2°C
  • OpenTherm sensor: 3.0°C (outdoor_air_temperature)

Please verify which temperature reading should be considered authoritative.

Also applies to: 47-47

fixtures/anna_loria_driessens/all_data.json (1)

16-23: Weather data values are internally consistent

The weather data shows good internal consistency:

  • Lower solar irradiance (97.6) aligns with "clouded" weather
  • Higher humidity (88%) is typical for cloudy conditions
  • Gateway temperature (6.81°C) closely matches OpenTherm sensor (7.5°C)
fixtures/adam_onoff_cooling_fake_firmware/all_data.json (2)

63-70: LGTM: Weather data structure is well-organized

The new weather object provides comprehensive environmental data with appropriate data types:

  • Temperature in Celsius
  • Humidity as percentage
  • Solar irradiance in W/m²
  • Wind speed in m/s
  • Wind bearing in degrees
  • Weather description as string

122-122: Verify item count increase

The item count increase from 64 to 69 (+5) correctly reflects the addition of new weather attributes (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed).

tests/data/adam/adam_plus_anna.json (1)

90-97: LGTM: Test data matches fixture format

The weather object in the test data correctly mirrors the structure from the fixtures, maintaining consistency across the codebase.

fixtures/adam_plus_anna/all_data.json (2)

90-97: LGTM: Weather data structure maintains consistency

The weather object implementation maintains consistency with other files in the codebase, using the same structure and data types.


136-136: Verify item count increase

The item count increase from 80 to 85 (+5) correctly reflects the addition of new weather attributes.

fixtures/m_adam_heating/all_data.json (1)

92-99: LGTM! Weather data structure is consistent.

The weather data structure maintains consistency with other fixtures and correctly handles negative temperatures.

tests/data/adam/adam_plus_anna_new.json (1)

176-183: LGTM! Weather data structure is consistent across test fixtures.

The weather object maintains the same structure and data types across different test scenarios, which is good for testing reliability.

fixtures/adam_plus_anna_new_regulation_off/all_data.json (2)

176-183: LGTM! Weather data structure is consistent with other fixtures.

The weather object implementation maintains consistency across all test fixtures, which is crucial for reliable testing.


296-296: Verify the updated item count.

The increase in item_count from 177 to 182 appears to correspond with the addition of new weather attributes.

fixtures/adam_plus_anna_new/all_data.json (1)

176-183: LGTM! Weather data structure is well-organized.

The new weather object provides a comprehensive and logically structured representation of weather data, with appropriate data types for each attribute.

tests/data/adam/adam_jip.json (1)

229-236: LGTM! Consistent weather data implementation.

The weather data structure maintains consistency with other fixtures while containing appropriate test values.

fixtures/m_adam_jip/all_data.json (2)

380-380: LGTM! Item count update is consistent.

The item count increase to 249 aligns with the addition of weather attributes, maintaining consistency with the schema changes.


232-239: Verify the duplicated weather data values.

The weather data values are identical to those in adam_jip.json. While this might be intentional for testing purposes, it's worth verifying.

✅ Verification successful

The script results show that the weather data in m_adam_jip/all_data.json is indeed identical to adam_jip.json, but this appears to be intentional. Looking at the broader context, we can see that files prefixed with m_ appear to be variants of their corresponding non-prefixed fixtures, likely for testing different scenarios. For example:

  • m_adam_cooling vs adam_heatpump_cooling
  • m_adam_multiple_devices_per_zone vs adam_multiple_devices_per_zone

Weather data duplication is expected in test fixtures

The identical weather data between m_adam_jip/all_data.json and adam_jip.json is intentional, as these are related test fixtures. Files prefixed with m_ appear to be variants of their base fixtures, maintaining the same weather data where appropriate for testing consistency.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Compare weather data across test fixtures
# Extract and compare weather objects
echo "Comparing weather data in test fixtures:"
for file in fixtures/*adam*/all_data.json; do
  echo "=== $file ==="
  jq -c '.. | select(.weather?) | .weather' "$file"
done

Length of output: 4657

fixtures/adam_jip/all_data.json (1)

233-240: LGTM! Weather data structure is well-organized.

The new weather object contains all essential weather metrics with appropriate value ranges. The item_count increase (from 244 to 249) correctly reflects the addition of these weather attributes.

scripts/manual_fixtures.py (1)

142-142: LGTM! Temperature values are appropriate for each mode.

The outdoor temperature values are correctly set for different scenarios:

  • Cooling mode: 29.65°C (appropriately warm)
  • Heating mode: -1.25°C (appropriately cold)
  • Anna cooling mode: 28.2°C (appropriately warm)

Also applies to: 223-223, 298-298

plugwise/common.py (1)

150-151: LGTM! Weather data counting implementation is consistent.

The implementation correctly follows the existing pattern for counting dictionary items, properly accounting for the weather dictionary itself by subtracting 1 from the total count.

tests/data/adam/adam_zone_per_device.json (1)

581-588: LGTM! Consider adding data validation for weather attributes.

The weather data structure looks good with comprehensive attributes. However, it would be beneficial to ensure the values are within expected ranges:

  • humidity: 0-100%
  • wind_bearing: 0-360 degrees
  • wind_speed: non-negative
  • solar_irradiance: non-negative
✅ Verification successful

All weather data values are within valid ranges

After analyzing the weather data across all test fixtures, I can confirm that:

  • All humidity values are between 0-100% (ranging from 35% to 91%)
  • All wind bearing values are between 0-360 degrees (ranging from 0.0° to 291.0°)
  • All wind speed values are non-negative (ranging from 1.79 to 8.2)
  • All solar irradiance values are non-negative (ranging from 0.0 to 653.6)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify weather data ranges across all test fixtures

# Search for weather data in JSON files and validate ranges
rg -U --multiline '(?s)"weather":\s*{\s*"humidity":\s*(\d+).*?"wind_bearing":\s*(\d+\.?\d*).*?"wind_speed":\s*(\d+\.?\d*).*?"solar_irradiance":\s*(\d+\.?\d*)' -g '*.json' | \
while IFS= read -r line; do
  echo "Validating weather data ranges in: $line"
  # Extract and validate values using awk
  echo "$line" | gawk '
    match($0, /"humidity":\s*(\d+)/, h) && 
    match($0, /"wind_bearing":\s*(\d+\.?\d*)/, wb) && 
    match($0, /"wind_speed":\s*(\d+\.?\d*)/, ws) && 
    match($0, /"solar_irradiance":\s*(\d+\.?\d*)/, si) {
      humidity = h[1]
      wind_bearing = wb[1]
      wind_speed = ws[1]
      solar_irradiance = si[1]
      
      if (humidity < 0 || humidity > 100) 
        print "Invalid humidity:", humidity
      if (wind_bearing < 0 || wind_bearing > 360) 
        print "Invalid wind_bearing:", wind_bearing
      if (wind_speed < 0) 
        print "Invalid wind_speed:", wind_speed
      if (solar_irradiance < 0) 
        print "Invalid solar_irradiance:", solar_irradiance
    }'
done

Length of output: 433


Script:

#!/bin/bash
# Description: Verify weather data ranges across all test files using a simpler pattern
rg -U --multiline '"weather":\s*{[^}]+}' -g '*.json' | while IFS= read -r line; do
    echo "$line" | gawk '
        match($0, /"humidity":\s*([0-9.]+)/, h) { humidity = h[1] }
        match($0, /"wind_bearing":\s*([0-9.]+)/, wb) { wind_bearing = wb[1] }
        match($0, /"wind_speed":\s*([0-9.]+)/, ws) { wind_speed = ws[1] }
        match($0, /"solar_irradiance":\s*([0-9.]+)/, si) { solar_irradiance = si[1] }
        END {
            if (humidity != "" && (humidity < 0 || humidity > 100))
                print "Invalid humidity:", humidity
            if (wind_bearing != "" && (wind_bearing < 0 || wind_bearing > 360))
                print "Invalid wind_bearing:", wind_bearing
            if (wind_speed != "" && wind_speed < 0)
                print "Invalid wind_speed:", wind_speed
            if (solar_irradiance != "" && solar_irradiance < 0)
                print "Invalid solar_irradiance:", solar_irradiance
            if (humidity == "" && wind_bearing == "" && wind_speed == "" && solar_irradiance == "")
                print "No weather data found"
            else
                print "Found values - humidity:", humidity, "wind_bearing:", wind_bearing, "wind_speed:", wind_speed, "solar_irradiance:", solar_irradiance
        }
    '
done

Length of output: 193


Script:

#!/bin/bash
# Description: Search for weather data in JSON files using simple grep
rg '"weather":' -g '*.json' -A 10 | while IFS= read -r line; do
    echo "$line" | grep -E '"(humidity|wind_bearing|wind_speed|solar_irradiance)":'
done

Length of output: 80636

tests/data/adam/adam_multiple_devices_per_zone.json (1)

584-591: LGTM! Weather data structure is consistent.

The weather data structure matches the format in other test fixtures, maintaining consistency across the test suite.

tests/test_adam.py (1)

39-39: LGTM! Entity count updates reflect new weather attributes.

The consistent increase in entity_items count (by 5) across all test methods correctly reflects the addition of new weather attributes (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed).

Also applies to: 210-210, 290-290, 328-328, 351-351, 376-376, 422-422

✅ Verification successful

Let me analyze the test files further to verify the entity count changes.


Entity count increases are consistent with the addition of 5 weather attributes

The git diff confirms that all entity_items counts in test_adam.py have been increased by exactly 5 across all test cases:

  • 177 → 182 (+5)
  • 369 → 374 (+5)
  • 497 → 502 (+5)
  • 64 → 69 (+5)
  • 80 → 85 (+5)
  • 244 → 249 (+5)

This consistent increment of 5 entities aligns perfectly with the addition of the five new weather attributes (humidity, solar_irradiance, weather_description, wind_bearing, wind_speed).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent entity count increase across test files

# Search for entity_items assertions and their values
rg 'assert self\.entity_items == \d+' tests/ | \
while IFS= read -r line; do
  echo "Found entity count in: $line"
done

Length of output: 6165


Script:

#!/bin/bash
# Get the git diff for test_adam.py to see the actual changes in entity counts
git diff origin/main -- tests/test_adam.py | grep -A 1 -B 1 "entity_items =="

Length of output: 1450

fixtures/m_adam_multiple_devices_per_zone/all_data.json (2)

575-582: LGTM! Weather data structure looks well-designed.

The new weather object provides a comprehensive set of environmental data with appropriate data types and reasonable value ranges.


590-590: LGTM! Item count update is consistent.

The increase from 369 to 374 correctly reflects the addition of 5 new weather-related fields.

fixtures/adam_zone_per_device/all_data.json (1)

581-588: Changes match the pattern from other files.

The weather object structure and item count update follow the same well-designed pattern as in fixtures/m_adam_multiple_devices_per_zone/all_data.json.

Also applies to: 596-596

fixtures/adam_multiple_devices_per_zone/all_data.json (1)

584-591: Changes match the pattern from other files.

The weather object structure and item count update follow the same well-designed pattern as in the previous files.

Also applies to: 599-599

plugwise/constants.py (1)

524-533: LGTM! Well-structured weather data class.

The WeatherData class is well-defined with appropriate types for all weather-related fields.

tests/data/adam/adam_heatpump_cooling.json (1)

309-316: LGTM! Well-structured weather data.

The weather data structure in the test fixture is consistent with the WeatherData TypedDict and contains realistic values for all fields.

fixtures/adam_heatpump_cooling/all_data.json (2)

817-817: LGTM! Item count correctly updated.

The item count increase from 497 to 502 accurately reflects the addition of the new weather attributes.


309-316: LGTM! Consider adding value range validation.

The weather data structure is well-organized and comprehensive, including all essential weather metrics. The values appear reasonable:

  • Temperature: 13.4°C (typical outdoor temperature)
  • Humidity: 88% (valid percentage)
  • Wind speed: 1.79 m/s (reasonable wind speed)
  • Wind bearing: 228.0° (valid degree range)
  • Solar irradiance: 208.2 W/m² (typical daylight value)
✅ Verification successful

Weather data structure is consistent across test fixtures

The weather data structure is consistently implemented across all test fixtures that include weather information, with values within reasonable ranges:

  • Humidity: 35-91%
  • Temperature: -1.25°C to 31°C
  • Solar irradiance: 0-653.6 W/m²
  • Wind bearing: 0-291°
  • Wind speed: 1.79-8.2 m/s
  • Weather descriptions: clear, cloudy, clouded, overcast, rain

The data in the reviewed file aligns with these ranges and follows the same structure used throughout the test fixtures.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the weather data structure is consistent across all test fixtures
fd -e json -x jq -r '.devices | .[] | select(.model == "Gateway") | .weather // empty' {}

Length of output: 8552

Comment on lines +16 to +23
"weather": {
"humidity": 88,
"outdoor_temperature": 6.81,
"solar_irradiance": 97.6,
"weather_description": "clouded",
"wind_bearing": 230.0,
"wind_speed": 4.12
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Standardize decimal precision across weather measurements

There are inconsistencies in decimal precision between different test fixtures:

  • outdoor_temperature: 6.81 vs 20.2
  • wind_speed: 4.12 vs 4.1

Standardize the decimal precision across all weather measurements to ensure consistent data representation. Consider using a fixed precision of 1 decimal place for all float values.

       "weather": {
         "humidity": 88,
-        "outdoor_temperature": 6.81,
+        "outdoor_temperature": 6.8,
         "solar_irradiance": 97.6,
         "weather_description": "clouded",
         "wind_bearing": 230.0,
-        "wind_speed": 4.12
+        "wind_speed": 4.1
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"weather": {
"humidity": 88,
"outdoor_temperature": 6.81,
"solar_irradiance": 97.6,
"weather_description": "clouded",
"wind_bearing": 230.0,
"wind_speed": 4.12
}
"weather": {
"humidity": 88,
"outdoor_temperature": 6.8,
"solar_irradiance": 97.6,
"weather_description": "clouded",
"wind_bearing": 230.0,
"wind_speed": 4.1
}

"gateway_id": "da224107914542988a88561b4452b0f6",
"heater_id": "056ee145a816487eaa69243c3280f8bf",
"item_count": 177,
"item_count": 182,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Item count in JSON file needs correction

The declared item_count of 182 in the JSON file appears to be incorrect. The actual count of scalar properties in the JSON structure is 208, and this count remains unchanged from the previous version. This suggests that either:

  • The item_count field is not meant to represent the total number of scalar properties
  • Or there's an error in the count that needs to be corrected
🔗 Analysis chain

Verify the updated item count.

The item count has been increased from 177 to 182, which aligns with the addition of new weather attributes.


Let me try a different approach to count the items correctly.


Let's try one more approach to understand the structure and count the items correctly.


Let's verify the exact item count by checking all the properties in the JSON structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the item count matches the actual number of items
# Count all unique keys in the JSON structure
jq '[.. | objects | keys[]] | unique | length' fixtures/adam_plus_anna_new/all_data.json

Length of output: 93


Script:

#!/bin/bash
# Let's check the actual structure of the JSON file first
jq 'keys' fixtures/adam_plus_anna_new/all_data.json

# Then count the total number of items in the main data array
jq '.data | length' fixtures/adam_plus_anna_new/all_data.json

Length of output: 146


Script:

#!/bin/bash
# Let's examine the actual content structure
jq '.devices | length' fixtures/adam_plus_anna_new/all_data.json

# Also check the gateway structure
jq '.gateway | keys' fixtures/adam_plus_anna_new/all_data.json

# Count all non-null values in the entire JSON structure
jq '[.. | select(. != null)] | length' fixtures/adam_plus_anna_new/all_data.json

Length of output: 339


Script:

#!/bin/bash
# Count all properties in the JSON structure
jq '[paths(scalars)] | length' fixtures/adam_plus_anna_new/all_data.json

# Also let's see the previous version's count for comparison
git show HEAD^:fixtures/adam_plus_anna_new/all_data.json | jq '[paths(scalars)] | length'

Length of output: 176

Comment thread plugwise/constants.py
Comment on lines +394 to +402
WeatherType = Literal[
"humidity",
"outdoor_temperature",
"solar_irradiance",
"weather_description",
"wind_bearing",
"wind_speed",
]
WEATHER: Final[tuple[str, ...]] = get_args(WeatherType)
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Align weather types with device measurements.

There's an inconsistency between WeatherType and DEVICE_MEASUREMENTS:

  • WeatherType has separate wind_bearing and wind_speed
  • DEVICE_MEASUREMENTS has combined wind_vector

Please align these definitions to use consistent field names.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might make sense, unless one is from the Smile and the other the HA standardised form?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CoMPaTech, indeed, if “wind_vector” is coming directly from the Smile in a combined format while “wind_bearing” and “wind_speed” follow HA’s standard naming, keeping them separate could be fine. Otherwise, if both are describing the same data from the same source, consolidating them into a consistent naming (either “wind_vector” or separate “wind_bearing”/“wind_speed”) would avoid confusion. Let me know if you prefer aligning these fields for a more uniform format, or if they should remain distinct.

Comment thread tests/test_anna.py
@CoMPaTech
Copy link
Copy Markdown
Member

I think we came across this earlier, but decided (back then) not to incorporate it as it was also just generic data from the internet (or maybe from a Core member, I don't really remember) - then again, it is provided data and as such could at least mimic what, for instance Anna, displays.

Copy link
Copy Markdown
Member

@CoMPaTech CoMPaTech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While reviewing, what do we do with outdoor_temperature if one has both? I remember we decided to opt for the physical sensor instead of the perceived one, just to be clear that should be (also) obvious to end users.

@bouwew
Copy link
Copy Markdown
Contributor Author

bouwew commented Dec 20, 2024

While reviewing, what do we do with outdoor_temperature if one has both? I remember we decided to opt for the physical sensor instead of the perceived one, just to be clear that should be (also) obvious to end users.

We solved that a long time ago by renaming it to outdoor_air_temperature. Both sensors are present when relevant.

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 20, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (be93d30) to head (9250faf).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #676   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           20        20           
  Lines         3469      3503   +34     
=========================================
+ Hits          3469      3503   +34     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugwise/helper.py (1)

801-819: LGTM with minor type hint suggestion

The implementation is clean and handles different measurement types appropriately. Consider adding a more specific return type hint:

-    ) -> float | int | str | None:
+    ) -> float | int | str | None:  # float for temp/irradiance, int for humidity, str for others
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b14d73 and 9d2bb4d.

📒 Files selected for processing (1)
  • plugwise/helper.py (5 hunks)
🔇 Additional comments (2)
plugwise/helper.py (2)

531-536: LGTM: Clean data structure initialization

The addition of the "weather" dictionary follows the existing pattern and maintains consistency with the codebase structure.


773-819: Verify weather data integration with thermostat devices

The implementation aligns with the PR objectives. Let's verify the integration:

Comment thread plugwise/helper.py
Comment on lines +773 to +803
def _get_gateway_measurements(self, entity_id: str, data: GwEntityData) -> None:
"""Adam & Anna: the Gateway weather-data is present under the Home location.

Available under the Home location.
"""
if self._is_thermostat and entity_id == self.gateway_id:
outdoor_temperature = self._object_value(
self._home_location, "outdoor_temperature"
)
if outdoor_temperature is not None:
data.update({"sensors": {"outdoor_temperature": outdoor_temperature}})
self._count += 1
if not (self._is_thermostat and entity_id == self.gateway_id):
return

def _object_value(self, obj_id: str, measurement: str) -> float | int | None:
measurements = DEVICE_MEASUREMENTS
for measurement, attrs in measurements.items():
value = self._location_value(self._home_location, measurement, attrs)
if value is not None:
if measurement == "wind_vector":
value_list: list[str] = str(value).split(",")
data["weather"]["wind_speed"] = format_measure(
value_list[0].strip("("),
getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
)
data["weather"]["wind_bearing"] = format_measure(
value_list[1].strip(")"),
getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
)
self._count += 2
else:
key = cast(WeatherType, measurement)
data["weather"][key] = value
self._count += 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider enhancing wind vector parsing robustness

While the implementation is functional, the wind vector parsing could be more robust:

  1. No validation of the value_list length before accessing indices
  2. No error handling for malformed vector strings

Consider this safer implementation:

-                    value_list: list[str] = str(value).split(",")
-                    data["weather"]["wind_speed"] = format_measure(
-                        value_list[0].strip("("),
-                        getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
-                    )
-                    data["weather"]["wind_bearing"] = format_measure(
-                        value_list[1].strip(")"),
-                        getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
-                    )
+                    try:
+                        value_list: list[str] = str(value).split(",")
+                        if len(value_list) >= 2:
+                            data["weather"]["wind_speed"] = format_measure(
+                                value_list[0].strip("("),
+                                getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
+                            )
+                            data["weather"]["wind_bearing"] = format_measure(
+                                value_list[1].strip(")"),
+                                getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
+                            )
+                            self._count += 2
+                    except (ValueError, IndexError) as err:
+                        LOGGER.warning("Failed to parse wind vector: %s", err)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def _get_gateway_measurements(self, entity_id: str, data: GwEntityData) -> None:
"""Adam & Anna: the Gateway weather-data is present under the Home location.
Available under the Home location.
"""
if self._is_thermostat and entity_id == self.gateway_id:
outdoor_temperature = self._object_value(
self._home_location, "outdoor_temperature"
)
if outdoor_temperature is not None:
data.update({"sensors": {"outdoor_temperature": outdoor_temperature}})
self._count += 1
if not (self._is_thermostat and entity_id == self.gateway_id):
return
def _object_value(self, obj_id: str, measurement: str) -> float | int | None:
measurements = DEVICE_MEASUREMENTS
for measurement, attrs in measurements.items():
value = self._location_value(self._home_location, measurement, attrs)
if value is not None:
if measurement == "wind_vector":
value_list: list[str] = str(value).split(",")
data["weather"]["wind_speed"] = format_measure(
value_list[0].strip("("),
getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
)
data["weather"]["wind_bearing"] = format_measure(
value_list[1].strip(")"),
getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
)
self._count += 2
else:
key = cast(WeatherType, measurement)
data["weather"][key] = value
self._count += 1
def _get_gateway_measurements(self, entity_id: str, data: GwEntityData) -> None:
"""Adam & Anna: the Gateway weather-data is present under the Home location.
Available under the Home location.
"""
if not (self._is_thermostat and entity_id == self.gateway_id):
return
measurements = DEVICE_MEASUREMENTS
for measurement, attrs in measurements.items():
value = self._location_value(self._home_location, measurement, attrs)
if value is not None:
if measurement == "wind_vector":
try:
value_list: list[str] = str(value).split(",")
if len(value_list) >= 2:
data["weather"]["wind_speed"] = format_measure(
value_list[0].strip("("),
getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
)
data["weather"]["wind_bearing"] = format_measure(
value_list[1].strip(")"),
getattr(attrs, ATTR_UNIT_OF_MEASUREMENT),
)
self._count += 2
except (ValueError, IndexError) as err:
LOGGER.warning("Failed to parse wind vector: %s", err)
else:
key = cast(WeatherType, measurement)
data["weather"][key] = value
self._count += 1

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
plugwise/helper.py (1)

804-822: Consider adding error handling for value conversions

While the method is well-structured, it could benefit from error handling around the value conversions, particularly for the humidity and measurement formatting operations.

Consider this safer implementation:

    def _loc_value(
        self, loc_id: str, measurement: str, attrs: DATA | UOM
    ) -> float | int | str | None:
        locator = f"./location[@id='{loc_id}']/logs/point_log[type='{measurement}']/period/measurement"
        if (found := self._domain_objects.find(locator)) is None:
            return None

        value: str = found.text
        try:
            match measurement:
                case "humidity":
                    return int(float(value))
                case "outdoor_temperature" | "solar_irradiance":
                    return format_measure(value, getattr(attrs, ATTR_UNIT_OF_MEASUREMENT))
                case _:
                    return value
+       except (ValueError, TypeError) as err:
+           LOGGER.warning("Failed to convert measurement value: %s", err)
+           return None
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d2bb4d and 6488ec9.

📒 Files selected for processing (1)
  • plugwise/helper.py (5 hunks)
🔇 Additional comments (2)
plugwise/helper.py (2)

531-536: LGTM: Clean initialization of weather data structure

The addition of the "weather" dictionary to GwEntityData follows the established pattern for data organization.


773-803: LGTM: Well-structured gateway measurements collection

The method effectively collects weather data from the gateway, with clear separation of concerns and proper entity validation.

The wind vector parsing could be more robust, as noted in a previous review comment.

@sonarqubecloud
Copy link
Copy Markdown