A Home Assistant custom integration for Aula + EasyIQ school management system, providing access to student schedules, homework assignments, and presence information.
- π Weekly Schedule (Weekplan): View your child's weekly school schedule as sensor data
- π Homework Assignments: Track homework assignments with descriptions and due dates
- π€ Presence Status: Monitor your child's attendance status
- π Calendar Integration: School events appear in Home Assistant calendar
- π Multi-language: English interface with Danish school data support
- Open HACS in Home Assistant
- Go to "Integrations"
- Click the three dots in the top right corner
- Select "Custom repositories"
- Add this repository URL:
https://github.com/esbenwiberg/easyiq - Select "Integration" as the category
- Click "Add"
- Find "EasyIQ" in the integration list and install it
- Restart Home Assistant
- Download the latest release from the releases page
- Extract the
custom_components/easyiqfolder to your Home Assistantcustom_componentsdirectory - Restart Home Assistant
- Install via HACS (see Installation section below)
- Add integration through Home Assistant UI
- Enter your Aula credentials
Want to contribute or test locally? See DEVELOPMENT_SETUP.md for complete instructions on:
- Installing Home Assistant for development
- Getting the localhost:8123 interface working
- Setting up the development environment
- Testing and debugging the integration
- Go to Settings β Devices & Services
- Click Add Integration
- Search for "EasyIQ"
- Enter your Aula credentials:
- Username: Your Aula username
- Password: Your Aula password
- Select which features to enable:
- School Schedule
- Weekly Plan (Weekplan)
- Homework (Lektier)
- Presence Status
After initial setup, you can configure individual update intervals and data range for different data types:
- Go to Settings β Devices & Services
- Find your EasyIQ integration
- Click Configure (or the three dots β Configure)
- Adjust the settings:
- Weekplan Update Interval: How often to fetch schedule data (default: 900s / 15 minutes)
- Homework Update Interval: How often to fetch homework assignments (default: 900s / 15 minutes)
- Presence Update Interval: How often to check attendance status (default: 300s / 5 minutes)
- Messages Update Interval: How often to check for new messages (default: 300s / 5 minutes)
- Weekplan Days Forward: How many business days of schedule to fetch (default: 5 days, range: 1-14)
- Homework Days Forward: How many business days of homework to fetch (default: 5 days, range: 1-14)
Notes:
- All intervals must be between 60 seconds (1 minute) and 3600 seconds (1 hour)
- Days forward settings only count business days (Monday-Friday), weekends are automatically excluded
- The integration will use the shortest configured interval as its base update frequency and selectively update different data types based on their individual intervals
Update Intervals:
- High Priority Data (Presence, Messages): 300-600 seconds (5-10 minutes)
- Medium Priority Data (Weekplan, Homework): 900-1800 seconds (15-30 minutes)
Days Forward:
- Weekplan: 5-7 days for weekly planning, 3 days for daily focus
- Homework: 5-10 days for better assignment planning, 3 days for immediate focus
This approach reduces API load while keeping important data fresh. The defaults prioritize presence monitoring and message notifications while reducing the frequency of schedule and homework updates. Adjust the days forward based on your planning needs - fewer days for faster updates and daily focus, more days for better long-term planning.
Add to your configuration.yaml:
easyiq:
username: your_aula_username
password: your_aula_password
school_schedule: true
weekplan: true
homework: true
presence: trueFor each child in your account, the integration creates:
sensor.easyiq_[child_name]- Main child sensor with weekly schedule overviewsensor.easyiq_[child_name]_weekplan- Detailed weekplan sensor with event data
binary_sensor.easyiq_[child_name]_present- Presence status (ON = present at school, OFF = not present)binary_sensor.easyiq_messages- Unread messages indicator (ON = has unread messages)
calendar.easyiq_[child_name]_weekplan- School schedule calendar with all eventscalendar.easyiq_[child_name]_homework- Homework assignments calendar with due dates
Each sensor provides detailed attributes:
Main Child Sensor:
child_id: Unique child identifierchild_name: Child's nameweek: Current week descriptionevents_count: Number of scheduled eventshtml_content: Formatted schedule HTMLevent_1_subject,event_1_time,event_1_activities: First event details- (up to 5 events with subject, time, and activities)
Weekplan Sensor:
child_id: Unique child identifierchild_name: Child's nameweekplan_summary: Detailed weekplan data with events array
Presence Binary Sensor:
status: Current status text (e.g., "HENTET/GΓ ET", "KOMMET/TIL STEDE")status_code: Numeric status code (0-8)status_description: English description of statuscheck_in_time: Actual arrival time (e.g., "07:59:02")check_out_time: Actual departure time (e.g., "15:07:12")entry_time: Planned arrival time (e.g., "07:30:00")exit_time: Planned departure time (e.g., "15:00:00")comment: Additional notes (e.g., "Selvbestemmer 1400-1500")exit_with: Who picked up the child (e.g., "Mormor")child_name: Name of the childlast_updated: When the data was last updated
Message Binary Sensor:
unread_count: Number of unread messagessubject: Subject of latest messagetext: Content of latest messagesender: Sender of latest messagecoordinator_available: Integration statuslast_update_success: Last update status
automation:
- alias: "Child arrived at school"
trigger:
- platform: state
entity_id: binary_sensor.easyiq_child_present
to: "on"
condition:
- condition: template
value_template: >
{{ state_attr('binary_sensor.easyiq_child_present', 'status_code') == 3 }}
action:
- service: notify.mobile_app
data:
title: "School Arrival"
message: >
{{ state_attr('binary_sensor.easyiq_child_present', 'child_name') }}
arrived at school at {{ state_attr('binary_sensor.easyiq_child_present', 'check_in_time') }}automation:
- alias: "Child picked up from school"
trigger:
- platform: state
entity_id: binary_sensor.easyiq_child_present
to: "off"
condition:
- condition: template
value_template: >
{{ state_attr('binary_sensor.easyiq_child_present', 'status_code') == 8 }}
action:
- service: notify.mobile_app
data:
title: "School Pickup"
message: >
{{ state_attr('binary_sensor.easyiq_child_present', 'child_name') }}
was picked up at {{ state_attr('binary_sensor.easyiq_child_present', 'check_out_time') }}
{% if state_attr('binary_sensor.easyiq_child_present', 'exit_with') %}
by {{ state_attr('binary_sensor.easyiq_child_present', 'exit_with') }}
{% endif %}type: entities
title: This Week's Schedule
entities:
- entity: sensor.easyiq_child_weekplan
type: attribute
attribute: html_contentsensor:
- platform: template
sensors:
next_school_event:
friendly_name: "Next School Event"
value_template: >
{% set events = state_attr('sensor.easyiq_child_weekplan', 'events') %}
{% if events %}
{{ events[0].courses }} at {{ events[0].start }}
{% else %}
No upcoming events
{% endif %}automation:
- alias: "Homework due tomorrow"
trigger:
- platform: time
at: "19:00:00"
condition:
- condition: template
value_template: >
{{ state_attr('sensor.easyiq_child_weekplan', 'homework_due_tomorrow') | length > 0 }}
action:
- service: notify.family
data:
message: "Homework due tomorrow: {{ state_attr('sensor.easyiq_child_weekplan', 'homework_due_tomorrow') | join(', ') }}"automation:
- alias: "School pickup reminder"
trigger:
- platform: template
value_template: >
{{ (as_timestamp(now()) - as_timestamp(state_attr('sensor.easyiq_child_weekplan', 'last_event_end'))) < 1800 }}
action:
- service: notify.mobile_app
data:
message: "School ends soon - pickup time!"type: markdown
content: |
## Today's Schedule
{% set events = state_attr('sensor.easyiq_child_weekplan', 'events') %}
{% for event in events if event.date == now().strftime('%Y-%m-%d') %}
- **{{ event.start }}**: {{ event.courses }}
{% endfor %}type: custom:auto-entities
card:
type: entities
title: This Week's Events
filter:
include:
- entity_id: sensor.easyiq_*_weekplan
options:
type: custom:multiple-entity-row
entity: sensor.easyiq_child_weekplan
name: "{{ state_attr(config.entity, 'child_name') }}"
secondary_info: "{{ state_attr(config.entity, 'events_count') }} events"type: glance
title: School Attendance
entities:
- entity: binary_sensor.easyiq_child_present
name: Status
attribute: status
- entity: binary_sensor.easyiq_child_present
name: Arrived
attribute: check_in_time
- entity: binary_sensor.easyiq_child_present
name: Left
attribute: check_out_time
- entity: binary_sensor.easyiq_child_present
name: Comment
attribute: commenttype: markdown
content: |
{% set entity = 'binary_sensor.easyiq_child_present' %}
{% set status_code = state_attr(entity, 'status_code') %}
{% if status_code == 8 %}
{% set icon = 'π ' %}
{% set color = '#4CAF50' %}
{% set english_status = 'Picked up / Gone' %}
{% elif status_code == 3 %}
{% set icon = 'π«' %}
{% set color = '#2196F3' %}
{% set english_status = 'Present at school' %}
{% elif status_code == 0 %}
{% set icon = 'β' %}
{% set color = '#FF9800' %}
{% set english_status = 'Not arrived' %}
{% else %}
{% set icon = 'β' %}
{% set color = '#757575' %}
{% set english_status = 'Unknown' %}
{% endif %}
<div style="padding: 20px; border-radius: 12px; background: #f8f9fa; border-left: 4px solid {{ color }};">
<h3 style="margin: 0 0 16px 0; color: {{ color }};">
<span style="font-size: 24px; margin-right: 8px;">{{ icon }}</span>
{{ state_attr(entity, 'child_name') }}
</h3>
<div style="font-size: 16px; line-height: 1.8;">
<div><strong style="color: {{ color }};">Status:</strong> {{ english_status }}</div>
<div><strong>Arrived:</strong> {{ state_attr(entity, 'check_in_time') or 'Not yet' }}</div>
<div><strong>Left:</strong> {{ state_attr(entity, 'check_out_time') or 'Still there' }}</div>
<div><strong>Planned pickup:</strong> {{ state_attr(entity, 'exit_time') or 'Not set' }}</div>
{% if state_attr(entity, 'comment') %}
<div style="margin-top: 12px; padding: 12px; background: #fff3cd; border-radius: 6px;">
<strong>Notes:</strong> {{ state_attr(entity, 'comment') }}
</div>
{% endif %}
</div>
</div>See Dashboard Presence Cards for more card options and styling variations.
sensor:
- platform: template
sensors:
homework_summary:
friendly_name: "Homework Summary"
value_template: >
{% set homework = state_attr('sensor.easyiq_child_weekplan', 'homework') %}
{% if homework %}
{{ homework | length }} assignments due
{% else %}
No homework
{% endif %}
attribute_templates:
due_today: >
{% set homework = state_attr('sensor.easyiq_child_weekplan', 'homework') %}
{{ homework | selectattr('due_date', 'eq', now().strftime('%Y-%m-%d')) | list | length }}
due_tomorrow: >
{% set homework = state_attr('sensor.easyiq_child_weekplan', 'homework') %}
{% set tomorrow = (now() + timedelta(days=1)).strftime('%Y-%m-%d') %}
{{ homework | selectattr('due_date', 'eq', tomorrow) | list | length }}Authentication Failed
- Verify your Aula username and password are correct
- Check if your account has access to EasyIQ features
- Ensure your institution uses EasyIQ (not all Danish schools do)
No Data Retrieved
- Confirm your children are enrolled in classes using EasyIQ
- Check the Home Assistant logs for detailed error messages
- Verify your institution's EasyIQ setup is active
Integration Not Loading
- Restart Home Assistant after installation
- Check
custom_components/easyiqfolder structure is correct - Review Home Assistant logs for import errors
Add to your configuration.yaml for detailed logs:
logger:
default: warning
logs:
custom_components.easyiq: debugRun the included test script to verify your credentials:
cd /config/custom_components/easyiq
python scripts/test_client.pyThis integration uses two different API systems depending on the data type:
- Weekplan Data: Uses EasyIQ CalendarGetWeekplanEvents endpoint (itemType 9)
- Homework Data: Uses EasyIQ CalendarGetWeekplanEvents endpoint (itemType 4)
- Accessed through
https://skoleportal.easyiqcloud.dk/Calendar/CalendarGetWeekplanEvents - Requires EasyIQ widget authentication tokens from Aula
- Presence Data: Uses
presence.getDailyOverviewendpoint for real-time attendance:- Current status (KOMMET/TIL STEDE, HENTET/GΓ ET, etc.)
- Check-in and check-out times
- Planned entry and exit times
- Comments and pickup information
- Messages Data: Uses Aula messaging endpoints for unread message counts and content
- Accessed through
https://www.aula.dk/api/v{version}endpoints - Uses direct Aula session authentication
The integration authenticates using your Aula credentials and automatically handles both API systems seamlessly.
The integration supports configurable update intervals for each data type, with intelligent API routing:
Default Update Intervals:
- Presence Data (Aula API): Every 5 minutes (300 seconds)
- Messages (Aula API): Every 5 minutes (300 seconds)
- Weekplan Data (EasyIQ API): Every 15 minutes (900 seconds)
- Homework Data (EasyIQ API): Every 15 minutes (900 seconds)
Smart Polling System:
- The coordinator automatically uses the shortest configured interval (5 minutes) as its base frequency
- Individual data types are updated only when their specific interval has elapsed
- Aula API calls (presence, messages) happen more frequently for real-time data
- EasyIQ API calls (weekplan, homework) happen less frequently for static schedule data
- This reduces unnecessary API load while prioritizing time-sensitive information
Example API Load (with 2 children and default intervals):
- Presence (Aula API): ~24 calls/hour (every 5 minutes)
- Messages (Aula API): ~12 calls/hour (every 5 minutes)
- Weekplan (EasyIQ API): ~8 calls/hour (every 15 minutes)
- Homework (EasyIQ API): ~8 calls/hour (every 15 minutes)
- Total: ~52 API calls/hour (vs. ~96 with fixed 5-minute intervals)
This represents a 46% reduction in total API calls while providing optimal update frequencies for different data priorities.
For comprehensive usage examples covering all entities and features:
- Complete Usage Examples - All entities with 50+ practical examples
- Presence Usage Examples - Detailed presence feature guide
- Dashboard Presence Cards - Beautiful presence cards with colored icons
- Weekplan Sensors: Schedule data, event counts, HTML content
- Calendar Entities: School events, homework assignments with Home Assistant calendar integration
- Presence Binary Sensors: Real-time attendance with Danish status labels and colored dashboard cards
- Message Binary Sensors: Unread message notifications with content preview
This integration works with Danish schools that use:
- Aula as their primary communication platform
- EasyIQ for schedule and homework management
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
git clone https://github.com/esbenwiberg/easyiq.git
cd easyiq-ha
pip install -r requirements-dev.txt# Test the client
python scripts/test_client.py
# Run with debug logging
python -c "import logging; logging.basicConfig(level=logging.DEBUG); exec(open('scripts/test_client.py').read())"This project is licensed under the MIT License - see the LICENSE file for details.
This integration is not officially affiliated with EasyIQ or Aula. It's a community-developed integration that interfaces with publicly available APIs.
This project is inspired by and builds upon the excellent work done in the Aula integration by @scaarup. Many of the authentication and API interaction patterns were adapted from that project.
- π Bug Reports: GitHub Issues
- π¬ Discussions: GitHub Discussions
- π Documentation: Wiki
See CHANGELOG.md for version history and updates.
