Home Assistant custom integration to provide public street city parking information for any location. This custom component has been built from the ground up to fetch public parking information and integrate this information into Home Assistant. This integration is built against the public websites provided by seety.co and seety Maps. (and maybe other similar sites such as Parkopedia in future). Sensors will be created for any desired location and specific service can be called to get parking information ad hoc of any location.
This integration is in no way affiliated with seety.
Whenever you exit your car (and while not at home), check if any public city parking limitations apply for your current location. Warn you when you need to place your parking disk or show local parking rates.
To detect exiting a car, an automation can be defined using sensor.smartphone_ha_activity changing from 'Automotive', or an iOS shortcut can be used to trigger when CarPlay is disconnected and a webhook request can be launched to Home Assistant to trigger an action.
- HACS: search for CityParking in the default HACS repo list or use below button to navigate directly to it on your local system and install via HACS.
- Restart Home Assistant
- Add 'City Parking' integration via HA Settings > 'Devices and Services' > 'Integrations'
- In the setup configuration, provide an origin.
-
This can be any HA sensor which has latitutde and longitude attributes (eg
person.jef,device_tracker.car, etc).You can also provide latitude and longitude information, eg
51.3304,3.802.You can also just provide the full address (but I noticed the current pywaze convertion from address to lat/lon is not very accurate).
-
-
sensor.parking_[origin]_address: sensor with adres linked to location oforigin -
sensor.parking_[origin]_days_restrictions: sensor with indication of days on which the city parking is restricted -
sensor.parking_[origin]_max_stay: sensor with max amount of minutes is allowed to park during the days and time restricted schedule -
sensor.parking_[origin]_price: sensor with price info for the city parking -
sensor.parking_[origin]_remarks: sensor with remarks related to the the city parking -
sensor.parking_[origin]_restriction_active: sensor with indication if the time and day restrictions are currenlty active. Eg if Sunday the city parking is not restricted, the restricted_active sensor will be False -
sensor.parking_[origin]_time_restrictions: sensor with indication of time schedule duding which the city parking is restricted -
sensor.parking_[origin]_type: sensor with type of city parking zone (eg disk, paid, free, etc) -
sensor.parking_[origin]_zone: sensor with zone name of the city parking (eg green, yellow, orange, red, blue, etc) -
Sensor data will be updated every 5min, unless the coordinates of the origin didn't change. The attribute
time_restriction_active_now,day_restriction_active_now,maxstay_*andrestriction_activewill always be updated every 5min. These indicate if the restrictions currently apply. -
For now all sensors have the same set of attributes
Attribute Description State zone originOriginal origin provided during setup of the sensor latitudeLatitude of the origin longitudeLongitude of the origin urlSeety.co url to the addresss typeType of the public parking, eg paid time_restrictionsTime restrictions for the public parking days_restrictionsDays at which the public parking is limited pricesPrice indication for 1 or 2 hours parking and amount of free parking allowed remarkdsExtra info related to the public parking max_stayMax time you can stay at the public parking zoneName of the zone, blue/orange/red zone indication of public parking addressAddress for which the parking information is shown time_restriction_active_nowTime restrictions are currently active day_restriction_active_nowDay restrictions are currently active maxstay_passed_nowMax stay has passed maxstay_elapsedTime (min) elapsed since max stay started maxstay_remainingTime (min) remaining until max stay is reached maxstay_start_timeTime at which max stay started restriction_activeTime and day restrictions are currently active last_updateLast time data was updated last_restriction_checkLast time restrictions were checked attributionAttribution for the data device_classDevice class iconIcon to display friendly_nameFriendly name for the sensor
-
Get notified when you stopped driving about public city parking restrictions that may apply:
-
Example automation script
alias: Parking Notification description: "" triggers: - trigger: state entity_id: - sensor.smartphone_ha_activity from: - Automotive for: hours: 0 minutes: 0 seconds: 30 - trigger: webhook allowed_methods: - POST - PUT local_only: true webhook_id: "cityparking" conditions: - condition: not conditions: - condition: zone entity_id: person.jef zone: zone.home actions: - action: script.parking_notification metadata: {} enabled: true mode: single
-
Example
parking_notificationscript. Generic script with actionable notificationalias: Parking Notification description: "Interactive parking notification, if 'source_sensor' var is set, the parking info of that sensor will be used, else the parking info of person.name will be fetched." icon: mdi:parking sequence: - if: - condition: template value_template: "{{ source_sensor != unavailable}}" then: - variables: extra_data: zone: "{{state_attr(source_sensor, 'zone')}}" type: "{{state_attr(source_sensor, 'type')}}" restriction_active: "{{state_attr(source_sensor, 'restriction_active')}}" address: "{{state_attr(source_sensor, 'address')}}" days_restrictions: "{{state_attr(source_sensor, 'days_restrictions')}}" time_restrictions: "{{state_attr(source_sensor, 'time_restrictions')}}" price: "{{state_attr(source_sensor, 'price')}}" remarks: "{{state_attr(source_sensor, 'remarks')}}" url: "{{state_attr(source_sensor, 'url')}}" else: - action: cityparking.city_parking_info metadata: {} data: origin: person.name response_variable: parking_info - variables: extra_data: zone: "{{parking_info.city_parking_info.extra_data.zone}}" type: "{{parking_info.city_parking_info.extra_data.type}}" restriction_active: "{{parking_info.city_parking_info.extra_data.restriction_active}}" address: "{{parking_info.city_parking_info.extra_data.address}}" days_restrictions: "{{parking_info.city_parking_info.extra_data.days_restrictions}}" time_restrictions: "{{parking_info.city_parking_info.extra_data.time_restrictions}}" price: "{{parking_info.city_parking_info.extra_data.price}}" remarks: "{{parking_info.city_parking_info.extra_data.remarks}}" url: "{{parking_info.city_parking_info.extra_data.url}}" - variables: critical_desired: >- {% if states('sensor.smartphone_ha_activity') == 'Automotive' or (trigger is defined and trigger.event is defined and trigger.event.data.triggerSource == 'carPlay') %}1{% else %}0{% endif %} notification_tag: parking title: >- 🅿️ {{extra_data.zone}} ({{extra_data.type}}) Active: {{extra_data.restriction_active}} message: >- {{extra_data.type}} ({{extra_data.zone}}): {{extra_data.address}} {% if extra_data.restriction_active %}⚠️{% endif %}Restricted on: {{extra_data.days_restrictions}}, between {{extra_data.time_restrictions}} Price: {{extra_data.price}} Remarks: {{extra_data.remarks}} actions_uri: - action: URI title: Map parking 🅿️ uri: "{{extra_data.url}}" activationMode: background authenticationRequired: true destructive: false behavior: default action_map_car: - action: map_car title: Map car 🗺️ activationMode: background authenticationRequired: true destructive: false behavior: default action_map_traffic: - action: map_traffic title: Map traffic 🛣️ activationMode: background authenticationRequired: true destructive: false behavior: default action_refresh_car_data: - action: refresh_car_data title: Refresh car data 🔄️ activationMode: background authenticationRequired: true destructive: false behavior: default actions_desired: >- {{actions_uri + action_map_car + action_map_traffic + action_refresh_car_data}} - choose: [] default: - continue_on_error: true data: title: "{{title}}" message: "{{message}}" data: push: sound: name: default critical: "{{critical_desired}}" url: "{{extra_data.url}}" group: "{{notification_tag}}" tag: "{{notification_tag}}" action_data: latitude: "{{state_attr('person.car','latitude')}}" longitude: "{{state_attr('person.car','longitude')}}" second_latitude: "{{extra_data.latitude}}" second_longitude: "{{extra_data.longitude}}" actions: "{{actions_desired}}" action: notify.notify - wait_for_trigger: - event_type: mobile_app_notification_action trigger: event timeout: hours: 0 minutes: 0 seconds: 30 milliseconds: 0 continue_on_timeout: true enabled: true - choose: - conditions: - condition: template value_template: "{{wait.trigger == None}}" sequence: - continue_on_error: true data: title: "{{title}}" message: "{{message}}" data: push: sound: name: default critical: "{{critical_desired}}" url: "{{extra_data.url}}" group: "{{notification_tag}}" tag: "{{notification_tag}}" action_data: latitude: "{{state_attr('person.car','latitude')}}" longitude: "{{state_attr('person.car','longitude')}}" second_latitude: "{{extra_data.latitude}}" second_longitude: "{{extra_data.longitude}}" action: notify.notify - stop: timeout - variables: option: "{{ wait.trigger.event.data.action }}" selected_entity: | {{ {'map_traffic': 'automation.traffic_notificaiton', 'map_car': 'person.car', 'refresh_car_data': 'script.refresh_car_data' }[wait.trigger.event.data.action] }} entity_type: "{{selected_entity.split('.')[0] }}" - choose: - conditions: - condition: template value_template: "{{ entity_type == 'sensor' or entity_type == 'person' }}" sequence: - data: message: >- {{option}}: {{state_attr(selected_entity,'thoroughfare')}} {{state_attr(selected_entity,'sub_thoroughfare')}}, {{state_attr(selected_entity,'locality')}} data: push: sound: name: default critical: "{{critical_desired}}" group: person tag: person action_data: latitude: "{{state_attr('person.car','latitude')}}" longitude: "{{state_attr('person.car','longitude')}}" second_latitude: "{{extra_data.latitude}}" second_longitude: "{{extra_data.longitude}}" url: /lovelace/parking action: notify.notify - conditions: - condition: template value_template: "{{ entity_type == 'light' }}" sequence: - data: {} target: entity_id: "{{selected_entity}}" action: light.toggle - conditions: - condition: template value_template: "{{ entity_type == 'switch' }}" sequence: - data: {} target: entity_id: "{{selected_entity}}" action: switch.toggle - conditions: - condition: template value_template: "{{ entity_type == 'script' }}" sequence: - data: {} target: entity_id: "{{selected_entity}}" action: script.turn_on - conditions: - condition: template value_template: "{{ entity_type == 'automation' }}" sequence: - data: skip_condition: true target: entity_id: "{{selected_entity}}" action: automation.trigger - conditions: - condition: template value_template: "{{ entity_type == 'lock' }}" sequence: - data: {} target: entity_id: "{{selected_entity}}" action: lock.lock - conditions: - condition: template value_template: "{{ entity_type == 'unlock' }}" sequence: - data: {} target: entity_id: "{{selected_entity|replace('unlock', 'lock')}}" action: lock.unlock
-
-
Find the public parking information to a given location.
-
The response will contain all available seety.co data. On top, a dict
extra_datais available which contains the most relevant data as used in the 'City Parking' sensors. -
It will return a JSON such as example below:
city_parking_info: user: user: verified: false cars: [] mustSendMailOnEachTransaction: true proAccountActivated: false subscribedToOnboardingCampaign: true time: "2026-01-28T22:03:31.214000+00:00" lastSeen: "2026-01-28T22:03:31.214000+00:00" confidence: 0 lang: en lastMapUpdate: "2024-11-20T23:00:00" remoteConfigsLastUpdate: messages: "2025-01-16" access_token: >- <token> expires_in: 10800 refresh_token: >- <token> status: OK location: status: OK results: - formatted_address: Raadhuisstraat 11, 1016 DB Amsterdam countryCode: NL geometry: location: lat: 52.37315 lng: 4.890025 types: - street_address rules: rules: days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 prices: "0": 0 "1": 1.7 "2": 3.3 hours: - "00:00" - "06:00" type: paid paymentPartner: shpv advantageInApp: false displayNotPayable: false overrides: {} forceDisplayPriceTables: false risk: 0 overrides: {} properties: type: orange-1 color: "#ff6a00" dotted: false closest: - 4.89029214636468 - 52.37323057359693 closestDist: 0.010858118135837055 maxDistToPay: 0.01 city: amsterdam twoSided: false status: OK streetComplete: rules: yellow: weight: 4.2 summary: days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 prices: "0": 0 "1": 1.7 "2": 3.3 hours: - "09:00" - "19:00" type: paid paymentPartner: shpv advantageInApp: false displayNotPayable: false overrides: {} forceDisplayPriceTables: false remarks: - "Fine: 150€." specialPermits: residents: [] disabled: [] maxStay: "600" color: color: "#ffdd00" dotted: false name: Yellow zone table: - rows: 09:00,19:00: - 0.4 - 0.9 - 1.7 - 3.4 - 5.2 - 6.9 - 8.6 - 10.3 - 10.3 cols: - "15" - "30" - "60" - "120" - "180" - "240" - "300" - "360" - "600" days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 accessHours: {} entryHours: null parkingPaymentProviders: - seety_nl - 4411_nl - driveulu_nl - ease2pay_nl - easypark_nl - lekkerparkeren_nl - mkbbrandstof_nl - parkd_nl - parkline_nl - parkmobile_nl - parksen_nl - paybyphone_nl - qpark_nl - sms_parking_nl - tanqyou_nl - yellowbrick_nl displayNotPayable: false yellow-10: weight: 4.2 summary: days: - 1 - 2 - 3 - 4 - 5 - 6 prices: "0": 0 "1": 1.2 "2": 2.5 hours: - "10:00" - "20:00" type: paid paymentPartner: shpv advantageInApp: false displayNotPayable: false overrides: {} forceDisplayPriceTables: false remarks: - "Fine: 150€." specialPermits: residents: [] disabled: [] maxStay: "600" color: color: "#ffdd00" dotted: false name: Yellow zone 10 table: - rows: 09:00,19:00: - 0.1 - 0.1 - 0.2 - 0.3 - 2 - 3.7 - 5.5 - 7.2 - 8.9 - 10.3 - 10.3 cols: - "15" - "60" - "120" - "180" - "240" - "300" - "360" - "420" - "480" - "540" - "600" days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 accessHours: {} entryHours: null parkingPaymentProviders: - seety_nl - 4411_nl - driveulu_nl - ease2pay_nl - easypark_nl - lekkerparkeren_nl - mkbbrandstof_nl - parkd_nl - parkline_nl - parkmobile_nl - parksen_nl - paybyphone_nl - qpark_nl - sms_parking_nl - tanqyou_nl - yellowbrick_nl displayNotPayable: false orange-3: weight: 5.3 summary: days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 prices: "0": 0 "1": 5.2 "2": 10.4 hours: - "00:00" - "24:00" type: paid paymentPartner: shpv advantageInApp: false displayNotPayable: false overrides: {} forceDisplayPriceTables: false remarks: - "Fine: 150€." specialPermits: residents: [] disabled: [] maxStay: "1440" color: color: "#ff6a00" dotted: false name: Orange zone 3 table: - rows: 19:00,24:00: - 0.4 - 0.9 - 1.7 - 3.4 - 5.2 - 6.8 - 10.3 - 12 - 13.6 - 18.9 - 20.4 - 27.2 - 34 - 34 cols: - "15" - "30" - "60" - "120" - "180" - "240" - "360" - "420" - "480" - "660" - "720" - "960" - "1260" - "1440" days: - 0 accessHours: {} entryHours: null - rows: 00:00,06:00: - 0.4 - 0.9 - 1.7 - 3.4 - 5.2 - 6.9 - 8.6 - 10.3 - 12 - 13.8 - 15.5 - 17.2 - 18.9 - 20.6 - 22.4 - 24.1 - 25.8 - 27.5 - 29.2 - 31 - 32.7 - 34.4 - 36.1 - 37.8 - 39.6 - 41.3 cols: - "15" - "30" - "60" - "120" - "180" - "240" - "300" - "360" - "420" - "480" - "540" - "600" - "660" - "720" - "780" - "840" - "900" - "960" - "1020" - "1080" - "1140" - "1200" - "1260" - "1320" - "1380" - "1440" days: - 1 - 2 - 3 - 4 - 5 - 6 accessHours: {} entryHours: null parkingPaymentProviders: - seety_nl - 4411_nl - driveulu_nl - ease2pay_nl - easypark_nl - lekkerparkeren_nl - mkbbrandstof_nl - parkd_nl - parkline_nl - parkmobile_nl - parksen_nl - paybyphone_nl - qpark_nl - sms_parking_nl - tanqyou_nl - yellowbrick_nl displayNotPayable: false noparking: weight: 0 summary: days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 prices: "0": 0 hours: - "00:00" - "24:00" type: noparking paymentPartner: null advantageInApp: false displayNotPayable: false overrides: {} forceDisplayPriceTables: false remarks: [] specialPermits: residents: [] disabled: [] maxStay: 0 color: color: "#000000" dotted: true name: Black dotted zone table: - rows: 00:00,24:00: [] cols: [] days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 accessHours: {} entryHours: null parkingPaymentProviders: [] displayNotPayable: false red: weight: 6.2 summary: days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 prices: "0": 0 "1": 5.2 "2": 10.4 hours: - "09:00" - "24:00" type: paid paymentPartner: shpv advantageInApp: false displayNotPayable: false overrides: {} forceDisplayPriceTables: false remarks: - "Fine: 150€." specialPermits: residents: [] disabled: [] maxStay: "600" color: color: "#ff0000" dotted: false name: Red zone table: - rows: 09:00,19:00: - 25.1 - 25.1 - 25.1 cols: - "15" - "60" - "600" days: - 1 - 2 - 3 - 4 - 5 - 6 accessHours: {} entryHours: null parkingPaymentProviders: - seety_nl - 4411_nl - driveulu_nl - ease2pay_nl - easypark_nl - lekkerparkeren_nl - mkbbrandstof_nl - parkd_nl - parkline_nl - parkmobile_nl - parksen_nl - paybyphone_nl - qpark_nl - sms_parking_nl - tanqyou_nl - yellowbrick_nl displayNotPayable: false table: - rows: 00:00,24:00: - 2 - 4 - 8.1 - 16.1 - 24.2 - 32.2 - 40.3 - 48.3 - 56.4 - 64.4 - 72.5 - 80.5 - 88.6 - 96.6 - 104.7 - 112.7 - 120.8 - 128.8 - 136.9 - 144.9 - 153 - 161 - 169.1 - 177.1 - 185.2 - 193.2 cols: - "15" - "30" - "60" - "120" - "180" - "240" - "300" - "360" - "420" - "480" - "540" - "600" - "660" - "720" - "780" - "840" - "900" - "960" - "1020" - "1080" - "1140" - "1200" - "1260" - "1320" - "1380" - "1440" days: - 0 - 1 - 2 - 3 - 4 - 5 - 6 accessHours: {} entryHours: null maxStay: "1440" remarks: - "Fine: 150€." specialPermits: residents: [] disabled: [] providers: - descriptionApp: null descriptionSMS: null fees: registration: fixed: 0 session: comment: null fixed: 0.35 percentage: null sessionSubscription: null notifSms: comment: null fixed: 0.15 percentage: null notifApp: null advantageApp: fr: - >- Il n'est pas nécessaire de sélectionner une durée spécifique (start & stop) - Disponible dans plus de 150 villes belges - Inscription plutôt facile en: - Not necessary to select a specific duration (start & stop) - Available in more than 60 Belgian cities - Registration rather easy nl: - >- Het is niet nodig om een specifieke duur te selecteren (start & stop) - Beschikbaar in meer dan 60 Belgische steden - Inschrijving eerder eenvoudig disadvantageApp: fr: - Relativement cher - >- Dans certains cas, il faut se rendre à l'horodateur pour avoir le code de la zone - Attention aux notifications payantes - Inscription obligatoire avant de découvrir l'app - Nombre de parkings publics limité en: - Relatively expensive - >- In some cases, you have to go to the parcmeter to get the code of the zone - Beware of paid notifications - Registration required before discovering the app - Limited number of public parkings nl: - Relatief duur - >- In sommige gevallen moet u naar de parkeermeter gaan om de code voor de zone te krijgen - Pas op voor meldingen die betalend zijn - Inschrijving vereist voor het ontdekken van de app - Beperkt aantal openbare parkings advantageSms: fr: [] en: [] nl: [] disadvantageSms: fr: [] en: [] nl: [] name: "4411" intName: 4411_nl rating: 4 logo: >- https://storage.googleapis.com/cpark-static-images/mobility-providers/4411.png subscriptions: [] url: www.4411.io transactionPrice: null notificationPrice: "0" registrationFees: "0" subscriptionPrice: "0" subscriptionType: null - descriptionApp: null descriptionSMS: null fees: registration: fixed: 0 session: comment: fr: Hors TVA en: Exclusive of VAT nl: Exclusief BTW fixed: 0.3 percentage: null sessionSubscription: comment: null fixed: 0 percentage: null notifSms: comment: null fixed: 0.25 percentage: null notifApp: null advantageApp: fr: - >- Inclus un système de navigation (mais très limité par rapport à Google maps ou Waze) en: [] nl: [] disadvantageApp: fr: - Inscription obligatoire avant de découvrir l'app - >- Obligation d'avoir une plaque de voiture valide pour accéder à l'application - Relativement cher - Peu d'explications sur le fonctionnement de la carte - Le design et l'expérience utilisateur pourraient être amélioré en: [] nl: [] advantageSms: fr: [] en: [] nl: [] disadvantageSms: fr: [] en: [] nl: [] name: Drive ULU intName: driveulu_nl rating: 4 logo: >- https://storage.googleapis.com/cpark-static-images/mobility-providers/drive-ulu.jpg subscriptions: [] url: www.driveulu.com transactionPrice: null notificationPrice: "0" registrationFees: "0" subscriptionPrice: null subscriptionType: null - descriptionApp: null descriptionSMS: null fees: registration: fixed: 0 session: comment: null fixed: 0.19 percentage: null sessionSubscription: comment: null fixed: 0 percentage: null notifSms: comment: fr: Commentaire en FR en: Commentaire en EN nl: Commentaire en NL fixed: 0 percentage: null notifApp: null advantageApp: fr: - Disponible dans plus de 140 villes aux Pays-Bas - Frais de transaction raisonnable si vous rechargez du crédit - >- Possibilité de payer son parking sans devoir créer de compte (mais dans ce cas les frais de transactions sont beaucoup plus chers (0,35€) en: [] nl: [] disadvantageApp: fr: - Application peu intuitive - >- Si vous n'utilisez par leur système de crédit, les frais de transactions sont très chers (0,25€ avec iDEAL et 0,35€ avec une carte de crédit) - >- Vous devez définir à l'avance combien de temps vous voulez rester stationné - >- Pas d'informations dans les zones où le paiement du parking n'est pas disponible en: [] nl: [] advantageSms: fr: [] en: [] nl: [] disadvantageSms: fr: [] en: [] nl: [] name: Easy2pay intName: ease2pay_nl rating: 4 logo: >- https://storage.googleapis.com/cpark-static-images/mobility-providers/ease2pay.png subscriptions: - period: 7 price: 0.49 - period: 30 price: 1.49 - period: 365 price: 14.99 url: http://www.ease2pay.nl/ transactionPrice: null notificationPrice: "0" registrationFees: "0" subscriptionPrice: null subscriptionType: null - descriptionApp: null descriptionSMS: null fees: registration: fixed: 0 session: comment: fr: Min. 29cts. en: Min. 29cts. nl: Min. 29cts. fixed: null percentage: 15 sessionSubscription: null notifSms: null notifApp: null advantageApp: fr: - Choix de la zone relativement aisé - Inscription relativement facile - Possibilité de payer son stationnement dans des parking publics en: [] nl: [] disadvantageApp: fr: - Une des applications la plus chère du marché - Attention aux notifications payantes - Obligé de choisir une durée de stationnement prédéfinie - Inscription obligatoire avant de découvrir l'app en: [] nl: [] advantageSms: fr: [] en: [] nl: [] disadvantageSms: fr: [] en: [] nl: [] name: EasyPark intName: easypark_nl rating: 4 logo: >- https://storage.googleapis.com/cpark-static-images/mobility-providers/easypark.png subscriptions: - period: 30 price: 1.99 url: www.easyparknederland.nl transactionPrice: null notificationPrice: "0" registrationFees: "0" subscriptionPrice: null subscriptionType: null - descriptionApp: null descriptionSMS: null fees: registration: fixed: 0 session: comment: null fixed: 0.22 percentage: null sessionSubscription: comment: null fixed: 0 percentage: null notifSms: null notifApp: null advantageApp: fr: - >- Notifications gratuites pour vous rappelez qu'une session est en cours - Vous pouvez ajouter autant de plaque que vous le désirez - Disponible dans plus de 100 villes aux Pays-bas en: [] nl: [] disadvantageApp: fr: - Frais de transaction relativement cher - Le design et l'expérience utilisateur pourraient être amélioré - Application uniquement disponible aux Pays-Bas - Inscription obligatoire afin de découvrir l'app en: [] nl: [] advantageSms: fr: [] en: [] nl: [] disadvantageSms: fr: [] en: [] nl: [] name: LekkerParkeren intName: lekkerparkeren_nl rating: 4 logo: >- https://storage.googleapis.com/cpark-static-images/mobility-providers/lekker-parkeren.png subscriptions: - period: 30 price: 1.99 url: http://www.lekkerparkeren.nl/ transactionPrice: null notificationPrice: "0" registrationFees: "0" subscriptionPrice: null subscriptionType: null - descriptionApp: fr: "<div class=\"prices\">\n <h3>Tarifs</h3>\n <ul>\n \t<li>Frais de transaction de 0.15€ (les moins chers)</li>\n\t<li>Frais d'activation : 0€</li>\n\t<li>Frais de notification dans l'app : gratuit </li>\n\t<li>Moyens de paiements acceptés (Carte de crédit, Domiciliation, Apple et Google Pay)</li>\n</ul></div>" en: "<div class=\"prices\">\n <h3>Rates</h3>\n <ul>\n \t<li>Transaction fee of 0.15€ (least expensive)</li>\n\t<li>Activation fee: 0€</li>\n\t<li>Notification fee in the app: free</li>\n\t<li>Accepted payment methods (Credit Card, domiciliation, Apple and Google Pay)</li>\n</ul></div>" nl: "<div class=\"prices\">\n <h3>Tarieven</h3>\n <ul>\n \t<li>Transactiekosten van 0.15€ (goedkoopste)</li>\n\t<li>Activeringskosten: 0€</li>\n\t<li>Notificatiekost in de app: gratis</li>\n\t<li>Betaalmiddelen (kredietkaart, domiciliering, Apple en Google Pay)</li>\n</ul></div>" descriptionSMS: null fees: registration: fixed: 0 session: comment: null fixed: 0.19 percentage: null sessionSubscription: null notifSms: null notifApp: null advantageApp: fr: - >- L'app vous aide à trouver les zones de stationnement gratuites ou les moins chères - Seety est l'app la moins chère pour payer son parking au Pays-Bas - Frais de transaction les plus bas du marché - L'app la plus intuitive (inscription rapide, facile et sécurisée) - Propose automatiquement la zone la plus proche - >- Il n'est pas nécessaire de sélectionner une durée spécifique (start & stop) - >- Notifications intelligentes gratuites pour éviter les mauvaises surprises - Recevez gratuitement une facture mensuelle pour les professionnels - >- Possibilité de réserver un grand nombre de parkings publics via l'app - Disponible partout aux Pays-Bas et en Belgique - Support client 5 étoiles en: [] nl: [] disadvantageApp: fr: - Payement du parking en rue pas encore disponible en France en: [] nl: [] advantageSms: fr: [] en: [] nl: [] disadvantageSms: fr: [] en: [] nl: [] name: Seety intName: seety_nl rating: 4.9 logo: https://storage.googleapis.com/cpark-static-images/seety.png subscriptions: [] url: https://seety.page.link/Kdp9 transactionPrice: "0.15" notificationPrice: "0" registrationFees: "0" subscriptionPrice: null subscriptionType: null - descriptionApp: null descriptionSMS: null fees: registration: fixed: 5 session: comment: null fixed: 0.34 percentage: null sessionSubscription: comment: fr: Abonnement flex. Min 0,15€, max 0,50€. en: Flex subscription. Min 0,15€, max 0,50€. nl: Flex abonnement. Min 0,15€, max 0,50€. fixed: 0.15 percentage: null notifSms: comment: null fixed: 0.35 percentage: null notifApp: null advantageApp: fr: - Possibilité d'ajouter certaines zones en favoris - Présentation des différents horodateurs à proximité en: [] nl: [] disadvantageApp: fr: - >- Vous devez payer 2,5€ chaque fois que vous voulez rajouter une plaque d'immatriculation - Une des applications la plus chère du marché - Inscription obligatoire avant de découvrir l'app - Uniquement disponible pour le parking en rue - Inscription relativement longue en: [] nl: [] advantageSms: fr: [] en: [] nl: [] disadvantageSms: fr: [] en: [] nl: [] name: Yellowbrick intName: yellowbrick_nl rating: 4 logo: >- https://storage.googleapis.com/cpark-static-images/mobility-providers/yellowbrick.png subscriptions: - period: 7 price: 0.75 url: https://www.yellowbrick.nl/ transactionPrice: null notificationPrice: "0" registrationFees: "0" subscriptionPrice: null subscriptionType: null city: fr: Amsterdam en: Amsterdam nl: Amsterdam cityName: Amsterdam status: OK origin: zone.home origin_coordinates: lat: 52.3731339 lon: 4.8903147 bounds: {} extra_data: origin: zone.home latitude: 52.3731339 longitude: 4.8903147 type: paid time_restrictions: - "00:00" - "06:00" days_restrictions: 7d/7 prices: 1.7€ (1h) - 3.3€ (2h) remarks: "Fine: 150€." maxStay: 24h zone: orange 🟠 address: Raadhuisstraat 11, 1016 DB Amsterdam, NL url: https://map.seety.co/Raadhuisstraat 11, 1016 DB Amsterdam, NL/16?lang=en type_src: "paid" time_restrictions_src: ["00:00", "06:00"] days_restrictions_src: [0,1,2,3,4,5,6] price_src: {1: 1,7, 2: 3.3} remarks_src: ["Fine: 150€"] max_stay_src: 1440 zone_src: orange-2 address_src: Raadhuisstraat 11, 1016 DB Amsterdam time_restriction_active_now: false day_restriction_active_now: false maxstay_passed_now: false maxstay_elapsed: 0 maxstay_remaining: 0 maxstay_start_time: "2026-02-08T12:54:59.578763+01:00" restriction_active: false last_update: "2026-02-08T12:54:59.578763+01:00" last_restriction_check: "2026-02-08T12:54:59.578770+01:00"
Markdown card. Below example has a condition to only be visible is some parking restiction would apply.
Replace sensor.parking_person_car_restriction_active with the name of your own parking sensor.
Translation of type is optional.
type: markdown
content: >
{% set source_sensor = 'sensor.parking_person_car_restriction_active' %}
{% set zone = state_attr(source_sensor, 'zone') %}
{% set type = state_attr(source_sensor, 'type') %}
{% set restriction_active = state_attr(source_sensor, 'restriction_active') %}
{% set address = state_attr(source_sensor, 'address') %}
{% set days_restrictions = state_attr(source_sensor, 'days_restrictions') %}
{% set time_restrictions = state_attr(source_sensor, 'time_restrictions') %}
{% set price = state_attr(source_sensor, 'price') %}
{% set remarks = state_attr(source_sensor, 'remarks_src') | list %}
{% set url = state_attr(source_sensor, 'url') %}
{% set translations = {
'free': 'Gratis',
'paid': 'Betalend',
'disc': 'Blauwe schijf',
'Unknown': ''
} %}
<a href='{{ url }}'>🅿️ {{zone}}: {{translations.get(type, '')}}</a>
🚘 {{address}}
{% if restriction_active == 'True' %}⚠️ {% endif %}Restricted on: {{days_restrictions}},
between {{time_restrictions}}
{% if price %}💶 Price: {{price}}{% endif %}
{% if remarks %} <details><summary><b>Remarks:</b></summary>
{% for remark in remarks %}
- {{ remark }} {% endfor %}
</details> {% endif %}
visibility:
- condition: state
entity: sensor.parking_person_car_restriction_active
state: "True"
Proof of concept status, still validating and extending functionalities. Issues section in GitHub.
The main logic and API connection related code can be found within source code CityParking/custom_components/cityparking:
All other files just contain boilerplat code for the integration to work wtihin HA or to have some constants/strings/translations.
If you would encounter some issues with this custom component, you can enable extra debug logging by adding below into your configuration.yaml:
logger:
default: info
logs:
custom_components.cityparking: debug
