Skip to content

Integration Setup

__init__.py handles integration lifecycle and service registration.

Lifecycle hooks

Function Purpose
async_setup Registers the Day Planner Lovelace card JS and all service actions
async_setup_entry Creates the coordinator, runs first refresh, defers platform setup until init completes
async_unload_entry Unloads all platforms and closes the HTTP session

Service actions

Service Input Response Description
sunriser.backup {path} Downloads config to HA config dir as .msgpack
sunriser.restore file_path Restores config from a .msgpack file
sunriser.get_errors {content} Retrieves device error log
sunriser.get_log {content} Retrieves device diagnostic log
sunriser.get_dayplanner_schedule pwm {pwm, name, color_id, markers} Reads day planner schedule
sunriser.set_dayplanner_schedule pwm, markers Writes day planner schedule
sunriser.get_weekplanner_schedule pwm {pwm, name, color_id, schedule} Reads week planner schedule
sunriser.set_weekplanner_schedule pwm, schedule Writes week planner schedule
sunriser.download_factory_backup {path} Downloads factory default config
sunriser.download_firmware {path} Downloads firmware info
sunriser.download_bootload {path} Downloads bootloader info
sunriser.factory_reset confirm: true Resets all device config to factory defaults

Reference

sunriser

Functions

async_setup(hass, config) async

Serve the Day Planner card JS and register it as a Lovelace resource.

Source code in custom_components/sunriser/__init__.py
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
async def async_setup(hass: HomeAssistant, config: dict[str, Any]) -> bool:
    """Serve the Day Planner card JS and register it as a Lovelace resource."""
    await hass.http.async_register_static_paths(
        [StaticPathConfig(_CARD_URL, str(_CARD_PATH), cache_headers=False)]
    )

    async def _register(_event: Event | None = None) -> None:
        lovelace = hass.data.get("lovelace")
        if lovelace is None:
            _LOGGER.warning(
                "SunRiser: lovelace not available, falling back to add_extra_js_url"
            )
            add_extra_js_url(hass, f"{_CARD_URL}?v={_CARD_VERSION}")
            return

        resources = lovelace.resources
        await resources.async_get_info()

        url_versioned = f"{_CARD_URL}?v={_CARD_VERSION}"
        for item in resources.async_items():
            item_url: str = item.get("url", "")
            if item_url.split("?")[0] == _CARD_URL:
                if item_url != url_versioned and isinstance(
                    resources, ResourceStorageCollection
                ):
                    await resources.async_update_item(
                        item["id"], {"res_type": "module", "url": url_versioned}
                    )
                return

        if isinstance(resources, ResourceStorageCollection):
            await resources.async_create_item(
                {"res_type": "module", "url": url_versioned}
            )
            _LOGGER.debug("SunRiser: registered Day Planner card as Lovelace resource")
        else:
            add_extra_js_url(hass, url_versioned)

    if hass.state == CoreState.running:
        await _register()
    else:
        hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, _register)

    _register_services(hass)
    return True

async_setup_entry(hass, entry) async

Source code in custom_components/sunriser/__init__.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    coordinator = SunRiserCoordinator(hass, entry)

    try:
        await coordinator.async_load_device_config()
    except aiohttp.ClientError as err:
        raise ConfigEntryNotReady(
            f"Cannot connect to SunRiser at {coordinator.host}: {err}"
        ) from err
    except Exception as err:
        _LOGGER.exception("Unexpected error loading SunRiser device config")
        raise ConfigEntryNotReady(f"Unexpected error: {err}") from err

    await coordinator.async_config_entry_first_refresh()

    entry.runtime_data = coordinator

    # Platform setup is deferred until all four init ticks complete so that
    # coordinator.config has PWM names, colors, and weather data before any
    # entity is created.  Each init tick makes exactly one HTTP request so the
    # WizFi360 has a full poll interval between connections.
    _platforms_loaded = False

    @callback
    def _on_coordinator_update() -> None:
        nonlocal _platforms_loaded
        if _platforms_loaded or not coordinator.init_complete:
            return
        _platforms_loaded = True
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
        )

    entry.async_on_unload(coordinator.async_add_listener(_on_coordinator_update))

    entry.async_on_unload(entry.add_update_listener(_async_reload_entry))

    return True

async_unload_entry(hass, entry) async

Source code in custom_components/sunriser/__init__.py
201
202
203
204
205
206
207
208
209
210
211
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    coordinator: SunRiserCoordinator = entry.runtime_data
    # Save in-memory state that must survive a same-session reload (options change,
    # reconfigure).  RestoreEntity covers HA restarts via the recorder.
    hass.data.setdefault(DOMAIN, {})[
        f"{entry.entry_id}_dst_auto_track"
    ] = coordinator._dst_auto_track
    unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
    if unload_ok:
        await coordinator.async_close()
    return unload_ok