{"id":38457685,"url":"https://github.com/paulvt/sinoptik","last_synced_at":"2026-01-17T04:55:05.389Z","repository":{"id":142836838,"uuid":"514869929","full_name":"paulvt/sinoptik","owner":"paulvt","description":"Read-only mirror of https://git.luon.net/paul/sinoptik","archived":false,"fork":false,"pushed_at":"2026-01-15T00:35:55.000Z","size":474,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-15T07:39:20.293Z","etag":null,"topics":["air-quality","json","pollen","rocket","rust","weather"],"latest_commit_sha":null,"homepage":"https://git.luon.net/paul/sinoptik","language":"Rust","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paulvt.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-07-17T14:42:51.000Z","updated_at":"2026-01-15T00:35:58.000Z","dependencies_parsed_at":"2025-01-17T07:28:18.745Z","dependency_job_id":"a722a29e-0637-450c-83e4-e8578dcd5d0f","html_url":"https://github.com/paulvt/sinoptik","commit_stats":{"total_commits":158,"total_committers":3,"mean_commits":"52.666666666666664","dds":"0.012658227848101222","last_synced_commit":"c2450267e00b5c0129266a91f81c63faf57e4fae"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/paulvt/sinoptik","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulvt%2Fsinoptik","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulvt%2Fsinoptik/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulvt%2Fsinoptik/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulvt%2Fsinoptik/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paulvt","download_url":"https://codeload.github.com/paulvt/sinoptik/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulvt%2Fsinoptik/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28497280,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T04:31:57.058Z","status":"ssl_error","status_checked_at":"2026-01-17T04:31:45.816Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["air-quality","json","pollen","rocket","rust","weather"],"created_at":"2026-01-17T04:55:03.962Z","updated_at":"2026-01-17T04:55:05.372Z","avatar_url":"https://github.com/paulvt.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sinoptik\n\nSinoptik is a (REST) API service that provides an API for today's weather\nforecast.  It can provide you with a specific set or all available metrics\nthat it supports.\n\nCurrently supported metrics are:\n\n* Air quality index (per hour, from [Luchtmeetnet])\n* NO₂ concentration (per hour, from [Luchtmeetnet])\n* O₃ concentration (per hour, from [Luchtmeetnet])\n* Particulate matter (PM10) concentration (per hour, from [Luchtmeetnet])\n* Pollen (per hour, from [Buienradar])\n* Pollen/air quality index (per hour, combined from [Buienradar] and\n  [Luchtmeetnet])\n* Precipitation (per 5 minutes, from [Buienradar])\n* UV index (per day, from [Buienradar])\n\n[Buienradar]: https://buienradar.nl\n[Luchtmeetnet]: https://luchtmeetnet.nl\n\nBecause of the currently supported data providers, only data for\nThe Netherlands can be queried.\n\n## Building \u0026 running\n\nUsing Cargo, it is easy to build and run Sinoptik, just run:\n\n```shell\n$ cargo run --release\n...\n   Compiling sinoptik v0.1.0 (/path/to/sinoptik)\n    Finished release [optimized] target(s) in 9m 26s\n     Running `/path/to/sinoptik/target/release/sinoptik`\n```\n\n(Note that Rocket listens on `127.0.0.1:3000` by default for debug builds, i.e.\nbuilds when you don't add `--release`.)\n\nYou can provide Rocket with configuration to use a different address and/or port.\nJust create a `Rocket.toml` file that contains (or copy `Rocket.toml.example`):\n\n```toml\n[default]\naddress = \"0.0.0.0\"\nport = 2356\n```\n\nThis will work independent of the type of build. For more about Rocket's\nconfiguration, see: \u003chttps://rocket.rs/v0.5-rc/guide/configuration/\u003e.\n\n## Forecast API endpoint\n\nThe `/forecast` API endpoint provides forecasts per requested metric a list of\nforecast item which are each comprised of a value and its (UNIX) timestamp. It\ndoes so for a requested location.\n\n### Locations\n\nTo select a location, you can either provide an address, or a geocoded position\nby providing a latitude and longitude.\nFor example, to get forecasts for all metrics for the Stationsplein in Utrecht,\nuse:\n\n```http\nGET /forecast?address=Stationsplein,Utrecht\u0026metrics[]=all\n```\n\nor directly by using its geocoded position:\n\n```http\nGET /forecast?lat=52.0902\u0026lon=5.1114\u0026metrics[]=all\n```\n\n### Metrics\n\nWhen querying, the metrics need to be selected. It can be one of: `AQI`, `NO2`,\n`O3`, `PAQI`, `PM10`, `pollen`, `precipitation` or `UVI`. If you use metric\n`all`, or `all` is part of the selected metrics, all metrics will be retrieved.\nNote that the parameter \"array\" notation as well as the repeated parameter\nnotation are supported. For example:\n\n```http\nGET /forecast?address=Stationsplein,Utrecht\u0026metrics[]=AQI\u0026metrics[]=pollen\nGET /forecast?address=Stationsplein,Utrecht\u0026metrics=AQI\u0026metrics=pollen\nGET /forecast?address=Stationsplein,Utrecht\u0026metrics=all\n```\n\n### Forecast responses\n\nThe response of the API is a JSON object that contains three fixed fields:\n\n* `lat`: the latitude of the geocoded position the forecast is for (number)\n* `lon`: the longitude of the geocoded position the forecast is for (number)\n* `time`: the (UNIX) timestamp of the forecast, basically \"now\" (number)\n\nThen, it contains a field per requested metric with a list of forecast items\nwith two fixed fields as value:\n\n* `time`: the (UNIX) timestamp for that forecasted value (number)\n* `value`: the forecasted value for the metric (number)\n\nAn example when requesting just UVI (because it's short) for some random\nposition:\n\n```json\n{\n  \"lat\": 52.0905169,\n  \"lon\": 5.1109709,\n  \"time\": 1652188682,\n  \"UVI\": [\n    {\n      \"time\": 1652140800,\n      \"value\": 4\n    },\n    {\n      \"time\": 1652227200,\n      \"value\": 4\n    },\n    {\n      \"time\": 1652313600,\n      \"value\": 4\n    },\n    {\n      \"time\": 1652400000,\n      \"value\": 4\n    },\n    {\n      \"time\": 1652486400,\n      \"value\": 5\n    }\n  ]\n}\n```\n\n#### Combined metric PAQI\n\nThe PAQI (pollen/air quality index) metric is a special combined metric.\nIf selected, it merges items from the AQI and pollen metric into `PAQI` by\nselecting the maximum value for each hour:\n\n```json\n{\n  \"lat\": 52.0905169,\n  \"lon\": 5.1109709,\n  \"time\": 1652189065,\n  \"PAQI\": [\n    {\n      \"time\": 1652187600,\n      \"value\": 6.09\n    },\n    {\n      \"time\": 1652191200,\n      \"value\": 6.09\n    },\n    ...\n  ]\n}\n```\n\n#### Errors\n\nIf geocoding of an address is requested but fails, a not found error is\nreturned (HTTP 404). with the following body (this will change in the future):\n\n```json\n{\n  \"error\": {\n    \"code\": 404,\n    \"reason\": \"Not Found\",\n    \"description\": \"The requested resource could not be found.\"\n  }\n}\n```\n\nIf for any specific metric an error occurs, the list with forecast items will\nbe absent. However, the `errors` field will contain the error message for each\nfailed metric. For example, say Buienradar is down and precipitation forecast\nitems can not be retrieved:\n\n```json\n{\n  \"lat\": 52.0905169,\n  \"lon\": 5.1109709,\n  \"time\": 1654524574,\n  ...\n  \"errors\": {\n    \"precipitation\": \"HTTP request error: error sending request for url (https://gpsgadget.buienradar.nl/data/raintext?lat=52.09\u0026lon=5.11): error trying to connect: tcp connect error: Connection refused (os error 111)\"\n  }\n}\n```\n\n## Map API endpoint\n\nThe `/map` API endpoint basically only exists for debugging purposes. Given an\naddress or geocoded position, it shows the current map for the provided metric\nand draws a crosshair on the position.\nCurrently, only the `PAQI`, `pollen` and `UVI` metrics are backed by a map.\n\nFor example, to get the current pollen map with a crosshair on Stationsplein in\nUtrecht, use:\n\n```http\nGET /map?address=Stationsplein,Utrecht\u0026metric=pollen\n```\n\nor directly by using its geocoded position:\n\n```http\nGET /map?lat=52.0902\u0026lon=5.1114\u0026metric=pollen\n```\n\n### Map responses\n\nThe response is a PNG image with a crosshair drawn on the map. If geocoding of\nan address fails or if the position is out of bounds of the map, nothing is\nreturned (HTTP 404). If the maps cannot/have not been downloaded or cached yet,\na service unavailable error is returned (HTTP 503).\n\n## Version API endpoint\n\nThe `/version` API endpoint provides information of the current version and\nbuild of the service.  This can be used to check if it needs to be updated.\nAgain, there is no path and no query parameters, just:\n\n```http\nGET /version\n```\n\n### Version responses\n\nThe response uses the JSON format and typically looks like this:\n\n```json\n{\n  \"version\": \"0.2.7\",\n  \"timestamp\": \"2023-05-29T13:34:34.701323159Z\",\n  \"git_sha\": \"bb5962d\",\n  \"git_timestamp\": \"2023-05-29T15:32:17.000000000+02:00\"\n}\n```\n\n(Build and git information in example output may be out of date.)\n\n## License\n\nSinoptik is licensed under the MIT license (see the `LICENSE` file or\n\u003chttp://opensource.org/licenses/MIT\u003e).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulvt%2Fsinoptik","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaulvt%2Fsinoptik","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulvt%2Fsinoptik/lists"}