{"id":35176637,"url":"https://github.com/toringer/home-assistant-sporet","last_synced_at":"2026-01-13T22:03:28.013Z","repository":{"id":327281619,"uuid":"1108675511","full_name":"toringer/home-assistant-sporet","owner":"toringer","description":"Home Assistant integration for monitoring cross-country ski trail conditions from Sporet.no - track grooming status and trail conditions","archived":false,"fork":false,"pushed_at":"2025-12-28T20:10:30.000Z","size":259,"stargazers_count":2,"open_issues_count":4,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-31T13:16:54.488Z","etag":null,"topics":["cross-country","custom-integration","home-assistant"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"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/toringer.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2025-12-02T19:07:02.000Z","updated_at":"2025-12-29T09:30:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/toringer/home-assistant-sporet","commit_stats":null,"previous_names":["toringer/home-assistant-sporet"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/toringer/home-assistant-sporet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toringer%2Fhome-assistant-sporet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toringer%2Fhome-assistant-sporet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toringer%2Fhome-assistant-sporet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toringer%2Fhome-assistant-sporet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/toringer","download_url":"https://codeload.github.com/toringer/home-assistant-sporet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toringer%2Fhome-assistant-sporet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28400890,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: 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":["cross-country","custom-integration","home-assistant"],"created_at":"2025-12-28T22:50:47.478Z","updated_at":"2026-01-13T22:03:28.008Z","avatar_url":"https://github.com/toringer.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![home-assistant-sporet](https://img.shields.io/github/release/toringer/home-assistant-sporet.svg?1)](https://github.com/toringer/home-assistant-sporet)\n[![Validate with hassfest](https://github.com/toringer/home-assistant-sporet/workflows/Validate%20with%20hassfest/badge.svg)](https://github.com/toringer/home-assistant-sporet/actions/workflows/hassfest.yaml)\n[![HACS Validation](https://github.com/toringer/home-assistant-sporet/actions/workflows/validate_hacs.yaml/badge.svg)](https://github.com/toringer/home-assistant-sporet/actions/workflows/validate_hacs.yaml)\n[![Maintenance](https://img.shields.io/maintenance/yes/2025.svg)](https://github.com/toringer/home-assistant-sporet)\n[![home-assistant-sporet_downloads](https://img.shields.io/github/downloads/toringer/home-assistant-sporet/total)](https://github.com/toringer/home-assistant-sporet)\n[![home-assistant-sporet_downloads](https://img.shields.io/github/downloads/toringer/home-assistant-sporet/latest/total)](https://github.com/toringer/home-assistant-sporet)\n\n\n# Sporet.no - Home Assistant Integration\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/toringer/home-assistant-sporet/master/assets/sporet.svg\" alt=\"Sporet.no Logo\" width=\"200\"/\u003e\n\u003c/div\u003e\n\nA Home Assistant custom component for monitoring cross-country ski trail conditions from [Sporet.no](https://sporet.no/).\n\n## Features\n\n- Monitor ski trail slope status\n- Track trail preparation time\n- View preparation quality across slope segments\n- Automatic updates every 15 minutes\n\n\n## Installation\n\n### HACS (Recommended)\n\n1. Open HACS in your Home Assistant instance\n2. Click on \"Integrations\"\n3. Click the three dots in the top right corner\n4. Select \"Custom repositories\"\n5. Add this repository URL: `https://github.com/yourusername/home-assistant-sporet`\n6. Select \"Integration\" as the category\n7. Click \"Add\"\n8. Find \"Sporet\" in the HACS integration list and click \"Download\"\n9. Restart Home Assistant\n\n### Manual Installation\n\n1. Download the `custom_components/sporet` folder from this repository\n2. Copy the entire `sporet` folder to your Home Assistant `custom_components` directory:\n   - Path: `\u003cconfig_dir\u003e/custom_components/sporet/`\n3. Restart Home Assistant\n\n## Configuration\n\n### Prerequisites\n\nBefore setting up the integration, you need:\n\n1. **Ski Trail Slope ID**: Find this at [sporet.no](https://sporet.no/)\n   - Navigate to your desired ski trail\n   - Select a slope in the map\n   - Click the `Share` button\n   - Extract the slope id from the copied URL\n\n\n2. **Bearer Token**:\n   - Log in to sporet.no\n   - Open the network anaylser in the developer tools of the browser\n   - Find the `details` traffic, find the `authorization` attribute in the header section\n   - Copy the token\n\n\u003e [!IMPORTANT]\n\u003e Make sure you copy the entire token!\n\u003e\n\u003e Some browsers might truncate the Bearer Token when you copy it. Look for a switch to\n\u003e \"display raw headers\" or similar which will ensure the entire string is available.\n\nAnother option is to right click on one of the requests to `https://api.sporet.no` and look for\n**Copy Request Headers**, or **Copy as Curl** or something similar.  Paste the result into\na plain text file and find the line starting with `Authorization:`.  Copy the entire line and \npaste it into the Bearer Token field below.\n\n\n### Setup Steps\n\n1. In Home Assistant, go to **Settings** → **Devices \u0026 Services**\n2. Click **+ Add Integration**\n3. Search for \"Sporet\"\n4. Enter your configuration:\n   - **Bearer Token**: Your API authentication token\n5. Click **Submit**\n\nThe integration will validate your credentials.\n\nAfter the main entry is created, you can add slopes and segments.\n\n1. Go to **Settings** → **Devices \u0026 Services**\n2. Find the \"Sporet\" integration\n3. Click the \"+\" sign next to \"Add entry\" in the Sporet Integration\n4. Add a Slope - either a \"Share\" link from the Slope or Segment or just the ID number\n\nThe integration will create sensors for the specified slope.\n\n## Sensors\n\nThe integration creates three sensors for each configured slope:\n\n### 1. Prepped Time\n- **Entity ID**: `sensor.\u003cslope_name\u003e_prepped_time`\n- **Description**: Timestamp of when the trail was last prepared\n- **Device Class**: Timestamp\n- **Example**: `2025-12-01T09:06:12Z`\n\n### 2. Prep Symbol\n- **Entity ID**: `sensor.\u003cslope_name\u003e_prep_symbol`\n- **Description**: Numeric code indicating overall trail condition\n- **Values**:\n  - `30`: Good condition\n  - `50`: Fair condition\n  - `70`: Poor condition or not groomed\n  - Other values as defined by Sporet\n- **Example**: `30`\n\n### 3. Prep Symbol Parts\n- **Entity ID**: `sensor.\u003cslope_name\u003e_prep_symbol_parts`\n- **Description**: Shows the lowest prep symbol value across all route segments\n- **Attributes**: Contains `parts` array with detailed breakdown by segment\n- **Example**: `30` (lowest value from all segments)\n\n### Additional Attributes\n\nEach sensor includes additional attributes with detailed route information:\n\n- `slope_id`: The route identifier\n- `slope_name`: Name of the ski trail route\n- `destination_name`: Name of the destination area\n- `county`: County name\n- `municipal`: Municipality name\n- `country`: Country\n- `prepped_by`: Organization responsible for grooming\n- `hasClassic`: Boolean - Classic skiing available\n- `hasSkating`: Boolean - Skating skiing available\n- `hasFloodlight`: Boolean - Floodlight available\n- `isScooterTrail`: Boolean - Scooter trail\n- `routelength`: Total length of the route in meters\n- `totalElevationGain`: Total elevation gain in meters\n- `totalElevationLoss`: Total elevation loss in meters\n- `parts`: (prep_symbol_parts sensor only) Array of segment-level prep symbols with percentages\n\n## Updating Bearer Token\n\nIf your bearer token expires or needs to be updated:\n\n1. Go to **Settings** → **Devices \u0026 Services**\n2. Find the \"Sporet\" integration\n3. Click **Configure**\n4. Enter your new bearer token\n5. Click **Submit**\n\nThe integration will reload with the new token without losing your configuration.\n\n## Example Automation\n\n### Notify when trail is freshly groomed\n\n```yaml\nautomation:\n  - alias: \"Notify when trail is groomed\"\n    trigger:\n      - platform: state\n        entity_id: sensor.sjusjoen_ljosheim_kort_prepped_time\n    condition:\n      - condition: template\n        value_template: \u003e\n          {{ (now() - states.sensor.sjusjoen_ljosheim_kort_prepped_time.state | as_datetime).total_seconds() \u003c 3600 }}\n    action:\n      - service: notify.mobile_app\n        data:\n          title: \"Trail Groomed!\"\n          message: \"Ljøsheim trail segment was just groomed.\"\n```\n\n### Display trail condition in Lovelace\n\n```yaml\ntype: entities\ntitle: Ski Trail Status\nentities:\n  - entity: sensor.heistadmoen_10_km_prepped_time\n    name: Last Groomed\n  - entity: sensor.heistadmoen_10_km_prep_symbol\n    name: Overall Condition\n  - entity: sensor.heistadmoen_10_km_prep_symbol_parts\n    name: Worst Segment Condition\n```\n\n## API Details\n\nThe integration uses the Sporet public API:\n\n- **Endpoint**: `https://api.sporet.no/loypeapi/public/skiroutes/{slope_id}/details`\n- **Authentication**: Bearer token in Authorization header\n- **Update Interval**: 900 seconds (15 minutes)\n- **Method**: GET\n\n\n## Troubleshooting\n\n### Cannot Connect Error\n\n- Verify your internet connection\n- Check if sporet.no is accessible\n- Ensure the API endpoint is not blocked by your firewall\n\n### Invalid Auth Error\n\n- Verify your bearer token is correct\n- Check if the token has expired\n- Regenerate a new token from sporet.no\n\n### Route Not Found Error\n\n- Verify the slope ID exists on sporet.no\n- Check the slope ID is correct\n- Make a manual API call to verify the route exists\n\n### Enable Debug Logging\n\nAdd to your `configuration.yaml`:\n\n```yaml\nlogger:\n  default: info\n  logs:\n    custom_components.sporet: debug\n```\n\n## Development\n\nThis integration includes a development container for easy testing:\n\n1. Open the project in VS Code\n2. Install the \"Remote - Containers\" extension\n3. Click \"Reopen in Container\" when prompted\n4. The development Home Assistant instance will start automatically\n5. Access at `http://localhost:8123`\n\n## Support\n\nFor issues, feature requests, or contributions:\n- GitHub Issues: [Create an issue](https://github.com/yourusername/home-assistant-sporet/issues)\n- Discussions: [Join the discussion](https://github.com/yourusername/home-assistant-sporet/discussions)\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## Credits\n\n- Data provided by [Sporet.no](https://sporet.no/)\n- Integration developed for Home Assistant\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoringer%2Fhome-assistant-sporet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftoringer%2Fhome-assistant-sporet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoringer%2Fhome-assistant-sporet/lists"}