Last Updated: 2026-03-24 (Commit convention for release notes filtering)
Before completing ANY task, check if you modified:
- Any .py files (especially
__init__.py,config_flow.py,const.py,sensor.py,translations.py) - Constants, API endpoints, or headers
- API request patterns or error handling
- Sensor definitions or translation mappings
- Data flow or architecture
If YES to ANY: You MUST update this CLAUDE.md file NOW:
- Update "Last Updated" date at top
- Add entry to Changelog section (at bottom)
- Update relevant documentation sections
IMPORTANT: This file must be kept up-to-date whenever significant changes are made to the codebase. Update this file BEFORE committing changes that affect architecture, add new features, modify data flows, or change development patterns.
This is a Home Assistant custom component that integrates weather data from Fintraffic's (Finnish Transport Infrastructure Agency) Digitraffic API into Home Assistant. It provides real-time road weather station data including temperature, precipitation, road surface conditions, visibility, and more.
- Type: Home Assistant Custom Component (HACS)
- Language: Python 3
- Integration Class: Cloud Polling
- Update Interval: 5 minutes (configurable in
const.py) - API: Fintraffic Digitraffic REST API (public, no authentication required)
- Repository: https://github.com/taskinen/digitraffic_hacs
- Version: 0.1.0
Digitraffic API
↓ (HTTP GET every 5 minutes)
DigitrafficDataUpdateCoordinator (_async_update_data)
↓ (parses sensorValues array into dict)
coordinator.data = {"SENSOR_KEY": value, "measuredTime": "...", ...}
↓ (Home Assistant polls coordinator)
DigitrafficWeatherSensor (native_value property)
↓ (checks if sensor needs translation)
translate_sensor_value() [if translate=True]
↓ (looks up code in SENSOR_VALUE_TRANSLATIONS)
Displayed in Home Assistant UI
custom_components/digitraffic/
├── __init__.py # Integration setup & data coordinator
├── manifest.json # Component metadata & dependencies
├── config_flow.py # UI configuration flow
├── const.py # Constants, API endpoints, sensor definitions
├── sensor.py # Sensor platform implementation
├── translations.py # Sensor value translation mappings
└── brand/ # Logo and icon assets
├── icon.png
└── logo.png
.github/workflows/
├── ci.yml # CI syntax validation workflow
└── release.yml # Release automation workflow
Purpose: Entry point for the integration. Manages setup, teardown, and data fetching.
Key Classes:
DigitrafficDataUpdateCoordinator: Inherits fromDataUpdateCoordinator- Fetches data from API every 5 minutes
- Processes JSON response into a flat dictionary
- Handles errors and timeouts
API Data Structure (Response):
{
"stationId": 12345,
"stationName": "Vantaa",
"measuredTime": "2026-01-02T12:00:00Z",
"sensorValues": [
{"name": "ILMA", "value": -5.2},
{"name": "KELI_1", "value": 2},
{"name": "VALLITSEVA_SÄÄ", "value": 63}
]
}Processed Data (coordinator.data):
{
"ILMA": -5.2,
"KELI_1": 2,
"VALLITSEVA_SÄÄ": 63,
"measuredTime": "2026-01-02T12:00:00Z",
"stationName": "Vantaa"
}Important Methods:
async_setup_entry(): Creates coordinator and forwards to platformsasync_unload_entry(): Cleanup on integration removal_async_update_data(): Fetches and processes API data
Defines integration properties:
- Domain:
digitraffic - Config flow enabled
- IoT class:
cloud_polling - Dependency:
aiohttp(HTTP client) - Codeowner: @taskinen
Purpose: Handles integration setup via Home Assistant UI.
Features:
- Fetches list of all available weather stations from API
- Provides search functionality (by name or ID)
- Validates station ID exists before creating entry
- Prevents duplicate station configurations (uses unique_id)
Key Functions:
fetch_stations(): Retrieves all stations from/api/weather/v1/stations(GeoJSON)validate_station_id(): Verifies station exists and is accessibleDigitrafficConfigFlow.async_step_user(): User interaction flow with search
API Endpoints Used:
- List stations:
https://tie.digitraffic.fi/api/weather/v1/stations(returns GeoJSON FeatureCollection) - Validate station:
https://tie.digitraffic.fi/api/weather/v1/stations/{id} - Get station data:
https://tie.digitraffic.fi/api/weather/v1/stations/{id}/data
Purpose: Central location for all constants, API endpoints, and sensor metadata.
Key Constants:
DOMAIN = "digitraffic"
PLATFORMS = ["sensor"]
CONF_STATION_ID = "station_id"
UPDATE_INTERVAL_MINUTES = 5
# API Endpoints
API_ENDPOINT_STATIONS = "https://tie.digitraffic.fi/api/weather/v1/stations"
API_ENDPOINT_STATION_DATA = "https://tie.digitraffic.fi/api/weather/v1/stations/{}/data"
# API Headers
API_USER_AGENT = "Home Assistant github.com/taskinen/digitraffic_hacs"SENSOR_MAP Structure: Massive dictionary (200+ sensors) mapping sensor keys to metadata:
SENSOR_MAP = {
"ILMA": {
"name": "Ilman lämpötila n. 4 metrin korkeudelta",
"unit": "°C",
"icon": "mdi:thermometer",
"device_class": "temperature", # Optional: HA device class
"state_class": "measurement" # Optional: HA state class
},
"KELI_1": {
"name": "Keliluokka 1",
"icon": "mdi:road",
"translate": True # NEW: Mark sensor for translation
},
# ... 200+ more sensors
}Sensor Categories:
- Air temperature (ILMA, ILMA_DERIVAATTA, etc.)
- Road surface temperature (TIE_1, TIE_2, etc.)
- Ground temperature (MAA_1, MAA_2, etc.)
- Wind (KESKITUULI, MAKSIMITUULI, TUULENSUUNTA)
- Precipitation (SADE, SADESUMMA, SATEEN_OLOMUOTO_PWDXX, etc.)
- Visibility (NÄKYVYYS_KM, NÄKYVYYS_M)
- Road conditions (KELI_1-4, TIENPINNAN_TILA_1-4)
- PWD (Present Weather Detector) status
- DSC (Dynamic Surface Condition) sensors
- Forecasts (ILMAN_LÄMPÖTILA_ENNUSTE, etc.)
Important: Sensors with "translate": True flag will have their numeric values translated to human-readable text.
Purpose: Creates and manages individual sensor entities.
Setup Function (async_setup_entry):
- Retrieves coordinator from hass.data
- Calls
coordinator.async_config_entry_first_refresh()to ensure initial data is loaded - Dynamic sensor discovery: Iterates through coordinator.data to discover available sensors
- Creates sensors for ALL sensor keys returned by API (not just those in SENSOR_MAP)
- Sensors not in SENSOR_MAP will use default formatting (key → "Key Name")
- Excludes metadata keys: "measuredTime", "stationName"
- Uses
entry.title(validated station name from config flow) for display - Adds all sensor entities to Home Assistant with immediate update
Key Classes:
DigitrafficWeatherSensor - Main sensor entity class
Initialization (__init__):
- Extends
CoordinatorEntityandSensorEntity - Retrieves sensor config from
SENSOR_MAP(uses empty dict if sensor not defined) - Sets sensor name, unique_id, icon, unit, device_class
- IMPORTANT: If
translate=True, setsstate_class=None(categorical data, not measurements) - Links sensor to device (weather station) via device_info
Properties:
-
native_value: Returns sensor state- If
translate=True: Callstranslate_sensor_value()to convert numeric codes to text - If
translate=False: Converts to float for numeric measurements - Returns
Nonefor invalid/non-numeric values
- If
-
available: Sensor is available if coordinator has data and sensor key exists -
extra_state_attributes: Additional sensor metadatameasured_time: Timestamp from APIraw_value: For translated sensors, preserves original numeric value
Device Info: All sensors from the same station are grouped under a single device:
{
"identifiers": {(DOMAIN, station_id)},
"name": station_name, # From config entry title
"manufacturer": "Fintraffic",
"model": "Road Weather Station",
"entry_type": "service", # Indicates this is a service/cloud integration
}Purpose: Translates numeric sensor codes to human-readable descriptions.
Added: 2026-01-02
Architecture:
SENSOR_VALUE_TRANSLATIONS = {
"SENSOR_KEY": {
numeric_code: "Human readable description",
...
},
...
}
def translate_sensor_value(sensor_key: str, value: Any) -> Any:
"""Main translation function"""Translation Categories:
-
Complete Mappings (verified from API):
-
VALLITSEVA_SÄÄ: WMO Code 4680 (0-99) - Present weather from automatic weather stations- Example: 63 → "Rain, heavy continuous"
- Example: 71 → "Snow, slight continuous"
- Source: https://codes.wmo.int/306/4680
-
SADE: Precipitation intensity (codes 0-6)- Source: API sensor ID 22
- Example: 0 → "Dry weather", 3 → "Abundant", 6 → "Abundant snow/sleet"
-
SATEEN_OLOMUOTO_PWDXX: Precipitation type from PWD sensor (codes 7-19)- Source: API sensor ID 25
- Example: 7 → "Dry weather", 10 → "Rain", 11 → "Snowfall", 19 → "Freezing rain"
-
KELI_1/2/3/4: Road condition class (codes 0-9)- Source: API sensors 27-28, 105, 115
- Example: 0 → "Sensor fault", 1 → "Dry", 3 → "Wet", 7 → "Ice", 9 → "Slushy"
-
VAROITUS_1/2/3/4: Warning levels (codes 0-4)- Source: API sensors 29-30, 106, 116, 175, 185
- Example: 0 → "OK", 1 → "Beware", 2 → "Alarm", 3 → "Frost"
-
PWD_STATUS: PWD sensor hardware status (codes 0-4)- Source: Vaisala PWD22 User Manual
- Example: 0 → "OK", 1 → "Hardware error", 3 → "Backscatter alarm", 4 → "Backscatter warning"
-
SADE_TILA: Precipitation state (codes 7-19)- Source: User observation - uses same PWD precipitation type codes as SATEEN_OLOMUOTO_PWDXX
- Example: 17 → "Graupel", 18 → "Freezing drizzle"
- Note: API has empty sensorValueDescriptions, but observed values match PWD codes
-
-
Complete Mappings (verified, simple binary):
VALOISAA: Light level binary (0: Dark, 1: Light)AURINKOUP: Sun position binary (0: Sun down, 1: Sun up)
-
Example Mappings (not verified from API - user should verify):
TIENPINNAN_TILA_1-4/OPT1/OPT2: Road surface state (0-5)- Example codes: 0: Dry, 1: Moist, 2: Wet, 3: Slush, 4: Frost, 5: Ice
- Note: These codes are inferred but not verified from API data
-
Placeholder Mappings (empty, user must fill):
- PWD state sensors:
PWD_TILA,PWD_NÄK_TILA,PWD_LÄHETTIMEN_TAKAISINSIRONNAN_MUUTOS - Station status:
ASEMAN_STATUS_1,ASEMAN_STATUS_2,ASEMAN_STATUS_OPT1,ASEMAN_STATUS_OPT2,ANTURIVIKA - DSC sensors:
DSC_STAT1,DSC_STAT2,DSC_VASTAANOTTIMEN_PUHTAUS1,DSC_VASTAANOTTIMEN_PUHTAUS2 - Optical sensors:
OPTISEN_ANTURIN_KELI1,OPTISEN_ANTURIN_KELI2,OPTISEN_ANTURIN_VAROITUS1,OPTISEN_ANTURIN_VAROITUS2 - Fiber sensors: All
KUITUVASTE_*variants - Forecast:
SATEEN_OLOMUOTO_ENNUSTE
Note: These sensors have empty dictionaries as placeholders because the API does not provide
sensorValueDescriptionsfor them and no manufacturer documentation could be found. Users should monitor actual sensor values and populate mappings based on observed codes and corresponding conditions. - PWD state sensors:
Translation Logic:
1. Check if sensor_key has a mapping in SENSOR_VALUE_TRANSLATIONS
2. If no mapping exists → return raw value
3. If mapping exists but is empty (placeholder) → return raw value
4. Try to convert value to int(float(value)) for lookup
5. If code found in mapping → return translated string
6. If code not found → return "Unknown (X)" where X is the code
7. If value is not numeric → return raw valueAdding New Translations:
To add or update translations, edit translations.py:
# Find the sensor in SENSOR_VALUE_TRANSLATIONS
"SENSOR_KEY": {
0: "Description for code 0",
1: "Description for code 1",
# Add more codes as you discover them
}Example Sensor Outputs:
Before translation:
sensor.vantaa_sateen_olomuoto: "20"
sensor.vantaa_vallitseva_saa: "63"
sensor.vantaa_keli_1: "2"
After translation:
sensor.vantaa_sateen_olomuoto: "Rain"
sensor.vantaa_vallitseva_saa: "Rain, heavy continuous"
sensor.vantaa_keli_1: "Wet"
With raw values preserved in attributes:
sensor.vantaa_sateen_olomuoto:
state: "Rain"
attributes:
raw_value: 20
measured_time: "2026-01-02T12:00:00Z"https://tie.digitraffic.fi/api/weather/v1
1. List All Stations
GET /stations
Returns: GeoJSON FeatureCollection with all weather stations
Response structure:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [lon, lat]},
"properties": {
"id": 12345,
"name": "Vantaa",
"collectionStatus": "GATHERING",
"state": "OK",
"dataUpdatedTime": "2026-01-02T12:00:00Z"
}
}
]
}2. Get Station Info
GET /stations/{id}
Returns: Single GeoJSON Feature with station metadata
3. Get Station Data (Used by Integration)
GET /stations/{id}/data
Returns: Latest sensor readings from the station
Response structure:
{
"id": 12345,
"stationId": 12345,
"stationName": "Vantaa",
"measuredTime": "2026-01-02T12:00:00Z",
"sensorValues": [
{
"id": 67890,
"roadStationId": 12345,
"name": "ILMA",
"oldName": "ilman lämpötila",
"shortName": "ilma",
"value": -5.2,
"unit": "°C",
"timeWindowStart": "2026-01-02T11:55:00Z",
"timeWindowEnd": "2026-01-02T12:00:00Z",
"measuredTime": "2026-01-02T12:00:00Z"
}
]
}- No Authentication Required: Public API
- User Identification: All requests include
Digitraffic-Userheader to identify the client - Rate Limiting: Not officially documented, but use reasonable intervals (5 minutes default)
- Timeout: 10 seconds (configured in
__init__.py) - Content-Type:
application/json - Compression: Supports gzip encoding
- Reliability: Generally stable, but implement error handling for network issues
The coordinator handles:
aiohttp.ClientError: Network/connection errorsasyncio.TimeoutError: Request timeout (10s)response.raise_for_status(): HTTP error codes (404, 500, etc.)UpdateFailed: Raised to Home Assistant when data fetch fails
- ALL_CAPS_WITH_UNDERSCORES (e.g.,
ILMA,TIE_1,KELI_2) - Numbers suffix variants (e.g.,
TIE_1,TIE_2,TIE_3,TIE_4) - Some have special suffixes:
_DERIVAATTA: Rate of change (derivative)_ENNUSTE: Forecast_OPT1,_OPT2: Optical sensors_PWDXX: Present Weather Detector
- Finnish language descriptions
- Stored in
SENSOR_MAP["name"] - Combined with station name:
"{station_name} {sensor_name}" - Example: "Vantaa Ilman lämpötila n. 4 metrin korkeudelta"
Format: digitraffic_{station_id}_{sensor_key}
Example: digitraffic_12345_ILMA
-
Find the sensor key from API response
-
Add to
SENSOR_MAPinconst.py:"NEW_SENSOR_KEY": { "name": "Finnish description", "unit": "Unit (if applicable)", # Optional "icon": "mdi:icon-name", "device_class": "temperature", # Optional, if HA has matching class "state_class": "measurement", # Optional: "measurement", "total", or None "translate": False # Set to True if sensor returns codes that need translation }
-
If sensor needs translation (returns numeric codes):
- Set
"translate": Truein SENSOR_MAP - Add mapping to
translations.py:"NEW_SENSOR_KEY": { 0: "Description for code 0", 1: "Description for code 1", # ... }
- Set
Common device classes used:
temperature: Temperature sensors (enables correct display)pressure: Atmospheric pressurehumidity: Relative humiditywind_speed: Wind sensorsprecipitation: Rain/snow amount
Full list: https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes
measurement: Instantaneous values (temperature, wind speed, etc.)total: Cumulative values (rain sum, etc.)total_increasing: Monotonically increasing totalsNone: Categorical data (road conditions, weather descriptions) - Required for translated sensors
IMPORTANT: Sensors with translate=True MUST have state_class=None because translated text values are categorical, not numeric measurements.
Always use this pattern for API calls:
try:
async with async_timeout.timeout(10):
response = await session.get(
url,
headers={"Digitraffic-User": API_USER_AGENT}
)
response.raise_for_status()
data = await response.json()
# Process data
return processed_data
except aiohttp.ClientError as err:
_LOGGER.error("Error message: %s", err)
raise UpdateFailed(f"Error: {err}") from err
except asyncio.TimeoutError as err:
_LOGGER.error("Timeout message")
raise UpdateFailed("Timeout") from err
except Exception as err:
_LOGGER.exception("Unexpected error")
raise UpdateFailed(f"Unexpected: {err}") from errUse appropriate log levels:
_LOGGER.debug(): Detailed information, API responses, validation details_LOGGER.info(): Important events, successful operations_LOGGER.warning(): Unexpected but handled situations_LOGGER.error(): Errors that affect functionality_LOGGER.exception(): Errors with full stack trace
- Edit
const.py: UpdateAPI_ENDPOINT_*constants - Test with a real station ID to verify response format
- Update data parsing in
__init__.pyif response structure changed
- Edit
const.py: ChangeUPDATE_INTERVAL_MINUTES - Restart Home Assistant or reload integration
Currently supports road weather stations. To add marine or rail stations:
- Create new constant for API endpoint
- Might need separate sensor platform or entity types
- Consider creating separate integration vs. expanding this one
Enable debug logging in Home Assistant:
# configuration.yaml
logger:
default: info
logs:
custom_components.digitraffic: debugCheck logs: Settings → System → Logs → Filter by "digitraffic"
- Edit
translations.pyto add/modify mappings - Reload integration: Developer Tools → YAML → Reload "Template entities" or restart HA
- Check sensor states update to show new translations
- Verify
raw_valueattribute still shows original numeric code
The repository uses GitHub Actions for automated testing and release management.
Workflow Files:
.github/workflows/ci.yml- Continuous Integration.github/workflows/release.yml- Release Management
Triggers: Every push and pull request to any branch
What it does:
- Validates Python syntax for all
.pyfiles usingpython -m py_compile - Validates
manifest.jsonas valid JSON - Validates
hacs.jsonas valid JSON - Runs in ~10-15 seconds
Purpose: Catch syntax errors early before they're merged. When branch protection is enabled, this prevents broken code from being committed.
Viewing Results:
- Go to the "Actions" tab in GitHub
- Click on the latest workflow run
- View the output of each validation step
Trigger: Manual dispatch only (Actions → Release → Run workflow)
What it does:
- Determines the next version number (auto-increment or manual)
- Updates
manifest.jsonwith the new version - Generates release notes from commit history (filtered by commit convention, see below)
- Commits the manifest.json change (as
chore: bump version to X.Y.Z) - Creates a git tag (format:
vX.Y.Z) - Creates a GitHub release
- HACS users see the new version available
Release Notes Filtering:
Auto-generated release notes exclude commits with these Conventional Commits prefixes:
| Prefix | Use for | Example |
|---|---|---|
ci: |
CI/CD workflow changes | ci: add release workflow |
docs: |
Documentation only | docs: update CLAUDE.md |
chore: |
Maintenance, dependencies | chore: add .gitignore |
style: |
Formatting, cosmetic | style: fix indentation |
refactor: |
Code restructuring | refactor: extract helper |
test: |
Adding or updating tests | test: add sensor tests |
build: |
Build system changes | build: update dependencies |
Commits without a prefix or with feat:/fix: are included in release notes.
The workflow's own version bump commit uses chore: prefix so it is automatically excluded.
Version Management:
The workflow uses semantic versioning (X.Y.Z format) and stores versions as git tags:
- Source of truth: Git tags matching
v*.*.*pattern - Default behavior: Auto-increment minor version (1.0.0 → 1.1.0 → 1.2.0)
- Manual override: You can specify any version number
- First release: Will be
v1.0.0(existing0.0.1tag is ignored)
Workflow Inputs:
-
Version (optional):
- Leave empty for auto-increment
- Or enter version number (e.g.,
2.0.0orv2.0.0) - Format must be
X.Y.Z(three numbers separated by dots)
-
Release Notes (optional):
- Leave empty for auto-generated from commits since last release
- Or enter custom release notes
-
Prerelease (checkbox):
- Check to mark as pre-release
- HACS won't auto-install pre-releases
Step-by-step:
- Go to your repository on GitHub
- Click "Actions" tab
- Click "Release" in the left sidebar
- Click "Run workflow" button (top right)
- Fill in the inputs (or leave empty for auto-increment):
- Version: [empty] or
1.0.0 - Release notes: [empty] or custom text
- Prerelease: unchecked (unless testing)
- Version: [empty] or
- Click "Run workflow"
- Wait ~30 seconds for workflow to complete
- Verify the release at:
https://github.com/taskinen/digitraffic_hacs/releases
What happens:
- Tag created:
vX.Y.Z - GitHub release created with release notes
manifest.jsonupdated and committed- HACS shows the new version to users
Example 1: First Release (Auto-increment)
Inputs:
Version: [empty]
Release notes: [empty]
Prerelease: unchecked
Result: v1.0.0 created
Release notes: Auto-generated from all commits
Example 2: Next Release (Auto-increment)
Current version: v1.0.0
Inputs:
Version: [empty]
Release notes: [empty]
Prerelease: unchecked
Result: v1.1.0 created
Release notes: Commits since v1.0.0
Example 3: Major Release (Manual)
Current version: v1.5.0
Inputs:
Version: 2.0.0
Release notes: "Major update with breaking changes"
Prerelease: unchecked
Result: v2.0.0 created
Next auto-increment will be v2.1.0
Example 4: Pre-release
Inputs:
Version: 1.2.0-beta
Release notes: [empty]
Prerelease: checked
Result: v1.2.0-beta created (marked as pre-release)
HACS won't auto-install this version
To see all releases:
# List all version tags
git tag -l 'v*.*.*'
# View specific release
git show v1.0.0
# Compare releases
git diff v1.0.0...v1.1.0Error: "Tag already exists"
- You're trying to create a version that already exists
- Check existing tags:
git tag -l 'v*.*.*' - Use a different version number
Error: "Invalid version format"
- Version must be
X.Y.Zformat (three numbers) - Examples:
1.0.0,2.5.3(not1.0,v1.0.0,1.0.0-rc1) - Pre-release versions like
1.0.0-betaare allowed
Workflow failed during commit
- Check GitHub Actions logs for details
- May need to fix merge conflicts manually
- Tag and release will NOT be created if commit fails
Want to undo a release:
- Delete the GitHub release (go to Releases → Delete)
- Delete the tag:
git tag -d vX.Y.Z git push origin :refs/tags/vX.Y.Z
- Revert the manifest.json commit:
git revert <commit-hash> git push origin main
How HACS uses releases:
- HACS reads GitHub releases (not tags alone)
- Version displayed in HACS UI comes from tag name (e.g.,
v1.0.0shows as1.0.0) - Users can see available versions and release notes
- Updates notify users when new versions are available
What users see:
Digitraffic
Current version: 1.0.0
Available version: 1.1.0
Release notes:
- Fix temperature sensor translation
- Add support for new weather codes
- Update API headers
Without releases (before CI/CD):
Digitraffic
Current version: abc1234 (commit hash)
Available version: def5678 (commit hash)
- Translation mappings incomplete: Many sensors have empty placeholder dictionaries in
translations.py. User must observe sensor values and fill in mappings based on real-world correlation with weather conditions. - No multi-language support: All sensor names and translations are in Finnish. Could add i18n support in future.
- No historical data: Only fetches latest readings, no history or graphs beyond HA's built-in recorder.
- Public API only: No authentication = can't access restricted data if it exists
- 5-minute updates: Faster updates would hit API more frequently (not recommended)
- Finnish stations only: Digitraffic is Finland-specific
- Read-only: No ability to control or configure stations via API
- Install integration via config flow
- Verify station search works
- Check that sensors are created (should be 50-100+ sensors depending on station)
- Verify sensor values update every 5 minutes
- Check translated sensors show text, not numbers
- Verify raw_value attribute exists on translated sensors
- Test removing and re-adding integration
- Verify unique_id prevents duplicate station setup
Some known station IDs for testing:
- Check
/api/weather/v1/stationsfor current list - Look for stations with
"state": "OK"and"collectionStatus": "GATHERING"
# Syntax check all Python files
python3 -m py_compile custom_components/digitraffic/*.py
# Check manifest
python3 -c "import json; json.load(open('custom_components/digitraffic/manifest.json'))"-
Translation improvements:
- Complete all sensor code mappings
- Add English translations
- User-customizable mappings via config flow
-
Additional data:
- Road weather forecasts (already in API, not fully utilized)
- Weather warnings and alerts
- Road condition cameras (separate API endpoint)
-
Better organization:
- Sensor grouping/categorization
- Hide sensors user doesn't want
- Custom sensor names via UI
-
Automation helpers:
- Binary sensors for road conditions (is_icy, is_snowing, etc.)
- Template sensors for common use cases
- Blueprints for common automations
-
Performance:
- Selective sensor updates (not all sensors every time)
- Conditional polling based on time of day
- Caching strategy for rarely-changing metadata
- Digitraffic Home: https://www.digitraffic.fi/en/
- Road Traffic API Docs: https://www.digitraffic.fi/en/road-traffic/
- API Swagger UI: https://tie.digitraffic.fi/swagger/
- WMO Code 4680: https://codes.wmo.int/306/4680 (Present weather codes)
- WMO Code Descriptions: https://artefacts.ceda.ac.uk/badc_datadocs/surface/code.html
- Vaisala PWD Sensors: https://www.vaisala.com/en/products/weather-environmental-sensors/present-weather-detectors-visbility-sensors-pwd-series
- Integration Development: https://developers.home-assistant.io/docs/creating_integration_manifest
- Sensor Platform: https://developers.home-assistant.io/docs/core/entity/sensor
- Config Flow: https://developers.home-assistant.io/docs/config_entries_config_flow_handler
- Data Update Coordinator: https://developers.home-assistant.io/docs/integration_fetching_data
- Main Repo: https://github.com/taskinen/digitraffic_hacs
- Issues: https://github.com/taskinen/digitraffic_hacs/issues
Added:
- Conventional Commits-style prefix convention for excluding internal commits from release notes
- Release workflow filters out commits prefixed with
ci:,docs:,chore:,style:,refactor:,test:,build: - Workflow's own version bump commit now uses
chore:prefix
Modified:
.github/workflows/release.yml: Updated release notes generation withgrep -vEfilter andchore:prefix on version bump commitCLAUDE.md: Added "Release Notes Filtering" section and commit message convention
Purpose: Auto-generated release notes now only include user-facing changes (features and fixes), excluding CI, docs, and maintenance commits.
Added:
-
.github/workflows/ci.yml: Continuous Integration workflow- Automatic Python syntax validation on every push and pull request
- Validates all
.pyfiles usingpython -m py_compile - Validates
manifest.jsonandhacs.jsonas valid JSON - Runs in ~10-15 seconds
-
.github/workflows/release.yml: Release automation workflow- Manual trigger for creating releases
- Auto-increment minor version by default (1.0.0 → 1.1.0 → 1.2.0)
- Manual version override option
- Auto-generated release notes from commit history
- Updates
manifest.jsonversion field automatically - Creates GitHub releases for HACS compatibility
- Workflow inputs: version (optional), release_notes (optional), prerelease (boolean)
Documentation:
- Added comprehensive "CI/CD and Release Management" section to CLAUDE.md
- Documented version management strategy (git tags as source of truth)
- Step-by-step release creation guide
- Troubleshooting section for common release issues
- HACS integration explanation
Version Management:
- Git tags matching
v*.*.*are the source of truth for versions - First release will be
v1.0.0(existing0.0.1tag is ignored) - Semantic versioning enforced (X.Y.Z format)
Purpose: Enables professional release management with clean version numbers in HACS UI. Users will see versions like "1.0.0" and "1.1.0" instead of commit hashes, with proper release notes for each update.
Updated:
translations.py: Corrected sensor value mappings using official API data, Vaisala documentation, and user observations- SADE: Fixed codes (now 0-6 instead of 0-1) - Added 5 additional precipitation intensity levels
- SATEEN_OLOMUOTO_PWDXX: Replaced incorrect codes with API codes 7-19 (was using codes 0, 10, 20, 30...)
- SADE_TILA: Corrected from binary (0-1) to PWD precipitation type codes (7-19) based on user observations
- KELI_1/2/3/4: Corrected all codes (0-9) to match API definitions - Code 0 now correctly shows "Sensor fault" instead of "Dry"
- VAROITUS_1/2/3/4: Added missing mappings (codes 0-4) for warning levels
- PWD_STATUS: Added hardware status codes (0-4) from Vaisala PWD22 User Manual
- All translations now use English descriptions with Finnish originals preserved in comments
Sources:
/api/weather/v1/sensorsendpoint -sensorValueDescriptionsfield- Vaisala PWD22 User Manual - Hardware status and diagnostic codes
- User observations of actual sensor values in production
Purpose: Ensures sensor value translations match the official Digitraffic API definitions and manufacturer documentation, providing accurate road condition, weather status, and sensor diagnostics displays. This fixes incorrect mappings that were based on assumptions rather than verified data.
Sensors Still Without Documentation:
The following sensors have empty sensorValueDescriptions in the API and no available manufacturer documentation:
- PWD_TILA, PWD_NÄK_TILA, PWD_LÄHETTIMEN_TAKAISINSIRONNAN_MUUTOS
- ASEMAN_STATUS_1/2/OPT1/OPT2, ANTURIVIKA
- DSC_STAT1/2, DSC_VASTAANOTTIMEN_PUHTAUS1/2
- OPTISEN_ANTURIN_KELI1/2, OPTISEN_ANTURIN_VAROITUS1/2
- KUITUVASTE_* (all fiber sensor variants)
- TIENPINNAN_TILA_* (all road surface state variants - have example mappings but not API-verified)
- SATEEN_OLOMUOTO_ENNUSTE
Users should monitor actual sensor values in Home Assistant and populate these mappings based on observed codes and corresponding conditions.
How to find API mappings in the future:
- Access
https://tie.digitraffic.fi/api/weather/v1/sensors - Search for sensor by name or ID
- Look for
sensorValueDescriptionsarray containing code-to-description mappings - For sensors without API mappings, consult manufacturer documentation (Vaisala PWD, DSC, etc.)
- Note that not all sensors have value descriptions available - those remain as empty placeholders for user observation
Improved:
- sensor.py section: Added detailed
async_setup_entrydocumentation - Device Info section: Added
entry_type: "service"field documentation - Sensor discovery: Documented dynamic sensor creation for all API-returned sensors
- Translations section: More accurate placeholder sensor listings
- Added prominent Claude Code update checklist at top of file
Purpose: Ensured CLAUDE.md accurately reflects current implementation details that were previously undocumented or incomplete.
Added:
API_USER_AGENTconstant inconst.pyDigitraffic-Userheader to all API requests
Modified:
__init__.py: Added header to coordinator API requestsconfig_flow.py: Added header to station fetch and validation requests
Purpose: Properly identifies the integration to Digitraffic API as requested by API guidelines. The header value is "Home Assistant github.com/taskinen/digitraffic_hacs".
Added:
translations.pymodule with translation mappings- Complete WMO 4680 weather code mappings (0-99)
- Example mappings for Finnish road condition codes
translate_sensor_value()functiontranslateflag support in SENSOR_MAP- Raw value preservation in sensor attributes
- State class handling for categorical vs. measurement sensors
Modified:
sensor.py: Added translation logic tonative_value, conditionalstate_class, raw value attributesconst.py: Addedtranslate: Trueflag to 40+ sensors
Purpose: Converts cryptic numeric sensor codes to human-readable descriptions (e.g., "63" → "Rain, heavy continuous")
When to update this file:
- Architecture changes: New modules, changed data flows, modified patterns
- New features: Translation system, forecasting, automations, etc.
- API changes: Endpoint updates, response format changes, new error handling
- Configuration changes: New constants, modified defaults, changed behavior
- Bug fixes with architectural impact: Workarounds that change patterns
- Deprecations: Removed features, changed recommendations
What to update:
- Add entries to Changelog section with date and description
- Update relevant sections (Architecture, File Purposes, Common Tasks, etc.)
- Update Last Updated date at the top
- Add new examples if patterns change
- Update Known Issues if bugs are fixed or new ones discovered
Update workflow:
- Make code changes
- Update CLAUDE.md BEFORE committing
- Commit both code and documentation together
Commit message convention:
Use Conventional Commits prefixes for internal commits that should be excluded from release notes (see "Release Notes Filtering" above). Feature and fix commits should either use feat:/fix: prefix or no prefix at all.
# Included in release notes:
Add sensor grouping feature
feat: add sensor grouping feature
fix: handle timeout in coordinator
# Excluded from release notes:
docs: update CLAUDE.md
ci: add release workflow
chore: add .gitignore
- Use Markdown
- Keep sections in current order for consistency
- Use code blocks with language hints (python, json, yaml, bash)
- Include examples for complex concepts
- Link to external resources when helpful
- Keep line length reasonable (80-120 chars) for readability
Remember: A well-maintained CLAUDE.md makes future development easier for everyone (including AI assistants like me!). Treat it as living documentation that evolves with the codebase.