npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

iobroker.familyplan

v0.1.15

Published

FamilienPlan calendar integration for ioBroker

Downloads

1,852

Readme

Logo

ioBroker.familyplan

NPM version Downloads Number of installations Current version in stable repository Test and Release

FamilienPlan adapter for ioBroker

This adapter imports calendar data from a FamilienPlan installation. It provides dynamic ioBroker objects, daily summaries, birthday and waste-collection texts, and persistent automation triggers for JavaScript and Blockly.

Requirements

  • Node.js 22 or newer
  • js-controller 6.0.11 or newer
  • Admin 8.0.11 or newer
  • A FamilienPlan installation with integration API support

Configuration

Connect to the FamilienPlan API

The adapter uses a read-only integration key belonging to a FamilienPlan person. The adapter always inherits that person's current permissions, so choose a person who is allowed to see every child and calendar entry that should be imported.

Create the key in FamilienPlan:

  1. Sign in to your FamilienPlan installation with an account that can manage the required person.
  2. Open People (Personen) and edit the person whose permissions the adapter should use.
  3. Find the API keys section, enter a descriptive name such as ioBroker, and select Create API key (API-Schlüssel erzeugen).
  4. Copy the generated key immediately and store it securely. The complete key is shown only when it is created.
  5. Administrators can review or revoke active read-only keys under Settings → Integrations → REST API keys (Einstellungen → Integrationen → REST-API-Schlüssel).

Configure ioBroker:

  1. Create or open an instance of the FamilienPlan adapter.
  2. Enter the public base URL of the FamilienPlan installation, for example https://family.example.com. Do not append /api/v1 or an endpoint path.
  3. Paste the generated key into API key.
  4. Select the IANA time zone used for calendar evaluation, for example Europe/Berlin.
  5. Select Test connection and permissions. A successful result includes the detected API version.
  6. Save the configuration and start the instance. info.connection becomes true after the first successful synchronization.

Treat the API key like a password. Do not include it in screenshots, issue reports, exported configurations, or logs. Revoking the key in FamilienPlan immediately prevents further synchronization. Permission changes made to its person apply to subsequent requests without creating a new key.

The configuration contains the following groups:

  • Connection: base URL, protected API key, connection test, IANA time zone, HTTP timeout, and TLS certificate verification.
  • Polling: week, month, quarter, or year range with optional days before and after it, polling interval, retry settings, optional child IDs, custody/location information, and object retention.
  • Timetable: optional timetable polling (disabled by default), with a 60-second default interval and a 10-second minimum.
  • Timeline: number of days, optional event-type filter, output template, separators, and date/time formats.
  • Birthdays and waste: relative output templates, separators, empty text, and waste-title mappings. All waste types returned by the API are imported.
  • Triggers: named rules with event type, optional custom type, child name, trigger position, offset/unit, and catch-up window.

Disabling TLS certificate verification is unsafe and produces an explicit warning. Use it only temporarily in a controlled local environment.

API

The adapter uses the following integration endpoints:

  • GET /api/v1/integrations/v1/status
  • GET /api/v1/integrations/v1/children
  • GET /api/v1/integrations/v1/calendar?from_at=…&to_at=…[&child_id=…]
  • GET /api/v1/integrations/v1/children/{id}/location
  • GET /api/v1/integrations/v1/children/{id}/timetable (optional server extension)

Authentication is sent exclusively in the Authorization: Bearer … header. The API key is never added to a URL.

Field mapping

API title is used unchanged, including standard stays. Occurrence folders (*.next, *.nextAfter, and birthdays.nextSignificant) expose description; their existing note state mirrors it for compatibility. Both are cleared when a description is null, empty, or absent without a legacy note. JSON retains explicit null descriptions and all other API fields. Birthday events without optional fields remain valid.

Location forecasts consider both current_until and next_change_at: the latter only identifies the next confirmed explicit stay. Calendar-based responsibility changes are compared by user ID. Calendar requests use encoded timestamps and chunks of 180 days, below the API limit of 366 days. Restricted calendar responses are used as supplied; children are only requested with read:children.

Timetables

Enable Fetch timetables in the Timetable configuration tab. The FamilienPlan server must include the integration timetable API extension; older versions without the endpoint remain usable for all other adapter features. The key needs read:children. Key restrictions and the associated person's current child permissions apply together. Timetables are fetched for all permitted children, independently of the calendar's optional child-ID filter.

The adapter uses the existing base URL, Bearer key, HTTP timeout and TLS settings. Recognized API prefixes are normalized to avoid duplicate /api/v1/integrations/v1 paths. It never calls the internal browser endpoint or supplies the optional on parameter. The children list is refreshed before each timetable polling cycle to recheck permissions. Timetable requests run sequentially without overlapping polling cycles or calendar synchronization; the configured interval starts after a cycle completes. Failed requests are retried on the next cycle. Pending timetable HTTP requests and the polling timer are cancelled on adapter shutdown.

The admin tab displays a timetable card for each child above the event search, including the current subject, teacher, lesson times and room, or the server-provided school-day status (break, before school, finished, or no school). The next lesson appears when available. An expandable weekly plan groups lessons by weekday and keeps its expanded state during live updates. Failed fetches show an unavailable notice and label any retained weekly plan as the last known version.

Each existing child path gains a children.<name>.timetable folder with read-only, acknowledged states:

| State | Meaning | | --- | --- | | status, statusText | Server status code and description | | configured | Whether a plan has been saved | | timezone | Server-provided timetable time zone | | evaluatedAt, statusDate | Server evaluation timestamp and status date | | date | Date of the daily schedule | | basis | planned: regular planned lessons, not live substitutions | | currentLesson.subject/start/end/room/teacher | Current lesson; all fields empty when the server returns null | | nextLesson.subject/start/end/room/teacher | Next lesson of the current day; all fields empty when null | | dailySchedule, weeklySchedule | JSON arrays of lessons | | json | Complete validated API response, including the underlying plan | | available | Whether the latest fetch returned usable data | | lastSuccessfulUpdate | Timestamp of the most recent successful fetch | | lastError | Fetch error; empty after success |

The status is copied from the server without recalculating it in the ioBroker time zone:

| Status | Meaning | | --- | --- | | lesson | A lesson is in progress | | break | Break between today's lessons | | before_school | Before today's first lesson | | finished | Today's final lesson has ended | | no_school | No lessons today, an explicitly free day, or an intentionally empty saved plan | | not_configured | No timetable has been saved | | outside_validity | Today is outside the saved plan's validity range |

Lesson start is inclusive and end is exclusive according to the server. Lesson start/end values remain local HH:MM strings in the supplied time zone, dates remain YYYY-MM-DD, and evaluatedAt retains its original offset. Lesson weekdays range from Monday 0 to Sunday 6. weeklySchedule is the regular week; dailySchedule respects validity and explicit days off. Holidays are not automatically excluded. Timetables are separate from calendar events and never enter appointment lists or calendar triggers.

On HTTP 401, 403, 404, network/server errors or invalid responses, available becomes false and lastError explains the failure. Previous valid values and lastSuccessfulUpdate remain unchanged: consumers must check available and the timestamp before treating those values as current. An error never becomes no_school or not_configured. Before the first successful fetch, lesson/status data may be absent. Repeated identical failures are logged only once until recovery or a different error. If the children list fails, all existing timetable folders are marked unavailable; children no longer returned by the permitted list have their timetable folders removed. Existing timetable data is also marked unavailable on restart or when the feature is disabled.

Objects

familyplan.0
├── info                 Connection, synchronization, API version, range, and counters
├── control.refresh      Writable manual-refresh button
├── calendar             Valid original API events and currently active events
├── children.<name>      Dynamically detected children, for example children.rika
├── appointments         Shared stable appointment overview
├── events.appointment   Dynamically detected event_type groups
├── timeline             today, tomorrow, days_2, …
├── birthdays            Relative birthday groups
├── waste                Relative waste-collection groups
└── triggers             Shared event, rule states, schedule, and persistent history

FamilienPlan API 0.1.82 calendar objects use event_type; the former type property is deliberately ignored. Known types include GENERAL, STAY, SCHOOL, SCHOOL_HOLIDAY, BIRTHDAY, PRIVATE, WASTE, CLEANING, and OTHER. Additional API values are supported dynamically. OTHER is grouped further by its normalized custom_type_label; events without a label use unknown.

Every event-type folder provides summaries, month groups, next, and nextAfter. The projections contain only events that have not started. An event is active from its inclusive starts_at until its exclusive ends_at value.

calendar.current contains all active events as JSON, their IDs, and their count. Its monotonic revision value changes only when an event starts or ends and is therefore suitable as an external automation trigger.

Children and custody changes

Each children.<name> folder exposes the child's name, birthDate, age, and a JSON summary. birthDate uses the configured birthday date format (default dd.MM.yyyy); age is the current age in the configured time zone and advances on the birthday. A child birth date takes precedence; otherwise a birthday explicitly linked by child_id can supply birth_date or a birth year derived from its occurrence date and known age. Birthday titles or matching numeric birthday IDs alone do not establish that link. If the API supplies neither source, birthDate remains empty and age remains null (unknown).

The child JSON replaces default_responsible_user_id with default_responsible_username. The name comes from the child response when supplied, or from known responsibility names matched by user ID in custody events and location responses. It is empty when no name can be resolved; the ID is retained internally for matching.

When location retrieval is enabled, children.<name>.location contains the current responsible person and nextChangeAt; next and nextAfter contain the following custody periods. These projections are recalculated from the cached STAY events during the local minute tick. Consequently, reaching nextChangeAt updates the child location without waiting for another API synchronization. An API synchronization is still required to retrieve newly created, edited, or deleted source data from FamilienPlan.

Timeline, birthdays, and waste collection

Timeline entries are assigned to calendar days in the configured time zone. Multi-day events appear on every affected day. The properties startsThisDay, endsThisDay, and continuesThisDay describe their relation to that day. IANA time zones ensure correct daylight-saving-time handling.

Birthday entries retain the age supplied by the API. If birth_date is missing, the displayed date is derived from the day and month of starts_at and from year(starts_at) - age. This value is a documented display fallback, not an additional API-confirmed birth date.

Waste collection uses event_type=WASTE. The waste type is derived from the part of the title before “in”, “am”, or “für”. Configured substring mappings take precedence, while the original title remains available.

Custody entries use event_type=STAY. Explicit entries have an ID and source=stay. Generated default stays have id=null, source=default, and generated=true. They receive stable internal keys, and matching adjacent default intervals split only by API query chunks are merged again. Explicit and generated entries are never treated as identical.

Reliable triggers

Supported positions are beforeStart, afterStart, beforeEnd, and afterEnd; offsets may use seconds, minutes, hours, or days. Rules filter directly by event_type. The custom_type_label filter applies only to OTHER. Child-name and responsible-person matching are case-insensitive. The optional responsible-person filter is especially useful for STAY rules, where the end of one household's interval is usually the beginning of the next household's interval.

Trigger rules are edited in expandable forms, grouped into event filters, firing time, trigger length, and catch-up settings. Optional title and description filters each support Matches exactly or Contains. All configured filters must match; empty filters match every event, and text matching ignores case and surrounding whitespace. Description filters use the API description, with a legacy note fallback only when description is absent.

Trigger length controls how long active remains true after an actual firing. Choose seconds, minutes, hours, or days (a day is 24 hours). Leaving the length empty keeps the trigger active until it is reset manually or its rule is disabled. Write true without acknowledgement to triggers.<rule-id>.reset to reset it; this button also works for finite lengths. Active state and manual resets survive adapter restarts. Further firings while active still increment count and update event; each firing starts a new finite duration.

The separate Catch-up window (seconds) limits how late a missed scheduled time may be fired, defaulting to 60 seconds for new rules. An unlimited trigger length does not mean unlimited catch-up. Existing rules keep their previous length and catch-up behavior until edited. Internally, the length retains the legacy catchUpSeconds configuration key, interpreted using lengthUnit; catchUpWindowSeconds stores the separate catch-up window. A persistent SHA-256 key made from the rule, event type, event key, start/end, position, and offset prevents duplicate triggers after a restart.

For robust automation, react to the monotonic triggers.<rule-id>.count state. Each rule has an active state. Its event JSON is written both when the trigger becomes active and when it is reset; the payload's active property identifies the transition. triggers.event receives these transitions from every rule as a common event stream. Event JSON preserves all API fields, including child_id, and adds child_name when available. API titles are preserved. description contains the API description, falls back to legacy note only when description is absent, and is null when neither is supplied. Birthday and waste JSON summaries also include the full event alongside their summary fields. lastTriggered, lastEventId, and scheduledFor provide additional context.

JavaScript example

on(
  { id: "familyplan.0.triggers.waste_before_start_1d.count", change: "ne" },
  () => {
    const payload = JSON.parse(
      getState("familyplan.0.triggers.waste_before_start_1d.event").val,
    );
    sendTo("telegram.0", "send", {
      text: `${payload.event.title} will be collected tomorrow.`,
    });
  },
);

Blockly

Use an “Object changed” block for familyplan.0.triggers.<rule-id>.count with the change type “not equal to previous value”. The branch can read the JSON event state or use lastEventId. To request a manual synchronization, write true without acknowledgement to control.refresh.

Troubleshooting and security

  • 401: The API key is missing, incorrect, or revoked.
  • 403: The person associated with the key lacks a required read permission.
  • 422: Check the configured range, time zone, and filters. Large ranges are automatically split into smaller API queries.
  • 429/5xx: Requests are retried with bounded exponential backoff, and the existing data is retained.
  • Timeout/DNS: Check the base URL, DNS resolution, reachability, and configured timeout.
  • TLS: Correct the certificate chain. Disable verification only in controlled test environments.

The API key is encrypted through encryptedNative, protected through protectedNative, and redacted together with authorization headers in error messages. Invalid individual events are skipped without rejecting an otherwise valid response. Never publish diagnostics or configuration exports containing a real key.

The adapter is distributed as a compiled npm package. npm pack builds the adapter before packaging. Admin configuration help and validation messages are translated into all supported languages; some short labels still use English fallback texts.

Development

Install the development dependencies and run the full local validation:

npm install
npm run validate

npm run validate performs TypeScript checking, ESLint, unit and package tests, and a clean build. HTTP tests use mocks and do not require a FamilienPlan server.

Include the generated build/ files when committing source changes so the repository contains the build/main.js entry point required by the adapter checker. The release script also rebuilds these files before its release commit.

Start the local ioBroker development environment with:

npm run dev-server setup
npm run dev-server watch

The Admin UI is available at http://127.0.0.1:8081 by default. Local data is stored below .dev-server/ and is not published.

Changelog

0.1.15 (2026-09-11)

  • (BenAhrdt) Include compiled adapter files in the repository for ioBroker adapter checker compatibility.
  • (BenAhrdt) Complete Admin UI translations and validation messages for all supported languages.

0.1.14 (2026-09-11)

  • (BenAhrdt) Exclude events ending exactly at the start of today from the admin tab's "From today" filter.
  • (BenAhrdt) Remove the unsupported common.noGit property from io-package.json.

0.1.13 (2026-09-07)

  • (BenAhrdt) change color og class shedule hours in tab

0.1.12 (2026-09-07)

  • (BenAhrdt) Add optional per-child timetable integration with server-provided lesson status, daily and weekly schedules, configurable polling, permission refresh, availability/error states, and cancellation on shutdown.
  • (BenAhrdt) Correct numeric state roles to value and add the d unit to daysLeft and daysUntil.
  • (BenAhrdt) Use sensor for active and acknowledged states, sensor.switch for trigger activation status, and state for all-day flags; make reset and refresh buttons write-only.
  • (BenAhrdt) Add daysLeft to children's current, next, and following custody projections, counting calendar days in the configured time zone until the respective change.
  • (BenAhrdt) Remove unnecessary child states from waste previews, including the waste event group, and update existing state definitions automatically.

0.1.11 (2026-09-05)

  • (BenAhrdt) Support FamilienPlan 0.1.100 birthday names and birth dates, prefer full names, and preserve original titles and all source fields.
  • (BenAhrdt) Keep missing birthday dates and ages unknown without inferring birth years; use server-provided annual occurrences and leap-day dates for birthday summaries.

Older changes are available in CHANGELOG_OLD.md.

License

MIT License

Copyright (c) 2026 Ben Schmidt

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.