Add Tomorrow.io 5-day forecast reporting#45
Conversation
Fetch daily forecast from Tomorrow.io and report 6 days of weather data (today + 5 days ahead) to each sprinkler device. Gives Netro better scheduling data — e.g., skip watering today if rain forecast tomorrow. - Add fetch_forecast() and _transform_forecast_response() to TomorrowClient - Map daily aggregated fields: temperatureMax→t_max, temperatureMin→t_min, rainAccumulationSum→rain (actual daily total, not intensity), dewPointAvg→t_dew - Forecast runs on separate 60-min interval (vs 30-min realtime) - Add t_dew support to metric↔US conversion functions - Strip t_dew for v1 devices (unsupported by v1 API) - 16 new tests covering forecast transform, fetch, and dew point conversion Closes #44 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 3 minutes and 31 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR adds daily weather forecast reporting from Tomorrow.io to the Netro Sprinkler plugin, enabling multi-day irrigation scheduling decisions. It includes forecast data fetching, transformation, device reporting, unit conversion support for dew point, and comprehensive test coverage. Changes
Sequence DiagramsequenceDiagram
actor Polling as Polling Thread
participant Plugin as plugin.py
participant TomorrowClient as TomorrowClient
participant TomorrowAPI as Tomorrow.io API
participant NetroAPI as Netro API
participant Device as Sprinkler Device
loop On Schedule
Polling->>Plugin: concurrent polling tick
Plugin->>Plugin: _update_forecast_from_tomorrow()
Plugin->>Plugin: schedule next run (_next_forecast_update)
Plugin->>TomorrowClient: fetch_forecast()
TomorrowClient->>TomorrowAPI: GET /v4/weather/forecast?timesteps=1d
TomorrowAPI-->>TomorrowClient: daily forecast data
TomorrowClient->>TomorrowClient: _transform_forecast_response()
TomorrowClient-->>Plugin: List[Dict] (transformed daily weather)
loop for each enabled device
Plugin->>Plugin: convert units for Netro v1 (remove t_dew)
Plugin->>NetroAPI: api_client.report_weather(date, weather_dict)
NetroAPI-->>Plugin: status=OK
Plugin->>Device: weather recorded
end
Plugin-->>Polling: forecast update complete
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~65 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Netro` Sprinklers.indigoPlugin/Contents/Info.plist:
- Around line 5-6: The PluginVersion value "2026.3.0" is already used as a git
tag and must be bumped to a unique, unused version; update the
<key>PluginVersion</key> entry by changing the <string> value to a new semantic
version (e.g., "2026.3.1" or the next appropriate patch/minor) that does not
already exist in tags, commit the change, and retry CI so the version check
passes.
In `@Netro` Sprinklers.indigoPlugin/Contents/Server Plugin/tomorrow_client.py:
- Around line 309-318: Limit the transformed forecast to six days by slicing the
parsed timelines.daily list before iteration: after extracting daily =
data["timelines"]["daily"], replace the unbounded loop over daily with a slice
like daily = daily[:6] (or equivalent) so the for day in daily loop only
processes today +5 days; update the forecasts-building logic that populates
forecasts accordingly and add a regression test that supplies a timelines.daily
array longer than six entries to verify only six are emitted.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3fa57be2-e09e-4418-b416-ae2232650d31
📒 Files selected for processing (6)
Netro Sprinklers.indigoPlugin/Contents/Info.plistNetro Sprinklers.indigoPlugin/Contents/Server Plugin/plugin.pyNetro Sprinklers.indigoPlugin/Contents/Server Plugin/tomorrow_client.pyNetro Sprinklers.indigoPlugin/Contents/Server Plugin/utils.pytests/test_tomorrow_client.pytests/test_weather_integration.py
| <key>PluginVersion</key> | ||
| <string>2026.2.0</string> | ||
| <string>2026.3.0</string> |
There was a problem hiding this comment.
Use a new, unused plugin version.
CI is already failing because 2026.3.0 exists as a git tag, so this release cannot pass the version check as written. Please bump PluginVersion to a unique value before merge.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Netro` Sprinklers.indigoPlugin/Contents/Info.plist around lines 5 - 6, The
PluginVersion value "2026.3.0" is already used as a git tag and must be bumped
to a unique, unused version; update the <key>PluginVersion</key> entry by
changing the <string> value to a new semantic version (e.g., "2026.3.1" or the
next appropriate patch/minor) that does not already exist in tags, commit the
change, and retry CI so the version check passes.
| try: | ||
| daily = data["timelines"]["daily"] | ||
| except (KeyError, TypeError): | ||
| self.logger.error( | ||
| "Unexpected Tomorrow.io forecast structure - missing timelines.daily" | ||
| ) | ||
| return None | ||
|
|
||
| forecasts = [] | ||
| for day in daily: |
There was a problem hiding this comment.
Cap the transformed forecast to six days.
This currently processes every entry in timelines.daily, but the feature contract and token-budget math assume today + 5 days only. If Tomorrow.io returns a longer daily horizon, we'll over-report to Netro and may send dates beyond the supported window. Please slice the daily list before iterating and add a regression test for responses longer than six days.
Proposed fix
- daily = data["timelines"]["daily"]
+ daily = data["timelines"]["daily"][:6]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Netro` Sprinklers.indigoPlugin/Contents/Server Plugin/tomorrow_client.py
around lines 309 - 318, Limit the transformed forecast to six days by slicing
the parsed timelines.daily list before iteration: after extracting daily =
data["timelines"]["daily"], replace the unbounded loop over daily with a slice
like daily = daily[:6] (or equivalent) so the for day in daily loop only
processes today +5 days; update the forecasts-building logic that populates
forecasts accordingly and add a regression test that supplies a timelines.daily
array longer than six entries to verify only six are emitted.
- Wrap per-day forecast transform in try/except so one bad value doesn't discard all 6 days - Add missing fetch_forecast error tests (ConnectionError, Timeout, generic Exception) - Add wind override boundary test at exactly 15.0 m/s for forecast - Fix fragile ternary f-string in debug log — use explicit if/else - Update stale class docstring to mention forecasts - Fix docstrings: optional field markers, refreshWeather mentions forecast, accurate API call count, "6 days" not hardcoded - Improve summary log to say "days fetched" not imply all succeeded - Log when zero sprinkler devices found (avoids wasting API calls silently) - Clarify v1 t_dew strip comment Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
/v4/weather/forecast?timesteps=1d) and report 6 days of weather data to each sprinkler device via Netro'sreport_weatherAPIrainAccumulationSum) instead of point-in-time intensityt_max,t_min,t_dewfields not available from realtime endpointFORECAST_UPDATE_INTERVAL_MINUTESconstant)Field mapping
temperatureAvgttemperatureMaxt_maxtemperatureMint_mindewPointAvgt_dewweatherCodeMaxconditionhumidityAvghumidityrainAccumulationSumrainprecipitationProbabilityMaxrain_probwindSpeedAvgwind_speedpressureSurfaceLevelAvgpressureToken budget
Test plan
Closes #44
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores