├── .github ├── CONTRIBUTING.md └── workflows │ ├── dart.yml │ └── publish.yml ├── .gitignore ├── .pubignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── _collect_arguments.js ├── analysis_options.yaml ├── example └── main.dart ├── lib ├── open_meteo.dart └── src │ ├── api.dart │ ├── apis │ ├── air_quality.dart │ ├── climate.dart │ ├── elevation.dart │ ├── ensemble.dart │ ├── flood.dart │ ├── geocoding.dart │ ├── historical.dart │ ├── marine.dart │ ├── satellite_radiation.dart │ └── weather.dart │ ├── enums │ ├── air_quality.dart │ ├── climate.dart │ ├── ensemble.dart │ ├── flood.dart │ ├── historical.dart │ ├── marine.dart │ ├── satellite_radiation.dart │ └── weather.dart │ ├── exceptions.dart │ ├── flatbuffer_web_combat.dart │ ├── model_export.dart │ ├── options.dart │ ├── response.dart │ └── weather_api_openmeteo_sdk_generated.dart ├── pubspec.yaml ├── test ├── air_quality_api_test.dart ├── climate_api_test.dart ├── elevation_api_test.dart ├── ensemble_api_test.dart ├── flood_api_test.dart ├── geocoding_api_test.dart ├── historical_api_test.dart ├── marine_api_test.dart ├── satellite_radiation_api_test.dart └── weather_api_test.dart └── weather_api.fbs /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | To keep things simple: 4 | - Pull requests are welcomed, you don't have to open any issue to make a pull request. 5 | - Before opening an issue, it must be something about the package. Do not ask the developers how to do something. 6 | -------------------------------------------------------------------------------- /.github/workflows/dart.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: Dart 7 | 8 | on: 9 | push: 10 | branches: [ "main" ] 11 | pull_request: 12 | branches: [ "main" ] 13 | 14 | jobs: 15 | test: 16 | if: "startsWith(github.event.head_commit.message, '`!`')" 17 | runs-on: ubuntu-latest 18 | continue-on-error: true 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | # Note: This workflow uses the latest stable version of the Dart SDK. 24 | # You can specify other versions if desired, see documentation here: 25 | # https://github.com/dart-lang/setup-dart/blob/main/README.md 26 | # - uses: dart-lang/setup-dart@v1 27 | - uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603 28 | 29 | - name: Install dependencies 30 | run: dart pub get 31 | 32 | - name: Verify formatting 33 | run: dart format --output=none --set-exit-if-changed . 34 | 35 | - name: Analyze project source 36 | run: dart analyze --fatal-infos 37 | 38 | - name: Run tests 39 | run: dart test 40 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to pub.dev 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v[0-9]+.[0-9]+.[0-9]+*' 7 | 8 | jobs: 9 | publish: 10 | permissions: 11 | id-token: write # Required for authentication using OIDC 12 | uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1 13 | # with: 14 | # working-directory: path/to/package/within/repository 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | build/ 7 | 8 | # Directory created by dartdoc 9 | # If you don't generate documentation locally you can remove this line. 10 | doc/api/ 11 | 12 | # Avoid committing generated Javascript files: 13 | *.dart.js 14 | *.info.json # Produced by the --dump-info flag. 15 | *.js # When generated by dart2js. Don't specify *.js if your 16 | # project includes source files written in JavaScript. 17 | *.js_ 18 | *.js.deps 19 | *.js.map 20 | 21 | # Don't include pubspec.lock in a library 22 | pubspec.lock 23 | 24 | # Ignore generated dart files 25 | *.*.dart 26 | -------------------------------------------------------------------------------- /.pubignore: -------------------------------------------------------------------------------- 1 | _collect_arguments.js 2 | _generated_dart_enums.zip 3 | weather_api.fbs -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.1 2 | 3 | * Initalize package. 4 | 5 | ## 0.0.2 6 | 7 | * Fix some problem 8 | 9 | ## 0.0.3 10 | 11 | * Updated README.md and Dependencies 12 | 13 | ## 0.0.4 14 | 15 | * Updated README.md and Dependencies 16 | 17 | ## 0.0.5 18 | 19 | * Added example 20 | 21 | ## 0.0.6 22 | 23 | * Added Geocoding API, document 24 | 25 | ## 0.0.7 26 | 27 | * Edit elements 28 | 29 | ## 0.0.8 30 | 31 | * Split Geocoding API to another code file 32 | 33 | ## 0.0.9 34 | 35 | * Added new UV options on Daily class 36 | 37 | ## 0.0.10 38 | 39 | * Updated packages. Revising the package. 40 | 41 | ## 0.1.0 42 | 43 | * Rework the code, port current implementation to enum for readability and usability. 44 | 45 | ## 0.1.1 46 | 47 | * Update README. 48 | 49 | ## 0.1.2 50 | 51 | * Fix typos 52 | 53 | ## 0.1.3 54 | 55 | * Add instructions to generator.js 56 | 57 | ## 0.1.4 58 | 59 | * Edit the project's scope 60 | 61 | ## 1.0.0 62 | 63 | * Breaking changes: This version changes how it organizes classes and introduce to lots of new features, all projects depends on this are now unable to update to this version without some changes to the code base. 64 | * Added all features available in Open-Meteo API. Some are still limited. 65 | * Fix bug & improve performace. 66 | * Added custom API URL & checking. 67 | 68 | ## 1.0.1 69 | 70 | * Edit name to fit the context. 71 | 72 | ## 1.0.3 73 | 74 | * Fix enum usage. 75 | 76 | ## 1.0.5 77 | 78 | * Adding documentation... 79 | 80 | ## 1.0.6 81 | 82 | * Fixed issue #1 where the values are flipped in the location's name in Search API. 83 | 84 | ## 1.0.7 85 | 86 | * Remove unnecessary dev dependencies, allowing Dart without Flutter to work. 87 | 88 | ## 1.0.8 89 | 90 | * Merge pull request #2 from alvaroarino/main 91 | * Missing "&" on hourly params 92 | 93 | ## 1.1.0 94 | 95 | * Now support typing using .request() method. 96 | * Patch up many small mistakes. 97 | * Introduce unit testing. 98 | * TODO: Integrate transform generator. 99 | 100 | ## 2.0.0 101 | 102 | * [BREAKING] Update API class interaction. All projects that depend on this package are now unable to update to this version without some changes to the implementation. 103 | * Each API now have its own set of parameter enums. 104 | * Added `copyWith` constructor method to allow overriding settings. 105 | * Change `Geocoding` and `Elevation` interaction for consistency. 106 | 107 | ## 2.0.1 108 | 109 | * Fix oversight where the packages only collects the `values` and ignore `valuesInt64`. 110 | 111 | ## 2.0.2-dev.1 112 | 113 | * Introduce `minutely15` to `WeatherApi`. 114 | * Update FlatBuffer's generated schema file. 115 | 116 | ## 2.0.2 117 | 118 | * Push changes back to release version. 119 | 120 | ## 2.0.3 121 | 122 | * Update known issues. 123 | 124 | ## 2.0.4 125 | 126 | * Update new variables. 127 | * Change the underlaying generating process for enums. 128 | 129 | ## 2.0.5 130 | 131 | * New Satellite Radiation API dropped. 132 | 133 | ## 2.1.5 134 | 135 | * Implements a patch for flatbuffer's Int64 class to support web platform. 136 | * Adds an optional `userAgent` value to all Apis. 137 | 138 | ## 2.1.6 139 | 140 | * Minor fixes to the enum. 141 | 142 | ## 2.1.7 143 | 144 | * Add model parameter for weather forcast api. 145 | 146 | ## 2.1.8 147 | 148 | * Fix some typos 149 | 150 | ## 3.0.0 151 | 152 | * Add support for multiple segmented response from open-meteo. 153 | * Add multiple locations input. 154 | * Add a method to override the generated URL before sending. 155 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Neurs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open-Meteo API SDK 2 | A free, silly, all-in-one API SDK to forecast weather, air quality, climate change, and many more by OpenMeteo with full typed support! 3 | 4 | All features from the [Open-Meteo API](https://open-meteo.com/en/features) have been implemented (some are limited). 5 | Be sure to read Open Meteo's [Terms of Use](https://open-meteo.com/en/terms/) before using this package in your project. 6 | 7 | - [Community highlights](#community-highlights) 8 | - [Usage & Docs](#usage--docs) 9 | - [Migration Guide](#migration-guide) 10 | - [Top Contributors](#top-contributors) 11 | 12 | > [!NOTE] 13 | > The package's updates and patches are now issue based. Meaning I won't work on the package's new features or fixes unless someone opens an issue, as I've moved on from flutter development for a good while now. 14 | > 15 | > If the feature requested or the bug is too big and takes a lot of time, I probably won't do it, sorry. 16 | > 17 | > I'll try my best to review your pull request though! It will be much appreciated. 18 | 19 | ## Community highlights 20 | A fun little spot to showcase some cool projects that people made from this package! I'll check the `Dependency graph` to find your project. So be sure to enable that feature in your repository. Otherwise I won't find it. 21 | 22 | ## Usage & Docs 23 | Each of the ~nine~ **ten** features available in Open-Meteo is represented by its class: `WeatherApi`, `HistoricalApi`, `EnsembleApi`, `ClimateApi`, `MarineApi`, `AirQualityApi`, `SatelliteRadiationApi`, `GeocodingApi`, `ElevationApi` and `FloodApi`. 24 | 25 | > [!NOTE] 26 | > All inputs to the API have been adapted to Dart-friendly variables. 27 | > 28 | > Time arguments are `DateTime` objects and parameters have enum representations. 29 | 30 | > [!TIP] 31 | > In each API, there are two main methods: 32 | > 33 | > - `request` uses FlatBuffer under the hood for the best performance and low overhead. Returns a Dart object and let you query information with type safety, and throws an exception if the API returns an error response, recommended for most use cases. 34 | > 35 | > - `requestJson` returns a JSON map, containing either the data or the raw error response. This method exists solely for debugging purposes. Server JSON encoding on a large amount of data is not feasible and could cause a heavy load on a free service, so pls try not to use it :) 36 | 37 | > [!CAUTION] 38 | > This is optional, but if you can, please also provide `userAgent` to the Apis. This can allow the folks at open-meteo to get a metric on how's your app doing. 39 | > 40 | > Using the default headers from the package makes your app's usage got mixed with other apps, so you might be limited even though you did nothing. 41 | 42 | For example, to get the hourly temperature in Celsius in Vietnam, 2 meters above sea level using `WeatherApi`, and only get information from `2025-10-01` to `2025-10-06`: 43 | 44 | ```dart 45 | import 'package:open_meteo/open_meteo.dart'; 46 | 47 | void main() async { 48 | final weather = WeatherApi( 49 | userAgent: "My-Flutter-App", 50 | temperatureUnit: TemperatureUnit.celsius, 51 | ); 52 | final response = await weather.request( 53 | locations: { 54 | OpenMeteoLocation( 55 | latitude: 16.16667, 56 | longitude: 107.83333, 57 | startDate: DateTime(2025, 10, 1), 58 | endDate: DateTime(2025, 10, 6), 59 | ) 60 | }, 61 | hourly: {WeatherHourly.temperature_2m}, 62 | ); 63 | final data = response.segments[0].hourlyData[WeatherHourly.temperature_2m]!; 64 | final temperatures = data.values; 65 | 66 | print(temperatures); 67 | } 68 | ``` 69 | 70 | In this example, the result is a `Map`: 71 | ``` 72 | { 73 | 2025-10-01 00:00:00.000: 19.502498626708984, 74 | 2025-10-01 01:00:00.000: 19.202499389648438, 75 | ..., 76 | 2025-10-06 22:00:00.000: 20.10249900817871, 77 | 2025-10-06 23:00:00.000: 19.552499771118164, 78 | } 79 | ``` 80 | 81 | To get the hourly temperature in Celsius in Vietnam and Berlin, 2 meters above sea level using `WeatherApi`, and only get information from `2025-10-01` to `2025-10-06`: 82 | 83 | ```dart 84 | import 'package:open_meteo/open_meteo.dart'; 85 | 86 | void main() async { 87 | final weather = WeatherApi( 88 | userAgent: "My-Flutter-App", 89 | temperatureUnit: TemperatureUnit.celsius, 90 | ); 91 | final response = await weather.request( 92 | locations: { 93 | OpenMeteoLocation( 94 | latitude: 16.16667, 95 | longitude: 107.83333, 96 | startDate: DateTime(2025, 10, 1), 97 | endDate: DateTime(2025, 10, 6), 98 | ), 99 | OpenMeteoLocation( 100 | latitude: 52.52, 101 | longitude: 13.41, 102 | startDate: DateTime(2025, 10, 1), 103 | endDate: DateTime(2025, 10, 6), 104 | ), 105 | }, 106 | hourly: {WeatherHourly.temperature_2m}, 107 | ); 108 | final vnData = response.segments[0].hourlyData[WeatherHourly.temperature_2m]!; 109 | final vnTemperatures = vnData.values; 110 | print("Vietnam's temperature:"); 111 | print(vnTemperatures); 112 | 113 | final blData = response.segments[1].hourlyData[WeatherHourly.temperature_2m]!; 114 | final blTemperatures = blData.values; 115 | print("Berlin's temperature:"); 116 | print(blTemperatures); 117 | } 118 | ``` 119 | 120 | In this example, the result is two `Map`, its position is accordance to the elements in `locations` passed: 121 | ``` 122 | Vietnam's temperature: 123 | { 124 | 2025-10-01 00:00:00.000: 19.502498626708984, 125 | 2025-10-01 01:00:00.000: 19.202499389648438, 126 | ..., 127 | 2025-10-06 22:00:00.000: 20.10249900817871, 128 | 2025-10-06 23:00:00.000: 19.552499771118164 129 | } 130 | Berlin's temperature: 131 | { 132 | 2025-10-01 05:00:00.000: 8.845499992370605, 133 | 2025-10-01 06:00:00.000: 8.245499610900879, 134 | ..., 135 | 2025-10-07 03:00:00.000: 11.795499801635742, 136 | 2025-10-07 04:00:00.000: 11.245499610900879 137 | } 138 | ``` 139 | 140 | > [!NOTE] 141 | > The `Geocoding` and `Elevation` are the two exceptions as they only have `requestJson` method available, the upstream API doesn't implement FlatBuffers. 142 | 143 | ```dart 144 | var result = await GeocodingApi().requestJson(name: "London"); 145 | ``` 146 | ```dart 147 | var result = await ElevationApi().requestJson(latitudes: [16.16667], longitudes: [107.83333]); 148 | ``` 149 | 150 | ## Migration Guide 151 | 152 | Version `3.x.x` comes with multiple segmented response support. 153 | 154 | You can now get multiple models with just one request call. 155 | 156 | Now in each API type; `latitude`, `longitude`, `elevation`, `startDate`, `endDate` is no longer available. Instead, the package moves all of them to a new class called `OpenMeteoLocation`. You can now pass multiple locations to a single `request` call! 157 | 158 | If you are using models, every single models across all APIs now belongs in an enum called `OpenMeteoModel`. 159 | 160 | Initialize and call request: 161 | ```dart 162 | // 1.x.x 163 | var weather = Weather( 164 | latitude: 16.16667, 165 | longitude: 107.83333, 166 | temperature_unit: TemperatureUnit.celsius 167 | ); 168 | await weather.request(hourly: [Hourly.temperature_2m]); 169 | 170 | // 2.x.x 171 | final weather = WeatherApi(temperatureUnit: TemperatureUnit.celsius); 172 | final response = await weather.request( 173 | latitude: 16.16667, 174 | longitude: 107.83333, 175 | hourly: {WeatherHourly.temperature_2m}, 176 | ); 177 | 178 | // 3.x.x 179 | final weather = WeatherApi(temperatureUnit: TemperatureUnit.celsius); 180 | final response = await weather.request( 181 | locations: { 182 | OpenMeteoLocation(latitude: 16.16667, longitude: 107.83333), 183 | }, 184 | hourly: {WeatherHourly.temperature_2m}, 185 | ); 186 | 187 | // 3.x.x exclusive feature: 188 | final weather = WeatherApi(temperatureUnit: TemperatureUnit.celsius); 189 | final response = await weather.request( 190 | locations: { 191 | OpenMeteoLocation(latitude: 16.16667, longitude: 107.83333), 192 | OpenMeteoLocation(latitude: 52.52, longitude: 13.41), 193 | }, 194 | hourly: {WeatherHourly.temperature_2m}, 195 | ); 196 | ``` 197 | 198 | Get a single result from a single segmented response: 199 | ```dart 200 | // 1.x.x & 2.x.x 201 | response.hourlyData[WeatherHourly.temperature_2m]!; 202 | 203 | // 3.x.x 204 | response.segments[0].hourlyData[WeatherHourly.temperature_2m]!; 205 | ``` 206 | 207 | Get multiple results from a multiple segmented response: 208 | ```dart 209 | // 1.x.x & 2.x.x 210 | // Not supported, requires multiple calls. 211 | 212 | // 3.x.x 213 | response.segments[0].hourlyData[WeatherHourly.temperature_2m]!; 214 | response.segments[1].hourlyData[WeatherHourly.temperature_2m]!; 215 | response.segments[...].hourlyData[WeatherHourly.temperature_2m]!; 216 | ``` 217 | 218 | ## Top Contributors 219 | 220 | 221 | 228 | 229 |
222 | 223 |
224 | MathNerd28 225 |
226 | 🛠️ | 💛 v1.1.0 - v2 227 |
230 | 231 | ## Issues & Pull requests 232 | Before reporting an issue, please check Open-Meteo's docs to make sure you're calling the correct endpoint with the correct arguments. 233 | 234 | There's a method to check the URL that the package generated to send the request: 235 | ```dart 236 | final weather = WeatherApi(); 237 | final response = await weather.request( 238 | locations: { 239 | OpenMeteoLocation(latitude: 16.16667, longitude: 107.83333), 240 | }, 241 | hourly: {WeatherHourly.temperature_2m}, 242 | ); 243 | 244 | print(response.urlUsed); // https://api.open-meteo.com/v1/forecast?latitude=16.16667&longitude=107.83333&hourly=temperature_2m&timeformat=unixtime&timezone=auto&format=flatbuffers 245 | ``` 246 | 247 | Contributions are welcomed! 248 | -------------------------------------------------------------------------------- /_collect_arguments.js: -------------------------------------------------------------------------------- 1 | // An invasive script to inject the open-meteo docs to capture all available variables. 2 | // This script also will generate an archive containing enum files of each type of API. 3 | // This script only works once, reload the page to parse the page again. 4 | 5 | const collectedData = { 6 | pages: {} 7 | }; 8 | 9 | const replacements = { 10 | 'pm2_5': 'pm2p5', 11 | 'windspeed': 'wind_speed', 12 | 'winddirection': 'wind_direction', 13 | }; 14 | 15 | const defaultValue = '$default$'; 16 | 17 | const staticSuffixes = { 18 | 'aggregation': { 19 | 'defaultValue': 'Aggregation.none', 20 | '_max': 'Aggregation.maximum', 21 | '_min': 'Aggregation.minimum', 22 | '_mean': 'Aggregation.mean', 23 | '_median': 'Aggregation.median', 24 | '_sum': 'Aggregation.sum', 25 | '_dominant': 'Aggregation.dominant', 26 | '_p10': 'Aggregation.p10', 27 | '_p25': 'Aggregation.p25', 28 | '_p75': 'Aggregation.p75', 29 | '_p90': 'Aggregation.p90', 30 | '_spread': 'Aggregation.spread', 31 | } 32 | }; 33 | 34 | const regexSuffixes = { 35 | 'altitude': /\_(\d+)m$/, 36 | 'depth,depthTo': /\_(\d+)_to_(\d+)cm$/, 37 | 'depth': /\_(\d+)cm$/, 38 | 'pressureLevel': /\_(\d+)hPa/, 39 | }; 40 | 41 | // JS port of the tranform algorithm by MathNerd28. 42 | // https://github.com/MathNerd28 43 | 44 | function buildIndex(inputs) { 45 | const index = {}; 46 | for (const input of inputs) { 47 | const properties = {}; 48 | const root = computeRoot(input, properties); 49 | if (!index[root]) { 50 | index[root] = {}; 51 | } 52 | index[root][input] = properties; 53 | } 54 | return index; 55 | } 56 | 57 | function computeRoot(root, properties) { 58 | // Check static suffixes 59 | for (const [suffixGroupKey, suffixGroupValue] of Object.entries(staticSuffixes)) { 60 | if (properties.hasOwnProperty(suffixGroupKey)) continue; 61 | for (const [suffixKey, suffixValue] of Object.entries(suffixGroupValue)) { 62 | if (!root.endsWith(suffixKey)) continue; 63 | properties[suffixGroupKey] = suffixValue; 64 | return computeRoot(root.substring(0, root.length - suffixKey.length), properties); 65 | } 66 | } 67 | 68 | // Check regex suffixes 69 | for (const [regexSuffixKey, regexSuffixValue] of Object.entries(regexSuffixes)) { 70 | if (properties.hasOwnProperty(regexSuffixKey)) continue; 71 | const match = regexSuffixValue.exec(root); 72 | if (match === null) continue; 73 | const captures = match.slice(1); 74 | properties[regexSuffixKey] = `(${captures.join(',')})`; 75 | return computeRoot(root.substring(0, match.index), properties); 76 | } 77 | 78 | // Apply replacements 79 | for (const [replacementKey, replacementValue] of Object.entries(replacements)) { 80 | root = root.replace(new RegExp(replacementKey, 'g'), replacementValue); 81 | } 82 | 83 | if (root === 'apparent_temperature' && !properties.hasOwnProperty('altitude')) { 84 | properties['altitude'] = '(2)'; 85 | } 86 | 87 | return root; 88 | } 89 | 90 | function decodeBuild(index) { 91 | let decodeOutput = ""; 92 | for (const [titleKey, titleValue] of Object.entries(index)) { 93 | for (const [childKey, childValue] of Object.entries(titleValue)) { 94 | if (Object.keys(childValue).length === 0) { 95 | decodeOutput += `${childKey}(Variable.${childKey},),`; 96 | continue; 97 | } 98 | 99 | for (const [valueKey, valueValue] of Object.entries(childValue)) { 100 | const extract = valueValue.replace(/[\(\)]/g, "").split(","); 101 | if (valueKey === 'depth,depthTo') { 102 | decodeOutput += `${childKey}(Variable.${titleKey}, depth: ${extract[0]}, depthTo: ${extract[1]},),`; 103 | continue; 104 | } 105 | decodeOutput += `${childKey}(Variable.${titleKey}, ${valueKey}: ${extract[0]},),`; 106 | } 107 | } 108 | } 109 | return decodeOutput; 110 | } 111 | 112 | function analyzeVariableProperties(variables) { 113 | const usedProperties = new Set(); 114 | 115 | for (const variable of variables) { 116 | const properties = {}; 117 | computeRoot(variable, properties); 118 | 119 | for (const key of Object.keys(properties)) { 120 | if (key === 'depth,depthTo') { 121 | usedProperties.add('depth'); 122 | usedProperties.add('depthTo'); 123 | } else { 124 | usedProperties.add(key); 125 | } 126 | } 127 | } 128 | 129 | return usedProperties; 130 | } 131 | 132 | function generateEnumOutput(pageKey, variableType, variables) { 133 | const suffix = { 134 | 'hourly': 'Hourly', 135 | 'daily': 'Daily', 136 | 'current': 'Current', 137 | 'minutely15': 'Minutely15' 138 | }[variableType] || variableType; 139 | 140 | const enumName = `${pageKey}${suffix}`; 141 | const variableArray = [...variables]; 142 | 143 | const apiTypeMap = { 144 | 'Weather': 'WeatherApi', 145 | 'Historical': 'HistoricalApi', 146 | 'Ensemble': 'EnsembleApi', 147 | 'Climate': 'ClimateApi', 148 | 'Marine': 'MarineApi', 149 | 'AirQuality': 'AirQualityApi', 150 | 'Flood': 'FloodApi' 151 | }; 152 | 153 | const timeTypeMap = { 154 | 'hourly': 'Hourly', 155 | 'daily': 'Daily', 156 | 'current': 'Current', 157 | 'minutely15': 'Minutely15' 158 | }; 159 | 160 | const apiClass = apiTypeMap[pageKey]; 161 | const timeClass = timeTypeMap[variableType]; 162 | 163 | const usedProperties = analyzeVariableProperties(variableArray); 164 | 165 | let output = `enum ${enumName} with Parameter<${apiClass}, ${timeClass}> {\n`; 166 | 167 | for (const variable of variableArray) { 168 | const properties = {}; 169 | const root = computeRoot(variable, properties); 170 | 171 | const enumValue = variable.replace(/[^a-zA-Z0-9_]/g, '_'); 172 | 173 | let constructorCall = `Variable.${root}`; 174 | 175 | const params = []; 176 | for (const [key, value] of Object.entries(properties)) { 177 | if (key === 'depth,depthTo') { 178 | const extract = value.replace(/[\(\)]/g, "").split(","); 179 | params.push(`depth: ${extract[0]}`); 180 | params.push(`depthTo: ${extract[1]}`); 181 | } else { 182 | const extract = value.replace(/[\(\)]/g, "").split(","); 183 | params.push(`${key}: ${extract[0]}`); 184 | } 185 | } 186 | 187 | if (params.length === 0) { 188 | output += ` ${enumValue}(\n ${constructorCall},\n ),\n`; 189 | } else { 190 | output += ` ${enumValue}(\n ${constructorCall},\n`; 191 | for (const param of params) { 192 | output += ` ${param},\n`; 193 | } 194 | output += ` ),\n`; 195 | } 196 | } 197 | 198 | output += `;\n\n`; 199 | 200 | output += ` @override\n final Variable variable;\n`; 201 | 202 | const allPossibleProperties = ['altitude', 'depth', 'depthTo', 'pressureLevel', 'aggregation']; 203 | const dynamicProperties = allPossibleProperties.filter(prop => usedProperties.has(prop)); 204 | 205 | for (const prop of dynamicProperties) { 206 | if (prop === 'aggregation') { 207 | output += ` @override\n final Aggregation ${prop};\n`; 208 | } else { 209 | output += ` @override\n final int ${prop};\n`; 210 | } 211 | } 212 | 213 | if (dynamicProperties.length > 0) { 214 | output += ` const ${enumName}(\n this.variable, {\n`; 215 | 216 | for (const prop of dynamicProperties) { 217 | if (prop === 'aggregation') { 218 | output += ` this.${prop} = Aggregation.none,\n`; 219 | } else { 220 | output += ` this.${prop} = 0,\n`; 221 | } 222 | } 223 | 224 | output += ` });\n\n`; 225 | } else { 226 | output += ` const ${enumName}(\n this.variable\n );\n\n`; 227 | } 228 | 229 | output += ` static final Map hashes =\n makeHashes(${enumName}.values);\n`; 230 | 231 | output += `}\n\n`; 232 | return output; 233 | } 234 | 235 | function fetchResult(variable) { 236 | return [...variable]; 237 | } 238 | 239 | function consoleVariable(title, variables, pageKey) { 240 | if (variables.size > 0) { 241 | const variableArray = fetchResult(variables); 242 | console.log(`%c${title}:`, "color: blue"); 243 | console.log(variableArray.join(",")); 244 | 245 | if (!collectedData.pages[pageKey]) { 246 | collectedData.pages[pageKey] = {}; 247 | } 248 | collectedData.pages[pageKey][title.toLowerCase()] = variableArray; 249 | } 250 | } 251 | 252 | function collectVariables(pageKey) { 253 | const hourlyVariables = new Set(); 254 | const dailyVariables = new Set(); 255 | const currentVariables = new Set(); 256 | const minutely15Variables = new Set(); 257 | 258 | setTimeout(() => { 259 | const variables = document.getElementsByClassName("peer-disabled:cursor-not-allowed peer-disabled:opacity-70 ml-[0.42rem] cursor-pointer truncate py-[0.1rem]"); 260 | for (let i = 0; i < variables.length; i++) { 261 | const label = variables[i].getAttribute("for"); 262 | if (label.endsWith("hourly")) { 263 | hourlyVariables.add(label.slice(0, -7)); 264 | } 265 | if (label.endsWith("daily")) { 266 | dailyVariables.add(label.slice(0, -6)); 267 | } 268 | if (label.endsWith("current")) { 269 | currentVariables.add(label.slice(0, -8)); 270 | } 271 | if (label.endsWith("minutely_15")) { 272 | minutely15Variables.add(label.slice(0, -12)); 273 | } 274 | } 275 | consoleVariable("Hourly", hourlyVariables, pageKey); 276 | consoleVariable("Daily", dailyVariables, pageKey); 277 | consoleVariable("Current", currentVariables, pageKey); 278 | consoleVariable("Minutely15", minutely15Variables, pageKey); 279 | 280 | console.log(`%cCollected variables for ${pageKey}`, "color: purple; font-weight: bold"); 281 | }, 1000); 282 | } 283 | 284 | const docPages = [ 285 | { path: "/en/docs", key: "Weather" }, 286 | { path: "/en/docs/historical-weather-api", key: "Historical" }, 287 | { path: "/en/docs/ensemble-api", key: "Ensemble" }, 288 | { path: "/en/docs/climate-api", key: "Climate" }, 289 | { path: "/en/docs/marine-weather-api", key: "Marine" }, 290 | { path: "/en/docs/air-quality-api", key: "AirQuality" }, 291 | { path: "/en/docs/satellite-radiation-api", key: "Satellite" }, 292 | { path: "/en/docs/flood-api", key: "Flood" } 293 | ]; 294 | 295 | function camelToSnake(str) { 296 | return str.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, ''); 297 | } 298 | 299 | function saveCollectedData() { 300 | console.log(`%cGenerating Dart enum files...`, "color: red; font-weight: bold; font-size: 16px"); 301 | 302 | const generatedFiles = {}; 303 | 304 | for (const [pageKey, pageData] of Object.entries(collectedData.pages)) { 305 | const fileName = camelToSnake(pageKey); 306 | 307 | let fileContent = `import '../api.dart';\nimport '../apis/${fileName}.dart';\nimport '../weather_api_openmeteo_sdk_generated.dart';\n\n`; 308 | fileContent += `// Generated Variable Enums for ${pageKey}\n\n`; 309 | 310 | const timeOrder = ['minutely15', 'current', 'hourly', 'daily']; 311 | 312 | for (const variableType of timeOrder) { 313 | if (pageData[variableType] && pageData[variableType].length > 0) { 314 | fileContent += generateEnumOutput(pageKey, variableType, pageData[variableType]); 315 | } 316 | } 317 | 318 | if (fileContent.trim() !== `import '../api.dart';\nimport '../apis/${fileName}.dart';\nimport '../weather_api_openmeteo_sdk_generated.dart';\n\n// Generated Variable Enums for ${pageKey}`) { 319 | generatedFiles[`${fileName}.dart`] = fileContent; 320 | } 321 | } 322 | 323 | console.log(`%cGenerated Files:`, "color: orange; font-weight: bold; font-size: 16px"); 324 | for (const [fileName, content] of Object.entries(generatedFiles)) { 325 | console.log(`%c${fileName}:`, "color: purple; font-weight: bold"); 326 | console.log(content); 327 | } 328 | 329 | createZipFile(generatedFiles); 330 | } 331 | 332 | async function createZipFile(files) { 333 | const script = document.createElement('script'); 334 | script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js'; 335 | document.head.appendChild(script); 336 | 337 | script.onload = async () => { 338 | const zip = new JSZip(); 339 | for (const [fileName, content] of Object.entries(files)) { 340 | zip.file(fileName, content); 341 | } 342 | 343 | const zipBlob = await zip.generateAsync({ type: 'blob' }); 344 | 345 | const zipUrl = URL.createObjectURL(zipBlob); 346 | const zipLink = document.createElement('a'); 347 | zipLink.href = zipUrl; 348 | zipLink.download = '_generated_dart_enums.zip'; 349 | document.body.appendChild(zipLink); 350 | zipLink.click(); 351 | document.body.removeChild(zipLink); 352 | URL.revokeObjectURL(zipUrl); 353 | 354 | console.log(`%cZIP file created with ${Object.keys(files).length} files!`, "color: green; font-weight: bold"); 355 | }; 356 | } 357 | 358 | for (let page = 0; page < docPages.length; page++) { 359 | setTimeout(() => { 360 | const button = document.querySelector(`a[href="${docPages[page].path}"]`); 361 | button.click(); 362 | const pageKey = docPages[page].key; 363 | console.log(`%c${button.innerText.trim()} (${pageKey})`, "color: green; font-size: 20px"); 364 | 365 | setTimeout(() => { 366 | collectVariables(pageKey); 367 | 368 | if (page === docPages.length - 1) { 369 | setTimeout(() => { 370 | saveCollectedData(); 371 | }, 2000); 372 | } 373 | }, 1000); 374 | }, 3000 * page); 375 | } 376 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | linter: 4 | rules: 5 | constant_identifier_names: false 6 | -------------------------------------------------------------------------------- /example/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | 3 | void main() async { 4 | final weather = WeatherApi( 5 | userAgent: "My-Flutter-App", 6 | temperatureUnit: TemperatureUnit.celsius, 7 | ); 8 | final response = await weather.request( 9 | locations: { 10 | OpenMeteoLocation( 11 | latitude: 16.16667, 12 | longitude: 107.83333, 13 | startDate: DateTime(2025, 10, 1), 14 | endDate: DateTime(2025, 10, 6), 15 | ) 16 | }, 17 | hourly: {WeatherHourly.temperature_2m}, 18 | ); 19 | final data = response.segments[0].hourlyData[WeatherHourly.temperature_2m]!; 20 | final temperatures = data.values; 21 | 22 | print(temperatures); 23 | } 24 | -------------------------------------------------------------------------------- /lib/open_meteo.dart: -------------------------------------------------------------------------------- 1 | export 'src/apis/air_quality.dart'; 2 | export 'src/apis/climate.dart'; 3 | export 'src/apis/elevation.dart'; 4 | export 'src/apis/ensemble.dart'; 5 | export 'src/apis/flood.dart'; 6 | export 'src/apis/geocoding.dart'; 7 | export 'src/apis/historical.dart'; 8 | export 'src/apis/marine.dart'; 9 | export 'src/apis/satellite_radiation.dart'; 10 | export 'src/apis/weather.dart'; 11 | export 'src/enums/air_quality.dart'; 12 | export 'src/enums/climate.dart'; 13 | export 'src/enums/ensemble.dart'; 14 | export 'src/enums/flood.dart'; 15 | export 'src/enums/historical.dart'; 16 | export 'src/enums/marine.dart'; 17 | export 'src/enums/satellite_radiation.dart'; 18 | export 'src/enums/weather.dart'; 19 | export 'src/exceptions.dart'; 20 | export 'src/options.dart'; 21 | export 'src/response.dart'; 22 | export 'src/model_export.dart'; 23 | -------------------------------------------------------------------------------- /lib/src/api.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:http/http.dart' as http; 5 | import './options.dart'; 6 | 7 | import 'exceptions.dart'; 8 | import 'weather_api_openmeteo_sdk_generated.dart'; 9 | 10 | mixin Parameter on Enum { 11 | Variable get variable; 12 | Aggregation get aggregation => Aggregation.none; 13 | int get altitude => 0; 14 | int get pressureLevel => 0; 15 | int get depth => 0; 16 | int get depthTo => 0; 17 | 18 | int get hash => computeHash( 19 | variable: variable, 20 | altitude: altitude, 21 | aggregation: aggregation, 22 | pressureLevel: pressureLevel, 23 | depth: depth, 24 | depthTo: depthTo, 25 | ); 26 | } 27 | 28 | int computeHash({ 29 | required Variable variable, 30 | required Aggregation aggregation, 31 | required int altitude, 32 | required int pressureLevel, 33 | required int depth, 34 | required int depthTo, 35 | }) => 36 | Object.hash(variable.value, aggregation.value, altitude, pressureLevel, 37 | depth, depthTo); 38 | 39 | Map makeHashes( 40 | Iterable values, 41 | ) => 42 | {for (final val in values) val.hash: val}; 43 | 44 | sealed class TimeType {} 45 | 46 | final class Minutely15 extends TimeType {} 47 | 48 | final class Current extends TimeType {} 49 | 50 | final class Hourly extends TimeType {} 51 | 52 | final class Daily extends TimeType {} 53 | 54 | abstract class BaseApi { 55 | static final Finalizer _finalizer = Finalizer((hashCode) { 56 | _clients[hashCode]?.close(); 57 | _clients.remove(hashCode); 58 | }); 59 | 60 | final String apiUrl; 61 | final String apiKey; 62 | final String userAgent; 63 | 64 | http.Client get _client => _clients.putIfAbsent(hashCode, () { 65 | _finalizer.attach(this, hashCode); 66 | return http.Client(); 67 | }); 68 | 69 | const BaseApi({ 70 | required this.apiUrl, 71 | this.apiKey = '', 72 | this.userAgent = 73 | 'Open-meteo-dart | https://github.com/neursh/open-meteo-dart', 74 | }); 75 | } 76 | 77 | final Map _clients = {}; 78 | 79 | Future> apiRequestJson( 80 | BaseApi api, 81 | Map queryParams, 82 | Uri Function(Uri)? overrideUri, 83 | ) async { 84 | Uri url = Uri.parse(api.apiUrl).replace( 85 | query: _encodeQuery(queryParams, { 86 | 'apikey': nullIfEqual(api.apiKey, ''), 87 | }), 88 | ); 89 | 90 | if (overrideUri != null) { 91 | url = overrideUri(url); 92 | } 93 | 94 | return jsonDecode( 95 | (await api._client.get(url, headers: {"User-Agent": api.userAgent})).body, 96 | ); 97 | } 98 | 99 | Future<(Uri, Uint8List)> apiRequestFlatBuffer( 100 | BaseApi api, 101 | Map queryParams, 102 | Uri Function(Uri)? overrideUri, 103 | ) async { 104 | Uri url = Uri.parse(api.apiUrl).replace( 105 | query: _encodeQuery(queryParams, { 106 | 'apikey': nullIfEqual(api.apiKey, ''), 107 | 'format': 'flatbuffers', 108 | }), 109 | ); 110 | 111 | if (overrideUri != null) { 112 | url = overrideUri(url); 113 | } 114 | 115 | http.Response response = 116 | await api._client.get(url, headers: {"User-Agent": api.userAgent}); 117 | if (response.statusCode != 200) { 118 | throw OpenMeteoApiError(jsonDecode(response.body)['reason']); 119 | } 120 | 121 | return (url, response.bodyBytes); 122 | } 123 | 124 | // Need this because Uri.encode... replaces commas 125 | // with %2C, causing Open-Meteo to reject it 126 | String _encodeQuery( 127 | Map queryParams, [ 128 | Map overrides = const {}, 129 | ]) => 130 | queryParams.entries 131 | .followedBy(overrides.entries) 132 | .map(_convertQueryEntry) 133 | .nonNulls 134 | .map((entry) => '${entry.key}=${entry.value}') 135 | .join('&'); 136 | 137 | MapEntry? _convertQueryEntry(MapEntry entry) => 138 | switch (entry.value) { 139 | null => null, 140 | Enum v => MapEntry(entry.key, v.name), 141 | Iterable v => MapEntry(entry.key, v.map((e) => e.name).join(',')), 142 | Iterable v => 143 | MapEntry(entry.key, v.map((e) => e.toString()).join(',')), 144 | Object v => MapEntry(entry.key, v.toString()), 145 | }; 146 | 147 | String? formatDate(DateTime? date) => date?.toIso8601String().substring(0, 10); 148 | String? formatTime(DateTime? time) => time?.toIso8601String(); 149 | 150 | T? nullIfEqual(T value, T defaultValue) => 151 | value == defaultValue ? null : value; 152 | 153 | T? nullIfEmpty(T iterable) => 154 | iterable.isEmpty ? null : iterable; 155 | 156 | class ParsedLocations { 157 | final List latitude; 158 | final List longitude; 159 | final List elevation; 160 | final List startDate; 161 | final List endDate; 162 | 163 | const ParsedLocations({ 164 | required this.latitude, 165 | required this.longitude, 166 | required this.elevation, 167 | required this.startDate, 168 | required this.endDate, 169 | }); 170 | } 171 | 172 | ParsedLocations parseLocations(Set locations) { 173 | List latitude = []; 174 | List longitude = []; 175 | List elevation = []; 176 | List startDate = []; 177 | List endDate = []; 178 | 179 | for (final location in locations) { 180 | latitude.add(location.latitude); 181 | longitude.add(location.longitude); 182 | if (location.elevation != null) { 183 | elevation.add(location.elevation!); 184 | } 185 | if (location.startDate != null) { 186 | startDate.add(formatDate(location.startDate)!); 187 | } 188 | if (location.endDate != null) { 189 | endDate.add(formatDate(location.endDate)!); 190 | } 191 | } 192 | 193 | checkMalformed(List childList) { 194 | return childList.isNotEmpty && childList.length != locations.length; 195 | } 196 | 197 | if (checkMalformed(elevation) || 198 | checkMalformed(startDate) || 199 | checkMalformed(endDate)) { 200 | throw OpenMeteoApiError( 201 | "Optional parameters must have the same number of elements as coordinates.", 202 | ); 203 | } 204 | 205 | return ParsedLocations( 206 | latitude: latitude, 207 | longitude: longitude, 208 | elevation: elevation, 209 | startDate: startDate, 210 | endDate: endDate, 211 | ); 212 | } 213 | -------------------------------------------------------------------------------- /lib/src/apis/air_quality.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../enums/air_quality.dart'; 3 | import '../options.dart'; 4 | import '../response.dart'; 5 | 6 | /// Pollutants and pollen forecast in 11 km resolution. 7 | /// 8 | /// https://open-meteo.com/en/docs/air-quality-api/ 9 | class AirQualityApi extends BaseApi { 10 | final CellSelection cellSelection; 11 | final AirQualityDomains domains; 12 | const AirQualityApi({ 13 | super.apiUrl = 'https://air-quality-api.open-meteo.com/v1/air-quality', 14 | super.apiKey, 15 | super.userAgent, 16 | this.cellSelection = CellSelection.nearest, 17 | this.domains = AirQualityDomains.auto, 18 | }); 19 | 20 | AirQualityApi copyWith({ 21 | String? apiUrl, 22 | String? apiKey, 23 | String? userAgent, 24 | CellSelection? cellSelection, 25 | AirQualityDomains? domains, 26 | }) => 27 | AirQualityApi( 28 | apiUrl: apiUrl ?? this.apiUrl, 29 | apiKey: apiKey ?? this.apiKey, 30 | userAgent: userAgent ?? this.userAgent, 31 | cellSelection: cellSelection ?? this.cellSelection, 32 | domains: domains ?? this.domains, 33 | ); 34 | 35 | /// This method returns a JSON map, 36 | /// containing either the data or the raw error response. 37 | /// This method exists solely for debug purposes, do not use in production. 38 | /// Use `request()` instead. 39 | Future> requestJson({ 40 | required Set locations, 41 | Set hourly = const {}, 42 | Set current = const {}, 43 | int? pastDays, 44 | int? pastHours, 45 | int? forecastDays, 46 | int? forecastHours, 47 | DateTime? startHour, 48 | DateTime? endHour, 49 | Uri Function(Uri)? overrideUri, 50 | }) => 51 | apiRequestJson( 52 | this, 53 | _queryParamMap( 54 | locations: locations, 55 | hourly: hourly, 56 | current: current, 57 | pastDays: pastDays, 58 | pastHours: pastHours, 59 | forecastDays: forecastDays, 60 | forecastHours: forecastHours, 61 | startHour: startHour, 62 | endHour: endHour, 63 | ), 64 | overrideUri, 65 | ); 66 | 67 | /// This method returns a Dart object, 68 | /// and throws an exception if the API returns an error response, 69 | /// recommended for most use cases. 70 | Future> request({ 71 | required Set locations, 72 | Set hourly = const {}, 73 | Set current = const {}, 74 | int? pastDays, 75 | int? pastHours, 76 | int? forecastDays, 77 | int? forecastHours, 78 | DateTime? startHour, 79 | DateTime? endHour, 80 | Uri Function(Uri)? overrideUri, 81 | }) => 82 | apiRequestFlatBuffer( 83 | this, 84 | _queryParamMap( 85 | locations: locations, 86 | hourly: hourly, 87 | current: current, 88 | pastDays: pastDays, 89 | pastHours: pastHours, 90 | forecastDays: forecastDays, 91 | forecastHours: forecastHours, 92 | startHour: startHour, 93 | endHour: endHour, 94 | ), 95 | overrideUri, 96 | ).then( 97 | (data) => ApiResponse.fromFlatBuffer( 98 | data.$1, 99 | data.$2, 100 | hourlyHashes: AirQualityHourly.hashes, 101 | currentHashes: AirQualityCurrent.hashes, 102 | ), 103 | ); 104 | 105 | Map _queryParamMap({ 106 | required Set locations, 107 | required Set hourly, 108 | required Set current, 109 | required int? pastDays, 110 | required int? pastHours, 111 | required int? forecastDays, 112 | required int? forecastHours, 113 | required DateTime? startHour, 114 | required DateTime? endHour, 115 | }) { 116 | final parsedLocations = parseLocations(locations); 117 | return { 118 | 'latitude': parsedLocations.latitude, 119 | 'longitude': parsedLocations.longitude, 120 | 'elevation': nullIfEmpty(parsedLocations.elevation), 121 | 'call_selection': nullIfEqual(cellSelection, CellSelection.nearest), 122 | 'domains': nullIfEqual(domains, AirQualityDomains.auto), 123 | 'hourly': nullIfEmpty(hourly), 124 | 'current': nullIfEmpty(current), 125 | 'past_days': pastDays, 126 | 'past_hours': pastHours, 127 | 'forecast_days': forecastDays, 128 | 'forecast_hours': forecastHours, 129 | 'start_date': nullIfEmpty(parsedLocations.startDate), 130 | 'end_date': nullIfEmpty(parsedLocations.endDate), 131 | 'start_hour': formatTime(startHour), 132 | 'end_hour': formatTime(endHour), 133 | 'timeformat': 'unixtime', 134 | 'timezone': 'auto', 135 | }; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /lib/src/apis/climate.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../enums/climate.dart'; 3 | import '../options.dart'; 4 | import '../response.dart'; 5 | import '../model_export.dart'; 6 | 7 | /// Explore Climate Change on a Local Level with High-Resolution Climate Data 8 | /// 9 | /// https://open-meteo.com/en/docs/climate-api/ 10 | class ClimateApi extends BaseApi { 11 | final Set models; 12 | final TemperatureUnit temperatureUnit; 13 | final WindspeedUnit windspeedUnit; 14 | final PrecipitationUnit precipitationUnit; 15 | final CellSelection cellSelection; 16 | final bool disableBiasCorrection; 17 | 18 | const ClimateApi({ 19 | super.apiUrl = 'https://climate-api.open-meteo.com/v1/climate', 20 | super.apiKey, 21 | super.userAgent, 22 | required this.models, 23 | this.temperatureUnit = TemperatureUnit.celsius, 24 | this.windspeedUnit = WindspeedUnit.kmh, 25 | this.precipitationUnit = PrecipitationUnit.mm, 26 | this.cellSelection = CellSelection.land, 27 | this.disableBiasCorrection = false, 28 | }); 29 | 30 | ClimateApi copyWith({ 31 | String? apiUrl, 32 | String? apiKey, 33 | String? userAgent, 34 | Set? models, 35 | TemperatureUnit? temperatureUnit, 36 | WindspeedUnit? windspeedUnit, 37 | PrecipitationUnit? precipitationUnit, 38 | CellSelection? cellSelection, 39 | bool? disableBiasCorrection, 40 | }) => 41 | ClimateApi( 42 | apiUrl: apiUrl ?? this.apiUrl, 43 | apiKey: apiKey ?? this.apiKey, 44 | userAgent: userAgent ?? this.userAgent, 45 | models: models ?? this.models, 46 | temperatureUnit: temperatureUnit ?? this.temperatureUnit, 47 | windspeedUnit: windspeedUnit ?? this.windspeedUnit, 48 | precipitationUnit: precipitationUnit ?? this.precipitationUnit, 49 | cellSelection: cellSelection ?? this.cellSelection, 50 | disableBiasCorrection: 51 | disableBiasCorrection ?? this.disableBiasCorrection, 52 | ); 53 | 54 | /// This method returns a JSON map, 55 | /// containing either the data or the raw error response. 56 | /// This method exists solely for debug purposes, do not use in production. 57 | /// Use `request()` instead. 58 | Future> requestJson({ 59 | required Set locations, 60 | required Set daily, 61 | Uri Function(Uri)? overrideUri, 62 | }) => 63 | apiRequestJson( 64 | this, 65 | _queryParamMap( 66 | locations: locations, 67 | daily: daily, 68 | ), 69 | overrideUri); 70 | 71 | /// This method returns a Dart object, 72 | /// and throws an exception if the API returns an error response, 73 | /// recommended for most use cases. 74 | Future> request({ 75 | required Set locations, 76 | required Set daily, 77 | Uri Function(Uri)? overrideUri, 78 | }) => 79 | apiRequestFlatBuffer( 80 | this, 81 | _queryParamMap( 82 | locations: locations, 83 | daily: daily, 84 | ), 85 | overrideUri, 86 | ).then( 87 | (data) => ApiResponse.fromFlatBuffer( 88 | data.$1, 89 | data.$2, 90 | dailyHashes: ClimateDaily.hashes, 91 | ), 92 | ); 93 | 94 | Map _queryParamMap({ 95 | required Set locations, 96 | required Set daily, 97 | }) { 98 | final parsedLocations = parseLocations(locations); 99 | return { 100 | 'models': models, 101 | 'latitude': parsedLocations.latitude, 102 | 'longitude': parsedLocations.longitude, 103 | 'elevation': nullIfEmpty(parsedLocations.elevation), 104 | 'daily': daily, 105 | 'temperature_unit': nullIfEqual(temperatureUnit, TemperatureUnit.celsius), 106 | 'windspeed_unit': nullIfEqual(windspeedUnit, WindspeedUnit.kmh), 107 | 'precipitation_unit': 108 | nullIfEqual(precipitationUnit, PrecipitationUnit.mm), 109 | 'cell_selection': nullIfEqual(cellSelection, CellSelection.land), 110 | 'disable_bias_correction': nullIfEqual(disableBiasCorrection, false), 111 | 'start_date': nullIfEmpty(parsedLocations.startDate), 112 | 'end_date': nullIfEmpty(parsedLocations.endDate), 113 | 'timeformat': 'unixtime', 114 | 'timezone': 'auto', 115 | }; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /lib/src/apis/elevation.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | 3 | /// 90 meter resolution digital elevation model. 4 | /// 5 | /// https://open-meteo.com/en/docs/elevation-api/ 6 | class ElevationApi extends BaseApi { 7 | const ElevationApi({ 8 | super.apiUrl = 'https://api.open-meteo.com/v1/elevation', 9 | super.apiKey, 10 | super.userAgent, 11 | }); 12 | 13 | ElevationApi copyWith({ 14 | String? apiUrl, 15 | String? apiKey, 16 | String? userAgent, 17 | }) => 18 | ElevationApi( 19 | apiUrl: apiUrl ?? this.apiUrl, 20 | apiKey: apiKey ?? this.apiKey, 21 | userAgent: userAgent ?? this.userAgent, 22 | ); 23 | 24 | /// This method returns a JSON map, 25 | /// containing either the data or the raw error response. 26 | Future> requestJson({ 27 | required Set latitudes, 28 | required Set longitudes, 29 | Uri Function(Uri)? overrideUri, 30 | }) => 31 | apiRequestJson( 32 | this, 33 | { 34 | 'latitude': latitudes, 35 | 'longitude': longitudes, 36 | }, 37 | overrideUri, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/apis/ensemble.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../enums/ensemble.dart'; 3 | import '../options.dart'; 4 | import '../response.dart'; 5 | import '../model_export.dart'; 6 | 7 | /// Hundreds Of Weather Forecasts, Every time, Everywhere, All at Once. 8 | /// 9 | /// https://open-meteo.com/en/docs/ensemble-api/ 10 | class EnsembleApi extends BaseApi { 11 | final Set models; 12 | final TemperatureUnit temperatureUnit; 13 | final WindspeedUnit windspeedUnit; 14 | final PrecipitationUnit precipitationUnit; 15 | final CellSelection cellSelection; 16 | 17 | const EnsembleApi({ 18 | super.apiUrl = 'https://ensemble-api.open-meteo.com/v1/ensemble', 19 | super.apiKey, 20 | super.userAgent, 21 | required this.models, 22 | this.temperatureUnit = TemperatureUnit.celsius, 23 | this.windspeedUnit = WindspeedUnit.kmh, 24 | this.precipitationUnit = PrecipitationUnit.mm, 25 | this.cellSelection = CellSelection.land, 26 | }); 27 | 28 | EnsembleApi copyWith( 29 | String? apiUrl, 30 | String? apiKey, 31 | String? userAgent, 32 | Set? models, 33 | TemperatureUnit? temperatureUnit, 34 | WindspeedUnit? windspeedUnit, 35 | PrecipitationUnit? precipitationUnit, 36 | CellSelection? cellSelection, 37 | ) => 38 | EnsembleApi( 39 | apiUrl: apiUrl ?? this.apiUrl, 40 | apiKey: apiKey ?? this.apiKey, 41 | userAgent: userAgent ?? this.userAgent, 42 | models: models ?? this.models, 43 | temperatureUnit: temperatureUnit ?? this.temperatureUnit, 44 | windspeedUnit: windspeedUnit ?? this.windspeedUnit, 45 | precipitationUnit: precipitationUnit ?? this.precipitationUnit, 46 | cellSelection: cellSelection ?? this.cellSelection, 47 | ); 48 | 49 | /// This method returns a JSON map, 50 | /// containing either the data or the raw error response. 51 | /// This method exists solely for debug purposes, do not use in production. 52 | /// Use `request()` instead. 53 | Future> requestJson({ 54 | required Set locations, 55 | required Set hourly, 56 | int? pastDays, 57 | int? pastHours, 58 | int? pastMinutely15, 59 | int? forecastDays, 60 | int? forecastHours, 61 | int? forecastMinutely15, 62 | DateTime? startHour, 63 | DateTime? endHour, 64 | DateTime? startMinutely15, 65 | DateTime? endMinutely15, 66 | Uri Function(Uri)? overrideUri, 67 | }) => 68 | apiRequestJson( 69 | this, 70 | _queryParamMap( 71 | locations: locations, 72 | hourly: hourly, 73 | pastDays: pastDays, 74 | pastHours: pastHours, 75 | pastMinutely15: pastMinutely15, 76 | forecastDays: forecastDays, 77 | forecastHours: forecastHours, 78 | forecastMinutely15: forecastMinutely15, 79 | startHour: startHour, 80 | endHour: endHour, 81 | startMinutely15: startMinutely15, 82 | endMinutely15: endMinutely15, 83 | ), 84 | overrideUri, 85 | ); 86 | 87 | /// This method returns a Dart object, 88 | /// and throws an exception if the API returns an error response, 89 | /// recommended for most use cases. 90 | Future> request({ 91 | required Set locations, 92 | required Set hourly, 93 | int? pastDays, 94 | int? pastHours, 95 | int? pastMinutely15, 96 | int? forecastDays, 97 | int? forecastHours, 98 | int? forecastMinutely15, 99 | DateTime? startHour, 100 | DateTime? endHour, 101 | DateTime? startMinutely15, 102 | DateTime? endMinutely15, 103 | Uri Function(Uri)? overrideUri, 104 | }) => 105 | apiRequestFlatBuffer( 106 | this, 107 | _queryParamMap( 108 | locations: locations, 109 | hourly: hourly, 110 | pastDays: pastDays, 111 | pastHours: pastHours, 112 | pastMinutely15: pastMinutely15, 113 | forecastDays: forecastDays, 114 | forecastHours: forecastHours, 115 | forecastMinutely15: forecastMinutely15, 116 | startHour: startHour, 117 | endHour: endHour, 118 | startMinutely15: startMinutely15, 119 | endMinutely15: endMinutely15, 120 | ), 121 | overrideUri, 122 | ).then( 123 | (data) => ApiResponse.fromFlatBuffer( 124 | data.$1, 125 | data.$2, 126 | hourlyHashes: EnsembleHourly.hashes, 127 | ), 128 | ); 129 | 130 | Map _queryParamMap({ 131 | required Set locations, 132 | required Set hourly, 133 | required int? pastDays, 134 | required int? pastHours, 135 | required int? pastMinutely15, 136 | required int? forecastDays, 137 | required int? forecastHours, 138 | required int? forecastMinutely15, 139 | required DateTime? startHour, 140 | required DateTime? endHour, 141 | required DateTime? startMinutely15, 142 | required DateTime? endMinutely15, 143 | }) { 144 | final parsedLocations = parseLocations(locations); 145 | return { 146 | 'latitude': parsedLocations.latitude, 147 | 'longitude': parsedLocations.longitude, 148 | 'elevation': nullIfEmpty(parsedLocations.elevation), 149 | 'models': models, 150 | 'hourly': hourly, 151 | 'temperature_unit': nullIfEqual(temperatureUnit, TemperatureUnit.celsius), 152 | 'windspeed_unit': nullIfEqual(windspeedUnit, WindspeedUnit.kmh), 153 | 'precipitation_unit': 154 | nullIfEqual(precipitationUnit, PrecipitationUnit.mm), 155 | 'cell_selection': nullIfEqual(cellSelection, CellSelection.land), 156 | 'past_days': pastDays, 157 | 'past_hours': pastHours, 158 | 'past_minutely_15': pastMinutely15, 159 | 'forecast_days': forecastDays, 160 | 'forecast_hours': forecastHours, 161 | 'forecast_minutely_15': forecastMinutely15, 162 | 'start_date': nullIfEmpty(parsedLocations.startDate), 163 | 'end_date': nullIfEmpty(parsedLocations.endDate), 164 | 'start_hour': formatTime(startHour), 165 | 'end_hour': formatTime(endHour), 166 | 'start_minytely_15': formatTime(startMinutely15), 167 | 'end_minutely_15': formatTime(endMinutely15), 168 | 'timeformat': 'unixtime', 169 | 'timezone': 'auto', 170 | }; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /lib/src/apis/flood.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../enums/flood.dart'; 3 | import '../options.dart'; 4 | import '../response.dart'; 5 | 6 | /// Simulated river discharge at 5 km resolution from 1984 up to 7 months forecast. 7 | /// 8 | /// https://open-meteo.com/en/docs/flood-api/ 9 | class FloodApi extends BaseApi { 10 | final CellSelection cellSelection; 11 | final bool ensemble; 12 | 13 | const FloodApi({ 14 | super.apiUrl = 'https://flood-api.open-meteo.com/v1/flood', 15 | super.apiKey, 16 | super.userAgent, 17 | this.cellSelection = CellSelection.nearest, 18 | this.ensemble = false, 19 | }); 20 | 21 | FloodApi copyWith({ 22 | String? apiUrl, 23 | String? apiKey, 24 | String? userAgent, 25 | CellSelection? cellSelection, 26 | bool? ensemble, 27 | }) => 28 | FloodApi( 29 | apiUrl: apiUrl ?? this.apiUrl, 30 | apiKey: apiKey ?? this.apiKey, 31 | userAgent: userAgent ?? this.userAgent, 32 | cellSelection: cellSelection ?? this.cellSelection, 33 | ensemble: ensemble ?? this.ensemble, 34 | ); 35 | 36 | /// This method returns a JSON map, 37 | /// containing either the data or the raw error response. 38 | /// This method exists solely for debug purposes, do not use in production. 39 | /// Use `request()` instead. 40 | Future> requestJson({ 41 | required Set locations, 42 | required Set daily, 43 | int? pastDays, 44 | int? forecastDays, 45 | Uri Function(Uri)? overrideUri, 46 | }) => 47 | apiRequestJson( 48 | this, 49 | _queryParamMap( 50 | locations: locations, 51 | daily: daily, 52 | pastDays: pastDays, 53 | forecastDays: forecastDays, 54 | ), 55 | overrideUri, 56 | ); 57 | 58 | /// This method returns a Dart object, 59 | /// and throws an exception if the API returns an error response, 60 | /// recommended for most use cases. 61 | Future> request({ 62 | required Set locations, 63 | required Set daily, 64 | int? pastDays, 65 | int? forecastDays, 66 | Uri Function(Uri)? overrideUri, 67 | }) => 68 | apiRequestFlatBuffer( 69 | this, 70 | _queryParamMap( 71 | locations: locations, 72 | daily: daily, 73 | pastDays: pastDays, 74 | forecastDays: forecastDays, 75 | ), 76 | overrideUri, 77 | ).then( 78 | (data) => ApiResponse.fromFlatBuffer( 79 | data.$1, 80 | data.$2, 81 | dailyHashes: FloodDaily.hashes, 82 | ), 83 | ); 84 | 85 | Map _queryParamMap({ 86 | required Set locations, 87 | required Set daily, 88 | required int? pastDays, 89 | required int? forecastDays, 90 | }) { 91 | final parsedLocations = parseLocations(locations); 92 | return { 93 | 'latitude': parsedLocations.latitude, 94 | 'longitude': parsedLocations.longitude, 95 | 'elevation': nullIfEmpty(parsedLocations.elevation), 96 | 'daily': daily, 97 | 'cell_selection': nullIfEqual(cellSelection, CellSelection.nearest), 98 | 'ensemble': nullIfEqual(ensemble, false), 99 | 'past_days': pastDays, 100 | 'forecast_days': forecastDays, 101 | 'start_date': nullIfEmpty(parsedLocations.startDate), 102 | 'end_date': nullIfEmpty(parsedLocations.endDate), 103 | 'timeformat': 'unixtime', 104 | 'timezone': 'auto', 105 | }; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /lib/src/apis/geocoding.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | 3 | /// Search locations globally in any language. 4 | /// 5 | /// https://open-meteo.com/en/docs/geocoding-api/ 6 | class GeocodingApi extends BaseApi { 7 | final String language; 8 | 9 | const GeocodingApi({ 10 | super.apiUrl = 'https://geocoding-api.open-meteo.com/v1/search', 11 | super.apiKey, 12 | super.userAgent, 13 | this.language = 'en', 14 | }); 15 | 16 | GeocodingApi copyWith({ 17 | String? apiUrl, 18 | String? apiKey, 19 | String? userAgent, 20 | String? language, 21 | }) => 22 | GeocodingApi( 23 | apiUrl: apiUrl ?? this.apiUrl, 24 | apiKey: apiKey ?? this.apiKey, 25 | userAgent: userAgent ?? this.userAgent, 26 | language: language ?? this.language, 27 | ); 28 | 29 | /// This method returns a JSON map, 30 | /// containing either the data or the raw error response. 31 | Future> requestJson({ 32 | required String name, 33 | int? count, 34 | Uri Function(Uri)? overrideUri, 35 | }) => 36 | apiRequestJson( 37 | this, 38 | { 39 | 'name': name, 40 | 'count': count, 41 | 'language': nullIfEqual(language, 'en'), 42 | }, 43 | overrideUri, 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/apis/historical.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../enums/historical.dart'; 3 | import '../options.dart'; 4 | import '../response.dart'; 5 | 6 | /// Discover how weather has shaped our world from 1940 until now. 7 | /// 8 | /// https://open-meteo.com/en/docs/historical-weather-api/ 9 | class HistoricalApi extends BaseApi { 10 | final TemperatureUnit temperatureUnit; 11 | final WindspeedUnit windspeedUnit; 12 | final PrecipitationUnit precipitationUnit; 13 | final CellSelection cellSelection; 14 | 15 | const HistoricalApi({ 16 | super.apiUrl = 'https://archive-api.open-meteo.com/v1/archive', 17 | super.apiKey, 18 | super.userAgent, 19 | this.temperatureUnit = TemperatureUnit.celsius, 20 | this.windspeedUnit = WindspeedUnit.kmh, 21 | this.precipitationUnit = PrecipitationUnit.mm, 22 | this.cellSelection = CellSelection.land, 23 | }); 24 | 25 | HistoricalApi copyWith( 26 | String? apiUrl, 27 | String? apiKey, 28 | String? userAgent, 29 | TemperatureUnit? temperatureUnit, 30 | WindspeedUnit? windspeedUnit, 31 | PrecipitationUnit? precipitationUnit, 32 | CellSelection? cellSelection, 33 | double? elevation, 34 | ) => 35 | HistoricalApi( 36 | apiUrl: apiUrl ?? this.apiUrl, 37 | apiKey: apiKey ?? this.apiKey, 38 | userAgent: userAgent ?? this.userAgent, 39 | temperatureUnit: temperatureUnit ?? this.temperatureUnit, 40 | windspeedUnit: windspeedUnit ?? this.windspeedUnit, 41 | precipitationUnit: precipitationUnit ?? this.precipitationUnit, 42 | cellSelection: cellSelection ?? this.cellSelection, 43 | ); 44 | 45 | /// This method returns a JSON map, 46 | /// containing either the data or the raw error response. 47 | /// This method exists solely for debug purposes, do not use in production. 48 | /// Use `request()` instead. 49 | Future> requestJson({ 50 | required Set locations, 51 | Set hourly = const {}, 52 | Set daily = const {}, 53 | double? elevation, 54 | Uri Function(Uri)? overrideUri, 55 | }) => 56 | apiRequestJson( 57 | this, 58 | _queryParamMap( 59 | locations: locations, 60 | hourly: hourly, 61 | daily: daily, 62 | ), 63 | overrideUri, 64 | ); 65 | 66 | /// This method returns a Dart object, 67 | /// and throws an exception if the API returns an error response, 68 | /// recommended for most use cases. 69 | Future> request({ 70 | required Set locations, 71 | Set hourly = const {}, 72 | Set daily = const {}, 73 | double? elevation, 74 | Uri Function(Uri)? overrideUri, 75 | }) => 76 | apiRequestFlatBuffer( 77 | this, 78 | _queryParamMap( 79 | locations: locations, 80 | hourly: hourly, 81 | daily: daily, 82 | ), 83 | overrideUri, 84 | ).then( 85 | (data) => ApiResponse.fromFlatBuffer( 86 | data.$1, 87 | data.$2, 88 | hourlyHashes: HistoricalHourly.hashes, 89 | dailyHashes: HistoricalDaily.hashes, 90 | ), 91 | ); 92 | 93 | Map _queryParamMap({ 94 | required Set locations, 95 | required Set hourly, 96 | required Set daily, 97 | }) { 98 | final parsedLocations = parseLocations(locations); 99 | return { 100 | 'latitude': parsedLocations.latitude, 101 | 'longitude': parsedLocations.longitude, 102 | 'elevation': nullIfEmpty(parsedLocations.elevation), 103 | 'start_date': nullIfEmpty(parsedLocations.startDate), 104 | 'end_date': nullIfEmpty(parsedLocations.endDate), 105 | 'hourly': nullIfEmpty(hourly), 106 | 'daily': nullIfEmpty(daily), 107 | 'temperature_unit': nullIfEqual(temperatureUnit, TemperatureUnit.celsius), 108 | 'windspeed_unit': nullIfEqual(windspeedUnit, WindspeedUnit.kmh), 109 | 'precipitaion_unit': nullIfEqual(precipitationUnit, PrecipitationUnit.mm), 110 | 'cell_selection': nullIfEqual(cellSelection, CellSelection.land), 111 | 'timeformat': 'unixtime', 112 | 'timezone': 'auto', 113 | }; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/src/apis/marine.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../enums/marine.dart'; 3 | import '../options.dart'; 4 | import '../response.dart'; 5 | 6 | /// Hourly wave forecasts at 5 km resolution 7 | /// 8 | /// https://open-meteo.com/en/docs/marine-weather-api/ 9 | class MarineApi extends BaseApi { 10 | final TemperatureUnit temperatureUnit; 11 | final WindspeedUnit windspeedUnit; 12 | final PrecipitationUnit precipitationUnit; 13 | final LengthUnit lengthUnit; 14 | final CellSelection cellSelection; 15 | 16 | const MarineApi({ 17 | super.apiUrl = 'https://marine-api.open-meteo.com/v1/marine', 18 | super.apiKey, 19 | super.userAgent, 20 | this.temperatureUnit = TemperatureUnit.celsius, 21 | this.windspeedUnit = WindspeedUnit.kmh, 22 | this.precipitationUnit = PrecipitationUnit.mm, 23 | this.lengthUnit = LengthUnit.metric, 24 | this.cellSelection = CellSelection.sea, 25 | }); 26 | 27 | MarineApi copyWith({ 28 | String? apiUrl, 29 | String? apiKey, 30 | String? userAgent, 31 | TemperatureUnit? temperatureUnit, 32 | WindspeedUnit? windspeedUnit, 33 | PrecipitationUnit? precipitationUnit, 34 | LengthUnit? lengthUnit, 35 | CellSelection? cellSelection, 36 | }) => 37 | MarineApi( 38 | apiUrl: apiUrl ?? this.apiUrl, 39 | apiKey: apiKey ?? this.apiKey, 40 | userAgent: userAgent ?? this.userAgent, 41 | temperatureUnit: temperatureUnit ?? this.temperatureUnit, 42 | windspeedUnit: windspeedUnit ?? this.windspeedUnit, 43 | precipitationUnit: precipitationUnit ?? this.precipitationUnit, 44 | lengthUnit: lengthUnit ?? this.lengthUnit, 45 | cellSelection: cellSelection ?? this.cellSelection, 46 | ); 47 | 48 | /// This method returns a JSON map, 49 | /// containing either the data or the raw error response. 50 | /// This method exists solely for debug purposes, do not use in production. 51 | /// Use `request()` instead. 52 | Future> requestJson({ 53 | required Set locations, 54 | Set current = const {}, 55 | Set hourly = const {}, 56 | Set daily = const {}, 57 | int? pastDays, 58 | int? pastHours, 59 | int? forecastDays, 60 | int? forecastHours, 61 | DateTime? startHour, 62 | DateTime? endHour, 63 | Uri Function(Uri)? overrideUri, 64 | }) => 65 | apiRequestJson( 66 | this, 67 | _queryParamMap( 68 | locations: locations, 69 | current: current, 70 | hourly: hourly, 71 | daily: daily, 72 | pastDays: pastDays, 73 | pastHours: pastHours, 74 | forecastDays: forecastDays, 75 | forecastHours: forecastHours, 76 | startHour: startHour, 77 | endHour: endHour, 78 | ), 79 | overrideUri, 80 | ); 81 | 82 | /// This method returns a Dart object, 83 | /// and throws an exception if the API returns an error response, 84 | /// recommended for most use cases. 85 | Future> request({ 86 | required Set locations, 87 | Set current = const {}, 88 | Set hourly = const {}, 89 | Set daily = const {}, 90 | int? pastDays, 91 | int? pastHours, 92 | int? forecastDays, 93 | int? forecastHours, 94 | DateTime? startHour, 95 | DateTime? endHour, 96 | Uri Function(Uri)? overrideUri, 97 | }) => 98 | apiRequestFlatBuffer( 99 | this, 100 | _queryParamMap( 101 | locations: locations, 102 | current: current, 103 | hourly: hourly, 104 | daily: daily, 105 | pastDays: pastDays, 106 | pastHours: pastHours, 107 | forecastDays: forecastDays, 108 | forecastHours: forecastHours, 109 | startHour: startHour, 110 | endHour: endHour, 111 | ), 112 | overrideUri, 113 | ).then( 114 | (data) => ApiResponse.fromFlatBuffer( 115 | data.$1, 116 | data.$2, 117 | currentHashes: MarineCurrent.hashes, 118 | hourlyHashes: MarineHourly.hashes, 119 | dailyHashes: MarineDaily.hashes, 120 | ), 121 | ); 122 | 123 | Map _queryParamMap({ 124 | required Set locations, 125 | required Set current, 126 | required Set hourly, 127 | required Set daily, 128 | required int? pastDays, 129 | required int? pastHours, 130 | required int? forecastDays, 131 | required int? forecastHours, 132 | required DateTime? startHour, 133 | required DateTime? endHour, 134 | }) { 135 | final parsedLocations = parseLocations(locations); 136 | return { 137 | 'latitude': parsedLocations.latitude, 138 | 'longitude': parsedLocations.longitude, 139 | 'elevation': nullIfEmpty(parsedLocations.elevation), 140 | 'current': nullIfEmpty(current), 141 | 'hourly': nullIfEmpty(hourly), 142 | 'daily': nullIfEmpty(daily), 143 | 'temperature_unit': nullIfEqual(temperatureUnit, TemperatureUnit.celsius), 144 | 'windspeed_unit': nullIfEqual(windspeedUnit, WindspeedUnit.kmh), 145 | 'precipitation_unit': 146 | nullIfEqual(precipitationUnit, PrecipitationUnit.mm), 147 | 'length_unit': nullIfEqual(lengthUnit, LengthUnit.metric), 148 | 'cell_selection': nullIfEqual(cellSelection, CellSelection.sea), 149 | 'past_days': pastDays, 150 | 'past_hours': pastHours, 151 | 'forecast_days': forecastDays, 152 | 'forecast_hours': forecastHours, 153 | 'start_date': nullIfEmpty(parsedLocations.startDate), 154 | 'end_date': nullIfEmpty(parsedLocations.endDate), 155 | 'start_hour': formatTime(startHour), 156 | 'end_hour': formatTime(endHour), 157 | 'timeformat': 'unixtime', 158 | 'timezone': 'auto', 159 | }; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /lib/src/apis/satellite_radiation.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../enums/satellite_radiation.dart'; 3 | import '../options.dart'; 4 | import '../response.dart'; 5 | import '../model_export.dart'; 6 | 7 | /// Hourly wave forecasts at 5 km resolution 8 | /// 9 | /// https://open-meteo.com/en/docs/marine-weather-api/ 10 | class SatelliteRadiationApi extends BaseApi { 11 | final Set models; 12 | final int tilt; 13 | final int azimuth; 14 | final CellSelection cellSelection; 15 | 16 | const SatelliteRadiationApi({ 17 | super.apiUrl = 'https://satellite-api.open-meteo.com/v1/archive', 18 | super.apiKey, 19 | super.userAgent, 20 | required this.models, 21 | this.tilt = 0, 22 | this.azimuth = 0, 23 | this.cellSelection = CellSelection.sea, 24 | }); 25 | 26 | SatelliteRadiationApi copyWith({ 27 | String? apiUrl, 28 | String? apiKey, 29 | String? userAgent, 30 | Set? models, 31 | int? tilt, 32 | int? azimuth, 33 | CellSelection? cellSelection, 34 | }) => 35 | SatelliteRadiationApi( 36 | apiUrl: apiUrl ?? this.apiUrl, 37 | apiKey: apiKey ?? this.apiKey, 38 | userAgent: userAgent ?? this.userAgent, 39 | models: models ?? this.models, 40 | tilt: tilt ?? this.tilt, 41 | azimuth: azimuth ?? this.azimuth, 42 | cellSelection: cellSelection ?? this.cellSelection, 43 | ); 44 | 45 | /// This method returns a JSON map, 46 | /// containing either the data or the raw error response. 47 | /// This method exists solely for debug purposes, do not use in production. 48 | /// Use `request()` instead. 49 | Future> requestJson({ 50 | required Set locations, 51 | Set hourly = const {}, 52 | Set daily = const {}, 53 | int? pastDays, 54 | int? pastHours, 55 | int? forecastDays, 56 | int? forecastHours, 57 | DateTime? startHour, 58 | DateTime? endHour, 59 | Uri Function(Uri)? overrideUri, 60 | }) => 61 | apiRequestJson( 62 | this, 63 | _queryParamMap( 64 | locations: locations, 65 | hourly: hourly, 66 | daily: daily, 67 | pastDays: pastDays, 68 | pastHours: pastHours, 69 | forecastDays: forecastDays, 70 | forecastHours: forecastHours, 71 | startHour: startHour, 72 | endHour: endHour, 73 | ), 74 | overrideUri, 75 | ); 76 | 77 | /// This method returns a Dart object, 78 | /// and throws an exception if the API returns an error response, 79 | /// recommended for most use cases. 80 | Future> request({ 81 | required Set locations, 82 | Set hourly = const {}, 83 | Set daily = const {}, 84 | int? pastDays, 85 | int? pastHours, 86 | int? forecastDays, 87 | int? forecastHours, 88 | DateTime? startHour, 89 | DateTime? endHour, 90 | Uri Function(Uri)? overrideUri, 91 | }) => 92 | apiRequestFlatBuffer( 93 | this, 94 | _queryParamMap( 95 | locations: locations, 96 | hourly: hourly, 97 | daily: daily, 98 | pastDays: pastDays, 99 | pastHours: pastHours, 100 | forecastDays: forecastDays, 101 | forecastHours: forecastHours, 102 | startHour: startHour, 103 | endHour: endHour, 104 | ), 105 | overrideUri, 106 | ).then( 107 | (data) => ApiResponse.fromFlatBuffer( 108 | data.$1, 109 | data.$2, 110 | hourlyHashes: SatelliteRadiationHourly.hashes, 111 | dailyHashes: SatelliteRadiationDaily.hashes, 112 | ), 113 | ); 114 | 115 | Map _queryParamMap({ 116 | required Set locations, 117 | required Set hourly, 118 | required Set daily, 119 | required int? pastDays, 120 | required int? pastHours, 121 | required int? forecastDays, 122 | required int? forecastHours, 123 | required DateTime? startHour, 124 | required DateTime? endHour, 125 | }) { 126 | final parsedLocations = parseLocations(locations); 127 | return { 128 | 'models': models, 129 | 'latitude': parsedLocations.latitude, 130 | 'longitude': parsedLocations.longitude, 131 | 'elevation': nullIfEmpty(parsedLocations.elevation), 132 | 'hourly': nullIfEmpty(hourly), 133 | 'daily': nullIfEmpty(daily), 134 | 'tilt': nullIfEqual(tilt, 0), 135 | 'azimuth': nullIfEqual(azimuth, 0), 136 | 'cell_selection': nullIfEqual(cellSelection, CellSelection.sea), 137 | 'past_days': pastDays, 138 | 'past_hours': pastHours, 139 | 'forecast_days': forecastDays, 140 | 'forecast_hours': forecastHours, 141 | 'start_date': nullIfEmpty(parsedLocations.startDate), 142 | 'end_date': nullIfEmpty(parsedLocations.endDate), 143 | 'start_hour': formatTime(startHour), 144 | 'end_hour': formatTime(endHour), 145 | 'timeformat': 'unixtime', 146 | 'timezone': 'auto', 147 | }; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /lib/src/apis/weather.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/src/weather_api_openmeteo_sdk_generated.dart'; 2 | 3 | import '../api.dart'; 4 | import '../enums/weather.dart'; 5 | import '../options.dart'; 6 | import '../response.dart'; 7 | 8 | /// Seamless integration of high-resolution weather models with up 16 days forecast. 9 | /// 10 | /// https://open-meteo.com/en/docs/ 11 | class WeatherApi extends BaseApi { 12 | final TemperatureUnit temperatureUnit; 13 | final WindspeedUnit windspeedUnit; 14 | final PrecipitationUnit precipitationUnit; 15 | final CellSelection cellSelection; 16 | 17 | const WeatherApi({ 18 | super.apiUrl = 'https://api.open-meteo.com/v1/forecast', 19 | super.apiKey, 20 | super.userAgent, 21 | this.temperatureUnit = TemperatureUnit.celsius, 22 | this.windspeedUnit = WindspeedUnit.kmh, 23 | this.precipitationUnit = PrecipitationUnit.mm, 24 | this.cellSelection = CellSelection.land, 25 | }); 26 | 27 | WeatherApi copyWith({ 28 | String? apiUrl, 29 | String? apiKey, 30 | String? userAgent, 31 | TemperatureUnit? temperatureUnit, 32 | WindspeedUnit? windspeedUnit, 33 | PrecipitationUnit? precipitationUnit, 34 | CellSelection? cellSelection, 35 | }) => 36 | WeatherApi( 37 | apiUrl: apiUrl ?? this.apiUrl, 38 | apiKey: apiKey ?? this.apiKey, 39 | userAgent: userAgent ?? this.userAgent, 40 | temperatureUnit: temperatureUnit ?? this.temperatureUnit, 41 | windspeedUnit: windspeedUnit ?? this.windspeedUnit, 42 | precipitationUnit: precipitationUnit ?? this.precipitationUnit, 43 | cellSelection: cellSelection ?? this.cellSelection, 44 | ); 45 | 46 | /// This method returns a JSON map, 47 | /// containing either the data or the raw error response. 48 | /// This method exists solely for debug purposes, do not use in production. 49 | /// Use `request()` instead. 50 | Future> requestJson({ 51 | required Set locations, 52 | Set hourly = const {}, 53 | Set daily = const {}, 54 | Set current = const {}, 55 | Set minutely15 = const {}, 56 | Set models = const {}, 57 | double? elevation, 58 | int? pastDays, 59 | int? pastHours, 60 | int? pastMinutely15, 61 | int? forecastDays, 62 | int? forecastHours, 63 | int? forecastMinutely15, 64 | DateTime? startHour, 65 | DateTime? endHour, 66 | Uri Function(Uri)? overrideUri, 67 | }) => 68 | apiRequestJson( 69 | this, 70 | _queryParamMap( 71 | locations: locations, 72 | hourly: hourly, 73 | daily: daily, 74 | minutely15: minutely15, 75 | current: current, 76 | models: models, 77 | elevation: elevation, 78 | pastDays: pastDays, 79 | pastHours: pastHours, 80 | pastMinutely15: pastMinutely15, 81 | forecastDays: forecastDays, 82 | forecastHours: forecastHours, 83 | forecastMinutely15: forecastMinutely15, 84 | startHour: startHour, 85 | endHour: endHour, 86 | ), 87 | overrideUri, 88 | ); 89 | 90 | /// This method returns a Dart object, 91 | /// and throws an exception if the API returns an error response, 92 | /// recommended for most use cases. 93 | Future> request({ 94 | required Set locations, 95 | Set hourly = const {}, 96 | Set daily = const {}, 97 | Set current = const {}, 98 | Set minutely15 = const {}, 99 | Set models = const {}, 100 | double? elevation, 101 | int? pastDays, 102 | int? pastHours, 103 | int? pastMinutely15, 104 | int? forecastDays, 105 | int? forecastHours, 106 | int? forecastMinutely15, 107 | DateTime? startHour, 108 | DateTime? endHour, 109 | Uri Function(Uri)? overrideUri, 110 | }) => 111 | apiRequestFlatBuffer( 112 | this, 113 | _queryParamMap( 114 | locations: locations, 115 | hourly: hourly, 116 | daily: daily, 117 | current: current, 118 | minutely15: minutely15, 119 | models: models, 120 | elevation: elevation, 121 | pastDays: pastDays, 122 | pastHours: pastHours, 123 | pastMinutely15: pastMinutely15, 124 | forecastDays: forecastDays, 125 | forecastHours: forecastHours, 126 | forecastMinutely15: forecastMinutely15, 127 | startHour: startHour, 128 | endHour: endHour, 129 | ), 130 | overrideUri, 131 | ).then( 132 | (data) => ApiResponse.fromFlatBuffer( 133 | data.$1, 134 | data.$2, 135 | minutely15Hashes: WeatherMinutely15.hashes, 136 | currentHashes: WeatherCurrent.hashes, 137 | hourlyHashes: WeatherHourly.hashes, 138 | dailyHashes: WeatherDaily.hashes, 139 | ), 140 | ); 141 | 142 | Map _queryParamMap({ 143 | required Set locations, 144 | required Set hourly, 145 | required Set daily, 146 | required Set current, 147 | required Set minutely15, 148 | required Set models, 149 | required double? elevation, 150 | required int? pastDays, 151 | required int? pastHours, 152 | required int? pastMinutely15, 153 | required int? forecastDays, 154 | required int? forecastHours, 155 | required int? forecastMinutely15, 156 | required DateTime? startHour, 157 | required DateTime? endHour, 158 | }) { 159 | final parsedLocations = parseLocations(locations); 160 | return { 161 | 'latitude': parsedLocations.latitude, 162 | 'longitude': parsedLocations.longitude, 163 | 'elevation': nullIfEmpty(parsedLocations.elevation), 164 | 'minutely_15': nullIfEmpty(minutely15), 165 | 'current': nullIfEmpty(current), 166 | 'hourly': nullIfEmpty(hourly), 167 | 'daily': nullIfEmpty(daily), 168 | 'models': nullIfEmpty(models), 169 | 'temperature_unit': nullIfEqual(temperatureUnit, TemperatureUnit.celsius), 170 | 'windspeed_unit': nullIfEqual(windspeedUnit, WindspeedUnit.kmh), 171 | 'precipitation_unit': 172 | nullIfEqual(precipitationUnit, PrecipitationUnit.mm), 173 | 'cell_selection': nullIfEqual(cellSelection, CellSelection.land), 174 | 'past_days': pastDays, 175 | 'past_hours': pastHours, 176 | 'past_minutely_15': pastMinutely15, 177 | 'forecast_days': forecastDays, 178 | 'forecast_hours': forecastHours, 179 | 'forecast_minutely_15': forecastMinutely15, 180 | 'start_date': nullIfEmpty(parsedLocations.startDate), 181 | 'end_date': nullIfEmpty(parsedLocations.endDate), 182 | 'start_hour': formatTime(startHour), 183 | 'end_hour': formatTime(endHour), 184 | 'timeformat': 'unixtime', 185 | 'timezone': 'auto', 186 | }; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /lib/src/enums/air_quality.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../apis/air_quality.dart'; 3 | import '../weather_api_openmeteo_sdk_generated.dart'; 4 | 5 | // Generated Variable Enums for AirQuality 6 | 7 | enum AirQualityCurrent with Parameter { 8 | european_aqi( 9 | Variable.european_aqi, 10 | ), 11 | us_aqi( 12 | Variable.us_aqi, 13 | ), 14 | pm10( 15 | Variable.pm10, 16 | ), 17 | pm2_5( 18 | Variable.pm2p5, 19 | ), 20 | carbon_monoxide( 21 | Variable.carbon_monoxide, 22 | ), 23 | nitrogen_dioxide( 24 | Variable.nitrogen_dioxide, 25 | ), 26 | sulphur_dioxide( 27 | Variable.sulphur_dioxide, 28 | ), 29 | ozone( 30 | Variable.ozone, 31 | ), 32 | aerosol_optical_depth( 33 | Variable.aerosol_optical_depth, 34 | ), 35 | dust( 36 | Variable.dust, 37 | ), 38 | uv_index( 39 | Variable.uv_index, 40 | ), 41 | uv_index_clear_sky( 42 | Variable.uv_index_clear_sky, 43 | ), 44 | ammonia( 45 | Variable.ammonia, 46 | ), 47 | alder_pollen( 48 | Variable.alder_pollen, 49 | ), 50 | birch_pollen( 51 | Variable.birch_pollen, 52 | ), 53 | grass_pollen( 54 | Variable.grass_pollen, 55 | ), 56 | mugwort_pollen( 57 | Variable.mugwort_pollen, 58 | ), 59 | olive_pollen( 60 | Variable.olive_pollen, 61 | ), 62 | ragweed_pollen( 63 | Variable.ragweed_pollen, 64 | ), 65 | ; 66 | 67 | @override 68 | final Variable variable; 69 | const AirQualityCurrent(this.variable); 70 | 71 | static final Map hashes = 72 | makeHashes(AirQualityCurrent.values); 73 | } 74 | 75 | enum AirQualityHourly with Parameter { 76 | pm10( 77 | Variable.pm10, 78 | ), 79 | pm2_5( 80 | Variable.pm2p5, 81 | ), 82 | carbon_monoxide( 83 | Variable.carbon_monoxide, 84 | ), 85 | carbon_dioxide( 86 | Variable.carbon_dioxide, 87 | ), 88 | nitrogen_dioxide( 89 | Variable.nitrogen_dioxide, 90 | ), 91 | sulphur_dioxide( 92 | Variable.sulphur_dioxide, 93 | ), 94 | ozone( 95 | Variable.ozone, 96 | ), 97 | aerosol_optical_depth( 98 | Variable.aerosol_optical_depth, 99 | ), 100 | dust( 101 | Variable.dust, 102 | ), 103 | uv_index( 104 | Variable.uv_index, 105 | ), 106 | uv_index_clear_sky( 107 | Variable.uv_index_clear_sky, 108 | ), 109 | ammonia( 110 | Variable.ammonia, 111 | ), 112 | methane( 113 | Variable.methane, 114 | ), 115 | alder_pollen( 116 | Variable.alder_pollen, 117 | ), 118 | birch_pollen( 119 | Variable.birch_pollen, 120 | ), 121 | grass_pollen( 122 | Variable.grass_pollen, 123 | ), 124 | mugwort_pollen( 125 | Variable.mugwort_pollen, 126 | ), 127 | olive_pollen( 128 | Variable.olive_pollen, 129 | ), 130 | ragweed_pollen( 131 | Variable.ragweed_pollen, 132 | ), 133 | european_aqi( 134 | Variable.european_aqi, 135 | ), 136 | european_aqi_pm2_5( 137 | Variable.european_aqi_pm2p5, 138 | ), 139 | european_aqi_pm10( 140 | Variable.european_aqi_pm10, 141 | ), 142 | european_aqi_nitrogen_dioxide( 143 | Variable.european_aqi_nitrogen_dioxide, 144 | ), 145 | european_aqi_ozone( 146 | Variable.european_aqi_ozone, 147 | ), 148 | european_aqi_sulphur_dioxide( 149 | Variable.european_aqi_sulphur_dioxide, 150 | ), 151 | us_aqi( 152 | Variable.us_aqi, 153 | ), 154 | us_aqi_pm2_5( 155 | Variable.us_aqi_pm2p5, 156 | ), 157 | us_aqi_pm10( 158 | Variable.us_aqi_pm10, 159 | ), 160 | us_aqi_nitrogen_dioxide( 161 | Variable.us_aqi_nitrogen_dioxide, 162 | ), 163 | us_aqi_carbon_monoxide( 164 | Variable.us_aqi_carbon_monoxide, 165 | ), 166 | us_aqi_ozone( 167 | Variable.us_aqi_ozone, 168 | ), 169 | us_aqi_sulphur_dioxide( 170 | Variable.us_aqi_sulphur_dioxide, 171 | ), 172 | formaldehyde( 173 | Variable.formaldehyde, 174 | ), 175 | glyoxal( 176 | Variable.glyoxal, 177 | ), 178 | non_methane_volatile_organic_compounds( 179 | Variable.non_methane_volatile_organic_compounds, 180 | ), 181 | pm10_wildfires( 182 | Variable.pm10_wildfires, 183 | ), 184 | peroxyacyl_nitrates( 185 | Variable.peroxyacyl_nitrates, 186 | ), 187 | secondary_inorganic_aerosol( 188 | Variable.secondary_inorganic_aerosol, 189 | ), 190 | residential_elementary_carbon( 191 | Variable.residential_elementary_carbon, 192 | ), 193 | total_elementary_carbon( 194 | Variable.total_elementary_carbon, 195 | ), 196 | sea_salt_aerosol( 197 | Variable.sea_salt_aerosol, 198 | ), 199 | nitrogen_monoxide( 200 | Variable.nitrogen_monoxide, 201 | ), 202 | ; 203 | 204 | @override 205 | final Variable variable; 206 | const AirQualityHourly(this.variable); 207 | 208 | static final Map hashes = 209 | makeHashes(AirQualityHourly.values); 210 | } 211 | 212 | enum AirQualityDomains { 213 | auto, 214 | cams_europe, 215 | cams_global; 216 | } 217 | -------------------------------------------------------------------------------- /lib/src/enums/climate.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../apis/climate.dart'; 3 | import '../weather_api_openmeteo_sdk_generated.dart'; 4 | 5 | // Generated Variable Enums for Climate 6 | 7 | enum ClimateDaily with Parameter { 8 | temperature_2m_mean( 9 | Variable.temperature, 10 | aggregation: Aggregation.mean, 11 | altitude: 2, 12 | ), 13 | temperature_2m_max( 14 | Variable.temperature, 15 | aggregation: Aggregation.maximum, 16 | altitude: 2, 17 | ), 18 | temperature_2m_min( 19 | Variable.temperature, 20 | aggregation: Aggregation.minimum, 21 | altitude: 2, 22 | ), 23 | wind_speed_10m_mean( 24 | Variable.wind_speed, 25 | aggregation: Aggregation.mean, 26 | altitude: 10, 27 | ), 28 | wind_speed_10m_max( 29 | Variable.wind_speed, 30 | aggregation: Aggregation.maximum, 31 | altitude: 10, 32 | ), 33 | cloud_cover_mean( 34 | Variable.cloud_cover, 35 | aggregation: Aggregation.mean, 36 | ), 37 | shortwave_radiation_sum( 38 | Variable.shortwave_radiation, 39 | aggregation: Aggregation.sum, 40 | ), 41 | relative_humidity_2m_mean( 42 | Variable.relative_humidity, 43 | aggregation: Aggregation.mean, 44 | altitude: 2, 45 | ), 46 | relative_humidity_2m_max( 47 | Variable.relative_humidity, 48 | aggregation: Aggregation.maximum, 49 | altitude: 2, 50 | ), 51 | relative_humidity_2m_min( 52 | Variable.relative_humidity, 53 | aggregation: Aggregation.minimum, 54 | altitude: 2, 55 | ), 56 | dew_point_2m_mean( 57 | Variable.dew_point, 58 | aggregation: Aggregation.mean, 59 | altitude: 2, 60 | ), 61 | dew_point_2m_min( 62 | Variable.dew_point, 63 | aggregation: Aggregation.minimum, 64 | altitude: 2, 65 | ), 66 | dew_point_2m_max( 67 | Variable.dew_point, 68 | aggregation: Aggregation.maximum, 69 | altitude: 2, 70 | ), 71 | precipitation_sum( 72 | Variable.precipitation, 73 | aggregation: Aggregation.sum, 74 | ), 75 | rain_sum( 76 | Variable.rain, 77 | aggregation: Aggregation.sum, 78 | ), 79 | snowfall_sum( 80 | Variable.snowfall, 81 | aggregation: Aggregation.sum, 82 | ), 83 | pressure_msl_mean( 84 | Variable.pressure_msl, 85 | aggregation: Aggregation.mean, 86 | ), 87 | soil_moisture_0_to_10cm_mean( 88 | Variable.soil_moisture, 89 | aggregation: Aggregation.mean, 90 | depth: 0, 91 | depthTo: 10, 92 | ), 93 | et0_fao_evapotranspiration_sum( 94 | Variable.et0_fao_evapotranspiration, 95 | aggregation: Aggregation.sum, 96 | ), 97 | ; 98 | 99 | @override 100 | final Variable variable; 101 | @override 102 | final int altitude; 103 | @override 104 | final int depth; 105 | @override 106 | final int depthTo; 107 | @override 108 | final Aggregation aggregation; 109 | const ClimateDaily( 110 | this.variable, { 111 | this.altitude = 0, 112 | this.depth = 0, 113 | this.depthTo = 0, 114 | this.aggregation = Aggregation.none, 115 | }); 116 | 117 | static final Map hashes = makeHashes(ClimateDaily.values); 118 | } 119 | -------------------------------------------------------------------------------- /lib/src/enums/ensemble.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../apis/ensemble.dart'; 3 | import '../weather_api_openmeteo_sdk_generated.dart'; 4 | 5 | // Generated Variable Enums for Ensemble 6 | 7 | enum EnsembleHourly with Parameter { 8 | temperature_2m( 9 | Variable.temperature, 10 | altitude: 2, 11 | ), 12 | relative_humidity_2m( 13 | Variable.relative_humidity, 14 | altitude: 2, 15 | ), 16 | dew_point_2m( 17 | Variable.dew_point, 18 | altitude: 2, 19 | ), 20 | apparent_temperature( 21 | Variable.apparent_temperature, 22 | altitude: 2, 23 | ), 24 | precipitation( 25 | Variable.precipitation, 26 | ), 27 | rain( 28 | Variable.rain, 29 | ), 30 | snowfall( 31 | Variable.snowfall, 32 | ), 33 | snow_depth( 34 | Variable.snow_depth, 35 | ), 36 | weather_code( 37 | Variable.weather_code, 38 | ), 39 | pressure_msl( 40 | Variable.pressure_msl, 41 | ), 42 | surface_pressure( 43 | Variable.surface_pressure, 44 | ), 45 | cloud_cover( 46 | Variable.cloud_cover, 47 | ), 48 | visibility( 49 | Variable.visibility, 50 | ), 51 | et0_fao_evapotranspiration( 52 | Variable.et0_fao_evapotranspiration, 53 | ), 54 | vapour_pressure_deficit( 55 | Variable.vapour_pressure_deficit, 56 | ), 57 | wind_speed_10m( 58 | Variable.wind_speed, 59 | altitude: 10, 60 | ), 61 | wind_speed_80m( 62 | Variable.wind_speed, 63 | altitude: 80, 64 | ), 65 | wind_speed_100m( 66 | Variable.wind_speed, 67 | altitude: 100, 68 | ), 69 | wind_speed_120m( 70 | Variable.wind_speed, 71 | altitude: 120, 72 | ), 73 | wind_direction_10m( 74 | Variable.wind_direction, 75 | altitude: 10, 76 | ), 77 | wind_direction_80m( 78 | Variable.wind_direction, 79 | altitude: 80, 80 | ), 81 | wind_direction_100m( 82 | Variable.wind_direction, 83 | altitude: 100, 84 | ), 85 | wind_direction_120m( 86 | Variable.wind_direction, 87 | altitude: 120, 88 | ), 89 | wind_gusts_10m( 90 | Variable.wind_gusts, 91 | altitude: 10, 92 | ), 93 | temperature_80m( 94 | Variable.temperature, 95 | altitude: 80, 96 | ), 97 | temperature_120m( 98 | Variable.temperature, 99 | altitude: 120, 100 | ), 101 | surface_temperature( 102 | Variable.surface_temperature, 103 | ), 104 | soil_temperature_0_to_10cm( 105 | Variable.soil_temperature, 106 | depth: 0, 107 | depthTo: 10, 108 | ), 109 | soil_temperature_10_to_40cm( 110 | Variable.soil_temperature, 111 | depth: 10, 112 | depthTo: 40, 113 | ), 114 | soil_temperature_40_to_100cm( 115 | Variable.soil_temperature, 116 | depth: 40, 117 | depthTo: 100, 118 | ), 119 | soil_temperature_100_to_200cm( 120 | Variable.soil_temperature, 121 | depth: 100, 122 | depthTo: 200, 123 | ), 124 | soil_moisture_0_to_10cm( 125 | Variable.soil_moisture, 126 | depth: 0, 127 | depthTo: 10, 128 | ), 129 | soil_moisture_10_to_40cm( 130 | Variable.soil_moisture, 131 | depth: 10, 132 | depthTo: 40, 133 | ), 134 | soil_moisture_40_to_100cm( 135 | Variable.soil_moisture, 136 | depth: 40, 137 | depthTo: 100, 138 | ), 139 | soil_moisture_100_to_200cm( 140 | Variable.soil_moisture, 141 | depth: 100, 142 | depthTo: 200, 143 | ), 144 | uv_index( 145 | Variable.uv_index, 146 | ), 147 | uv_index_clear_sky( 148 | Variable.uv_index_clear_sky, 149 | ), 150 | temperature_500hPa( 151 | Variable.temperature, 152 | pressureLevel: 500, 153 | ), 154 | temperature_850hPa( 155 | Variable.temperature, 156 | pressureLevel: 850, 157 | ), 158 | geopotential_height_500hPa( 159 | Variable.geopotential_height, 160 | pressureLevel: 500, 161 | ), 162 | geopotential_height_850hPa( 163 | Variable.geopotential_height, 164 | pressureLevel: 850, 165 | ), 166 | wet_bulb_temperature_2m( 167 | Variable.wet_bulb_temperature, 168 | altitude: 2, 169 | ), 170 | cape( 171 | Variable.cape, 172 | ), 173 | freezing_level_height( 174 | Variable.freezing_level_height, 175 | ), 176 | sunshine_duration( 177 | Variable.sunshine_duration, 178 | ), 179 | shortwave_radiation( 180 | Variable.shortwave_radiation, 181 | ), 182 | direct_radiation( 183 | Variable.direct_radiation, 184 | ), 185 | diffuse_radiation( 186 | Variable.diffuse_radiation, 187 | ), 188 | direct_normal_irradiance( 189 | Variable.direct_normal_irradiance, 190 | ), 191 | global_tilted_irradiance( 192 | Variable.global_tilted_irradiance, 193 | ), 194 | shortwave_radiation_instant( 195 | Variable.shortwave_radiation_instant, 196 | ), 197 | direct_radiation_instant( 198 | Variable.direct_radiation_instant, 199 | ), 200 | diffuse_radiation_instant( 201 | Variable.diffuse_radiation_instant, 202 | ), 203 | direct_normal_irradiance_instant( 204 | Variable.direct_normal_irradiance_instant, 205 | ), 206 | global_tilted_irradiance_instant( 207 | Variable.global_tilted_irradiance_instant, 208 | ), 209 | ; 210 | 211 | @override 212 | final Variable variable; 213 | @override 214 | final int altitude; 215 | @override 216 | final int depth; 217 | @override 218 | final int depthTo; 219 | @override 220 | final int pressureLevel; 221 | const EnsembleHourly( 222 | this.variable, { 223 | this.altitude = 0, 224 | this.depth = 0, 225 | this.depthTo = 0, 226 | this.pressureLevel = 0, 227 | }); 228 | 229 | static final Map hashes = 230 | makeHashes(EnsembleHourly.values); 231 | } 232 | 233 | enum EnsembleDaily with Parameter { 234 | temperature_2m_mean( 235 | Variable.temperature, 236 | aggregation: Aggregation.mean, 237 | altitude: 2, 238 | ), 239 | temperature_2m_min( 240 | Variable.temperature, 241 | aggregation: Aggregation.minimum, 242 | altitude: 2, 243 | ), 244 | temperature_2m_max( 245 | Variable.temperature, 246 | aggregation: Aggregation.maximum, 247 | altitude: 2, 248 | ), 249 | apparent_temperature_mean( 250 | Variable.apparent_temperature, 251 | aggregation: Aggregation.mean, 252 | altitude: 2, 253 | ), 254 | apparent_temperature_min( 255 | Variable.apparent_temperature, 256 | aggregation: Aggregation.minimum, 257 | altitude: 2, 258 | ), 259 | apparent_temperature_max( 260 | Variable.apparent_temperature, 261 | aggregation: Aggregation.maximum, 262 | altitude: 2, 263 | ), 264 | wind_speed_10m_mean( 265 | Variable.wind_speed, 266 | aggregation: Aggregation.mean, 267 | altitude: 10, 268 | ), 269 | wind_speed_10m_min( 270 | Variable.wind_speed, 271 | aggregation: Aggregation.minimum, 272 | altitude: 10, 273 | ), 274 | wind_speed_10m_max( 275 | Variable.wind_speed, 276 | aggregation: Aggregation.maximum, 277 | altitude: 10, 278 | ), 279 | wind_direction_10m_dominant( 280 | Variable.wind_direction, 281 | aggregation: Aggregation.dominant, 282 | altitude: 10, 283 | ), 284 | wind_gusts_10m_mean( 285 | Variable.wind_gusts, 286 | aggregation: Aggregation.mean, 287 | altitude: 10, 288 | ), 289 | wind_gusts_10m_min( 290 | Variable.wind_gusts, 291 | aggregation: Aggregation.minimum, 292 | altitude: 10, 293 | ), 294 | wind_gusts_10m_max( 295 | Variable.wind_gusts, 296 | aggregation: Aggregation.maximum, 297 | altitude: 10, 298 | ), 299 | wind_speed_100m_mean( 300 | Variable.wind_speed, 301 | aggregation: Aggregation.mean, 302 | altitude: 100, 303 | ), 304 | wind_speed_100m_min( 305 | Variable.wind_speed, 306 | aggregation: Aggregation.minimum, 307 | altitude: 100, 308 | ), 309 | wind_speed_100m_max( 310 | Variable.wind_speed, 311 | aggregation: Aggregation.maximum, 312 | altitude: 100, 313 | ), 314 | wind_direction_100m_dominant( 315 | Variable.wind_direction, 316 | aggregation: Aggregation.dominant, 317 | altitude: 100, 318 | ), 319 | cloud_cover_mean( 320 | Variable.cloud_cover, 321 | aggregation: Aggregation.mean, 322 | ), 323 | cloud_cover_min( 324 | Variable.cloud_cover, 325 | aggregation: Aggregation.minimum, 326 | ), 327 | cloud_cover_max( 328 | Variable.cloud_cover, 329 | aggregation: Aggregation.maximum, 330 | ), 331 | precipitation_sum( 332 | Variable.precipitation, 333 | aggregation: Aggregation.sum, 334 | ), 335 | precipitation_hours( 336 | Variable.precipitation_hours, 337 | ), 338 | rain_sum( 339 | Variable.rain, 340 | aggregation: Aggregation.sum, 341 | ), 342 | snowfall_sum( 343 | Variable.snowfall, 344 | aggregation: Aggregation.sum, 345 | ), 346 | pressure_msl_mean( 347 | Variable.pressure_msl, 348 | aggregation: Aggregation.mean, 349 | ), 350 | pressure_msl_min( 351 | Variable.pressure_msl, 352 | aggregation: Aggregation.minimum, 353 | ), 354 | pressure_msl_max( 355 | Variable.pressure_msl, 356 | aggregation: Aggregation.maximum, 357 | ), 358 | surface_pressure_mean( 359 | Variable.surface_pressure, 360 | aggregation: Aggregation.mean, 361 | ), 362 | surface_pressure_min( 363 | Variable.surface_pressure, 364 | aggregation: Aggregation.minimum, 365 | ), 366 | surface_pressure_max( 367 | Variable.surface_pressure, 368 | aggregation: Aggregation.maximum, 369 | ), 370 | relative_humidity_2m_mean( 371 | Variable.relative_humidity, 372 | aggregation: Aggregation.mean, 373 | altitude: 2, 374 | ), 375 | relative_humidity_2m_min( 376 | Variable.relative_humidity, 377 | aggregation: Aggregation.minimum, 378 | altitude: 2, 379 | ), 380 | relative_humidity_2m_max( 381 | Variable.relative_humidity, 382 | aggregation: Aggregation.maximum, 383 | altitude: 2, 384 | ), 385 | cape_mean( 386 | Variable.cape, 387 | aggregation: Aggregation.mean, 388 | ), 389 | cape_min( 390 | Variable.cape, 391 | aggregation: Aggregation.minimum, 392 | ), 393 | cape_max( 394 | Variable.cape, 395 | aggregation: Aggregation.maximum, 396 | ), 397 | dew_point_2m_mean( 398 | Variable.dew_point, 399 | aggregation: Aggregation.mean, 400 | altitude: 2, 401 | ), 402 | dew_point_2m_min( 403 | Variable.dew_point, 404 | aggregation: Aggregation.minimum, 405 | altitude: 2, 406 | ), 407 | dew_point_2m_max( 408 | Variable.dew_point, 409 | aggregation: Aggregation.maximum, 410 | altitude: 2, 411 | ), 412 | et0_fao_evapotranspiration( 413 | Variable.et0_fao_evapotranspiration, 414 | ), 415 | shortwave_radiation_sum( 416 | Variable.shortwave_radiation, 417 | aggregation: Aggregation.sum, 418 | ), 419 | ; 420 | 421 | @override 422 | final Variable variable; 423 | @override 424 | final int altitude; 425 | @override 426 | final Aggregation aggregation; 427 | const EnsembleDaily( 428 | this.variable, { 429 | this.altitude = 0, 430 | this.aggregation = Aggregation.none, 431 | }); 432 | 433 | static final Map hashes = 434 | makeHashes(EnsembleDaily.values); 435 | } 436 | -------------------------------------------------------------------------------- /lib/src/enums/flood.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../apis/flood.dart'; 3 | import '../weather_api_openmeteo_sdk_generated.dart'; 4 | 5 | // Generated Variable Enums for Flood 6 | 7 | enum FloodDaily with Parameter { 8 | river_discharge( 9 | Variable.river_discharge, 10 | ), 11 | river_discharge_mean( 12 | Variable.river_discharge, 13 | aggregation: Aggregation.mean, 14 | ), 15 | river_discharge_median( 16 | Variable.river_discharge, 17 | aggregation: Aggregation.median, 18 | ), 19 | river_discharge_max( 20 | Variable.river_discharge, 21 | aggregation: Aggregation.maximum, 22 | ), 23 | river_discharge_min( 24 | Variable.river_discharge, 25 | aggregation: Aggregation.minimum, 26 | ), 27 | river_discharge_p25( 28 | Variable.river_discharge, 29 | aggregation: Aggregation.p25, 30 | ), 31 | river_discharge_p75( 32 | Variable.river_discharge, 33 | aggregation: Aggregation.p75, 34 | ), 35 | ; 36 | 37 | @override 38 | final Variable variable; 39 | @override 40 | final Aggregation aggregation; 41 | const FloodDaily( 42 | this.variable, { 43 | this.aggregation = Aggregation.none, 44 | }); 45 | 46 | static final Map hashes = makeHashes(FloodDaily.values); 47 | } 48 | -------------------------------------------------------------------------------- /lib/src/enums/historical.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../apis/historical.dart'; 3 | import '../weather_api_openmeteo_sdk_generated.dart'; 4 | 5 | // Generated Variable Enums for Historical 6 | 7 | enum HistoricalHourly with Parameter { 8 | temperature_2m( 9 | Variable.temperature, 10 | altitude: 2, 11 | ), 12 | relative_humidity_2m( 13 | Variable.relative_humidity, 14 | altitude: 2, 15 | ), 16 | dew_point_2m( 17 | Variable.dew_point, 18 | altitude: 2, 19 | ), 20 | apparent_temperature( 21 | Variable.apparent_temperature, 22 | altitude: 2, 23 | ), 24 | precipitation( 25 | Variable.precipitation, 26 | ), 27 | rain( 28 | Variable.rain, 29 | ), 30 | snowfall( 31 | Variable.snowfall, 32 | ), 33 | snow_depth( 34 | Variable.snow_depth, 35 | ), 36 | weather_code( 37 | Variable.weather_code, 38 | ), 39 | pressure_msl( 40 | Variable.pressure_msl, 41 | ), 42 | surface_pressure( 43 | Variable.surface_pressure, 44 | ), 45 | cloud_cover( 46 | Variable.cloud_cover, 47 | ), 48 | cloud_cover_low( 49 | Variable.cloud_cover_low, 50 | ), 51 | cloud_cover_mid( 52 | Variable.cloud_cover_mid, 53 | ), 54 | cloud_cover_high( 55 | Variable.cloud_cover_high, 56 | ), 57 | et0_fao_evapotranspiration( 58 | Variable.et0_fao_evapotranspiration, 59 | ), 60 | vapour_pressure_deficit( 61 | Variable.vapour_pressure_deficit, 62 | ), 63 | wind_speed_10m( 64 | Variable.wind_speed, 65 | altitude: 10, 66 | ), 67 | wind_speed_100m( 68 | Variable.wind_speed, 69 | altitude: 100, 70 | ), 71 | wind_direction_10m( 72 | Variable.wind_direction, 73 | altitude: 10, 74 | ), 75 | wind_direction_100m( 76 | Variable.wind_direction, 77 | altitude: 100, 78 | ), 79 | wind_gusts_10m( 80 | Variable.wind_gusts, 81 | altitude: 10, 82 | ), 83 | soil_temperature_0_to_7cm( 84 | Variable.soil_temperature, 85 | depth: 0, 86 | depthTo: 7, 87 | ), 88 | soil_temperature_7_to_28cm( 89 | Variable.soil_temperature, 90 | depth: 7, 91 | depthTo: 28, 92 | ), 93 | soil_temperature_28_to_100cm( 94 | Variable.soil_temperature, 95 | depth: 28, 96 | depthTo: 100, 97 | ), 98 | soil_temperature_100_to_255cm( 99 | Variable.soil_temperature, 100 | depth: 100, 101 | depthTo: 255, 102 | ), 103 | soil_moisture_0_to_7cm( 104 | Variable.soil_moisture, 105 | depth: 0, 106 | depthTo: 7, 107 | ), 108 | soil_moisture_7_to_28cm( 109 | Variable.soil_moisture, 110 | depth: 7, 111 | depthTo: 28, 112 | ), 113 | soil_moisture_28_to_100cm( 114 | Variable.soil_moisture, 115 | depth: 28, 116 | depthTo: 100, 117 | ), 118 | soil_moisture_100_to_255cm( 119 | Variable.soil_moisture, 120 | depth: 100, 121 | depthTo: 255, 122 | ), 123 | boundary_layer_height( 124 | Variable.boundary_layer_height, 125 | ), 126 | wet_bulb_temperature_2m( 127 | Variable.wet_bulb_temperature, 128 | altitude: 2, 129 | ), 130 | total_column_integrated_water_vapour( 131 | Variable.total_column_integrated_water_vapour, 132 | ), 133 | is_day( 134 | Variable.is_day, 135 | ), 136 | sunshine_duration( 137 | Variable.sunshine_duration, 138 | ), 139 | albedo( 140 | Variable.albedo, 141 | ), 142 | snow_depth_water_equivalent( 143 | Variable.snow_depth_water_equivalent, 144 | ), 145 | shortwave_radiation( 146 | Variable.shortwave_radiation, 147 | ), 148 | direct_radiation( 149 | Variable.direct_radiation, 150 | ), 151 | diffuse_radiation( 152 | Variable.diffuse_radiation, 153 | ), 154 | direct_normal_irradiance( 155 | Variable.direct_normal_irradiance, 156 | ), 157 | global_tilted_irradiance( 158 | Variable.global_tilted_irradiance, 159 | ), 160 | terrestrial_radiation( 161 | Variable.terrestrial_radiation, 162 | ), 163 | shortwave_radiation_instant( 164 | Variable.shortwave_radiation_instant, 165 | ), 166 | direct_radiation_instant( 167 | Variable.direct_radiation_instant, 168 | ), 169 | diffuse_radiation_instant( 170 | Variable.diffuse_radiation_instant, 171 | ), 172 | direct_normal_irradiance_instant( 173 | Variable.direct_normal_irradiance_instant, 174 | ), 175 | global_tilted_irradiance_instant( 176 | Variable.global_tilted_irradiance_instant, 177 | ), 178 | terrestrial_radiation_instant( 179 | Variable.terrestrial_radiation_instant, 180 | ), 181 | temperature_2m_spread( 182 | Variable.temperature, 183 | aggregation: Aggregation.spread, 184 | altitude: 2, 185 | ), 186 | dew_point_2m_spread( 187 | Variable.dew_point, 188 | aggregation: Aggregation.spread, 189 | altitude: 2, 190 | ), 191 | precipitation_spread( 192 | Variable.precipitation, 193 | aggregation: Aggregation.spread, 194 | ), 195 | snowfall_spread( 196 | Variable.snowfall, 197 | aggregation: Aggregation.spread, 198 | ), 199 | shortwave_radiation_spread( 200 | Variable.shortwave_radiation, 201 | aggregation: Aggregation.spread, 202 | ), 203 | direct_radiation_spread( 204 | Variable.direct_radiation, 205 | aggregation: Aggregation.spread, 206 | ), 207 | pressure_msl_spread( 208 | Variable.pressure_msl, 209 | aggregation: Aggregation.spread, 210 | ), 211 | cloud_cover_low_spread( 212 | Variable.cloud_cover_low, 213 | aggregation: Aggregation.spread, 214 | ), 215 | cloud_cover_mid_spread( 216 | Variable.cloud_cover_mid, 217 | aggregation: Aggregation.spread, 218 | ), 219 | cloud_cover_high_spread( 220 | Variable.cloud_cover_high, 221 | aggregation: Aggregation.spread, 222 | ), 223 | wind_speed_10m_spread( 224 | Variable.wind_speed, 225 | aggregation: Aggregation.spread, 226 | altitude: 10, 227 | ), 228 | wind_speed_100m_spread( 229 | Variable.wind_speed, 230 | aggregation: Aggregation.spread, 231 | altitude: 100, 232 | ), 233 | wind_direction_10m_spread( 234 | Variable.wind_direction, 235 | aggregation: Aggregation.spread, 236 | altitude: 10, 237 | ), 238 | wind_direction_100m_spread( 239 | Variable.wind_direction, 240 | aggregation: Aggregation.spread, 241 | altitude: 100, 242 | ), 243 | wind_gusts_10m_spread( 244 | Variable.wind_gusts, 245 | aggregation: Aggregation.spread, 246 | altitude: 10, 247 | ), 248 | soil_temperature_0_to_7cm_spread( 249 | Variable.soil_temperature, 250 | aggregation: Aggregation.spread, 251 | depth: 0, 252 | depthTo: 7, 253 | ), 254 | soil_temperature_7_to_28cm_spread( 255 | Variable.soil_temperature, 256 | aggregation: Aggregation.spread, 257 | depth: 7, 258 | depthTo: 28, 259 | ), 260 | soil_temperature_28_to_100cm_spread( 261 | Variable.soil_temperature, 262 | aggregation: Aggregation.spread, 263 | depth: 28, 264 | depthTo: 100, 265 | ), 266 | soil_temperature_100_to_255cm_spread( 267 | Variable.soil_temperature, 268 | aggregation: Aggregation.spread, 269 | depth: 100, 270 | depthTo: 255, 271 | ), 272 | soil_moisture_0_to_7cm_spread( 273 | Variable.soil_moisture, 274 | aggregation: Aggregation.spread, 275 | depth: 0, 276 | depthTo: 7, 277 | ), 278 | soil_moisture_7_to_28cm_spread( 279 | Variable.soil_moisture, 280 | aggregation: Aggregation.spread, 281 | depth: 7, 282 | depthTo: 28, 283 | ), 284 | soil_moisture_28_to_100cm_spread( 285 | Variable.soil_moisture, 286 | aggregation: Aggregation.spread, 287 | depth: 28, 288 | depthTo: 100, 289 | ), 290 | soil_moisture_100_to_255cm_spread( 291 | Variable.soil_moisture, 292 | aggregation: Aggregation.spread, 293 | depth: 100, 294 | depthTo: 255, 295 | ), 296 | ; 297 | 298 | @override 299 | final Variable variable; 300 | @override 301 | final int altitude; 302 | @override 303 | final int depth; 304 | @override 305 | final int depthTo; 306 | @override 307 | final Aggregation aggregation; 308 | const HistoricalHourly( 309 | this.variable, { 310 | this.altitude = 0, 311 | this.depth = 0, 312 | this.depthTo = 0, 313 | this.aggregation = Aggregation.none, 314 | }); 315 | 316 | static final Map hashes = 317 | makeHashes(HistoricalHourly.values); 318 | } 319 | 320 | enum HistoricalDaily with Parameter { 321 | weather_code( 322 | Variable.weather_code, 323 | ), 324 | temperature_2m_mean( 325 | Variable.temperature, 326 | aggregation: Aggregation.mean, 327 | altitude: 2, 328 | ), 329 | temperature_2m_max( 330 | Variable.temperature, 331 | aggregation: Aggregation.maximum, 332 | altitude: 2, 333 | ), 334 | temperature_2m_min( 335 | Variable.temperature, 336 | aggregation: Aggregation.minimum, 337 | altitude: 2, 338 | ), 339 | apparent_temperature_mean( 340 | Variable.apparent_temperature, 341 | aggregation: Aggregation.mean, 342 | altitude: 2, 343 | ), 344 | apparent_temperature_max( 345 | Variable.apparent_temperature, 346 | aggregation: Aggregation.maximum, 347 | altitude: 2, 348 | ), 349 | apparent_temperature_min( 350 | Variable.apparent_temperature, 351 | aggregation: Aggregation.minimum, 352 | altitude: 2, 353 | ), 354 | sunrise( 355 | Variable.sunrise, 356 | ), 357 | sunset( 358 | Variable.sunset, 359 | ), 360 | daylight_duration( 361 | Variable.daylight_duration, 362 | ), 363 | sunshine_duration( 364 | Variable.sunshine_duration, 365 | ), 366 | precipitation_sum( 367 | Variable.precipitation, 368 | aggregation: Aggregation.sum, 369 | ), 370 | rain_sum( 371 | Variable.rain, 372 | aggregation: Aggregation.sum, 373 | ), 374 | snowfall_sum( 375 | Variable.snowfall, 376 | aggregation: Aggregation.sum, 377 | ), 378 | precipitation_hours( 379 | Variable.precipitation_hours, 380 | ), 381 | wind_speed_10m_max( 382 | Variable.wind_speed, 383 | aggregation: Aggregation.maximum, 384 | altitude: 10, 385 | ), 386 | wind_gusts_10m_max( 387 | Variable.wind_gusts, 388 | aggregation: Aggregation.maximum, 389 | altitude: 10, 390 | ), 391 | wind_direction_10m_dominant( 392 | Variable.wind_direction, 393 | aggregation: Aggregation.dominant, 394 | altitude: 10, 395 | ), 396 | shortwave_radiation_sum( 397 | Variable.shortwave_radiation, 398 | aggregation: Aggregation.sum, 399 | ), 400 | et0_fao_evapotranspiration( 401 | Variable.et0_fao_evapotranspiration, 402 | ), 403 | cape_mean( 404 | Variable.cape, 405 | aggregation: Aggregation.mean, 406 | ), 407 | cape_max( 408 | Variable.cape, 409 | aggregation: Aggregation.maximum, 410 | ), 411 | cape_min( 412 | Variable.cape, 413 | aggregation: Aggregation.minimum, 414 | ), 415 | cloud_cover_mean( 416 | Variable.cloud_cover, 417 | aggregation: Aggregation.mean, 418 | ), 419 | cloud_cover_max( 420 | Variable.cloud_cover, 421 | aggregation: Aggregation.maximum, 422 | ), 423 | cloud_cover_min( 424 | Variable.cloud_cover, 425 | aggregation: Aggregation.minimum, 426 | ), 427 | dew_point_2m_mean( 428 | Variable.dew_point, 429 | aggregation: Aggregation.mean, 430 | altitude: 2, 431 | ), 432 | dew_point_2m_max( 433 | Variable.dew_point, 434 | aggregation: Aggregation.maximum, 435 | altitude: 2, 436 | ), 437 | dew_point_2m_min( 438 | Variable.dew_point, 439 | aggregation: Aggregation.minimum, 440 | altitude: 2, 441 | ), 442 | et0_fao_evapotranspiration_sum( 443 | Variable.et0_fao_evapotranspiration, 444 | aggregation: Aggregation.sum, 445 | ), 446 | leaf_wetness_probability_mean( 447 | Variable.leaf_wetness_probability, 448 | aggregation: Aggregation.mean, 449 | ), 450 | precipitation_probability_mean( 451 | Variable.precipitation_probability, 452 | aggregation: Aggregation.mean, 453 | ), 454 | precipitation_probability_min( 455 | Variable.precipitation_probability, 456 | aggregation: Aggregation.minimum, 457 | ), 458 | relative_humidity_2m_mean( 459 | Variable.relative_humidity, 460 | aggregation: Aggregation.mean, 461 | altitude: 2, 462 | ), 463 | relative_humidity_2m_max( 464 | Variable.relative_humidity, 465 | aggregation: Aggregation.maximum, 466 | altitude: 2, 467 | ), 468 | relative_humidity_2m_min( 469 | Variable.relative_humidity, 470 | aggregation: Aggregation.minimum, 471 | altitude: 2, 472 | ), 473 | snowfall_water_equivalent_sum( 474 | Variable.snowfall_water_equivalent, 475 | aggregation: Aggregation.sum, 476 | ), 477 | pressure_msl_mean( 478 | Variable.pressure_msl, 479 | aggregation: Aggregation.mean, 480 | ), 481 | pressure_msl_max( 482 | Variable.pressure_msl, 483 | aggregation: Aggregation.maximum, 484 | ), 485 | pressure_msl_min( 486 | Variable.pressure_msl, 487 | aggregation: Aggregation.minimum, 488 | ), 489 | surface_pressure_mean( 490 | Variable.surface_pressure, 491 | aggregation: Aggregation.mean, 492 | ), 493 | surface_pressure_max( 494 | Variable.surface_pressure, 495 | aggregation: Aggregation.maximum, 496 | ), 497 | surface_pressure_min( 498 | Variable.surface_pressure, 499 | aggregation: Aggregation.minimum, 500 | ), 501 | updraft_max( 502 | Variable.updraft, 503 | aggregation: Aggregation.maximum, 504 | ), 505 | visibility_mean( 506 | Variable.visibility, 507 | aggregation: Aggregation.mean, 508 | ), 509 | visibility_min( 510 | Variable.visibility, 511 | aggregation: Aggregation.minimum, 512 | ), 513 | visibility_max( 514 | Variable.visibility, 515 | aggregation: Aggregation.maximum, 516 | ), 517 | wind_gusts_10m_mean( 518 | Variable.wind_gusts, 519 | aggregation: Aggregation.mean, 520 | altitude: 10, 521 | ), 522 | wind_speed_10m_mean( 523 | Variable.wind_speed, 524 | aggregation: Aggregation.mean, 525 | altitude: 10, 526 | ), 527 | wind_gusts_10m_min( 528 | Variable.wind_gusts, 529 | aggregation: Aggregation.minimum, 530 | altitude: 10, 531 | ), 532 | wind_speed_10m_min( 533 | Variable.wind_speed, 534 | aggregation: Aggregation.minimum, 535 | altitude: 10, 536 | ), 537 | wet_bulb_temperature_2m_mean( 538 | Variable.wet_bulb_temperature, 539 | aggregation: Aggregation.mean, 540 | altitude: 2, 541 | ), 542 | wet_bulb_temperature_2m_max( 543 | Variable.wet_bulb_temperature, 544 | aggregation: Aggregation.maximum, 545 | altitude: 2, 546 | ), 547 | wet_bulb_temperature_2m_min( 548 | Variable.wet_bulb_temperature, 549 | aggregation: Aggregation.minimum, 550 | altitude: 2, 551 | ), 552 | vapour_pressure_deficit_max( 553 | Variable.vapour_pressure_deficit, 554 | aggregation: Aggregation.maximum, 555 | ), 556 | soil_moisture_0_to_100cm_mean( 557 | Variable.soil_moisture, 558 | aggregation: Aggregation.mean, 559 | depth: 0, 560 | depthTo: 100, 561 | ), 562 | soil_moisture_0_to_10cm_mean( 563 | Variable.soil_moisture, 564 | aggregation: Aggregation.mean, 565 | depth: 0, 566 | depthTo: 10, 567 | ), 568 | soil_moisture_0_to_7cm_mean( 569 | Variable.soil_moisture, 570 | aggregation: Aggregation.mean, 571 | depth: 0, 572 | depthTo: 7, 573 | ), 574 | soil_moisture_28_to_100cm_mean( 575 | Variable.soil_moisture, 576 | aggregation: Aggregation.mean, 577 | depth: 28, 578 | depthTo: 100, 579 | ), 580 | soil_moisture_7_to_28cm_mean( 581 | Variable.soil_moisture, 582 | aggregation: Aggregation.mean, 583 | depth: 7, 584 | depthTo: 28, 585 | ), 586 | soil_temperature_0_to_100cm_mean( 587 | Variable.soil_temperature, 588 | aggregation: Aggregation.mean, 589 | depth: 0, 590 | depthTo: 100, 591 | ), 592 | soil_temperature_0_to_7cm_mean( 593 | Variable.soil_temperature, 594 | aggregation: Aggregation.mean, 595 | depth: 0, 596 | depthTo: 7, 597 | ), 598 | soil_temperature_28_to_100cm_mean( 599 | Variable.soil_temperature, 600 | aggregation: Aggregation.mean, 601 | depth: 28, 602 | depthTo: 100, 603 | ), 604 | soil_temperature_7_to_28cm_mean( 605 | Variable.soil_temperature, 606 | aggregation: Aggregation.mean, 607 | depth: 7, 608 | depthTo: 28, 609 | ), 610 | ; 611 | 612 | @override 613 | final Variable variable; 614 | @override 615 | final int altitude; 616 | @override 617 | final int depth; 618 | @override 619 | final int depthTo; 620 | @override 621 | final Aggregation aggregation; 622 | const HistoricalDaily( 623 | this.variable, { 624 | this.altitude = 0, 625 | this.depth = 0, 626 | this.depthTo = 0, 627 | this.aggregation = Aggregation.none, 628 | }); 629 | 630 | static final Map hashes = 631 | makeHashes(HistoricalDaily.values); 632 | } 633 | -------------------------------------------------------------------------------- /lib/src/enums/marine.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../apis/marine.dart'; 3 | import '../weather_api_openmeteo_sdk_generated.dart'; 4 | 5 | // Generated Variable Enums for Marine 6 | 7 | enum MarineMinutely15 with Parameter { 8 | ocean_current_velocity( 9 | Variable.ocean_current_velocity, 10 | ), 11 | ocean_current_direction( 12 | Variable.ocean_current_direction, 13 | ), 14 | sea_level_height_msl( 15 | Variable.sea_level_height_msl, 16 | ), 17 | ; 18 | 19 | @override 20 | final Variable variable; 21 | const MarineMinutely15(this.variable); 22 | 23 | static final Map hashes = 24 | makeHashes(MarineMinutely15.values); 25 | } 26 | 27 | enum MarineCurrent with Parameter { 28 | wave_height( 29 | Variable.wave_height, 30 | ), 31 | wave_direction( 32 | Variable.wave_direction, 33 | ), 34 | wave_period( 35 | Variable.wave_period, 36 | ), 37 | wind_wave_peak_period( 38 | Variable.wind_wave_peak_period, 39 | ), 40 | wind_wave_height( 41 | Variable.wind_wave_height, 42 | ), 43 | wind_wave_direction( 44 | Variable.wind_wave_direction, 45 | ), 46 | wind_wave_period( 47 | Variable.wind_wave_period, 48 | ), 49 | swell_wave_height( 50 | Variable.swell_wave_height, 51 | ), 52 | swell_wave_direction( 53 | Variable.swell_wave_direction, 54 | ), 55 | swell_wave_period( 56 | Variable.swell_wave_period, 57 | ), 58 | swell_wave_peak_period( 59 | Variable.swell_wave_peak_period, 60 | ), 61 | secondary_swell_wave_height( 62 | Variable.secondary_swell_wave_height, 63 | ), 64 | secondary_swell_wave_period( 65 | Variable.secondary_swell_wave_period, 66 | ), 67 | secondary_swell_wave_direction( 68 | Variable.secondary_swell_wave_direction, 69 | ), 70 | // Dunno, the upstream API returns nothing for these ones. 71 | // tertiary_swell_wave_height( 72 | // Variable.tertiary_swell_wave_height, 73 | // ), 74 | // tertiary_swell_wave_period( 75 | // Variable.tertiary_swell_wave_period, 76 | // ), 77 | // tertiary_swell_wave_direction( 78 | // Variable.tertiary_swell_wave_direction, 79 | // ), 80 | sea_level_height_msl( 81 | Variable.sea_level_height_msl, 82 | ), 83 | sea_surface_temperature( 84 | Variable.sea_surface_temperature, 85 | ), 86 | ocean_current_velocity( 87 | Variable.ocean_current_velocity, 88 | ), 89 | ocean_current_direction( 90 | Variable.ocean_current_direction, 91 | ), 92 | ; 93 | 94 | @override 95 | final Variable variable; 96 | const MarineCurrent(this.variable); 97 | 98 | static final Map hashes = 99 | makeHashes(MarineCurrent.values); 100 | } 101 | 102 | enum MarineHourly with Parameter { 103 | wave_height( 104 | Variable.wave_height, 105 | ), 106 | wave_direction( 107 | Variable.wave_direction, 108 | ), 109 | wave_period( 110 | Variable.wave_period, 111 | ), 112 | wind_wave_peak_period( 113 | Variable.wind_wave_peak_period, 114 | ), 115 | wind_wave_height( 116 | Variable.wind_wave_height, 117 | ), 118 | wind_wave_direction( 119 | Variable.wind_wave_direction, 120 | ), 121 | wind_wave_period( 122 | Variable.wind_wave_period, 123 | ), 124 | swell_wave_height( 125 | Variable.swell_wave_height, 126 | ), 127 | swell_wave_direction( 128 | Variable.swell_wave_direction, 129 | ), 130 | swell_wave_period( 131 | Variable.swell_wave_period, 132 | ), 133 | swell_wave_peak_period( 134 | Variable.swell_wave_peak_period, 135 | ), 136 | secondary_swell_wave_height( 137 | Variable.secondary_swell_wave_height, 138 | ), 139 | secondary_swell_wave_period( 140 | Variable.secondary_swell_wave_period, 141 | ), 142 | secondary_swell_wave_direction( 143 | Variable.secondary_swell_wave_direction, 144 | ), 145 | tertiary_swell_wave_height( 146 | Variable.tertiary_swell_wave_height, 147 | ), 148 | tertiary_swell_wave_period( 149 | Variable.tertiary_swell_wave_period, 150 | ), 151 | tertiary_swell_wave_direction( 152 | Variable.tertiary_swell_wave_direction, 153 | ), 154 | sea_level_height_msl( 155 | Variable.sea_level_height_msl, 156 | ), 157 | sea_surface_temperature( 158 | Variable.sea_surface_temperature, 159 | ), 160 | ocean_current_velocity( 161 | Variable.ocean_current_velocity, 162 | ), 163 | ocean_current_direction( 164 | Variable.ocean_current_direction, 165 | ), 166 | invert_barometer_height( 167 | Variable.invert_barometer_height, 168 | ), 169 | ; 170 | 171 | @override 172 | final Variable variable; 173 | const MarineHourly(this.variable); 174 | 175 | static final Map hashes = makeHashes(MarineHourly.values); 176 | } 177 | 178 | enum MarineDaily with Parameter { 179 | wave_height_max( 180 | Variable.wave_height, 181 | aggregation: Aggregation.maximum, 182 | ), 183 | wave_direction_dominant( 184 | Variable.wave_direction, 185 | aggregation: Aggregation.dominant, 186 | ), 187 | wave_period_max( 188 | Variable.wave_period, 189 | aggregation: Aggregation.maximum, 190 | ), 191 | wind_wave_height_max( 192 | Variable.wind_wave_height, 193 | aggregation: Aggregation.maximum, 194 | ), 195 | wind_wave_direction_dominant( 196 | Variable.wind_wave_direction, 197 | aggregation: Aggregation.dominant, 198 | ), 199 | wind_wave_period_max( 200 | Variable.wind_wave_period, 201 | aggregation: Aggregation.maximum, 202 | ), 203 | wind_wave_peak_period_max( 204 | Variable.wind_wave_peak_period, 205 | aggregation: Aggregation.maximum, 206 | ), 207 | swell_wave_height_max( 208 | Variable.swell_wave_height, 209 | aggregation: Aggregation.maximum, 210 | ), 211 | swell_wave_direction_dominant( 212 | Variable.swell_wave_direction, 213 | aggregation: Aggregation.dominant, 214 | ), 215 | swell_wave_period_max( 216 | Variable.swell_wave_period, 217 | aggregation: Aggregation.maximum, 218 | ), 219 | swell_wave_peak_period_max( 220 | Variable.swell_wave_peak_period, 221 | aggregation: Aggregation.maximum, 222 | ), 223 | ; 224 | 225 | @override 226 | final Variable variable; 227 | @override 228 | final Aggregation aggregation; 229 | const MarineDaily( 230 | this.variable, { 231 | this.aggregation = Aggregation.none, 232 | }); 233 | 234 | static final Map hashes = makeHashes(MarineDaily.values); 235 | } 236 | -------------------------------------------------------------------------------- /lib/src/enums/satellite_radiation.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../apis/satellite_radiation.dart'; 3 | import '../weather_api_openmeteo_sdk_generated.dart'; 4 | 5 | // Generated Variable Enums for SatelliteRadiation 6 | 7 | enum SatelliteRadiationHourly with Parameter { 8 | shortwave_radiation( 9 | Variable.shortwave_radiation, 10 | ), 11 | direct_radiation( 12 | Variable.direct_radiation, 13 | ), 14 | diffuse_radiation( 15 | Variable.diffuse_radiation, 16 | ), 17 | direct_normal_irradiance( 18 | Variable.direct_normal_irradiance, 19 | ), 20 | global_tilted_irradiance( 21 | Variable.global_tilted_irradiance, 22 | ), 23 | terrestrial_radiation( 24 | Variable.terrestrial_radiation, 25 | ), 26 | shortwave_radiation_instant( 27 | Variable.shortwave_radiation_instant, 28 | ), 29 | direct_radiation_instant( 30 | Variable.direct_radiation_instant, 31 | ), 32 | diffuse_radiation_instant( 33 | Variable.diffuse_radiation_instant, 34 | ), 35 | direct_normal_irradiance_instant( 36 | Variable.direct_normal_irradiance_instant, 37 | ), 38 | global_tilted_irradiance_instant( 39 | Variable.global_tilted_irradiance_instant, 40 | ), 41 | terrestrial_radiation_instant( 42 | Variable.terrestrial_radiation_instant, 43 | ), 44 | is_day( 45 | Variable.is_day, 46 | ), 47 | sunshine_duration( 48 | Variable.sunshine_duration, 49 | ), 50 | ; 51 | 52 | @override 53 | final Variable variable; 54 | const SatelliteRadiationHourly(this.variable); 55 | 56 | static final Map hashes = 57 | makeHashes(SatelliteRadiationHourly.values); 58 | } 59 | 60 | enum SatelliteRadiationDaily with Parameter { 61 | sunrise( 62 | Variable.sunrise, 63 | ), 64 | sunset( 65 | Variable.sunset, 66 | ), 67 | daylight_duration( 68 | Variable.daylight_duration, 69 | ), 70 | sunshine_duration( 71 | Variable.sunshine_duration, 72 | ), 73 | shortwave_radiation_sum( 74 | Variable.shortwave_radiation, 75 | aggregation: Aggregation.sum, 76 | ), 77 | ; 78 | 79 | @override 80 | final Variable variable; 81 | @override 82 | final Aggregation aggregation; 83 | const SatelliteRadiationDaily( 84 | this.variable, { 85 | this.aggregation = Aggregation.none, 86 | }); 87 | 88 | static final Map hashes = 89 | makeHashes(SatelliteRadiationDaily.values); 90 | } 91 | -------------------------------------------------------------------------------- /lib/src/enums/weather.dart: -------------------------------------------------------------------------------- 1 | import '../api.dart'; 2 | import '../apis/weather.dart'; 3 | import '../weather_api_openmeteo_sdk_generated.dart'; 4 | 5 | // Generated Variable Enums for Weather 6 | 7 | enum WeatherMinutely15 with Parameter { 8 | temperature_2m( 9 | Variable.temperature, 10 | altitude: 2, 11 | ), 12 | relative_humidity_2m( 13 | Variable.relative_humidity, 14 | altitude: 2, 15 | ), 16 | dew_point_2m( 17 | Variable.dew_point, 18 | altitude: 2, 19 | ), 20 | apparent_temperature( 21 | Variable.apparent_temperature, 22 | altitude: 2, 23 | ), 24 | precipitation( 25 | Variable.precipitation, 26 | ), 27 | rain( 28 | Variable.rain, 29 | ), 30 | snowfall( 31 | Variable.snowfall, 32 | ), 33 | snowfall_height( 34 | Variable.snowfall_height, 35 | ), 36 | freezing_level_height( 37 | Variable.freezing_level_height, 38 | ), 39 | sunshine_duration( 40 | Variable.sunshine_duration, 41 | ), 42 | weather_code( 43 | Variable.weather_code, 44 | ), 45 | wind_speed_10m( 46 | Variable.wind_speed, 47 | altitude: 10, 48 | ), 49 | wind_speed_80m( 50 | Variable.wind_speed, 51 | altitude: 80, 52 | ), 53 | wind_direction_10m( 54 | Variable.wind_direction, 55 | altitude: 10, 56 | ), 57 | wind_direction_80m( 58 | Variable.wind_direction, 59 | altitude: 80, 60 | ), 61 | wind_gusts_10m( 62 | Variable.wind_gusts, 63 | altitude: 10, 64 | ), 65 | visibility( 66 | Variable.visibility, 67 | ), 68 | cape( 69 | Variable.cape, 70 | ), 71 | lightning_potential( 72 | Variable.lightning_potential, 73 | ), 74 | is_day( 75 | Variable.is_day, 76 | ), 77 | shortwave_radiation( 78 | Variable.shortwave_radiation, 79 | ), 80 | direct_radiation( 81 | Variable.direct_radiation, 82 | ), 83 | diffuse_radiation( 84 | Variable.diffuse_radiation, 85 | ), 86 | direct_normal_irradiance( 87 | Variable.direct_normal_irradiance, 88 | ), 89 | global_tilted_irradiance( 90 | Variable.global_tilted_irradiance, 91 | ), 92 | terrestrial_radiation( 93 | Variable.terrestrial_radiation, 94 | ), 95 | shortwave_radiation_instant( 96 | Variable.shortwave_radiation_instant, 97 | ), 98 | direct_radiation_instant( 99 | Variable.direct_radiation_instant, 100 | ), 101 | diffuse_radiation_instant( 102 | Variable.diffuse_radiation_instant, 103 | ), 104 | direct_normal_irradiance_instant( 105 | Variable.direct_normal_irradiance_instant, 106 | ), 107 | global_tilted_irradiance_instant( 108 | Variable.global_tilted_irradiance_instant, 109 | ), 110 | terrestrial_radiation_instant( 111 | Variable.terrestrial_radiation_instant, 112 | ), 113 | ; 114 | 115 | @override 116 | final Variable variable; 117 | @override 118 | final int altitude; 119 | const WeatherMinutely15( 120 | this.variable, { 121 | this.altitude = 0, 122 | }); 123 | 124 | static final Map hashes = 125 | makeHashes(WeatherMinutely15.values); 126 | } 127 | 128 | enum WeatherCurrent with Parameter { 129 | temperature_2m( 130 | Variable.temperature, 131 | altitude: 2, 132 | ), 133 | relative_humidity_2m( 134 | Variable.relative_humidity, 135 | altitude: 2, 136 | ), 137 | apparent_temperature( 138 | Variable.apparent_temperature, 139 | altitude: 2, 140 | ), 141 | is_day( 142 | Variable.is_day, 143 | ), 144 | precipitation( 145 | Variable.precipitation, 146 | ), 147 | rain( 148 | Variable.rain, 149 | ), 150 | showers( 151 | Variable.showers, 152 | ), 153 | snowfall( 154 | Variable.snowfall, 155 | ), 156 | weather_code( 157 | Variable.weather_code, 158 | ), 159 | cloud_cover( 160 | Variable.cloud_cover, 161 | ), 162 | pressure_msl( 163 | Variable.pressure_msl, 164 | ), 165 | surface_pressure( 166 | Variable.surface_pressure, 167 | ), 168 | wind_speed_10m( 169 | Variable.wind_speed, 170 | altitude: 10, 171 | ), 172 | wind_direction_10m( 173 | Variable.wind_direction, 174 | altitude: 10, 175 | ), 176 | wind_gusts_10m( 177 | Variable.wind_gusts, 178 | altitude: 10, 179 | ), 180 | ; 181 | 182 | @override 183 | final Variable variable; 184 | @override 185 | final int altitude; 186 | const WeatherCurrent( 187 | this.variable, { 188 | this.altitude = 0, 189 | }); 190 | 191 | static final Map hashes = 192 | makeHashes(WeatherCurrent.values); 193 | } 194 | 195 | enum WeatherHourly with Parameter { 196 | temperature_2m( 197 | Variable.temperature, 198 | altitude: 2, 199 | ), 200 | relative_humidity_2m( 201 | Variable.relative_humidity, 202 | altitude: 2, 203 | ), 204 | dew_point_2m( 205 | Variable.dew_point, 206 | altitude: 2, 207 | ), 208 | apparent_temperature( 209 | Variable.apparent_temperature, 210 | altitude: 2, 211 | ), 212 | precipitation_probability( 213 | Variable.precipitation_probability, 214 | ), 215 | precipitation( 216 | Variable.precipitation, 217 | ), 218 | rain( 219 | Variable.rain, 220 | ), 221 | showers( 222 | Variable.showers, 223 | ), 224 | snowfall( 225 | Variable.snowfall, 226 | ), 227 | snow_depth( 228 | Variable.snow_depth, 229 | ), 230 | weather_code( 231 | Variable.weather_code, 232 | ), 233 | pressure_msl( 234 | Variable.pressure_msl, 235 | ), 236 | surface_pressure( 237 | Variable.surface_pressure, 238 | ), 239 | cloud_cover( 240 | Variable.cloud_cover, 241 | ), 242 | cloud_cover_low( 243 | Variable.cloud_cover_low, 244 | ), 245 | cloud_cover_mid( 246 | Variable.cloud_cover_mid, 247 | ), 248 | cloud_cover_high( 249 | Variable.cloud_cover_high, 250 | ), 251 | visibility( 252 | Variable.visibility, 253 | ), 254 | evapotranspiration( 255 | Variable.evapotranspiration, 256 | ), 257 | et0_fao_evapotranspiration( 258 | Variable.et0_fao_evapotranspiration, 259 | ), 260 | vapour_pressure_deficit( 261 | Variable.vapour_pressure_deficit, 262 | ), 263 | wind_speed_10m( 264 | Variable.wind_speed, 265 | altitude: 10, 266 | ), 267 | wind_speed_80m( 268 | Variable.wind_speed, 269 | altitude: 80, 270 | ), 271 | wind_speed_120m( 272 | Variable.wind_speed, 273 | altitude: 120, 274 | ), 275 | wind_speed_180m( 276 | Variable.wind_speed, 277 | altitude: 180, 278 | ), 279 | wind_direction_10m( 280 | Variable.wind_direction, 281 | altitude: 10, 282 | ), 283 | wind_direction_80m( 284 | Variable.wind_direction, 285 | altitude: 80, 286 | ), 287 | wind_direction_120m( 288 | Variable.wind_direction, 289 | altitude: 120, 290 | ), 291 | wind_direction_180m( 292 | Variable.wind_direction, 293 | altitude: 180, 294 | ), 295 | wind_gusts_10m( 296 | Variable.wind_gusts, 297 | altitude: 10, 298 | ), 299 | temperature_80m( 300 | Variable.temperature, 301 | altitude: 80, 302 | ), 303 | temperature_120m( 304 | Variable.temperature, 305 | altitude: 120, 306 | ), 307 | temperature_180m( 308 | Variable.temperature, 309 | altitude: 180, 310 | ), 311 | soil_temperature_0cm( 312 | Variable.soil_temperature, 313 | depth: 0, 314 | ), 315 | soil_temperature_6cm( 316 | Variable.soil_temperature, 317 | depth: 6, 318 | ), 319 | soil_temperature_18cm( 320 | Variable.soil_temperature, 321 | depth: 18, 322 | ), 323 | soil_temperature_54cm( 324 | Variable.soil_temperature, 325 | depth: 54, 326 | ), 327 | soil_moisture_0_to_1cm( 328 | Variable.soil_moisture, 329 | depth: 0, 330 | depthTo: 1, 331 | ), 332 | soil_moisture_1_to_3cm( 333 | Variable.soil_moisture, 334 | depth: 1, 335 | depthTo: 3, 336 | ), 337 | soil_moisture_3_to_9cm( 338 | Variable.soil_moisture, 339 | depth: 3, 340 | depthTo: 9, 341 | ), 342 | soil_moisture_9_to_27cm( 343 | Variable.soil_moisture, 344 | depth: 9, 345 | depthTo: 27, 346 | ), 347 | soil_moisture_27_to_81cm( 348 | Variable.soil_moisture, 349 | depth: 27, 350 | depthTo: 81, 351 | ), 352 | uv_index( 353 | Variable.uv_index, 354 | ), 355 | uv_index_clear_sky( 356 | Variable.uv_index_clear_sky, 357 | ), 358 | is_day( 359 | Variable.is_day, 360 | ), 361 | sunshine_duration( 362 | Variable.sunshine_duration, 363 | ), 364 | wet_bulb_temperature_2m( 365 | Variable.wet_bulb_temperature, 366 | altitude: 2, 367 | ), 368 | total_column_integrated_water_vapour( 369 | Variable.total_column_integrated_water_vapour, 370 | ), 371 | cape( 372 | Variable.cape, 373 | ), 374 | lifted_index( 375 | Variable.lifted_index, 376 | ), 377 | convective_inhibition( 378 | Variable.convective_inhibition, 379 | ), 380 | freezing_level_height( 381 | Variable.freezing_level_height, 382 | ), 383 | boundary_layer_height( 384 | Variable.boundary_layer_height, 385 | ), 386 | shortwave_radiation( 387 | Variable.shortwave_radiation, 388 | ), 389 | direct_radiation( 390 | Variable.direct_radiation, 391 | ), 392 | diffuse_radiation( 393 | Variable.diffuse_radiation, 394 | ), 395 | direct_normal_irradiance( 396 | Variable.direct_normal_irradiance, 397 | ), 398 | global_tilted_irradiance( 399 | Variable.global_tilted_irradiance, 400 | ), 401 | terrestrial_radiation( 402 | Variable.terrestrial_radiation, 403 | ), 404 | shortwave_radiation_instant( 405 | Variable.shortwave_radiation_instant, 406 | ), 407 | direct_radiation_instant( 408 | Variable.direct_radiation_instant, 409 | ), 410 | diffuse_radiation_instant( 411 | Variable.diffuse_radiation_instant, 412 | ), 413 | direct_normal_irradiance_instant( 414 | Variable.direct_normal_irradiance_instant, 415 | ), 416 | global_tilted_irradiance_instant( 417 | Variable.global_tilted_irradiance_instant, 418 | ), 419 | terrestrial_radiation_instant( 420 | Variable.terrestrial_radiation_instant, 421 | ), 422 | ; 423 | 424 | @override 425 | final Variable variable; 426 | @override 427 | final int altitude; 428 | @override 429 | final int depth; 430 | @override 431 | final int depthTo; 432 | const WeatherHourly( 433 | this.variable, { 434 | this.altitude = 0, 435 | this.depth = 0, 436 | this.depthTo = 0, 437 | }); 438 | 439 | static final Map hashes = 440 | makeHashes(WeatherHourly.values); 441 | } 442 | 443 | enum WeatherDaily with Parameter { 444 | weather_code( 445 | Variable.weather_code, 446 | ), 447 | temperature_2m_max( 448 | Variable.temperature, 449 | aggregation: Aggregation.maximum, 450 | altitude: 2, 451 | ), 452 | temperature_2m_min( 453 | Variable.temperature, 454 | aggregation: Aggregation.minimum, 455 | altitude: 2, 456 | ), 457 | apparent_temperature_max( 458 | Variable.apparent_temperature, 459 | aggregation: Aggregation.maximum, 460 | altitude: 2, 461 | ), 462 | apparent_temperature_min( 463 | Variable.apparent_temperature, 464 | aggregation: Aggregation.minimum, 465 | altitude: 2, 466 | ), 467 | sunrise( 468 | Variable.sunrise, 469 | ), 470 | sunset( 471 | Variable.sunset, 472 | ), 473 | daylight_duration( 474 | Variable.daylight_duration, 475 | ), 476 | sunshine_duration( 477 | Variable.sunshine_duration, 478 | ), 479 | uv_index_max( 480 | Variable.uv_index, 481 | aggregation: Aggregation.maximum, 482 | ), 483 | uv_index_clear_sky_max( 484 | Variable.uv_index_clear_sky, 485 | aggregation: Aggregation.maximum, 486 | ), 487 | rain_sum( 488 | Variable.rain, 489 | aggregation: Aggregation.sum, 490 | ), 491 | showers_sum( 492 | Variable.showers, 493 | aggregation: Aggregation.sum, 494 | ), 495 | snowfall_sum( 496 | Variable.snowfall, 497 | aggregation: Aggregation.sum, 498 | ), 499 | precipitation_sum( 500 | Variable.precipitation, 501 | aggregation: Aggregation.sum, 502 | ), 503 | precipitation_hours( 504 | Variable.precipitation_hours, 505 | ), 506 | precipitation_probability_max( 507 | Variable.precipitation_probability, 508 | aggregation: Aggregation.maximum, 509 | ), 510 | wind_speed_10m_max( 511 | Variable.wind_speed, 512 | aggregation: Aggregation.maximum, 513 | altitude: 10, 514 | ), 515 | wind_gusts_10m_max( 516 | Variable.wind_gusts, 517 | aggregation: Aggregation.maximum, 518 | altitude: 10, 519 | ), 520 | wind_direction_10m_dominant( 521 | Variable.wind_direction, 522 | aggregation: Aggregation.dominant, 523 | altitude: 10, 524 | ), 525 | shortwave_radiation_sum( 526 | Variable.shortwave_radiation, 527 | aggregation: Aggregation.sum, 528 | ), 529 | et0_fao_evapotranspiration( 530 | Variable.et0_fao_evapotranspiration, 531 | ), 532 | temperature_2m_mean( 533 | Variable.temperature, 534 | aggregation: Aggregation.mean, 535 | altitude: 2, 536 | ), 537 | apparent_temperature_mean( 538 | Variable.apparent_temperature, 539 | aggregation: Aggregation.mean, 540 | altitude: 2, 541 | ), 542 | cape_mean( 543 | Variable.cape, 544 | aggregation: Aggregation.mean, 545 | ), 546 | cape_max( 547 | Variable.cape, 548 | aggregation: Aggregation.maximum, 549 | ), 550 | cape_min( 551 | Variable.cape, 552 | aggregation: Aggregation.minimum, 553 | ), 554 | cloud_cover_mean( 555 | Variable.cloud_cover, 556 | aggregation: Aggregation.mean, 557 | ), 558 | cloud_cover_max( 559 | Variable.cloud_cover, 560 | aggregation: Aggregation.maximum, 561 | ), 562 | cloud_cover_min( 563 | Variable.cloud_cover, 564 | aggregation: Aggregation.minimum, 565 | ), 566 | dew_point_2m_mean( 567 | Variable.dew_point, 568 | aggregation: Aggregation.mean, 569 | altitude: 2, 570 | ), 571 | dew_point_2m_max( 572 | Variable.dew_point, 573 | aggregation: Aggregation.maximum, 574 | altitude: 2, 575 | ), 576 | dew_point_2m_min( 577 | Variable.dew_point, 578 | aggregation: Aggregation.minimum, 579 | altitude: 2, 580 | ), 581 | et0_fao_evapotranspiration_sum( 582 | Variable.et0_fao_evapotranspiration, 583 | aggregation: Aggregation.sum, 584 | ), 585 | leaf_wetness_probability_mean( 586 | Variable.leaf_wetness_probability, 587 | aggregation: Aggregation.mean, 588 | ), 589 | precipitation_probability_mean( 590 | Variable.precipitation_probability, 591 | aggregation: Aggregation.mean, 592 | ), 593 | precipitation_probability_min( 594 | Variable.precipitation_probability, 595 | aggregation: Aggregation.minimum, 596 | ), 597 | relative_humidity_2m_mean( 598 | Variable.relative_humidity, 599 | aggregation: Aggregation.mean, 600 | altitude: 2, 601 | ), 602 | relative_humidity_2m_max( 603 | Variable.relative_humidity, 604 | aggregation: Aggregation.maximum, 605 | altitude: 2, 606 | ), 607 | relative_humidity_2m_min( 608 | Variable.relative_humidity, 609 | aggregation: Aggregation.minimum, 610 | altitude: 2, 611 | ), 612 | snowfall_water_equivalent_sum( 613 | Variable.snowfall_water_equivalent, 614 | aggregation: Aggregation.sum, 615 | ), 616 | pressure_msl_mean( 617 | Variable.pressure_msl, 618 | aggregation: Aggregation.mean, 619 | ), 620 | pressure_msl_max( 621 | Variable.pressure_msl, 622 | aggregation: Aggregation.maximum, 623 | ), 624 | pressure_msl_min( 625 | Variable.pressure_msl, 626 | aggregation: Aggregation.minimum, 627 | ), 628 | surface_pressure_mean( 629 | Variable.surface_pressure, 630 | aggregation: Aggregation.mean, 631 | ), 632 | surface_pressure_max( 633 | Variable.surface_pressure, 634 | aggregation: Aggregation.maximum, 635 | ), 636 | surface_pressure_min( 637 | Variable.surface_pressure, 638 | aggregation: Aggregation.minimum, 639 | ), 640 | updraft_max( 641 | Variable.updraft, 642 | aggregation: Aggregation.maximum, 643 | ), 644 | visibility_mean( 645 | Variable.visibility, 646 | aggregation: Aggregation.mean, 647 | ), 648 | visibility_min( 649 | Variable.visibility, 650 | aggregation: Aggregation.minimum, 651 | ), 652 | visibility_max( 653 | Variable.visibility, 654 | aggregation: Aggregation.maximum, 655 | ), 656 | wind_gusts_10m_mean( 657 | Variable.wind_gusts, 658 | aggregation: Aggregation.mean, 659 | altitude: 10, 660 | ), 661 | wind_speed_10m_mean( 662 | Variable.wind_speed, 663 | aggregation: Aggregation.mean, 664 | altitude: 10, 665 | ), 666 | wind_gusts_10m_min( 667 | Variable.wind_gusts, 668 | aggregation: Aggregation.minimum, 669 | altitude: 10, 670 | ), 671 | wind_speed_10m_min( 672 | Variable.wind_speed, 673 | aggregation: Aggregation.minimum, 674 | altitude: 10, 675 | ), 676 | wet_bulb_temperature_2m_mean( 677 | Variable.wet_bulb_temperature, 678 | aggregation: Aggregation.mean, 679 | altitude: 2, 680 | ), 681 | wet_bulb_temperature_2m_max( 682 | Variable.wet_bulb_temperature, 683 | aggregation: Aggregation.maximum, 684 | altitude: 2, 685 | ), 686 | wet_bulb_temperature_2m_min( 687 | Variable.wet_bulb_temperature, 688 | aggregation: Aggregation.minimum, 689 | altitude: 2, 690 | ), 691 | vapour_pressure_deficit_max( 692 | Variable.vapour_pressure_deficit, 693 | aggregation: Aggregation.maximum, 694 | ), 695 | ; 696 | 697 | @override 698 | final Variable variable; 699 | @override 700 | final int altitude; 701 | @override 702 | final Aggregation aggregation; 703 | const WeatherDaily( 704 | this.variable, { 705 | this.altitude = 0, 706 | this.aggregation = Aggregation.none, 707 | }); 708 | 709 | static final Map hashes = makeHashes(WeatherDaily.values); 710 | } 711 | -------------------------------------------------------------------------------- /lib/src/exceptions.dart: -------------------------------------------------------------------------------- 1 | class OpenMeteoApiError implements Exception { 2 | String reason; 3 | OpenMeteoApiError(this.reason); 4 | 5 | @override 6 | String toString() => '$runtimeType: $reason'; 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/flatbuffer_web_combat.dart: -------------------------------------------------------------------------------- 1 | export 'package:flat_buffers/flat_buffers.dart' hide Int64Reader; 2 | 3 | import 'package:flat_buffers/flat_buffers.dart'; 4 | import 'dart:typed_data'; 5 | 6 | const bool kIsWeb = bool.fromEnvironment('dart.library.js_util'); 7 | 8 | class Int64Reader extends Reader { 9 | const Int64Reader(); 10 | 11 | @override 12 | int read(BufferContext bc, int offset) { 13 | if (kIsWeb) { 14 | // Read as two 32-bit integers and combine 15 | final low = bc.buffer.getUint32(offset, Endian.little); 16 | final high = bc.buffer.getUint32(offset + 4, Endian.little); 17 | 18 | // Combine into JavaScript number (loses precision beyond 53 bits) 19 | return (high * 0x100000000) + low; 20 | } 21 | 22 | return bc.buffer.getInt64(offset, Endian.little); 23 | } 24 | 25 | @override 26 | int get size => 8; 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/model_export.dart: -------------------------------------------------------------------------------- 1 | import 'weather_api_openmeteo_sdk_generated.dart' show Model; 2 | 3 | typedef OpenMeteoModel = Model; 4 | -------------------------------------------------------------------------------- /lib/src/options.dart: -------------------------------------------------------------------------------- 1 | /// Temperature unit. 2 | enum TemperatureUnit { 3 | celsius, 4 | fahrenheit; 5 | } 6 | 7 | /// Wind speed unit. 8 | enum WindspeedUnit { 9 | kmh, 10 | ms, 11 | mph, 12 | kn; 13 | } 14 | 15 | /// Precipitation amount unit. 16 | enum PrecipitationUnit { 17 | mm, 18 | inch; 19 | } 20 | 21 | /// Metric and imperial. 22 | enum LengthUnit { 23 | metric, 24 | imperial; 25 | } 26 | 27 | /// Set a preference how grid-cells are selected. 28 | enum CellSelection { 29 | /// Selects suitable grid-cell on land with similar elevation to the requested coordinates using a 90-meter digital elevation model. 30 | land, 31 | 32 | /// Prefers grid-cells on sea. 33 | sea, 34 | 35 | /// Selects the nearest possible grid-cell. 36 | nearest; 37 | } 38 | 39 | class OpenMeteoLocation { 40 | final double latitude; 41 | final double longitude; 42 | final double? elevation; 43 | final DateTime? startDate; 44 | final DateTime? endDate; 45 | 46 | const OpenMeteoLocation({ 47 | required this.latitude, 48 | required this.longitude, 49 | this.elevation, 50 | this.startDate, 51 | this.endDate, 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /lib/src/response.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flat_buffers/flat_buffers.dart'; 4 | 5 | import 'api.dart'; 6 | import 'weather_api_openmeteo_sdk_generated.dart'; 7 | 8 | class ApiResponse { 9 | final Uri urlUsed; 10 | final List segments; 11 | 12 | const ApiResponse._({ 13 | required this.urlUsed, 14 | required this.segments, 15 | }); 16 | 17 | factory ApiResponse.fromFlatBuffer( 18 | Uri urlUsed, 19 | Uint8List bytes, { 20 | Map>? minutely15Hashes, 21 | Map>? currentHashes, 22 | Map>? hourlyHashes, 23 | Map>? dailyHashes, 24 | }) { 25 | List segments = []; 26 | 27 | ByteData buffer = BufferContext.fromBytes(bytes).buffer; 28 | int bytesLength = bytes.length; 29 | int iteratedBytes = 0; 30 | while (bytesLength > 0) { 31 | int prefixed = buffer.getUint32(iteratedBytes, Endian.little); 32 | 33 | WeatherApiResponse response = WeatherApiResponse( 34 | bytes.sublist(iteratedBytes + 4, iteratedBytes + prefixed + 4)); 35 | 36 | segments.add(ResponseSegment.fromApiResponse( 37 | response, 38 | minutely15Hashes: minutely15Hashes, 39 | currentHashes: currentHashes, 40 | hourlyHashes: hourlyHashes, 41 | dailyHashes: dailyHashes, 42 | )); 43 | 44 | bytesLength -= 4 + prefixed; 45 | iteratedBytes += 4 + prefixed; 46 | } 47 | 48 | return ApiResponse._( 49 | urlUsed: urlUsed, 50 | segments: segments, 51 | ); 52 | } 53 | } 54 | 55 | class ResponseSegment { 56 | final Model model; 57 | final double latitude; 58 | final double longitude; 59 | final double elevation; 60 | final Duration generationTime; 61 | final Duration utcOffset; 62 | final String? timezone; 63 | final String? timezoneAbbreviation; 64 | final Map, ParameterValues> minutely15Data; 65 | final Map, ParameterValue> currentData; 66 | final Map, ParameterValues> hourlyData; 67 | final Map, ParameterValues> dailyData; 68 | 69 | const ResponseSegment._({ 70 | required this.model, 71 | required this.latitude, 72 | required this.longitude, 73 | required this.elevation, 74 | required this.generationTime, 75 | required this.utcOffset, 76 | required this.timezone, 77 | required this.timezoneAbbreviation, 78 | required this.minutely15Data, 79 | required this.currentData, 80 | required this.hourlyData, 81 | required this.dailyData, 82 | }); 83 | 84 | factory ResponseSegment.fromApiResponse( 85 | WeatherApiResponse response, { 86 | Map>? minutely15Hashes, 87 | Map>? currentHashes, 88 | Map>? hourlyHashes, 89 | Map>? dailyHashes, 90 | }) { 91 | return ResponseSegment._( 92 | model: response.model, 93 | latitude: response.latitude, 94 | longitude: response.longitude, 95 | elevation: response.elevation, 96 | generationTime: Duration( 97 | microseconds: (response.generationTimeMilliseconds * 1000).round(), 98 | ), 99 | utcOffset: Duration(seconds: response.utcOffsetSeconds), 100 | timezone: response.timezone, 101 | timezoneAbbreviation: response.timezoneAbbreviation, 102 | minutely15Data: 103 | _deserializeMultiple(response.minutely15, minutely15Hashes), 104 | currentData: _deserializeSingle(response.current, currentHashes), 105 | hourlyData: _deserializeMultiple(response.hourly, hourlyHashes), 106 | dailyData: _deserializeMultiple(response.daily, dailyHashes), 107 | ); 108 | } 109 | } 110 | 111 | class ParameterValue { 112 | final String unit; 113 | final DateTime time; 114 | final double value; 115 | 116 | const ParameterValue._({ 117 | required this.unit, 118 | required this.time, 119 | required this.value, 120 | }); 121 | } 122 | 123 | class ParameterValues { 124 | final String unit; 125 | final Map values; 126 | 127 | const ParameterValues._({ 128 | required this.unit, 129 | required this.values, 130 | }); 131 | } 132 | 133 | int _computeHash(VariableWithValues v) => computeHash( 134 | variable: v.variable, 135 | altitude: v.altitude, 136 | aggregation: v.aggregation, 137 | pressureLevel: v.pressureLevel, 138 | depth: v.depth, 139 | depthTo: v.depthTo, 140 | ); 141 | 142 | Map _deserializeSingle( 143 | VariablesWithTime? data, 144 | Map? hashes, 145 | ) { 146 | if (data == null || hashes == null) return {}; 147 | List? variables = data.variables; 148 | if (variables == null) return {}; 149 | 150 | DateTime timestamp = DateTime.fromMillisecondsSinceEpoch(data.time * 1000); 151 | 152 | return Map.fromEntries(variables.map((v) { 153 | ApiParameter? parameter = hashes[_computeHash(v)]; 154 | if (parameter == null) return null; 155 | 156 | return MapEntry( 157 | parameter, 158 | ParameterValue._( 159 | unit: _unitsMap[v.unit]!, 160 | time: timestamp, 161 | value: v.value, 162 | ), 163 | ); 164 | }).nonNulls); 165 | } 166 | 167 | Map _deserializeMultiple( 168 | VariablesWithTime? data, 169 | Map? hashes, 170 | ) { 171 | if (data == null || hashes == null) return {}; 172 | List? variables = data.variables; 173 | if (variables == null) return {}; 174 | 175 | DateTime startTime = DateTime.fromMillisecondsSinceEpoch(data.time * 1000); 176 | DateTime endTime = DateTime.fromMillisecondsSinceEpoch(data.timeEnd * 1000); 177 | Duration interval = Duration(seconds: data.interval); 178 | List timestamps = [ 179 | for (DateTime time = startTime; 180 | time.isBefore(endTime); 181 | time = time.add(interval)) 182 | time 183 | ]; 184 | 185 | return Map.fromEntries(variables.map((v) { 186 | ApiParameter? parameter = hashes[_computeHash(v)]; 187 | if (parameter == null) return null; 188 | 189 | return MapEntry( 190 | parameter, 191 | ParameterValues._( 192 | unit: _unitsMap[v.unit] ?? "", 193 | values: (v.values ?? v.valuesInt64) 194 | ?.asMap() 195 | .map((index, value) => MapEntry(timestamps[index], value)) ?? 196 | {}, 197 | ), 198 | ); 199 | }).nonNulls); 200 | } 201 | 202 | const Map _unitsMap = { 203 | Unit.undefined: '', 204 | Unit.celsius: '°C', 205 | Unit.centimetre: 'cm', 206 | Unit.cubic_metre_per_cubic_metre: 'm³/m³', 207 | Unit.cubic_metre_per_second: 'm³/s', 208 | Unit.degree_direction: '°', 209 | Unit.dimensionless_integer: '', 210 | Unit.dimensionless: '', 211 | Unit.european_air_quality_index: 'AQI', 212 | Unit.fahrenheit: '°F', 213 | Unit.feet: 'ft', 214 | Unit.fraction: '', 215 | Unit.gdd_celsius: '°C GDD', 216 | Unit.geopotential_metre: 'm', 217 | Unit.grains_per_cubic_metre: 'grains/m³', 218 | Unit.gram_per_kilogram: 'g/kg', 219 | Unit.hectopascal: 'hPa', 220 | Unit.hours: 'hr', 221 | Unit.inch: 'in', 222 | Unit.iso8601: '', 223 | Unit.joule_per_kilogram: 'J/kg', 224 | Unit.kelvin: 'kelvins', 225 | Unit.kilopascal: 'kPa', 226 | Unit.kilogram_per_square_metre: 'kg/m²', 227 | Unit.kilometres_per_hour: 'km/h', 228 | Unit.knots: 'kn', 229 | Unit.megajoule_per_square_metre: 'MJ/m²', 230 | Unit.metre_per_second_not_unit_converted: 'm/s', 231 | Unit.metre_per_second: 'm/s', 232 | Unit.metre: 'm', 233 | Unit.micrograms_per_cubic_metre: 'mcg/m³', 234 | Unit.miles_per_hour: 'mph', 235 | Unit.millimetre: 'mm', 236 | Unit.pascal: 'Pa', 237 | Unit.per_second: 'Hz', 238 | Unit.percentage: '%', 239 | Unit.seconds: 's', 240 | Unit.unix_time: 's', 241 | Unit.us_air_quality_index: 'AQI', 242 | Unit.watt_per_square_metre: 'W/m²', 243 | Unit.wmo_code: '', 244 | }; 245 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: open_meteo 2 | description: A free, silly, all-in-one API SDK to forecast weather, air quality, climate change, and many more by OpenMeteo with full typed support! 3 | version: 3.0.0 4 | homepage: https://github.com/neursh/open-meteo-dart 5 | repository: https://github.com/neursh/open-meteo-dart 6 | 7 | environment: 8 | sdk: ^3.0.0 9 | 10 | dependencies: 11 | flat_buffers: '^23.5.26' 12 | http: ^1.0.0 13 | dev_dependencies: 14 | lints: ^4.0.0 15 | test: ^1.25.8 16 | -------------------------------------------------------------------------------- /test/air_quality_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('air quality api', () { 6 | const latitude = 52.52, longitude = 13.405; // Berlin 7 | 8 | group('constructor', () { 9 | test('with defaults', () { 10 | expect(() => AirQualityApi(), returnsNormally); 11 | }); 12 | 13 | group('with custom', () { 14 | test('url/key', () { 15 | expect( 16 | () => AirQualityApi( 17 | apiUrl: 'https://api.custom.url/some/path', 18 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 19 | ), 20 | returnsNormally, 21 | ); 22 | }); 23 | test('cell selection', () { 24 | expect( 25 | () => AirQualityApi(cellSelection: CellSelection.sea), 26 | returnsNormally, 27 | ); 28 | }); 29 | test('domains', () { 30 | expect( 31 | () => AirQualityApi(domains: AirQualityDomains.cams_europe), 32 | returnsNormally, 33 | ); 34 | }); 35 | }); 36 | }); 37 | 38 | group('flatbuffers', () { 39 | late AirQualityApi api; 40 | setUp(() { 41 | api = AirQualityApi(); 42 | }); 43 | 44 | group('enum deserialization', () { 45 | test('for current data', () async { 46 | final response = await api.request( 47 | locations: { 48 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 49 | }, 50 | current: AirQualityCurrent.values.toSet(), 51 | ); 52 | expect( 53 | response.segments[0].currentData.keys, 54 | containsAll(AirQualityCurrent.values), 55 | ); 56 | }); 57 | test('for hourly data', () async { 58 | final response = await api.request( 59 | locations: { 60 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 61 | }, 62 | hourly: AirQualityHourly.values.toSet(), 63 | ); 64 | expect( 65 | response.segments[0].hourlyData.keys, 66 | containsAll(AirQualityHourly.values), 67 | ); 68 | }); 69 | }); 70 | 71 | group('get', () { 72 | test('current aqi', () async { 73 | final result = await api.request( 74 | locations: { 75 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 76 | }, 77 | current: {AirQualityCurrent.european_aqi}, 78 | ); 79 | final temperature = 80 | result.segments[0].currentData[AirQualityCurrent.european_aqi]; 81 | expect(temperature, isNotNull); 82 | }); 83 | test('hourly aqi', () async { 84 | final result = await api.request( 85 | locations: { 86 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 87 | }, 88 | hourly: {AirQualityHourly.european_aqi}, 89 | ); 90 | final temperature = 91 | result.segments[0].hourlyData[AirQualityHourly.european_aqi]; 92 | expect(temperature, isNotNull); 93 | expect(temperature!.values, isNotEmpty); 94 | }); 95 | }); 96 | }); 97 | 98 | group('json get', () { 99 | late AirQualityApi api; 100 | setUp(() { 101 | api = AirQualityApi(); 102 | }); 103 | 104 | test('current aqi', () async { 105 | final result = await api.requestJson( 106 | locations: { 107 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 108 | }, 109 | current: {AirQualityCurrent.european_aqi}, 110 | ); 111 | expect(result['error'], isNot(true)); 112 | expect(result['current'], isNotNull); 113 | expect(result['current']['european_aqi'], isNotNull); 114 | }); 115 | test('hourly aqi', () async { 116 | final result = await api.requestJson( 117 | locations: { 118 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 119 | }, 120 | hourly: {AirQualityHourly.european_aqi}, 121 | ); 122 | expect(result['error'], isNot(true)); 123 | expect(result['hourly'], isNotNull); 124 | expect(result['hourly']['european_aqi'], isNotNull); 125 | expect( 126 | result['hourly']['time'].length, 127 | result['hourly']['european_aqi'].length, 128 | ); 129 | }); 130 | }); 131 | }); 132 | } 133 | -------------------------------------------------------------------------------- /test/climate_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('climate api', () { 6 | const latitude = 52.52, longitude = 13.405; // Berlin 7 | const models = {OpenMeteoModel.CMCC_CM2_VHR4}; 8 | final startDate = DateTime(2022, 1, 1), endDate = DateTime(2022, 1, 2); 9 | 10 | group('constructor', () { 11 | test('with single model', () { 12 | expect( 13 | () => ClimateApi(models: {OpenMeteoModel.CMCC_CM2_VHR4}), 14 | returnsNormally, 15 | ); 16 | }); 17 | 18 | test('with multiple models', () { 19 | expect( 20 | () => ClimateApi(models: { 21 | OpenMeteoModel.CMCC_CM2_VHR4, 22 | OpenMeteoModel.NICAM16_8S, 23 | }), 24 | returnsNormally, 25 | ); 26 | }); 27 | 28 | group('with custom', () { 29 | test('url/key', () { 30 | expect( 31 | () => ClimateApi( 32 | models: models, 33 | apiUrl: 'https://api.custom.url/some/path', 34 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 35 | ), 36 | returnsNormally, 37 | ); 38 | }); 39 | test('units', () { 40 | expect( 41 | () => ClimateApi( 42 | models: models, 43 | windspeedUnit: WindspeedUnit.mph, 44 | temperatureUnit: TemperatureUnit.fahrenheit, 45 | precipitationUnit: PrecipitationUnit.inch, 46 | ), 47 | returnsNormally, 48 | ); 49 | }); 50 | test('cell selection', () { 51 | expect( 52 | () => ClimateApi( 53 | models: models, 54 | cellSelection: CellSelection.sea, 55 | ), 56 | returnsNormally, 57 | ); 58 | }); 59 | test('bias correction', () { 60 | expect( 61 | () => ClimateApi( 62 | models: models, 63 | disableBiasCorrection: true, 64 | ), 65 | returnsNormally, 66 | ); 67 | }); 68 | }); 69 | }); 70 | 71 | group('flatbuffers', () { 72 | late ClimateApi api; 73 | setUp(() { 74 | api = ClimateApi(models: models); 75 | }); 76 | 77 | group('enum deserialization', () { 78 | test('for daily data', () async { 79 | final response = await api.request( 80 | locations: { 81 | OpenMeteoLocation( 82 | latitude: latitude, 83 | longitude: longitude, 84 | startDate: startDate, 85 | endDate: endDate, 86 | ) 87 | }, 88 | daily: ClimateDaily.values.toSet(), 89 | ); 90 | expect( 91 | response.segments[0].dailyData.keys, 92 | containsAll(ClimateDaily.values), 93 | ); 94 | }); 95 | }); 96 | 97 | group('get', () { 98 | test('daily temperature max', () async { 99 | final result = await api.request( 100 | locations: { 101 | OpenMeteoLocation( 102 | latitude: latitude, 103 | longitude: longitude, 104 | startDate: startDate, 105 | endDate: endDate, 106 | ) 107 | }, 108 | daily: {ClimateDaily.temperature_2m_max}, 109 | ); 110 | final temperature = 111 | result.segments[0].dailyData[ClimateDaily.temperature_2m_max]; 112 | expect(temperature, isNotNull); 113 | expect(temperature!.values, isNotEmpty); 114 | }); 115 | }); 116 | }); 117 | 118 | group('json get', () { 119 | late ClimateApi api; 120 | setUp(() { 121 | api = ClimateApi(models: models); 122 | }); 123 | 124 | test('daily temperature max', () async { 125 | final result = await api.requestJson( 126 | locations: { 127 | OpenMeteoLocation( 128 | latitude: latitude, 129 | longitude: longitude, 130 | startDate: startDate, 131 | endDate: endDate, 132 | ) 133 | }, 134 | daily: {ClimateDaily.temperature_2m_max}, 135 | ); 136 | expect(result['error'], isNot(true)); 137 | expect(result['daily'], isNotNull); 138 | expect(result['daily']['temperature_2m_max'], isNotNull); 139 | expect( 140 | result['daily']['time'].length, 141 | result['daily']['temperature_2m_max'].length, 142 | ); 143 | }); 144 | }); 145 | }); 146 | } 147 | -------------------------------------------------------------------------------- /test/elevation_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('elevation api', () { 6 | group('constructor', () { 7 | test('with defaults', () { 8 | expect(() => ElevationApi(), returnsNormally); 9 | }); 10 | 11 | group('with custom', () { 12 | test('url/key', () { 13 | expect( 14 | () => ElevationApi( 15 | apiUrl: 'https://api.custom.url/some/path', 16 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 17 | ), 18 | returnsNormally, 19 | ); 20 | }); 21 | }); 22 | }); 23 | 24 | group('json get', () { 25 | late ElevationApi api; 26 | setUp(() { 27 | api = ElevationApi(); 28 | }); 29 | 30 | test('single elevation', () async { 31 | final result = await api.requestJson( 32 | latitudes: {52.52}, 33 | longitudes: {13.41}, 34 | ); 35 | expect(result['error'], isNot(true)); 36 | expect(result['elevation'], isNotNull); 37 | expect(result['elevation'][0], isA()); 38 | }); 39 | test('multiple elevations', () async { 40 | final result = await api.requestJson( 41 | latitudes: {52.52, 51.507}, 42 | longitudes: {13.405, -0.128}, 43 | ); 44 | expect(result['error'], isNot(true)); 45 | expect(result['elevation'], isNotNull); 46 | expect(result['elevation'][0], isA()); 47 | expect(result['elevation'][1], isA()); 48 | }); 49 | }); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /test/ensemble_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('ensemble api', () { 6 | const latitude = 52.52, longitude = 13.405; // Berlin 7 | const models = {OpenMeteoModel.icon_seamless}; 8 | 9 | group('constructor', () { 10 | test('with single model', () { 11 | expect( 12 | () => EnsembleApi(models: {OpenMeteoModel.icon_seamless}), 13 | returnsNormally, 14 | ); 15 | }); 16 | test('with multiple models', () { 17 | expect( 18 | () => EnsembleApi(models: { 19 | OpenMeteoModel.icon_seamless, 20 | OpenMeteoModel.gfs_seamless, 21 | }), 22 | returnsNormally, 23 | ); 24 | }); 25 | 26 | group('with custom', () { 27 | test('url/key', () { 28 | expect( 29 | () => EnsembleApi( 30 | models: models, 31 | apiUrl: 'https://api.custom.url/some/path', 32 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 33 | ), 34 | returnsNormally, 35 | ); 36 | }); 37 | test('units', () { 38 | expect( 39 | () => EnsembleApi( 40 | models: models, 41 | windspeedUnit: WindspeedUnit.mph, 42 | temperatureUnit: TemperatureUnit.fahrenheit, 43 | precipitationUnit: PrecipitationUnit.inch, 44 | ), 45 | returnsNormally, 46 | ); 47 | }); 48 | test('cell selection', () { 49 | expect( 50 | () => EnsembleApi( 51 | models: models, 52 | cellSelection: CellSelection.sea, 53 | ), 54 | returnsNormally, 55 | ); 56 | }); 57 | }); 58 | }); 59 | 60 | group('flatbuffers', () { 61 | late EnsembleApi api; 62 | setUp(() { 63 | api = EnsembleApi(models: models); 64 | }); 65 | 66 | group('enum deserialization', () { 67 | // Waiting for https://github.com/open-meteo/open-meteo/pull/939 68 | // test('for hourly data', () async { 69 | // final response = await api.request( 70 | // latitude: latitude, 71 | // longitude: longitude, 72 | // hourly: HourlyEnsemble.values.toSet(), 73 | // ); 74 | // expect( 75 | // response.hourlyData.keys, 76 | // containsAll(HourlyEnsemble.values), 77 | // ); 78 | // }); 79 | }); 80 | 81 | group('get', () { 82 | test('hourly temperature', () async { 83 | final result = await api.request( 84 | locations: { 85 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 86 | }, 87 | hourly: {EnsembleHourly.temperature_2m}, 88 | ); 89 | final temperature = 90 | result.segments[0].hourlyData[EnsembleHourly.temperature_2m]; 91 | expect(temperature, isNotNull); 92 | expect(temperature!.values, isNotEmpty); 93 | }); 94 | }); 95 | }); 96 | 97 | group('json get', () { 98 | late EnsembleApi api; 99 | setUp(() { 100 | api = EnsembleApi(models: models); 101 | }); 102 | 103 | test('hourly temperature', () async { 104 | final result = await api.requestJson( 105 | locations: { 106 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 107 | }, 108 | hourly: {EnsembleHourly.temperature_2m}, 109 | ); 110 | expect(result['error'], isNot(true)); 111 | expect(result['hourly'], isNotNull); 112 | expect(result['hourly']['temperature_2m'], isNotNull); 113 | expect( 114 | result['hourly']['time'].length, 115 | result['hourly']['temperature_2m'].length, 116 | ); 117 | }); 118 | }); 119 | }); 120 | } 121 | -------------------------------------------------------------------------------- /test/flood_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('Flood api', () { 6 | const latitude = 52.52, longitude = 13.405; // Berlin 7 | 8 | group('constructor', () { 9 | test('with defaults', () { 10 | expect(() => FloodApi(), returnsNormally); 11 | }); 12 | 13 | group('with custom', () { 14 | test('url/key', () { 15 | expect( 16 | () => FloodApi( 17 | apiUrl: 'https://api.custom.url/some/path', 18 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 19 | ), 20 | returnsNormally, 21 | ); 22 | }); 23 | test('cell selection', () { 24 | expect( 25 | () => FloodApi(cellSelection: CellSelection.sea), 26 | returnsNormally, 27 | ); 28 | }); 29 | test('ensemble', () { 30 | expect( 31 | () => FloodApi(ensemble: true), 32 | returnsNormally, 33 | ); 34 | }); 35 | }); 36 | }); 37 | 38 | group('flatbuffers', () { 39 | late FloodApi api; 40 | setUp(() { 41 | api = FloodApi(); 42 | }); 43 | 44 | group('enum deserialization', () { 45 | test('for daily data', () async { 46 | final response = await api.request( 47 | locations: { 48 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 49 | }, 50 | daily: FloodDaily.values.toSet(), 51 | ); 52 | expect( 53 | response.segments[0].dailyData.keys, 54 | containsAll(FloodDaily.values), 55 | ); 56 | }); 57 | }); 58 | 59 | group('get', () { 60 | test('daily river discharge', () async { 61 | final result = await api.request( 62 | locations: { 63 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 64 | }, 65 | daily: {FloodDaily.river_discharge}, 66 | ); 67 | final temperature = 68 | result.segments[0].dailyData[FloodDaily.river_discharge]; 69 | expect(temperature, isNotNull); 70 | expect(temperature!.values, isNotEmpty); 71 | }); 72 | }); 73 | }); 74 | 75 | group('json get', () { 76 | late FloodApi api; 77 | setUp(() { 78 | api = FloodApi(); 79 | }); 80 | 81 | test('daily river discharge', () async { 82 | final result = await api.requestJson( 83 | locations: { 84 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 85 | }, 86 | daily: {FloodDaily.river_discharge}, 87 | ); 88 | expect(result['error'], isNot(true)); 89 | expect(result['daily'], isNotNull); 90 | expect(result['daily']['river_discharge'], isNotNull); 91 | expect( 92 | result['daily']['time'].length, 93 | result['daily']['river_discharge'].length, 94 | ); 95 | }); 96 | }); 97 | }); 98 | } 99 | -------------------------------------------------------------------------------- /test/geocoding_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('geocoding api', () { 6 | group('constructor', () { 7 | test('with defaults', () { 8 | expect(() => GeocodingApi(), returnsNormally); 9 | }); 10 | 11 | group('with custom', () { 12 | test('url/key', () { 13 | expect( 14 | () => GeocodingApi( 15 | apiUrl: 'https://api.custom.url/some/path', 16 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 17 | ), 18 | returnsNormally, 19 | ); 20 | }); 21 | test('language', () { 22 | expect( 23 | () => GeocodingApi(language: 'fr'), 24 | returnsNormally, 25 | ); 26 | }); 27 | }); 28 | }); 29 | 30 | group('json get', () { 31 | late GeocodingApi api; 32 | setUp(() { 33 | api = GeocodingApi(); 34 | }); 35 | 36 | test('location of Berlin', () async { 37 | final result = await api.requestJson(name: 'Berlin'); 38 | expect(result['error'], isNot(true)); 39 | expect(result['results'], isNotNull); 40 | expect(result['results'][0]['name'], 'Berlin'); 41 | }); 42 | }); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /test/historical_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('historical api', () { 6 | const latitude = 52.52, longitude = 13.405; // Berlin 7 | final startDate = DateTime(2022, 1, 1), endDate = DateTime(2022, 1, 2); 8 | 9 | group('constructor', () { 10 | test('with defaults', () { 11 | expect(() => HistoricalApi(), returnsNormally); 12 | }); 13 | 14 | group('with custom', () { 15 | test('url/key', () { 16 | expect( 17 | () => HistoricalApi( 18 | apiUrl: 'https://api.custom.url/some/path', 19 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 20 | ), 21 | returnsNormally, 22 | ); 23 | }); 24 | test('units', () { 25 | expect( 26 | () => HistoricalApi( 27 | windspeedUnit: WindspeedUnit.mph, 28 | temperatureUnit: TemperatureUnit.fahrenheit, 29 | precipitationUnit: PrecipitationUnit.inch, 30 | ), 31 | returnsNormally, 32 | ); 33 | }); 34 | test('cell selection', () { 35 | expect( 36 | () => HistoricalApi(cellSelection: CellSelection.sea), 37 | returnsNormally, 38 | ); 39 | }); 40 | }); 41 | }); 42 | 43 | group('flatbuffers', () { 44 | late HistoricalApi api; 45 | setUp(() { 46 | api = HistoricalApi(); 47 | }); 48 | 49 | group('enum deserialization', () { 50 | test('for hourly data', () async { 51 | final response = await api.request( 52 | locations: { 53 | OpenMeteoLocation( 54 | latitude: latitude, 55 | longitude: longitude, 56 | startDate: startDate, 57 | endDate: endDate, 58 | ) 59 | }, 60 | hourly: HistoricalHourly.values.toSet(), 61 | ); 62 | expect( 63 | response.segments[0].hourlyData.keys, 64 | containsAll(HistoricalHourly.values), 65 | ); 66 | }); 67 | test('for daily data', () async { 68 | final response = await api.request( 69 | locations: { 70 | OpenMeteoLocation( 71 | latitude: latitude, 72 | longitude: longitude, 73 | startDate: startDate, 74 | endDate: endDate, 75 | ) 76 | }, 77 | daily: HistoricalDaily.values.toSet(), 78 | ); 79 | expect( 80 | response.segments[0].dailyData.keys, 81 | containsAll(HistoricalDaily.values), 82 | ); 83 | }); 84 | }); 85 | 86 | group('get', () { 87 | test('hourly temperature', () async { 88 | final result = await api.request( 89 | locations: { 90 | OpenMeteoLocation( 91 | latitude: latitude, 92 | longitude: longitude, 93 | startDate: startDate, 94 | endDate: endDate, 95 | ) 96 | }, 97 | hourly: {HistoricalHourly.temperature_2m}, 98 | ); 99 | final temperature = 100 | result.segments[0].hourlyData[HistoricalHourly.temperature_2m]; 101 | expect(temperature, isNotNull); 102 | expect(temperature!.values, isNotEmpty); 103 | }); 104 | test('daily temperature max', () async { 105 | final result = await api.request( 106 | locations: { 107 | OpenMeteoLocation( 108 | latitude: latitude, 109 | longitude: longitude, 110 | startDate: startDate, 111 | endDate: endDate, 112 | ) 113 | }, 114 | daily: {HistoricalDaily.temperature_2m_max}, 115 | ); 116 | final temperature = 117 | result.segments[0].dailyData[HistoricalDaily.temperature_2m_max]; 118 | expect(temperature, isNotNull); 119 | expect(temperature!.values, isNotEmpty); 120 | }); 121 | }); 122 | }); 123 | 124 | group('json get', () { 125 | late HistoricalApi api; 126 | setUp(() { 127 | api = HistoricalApi(); 128 | }); 129 | 130 | test('hourly temperature', () async { 131 | final result = await api.requestJson( 132 | locations: { 133 | OpenMeteoLocation( 134 | latitude: latitude, 135 | longitude: longitude, 136 | startDate: startDate, 137 | endDate: endDate, 138 | ) 139 | }, 140 | hourly: {HistoricalHourly.temperature_2m}, 141 | ); 142 | expect(result['error'], isNot(true)); 143 | expect(result['hourly'], isNotNull); 144 | expect(result['hourly']['temperature_2m'], isNotNull); 145 | expect( 146 | result['hourly']['time'].length, 147 | result['hourly']['temperature_2m'].length, 148 | ); 149 | }); 150 | test('daily temperature max', () async { 151 | final result = await api.requestJson( 152 | locations: { 153 | OpenMeteoLocation( 154 | latitude: latitude, 155 | longitude: longitude, 156 | startDate: startDate, 157 | endDate: endDate, 158 | ) 159 | }, 160 | daily: {HistoricalDaily.temperature_2m_max}, 161 | ); 162 | expect(result['error'], isNot(true)); 163 | expect(result['daily'], isNotNull); 164 | expect(result['daily']['temperature_2m_max'], isNotNull); 165 | expect( 166 | result['daily']['time'].length, 167 | result['daily']['temperature_2m_max'].length, 168 | ); 169 | }); 170 | }); 171 | }); 172 | } 173 | -------------------------------------------------------------------------------- /test/marine_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('marine api', () { 6 | const latitude = 54.544587, longitude = 10.227487; // Baltic Sea near Kiel 7 | 8 | group('constructor', () { 9 | test('with defaults', () { 10 | expect(() => MarineApi(), returnsNormally); 11 | }); 12 | 13 | group('with custom', () { 14 | test('url/key', () { 15 | expect( 16 | () => MarineApi( 17 | apiUrl: 'https://api.custom.url/some/path', 18 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 19 | ), 20 | returnsNormally, 21 | ); 22 | }); 23 | test('units', () { 24 | expect( 25 | () => MarineApi( 26 | windspeedUnit: WindspeedUnit.mph, 27 | temperatureUnit: TemperatureUnit.fahrenheit, 28 | precipitationUnit: PrecipitationUnit.inch, 29 | lengthUnit: LengthUnit.imperial, 30 | ), 31 | returnsNormally, 32 | ); 33 | }); 34 | test('cell selection', () { 35 | expect( 36 | () => MarineApi(cellSelection: CellSelection.sea), 37 | returnsNormally, 38 | ); 39 | }); 40 | }); 41 | }); 42 | 43 | group('flatbuffers', () { 44 | late MarineApi api; 45 | setUp(() { 46 | api = MarineApi(); 47 | }); 48 | 49 | group('enum deserialization', () { 50 | test('for current data', () async { 51 | final response = await api.request( 52 | locations: { 53 | OpenMeteoLocation( 54 | latitude: latitude, 55 | longitude: longitude, 56 | ) 57 | }, 58 | current: MarineCurrent.values.toSet(), 59 | ); 60 | expect(response.segments[0].currentData.keys, 61 | containsAll(MarineCurrent.values)); 62 | }); 63 | test('for hourly data', () async { 64 | final response = await api.request( 65 | locations: { 66 | OpenMeteoLocation( 67 | latitude: latitude, 68 | longitude: longitude, 69 | ) 70 | }, 71 | hourly: MarineHourly.values.toSet(), 72 | ); 73 | expect(response.segments[0].hourlyData.keys, 74 | containsAll(MarineHourly.values)); 75 | }); 76 | // Waiting for https://github.com/open-meteo/open-meteo/issues/936 77 | // test('for daily data', () async { 78 | // final response = await api.request( 79 | // latitude: latitude, 80 | // longitude: longitude, 81 | // daily: DailyMarine.values.toSet(), 82 | // ); 83 | // expect( 84 | // response.dailyData.keys, 85 | // containsAll(DailyMarine.values), 86 | // ); 87 | // }); 88 | }); 89 | 90 | group('get', () { 91 | test('current wave height', () async { 92 | final result = await api.request( 93 | locations: { 94 | OpenMeteoLocation( 95 | latitude: latitude, 96 | longitude: longitude, 97 | ) 98 | }, 99 | current: {MarineCurrent.wave_height}, 100 | ); 101 | final waveHeight = 102 | result.segments[0].currentData[MarineCurrent.wave_height]; 103 | expect(waveHeight, isNotNull); 104 | }); 105 | test('hourly wave height', () async { 106 | final result = await api.request( 107 | locations: { 108 | OpenMeteoLocation( 109 | latitude: latitude, 110 | longitude: longitude, 111 | ) 112 | }, 113 | hourly: {MarineHourly.wave_height}, 114 | ); 115 | final waveHeight = 116 | result.segments[0].hourlyData[MarineHourly.wave_height]; 117 | expect(waveHeight, isNotNull); 118 | expect(waveHeight!.values, isNotEmpty); 119 | }); 120 | // test('daily wave height max', () async { 121 | // final result = await api.request( 122 | // latitude: latitude, 123 | // longitude: longitude, 124 | // daily: [DailyMarine.wave_height_max], 125 | // ); 126 | // final waveHeight = result.dailyData[DailyMarine.wave_height_max]; 127 | // expect(waveHeight, isNotNull); 128 | // expect(waveHeight!.data, isNotEmpty); 129 | // }); 130 | }); 131 | }); 132 | 133 | group('json get', () { 134 | late MarineApi api; 135 | setUp(() { 136 | api = MarineApi(); 137 | }); 138 | 139 | test('current wave height', () async { 140 | final result = await api.requestJson( 141 | locations: { 142 | OpenMeteoLocation( 143 | latitude: latitude, 144 | longitude: longitude, 145 | ) 146 | }, 147 | current: {MarineCurrent.wave_height}, 148 | ); 149 | expect(result['error'], isNot(true)); 150 | expect(result['current'], isNotNull); 151 | expect(result['current']['wave_height'], isNotNull); 152 | }); 153 | test('hourly wave height', () async { 154 | final result = await api.requestJson( 155 | locations: { 156 | OpenMeteoLocation( 157 | latitude: latitude, 158 | longitude: longitude, 159 | ) 160 | }, 161 | hourly: {MarineHourly.wave_height}, 162 | ); 163 | expect(result['error'], isNot(true)); 164 | expect(result['hourly'], isNotNull); 165 | expect(result['hourly']['wave_height'], isNotNull); 166 | expect( 167 | result['hourly']['time'].length, 168 | result['hourly']['wave_height'].length, 169 | ); 170 | }); 171 | test('daily wave height max', () async { 172 | final result = await api.requestJson( 173 | locations: { 174 | OpenMeteoLocation( 175 | latitude: latitude, 176 | longitude: longitude, 177 | ) 178 | }, 179 | daily: {MarineDaily.wave_height_max}, 180 | ); 181 | expect(result['error'], isNot(true)); 182 | expect(result['daily'], isNotNull); 183 | expect(result['daily']['wave_height_max'], isNotNull); 184 | expect( 185 | result['daily']['time'].length, 186 | result['daily']['wave_height_max'].length, 187 | ); 188 | }); 189 | }); 190 | }); 191 | } 192 | -------------------------------------------------------------------------------- /test/satellite_radiation_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('satellite api', () { 6 | const latitude = 52.52, longitude = 13.405; // Berlin 7 | 8 | group('constructor', () { 9 | test('with defaults', () { 10 | expect( 11 | () => SatelliteRadiationApi( 12 | models: {OpenMeteoModel.satellite_radiation_seamless}), 13 | returnsNormally); 14 | }); 15 | 16 | group('with custom', () { 17 | test('url/key', () { 18 | expect( 19 | () => SatelliteRadiationApi( 20 | apiUrl: 'https://api.custom.url/some/path', 21 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 22 | models: {OpenMeteoModel.satellite_radiation_seamless}), 23 | returnsNormally, 24 | ); 25 | }); 26 | test('cell selection', () { 27 | expect( 28 | () => SatelliteRadiationApi( 29 | cellSelection: CellSelection.sea, 30 | models: {OpenMeteoModel.satellite_radiation_seamless}), 31 | returnsNormally, 32 | ); 33 | }); 34 | }); 35 | }); 36 | 37 | group('flatbuffers', () { 38 | late SatelliteRadiationApi api; 39 | setUp(() { 40 | api = SatelliteRadiationApi( 41 | models: {OpenMeteoModel.satellite_radiation_seamless}); 42 | }); 43 | 44 | group('enum deserialization', () { 45 | test('for hourly data', () async { 46 | final response = await api.request( 47 | locations: { 48 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 49 | }, 50 | hourly: SatelliteRadiationHourly.values.toSet(), 51 | ); 52 | expect( 53 | response.segments[0].hourlyData.keys, 54 | containsAll(SatelliteRadiationHourly.values), 55 | ); 56 | }); 57 | test('for daily data', () async { 58 | final response = await api.request( 59 | locations: { 60 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 61 | }, 62 | daily: SatelliteRadiationDaily.values.toSet(), 63 | ); 64 | expect( 65 | response.segments[0].dailyData.keys, 66 | containsAll(SatelliteRadiationDaily.values), 67 | ); 68 | }); 69 | }); 70 | 71 | group('get', () { 72 | test('hourly diffuse radiation', () async { 73 | final result = await api.request( 74 | locations: { 75 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 76 | }, 77 | hourly: {SatelliteRadiationHourly.diffuse_radiation}, 78 | ); 79 | final temperature = result.segments[0] 80 | .hourlyData[SatelliteRadiationHourly.diffuse_radiation]; 81 | expect(temperature, isNotNull); 82 | expect(temperature!.values, isNotEmpty); 83 | }); 84 | test('daily shortwave radiation', () async { 85 | final result = await api.request( 86 | locations: { 87 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 88 | }, 89 | daily: {SatelliteRadiationDaily.shortwave_radiation_sum}, 90 | ); 91 | final temperature = result.segments[0] 92 | .dailyData[SatelliteRadiationDaily.shortwave_radiation_sum]; 93 | expect(temperature, isNotNull); 94 | expect(temperature!.values, isNotEmpty); 95 | }); 96 | }); 97 | }); 98 | 99 | group('json get', () { 100 | late SatelliteRadiationApi api; 101 | setUp(() { 102 | api = SatelliteRadiationApi( 103 | models: {OpenMeteoModel.satellite_radiation_seamless}); 104 | }); 105 | test('hourly diffuse radiation', () async { 106 | final result = await api.requestJson( 107 | locations: { 108 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 109 | }, 110 | hourly: {SatelliteRadiationHourly.diffuse_radiation}, 111 | ); 112 | expect(result['error'], isNot(true)); 113 | expect(result['hourly'], isNotNull); 114 | expect(result['hourly']['diffuse_radiation'], isNotNull); 115 | expect( 116 | result['hourly']['time'].length, 117 | result['hourly']['diffuse_radiation'].length, 118 | ); 119 | }); 120 | test('daily shortwave radiation', () async { 121 | final result = await api.requestJson( 122 | locations: { 123 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 124 | }, 125 | daily: {SatelliteRadiationDaily.shortwave_radiation_sum}, 126 | ); 127 | expect(result['error'], isNot(true)); 128 | expect(result['daily'], isNotNull); 129 | expect(result['daily']['shortwave_radiation_sum'], isNotNull); 130 | expect( 131 | result['daily']['time'].length, 132 | result['daily']['shortwave_radiation_sum'].length, 133 | ); 134 | }); 135 | }); 136 | }); 137 | } 138 | -------------------------------------------------------------------------------- /test/weather_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:open_meteo/open_meteo.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('weather api', () { 6 | const latitude = 52.52, longitude = 13.405; // Berlin 7 | 8 | group('constructor', () { 9 | test('with defaults', () { 10 | expect(() => WeatherApi(), returnsNormally); 11 | }); 12 | 13 | group('with custom', () { 14 | test('url/key', () { 15 | expect( 16 | () => WeatherApi( 17 | apiUrl: 'https://api.custom.url/some/path', 18 | apiKey: 'idk-the-format-of-open-meteo-api-keys', 19 | ), 20 | returnsNormally, 21 | ); 22 | }); 23 | test('units', () { 24 | expect( 25 | () => WeatherApi( 26 | windspeedUnit: WindspeedUnit.mph, 27 | temperatureUnit: TemperatureUnit.fahrenheit, 28 | precipitationUnit: PrecipitationUnit.inch, 29 | ), 30 | returnsNormally, 31 | ); 32 | }); 33 | test('cell selection', () { 34 | expect( 35 | () => WeatherApi(cellSelection: CellSelection.sea), 36 | returnsNormally, 37 | ); 38 | }); 39 | }); 40 | }); 41 | 42 | group('flatbuffers', () { 43 | late WeatherApi api; 44 | setUp(() { 45 | api = WeatherApi(); 46 | }); 47 | 48 | group('enum deserialization', () { 49 | test('for current data', () async { 50 | final response = await api.request( 51 | locations: { 52 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 53 | }, 54 | current: WeatherCurrent.values.toSet(), 55 | ); 56 | expect( 57 | response.segments[0].currentData.keys, 58 | containsAll(WeatherCurrent.values), 59 | ); 60 | }); 61 | test('for hourly data', () async { 62 | final response = await api.request( 63 | locations: { 64 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 65 | }, 66 | hourly: WeatherHourly.values.toSet(), 67 | ); 68 | expect( 69 | response.segments[0].hourlyData.keys, 70 | containsAll(WeatherHourly.values), 71 | ); 72 | }); 73 | test('for daily data', () async { 74 | final response = await api.request( 75 | locations: { 76 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 77 | }, 78 | daily: WeatherDaily.values.toSet(), 79 | ); 80 | expect( 81 | response.segments[0].dailyData.keys, 82 | containsAll(WeatherDaily.values), 83 | ); 84 | }); 85 | }); 86 | 87 | group('get', () { 88 | test('current temperature', () async { 89 | final result = await api.request( 90 | locations: { 91 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 92 | }, 93 | current: {WeatherCurrent.temperature_2m}, 94 | ); 95 | final temperature = 96 | result.segments[0].currentData[WeatherCurrent.temperature_2m]; 97 | expect(temperature, isNotNull); 98 | }); 99 | test('hourly temperature', () async { 100 | final result = await api.request( 101 | locations: { 102 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 103 | }, 104 | hourly: {WeatherHourly.temperature_2m}, 105 | ); 106 | final temperature = 107 | result.segments[0].hourlyData[WeatherHourly.temperature_2m]; 108 | expect(temperature, isNotNull); 109 | expect(temperature!.values, isNotEmpty); 110 | }); 111 | test('daily temperature max', () async { 112 | final result = await api.request( 113 | locations: { 114 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 115 | }, 116 | daily: {WeatherDaily.temperature_2m_max}, 117 | ); 118 | final temperature = 119 | result.segments[0].dailyData[WeatherDaily.temperature_2m_max]; 120 | expect(temperature, isNotNull); 121 | expect(temperature!.values, isNotEmpty); 122 | }); 123 | }); 124 | }); 125 | 126 | group('json get', () { 127 | late WeatherApi api; 128 | setUp(() { 129 | api = WeatherApi(); 130 | }); 131 | 132 | test('current temperature', () async { 133 | final result = await api.requestJson( 134 | locations: { 135 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 136 | }, 137 | current: {WeatherCurrent.temperature_2m}, 138 | ); 139 | expect(result['error'], isNot(true)); 140 | expect(result['current'], isNotNull); 141 | expect(result['current']['temperature_2m'], isNotNull); 142 | }); 143 | test('hourly temperature', () async { 144 | final result = await api.requestJson( 145 | locations: { 146 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 147 | }, 148 | hourly: {WeatherHourly.temperature_2m}, 149 | ); 150 | expect(result['error'], isNot(true)); 151 | expect(result['hourly'], isNotNull); 152 | expect(result['hourly']['temperature_2m'], isNotNull); 153 | expect( 154 | result['hourly']['time'].length, 155 | result['hourly']['temperature_2m'].length, 156 | ); 157 | }); 158 | test('daily temperature max', () async { 159 | final result = await api.requestJson( 160 | locations: { 161 | OpenMeteoLocation(latitude: latitude, longitude: longitude) 162 | }, 163 | daily: {WeatherDaily.temperature_2m_max}, 164 | ); 165 | expect(result['error'], isNot(true)); 166 | expect(result['daily'], isNotNull); 167 | expect(result['daily']['temperature_2m_max'], isNotNull); 168 | expect( 169 | result['daily']['time'].length, 170 | result['daily']['temperature_2m_max'].length, 171 | ); 172 | }); 173 | }); 174 | }); 175 | } 176 | -------------------------------------------------------------------------------- /weather_api.fbs: -------------------------------------------------------------------------------- 1 | // Flatbuffers API result format for open-meteo weather data 2 | // 3 | // Generate swift code with: 4 | // flatc --swift -o swift/Sources/OpenMeteoSdk/ flatbuffers/*.fbs 5 | // See DEVELOPMENT.md for more information 6 | // 7 | // Make sure flatbuffers is installed with `brew install flatbuffers` 8 | 9 | namespace openmeteo_sdk; 10 | 11 | enum Unit : ubyte { 12 | undefined = 0, 13 | celsius, 14 | centimetre, 15 | cubic_metre_per_cubic_metre, 16 | cubic_metre_per_second, 17 | degree_direction, 18 | dimensionless_integer, 19 | dimensionless, 20 | european_air_quality_index, 21 | fahrenheit, 22 | feet, 23 | fraction, 24 | gdd_celsius, 25 | geopotential_metre, 26 | grains_per_cubic_metre, 27 | gram_per_kilogram, 28 | hectopascal, 29 | hours, 30 | inch, 31 | iso8601, 32 | joule_per_kilogram, 33 | kelvin, 34 | kilopascal, 35 | kilogram_per_square_metre, 36 | kilometres_per_hour, 37 | knots, 38 | megajoule_per_square_metre, 39 | metre_per_second_not_unit_converted, 40 | metre_per_second, 41 | metre, 42 | micrograms_per_cubic_metre, 43 | miles_per_hour, 44 | millimetre, 45 | pascal, 46 | per_second, 47 | percentage, 48 | seconds, 49 | unix_time, 50 | us_air_quality_index, 51 | watt_per_square_metre, 52 | wmo_code, 53 | parts_per_million 54 | } 55 | 56 | enum Model: ubyte { 57 | undefined = 0, 58 | best_match, 59 | gfs_seamless, 60 | gfs_global, 61 | gfs_hrrr, 62 | meteofrance_seamless, 63 | meteofrance_arpege_seamless, 64 | meteofrance_arpege_world, 65 | meteofrance_arpege_europe, 66 | meteofrance_arome_seamless, 67 | meteofrance_arome_france, 68 | meteofrance_arome_france_hd, 69 | jma_seamless, 70 | jma_msm, 71 | jms_gsm, 72 | jma_gsm, 73 | gem_seamless, 74 | gem_global, 75 | gem_regional, 76 | gem_hrdps_continental, 77 | icon_seamless, 78 | icon_global, 79 | icon_eu, 80 | icon_d2, 81 | ecmwf_ifs04, 82 | metno_nordic, 83 | era5_seamless, 84 | era5, 85 | cerra, 86 | era5_land, 87 | ecmwf_ifs, 88 | gwam, 89 | ewam, 90 | glofas_seamless_v3, 91 | glofas_forecast_v3, 92 | glofas_consolidated_v3, 93 | glofas_seamless_v4, 94 | glofas_forecast_v4, 95 | glofas_consolidated_v4, 96 | gfs025, 97 | gfs05, 98 | CMCC_CM2_VHR4, 99 | FGOALS_f3_H_highresSST, 100 | FGOALS_f3_H, 101 | HiRAM_SIT_HR, 102 | MRI_AGCM3_2_S, 103 | EC_Earth3P_HR, 104 | MPI_ESM1_2_XR, 105 | NICAM16_8S, 106 | cams_europe, 107 | cams_global, 108 | cfsv2, 109 | era5_ocean, 110 | cma_grapes_global, 111 | bom_access_global, 112 | bom_access_global_ensemble, 113 | arpae_cosmo_seamless, 114 | arpae_cosmo_2i, 115 | arpae_cosmo_2i_ruc, 116 | arpae_cosmo_5m, 117 | ecmwf_ifs025, 118 | ecmwf_aifs025, 119 | gfs013, 120 | gfs_graphcast025, 121 | ecmwf_wam025, 122 | meteofrance_wave, 123 | meteofrance_currents, 124 | ecmwf_wam025_ensemble, 125 | ncep_gfswave025, 126 | ncep_gefswave025, 127 | knmi_seamless, 128 | knmi_harmonie_arome_europe, 129 | knmi_harmonie_arome_netherlands, 130 | dmi_seamless, 131 | dmi_harmonie_arome_europe, 132 | metno_seamless, 133 | era5_ensemble, 134 | ecmwf_ifs_analysis, 135 | ecmwf_ifs_long_window, 136 | ecmwf_ifs_analysis_long_window, 137 | ukmo_global_deterministic_10km, 138 | ukmo_uk_deterministic_2km, 139 | ukmo_seamless, 140 | ncep_gfswave016, 141 | ncep_nbm_conus, 142 | ukmo_global_ensemble_20km, 143 | ecmwf_aifs025_single, 144 | jma_jaxa_himawari, 145 | eumetsat_sarah3, 146 | eumetsat_lsa_saf_msg, 147 | eumetsat_lsa_saf_iodc, 148 | satellite_radiation_seamless, 149 | kma_gdps, 150 | kma_ldps, 151 | kma_seamless, 152 | italia_meteo_arpae_icon_2i 153 | } 154 | 155 | enum Variable: ubyte { 156 | undefined = 0, 157 | apparent_temperature, 158 | cape, 159 | cloud_cover, 160 | cloud_cover_high, 161 | cloud_cover_low, 162 | cloud_cover_mid, 163 | daylight_duration, 164 | dew_point, 165 | diffuse_radiation, 166 | diffuse_radiation_instant, 167 | direct_normal_irradiance, 168 | direct_normal_irradiance_instant, 169 | direct_radiation, 170 | direct_radiation_instant, 171 | et0_fao_evapotranspiration, 172 | evapotranspiration, 173 | freezing_level_height, 174 | growing_degree_days, 175 | is_day, 176 | latent_heat_flux, 177 | leaf_wetness_probability, 178 | lifted_index, 179 | lightning_potential, 180 | precipitation, 181 | precipitation_hours, 182 | precipitation_probability, 183 | pressure_msl, 184 | rain, 185 | relative_humidity, 186 | runoff, 187 | sensible_heat_flux, 188 | shortwave_radiation, 189 | shortwave_radiation_instant, 190 | showers, 191 | snow_depth, 192 | snow_height, 193 | snowfall, 194 | snowfall_height, 195 | snowfall_water_equivalent, 196 | sunrise, 197 | sunset, 198 | soil_moisture, 199 | soil_moisture_index, 200 | soil_temperature, 201 | surface_pressure, 202 | surface_temperature, 203 | temperature, 204 | terrestrial_radiation, 205 | terrestrial_radiation_instant, 206 | total_column_integrated_water_vapour, 207 | updraft, 208 | uv_index, 209 | uv_index_clear_sky, 210 | vapour_pressure_deficit, 211 | visibility, 212 | weather_code, 213 | wind_direction, 214 | wind_gusts, 215 | wind_speed, 216 | vertical_velocity, 217 | geopotential_height, 218 | wet_bulb_temperature, 219 | river_discharge, 220 | wave_height, 221 | wave_period, 222 | wave_direction, 223 | wind_wave_height, 224 | wind_wave_period, 225 | wind_wave_peak_period, 226 | wind_wave_direction, 227 | swell_wave_height, 228 | swell_wave_period, 229 | swell_wave_peak_period, 230 | swell_wave_direction, 231 | pm10, 232 | pm2p5, 233 | dust, 234 | aerosol_optical_depth, 235 | carbon_monoxide, 236 | nitrogen_dioxide, 237 | ammonia, 238 | ozone, 239 | sulphur_dioxide, 240 | alder_pollen, 241 | birch_pollen, 242 | grass_pollen, 243 | mugwort_pollen, 244 | olive_pollen, 245 | ragweed_pollen, 246 | european_aqi, 247 | european_aqi_pm2p5, 248 | european_aqi_pm10, 249 | european_aqi_nitrogen_dioxide, 250 | european_aqi_ozone, 251 | european_aqi_sulphur_dioxide, 252 | us_aqi, 253 | us_aqi_pm2p5, 254 | us_aqi_pm10, 255 | us_aqi_nitrogen_dioxide, 256 | us_aqi_ozone, 257 | us_aqi_sulphur_dioxide, 258 | us_aqi_carbon_monoxide, 259 | sunshine_duration, 260 | convective_inhibition, 261 | shortwave_radiation_clear_sky, 262 | global_tilted_irradiance, 263 | global_tilted_irradiance_instant, 264 | ocean_current_velocity, 265 | ocean_current_direction, 266 | cloud_base, 267 | cloud_top, 268 | mass_density, 269 | boundary_layer_height, 270 | formaldehyde, 271 | glyoxal, 272 | non_methane_volatile_organic_compounds, 273 | pm10_wildfires, 274 | peroxyacyl_nitrates, 275 | secondary_inorganic_aerosol, 276 | residential_elementary_carbon, 277 | total_elementary_carbon, 278 | pm2_5_total_organic_matter, 279 | sea_salt_aerosol, 280 | nitrogen_monoxide, 281 | thunderstorm_probability, 282 | rain_probability, 283 | freezing_rain_probability, 284 | ice_pellets_probability, 285 | snowfall_probability, 286 | carbon_dioxide, 287 | methane, 288 | sea_level_height_msl, 289 | sea_surface_temperature, 290 | invert_barometer_height, 291 | hail, 292 | albedo, 293 | precipitation_type, 294 | convective_cloud_base, 295 | convective_cloud_top, 296 | snow_depth_water_equivalent, 297 | secondary_swell_wave_height, 298 | secondary_swell_wave_period, 299 | secondary_swell_wave_peak_period, 300 | secondary_swell_wave_direction, 301 | tertiary_swell_wave_height, 302 | tertiary_swell_wave_period, 303 | tertiary_swell_wave_peak_period, 304 | tertiary_swell_wave_direction, 305 | } 306 | 307 | enum Aggregation: ubyte { 308 | none = 0, 309 | minimum, 310 | maximum, 311 | mean, 312 | p10, 313 | p25, 314 | median, 315 | p75, 316 | p90, 317 | dominant, 318 | sum, 319 | spread 320 | } 321 | 322 | table VariableWithValues { 323 | variable: Variable; 324 | unit: Unit; 325 | 326 | value: float; // Only used for current conditions 327 | values: [float]; // Contains a time series of data 328 | values_int64: [int64]; // Only for sunrise/set as a unix timestamp 329 | 330 | altitude: int16; 331 | aggregation: Aggregation; 332 | pressure_level: int16; 333 | depth: int16; 334 | depth_to: int16; 335 | ensemble_member: int16; 336 | previous_day: int16; 337 | } 338 | 339 | table VariablesWithTime { 340 | time: int64; 341 | time_end: int64; 342 | interval: int32; 343 | variables: [VariableWithValues]; 344 | } 345 | 346 | table WeatherApiResponse { 347 | latitude: float; 348 | longitude: float; 349 | elevation: float; 350 | generation_time_milliseconds: float; 351 | location_id: int64; 352 | model: Model; 353 | utc_offset_seconds: int32; 354 | timezone: string; 355 | timezone_abbreviation: string; 356 | current: VariablesWithTime; 357 | daily: VariablesWithTime; 358 | hourly: VariablesWithTime; 359 | minutely_15: VariablesWithTime; 360 | six_hourly: VariablesWithTime; 361 | } 362 | 363 | root_type WeatherApiResponse; 364 | --------------------------------------------------------------------------------