From 7b62009e0d56e5025bea3c8238982404e329c76f Mon Sep 17 00:00:00 2001
From: sudoxnym
Date: Sun, 7 Dec 2025 08:04:02 -0600
Subject: [PATCH] rebrand to sleepd, remove next alarm sensor
---
CONTRIBUTING.md | 2 +-
DEPLOY.md | 8 +-
README.md | 16 +-
custom_components/saas/manifest.json | 10 -
.../{saas => sleepd}/__init__.py | 114 +-
custom_components/{saas => sleepd}/button.py | 1252 ++++++------
.../{saas => sleepd}/config_flow.py | 368 ++--
custom_components/{saas => sleepd}/const.py | 316 +--
custom_components/sleepd/manifest.json | 10 +
custom_components/{saas => sleepd}/sensor.py | 1783 ++++++++---------
.../{saas => sleepd}/services.py | 144 +-
.../{saas => sleepd}/services.yaml | 0
.../{saas => sleepd}/translations/ar.json | 148 +-
.../{saas => sleepd}/translations/de.json | 148 +-
.../{saas => sleepd}/translations/en.json | 148 +-
.../{saas => sleepd}/translations/es.json | 148 +-
.../{saas => sleepd}/translations/fr.json | 148 +-
.../{saas => sleepd}/translations/it.json | 148 +-
.../{saas => sleepd}/translations/ja.json | 148 +-
.../{saas => sleepd}/translations/ko.json | 148 +-
.../{saas => sleepd}/translations/nl.json | 148 +-
.../{saas => sleepd}/translations/pl.json | 148 +-
.../{saas => sleepd}/translations/pt.json | 148 +-
.../{saas => sleepd}/translations/pue.json | 148 +-
.../{saas => sleepd}/translations/ru.json | 10 +-
.../{saas => sleepd}/translations/sv.json | 148 +-
.../{saas => sleepd}/translations/zh.json | 148 +-
hacs.json | 2 +-
28 files changed, 2996 insertions(+), 3111 deletions(-)
delete mode 100644 custom_components/saas/manifest.json
rename custom_components/{saas => sleepd}/__init__.py (88%)
rename custom_components/{saas => sleepd}/button.py (85%)
rename custom_components/{saas => sleepd}/config_flow.py (95%)
rename custom_components/{saas => sleepd}/const.py (93%)
create mode 100644 custom_components/sleepd/manifest.json
rename custom_components/{saas => sleepd}/sensor.py (82%)
rename custom_components/{saas => sleepd}/services.py (85%)
rename custom_components/{saas => sleepd}/services.yaml (100%)
rename custom_components/{saas => sleepd}/translations/ar.json (90%)
rename custom_components/{saas => sleepd}/translations/de.json (88%)
rename custom_components/{saas => sleepd}/translations/en.json (85%)
rename custom_components/{saas => sleepd}/translations/es.json (89%)
rename custom_components/{saas => sleepd}/translations/fr.json (89%)
rename custom_components/{saas => sleepd}/translations/it.json (90%)
rename custom_components/{saas => sleepd}/translations/ja.json (87%)
rename custom_components/{saas => sleepd}/translations/ko.json (87%)
rename custom_components/{saas => sleepd}/translations/nl.json (89%)
rename custom_components/{saas => sleepd}/translations/pl.json (90%)
rename custom_components/{saas => sleepd}/translations/pt.json (89%)
rename custom_components/{saas => sleepd}/translations/pue.json (87%)
rename custom_components/{saas => sleepd}/translations/ru.json (91%)
rename custom_components/{saas => sleepd}/translations/sv.json (89%)
rename custom_components/{saas => sleepd}/translations/zh.json (87%)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ac5921f..3d34602 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,4 +1,4 @@
-# Contributing to SAAS - Sleep As Android Status
+# Contributing to sleepd - Sleep As Android Status
Thanks for helping improve the project!
diff --git a/DEPLOY.md b/DEPLOY.md
index 3300b09..40758da 100644
--- a/DEPLOY.md
+++ b/DEPLOY.md
@@ -1,4 +1,4 @@
-# 🧪 Deploying SAAS - Sleep As Android Status via HACS
+# 🧪 Deploying sleepd - Sleep As Android Status via HACS
## 🛠️ Pre-requisites
@@ -11,12 +11,12 @@
1. In HACS, go to "Integrations"
2. Click the 3-dot menu > Custom repositories
-3. Paste: `https://github.com/sudoxnym/saas`
+3. Paste: `https://github.com/sudoxnym/sleepd`
4. Set Category to "Integration"
5. Click "Add"
-6. Refresh, search for `SAAS - Sleep As Android Status`, and install
+6. Refresh, search for `sleepd - Sleep As Android Status`, and install
7. Restart Home Assistant
-8. Go to Settings > Devices & Services > Add Integration > search "SAAS"
+8. Go to Settings > Devices & Services > Add Integration > search "sleepd"
9. Configure the integration with your MQTT topic and states
## 🧪 Testing
diff --git a/README.md b/README.md
index e738dae..01005f1 100644
--- a/README.md
+++ b/README.md
@@ -4,10 +4,10 @@
-🌙 saas - Sleep As Android status
+🌙 sleepd - Sleep As Android status
🚨 0.2.0 breaking changes 🚨
-due to changes in **Home Assistant** 2025.12, you **must** remove your existing **SAAS** integration entries and re-add them after updating to this version.
+due to changes in **Home Assistant** 2025.12, you **must** remove your existing **sleepd** integration entries and re-add them after updating to this version.
---
@@ -21,7 +21,7 @@ sleep as android status is my solution for wake/sleep state within HA. it listen
-
- 📡 9 sensors
+ 📡 8 sensors
| Sensor | Description |
| ------ | ----------- |
@@ -57,7 +57,7 @@ sleep as android status is my solution for wake/sleep state within HA. it listen
🛠️ 1 service
-service: saas.saas_example_alarm_set
+service: sleepd.sleepd_example_alarm_set
data:
message: Example Message!
day: monday
@@ -86,15 +86,15 @@ data:
🧪 installation:
- - add
https://www.github.com/sudoxnym/saas to your custom repositories in HACS
- - search and download **SAAS - Sleep As Android status**
+ - add
https://www.github.com/sudoxnym/sleepd to your custom repositories in HACS
+ - search and download **sleepd - Sleep As Android status**
- restart Home Assistant
-
-
+
- - add integration: **SAAS - Sleep As Android status**
+ - add integration: **sleepd - Sleep As Android status**
⚙️ configuration:
diff --git a/custom_components/saas/manifest.json b/custom_components/saas/manifest.json
deleted file mode 100644
index d4c0023..0000000
--- a/custom_components/saas/manifest.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "domain": "saas",
- "name": "SAAS - Sleep As Android Status",
- "codeowners": ["@sudoxnym"],
- "config_flow": true,
- "dependencies": ["mqtt", "mobile_app"],
- "documentation": "https://www.github.com/sudoxnym/saas",
- "issue_tracker": "https://www.github.com/sudoxnym/saas/issues",
- "version": "0.2.1"
-}
diff --git a/custom_components/saas/__init__.py b/custom_components/sleepd/__init__.py
similarity index 88%
rename from custom_components/saas/__init__.py
rename to custom_components/sleepd/__init__.py
index 0f7911e..62fae31 100644
--- a/custom_components/saas/__init__.py
+++ b/custom_components/sleepd/__init__.py
@@ -1,57 +1,57 @@
-import asyncio
-import logging
-from homeassistant.config_entries import ConfigEntry
-from homeassistant.core import HomeAssistant
-from .const import DOMAIN
-from .services import async_setup_services # Import the service setup function
-
-_LOGGER = logging.getLogger(__name__)
-
-async def async_setup(hass: HomeAssistant, config: dict) -> bool:
- """Set up the SAAS - Sleep As Android Status component."""
- _LOGGER.info("Starting setup of the SAAS component")
- return True
-
-async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
- """Set up a config entry."""
- _LOGGER.info(f"Starting setup of config entry with ID: {entry.entry_id}")
-
- # ensure we have a dict for this integration
- hass.data.setdefault(DOMAIN, {})
-
- # merge original data + any saved options so runtime sees edits
- merged = {**entry.data, **entry.options}
- hass.data[DOMAIN][entry.entry_id] = merged
- _LOGGER.debug(
- "Merged entry.data and entry.options for %s: %s",
- entry.entry_id,
- hass.data[DOMAIN][entry.entry_id],
- )
-
- # forward setup to sensor and button platforms
- await hass.config_entries.async_forward_entry_setups(entry, ["sensor", "button"])
-
- # set up any custom services
- _LOGGER.info("Starting setup of services")
- await async_setup_services(hass)
- _LOGGER.info("Finished setup of services")
-
- _LOGGER.info("Finished setup of config entry")
- return True
-
-async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
- """Unload a config entry."""
- _LOGGER.info(f"Starting unload of config entry with ID: {entry.entry_id}")
-
- # unload sensor and button platforms
- unload_ok = await hass.config_entries.async_unload_platforms(entry, ["sensor", "button"])
- if not unload_ok:
- _LOGGER.error("Failed to unload platforms for saas")
- return False
-
- # clean up our stored data
- hass.data[DOMAIN].pop(entry.entry_id, None)
-
- _LOGGER.info(f"hass.data[{DOMAIN}] after unload: {hass.data.get(DOMAIN)}")
- _LOGGER.info("Finished unload of config entry")
- return True
+import asyncio
+import logging
+from homeassistant.config_entries import ConfigEntry
+from homeassistant.core import HomeAssistant
+from .const import DOMAIN
+from .services import async_setup_services # Import the service setup function
+
+_LOGGER = logging.getLogger(__name__)
+
+async def async_setup(hass: HomeAssistant, config: dict) -> bool:
+ """Set up the sleepd - Sleep As Android Status component."""
+ _LOGGER.info("Starting setup of the sleepd component")
+ return True
+
+async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
+ """Set up a config entry."""
+ _LOGGER.info(f"Starting setup of config entry with ID: {entry.entry_id}")
+
+ # ensure we have a dict for this integration
+ hass.data.setdefault(DOMAIN, {})
+
+ # merge original data + any saved options so runtime sees edits
+ merged = {**entry.data, **entry.options}
+ hass.data[DOMAIN][entry.entry_id] = merged
+ _LOGGER.debug(
+ "Merged entry.data and entry.options for %s: %s",
+ entry.entry_id,
+ hass.data[DOMAIN][entry.entry_id],
+ )
+
+ # forward setup to sensor and button platforms
+ await hass.config_entries.async_forward_entry_setups(entry, ["sensor", "button"])
+
+ # set up any custom services
+ _LOGGER.info("Starting setup of services")
+ await async_setup_services(hass)
+ _LOGGER.info("Finished setup of services")
+
+ _LOGGER.info("Finished setup of config entry")
+ return True
+
+async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
+ """Unload a config entry."""
+ _LOGGER.info(f"Starting unload of config entry with ID: {entry.entry_id}")
+
+ # unload sensor and button platforms
+ unload_ok = await hass.config_entries.async_unload_platforms(entry, ["sensor", "button"])
+ if not unload_ok:
+ _LOGGER.error("Failed to unload platforms for sleepd")
+ return False
+
+ # clean up our stored data
+ hass.data[DOMAIN].pop(entry.entry_id, None)
+
+ _LOGGER.info(f"hass.data[{DOMAIN}] after unload: {hass.data.get(DOMAIN)}")
+ _LOGGER.info("Finished unload of config entry")
+ return True
diff --git a/custom_components/saas/button.py b/custom_components/sleepd/button.py
similarity index 85%
rename from custom_components/saas/button.py
rename to custom_components/sleepd/button.py
index 4a24eaa..59cffb5 100644
--- a/custom_components/saas/button.py
+++ b/custom_components/sleepd/button.py
@@ -1,626 +1,626 @@
-import logging
-from homeassistant.components.button import ButtonEntity
-from homeassistant.helpers import device_registry as dr
-from .const import DOMAIN, INTEGRATION_NAME, MODEL, CONF_NAME, CONF_NOTIFY_TARGET
-import asyncio
-
-# Set up logging
-# _LOGGER = logging.getLogger(__name__)
-
-class SAASSleepTrackingStart(ButtonEntity):
- def __init__(self, hass, name, notify_target):
- """Initialize the button."""
- # _LOGGER.debug("Initializing SAAS Sleep Tracking Start button with name: %s", name)
- self._hass = hass
- self._name = name
- self._notify_target = notify_target # Store notify_target as an instance variable
- self._state = "off"
- # _LOGGER.debug("Button initialized with state: %s", self._state)
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- unique_id = f"saas_sleep_tracking_start_{self._name}"
- # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
- return unique_id
-
- @property
- def name(self):
- """Return the name of the button."""
- name = f"SAAS {self._name} Sleep Tracking Start"
- # _LOGGER.debug("Getting name of the button: %s", name)
- return name
-
- @property
- def is_on(self):
- """Return true if the button is on."""
- # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
- return self._state == "on"
-
- @property
- def device_info(self):
- """Return information about the device."""
- device_info = {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
- # _LOGGER.debug("Getting device information: %s", device_info)
- return device_info
-
- def press(self):
- if not self._notify_target:
- self._hass.components.persistent_notification.async_create(
- "add a mobile device to use this function",
- title=self.name,
- )
- return
- """Press the button."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- service_data = {
- "message": "command_broadcast_intent",
- "data": {
- "intent_package_name": "com.urbandroid.sleep",
- "intent_action": "com.urbandroid.sleep.alarmclock.START_SLEEP_TRACK",
- },
- }
- # _LOGGER.debug("Pressing the button with service call:\n"
- # "service: %s\n"
- # "data:\n"
- # "%s", service_name, service_data)
- self._hass.services.call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- self._state = "on"
- self.schedule_update_ha_state()
- # _LOGGER.debug("Button pressed. Current state: %s", self._state)
-
-class SAASSleepTrackingStop(ButtonEntity):
- def __init__(self, hass, name, notify_target):
- """Initialize the button."""
- # _LOGGER.debug("Initializing SAAS Sleep Tracking Stop button with name: %s", name)
- self._hass = hass
- self._name = name
- self._notify_target = notify_target
- self._state = "off"
- # _LOGGER.debug("Button initialized with state: %s", self._state)
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- unique_id = f"saas_sleep_tracking_stop_{self._name}"
- # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
- return unique_id
-
- @property
- def name(self):
- """Return the name of the button."""
- name = f"SAAS {self._name} Sleep Tracking Stop"
- # _LOGGER.debug("Getting name of the button: %s", name)
- return name
-
- @property
- def is_on(self):
- """Return true if the button is on."""
- # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
- return self._state == "on"
-
- @property
- def device_info(self):
- """Return information about the device."""
- device_info = {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
- # _LOGGER.debug("Getting device information: %s", device_info)
- return device_info
-
- def press(self):
- if not self._notify_target:
- self._hass.components.persistent_notification.async_create(
- "add a mobile device to use this function",
- title=self.name,
- )
- return
- """Press the button."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- service_data = {
- "message": "command_broadcast_intent",
- "data": {
- "intent_package_name": "com.urbandroid.sleep",
- "intent_action": "com.urbandroid.sleep.alarmclock.STOP_SLEEP_TRACK",
- },
- }
- # _LOGGER.debug("Pressing the button with service call:\n"
- # "service: %s\n"
- # "data:\n"
- # "%s", service_name, service_data)
- self._hass.services.call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- self._state = "on"
- self.schedule_update_ha_state()
- # _LOGGER.debug("Button pressed. Current state: %s", self._state)
-
-class SAASSleepTrackingPause(ButtonEntity):
- def __init__(self, hass, name, notify_target):
- """Initialize the button."""
- # _LOGGER.debug("Initializing SAAS Sleep Tracking Pause button with name: %s", name)
- self._hass = hass
- self._name = name
- self._notify_target = notify_target
- self._state = "off"
- # _LOGGER.debug("Button initialized with state: %s", self._state)
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- unique_id = f"saas_sleep_tracking_pause_{self._name}"
- # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
- return unique_id
-
- @property
- def name(self):
- """Return the name of the button."""
- name = f"SAAS {self._name} Sleep Tracking Pause"
- # _LOGGER.debug("Getting name of the button: %s", name)
- return name
-
- @property
- def is_on(self):
- """Return true if the button is on."""
- # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
- return self._state == "on"
-
- @property
- def device_info(self):
- """Return information about the device."""
- device_info = {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
- # _LOGGER.debug("Getting device information: %s", device_info)
- return device_info
-
- def press(self):
- if not self._notify_target:
- self._hass.components.persistent_notification.async_create(
- "add a mobile device to use this function",
- title=self.name,
- )
- return
- """Press the button."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- service_data = {
- "message": "command_broadcast_intent",
- "data": {
- "intent_package_name": "com.urbandroid.sleep",
- "intent_action": "com.urbandroid.sleep.ACTION_PAUSE_TRACKING",
- },
- }
- # _LOGGER.debug("Pressing the button with service call:\n"
- # "service: %s\n"
- # "data:\n"
- # "%s", service_name, service_data)
- self._hass.services.call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- self._state = "on"
- self.schedule_update_ha_state()
- # _LOGGER.debug("Button pressed. Current state: %s", self._state)
-
-class SAASSleepTrackingResume(ButtonEntity):
- def __init__(self, hass, name, notify_target):
- """Initialize the button."""
- # _LOGGER.debug("Initializing SAAS Sleep Tracking Pause button with name: %s", name)
- self._hass = hass
- self._name = name
- self._notify_target = notify_target
- self._state = "off"
- # _LOGGER.debug("Button initialized with state: %s", self._state)
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- unique_id = f"saas_sleep_tracking_resume_{self._name}"
- # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
- return unique_id
-
- @property
- def name(self):
- """Return the name of the button."""
- name = f"SAAS {self._name} Sleep Tracking Resume"
- # _LOGGER.debug("Getting name of the button: %s", name)
- return name
-
- @property
- def is_on(self):
- """Return true if the button is on."""
- # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
- return self._state == "on"
-
- @property
- def device_info(self):
- """Return information about the device."""
- device_info = {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
- # _LOGGER.debug("Getting device information: %s", device_info)
- return device_info
-
- def press(self):
- if not self._notify_target:
- self._hass.components.persistent_notification.async_create(
- "add a mobile device to use this function",
- title=self.name,
- )
- return
- """Press the button."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- service_data = {
- "message": "command_broadcast_intent",
- "data": {
- "intent_package_name": "com.urbandroid.sleep",
- "intent_action": "com.urbandroid.sleep.ACTION_RESUME_TRACKING",
- },
- }
- # _LOGGER.debug("Pressing the button with service call:\n"
- # "service: %s\n"
- # "data:\n"
- # "%s", service_name, service_data)
- self._hass.services.call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- self._state = "on"
- self.schedule_update_ha_state()
- # _LOGGER.debug("Button pressed. Current state: %s", self._state)
-
-class SAASAlarmClockSnooze(ButtonEntity):
- def __init__(self, hass, name, notify_target):
- """Initialize the button."""
- # _LOGGER.debug("Initializing SAAS Alarm Clock Snooze button with name: %s", name)
- self._hass = hass
- self._name = name
- self._notify_target = notify_target
- self._state = "off"
- # _LOGGER.debug("Button initialized with state: %s", self._state)
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- unique_id = f"saas_alarm_clock_snooze_{self._name}"
- # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
- return unique_id
-
- @property
- def name(self):
- """Return the name of the button."""
- name = f"SAAS {self._name} Alarm Clock Snooze"
- # _LOGGER.debug("Getting name of the button: %s", name)
- return name
-
- @property
- def is_on(self):
- """Return true if the button is on."""
- # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
- return self._state == "on"
-
- @property
- def device_info(self):
- """Return information about the device."""
- device_info = {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
- # _LOGGER.debug("Getting device information: %s", device_info)
- return device_info
-
- def press(self):
- if not self._notify_target:
- self._hass.components.persistent_notification.async_create(
- "add a mobile device to use this function",
- title=self.name,
- )
- return
- """Press the button."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- service_data = {
- "message": "command_broadcast_intent",
- "data": {
- "intent_package_name": "com.urbandroid.sleep",
- "intent_action": "com.urbandroid.sleep.alarmclock.ALARM_SNOOZE",
- },
- }
- # _LOGGER.debug("Pressing the button with service call:\n"
- # "service: %s\n"
- # "data:\n"
- # "%s", service_name, service_data)
- self._hass.services.call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- self._state = "on"
- self.schedule_update_ha_state()
- # _LOGGER.debug("Button pressed. Current state: %s", self._state)
-
-class SAASAlarmClockDisable(ButtonEntity):
- def __init__(self, hass, name, notify_target):
- """Initialize the button."""
- # _LOGGER.debug("Initializing SAAS Alarm Clock Disable button with name: %s", name)
- self._hass = hass
- self._name = name
- self._notify_target = notify_target
- self._state = "off"
- # _LOGGER.debug("Button initialized with state: %s", self._state)
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- unique_id = f"saas_alarm_clock_disable_{self._name}"
- # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
- return unique_id
-
- @property
- def name(self):
- """Return the name of the button."""
- name = f"SAAS {self._name} Alarm Clock Disable"
- # _LOGGER.debug("Getting name of the button: %s", name)
- return name
-
- @property
- def is_on(self):
- """Return true if the button is on."""
- # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
- return self._state == "on"
-
- @property
- def device_info(self):
- """Return information about the device."""
- device_info = {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
- # _LOGGER.debug("Getting device information: %s", device_info)
- return device_info
-
- def press(self):
- if not self._notify_target:
- self._hass.components.persistent_notification.async_create(
- "add a mobile device to use this function",
- title=self.name,
- )
- return
- """Press the button."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- service_data = {
- "message": "command_broadcast_intent",
- "data": {
- "intent_package_name": "com.urbandroid.sleep",
- "intent_action": "com.urbandroid.sleep.alarmclock.ALARM_DISMISS_CAPTCHA",
- },
- }
- # _LOGGER.debug("Pressing the button with service call:\n"
- # "service: %s\n"
- # "data:\n"
- # "%s", service_name, service_data)
- self._hass.services.call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- self._state = "on"
- self.schedule_update_ha_state()
- # _LOGGER.debug("Button pressed. Current state: %s", self._state)
-
-class SAASSleepTrackingStartWithAlarm(ButtonEntity):
- def __init__(self, hass, name, notify_target):
- """Initialize the button."""
- # _LOGGER.debug("Initializing SAAS Sleep Tracking Start with Alarm button with name: %s", name)
- self._hass = hass
- self._name = name
- self._notify_target = notify_target
- self._state = "off"
- # _LOGGER.debug("Button initialized with state: %s", self._state)
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- unique_id = f"saas_sleep_tracking_start_with_alarm_{self._name}"
- # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
- return unique_id
-
- @property
- def name(self):
- """Return the name of the button."""
- name = f"SAAS {self._name} Sleep Tracking Start with Alarm"
- # _LOGGER.debug("Getting name of the button: %s", name)
- return name
-
- @property
- def is_on(self):
- """Return true if the button is on."""
- # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
- return self._state == "on"
-
- @property
- def device_info(self):
- """Return information about the device."""
- device_info = {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
- # _LOGGER.debug("Getting device information: %s", device_info)
- return device_info
-
- def press(self):
- if not self._notify_target:
- self._hass.components.persistent_notification.async_create(
- "add a mobile device to use this function",
- title=self.name,
- )
- return
- """Press the button."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- service_data = {
- "message": "command_broadcast_intent",
- "data": {
- "intent_package_name": "com.urbandroid.sleep",
- "intent_action": "com.urbandroid.sleep.alarmclock.START_SLEEP_TRACK_WITH_IDEAL_ALARM_ACTION",
- },
- }
- # _LOGGER.debug("Pressing the button with service call:\n"
- # "service: %s\n"
- # "data:\n"
- # "%s", service_name, service_data)
- self._hass.services.call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- self._state = "on"
- self.schedule_update_ha_state()
- # _LOGGER.debug("Button pressed. Current state: %s", self._state)
-
-class SAASLullabyStop(ButtonEntity):
- def __init__(self, hass, name, notify_target):
- """Initialize the button."""
- # _LOGGER.debug("Initializing SAAS Lullaby Stop button with name: %s", name)
- self._hass = hass
- self._name = name
- self._notify_target = notify_target
- self._state = "off"
- # _LOGGER.debug("Button initialized with state: %s", self._state)
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- unique_id = f"saas_lullaby_stop_{self._name}"
- # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
- return unique_id
-
- @property
- def name(self):
- """Return the name of the button."""
- name = f"SAAS {self._name} Lullaby Stop"
- # _LOGGER.debug("Getting name of the button: %s", name)
- return name
-
- @property
- def is_on(self):
- """Return true if the button is on."""
- # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
- return self._state == "on"
-
- @property
- def device_info(self):
- """Return information about the device."""
- device_info = {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
- # _LOGGER.debug("Getting device information: %s", device_info)
- return device_info
-
- def press(self):
- if not self._notify_target:
- self._hass.components.persistent_notification.async_create(
- "add a mobile device to use this function",
- title=self.name,
- )
- return
- """Press the button."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- service_data = {
- "message": "command_broadcast_intent",
- "data": {
- "intent_package_name": "com.urbandroid.sleep",
- "intent_action": "com.urbandroid.sleep.ACTION_LULLABY_STOP_PLAYBACK",
- },
- }
- # _LOGGER.debug("Pressing the button with service call:\n"
- # "service: %s\n"
- # "data:\n"
- # "%s", service_name, service_data)
- self._hass.services.call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- self._state = "on"
- self.schedule_update_ha_state()
- # _LOGGER.debug("Button pressed. Current state: %s", self._state)
-
-
-
-async def async_setup_entry(hass, config_entry, async_add_entities):
- notify_target = config_entry.data.get(CONF_NOTIFY_TARGET)
- if not notify_target:
- _LOGGER.warning("no notify_target configured; skipping button setup")
- return
- # _LOGGER.debug("Setting up SAAS Sleep Tracking buttons from a config entry with data: %s", config_entry.data)
-
- # Extract the necessary data from config_entry.data
- name = config_entry.data[CONF_NAME]
- notify_target = config_entry.data.get(CONF_NOTIFY_TARGET)
-
- # Create instances of SAASSleepTrackingStart, SAASSleepTrackingStop and SAASSleepTrackingPause
- entities = [
- SAASSleepTrackingStart(hass, name, notify_target),
- SAASSleepTrackingStop(hass, name, notify_target),
- SAASSleepTrackingPause(hass, name, notify_target),
- SAASSleepTrackingResume(hass, name, notify_target),
- SAASAlarmClockSnooze(hass, name, notify_target),
- SAASAlarmClockDisable(hass, name, notify_target),
- SAASSleepTrackingStartWithAlarm(hass, name, notify_target),
- SAASLullabyStop(hass, name, notify_target),
- ]
-
- # Call async_setup on each entity if it has that method
- for entity in entities:
- if hasattr(entity, "async_setup"):
- await entity.async_setup()
-
- # Add the entities
- async_add_entities(entities)
- # _LOGGER.debug("SAAS Sleep Tracking buttons set up successfully")
\ No newline at end of file
+import logging
+from homeassistant.components.button import ButtonEntity
+from homeassistant.helpers import device_registry as dr
+from .const import DOMAIN, INTEGRATION_NAME, MODEL, CONF_NAME, CONF_NOTIFY_TARGET
+import asyncio
+
+# Set up logging
+# _LOGGER = logging.getLogger(__name__)
+
+class sleepdSleepTrackingStart(ButtonEntity):
+ def __init__(self, hass, name, notify_target):
+ """Initialize the button."""
+ # _LOGGER.debug("Initializing sleepd Sleep Tracking Start button with name: %s", name)
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target # Store notify_target as an instance variable
+ self._state = "off"
+ # _LOGGER.debug("Button initialized with state: %s", self._state)
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ unique_id = f"sleepd_sleep_tracking_start_{self._name}"
+ # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
+ return unique_id
+
+ @property
+ def name(self):
+ """Return the name of the button."""
+ name = f"sleepd {self._name} Sleep Tracking Start"
+ # _LOGGER.debug("Getting name of the button: %s", name)
+ return name
+
+ @property
+ def is_on(self):
+ """Return true if the button is on."""
+ # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
+ return self._state == "on"
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ device_info = {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+ # _LOGGER.debug("Getting device information: %s", device_info)
+ return device_info
+
+ def press(self):
+ if not self._notify_target:
+ self._hass.components.persistent_notification.async_create(
+ "add a mobile device to use this function",
+ title=self.name,
+ )
+ return
+ """Press the button."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ service_data = {
+ "message": "command_broadcast_intent",
+ "data": {
+ "intent_package_name": "com.urbandroid.sleep",
+ "intent_action": "com.urbandroid.sleep.alarmclock.START_SLEEP_TRACK",
+ },
+ }
+ # _LOGGER.debug("Pressing the button with service call:\n"
+ # "service: %s\n"
+ # "data:\n"
+ # "%s", service_name, service_data)
+ self._hass.services.call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ self._state = "on"
+ self.schedule_update_ha_state()
+ # _LOGGER.debug("Button pressed. Current state: %s", self._state)
+
+class sleepdSleepTrackingStop(ButtonEntity):
+ def __init__(self, hass, name, notify_target):
+ """Initialize the button."""
+ # _LOGGER.debug("Initializing sleepd Sleep Tracking Stop button with name: %s", name)
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target
+ self._state = "off"
+ # _LOGGER.debug("Button initialized with state: %s", self._state)
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ unique_id = f"sleepd_sleep_tracking_stop_{self._name}"
+ # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
+ return unique_id
+
+ @property
+ def name(self):
+ """Return the name of the button."""
+ name = f"sleepd {self._name} Sleep Tracking Stop"
+ # _LOGGER.debug("Getting name of the button: %s", name)
+ return name
+
+ @property
+ def is_on(self):
+ """Return true if the button is on."""
+ # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
+ return self._state == "on"
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ device_info = {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+ # _LOGGER.debug("Getting device information: %s", device_info)
+ return device_info
+
+ def press(self):
+ if not self._notify_target:
+ self._hass.components.persistent_notification.async_create(
+ "add a mobile device to use this function",
+ title=self.name,
+ )
+ return
+ """Press the button."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ service_data = {
+ "message": "command_broadcast_intent",
+ "data": {
+ "intent_package_name": "com.urbandroid.sleep",
+ "intent_action": "com.urbandroid.sleep.alarmclock.STOP_SLEEP_TRACK",
+ },
+ }
+ # _LOGGER.debug("Pressing the button with service call:\n"
+ # "service: %s\n"
+ # "data:\n"
+ # "%s", service_name, service_data)
+ self._hass.services.call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ self._state = "on"
+ self.schedule_update_ha_state()
+ # _LOGGER.debug("Button pressed. Current state: %s", self._state)
+
+class sleepdSleepTrackingPause(ButtonEntity):
+ def __init__(self, hass, name, notify_target):
+ """Initialize the button."""
+ # _LOGGER.debug("Initializing sleepd Sleep Tracking Pause button with name: %s", name)
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target
+ self._state = "off"
+ # _LOGGER.debug("Button initialized with state: %s", self._state)
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ unique_id = f"sleepd_sleep_tracking_pause_{self._name}"
+ # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
+ return unique_id
+
+ @property
+ def name(self):
+ """Return the name of the button."""
+ name = f"sleepd {self._name} Sleep Tracking Pause"
+ # _LOGGER.debug("Getting name of the button: %s", name)
+ return name
+
+ @property
+ def is_on(self):
+ """Return true if the button is on."""
+ # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
+ return self._state == "on"
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ device_info = {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+ # _LOGGER.debug("Getting device information: %s", device_info)
+ return device_info
+
+ def press(self):
+ if not self._notify_target:
+ self._hass.components.persistent_notification.async_create(
+ "add a mobile device to use this function",
+ title=self.name,
+ )
+ return
+ """Press the button."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ service_data = {
+ "message": "command_broadcast_intent",
+ "data": {
+ "intent_package_name": "com.urbandroid.sleep",
+ "intent_action": "com.urbandroid.sleep.ACTION_PAUSE_TRACKING",
+ },
+ }
+ # _LOGGER.debug("Pressing the button with service call:\n"
+ # "service: %s\n"
+ # "data:\n"
+ # "%s", service_name, service_data)
+ self._hass.services.call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ self._state = "on"
+ self.schedule_update_ha_state()
+ # _LOGGER.debug("Button pressed. Current state: %s", self._state)
+
+class sleepdSleepTrackingResume(ButtonEntity):
+ def __init__(self, hass, name, notify_target):
+ """Initialize the button."""
+ # _LOGGER.debug("Initializing sleepd Sleep Tracking Pause button with name: %s", name)
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target
+ self._state = "off"
+ # _LOGGER.debug("Button initialized with state: %s", self._state)
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ unique_id = f"sleepd_sleep_tracking_resume_{self._name}"
+ # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
+ return unique_id
+
+ @property
+ def name(self):
+ """Return the name of the button."""
+ name = f"sleepd {self._name} Sleep Tracking Resume"
+ # _LOGGER.debug("Getting name of the button: %s", name)
+ return name
+
+ @property
+ def is_on(self):
+ """Return true if the button is on."""
+ # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
+ return self._state == "on"
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ device_info = {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+ # _LOGGER.debug("Getting device information: %s", device_info)
+ return device_info
+
+ def press(self):
+ if not self._notify_target:
+ self._hass.components.persistent_notification.async_create(
+ "add a mobile device to use this function",
+ title=self.name,
+ )
+ return
+ """Press the button."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ service_data = {
+ "message": "command_broadcast_intent",
+ "data": {
+ "intent_package_name": "com.urbandroid.sleep",
+ "intent_action": "com.urbandroid.sleep.ACTION_RESUME_TRACKING",
+ },
+ }
+ # _LOGGER.debug("Pressing the button with service call:\n"
+ # "service: %s\n"
+ # "data:\n"
+ # "%s", service_name, service_data)
+ self._hass.services.call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ self._state = "on"
+ self.schedule_update_ha_state()
+ # _LOGGER.debug("Button pressed. Current state: %s", self._state)
+
+class sleepdAlarmClockSnooze(ButtonEntity):
+ def __init__(self, hass, name, notify_target):
+ """Initialize the button."""
+ # _LOGGER.debug("Initializing sleepd Alarm Clock Snooze button with name: %s", name)
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target
+ self._state = "off"
+ # _LOGGER.debug("Button initialized with state: %s", self._state)
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ unique_id = f"sleepd_alarm_clock_snooze_{self._name}"
+ # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
+ return unique_id
+
+ @property
+ def name(self):
+ """Return the name of the button."""
+ name = f"sleepd {self._name} Alarm Clock Snooze"
+ # _LOGGER.debug("Getting name of the button: %s", name)
+ return name
+
+ @property
+ def is_on(self):
+ """Return true if the button is on."""
+ # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
+ return self._state == "on"
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ device_info = {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+ # _LOGGER.debug("Getting device information: %s", device_info)
+ return device_info
+
+ def press(self):
+ if not self._notify_target:
+ self._hass.components.persistent_notification.async_create(
+ "add a mobile device to use this function",
+ title=self.name,
+ )
+ return
+ """Press the button."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ service_data = {
+ "message": "command_broadcast_intent",
+ "data": {
+ "intent_package_name": "com.urbandroid.sleep",
+ "intent_action": "com.urbandroid.sleep.alarmclock.ALARM_SNOOZE",
+ },
+ }
+ # _LOGGER.debug("Pressing the button with service call:\n"
+ # "service: %s\n"
+ # "data:\n"
+ # "%s", service_name, service_data)
+ self._hass.services.call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ self._state = "on"
+ self.schedule_update_ha_state()
+ # _LOGGER.debug("Button pressed. Current state: %s", self._state)
+
+class sleepdAlarmClockDisable(ButtonEntity):
+ def __init__(self, hass, name, notify_target):
+ """Initialize the button."""
+ # _LOGGER.debug("Initializing sleepd Alarm Clock Disable button with name: %s", name)
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target
+ self._state = "off"
+ # _LOGGER.debug("Button initialized with state: %s", self._state)
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ unique_id = f"sleepd_alarm_clock_disable_{self._name}"
+ # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
+ return unique_id
+
+ @property
+ def name(self):
+ """Return the name of the button."""
+ name = f"sleepd {self._name} Alarm Clock Disable"
+ # _LOGGER.debug("Getting name of the button: %s", name)
+ return name
+
+ @property
+ def is_on(self):
+ """Return true if the button is on."""
+ # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
+ return self._state == "on"
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ device_info = {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+ # _LOGGER.debug("Getting device information: %s", device_info)
+ return device_info
+
+ def press(self):
+ if not self._notify_target:
+ self._hass.components.persistent_notification.async_create(
+ "add a mobile device to use this function",
+ title=self.name,
+ )
+ return
+ """Press the button."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ service_data = {
+ "message": "command_broadcast_intent",
+ "data": {
+ "intent_package_name": "com.urbandroid.sleep",
+ "intent_action": "com.urbandroid.sleep.alarmclock.ALARM_DISMISS_CAPTCHA",
+ },
+ }
+ # _LOGGER.debug("Pressing the button with service call:\n"
+ # "service: %s\n"
+ # "data:\n"
+ # "%s", service_name, service_data)
+ self._hass.services.call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ self._state = "on"
+ self.schedule_update_ha_state()
+ # _LOGGER.debug("Button pressed. Current state: %s", self._state)
+
+class sleepdSleepTrackingStartWithAlarm(ButtonEntity):
+ def __init__(self, hass, name, notify_target):
+ """Initialize the button."""
+ # _LOGGER.debug("Initializing sleepd Sleep Tracking Start with Alarm button with name: %s", name)
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target
+ self._state = "off"
+ # _LOGGER.debug("Button initialized with state: %s", self._state)
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ unique_id = f"sleepd_sleep_tracking_start_with_alarm_{self._name}"
+ # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
+ return unique_id
+
+ @property
+ def name(self):
+ """Return the name of the button."""
+ name = f"sleepd {self._name} Sleep Tracking Start with Alarm"
+ # _LOGGER.debug("Getting name of the button: %s", name)
+ return name
+
+ @property
+ def is_on(self):
+ """Return true if the button is on."""
+ # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
+ return self._state == "on"
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ device_info = {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+ # _LOGGER.debug("Getting device information: %s", device_info)
+ return device_info
+
+ def press(self):
+ if not self._notify_target:
+ self._hass.components.persistent_notification.async_create(
+ "add a mobile device to use this function",
+ title=self.name,
+ )
+ return
+ """Press the button."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ service_data = {
+ "message": "command_broadcast_intent",
+ "data": {
+ "intent_package_name": "com.urbandroid.sleep",
+ "intent_action": "com.urbandroid.sleep.alarmclock.START_SLEEP_TRACK_WITH_IDEAL_ALARM_ACTION",
+ },
+ }
+ # _LOGGER.debug("Pressing the button with service call:\n"
+ # "service: %s\n"
+ # "data:\n"
+ # "%s", service_name, service_data)
+ self._hass.services.call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ self._state = "on"
+ self.schedule_update_ha_state()
+ # _LOGGER.debug("Button pressed. Current state: %s", self._state)
+
+class sleepdLullabyStop(ButtonEntity):
+ def __init__(self, hass, name, notify_target):
+ """Initialize the button."""
+ # _LOGGER.debug("Initializing sleepd Lullaby Stop button with name: %s", name)
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target
+ self._state = "off"
+ # _LOGGER.debug("Button initialized with state: %s", self._state)
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ unique_id = f"sleepd_lullaby_stop_{self._name}"
+ # _LOGGER.debug("Getting unique ID for the button: %s", unique_id)
+ return unique_id
+
+ @property
+ def name(self):
+ """Return the name of the button."""
+ name = f"sleepd {self._name} Lullaby Stop"
+ # _LOGGER.debug("Getting name of the button: %s", name)
+ return name
+
+ @property
+ def is_on(self):
+ """Return true if the button is on."""
+ # _LOGGER.debug("Checking if the button is on. Current state: %s", self._state)
+ return self._state == "on"
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ device_info = {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+ # _LOGGER.debug("Getting device information: %s", device_info)
+ return device_info
+
+ def press(self):
+ if not self._notify_target:
+ self._hass.components.persistent_notification.async_create(
+ "add a mobile device to use this function",
+ title=self.name,
+ )
+ return
+ """Press the button."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ service_data = {
+ "message": "command_broadcast_intent",
+ "data": {
+ "intent_package_name": "com.urbandroid.sleep",
+ "intent_action": "com.urbandroid.sleep.ACTION_LULLABY_STOP_PLAYBACK",
+ },
+ }
+ # _LOGGER.debug("Pressing the button with service call:\n"
+ # "service: %s\n"
+ # "data:\n"
+ # "%s", service_name, service_data)
+ self._hass.services.call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ self._state = "on"
+ self.schedule_update_ha_state()
+ # _LOGGER.debug("Button pressed. Current state: %s", self._state)
+
+
+
+async def async_setup_entry(hass, config_entry, async_add_entities):
+ notify_target = config_entry.data.get(CONF_NOTIFY_TARGET)
+ if not notify_target:
+ _LOGGER.warning("no notify_target configured; skipping button setup")
+ return
+ # _LOGGER.debug("Setting up sleepd Sleep Tracking buttons from a config entry with data: %s", config_entry.data)
+
+ # Extract the necessary data from config_entry.data
+ name = config_entry.data[CONF_NAME]
+ notify_target = config_entry.data.get(CONF_NOTIFY_TARGET)
+
+ # Create instances of sleepdSleepTrackingStart, sleepdSleepTrackingStop and sleepdSleepTrackingPause
+ entities = [
+ sleepdSleepTrackingStart(hass, name, notify_target),
+ sleepdSleepTrackingStop(hass, name, notify_target),
+ sleepdSleepTrackingPause(hass, name, notify_target),
+ sleepdSleepTrackingResume(hass, name, notify_target),
+ sleepdAlarmClockSnooze(hass, name, notify_target),
+ sleepdAlarmClockDisable(hass, name, notify_target),
+ sleepdSleepTrackingStartWithAlarm(hass, name, notify_target),
+ sleepdLullabyStop(hass, name, notify_target),
+ ]
+
+ # Call async_setup on each entity if it has that method
+ for entity in entities:
+ if hasattr(entity, "async_setup"):
+ await entity.async_setup()
+
+ # Add the entities
+ async_add_entities(entities)
+ # _LOGGER.debug("sleepd Sleep Tracking buttons set up successfully")
\ No newline at end of file
diff --git a/custom_components/saas/config_flow.py b/custom_components/sleepd/config_flow.py
similarity index 95%
rename from custom_components/saas/config_flow.py
rename to custom_components/sleepd/config_flow.py
index 348a47f..addcb7b 100644
--- a/custom_components/saas/config_flow.py
+++ b/custom_components/sleepd/config_flow.py
@@ -1,184 +1,184 @@
-import logging
-import voluptuous as vol
-from .const import (
- DOMAIN,
- CONF_NAME,
- CONF_TOPIC,
- AVAILABLE_STATES,
- CONF_AWAKE_DURATION,
- CONF_SLEEP_DURATION,
- CONF_AWAKE_STATES,
- CONF_SLEEP_STATES,
- DEFAULT_AWAKE_DURATION,
- DEFAULT_SLEEP_DURATION,
- DEFAULT_AWAKE_STATES,
- DEFAULT_SLEEP_STATES,
- CONF_NOTIFY_TARGET,
-)
-from homeassistant import config_entries
-from voluptuous import Schema, Required, Optional, In
-from homeassistant.helpers import config_validation as cv
-
-_LOGGER = logging.getLogger(__name__)
-
-
-class MyConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
- """Handle the initial config flow for SAAS."""
- VERSION = 2
- CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH
-
- async def async_step_user(self, user_input=None):
- """Initial setup step."""
- errors = {}
-
- # discover available mobile_app notify services
- notify_services = self.hass.services.async_services().get("notify", {})
- notify_targets = {
- svc.replace("mobile_app_", "")
- .replace("_", " ")
- .lower(): svc
- for svc in notify_services
- if svc.startswith("mobile_app_")
- }
-
- if user_input is not None:
- # map chosen label back to service name, or remove if invalid
- nt_label = user_input.get(CONF_NOTIFY_TARGET)
- if nt_label in notify_targets:
- user_input[CONF_NOTIFY_TARGET] = notify_targets[nt_label]
- else:
- user_input.pop(CONF_NOTIFY_TARGET, None)
-
- # basic validation
- if not user_input.get(CONF_NAME):
- errors[CONF_NAME] = "required"
-
- if not errors:
- return self.async_create_entry(
- title=user_input[CONF_NAME],
- data=user_input
- )
-
- # build initial form schema
- schema = {
- Required(CONF_NAME): str,
- Required(CONF_TOPIC): str,
- Required(CONF_AWAKE_DURATION, default=DEFAULT_AWAKE_DURATION): int,
- Required(CONF_SLEEP_DURATION, default=DEFAULT_SLEEP_DURATION): int,
- Required(
- CONF_AWAKE_STATES, default=DEFAULT_AWAKE_STATES
- ): cv.multi_select(AVAILABLE_STATES),
- Required(
- CONF_SLEEP_STATES, default=DEFAULT_SLEEP_STATES
- ): cv.multi_select(AVAILABLE_STATES),
- }
- if notify_targets:
- # truly optional, only real targets, no blank choice
- schema[Optional(CONF_NOTIFY_TARGET)] = In(list(notify_targets.keys()))
-
- return self.async_show_form(
- step_id="user",
- data_schema=Schema(schema),
- errors=errors,
- )
-
- @staticmethod
- @config_entries.callback
- def async_get_options_flow(entry):
- """Return options flow handler."""
- return OptionsFlowHandler(entry)
-
-
-class OptionsFlowHandler(config_entries.OptionsFlow):
- """Handle SAAS options editing."""
-
- def __init__(self, entry):
- super().__init__()
- self._config_entry = entry
-
- async def async_step_init(self, user_input=None):
- """Manage the options form (edit)."""
- current = dict(self._config_entry.data)
-
- # discover mobile_app notify services again
- notify_services = self.hass.services.async_services().get("notify", {})
- notify_targets = {
- svc.replace("mobile_app_", "")
- .replace("_", " ")
- .lower(): svc
- for svc in notify_services
- if svc.startswith("mobile_app_")
- }
- # reverse map for defaults
- reverse_map = {v: k for k, v in notify_targets.items()}
-
- if user_input is not None:
- new_data = current.copy()
-
- # standard fields
- for key in (
- CONF_NAME,
- CONF_TOPIC,
- CONF_AWAKE_DURATION,
- CONF_SLEEP_DURATION,
- CONF_AWAKE_STATES,
- CONF_SLEEP_STATES,
- ):
- if key in user_input:
- new_data[key] = user_input[key]
-
- # handle notify_target with "no mobile" option
- sel = user_input.get(CONF_NOTIFY_TARGET)
- if sel == "no mobile":
- new_data.pop(CONF_NOTIFY_TARGET, None)
- elif sel in notify_targets:
- new_data[CONF_NOTIFY_TARGET] = notify_targets[sel]
-
- # persist back into entry.data and reload
- self.hass.config_entries.async_update_entry(
- self._config_entry,
- data=new_data,
- )
- await self.hass.config_entries.async_reload(self._config_entry.entry_id)
-
- return self.async_create_entry(title="", data=None)
-
- # build edit form schema with defaults
- schema = {
- Required(
- CONF_NAME, default=current.get(CONF_NAME, "")
- ): str,
- Required(
- CONF_TOPIC, default=current.get(CONF_TOPIC, "")
- ): str,
- Required(
- CONF_AWAKE_DURATION,
- default=current.get(CONF_AWAKE_DURATION, DEFAULT_AWAKE_DURATION),
- ): int,
- Required(
- CONF_SLEEP_DURATION,
- default=current.get(CONF_SLEEP_DURATION, DEFAULT_SLEEP_DURATION),
- ): int,
- Required(
- CONF_AWAKE_STATES,
- default=current.get(CONF_AWAKE_STATES, DEFAULT_AWAKE_STATES),
- ): cv.multi_select(AVAILABLE_STATES),
- Required(
- CONF_SLEEP_STATES,
- default=current.get(CONF_SLEEP_STATES, DEFAULT_SLEEP_STATES),
- ): cv.multi_select(AVAILABLE_STATES),
- }
-
- if notify_targets:
- # prepend "no mobile", then all real targets, all lowercase with spaces
- labels = ["no mobile"] + list(notify_targets.keys())
- default_label = reverse_map.get(
- current.get(CONF_NOTIFY_TARGET), "no mobile"
- )
- schema[Optional(CONF_NOTIFY_TARGET, default=default_label)] = In(labels)
-
- return self.async_show_form(
- step_id="init",
- data_schema=Schema(schema),
- errors={},
- )
+import logging
+import voluptuous as vol
+from .const import (
+ DOMAIN,
+ CONF_NAME,
+ CONF_TOPIC,
+ AVAILABLE_STATES,
+ CONF_AWAKE_DURATION,
+ CONF_SLEEP_DURATION,
+ CONF_AWAKE_STATES,
+ CONF_SLEEP_STATES,
+ DEFAULT_AWAKE_DURATION,
+ DEFAULT_SLEEP_DURATION,
+ DEFAULT_AWAKE_STATES,
+ DEFAULT_SLEEP_STATES,
+ CONF_NOTIFY_TARGET,
+)
+from homeassistant import config_entries
+from voluptuous import Schema, Required, Optional, In
+from homeassistant.helpers import config_validation as cv
+
+_LOGGER = logging.getLogger(__name__)
+
+
+class MyConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
+ """Handle the initial config flow for sleepd."""
+ VERSION = 2
+ CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH
+
+ async def async_step_user(self, user_input=None):
+ """Initial setup step."""
+ errors = {}
+
+ # discover available mobile_app notify services
+ notify_services = self.hass.services.async_services().get("notify", {})
+ notify_targets = {
+ svc.replace("mobile_app_", "")
+ .replace("_", " ")
+ .lower(): svc
+ for svc in notify_services
+ if svc.startswith("mobile_app_")
+ }
+
+ if user_input is not None:
+ # map chosen label back to service name, or remove if invalid
+ nt_label = user_input.get(CONF_NOTIFY_TARGET)
+ if nt_label in notify_targets:
+ user_input[CONF_NOTIFY_TARGET] = notify_targets[nt_label]
+ else:
+ user_input.pop(CONF_NOTIFY_TARGET, None)
+
+ # basic validation
+ if not user_input.get(CONF_NAME):
+ errors[CONF_NAME] = "required"
+
+ if not errors:
+ return self.async_create_entry(
+ title=user_input[CONF_NAME],
+ data=user_input
+ )
+
+ # build initial form schema
+ schema = {
+ Required(CONF_NAME): str,
+ Required(CONF_TOPIC): str,
+ Required(CONF_AWAKE_DURATION, default=DEFAULT_AWAKE_DURATION): int,
+ Required(CONF_SLEEP_DURATION, default=DEFAULT_SLEEP_DURATION): int,
+ Required(
+ CONF_AWAKE_STATES, default=DEFAULT_AWAKE_STATES
+ ): cv.multi_select(AVAILABLE_STATES),
+ Required(
+ CONF_SLEEP_STATES, default=DEFAULT_SLEEP_STATES
+ ): cv.multi_select(AVAILABLE_STATES),
+ }
+ if notify_targets:
+ # truly optional, only real targets, no blank choice
+ schema[Optional(CONF_NOTIFY_TARGET)] = In(list(notify_targets.keys()))
+
+ return self.async_show_form(
+ step_id="user",
+ data_schema=Schema(schema),
+ errors=errors,
+ )
+
+ @staticmethod
+ @config_entries.callback
+ def async_get_options_flow(entry):
+ """Return options flow handler."""
+ return OptionsFlowHandler(entry)
+
+
+class OptionsFlowHandler(config_entries.OptionsFlow):
+ """Handle sleepd options editing."""
+
+ def __init__(self, entry):
+ super().__init__()
+ self._config_entry = entry
+
+ async def async_step_init(self, user_input=None):
+ """Manage the options form (edit)."""
+ current = dict(self._config_entry.data)
+
+ # discover mobile_app notify services again
+ notify_services = self.hass.services.async_services().get("notify", {})
+ notify_targets = {
+ svc.replace("mobile_app_", "")
+ .replace("_", " ")
+ .lower(): svc
+ for svc in notify_services
+ if svc.startswith("mobile_app_")
+ }
+ # reverse map for defaults
+ reverse_map = {v: k for k, v in notify_targets.items()}
+
+ if user_input is not None:
+ new_data = current.copy()
+
+ # standard fields
+ for key in (
+ CONF_NAME,
+ CONF_TOPIC,
+ CONF_AWAKE_DURATION,
+ CONF_SLEEP_DURATION,
+ CONF_AWAKE_STATES,
+ CONF_SLEEP_STATES,
+ ):
+ if key in user_input:
+ new_data[key] = user_input[key]
+
+ # handle notify_target with "no mobile" option
+ sel = user_input.get(CONF_NOTIFY_TARGET)
+ if sel == "no mobile":
+ new_data.pop(CONF_NOTIFY_TARGET, None)
+ elif sel in notify_targets:
+ new_data[CONF_NOTIFY_TARGET] = notify_targets[sel]
+
+ # persist back into entry.data and reload
+ self.hass.config_entries.async_update_entry(
+ self._config_entry,
+ data=new_data,
+ )
+ await self.hass.config_entries.async_reload(self._config_entry.entry_id)
+
+ return self.async_create_entry(title="", data=None)
+
+ # build edit form schema with defaults
+ schema = {
+ Required(
+ CONF_NAME, default=current.get(CONF_NAME, "")
+ ): str,
+ Required(
+ CONF_TOPIC, default=current.get(CONF_TOPIC, "")
+ ): str,
+ Required(
+ CONF_AWAKE_DURATION,
+ default=current.get(CONF_AWAKE_DURATION, DEFAULT_AWAKE_DURATION),
+ ): int,
+ Required(
+ CONF_SLEEP_DURATION,
+ default=current.get(CONF_SLEEP_DURATION, DEFAULT_SLEEP_DURATION),
+ ): int,
+ Required(
+ CONF_AWAKE_STATES,
+ default=current.get(CONF_AWAKE_STATES, DEFAULT_AWAKE_STATES),
+ ): cv.multi_select(AVAILABLE_STATES),
+ Required(
+ CONF_SLEEP_STATES,
+ default=current.get(CONF_SLEEP_STATES, DEFAULT_SLEEP_STATES),
+ ): cv.multi_select(AVAILABLE_STATES),
+ }
+
+ if notify_targets:
+ # prepend "no mobile", then all real targets, all lowercase with spaces
+ labels = ["no mobile"] + list(notify_targets.keys())
+ default_label = reverse_map.get(
+ current.get(CONF_NOTIFY_TARGET), "no mobile"
+ )
+ schema[Optional(CONF_NOTIFY_TARGET, default=default_label)] = In(labels)
+
+ return self.async_show_form(
+ step_id="init",
+ data_schema=Schema(schema),
+ errors={},
+ )
diff --git a/custom_components/saas/const.py b/custom_components/sleepd/const.py
similarity index 93%
rename from custom_components/saas/const.py
rename to custom_components/sleepd/const.py
index 95974a7..14ce618 100644
--- a/custom_components/saas/const.py
+++ b/custom_components/sleepd/const.py
@@ -1,159 +1,159 @@
-"""Constants for the SAAS - Sleep As Android Stats integration."""
-
-DOMAIN = "saas"
-
-INTEGRATION_NAME = "SAAS - Sleep As Android Stats"
-MODEL = "SAAS - Version 0.0.1"
-
-CONF_NAME = "name" # Name of the Integration
-CONF_TOPIC = "topic_template" # MQTT Topic for Sleep As Android Events
-CONF_AWAKE_DURATION = "awake_duration" # Awake Duration
-CONF_SLEEP_DURATION = "sleep_duration" # Sleep Duration
-CONF_AWAKE_STATES = "awake_states" # Awake States
-CONF_SLEEP_STATES = "sleep_states" # Sleep States
-CONF_NOTIFY_TARGET = "notify_target" # Notify Target
-
-DEFAULT_AWAKE_DURATION = 10 # Default Awake Duration
-DEFAULT_SLEEP_DURATION = 10 # Default Sleep Duration
-DEFAULT_AWAKE_STATES = ["Awake", "Sleep Tracking Stopped"] # Default Awake States
-DEFAULT_SLEEP_STATES = [
- "Not Awake",
- "Rem",
- "Light Sleep",
- "Deep Sleep",
- "Sleep Tracking Started",
-] # Default Sleep States
-
-SENSOR_TYPES = {
- "state": {"name": "State", "device_class": None},
- "awake": {"name": "Awake", "device_class": "motion"},
-}
-
-DAY_MAPPING = {
- "sunday": 1,
- "monday": 2,
- "tuesday": 3,
- "wednesday": 4,
- "thursday": 5,
- "friday": 6,
- "saturday": 7,
-}
-
-AVAILABLE_STATES = [
- 'Unknown',
- 'Alarm Alert Dismiss',
- 'Alarm Alert Start',
- 'Alarm Rescheduled',
- 'Alarm Skip Next',
- 'Alarm Snooze Canceled',
- 'Alarm Snooze Clicked',
- 'Antisnoring',
- 'Apnea Alarm',
- 'Awake',
- 'Before Alarm',
- 'Before Smart Period',
- 'Deep Sleep',
- 'Light Sleep',
- 'Lullaby Start',
- 'Lullaby Stop',
- 'Lullaby Volume Down',
- 'Not Awake',
- 'Rem',
- 'Show Skip Next Alarm',
- 'Sleep Tracking Paused',
- 'Sleep Tracking Resumed',
- 'Sleep Tracking Started',
- 'Sleep Tracking Stopped',
- 'Smart Period',
- 'Sound Event Baby',
- 'Sound Event Cough',
- 'Sound Event Laugh',
- 'Sound Event Snore',
- 'Sound Event Talk',
- 'Time for Bed',
-]
-
-STATE_MAPPING = {
- "unknown": "Unknown",
- "sleep_tracking_started": "Sleep Tracking Started",
- "sleep_tracking_stopped": "Sleep Tracking Stopped",
- "sleep_tracking_paused": "Sleep Tracking Paused",
- "sleep_tracking_resumed": "Sleep Tracking Resumed",
- "alarm_snooze_clicked": "Alarm Snoozed",
- "alarm_snooze_canceled": "Snooze Canceled",
- "time_to_bed_alarm_alert": "Time for Bed",
- "alarm_alert_start": "Alarm Alert Started",
- "alarm_alert_dismiss": "Alarm Dismissed",
- "alarm_skip_next": "Skip Next Alarm",
- "show_skip_next_alarm": "Show Skip Next Alarm",
- "rem": "REM",
- "smart_period": "Smart Period",
- "before_smart_period": "Before Smart Period",
- "lullaby_start": "Lullaby Start",
- "lullaby_stop": "Lullaby Stop",
- "lullaby_volume_down": "Lullaby Volume Down",
- "deep_sleep": "Deep Sleep",
- "light_sleep": "Light Sleep",
- "awake": "Awake",
- "not_awake": "Not Awake",
- "apnea_alarm": "Apnea Alarm",
- "antisnoring": "Antisnoring",
- "before_alarm": "Before Alarm",
- "sound_event_snore": "Snore Detected",
- "sound_event_talk": "Talk Detected",
- "sound_event_cough": "Cough Detected",
- "sound_event_baby": "Baby Cry Detected",
- "sound_event_laugh": "Laugh Detected",
- "alarm_rescheduled": "Alarm Rescheduled",
-}
-
-REVERSE_STATE_MAPPING = {v: k for k, v in STATE_MAPPING.items()}
-
-SLEEP_STAGE_MAPPING = {
- "unknown": "Unknown",
- "rem": "REM",
- "deep_sleep": "Deep Sleep",
- "light_sleep": "Light Sleep",
- "awake": "Awake",
- "not_awake": "Not Awake",
-}
-
-SOUND_MAPPING = {
- 'sound_event_snore': "Snore Detected",
- 'sound_event_talk': "Talk Detected",
- 'sound_event_cough': "Cough Detected",
- 'sound_event_baby': "Baby Cry Detected",
- 'sound_event_laugh': "Laugh Detected",
-}
-
-LULLABY_MAPPING = {
- "lullaby_start": "Lullaby Start",
- "lullaby_stop": "Lullaby Stop",
- "lullaby_volume_down": "Lullaby Volume Down",
-}
-
-DISTURBANCE_MAPPING = {
- 'apnea_alarm': "Apnea Alarm",
- 'antisnoring': "Antisnoring",
-}
-
-ALARM_EVENT_MAPPING = {
- 'before_alarm': "Before Alarm",
- 'alarm_snooze_clicked': "Alarm Snoozed",
- 'alarm_snooze_canceled': "Snooze Canceled",
- 'time_to_bed_alarm_alert': "Time for Bed",
- 'alarm_alert_start': "Alarm Alert Started",
- 'alarm_alert_dismiss': "Alarm Dismissed",
- 'alarm_skip_next': "Skip Next Alarm",
- 'show_skip_next_alarm': "Show Skip Next Alarm",
- 'smart_period': "Smart Period",
- 'before_smart_period': "Before Smart Period",
- "alarm_rescheduled": "Alarm Rescheduled",
-}
-
-SLEEP_TRACKING_MAPPING = {
- 'sleep_tracking_started': "Sleep Tracking Started",
- 'sleep_tracking_stopped': "Sleep Tracking Stopped",
- 'sleep_tracking_paused': "Sleep Tracking Paused",
- 'sleep_tracking_resumed': "Sleep Tracking Resumed",
+"""Constants for the sleepd - Sleep As Android Stats integration."""
+
+DOMAIN = "sleepd"
+
+INTEGRATION_NAME = "sleepd - Sleep As Android Stats"
+MODEL = "sleepd - Version 0.0.1"
+
+CONF_NAME = "name" # Name of the Integration
+CONF_TOPIC = "topic_template" # MQTT Topic for Sleep As Android Events
+CONF_AWAKE_DURATION = "awake_duration" # Awake Duration
+CONF_SLEEP_DURATION = "sleep_duration" # Sleep Duration
+CONF_AWAKE_STATES = "awake_states" # Awake States
+CONF_SLEEP_STATES = "sleep_states" # Sleep States
+CONF_NOTIFY_TARGET = "notify_target" # Notify Target
+
+DEFAULT_AWAKE_DURATION = 10 # Default Awake Duration
+DEFAULT_SLEEP_DURATION = 10 # Default Sleep Duration
+DEFAULT_AWAKE_STATES = ["Awake", "Sleep Tracking Stopped"] # Default Awake States
+DEFAULT_SLEEP_STATES = [
+ "Not Awake",
+ "Rem",
+ "Light Sleep",
+ "Deep Sleep",
+ "Sleep Tracking Started",
+] # Default Sleep States
+
+SENSOR_TYPES = {
+ "state": {"name": "State", "device_class": None},
+ "awake": {"name": "Awake", "device_class": "motion"},
+}
+
+DAY_MAPPING = {
+ "sunday": 1,
+ "monday": 2,
+ "tuesday": 3,
+ "wednesday": 4,
+ "thursday": 5,
+ "friday": 6,
+ "saturday": 7,
+}
+
+AVAILABLE_STATES = [
+ 'Unknown',
+ 'Alarm Alert Dismiss',
+ 'Alarm Alert Start',
+ 'Alarm Rescheduled',
+ 'Alarm Skip Next',
+ 'Alarm Snooze Canceled',
+ 'Alarm Snooze Clicked',
+ 'Antisnoring',
+ 'Apnea Alarm',
+ 'Awake',
+ 'Before Alarm',
+ 'Before Smart Period',
+ 'Deep Sleep',
+ 'Light Sleep',
+ 'Lullaby Start',
+ 'Lullaby Stop',
+ 'Lullaby Volume Down',
+ 'Not Awake',
+ 'Rem',
+ 'Show Skip Next Alarm',
+ 'Sleep Tracking Paused',
+ 'Sleep Tracking Resumed',
+ 'Sleep Tracking Started',
+ 'Sleep Tracking Stopped',
+ 'Smart Period',
+ 'Sound Event Baby',
+ 'Sound Event Cough',
+ 'Sound Event Laugh',
+ 'Sound Event Snore',
+ 'Sound Event Talk',
+ 'Time for Bed',
+]
+
+STATE_MAPPING = {
+ "unknown": "Unknown",
+ "sleep_tracking_started": "Sleep Tracking Started",
+ "sleep_tracking_stopped": "Sleep Tracking Stopped",
+ "sleep_tracking_paused": "Sleep Tracking Paused",
+ "sleep_tracking_resumed": "Sleep Tracking Resumed",
+ "alarm_snooze_clicked": "Alarm Snoozed",
+ "alarm_snooze_canceled": "Snooze Canceled",
+ "time_to_bed_alarm_alert": "Time for Bed",
+ "alarm_alert_start": "Alarm Alert Started",
+ "alarm_alert_dismiss": "Alarm Dismissed",
+ "alarm_skip_next": "Skip Next Alarm",
+ "show_skip_next_alarm": "Show Skip Next Alarm",
+ "rem": "REM",
+ "smart_period": "Smart Period",
+ "before_smart_period": "Before Smart Period",
+ "lullaby_start": "Lullaby Start",
+ "lullaby_stop": "Lullaby Stop",
+ "lullaby_volume_down": "Lullaby Volume Down",
+ "deep_sleep": "Deep Sleep",
+ "light_sleep": "Light Sleep",
+ "awake": "Awake",
+ "not_awake": "Not Awake",
+ "apnea_alarm": "Apnea Alarm",
+ "antisnoring": "Antisnoring",
+ "before_alarm": "Before Alarm",
+ "sound_event_snore": "Snore Detected",
+ "sound_event_talk": "Talk Detected",
+ "sound_event_cough": "Cough Detected",
+ "sound_event_baby": "Baby Cry Detected",
+ "sound_event_laugh": "Laugh Detected",
+ "alarm_rescheduled": "Alarm Rescheduled",
+}
+
+REVERSE_STATE_MAPPING = {v: k for k, v in STATE_MAPPING.items()}
+
+SLEEP_STAGE_MAPPING = {
+ "unknown": "Unknown",
+ "rem": "REM",
+ "deep_sleep": "Deep Sleep",
+ "light_sleep": "Light Sleep",
+ "awake": "Awake",
+ "not_awake": "Not Awake",
+}
+
+SOUND_MAPPING = {
+ 'sound_event_snore': "Snore Detected",
+ 'sound_event_talk': "Talk Detected",
+ 'sound_event_cough': "Cough Detected",
+ 'sound_event_baby': "Baby Cry Detected",
+ 'sound_event_laugh': "Laugh Detected",
+}
+
+LULLABY_MAPPING = {
+ "lullaby_start": "Lullaby Start",
+ "lullaby_stop": "Lullaby Stop",
+ "lullaby_volume_down": "Lullaby Volume Down",
+}
+
+DISTURBANCE_MAPPING = {
+ 'apnea_alarm': "Apnea Alarm",
+ 'antisnoring': "Antisnoring",
+}
+
+ALARM_EVENT_MAPPING = {
+ 'before_alarm': "Before Alarm",
+ 'alarm_snooze_clicked': "Alarm Snoozed",
+ 'alarm_snooze_canceled': "Snooze Canceled",
+ 'time_to_bed_alarm_alert': "Time for Bed",
+ 'alarm_alert_start': "Alarm Alert Started",
+ 'alarm_alert_dismiss': "Alarm Dismissed",
+ 'alarm_skip_next': "Skip Next Alarm",
+ 'show_skip_next_alarm': "Show Skip Next Alarm",
+ 'smart_period': "Smart Period",
+ 'before_smart_period': "Before Smart Period",
+ "alarm_rescheduled": "Alarm Rescheduled",
+}
+
+SLEEP_TRACKING_MAPPING = {
+ 'sleep_tracking_started': "Sleep Tracking Started",
+ 'sleep_tracking_stopped': "Sleep Tracking Stopped",
+ 'sleep_tracking_paused': "Sleep Tracking Paused",
+ 'sleep_tracking_resumed': "Sleep Tracking Resumed",
}
\ No newline at end of file
diff --git a/custom_components/sleepd/manifest.json b/custom_components/sleepd/manifest.json
new file mode 100644
index 0000000..d418f06
--- /dev/null
+++ b/custom_components/sleepd/manifest.json
@@ -0,0 +1,10 @@
+{
+ "domain": "sleepd",
+ "name": "sleepd - Sleep As Android Status",
+ "codeowners": ["@sudoxnym"],
+ "config_flow": true,
+ "dependencies": ["mqtt", "mobile_app"],
+ "documentation": "https://www.github.com/sudoxnym/sleepd",
+ "issue_tracker": "https://www.github.com/sudoxnym/sleepd/issues",
+ "version": "0.2.1"
+}
diff --git a/custom_components/saas/sensor.py b/custom_components/sleepd/sensor.py
similarity index 82%
rename from custom_components/saas/sensor.py
rename to custom_components/sleepd/sensor.py
index 0fcee75..50c2193 100644
--- a/custom_components/saas/sensor.py
+++ b/custom_components/sleepd/sensor.py
@@ -1,950 +1,835 @@
-import asyncio, json, logging, time, inspect, pytz
-from datetime import timedelta, datetime, timezone
-from collections import deque
-from homeassistant.helpers.event import async_track_time_interval, async_call_later
-from homeassistant.helpers.dispatcher import async_dispatcher_connect
-from homeassistant.helpers.restore_state import RestoreEntity
-from homeassistant.components.mqtt import async_subscribe
-from homeassistant.helpers.entity import Entity
-from homeassistant.util import dt as dt_util
-from homeassistant.components import mqtt
-from .const import DOMAIN, CONF_NAME, CONF_TOPIC, CONF_AWAKE_STATES, CONF_SLEEP_STATES, CONF_AWAKE_DURATION, CONF_SLEEP_DURATION, INTEGRATION_NAME, MODEL, STATE_MAPPING, SOUND_MAPPING, DISTURBANCE_MAPPING, ALARM_EVENT_MAPPING, SLEEP_TRACKING_MAPPING, LULLABY_MAPPING, REVERSE_STATE_MAPPING, SLEEP_STAGE_MAPPING
-
-_LOGGER = logging.getLogger(__name__)
-_LOGGER.setLevel(logging.DEBUG)
-
-class SAASSensor(RestoreEntity):
- """Representation of a SAAS - Sleep As Android Stats sensor."""
-
- def __init__(self, hass, name, mapping, entry_id):
- """Initialize the sensor."""
- self._state = None
- self._name = name
- self._hass = hass
- self._mapping = mapping
- self.entry_id = entry_id
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- return f"saas_sensor_{self._name}"
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return f"SAAS {self._name} State"
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- async def async_added_to_hass(self):
- """Run when entity about to be added."""
- await super().async_added_to_hass()
-
- # Load the previous state from the state machine
- state = await self.async_get_last_state()
- if state:
- self._state = state.state
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
-
- async def message_received(msg):
- """Handle new MQTT messages."""
- # Parse the incoming message
- msg_json = json.loads(msg.payload)
-
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json}")
-
- # Extract the EVENT field
- event = msg_json.get('event')
-
- if event is None:
- _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json}")
- return
-
- # Use the mapping to convert the event to the corresponding state
- new_state = self._mapping.get(event)
- if new_state is not None:
- self._state = new_state
- self.async_schedule_update_ha_state()
-
- # Subscribe to the topic from the user input
- await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- # Save the current state to the state machine
- self._hass.states.async_set(self.entity_id, self._state)
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
-
-class SAASAlarmEventSensor(RestoreEntity):
- """Representation of a SAAS - Sleep As Android Stats sensor for Alarm Events."""
-
- def __init__(self, hass, name, mapping, entry_id):
- """Initialize the sensor."""
- self._state = None
- self._name = name
- self._hass = hass
- self._mapping = mapping
- self._value1 = None
- self._value2 = None
- self._time = None
- self.entry_id = entry_id
- self._last_event = None
- self._timeout_task = None
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- return f"saas_alarm_event_sensor_{self._name}"
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return f"SAAS {self._name} Alarm Event"
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- @property
- def extra_state_attributes(self):
- """Return the extra state attributes."""
- if self._state is not None:
- return {
- "Last Event": self._last_event,
- "Message": self._value2 if self._value2 else "No message received",
- "Timestamp": self._value1 if self._value1 else "No timestamp received",
- "Time": self._time.strftime('%H:%M') if self._time else "No time received",
- "Date": self._time.strftime('%m/%d/%Y') if self._time else "No date received",
- }
- return {}
-
- async def async_added_to_hass(self):
- """Run when entity about to be added."""
- await super().async_added_to_hass()
-
- # Load the previous state from the state machine
- state = await self.async_get_last_state()
- if state:
- self._state = state.state
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
-
- # Start the timeout task as soon as the sensor is loaded
- self._timeout_task = asyncio.create_task(self.timeout())
-
- async def message_received(msg):
- """Handle new MQTT messages."""
- # Cancel the previous timeout task if it exists
- if self._timeout_task:
- self._timeout_task.cancel()
-
- # Parse the incoming message
- msg_json = json.loads(msg.payload)
-
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
-
- # Extract the 'value1' and 'value2' fields
- value1 = msg_json.get('value1')
-
- # Parse 'value1' as a datetime
- if value1:
- timestamp = int(value1) / 1000.0
- self._time = datetime.fromtimestamp(timestamp)
- self._value1 = value1
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
-
- # Extract the 'value2' field
- value2 = msg_json.get('value2')
-
- # Store 'value2' as the message if it exists
- self._value2 = value2 if value2 else "None"
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
-
- # Extract the EVENT field
- event = msg_json.get('event')
-
- if event is None:
- _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
- return
-
- # Use the mapping to convert the event to the corresponding state
- new_state = self._mapping.get(event) # Default to "None" if no mapping found
- if new_state is not None:
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
- self._state = new_state
- self._last_event = new_state # Update the last event
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
- self.async_schedule_update_ha_state()
-
- # Create a new timeout task
- self._timeout_task = asyncio.create_task(self.timeout())
-
- # Subscribe to the topic from the user input
- await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- # Save the current state to the state machine
- self._hass.states.async_set(self.entity_id, self._state)
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
-
- async def timeout(self):
- """Set the state to 'None' after a timeout."""
- await asyncio.sleep(15)
- self._state = "None"
- self._last_event = "None"
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
- self.async_schedule_update_ha_state()
-
-class SAASNextAlarmSensor(RestoreEntity):
- """Sensor that exposes the next scheduled alarm time and label."""
-
- def __init__(self, hass, name, entry_id):
- self._hass = hass
- self._name = name
- self.entry_id = entry_id
- self._state = None
- self._label = None
- self._alarms = []
-
- @property
- def unique_id(self):
- return f"saas_next_alarm_{self._name}"
-
- @property
- def name(self):
- return f"SAAS {self._name} Next Alarm"
-
- @property
- def state(self):
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- @property
- def extra_state_attributes(self):
- attrs = {}
- if self._label:
- attrs["Label"] = self._label
- if self._alarms:
- attrs["Alarms"] = self._alarms
- return attrs
-
- async def async_added_to_hass(self):
- await super().async_added_to_hass()
-
- state = await self.async_get_last_state()
- if state:
- self._state = state.state if state.state != "None" else None
- self._label = state.attributes.get("Label")
- saved = state.attributes.get("Alarms")
- if isinstance(saved, list):
- self._alarms = saved
-
- async def message_received(msg):
- msg_json = json.loads(msg.payload)
- event = msg_json.get("event")
- value1 = msg_json.get("value1")
- value2 = msg_json.get("value2")
-
- if event == "alarm_rescheduled":
- if value1:
- ts = int(value1) / 1000.0
- dt = dt_util.as_local(datetime.fromtimestamp(ts))
- epoch = dt.timestamp()
- found = False
- for alarm in self._alarms:
- if alarm["timestamp"] == epoch:
- alarm["label"] = value2
- found = True
- break
- if not found:
- self._alarms.append({"timestamp": epoch, "label": value2})
- self._alarms.sort(key=lambda x: x["timestamp"])
- self._alarms = self._alarms[:10]
-
- elif event in ("alarm_alert_dismiss", "alarm_skip_next"):
- if value1:
- ts = int(value1) / 1000.0
- dt = dt_util.as_local(datetime.fromtimestamp(ts))
- epoch = dt.timestamp()
- self._alarms = [a for a in self._alarms if a["timestamp"] != epoch]
- elif self._alarms:
- self._alarms.pop(0)
- else:
- return
-
- if self._alarms:
- next_alarm = self._alarms[0]
- dt = dt_util.as_local(datetime.fromtimestamp(next_alarm["timestamp"]))
- self._state = dt.strftime("%Y-%m-%d %H:%M")
- self._label = next_alarm.get("label")
- else:
- self._state = None
- self._label = None
-
- self.async_schedule_update_ha_state()
-
- await async_subscribe(
- self._hass,
- self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC],
- message_received,
- )
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- self.hass.states.async_set(
- self.entity_id,
- self._state,
- {"Label": self._label, "Alarms": self._alarms},
- )
- _LOGGER.info(
- f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}"
- )
-
-class SAASSoundSensor(RestoreEntity):
- """Representation of a SAAS - Sleep As Android Stats sensor for Sound Events."""
-
- def __init__(self, hass, name, mapping, entry_id):
- """Initialize the sensor."""
- self._state = None
- self._name = name
- self._hass = hass
- self._mapping = mapping
- self._value1 = None
- self._value2 = None
- self._time = None
- self.entry_id = entry_id
- self._last_event = None
- self._timeout_task = None
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- return f"saas_sound_sensor_{self._name}"
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return f"SAAS {self._name} Sound"
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- @property
- def extra_state_attributes(self):
- """Return the extra state attributes."""
- return {
- "Last Event": self._last_event,
- "Timestamp": self._value1 if self._value1 else "No timestamp received",
- "Time": self._time.strftime('%H:%M') if self._time else "No time received",
- "Date": self._time.strftime('%m/%d/%Y') if self._time else "No date received",
- }
-
- async def async_added_to_hass(self):
- """Run when entity about to be added."""
- await super().async_added_to_hass()
-
- # Load the previous state from the state machine
- state = await self.async_get_last_state()
- if state:
- self._state = state.state
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
-
- # Start the timeout task as soon as the sensor is loaded
- self._timeout_task = asyncio.create_task(self.timeout())
-
- async def message_received(msg):
- """Handle new MQTT messages."""
- # Cancel the previous timeout task if it exists
- if self._timeout_task:
- self._timeout_task.cancel()
-
- # Parse the incoming message
- msg_json = json.loads(msg.payload)
-
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
-
- # Extract the EVENT field
- event = msg_json.get('event')
-
- if event is None:
- _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
- return
-
- # Use the mapping to convert the event to the corresponding state
- new_state = self._mapping.get(event)
- if new_state is not None:
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
- self._state = new_state
- self._last_event = new_state # Update the last event
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
-
- # Extract the 'value1' and 'value2' fields
- value1 = msg_json.get('value1')
-
- # Parse 'value1' as a datetime
- if value1:
- timestamp = int(value1) / 1000.0
- self._time = datetime.fromtimestamp(timestamp)
- self._value1 = value1
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
-
- # Extract the 'value2' field
- value2 = msg_json.get('value2')
-
- # Store 'value2' as the message if it exists
- self._value2 = value2 if value2 else "None"
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
-
- self.async_schedule_update_ha_state()
-
- # Create a new timeout task
- self._timeout_task = asyncio.create_task(self.timeout())
-
- # Subscribe to the topic from the user input
- await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- # Save the current state to the state machine
- self._hass.states.async_set(self.entity_id, self._state)
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
-
- async def timeout(self):
- """Set the state to 'None' after a timeout."""
- await asyncio.sleep(15)
- self._state = "None"
- self._last_event = "None"
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
- self.async_schedule_update_ha_state()
-
-class SAASSleepTrackingSensor(RestoreEntity):
- """Representation of a SAAS - Sleep As Android Stats sensor for Sleep Tracking."""
- def __init__(self, hass, name, mapping, entry_id):
- """Initialize the sensor."""
- self._state = None
- self._name = name
- self._hass = hass
- self._mapping = mapping
- self.entry_id = entry_id
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- return f"saas_sleep_tracking_sensor_{self._name}"
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return f"SAAS {self._name} Sleep Tracking"
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- async def async_added_to_hass(self):
- """Run when entity about to be added."""
- await super().async_added_to_hass()
-
- # Load the previous state from the state machine
- state = await self.async_get_last_state()
- if state:
- self._state = state.state
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
-
- async def message_received(msg):
- """Handle new MQTT messages."""
- # Parse the incoming message
- msg_json = json.loads(msg.payload)
-
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
-
- # Extract the EVENT field
- event = msg_json.get('event')
-
- if event is None:
- _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
- return
-
- # Use the mapping to convert the event to the corresponding state
- new_state = self._mapping.get(event) # Removed default to "None"
- if new_state is not None: # Only update state if a mapping is found
- self._state = new_state
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
- self.async_schedule_update_ha_state()
-
- # Subscribe to the topic from the user input
- await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- # Save the current state to the state machine
- self._hass.states.async_set(self.entity_id, self._state)
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
-
-class SAASDisturbanceSensor(RestoreEntity):
- """Representation of a SAAS - Sleep As Android Stats sensor for Disturbance Events."""
-
- def __init__(self, hass, name, mapping, entry_id):
- """Initialize the sensor."""
- self._state = None
- self._name = name
- self._hass = hass
- self._mapping = mapping
- self._value1 = None
- self._value2 = None
- self._time = None
- self.entry_id = entry_id
- self._last_event = None
- self._timeout_task = None
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- return f"saas_disturbance_sensor_{self._name}"
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return f"SAAS {self._name} Disturbance"
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- @property
- def extra_state_attributes(self):
- """Return the extra state attributes."""
- return {
- "Last Event": self._last_event,
- "Timestamp": self._value1 if self._value1 else "No timestamp received",
- "Time": self._time.strftime('%H:%M') if self._time else "No time received",
- "Date": self._time.strftime('%m/%d/%Y') if self._time else "No date received",
- }
-
- async def async_added_to_hass(self):
- """Run when entity about to be added."""
- await super().async_added_to_hass()
-
- # Load the previous state from the state machine
- state = await self.async_get_last_state()
- if state:
- self._state = state.state
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
-
- # Start the timeout task as soon as the sensor is loaded
- self._timeout_task = asyncio.create_task(self.timeout())
-
- async def message_received(msg):
- """Handle new MQTT messages."""
- # Cancel the previous timeout task if it exists
- if self._timeout_task:
- self._timeout_task.cancel()
-
- # Parse the incoming message
- msg_json = json.loads(msg.payload)
-
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
-
- # Extract the EVENT field
- event = msg_json.get('event')
-
- if event is None:
- _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
- return
-
- # Use the mapping to convert the event to the corresponding state
- new_state = self._mapping.get(event)
- if new_state is not None:
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
- self._state = new_state
- self._last_event = new_state # Update the last event
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
-
- # Extract the 'value1' and 'value2' fields
- value1 = msg_json.get('value1')
-
- # Parse 'value1' as a datetime
- if value1:
- timestamp = int(value1) / 1000.0
- self._time = datetime.fromtimestamp(timestamp)
- self._value1 = value1
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
-
- # Extract the 'value2' field
- value2 = msg_json.get('value2')
-
- # Store 'value2' as the message if it exists
- self._value2 = value2 if value2 else "None"
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
-
- self.async_schedule_update_ha_state()
-
- # Create a new timeout task
- self._timeout_task = asyncio.create_task(self.timeout())
-
- # Subscribe to the topic from the user input
- await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- # Save the current state to the state machine
- self._hass.states.async_set(self.entity_id, self._state)
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
-
- async def timeout(self):
- """Set the state to 'None' after a timeout."""
- await asyncio.sleep(15)
- self._state = "None"
- self._last_event = "None"
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
- self.async_schedule_update_ha_state()
-
-class SAASLullabySensor(RestoreEntity):
- """Representation of a SAAS - Sleep As Android Stats sensor for Lullaby."""
- def __init__(self, hass, name, mapping, entry_id):
- """Initialize the sensor."""
- self._state = None
- self._name = name
- self._hass = hass
- self._mapping = mapping
- self.entry_id = entry_id
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- return f"saas_lullaby_sensor_{self._name}"
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return f"SAAS {self._name} Lullaby"
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- async def async_added_to_hass(self):
- """Run when entity about to be added."""
- await super().async_added_to_hass()
-
- # Load the previous state from the state machine
- state = await self.async_get_last_state()
- if state:
- self._state = state.state
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
-
- async def message_received(msg):
- """Handle new MQTT messages."""
- # Parse the incoming message
- msg_json = json.loads(msg.payload)
-
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
-
- # Extract the EVENT field
- event = msg_json.get('event')
-
- if event is None:
- _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
- return
-
- # Use the mapping to convert the event to the corresponding state
- new_state = self._mapping.get(event, "None") # Default to "None" if no mapping found
- self._state = new_state
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
- self.async_schedule_update_ha_state()
-
- # Subscribe to the topic from the user input
- await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- # Save the current state to the state machine
- self._hass.states.async_set(self.entity_id, self._state)
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
-
-class SAASSleepStage(RestoreEntity):
- """Representation of a SAAS - Sleep As Android Stats sensor for Sleep Stage."""
- def __init__(self, hass, name, mapping, entry_id):
- """Initialize the sensor."""
- self._state = None
- self._name = name
- self._hass = hass
- self._mapping = mapping
- self.entry_id = entry_id
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- return f"saas_sleep_stage_sensor_{self._name}"
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return f"SAAS {self._name} Sleep Stage"
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- async def async_added_to_hass(self):
- """Run when entity about to be added."""
- await super().async_added_to_hass()
-
- # Load the previous state from the state machine
- state = await self.async_get_last_state()
- if state:
- self._state = state.state
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
-
- async def message_received(msg):
- """Handle new MQTT messages."""
- # Parse the incoming message
- msg_json = json.loads(msg.payload)
-
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
-
- # Extract the EVENT field
- event = msg_json.get('event')
-
- if event is None:
- _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
- return
-
- # Use the mapping to convert the event to the corresponding state
- new_state = self._mapping.get(event, "None") # Default to "None" if no mapping found
- self._state = new_state
- _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
- self.async_schedule_update_ha_state()
-
- # Subscribe to the topic from the user input
- await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- # Save the current state to the state machine
- self._hass.states.async_set(self.entity_id, self._state)
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
-
-class SAASWakeStatusSensor(RestoreEntity):
- def __init__(self, hass, name, awake_states, sleep_states, awake_duration, sleep_duration, mqtt_topic, entry_id):
- self._state = None
- self._name = name
- self.awake_duration = timedelta(seconds=awake_duration)
- self.sleep_duration = timedelta(seconds=sleep_duration)
- self.awake_states = awake_states
- self.sleep_states = sleep_states
- self.hass = hass
- self.mqtt_topic = mqtt_topic
- self.entry_id = entry_id
- self.awake_timer = None
- self.sleep_timer = None
-
- @property
- def unique_id(self):
- """Return a unique ID."""
- return f"saas_wake_status_{self._name}"
-
- @property
- def name(self):
- """Return the name of the sensor."""
- return f"SAAS {self._name} Wake Status"
-
- @property
- def state(self):
- """Return the state of the sensor."""
- return self._state
-
- @property
- def device_info(self):
- """Return information about the device."""
- return {
- "identifiers": {(DOMAIN, self._name)},
- "name": self._name,
- "manufacturer": INTEGRATION_NAME,
- "model": MODEL,
- }
-
- def process_message(self, message):
- try:
- now = dt_util.utcnow() # Define 'now' before using it for logging
-
- # Extract the 'event' from the incoming message
- event = message.get('event')
- _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Extracted Event {event} from message.")
-
- # Map the event to a known state, or "Unknown" if the event is not recognized
- mapped_value = STATE_MAPPING.get(event, "Unknown")
- _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {mapped_value}.")
-
- # If the event could not be mapped to a known state, set the sensor state to "Unknown"
- if mapped_value == "Unknown":
- self._state = "Unknown"
- _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Event {event} could not be mapped to a known state. Setting sensor state to 'Unknown'.")
-
- # If the mapped value is in the awake states, start or restart the awake timer and cancel the sleep timer
- if mapped_value in self.awake_states:
- if self.awake_timer:
- self.awake_timer.cancel()
- self.awake_timer = self.hass.loop.call_later(self.awake_duration.total_seconds(), self.set_state, "Awake")
- if self.sleep_timer:
- self.sleep_timer.cancel()
- self.sleep_timer = None
- _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped value {mapped_value} is in awake states. Starting or restarting awake timer and cancelling sleep timer.")
-
- # If the mapped value is in the sleep states, start or restart the sleep timer and cancel the awake timer
- elif mapped_value in self.sleep_states:
- if self.sleep_timer:
- self.sleep_timer.cancel()
- self.sleep_timer = self.hass.loop.call_later(self.sleep_duration.total_seconds(), self.set_state, "Asleep")
- if self.awake_timer:
- self.awake_timer.cancel()
- self.awake_timer = None
- _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped value {mapped_value} is in sleep states. Starting or restarting sleep timer and cancelling awake timer.")
-
- except Exception as e:
- _LOGGER.error(f"Error processing message: {e}")
-
- def set_state(self, state):
- self._state = state
- self.async_schedule_update_ha_state()
-
- async def async_added_to_hass(self):
- """Run when entity about to be added."""
- await super().async_added_to_hass()
-
- # Load the previous state from the state machine
- state = await self.async_get_last_state()
- if state:
- self._state = state.state
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
-
- # Subscribe to the MQTT topic to receive messages
- await mqtt.async_subscribe(
- self.hass,
- self.mqtt_topic,
- lambda message: self.process_message(json.loads(message.payload))
- )
-
- async def async_will_remove_from_hass(self):
- """Run when entity will be removed from hass."""
- # Save the current state to the state machine
- self.hass.states.async_set(self.entity_id, self._state)
- _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
-
-async def async_setup_entry(hass, entry, async_add_entities):
- """Set up the SAAS sensor platform from a config entry."""
- name = entry.data.get(CONF_NAME, "Default Name")
- topic = entry.data.get(CONF_TOPIC)
- awake_states = entry.data.get(CONF_AWAKE_STATES)
- sleep_states = entry.data.get(CONF_SLEEP_STATES)
- awake_duration = entry.data.get(CONF_AWAKE_DURATION)
- sleep_duration = entry.data.get(CONF_SLEEP_DURATION)
- entry_id = entry.entry_id
- hass.data[DOMAIN][entry.entry_id] = entry.data
-
- entities = [
- SAASSensor(hass, name, STATE_MAPPING, entry_id),
- SAASAlarmEventSensor(hass, name, ALARM_EVENT_MAPPING, entry_id),
- SAASNextAlarmSensor(hass, name, entry_id),
- SAASSoundSensor(hass, name, SOUND_MAPPING, entry_id),
- SAASSleepTrackingSensor(hass, name, SLEEP_TRACKING_MAPPING, entry_id),
- SAASDisturbanceSensor(hass, name, DISTURBANCE_MAPPING, entry_id),
- SAASLullabySensor(hass, name, LULLABY_MAPPING, entry_id),
- SAASSleepStage(hass, name, SLEEP_STAGE_MAPPING, entry_id),
- SAASWakeStatusSensor(hass, name, awake_states, sleep_states, awake_duration, sleep_duration, topic, entry_id)
- ]
-
- for entity in entities:
- if hasattr(entity, "async_setup"):
- await entity.async_setup()
-
+import asyncio, json, logging, time, inspect, pytz
+from datetime import timedelta, datetime, timezone
+from collections import deque
+from homeassistant.helpers.event import async_track_time_interval, async_call_later
+from homeassistant.helpers.dispatcher import async_dispatcher_connect
+from homeassistant.helpers.restore_state import RestoreEntity
+from homeassistant.components.mqtt import async_subscribe
+from homeassistant.helpers.entity import Entity
+from homeassistant.util import dt as dt_util
+from homeassistant.components import mqtt
+from .const import DOMAIN, CONF_NAME, CONF_TOPIC, CONF_AWAKE_STATES, CONF_SLEEP_STATES, CONF_AWAKE_DURATION, CONF_SLEEP_DURATION, INTEGRATION_NAME, MODEL, STATE_MAPPING, SOUND_MAPPING, DISTURBANCE_MAPPING, ALARM_EVENT_MAPPING, SLEEP_TRACKING_MAPPING, LULLABY_MAPPING, REVERSE_STATE_MAPPING, SLEEP_STAGE_MAPPING
+
+_LOGGER = logging.getLogger(__name__)
+_LOGGER.setLevel(logging.DEBUG)
+
+class sleepdSensor(RestoreEntity):
+ """Representation of a sleepd - Sleep As Android Stats sensor."""
+
+ def __init__(self, hass, name, mapping, entry_id):
+ """Initialize the sensor."""
+ self._state = None
+ self._name = name
+ self._hass = hass
+ self._mapping = mapping
+ self.entry_id = entry_id
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ return f"sleepd_sensor_{self._name}"
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return f"sleepd {self._name} State"
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ return {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+
+ async def async_added_to_hass(self):
+ """Run when entity about to be added."""
+ await super().async_added_to_hass()
+
+ # Load the previous state from the state machine
+ state = await self.async_get_last_state()
+ if state:
+ self._state = state.state
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
+
+ async def message_received(msg):
+ """Handle new MQTT messages."""
+ # Parse the incoming message
+ msg_json = json.loads(msg.payload)
+
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json}")
+
+ # Extract the EVENT field
+ event = msg_json.get('event')
+
+ if event is None:
+ _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json}")
+ return
+
+ # Use the mapping to convert the event to the corresponding state
+ new_state = self._mapping.get(event)
+ if new_state is not None:
+ self._state = new_state
+ self.async_schedule_update_ha_state()
+
+ # Subscribe to the topic from the user input
+ await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
+
+ async def async_will_remove_from_hass(self):
+ """Run when entity will be removed from hass."""
+ # Save the current state to the state machine
+ self._hass.states.async_set(self.entity_id, self._state)
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
+
+class sleepdAlarmEventSensor(RestoreEntity):
+ """Representation of a sleepd - Sleep As Android Stats sensor for Alarm Events."""
+
+ def __init__(self, hass, name, mapping, entry_id):
+ """Initialize the sensor."""
+ self._state = None
+ self._name = name
+ self._hass = hass
+ self._mapping = mapping
+ self._value1 = None
+ self._value2 = None
+ self._time = None
+ self.entry_id = entry_id
+ self._last_event = None
+ self._timeout_task = None
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ return f"sleepd_alarm_event_sensor_{self._name}"
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return f"sleepd {self._name} Alarm Event"
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ return {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+
+ @property
+ def extra_state_attributes(self):
+ """Return the extra state attributes."""
+ if self._state is not None:
+ return {
+ "Last Event": self._last_event,
+ "Message": self._value2 if self._value2 else "No message received",
+ "Timestamp": self._value1 if self._value1 else "No timestamp received",
+ "Time": self._time.strftime('%H:%M') if self._time else "No time received",
+ "Date": self._time.strftime('%m/%d/%Y') if self._time else "No date received",
+ }
+ return {}
+
+ async def async_added_to_hass(self):
+ """Run when entity about to be added."""
+ await super().async_added_to_hass()
+
+ # Load the previous state from the state machine
+ state = await self.async_get_last_state()
+ if state:
+ self._state = state.state
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
+
+ # Start the timeout task as soon as the sensor is loaded
+ self._timeout_task = asyncio.create_task(self.timeout())
+
+ async def message_received(msg):
+ """Handle new MQTT messages."""
+ # Cancel the previous timeout task if it exists
+ if self._timeout_task:
+ self._timeout_task.cancel()
+
+ # Parse the incoming message
+ msg_json = json.loads(msg.payload)
+
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
+
+ # Extract the 'value1' and 'value2' fields
+ value1 = msg_json.get('value1')
+
+ # Parse 'value1' as a datetime
+ if value1:
+ timestamp = int(value1) / 1000.0
+ self._time = datetime.fromtimestamp(timestamp)
+ self._value1 = value1
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
+
+ # Extract the 'value2' field
+ value2 = msg_json.get('value2')
+
+ # Store 'value2' as the message if it exists
+ self._value2 = value2 if value2 else "None"
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
+
+ # Extract the EVENT field
+ event = msg_json.get('event')
+
+ if event is None:
+ _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
+ return
+
+ # Use the mapping to convert the event to the corresponding state
+ new_state = self._mapping.get(event) # Default to "None" if no mapping found
+ if new_state is not None:
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
+ self._state = new_state
+ self._last_event = new_state # Update the last event
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
+ self.async_schedule_update_ha_state()
+
+ # Create a new timeout task
+ self._timeout_task = asyncio.create_task(self.timeout())
+
+ # Subscribe to the topic from the user input
+ await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
+
+ async def async_will_remove_from_hass(self):
+ """Run when entity will be removed from hass."""
+ # Save the current state to the state machine
+ self._hass.states.async_set(self.entity_id, self._state)
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
+
+ async def timeout(self):
+ """Set the state to 'None' after a timeout."""
+ await asyncio.sleep(15)
+ self._state = "None"
+ self._last_event = "None"
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
+ self.async_schedule_update_ha_state()
+
+class sleepdSoundSensor(RestoreEntity):
+ """Representation of a sleepd - Sleep As Android Stats sensor for Sound Events."""
+
+ def __init__(self, hass, name, mapping, entry_id):
+ """Initialize the sensor."""
+ self._state = None
+ self._name = name
+ self._hass = hass
+ self._mapping = mapping
+ self._value1 = None
+ self._value2 = None
+ self._time = None
+ self.entry_id = entry_id
+ self._last_event = None
+ self._timeout_task = None
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ return f"sleepd_sound_sensor_{self._name}"
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return f"sleepd {self._name} Sound"
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ return {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+
+ @property
+ def extra_state_attributes(self):
+ """Return the extra state attributes."""
+ return {
+ "Last Event": self._last_event,
+ "Timestamp": self._value1 if self._value1 else "No timestamp received",
+ "Time": self._time.strftime('%H:%M') if self._time else "No time received",
+ "Date": self._time.strftime('%m/%d/%Y') if self._time else "No date received",
+ }
+
+ async def async_added_to_hass(self):
+ """Run when entity about to be added."""
+ await super().async_added_to_hass()
+
+ # Load the previous state from the state machine
+ state = await self.async_get_last_state()
+ if state:
+ self._state = state.state
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
+
+ # Start the timeout task as soon as the sensor is loaded
+ self._timeout_task = asyncio.create_task(self.timeout())
+
+ async def message_received(msg):
+ """Handle new MQTT messages."""
+ # Cancel the previous timeout task if it exists
+ if self._timeout_task:
+ self._timeout_task.cancel()
+
+ # Parse the incoming message
+ msg_json = json.loads(msg.payload)
+
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
+
+ # Extract the EVENT field
+ event = msg_json.get('event')
+
+ if event is None:
+ _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
+ return
+
+ # Use the mapping to convert the event to the corresponding state
+ new_state = self._mapping.get(event)
+ if new_state is not None:
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
+ self._state = new_state
+ self._last_event = new_state # Update the last event
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
+
+ # Extract the 'value1' and 'value2' fields
+ value1 = msg_json.get('value1')
+
+ # Parse 'value1' as a datetime
+ if value1:
+ timestamp = int(value1) / 1000.0
+ self._time = datetime.fromtimestamp(timestamp)
+ self._value1 = value1
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
+
+ # Extract the 'value2' field
+ value2 = msg_json.get('value2')
+
+ # Store 'value2' as the message if it exists
+ self._value2 = value2 if value2 else "None"
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
+
+ self.async_schedule_update_ha_state()
+
+ # Create a new timeout task
+ self._timeout_task = asyncio.create_task(self.timeout())
+
+ # Subscribe to the topic from the user input
+ await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
+
+ async def async_will_remove_from_hass(self):
+ """Run when entity will be removed from hass."""
+ # Save the current state to the state machine
+ self._hass.states.async_set(self.entity_id, self._state)
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
+
+ async def timeout(self):
+ """Set the state to 'None' after a timeout."""
+ await asyncio.sleep(15)
+ self._state = "None"
+ self._last_event = "None"
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
+ self.async_schedule_update_ha_state()
+
+class sleepdSleepTrackingSensor(RestoreEntity):
+ """Representation of a sleepd - Sleep As Android Stats sensor for Sleep Tracking."""
+ def __init__(self, hass, name, mapping, entry_id):
+ """Initialize the sensor."""
+ self._state = None
+ self._name = name
+ self._hass = hass
+ self._mapping = mapping
+ self.entry_id = entry_id
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ return f"sleepd_sleep_tracking_sensor_{self._name}"
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return f"sleepd {self._name} Sleep Tracking"
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ return {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+
+ async def async_added_to_hass(self):
+ """Run when entity about to be added."""
+ await super().async_added_to_hass()
+
+ # Load the previous state from the state machine
+ state = await self.async_get_last_state()
+ if state:
+ self._state = state.state
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
+
+ async def message_received(msg):
+ """Handle new MQTT messages."""
+ # Parse the incoming message
+ msg_json = json.loads(msg.payload)
+
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
+
+ # Extract the EVENT field
+ event = msg_json.get('event')
+
+ if event is None:
+ _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
+ return
+
+ # Use the mapping to convert the event to the corresponding state
+ new_state = self._mapping.get(event) # Removed default to "None"
+ if new_state is not None: # Only update state if a mapping is found
+ self._state = new_state
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
+ self.async_schedule_update_ha_state()
+
+ # Subscribe to the topic from the user input
+ await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
+
+ async def async_will_remove_from_hass(self):
+ """Run when entity will be removed from hass."""
+ # Save the current state to the state machine
+ self._hass.states.async_set(self.entity_id, self._state)
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
+
+class sleepdDisturbanceSensor(RestoreEntity):
+ """Representation of a sleepd - Sleep As Android Stats sensor for Disturbance Events."""
+
+ def __init__(self, hass, name, mapping, entry_id):
+ """Initialize the sensor."""
+ self._state = None
+ self._name = name
+ self._hass = hass
+ self._mapping = mapping
+ self._value1 = None
+ self._value2 = None
+ self._time = None
+ self.entry_id = entry_id
+ self._last_event = None
+ self._timeout_task = None
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ return f"sleepd_disturbance_sensor_{self._name}"
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return f"sleepd {self._name} Disturbance"
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ return {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+
+ @property
+ def extra_state_attributes(self):
+ """Return the extra state attributes."""
+ return {
+ "Last Event": self._last_event,
+ "Timestamp": self._value1 if self._value1 else "No timestamp received",
+ "Time": self._time.strftime('%H:%M') if self._time else "No time received",
+ "Date": self._time.strftime('%m/%d/%Y') if self._time else "No date received",
+ }
+
+ async def async_added_to_hass(self):
+ """Run when entity about to be added."""
+ await super().async_added_to_hass()
+
+ # Load the previous state from the state machine
+ state = await self.async_get_last_state()
+ if state:
+ self._state = state.state
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
+
+ # Start the timeout task as soon as the sensor is loaded
+ self._timeout_task = asyncio.create_task(self.timeout())
+
+ async def message_received(msg):
+ """Handle new MQTT messages."""
+ # Cancel the previous timeout task if it exists
+ if self._timeout_task:
+ self._timeout_task.cancel()
+
+ # Parse the incoming message
+ msg_json = json.loads(msg.payload)
+
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
+
+ # Extract the EVENT field
+ event = msg_json.get('event')
+
+ if event is None:
+ _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
+ return
+
+ # Use the mapping to convert the event to the corresponding state
+ new_state = self._mapping.get(event)
+ if new_state is not None:
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
+ self._state = new_state
+ self._last_event = new_state # Update the last event
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
+
+ # Extract the 'value1' and 'value2' fields
+ value1 = msg_json.get('value1')
+
+ # Parse 'value1' as a datetime
+ if value1:
+ timestamp = int(value1) / 1000.0
+ self._time = datetime.fromtimestamp(timestamp)
+ self._value1 = value1
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
+
+ # Extract the 'value2' field
+ value2 = msg_json.get('value2')
+
+ # Store 'value2' as the message if it exists
+ self._value2 = value2 if value2 else "None"
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
+
+ self.async_schedule_update_ha_state()
+
+ # Create a new timeout task
+ self._timeout_task = asyncio.create_task(self.timeout())
+
+ # Subscribe to the topic from the user input
+ await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
+
+ async def async_will_remove_from_hass(self):
+ """Run when entity will be removed from hass."""
+ # Save the current state to the state machine
+ self._hass.states.async_set(self.entity_id, self._state)
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
+
+ async def timeout(self):
+ """Set the state to 'None' after a timeout."""
+ await asyncio.sleep(15)
+ self._state = "None"
+ self._last_event = "None"
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
+ self.async_schedule_update_ha_state()
+
+class sleepdLullabySensor(RestoreEntity):
+ """Representation of a sleepd - Sleep As Android Stats sensor for Lullaby."""
+ def __init__(self, hass, name, mapping, entry_id):
+ """Initialize the sensor."""
+ self._state = None
+ self._name = name
+ self._hass = hass
+ self._mapping = mapping
+ self.entry_id = entry_id
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ return f"sleepd_lullaby_sensor_{self._name}"
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return f"sleepd {self._name} Lullaby"
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ return {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+
+ async def async_added_to_hass(self):
+ """Run when entity about to be added."""
+ await super().async_added_to_hass()
+
+ # Load the previous state from the state machine
+ state = await self.async_get_last_state()
+ if state:
+ self._state = state.state
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
+
+ async def message_received(msg):
+ """Handle new MQTT messages."""
+ # Parse the incoming message
+ msg_json = json.loads(msg.payload)
+
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
+
+ # Extract the EVENT field
+ event = msg_json.get('event')
+
+ if event is None:
+ _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
+ return
+
+ # Use the mapping to convert the event to the corresponding state
+ new_state = self._mapping.get(event, "None") # Default to "None" if no mapping found
+ self._state = new_state
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
+ self.async_schedule_update_ha_state()
+
+ # Subscribe to the topic from the user input
+ await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
+
+ async def async_will_remove_from_hass(self):
+ """Run when entity will be removed from hass."""
+ # Save the current state to the state machine
+ self._hass.states.async_set(self.entity_id, self._state)
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
+
+class sleepdSleepStage(RestoreEntity):
+ """Representation of a sleepd - Sleep As Android Stats sensor for Sleep Stage."""
+ def __init__(self, hass, name, mapping, entry_id):
+ """Initialize the sensor."""
+ self._state = None
+ self._name = name
+ self._hass = hass
+ self._mapping = mapping
+ self.entry_id = entry_id
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ return f"sleepd_sleep_stage_sensor_{self._name}"
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return f"sleepd {self._name} Sleep Stage"
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ return {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+
+ async def async_added_to_hass(self):
+ """Run when entity about to be added."""
+ await super().async_added_to_hass()
+
+ # Load the previous state from the state machine
+ state = await self.async_get_last_state()
+ if state:
+ self._state = state.state
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
+
+ async def message_received(msg):
+ """Handle new MQTT messages."""
+ # Parse the incoming message
+ msg_json = json.loads(msg.payload)
+
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
+
+ # Extract the EVENT field
+ event = msg_json.get('event')
+
+ if event is None:
+ _LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
+ return
+
+ # Use the mapping to convert the event to the corresponding state
+ new_state = self._mapping.get(event, "None") # Default to "None" if no mapping found
+ self._state = new_state
+ _LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
+ self.async_schedule_update_ha_state()
+
+ # Subscribe to the topic from the user input
+ await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
+
+ async def async_will_remove_from_hass(self):
+ """Run when entity will be removed from hass."""
+ # Save the current state to the state machine
+ self._hass.states.async_set(self.entity_id, self._state)
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
+
+class sleepdWakeStatusSensor(RestoreEntity):
+ def __init__(self, hass, name, awake_states, sleep_states, awake_duration, sleep_duration, mqtt_topic, entry_id):
+ self._state = None
+ self._name = name
+ self.awake_duration = timedelta(seconds=awake_duration)
+ self.sleep_duration = timedelta(seconds=sleep_duration)
+ self.awake_states = awake_states
+ self.sleep_states = sleep_states
+ self.hass = hass
+ self.mqtt_topic = mqtt_topic
+ self.entry_id = entry_id
+ self.awake_timer = None
+ self.sleep_timer = None
+
+ @property
+ def unique_id(self):
+ """Return a unique ID."""
+ return f"sleepd_wake_status_{self._name}"
+
+ @property
+ def name(self):
+ """Return the name of the sensor."""
+ return f"sleepd {self._name} Wake Status"
+
+ @property
+ def state(self):
+ """Return the state of the sensor."""
+ return self._state
+
+ @property
+ def device_info(self):
+ """Return information about the device."""
+ return {
+ "identifiers": {(DOMAIN, self._name)},
+ "name": self._name,
+ "manufacturer": INTEGRATION_NAME,
+ "model": MODEL,
+ }
+
+ def process_message(self, message):
+ try:
+ now = dt_util.utcnow() # Define 'now' before using it for logging
+
+ # Extract the 'event' from the incoming message
+ event = message.get('event')
+ _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Extracted Event {event} from message.")
+
+ # Map the event to a known state, or "Unknown" if the event is not recognized
+ mapped_value = STATE_MAPPING.get(event, "Unknown")
+ _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {mapped_value}.")
+
+ # If the event could not be mapped to a known state, set the sensor state to "Unknown"
+ if mapped_value == "Unknown":
+ self._state = "Unknown"
+ _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Event {event} could not be mapped to a known state. Setting sensor state to 'Unknown'.")
+
+ # If the mapped value is in the awake states, start or restart the awake timer and cancel the sleep timer
+ if mapped_value in self.awake_states:
+ if self.awake_timer:
+ self.awake_timer.cancel()
+ self.awake_timer = self.hass.loop.call_later(self.awake_duration.total_seconds(), self.set_state, "Awake")
+ if self.sleep_timer:
+ self.sleep_timer.cancel()
+ self.sleep_timer = None
+ _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped value {mapped_value} is in awake states. Starting or restarting awake timer and cancelling sleep timer.")
+
+ # If the mapped value is in the sleep states, start or restart the sleep timer and cancel the awake timer
+ elif mapped_value in self.sleep_states:
+ if self.sleep_timer:
+ self.sleep_timer.cancel()
+ self.sleep_timer = self.hass.loop.call_later(self.sleep_duration.total_seconds(), self.set_state, "Asleep")
+ if self.awake_timer:
+ self.awake_timer.cancel()
+ self.awake_timer = None
+ _LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped value {mapped_value} is in sleep states. Starting or restarting sleep timer and cancelling awake timer.")
+
+ except Exception as e:
+ _LOGGER.error(f"Error processing message: {e}")
+
+ def set_state(self, state):
+ self._state = state
+ self.async_schedule_update_ha_state()
+
+ async def async_added_to_hass(self):
+ """Run when entity about to be added."""
+ await super().async_added_to_hass()
+
+ # Load the previous state from the state machine
+ state = await self.async_get_last_state()
+ if state:
+ self._state = state.state
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
+
+ # Subscribe to the MQTT topic to receive messages
+ await mqtt.async_subscribe(
+ self.hass,
+ self.mqtt_topic,
+ lambda message: self.process_message(json.loads(message.payload))
+ )
+
+ async def async_will_remove_from_hass(self):
+ """Run when entity will be removed from hass."""
+ # Save the current state to the state machine
+ self.hass.states.async_set(self.entity_id, self._state)
+ _LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
+
+async def async_setup_entry(hass, entry, async_add_entities):
+ """Set up the sleepd sensor platform from a config entry."""
+ name = entry.data.get(CONF_NAME, "Default Name")
+ topic = entry.data.get(CONF_TOPIC)
+ awake_states = entry.data.get(CONF_AWAKE_STATES)
+ sleep_states = entry.data.get(CONF_SLEEP_STATES)
+ awake_duration = entry.data.get(CONF_AWAKE_DURATION)
+ sleep_duration = entry.data.get(CONF_SLEEP_DURATION)
+ entry_id = entry.entry_id
+ hass.data[DOMAIN][entry.entry_id] = entry.data
+
+ entities = [
+ sleepdSensor(hass, name, STATE_MAPPING, entry_id),
+ sleepdAlarmEventSensor(hass, name, ALARM_EVENT_MAPPING, entry_id),
+ sleepdSoundSensor(hass, name, SOUND_MAPPING, entry_id),
+ sleepdSleepTrackingSensor(hass, name, SLEEP_TRACKING_MAPPING, entry_id),
+ sleepdDisturbanceSensor(hass, name, DISTURBANCE_MAPPING, entry_id),
+ sleepdLullabySensor(hass, name, LULLABY_MAPPING, entry_id),
+ sleepdSleepStage(hass, name, SLEEP_STAGE_MAPPING, entry_id),
+ sleepdWakeStatusSensor(hass, name, awake_states, sleep_states, awake_duration, sleep_duration, topic, entry_id)
+ ]
+
+ for entity in entities:
+ if hasattr(entity, "async_setup"):
+ await entity.async_setup()
+
async_add_entities(entities)
\ No newline at end of file
diff --git a/custom_components/saas/services.py b/custom_components/sleepd/services.py
similarity index 85%
rename from custom_components/saas/services.py
rename to custom_components/sleepd/services.py
index d61ad18..7a89336 100644
--- a/custom_components/saas/services.py
+++ b/custom_components/sleepd/services.py
@@ -1,73 +1,73 @@
-import logging
-from homeassistant.core import ServiceCall, HomeAssistant
-from .const import DOMAIN, DAY_MAPPING
-
-_LOGGER = logging.getLogger(__name__)
-
-class SAASService:
- def __init__(self, hass, name, notify_target):
- self._hass = hass
- self._name = name
- self._notify_target = notify_target
- _LOGGER.debug(f"SAASService initialized with name: {name}, notify_target: {notify_target}")
-
- async def call_service(self, service_call: ServiceCall):
- """Call the service."""
- service_name = self._notify_target # Remove the "notify." prefix
-
- # Extract parameters with default values
- params = ['message', 'day', 'hour', 'minute']
- defaults = ['Default Message', 'monday', 0, 0]
- message, day, hour, minute = (service_call.data.get(param, default) for param, default in zip(params, defaults))
-
- _LOGGER.debug(f"Extracted parameters from service call: message: {message}, day: {day}, hour: {hour}, minute: {minute}")
-
- # Convert day name to number
- day_number = DAY_MAPPING.get(day.lower(), day)
-
- _LOGGER.debug(f"Converted day name to number: {day_number}")
-
- _LOGGER.info(f"Service called with message: {message}, day: {day_number}, hours: {hour}, minutes: {minute}")
-
- service_data = {
- "message": "command_activity",
- "data": {
- "intent_action": "android.intent.action.SET_ALARM",
- "intent_extras": f"android.intent.extra.alarm.SKIP_UI:true,android.intent.extra.alarm.MESSAGE:{message},android.intent.extra.alarm.DAYS:{day_number}:ArrayList,android.intent.extra.alarm.HOUR:{hour},android.intent.extra.alarm.MINUTES:{minute}"
- },
- }
-
- _LOGGER.debug(f"Prepared service data: {service_data}")
-
- try:
- await self._hass.services.async_call(
- "notify",
- service_name,
- service_data,
- blocking=True,
- )
- _LOGGER.info(f"Service call completed")
- except Exception as e:
- _LOGGER.error(f"Error occurred while calling service: {e}")
-
-async def async_setup_services(hass: HomeAssistant) -> None:
- """Set up services for the SAAS component."""
- _LOGGER.info(f"Setting up services for {DOMAIN}")
- # Register the service for each entry
- for entry_id, entry_data in hass.data.get(DOMAIN, {}).items():
- if entry_data:
- name = entry_data.get('name', 'default name')
- notify_target = entry_data.get('notify_target', 'default notify target')
- if notify_target: # Only register the service if notify_target was chosen
- _LOGGER.debug(f"Found notify_target: {notify_target} for name: {name}. Registering service.")
- saas_service = SAASService(hass, name, notify_target)
- try:
- hass.services.async_register(DOMAIN, f'saas_{name}_alarm_set', saas_service.call_service)
- _LOGGER.info(f"Registered service: saas_{name}_alarm_set")
- except Exception as e:
- _LOGGER.error(f"Error occurred while registering service: {e}")
- else:
- _LOGGER.warning(f"No notify_target found for name: {name}. Skipping service registration.")
- else:
- _LOGGER.warning(f"No entry data found for entry_id: {entry_id}")
+import logging
+from homeassistant.core import ServiceCall, HomeAssistant
+from .const import DOMAIN, DAY_MAPPING
+
+_LOGGER = logging.getLogger(__name__)
+
+class sleepdService:
+ def __init__(self, hass, name, notify_target):
+ self._hass = hass
+ self._name = name
+ self._notify_target = notify_target
+ _LOGGER.debug(f"sleepdService initialized with name: {name}, notify_target: {notify_target}")
+
+ async def call_service(self, service_call: ServiceCall):
+ """Call the service."""
+ service_name = self._notify_target # Remove the "notify." prefix
+
+ # Extract parameters with default values
+ params = ['message', 'day', 'hour', 'minute']
+ defaults = ['Default Message', 'monday', 0, 0]
+ message, day, hour, minute = (service_call.data.get(param, default) for param, default in zip(params, defaults))
+
+ _LOGGER.debug(f"Extracted parameters from service call: message: {message}, day: {day}, hour: {hour}, minute: {minute}")
+
+ # Convert day name to number
+ day_number = DAY_MAPPING.get(day.lower(), day)
+
+ _LOGGER.debug(f"Converted day name to number: {day_number}")
+
+ _LOGGER.info(f"Service called with message: {message}, day: {day_number}, hours: {hour}, minutes: {minute}")
+
+ service_data = {
+ "message": "command_activity",
+ "data": {
+ "intent_action": "android.intent.action.SET_ALARM",
+ "intent_extras": f"android.intent.extra.alarm.SKIP_UI:true,android.intent.extra.alarm.MESSAGE:{message},android.intent.extra.alarm.DAYS:{day_number}:ArrayList,android.intent.extra.alarm.HOUR:{hour},android.intent.extra.alarm.MINUTES:{minute}"
+ },
+ }
+
+ _LOGGER.debug(f"Prepared service data: {service_data}")
+
+ try:
+ await self._hass.services.async_call(
+ "notify",
+ service_name,
+ service_data,
+ blocking=True,
+ )
+ _LOGGER.info(f"Service call completed")
+ except Exception as e:
+ _LOGGER.error(f"Error occurred while calling service: {e}")
+
+async def async_setup_services(hass: HomeAssistant) -> None:
+ """Set up services for the sleepd component."""
+ _LOGGER.info(f"Setting up services for {DOMAIN}")
+ # Register the service for each entry
+ for entry_id, entry_data in hass.data.get(DOMAIN, {}).items():
+ if entry_data:
+ name = entry_data.get('name', 'default name')
+ notify_target = entry_data.get('notify_target', 'default notify target')
+ if notify_target: # Only register the service if notify_target was chosen
+ _LOGGER.debug(f"Found notify_target: {notify_target} for name: {name}. Registering service.")
+ sleepd_service = sleepdService(hass, name, notify_target)
+ try:
+ hass.services.async_register(DOMAIN, f'sleepd_{name}_alarm_set', sleepd_service.call_service)
+ _LOGGER.info(f"Registered service: sleepd_{name}_alarm_set")
+ except Exception as e:
+ _LOGGER.error(f"Error occurred while registering service: {e}")
+ else:
+ _LOGGER.warning(f"No notify_target found for name: {name}. Skipping service registration.")
+ else:
+ _LOGGER.warning(f"No entry data found for entry_id: {entry_id}")
_LOGGER.info(f"Finished setting up services for {DOMAIN}")
\ No newline at end of file
diff --git a/custom_components/saas/services.yaml b/custom_components/sleepd/services.yaml
similarity index 100%
rename from custom_components/saas/services.yaml
rename to custom_components/sleepd/services.yaml
diff --git a/custom_components/saas/translations/ar.json b/custom_components/sleepd/translations/ar.json
similarity index 90%
rename from custom_components/saas/translations/ar.json
rename to custom_components/sleepd/translations/ar.json
index 1e3a4a8..95c1766 100644
--- a/custom_components/saas/translations/ar.json
+++ b/custom_components/sleepd/translations/ar.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - حالة Sleep As Android",
- "config": {
- "step": {
- "user": {
- "title": "التكوين لـ SAAS - حالة Sleep As Android",
- "description": "تكوين الإعدادات الأساسية لتكامل SAAS.",
- "data": {
- "name": "الاسم للمستشعر",
- "topic_template": "موضوع MQTT لأحداث Sleep As Android",
- "qos": "جودة الخدمة (QoS) لـ MQTT",
- "awake_duration": "مدة اليقظة",
- "sleep_duration": "مدة النوم",
- "awake_states": "حالات اليقظة*",
- "sleep_states": "حالات النوم*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "إعدادات تكامل SAAS",
- "description": "تكوين الإعدادات الأساسية لتكامل SAAS.",
- "data": {
- "name": "الاسم للمستشعر",
- "topic_template": "موضوع MQTT (من Sleep As Android)",
- "qos": "جودة الخدمة (QoS) لـ MQTT",
- "awake_duration": "مدة اليقظة",
- "sleep_duration": "مدة النوم",
- "awake_states": "حالات اليقظة*",
- "sleep_states": "حالات النوم*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "غير معروف",
- "Sleep Tracking Started": "بدأ تتبع النوم",
- "Sleep Tracking Stopped": "توقف تتبع النوم",
- "Sleep Tracking Paused": "تم إيقاف تتبع النوم مؤقتًا",
- "Sleep Tracking Resumed": "استأنف تتبع النوم",
- "Alarm Snoozed": "تأجيل الإنذار",
- "Snooze Canceled": "تم إلغاء التأجيل",
- "Time for Bed": "وقت النوم",
- "Alarm Alert Started": "بدأ تنبيه الإنذار",
- "Alarm Dismissed": "تم تجاهل الإنذار",
- "Skip Next Alarm": "تخطي الإنذار التالي",
- "Show Skip Next Alarm": "إظهار تخطي الإنذار التالي",
- "REM": "REM",
- "Smart Period": "الفترة الذكية",
- "Before Smart Period": "قبل الفترة الذكية",
- "Lullaby Start": "بداية التهليل",
- "Lullaby Stop": "توقف التهليل",
- "Lullaby Volume Down": "خفض صوت التهليل",
- "Deep Sleep": "نوم عميق",
- "Light Sleep": "نوم خفيف",
- "Awake": "مستيقظ",
- "Not Awake": "غير مستيقظ",
- "Apnea Alarm": "إنذار الأنابيب",
- "Antisnoring": "مضاد للشخير",
- "Before Alarm": "قبل الإنذار",
- "Snore Detected": "تم اكتشاف الشخير",
- "Talk Detected": "تم اكتشاف الكلام",
- "Cough Detected": "تم اكتشاف السعال",
- "Baby Cry Detected": "تم اكتشاف بكاء الطفل",
- "Laugh Detected": "تم اكتشاف الضحك",
- "Alarm Rescheduled": "تم إعادة جدولة الإنذار",
- "None": "لا شيء"
- }
- }
- }
+{
+ "title": "sleepd - حالة Sleep As Android",
+ "config": {
+ "step": {
+ "user": {
+ "title": "التكوين لـ sleepd - حالة Sleep As Android",
+ "description": "تكوين الإعدادات الأساسية لتكامل sleepd.",
+ "data": {
+ "name": "الاسم للمستشعر",
+ "topic_template": "موضوع MQTT لأحداث Sleep As Android",
+ "qos": "جودة الخدمة (QoS) لـ MQTT",
+ "awake_duration": "مدة اليقظة",
+ "sleep_duration": "مدة النوم",
+ "awake_states": "حالات اليقظة*",
+ "sleep_states": "حالات النوم*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "إعدادات تكامل sleepd",
+ "description": "تكوين الإعدادات الأساسية لتكامل sleepd.",
+ "data": {
+ "name": "الاسم للمستشعر",
+ "topic_template": "موضوع MQTT (من Sleep As Android)",
+ "qos": "جودة الخدمة (QoS) لـ MQTT",
+ "awake_duration": "مدة اليقظة",
+ "sleep_duration": "مدة النوم",
+ "awake_states": "حالات اليقظة*",
+ "sleep_states": "حالات النوم*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "غير معروف",
+ "Sleep Tracking Started": "بدأ تتبع النوم",
+ "Sleep Tracking Stopped": "توقف تتبع النوم",
+ "Sleep Tracking Paused": "تم إيقاف تتبع النوم مؤقتًا",
+ "Sleep Tracking Resumed": "استأنف تتبع النوم",
+ "Alarm Snoozed": "تأجيل الإنذار",
+ "Snooze Canceled": "تم إلغاء التأجيل",
+ "Time for Bed": "وقت النوم",
+ "Alarm Alert Started": "بدأ تنبيه الإنذار",
+ "Alarm Dismissed": "تم تجاهل الإنذار",
+ "Skip Next Alarm": "تخطي الإنذار التالي",
+ "Show Skip Next Alarm": "إظهار تخطي الإنذار التالي",
+ "REM": "REM",
+ "Smart Period": "الفترة الذكية",
+ "Before Smart Period": "قبل الفترة الذكية",
+ "Lullaby Start": "بداية التهليل",
+ "Lullaby Stop": "توقف التهليل",
+ "Lullaby Volume Down": "خفض صوت التهليل",
+ "Deep Sleep": "نوم عميق",
+ "Light Sleep": "نوم خفيف",
+ "Awake": "مستيقظ",
+ "Not Awake": "غير مستيقظ",
+ "Apnea Alarm": "إنذار الأنابيب",
+ "Antisnoring": "مضاد للشخير",
+ "Before Alarm": "قبل الإنذار",
+ "Snore Detected": "تم اكتشاف الشخير",
+ "Talk Detected": "تم اكتشاف الكلام",
+ "Cough Detected": "تم اكتشاف السعال",
+ "Baby Cry Detected": "تم اكتشاف بكاء الطفل",
+ "Laugh Detected": "تم اكتشاف الضحك",
+ "Alarm Rescheduled": "تم إعادة جدولة الإنذار",
+ "None": "لا شيء"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/de.json b/custom_components/sleepd/translations/de.json
similarity index 88%
rename from custom_components/saas/translations/de.json
rename to custom_components/sleepd/translations/de.json
index dea54ce..69de9b3 100644
--- a/custom_components/saas/translations/de.json
+++ b/custom_components/sleepd/translations/de.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Sleep As Android Status",
- "config": {
- "step": {
- "user": {
- "title": "Konfiguration für SAAS - Sleep As Android Status",
- "description": "Konfigurieren Sie die grundlegenden Einstellungen für die SAAS-Integration.",
- "data": {
- "name": "Name für Sensor",
- "topic_template": "MQTT-Thema für Sleep As Android Ereignisse",
- "qos": "Quality of Service (QoS) für MQTT",
- "awake_duration": "Wachdauer",
- "sleep_duration": "Schlafdauer",
- "awake_states": "Wachzustände*",
- "sleep_states": "Schlafzustände*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "SAAS-Integrationseinstellungen",
- "description": "Konfigurieren Sie die grundlegenden Einstellungen für die SAAS-Integration.",
- "data": {
- "name": "Name für Sensor",
- "topic_template": "MQTT-Thema (von Sleep As Android)",
- "qos": "MQTT Quality of Service (QoS)",
- "awake_duration": "Wachdauer",
- "sleep_duration": "Schlafdauer",
- "awake_states": "Wachzustände*",
- "sleep_states": "Schlafzustände*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Unbekannt",
- "Sleep Tracking Started": "Schlafüberwachung Gestartet",
- "Sleep Tracking Stopped": "Schlafüberwachung Gestoppt",
- "Sleep Tracking Paused": "Schlafüberwachung Pausiert",
- "Sleep Tracking Resumed": "Schlafüberwachung Fortgesetzt",
- "Alarm Snoozed": "Alarm Snoozed",
- "Snooze Canceled": "Snooze Abgebrochen",
- "Time for Bed": "Zeit fürs Bett",
- "Alarm Alert Started": "Alarmalarm Gestartet",
- "Alarm Dismissed": "Alarm Abgewiesen",
- "Skip Next Alarm": "Nächsten Alarm Überspringen",
- "Show Skip Next Alarm": "Zeige 'Nächsten Alarm Überspringen'",
- "REM": "REM",
- "Smart Period": "Intelligenter Zeitraum",
- "Before Smart Period": "Vor Intelligenter Zeitraum",
- "Lullaby Start": "Wiegenlied Start",
- "Lullaby Stop": "Wiegenlied Stop",
- "Lullaby Volume Down": "Wiegenlied Lautstärke Runter",
- "Deep Sleep": "Tiefschlaf",
- "Light Sleep": "Leichter Schlaf",
- "Awake": "Wach",
- "Not Awake": "Nicht Wach",
- "Apnea Alarm": "Apnoe Alarm",
- "Antisnoring": "Antischnarchen",
- "Before Alarm": "Vor Alarm",
- "Snore Detected": "Schnarchen Erkannt",
- "Talk Detected": "Gespräch Erkannt",
- "Cough Detected": "Husten Erkannt",
- "Baby Cry Detected": "Babyweinen Erkannt",
- "Laugh Detected": "Lachen Erkannt",
- "Alarm Rescheduled": "Alarm Neu Geplant",
- "None": "Keine"
- }
- }
- }
+{
+ "title": "sleepd - Sleep As Android Status",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Konfiguration für sleepd - Sleep As Android Status",
+ "description": "Konfigurieren Sie die grundlegenden Einstellungen für die sleepd-Integration.",
+ "data": {
+ "name": "Name für Sensor",
+ "topic_template": "MQTT-Thema für Sleep As Android Ereignisse",
+ "qos": "Quality of Service (QoS) für MQTT",
+ "awake_duration": "Wachdauer",
+ "sleep_duration": "Schlafdauer",
+ "awake_states": "Wachzustände*",
+ "sleep_states": "Schlafzustände*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "sleepd-Integrationseinstellungen",
+ "description": "Konfigurieren Sie die grundlegenden Einstellungen für die sleepd-Integration.",
+ "data": {
+ "name": "Name für Sensor",
+ "topic_template": "MQTT-Thema (von Sleep As Android)",
+ "qos": "MQTT Quality of Service (QoS)",
+ "awake_duration": "Wachdauer",
+ "sleep_duration": "Schlafdauer",
+ "awake_states": "Wachzustände*",
+ "sleep_states": "Schlafzustände*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Unbekannt",
+ "Sleep Tracking Started": "Schlafüberwachung Gestartet",
+ "Sleep Tracking Stopped": "Schlafüberwachung Gestoppt",
+ "Sleep Tracking Paused": "Schlafüberwachung Pausiert",
+ "Sleep Tracking Resumed": "Schlafüberwachung Fortgesetzt",
+ "Alarm Snoozed": "Alarm Snoozed",
+ "Snooze Canceled": "Snooze Abgebrochen",
+ "Time for Bed": "Zeit fürs Bett",
+ "Alarm Alert Started": "Alarmalarm Gestartet",
+ "Alarm Dismissed": "Alarm Abgewiesen",
+ "Skip Next Alarm": "Nächsten Alarm Überspringen",
+ "Show Skip Next Alarm": "Zeige 'Nächsten Alarm Überspringen'",
+ "REM": "REM",
+ "Smart Period": "Intelligenter Zeitraum",
+ "Before Smart Period": "Vor Intelligenter Zeitraum",
+ "Lullaby Start": "Wiegenlied Start",
+ "Lullaby Stop": "Wiegenlied Stop",
+ "Lullaby Volume Down": "Wiegenlied Lautstärke Runter",
+ "Deep Sleep": "Tiefschlaf",
+ "Light Sleep": "Leichter Schlaf",
+ "Awake": "Wach",
+ "Not Awake": "Nicht Wach",
+ "Apnea Alarm": "Apnoe Alarm",
+ "Antisnoring": "Antischnarchen",
+ "Before Alarm": "Vor Alarm",
+ "Snore Detected": "Schnarchen Erkannt",
+ "Talk Detected": "Gespräch Erkannt",
+ "Cough Detected": "Husten Erkannt",
+ "Baby Cry Detected": "Babyweinen Erkannt",
+ "Laugh Detected": "Lachen Erkannt",
+ "Alarm Rescheduled": "Alarm Neu Geplant",
+ "None": "Keine"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/en.json b/custom_components/sleepd/translations/en.json
similarity index 85%
rename from custom_components/saas/translations/en.json
rename to custom_components/sleepd/translations/en.json
index 630e021..15ca0e8 100644
--- a/custom_components/saas/translations/en.json
+++ b/custom_components/sleepd/translations/en.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Sleep As Android Status",
- "config": {
- "step": {
- "user": {
- "title": "Configuration for SAAS - Sleep As Android Status",
- "description": "Configure the basic settings for the SAAS integration.",
- "data": {
- "name": "Name for Sensor",
- "topic_template": "MQTT Topic for Sleep As Android Events",
- "qos": "Quality of Service (QoS) for MQTT",
- "awake_duration": "Awake Duration",
- "sleep_duration": "Asleep Duration",
- "awake_states": "Awake States*",
- "sleep_states": "Asleep States*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "SAAS Integration Settings",
- "description": "Configure the basic settings for the SAAS integration.",
- "data": {
- "name": "Name for Sensor",
- "topic_template": "MQTT Topic (from Sleep As Android)",
- "qos": "MQTT Quality of Service (QoS)",
- "awake_duration": "Awake Duration",
- "sleep_duration": "Asleep Duration",
- "awake_states": "Awake States*",
- "sleep_states": "Asleep States*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Unknown",
- "Sleep Tracking Started": "Sleep Tracking Started",
- "Sleep Tracking Stopped": "Sleep Tracking Stopped",
- "Sleep Tracking Paused": "Sleep Tracking Paused",
- "Sleep Tracking Resumed": "Sleep Tracking Resumed",
- "Alarm Snoozed": "Alarm Snoozed",
- "Snooze Canceled": "Snooze Canceled",
- "Time for Bed": "Time for Bed",
- "Alarm Alert Started": "Alarm Alert Started",
- "Alarm Dismissed": "Alarm Dismissed",
- "Skip Next Alarm": "Skip Next Alarm",
- "Show Skip Next Alarm": "Show Skip Next Alarm",
- "REM": "REM",
- "Smart Period": "Smart Period",
- "Before Smart Period": "Before Smart Period",
- "Lullaby Start": "Lullaby Start",
- "Lullaby Stop": "Lullaby Stop",
- "Lullaby Volume Down": "Lullaby Volume Down",
- "Deep Sleep": "Deep Sleep",
- "Light Sleep": "Light Sleep",
- "Awake": "Awake",
- "Not Awake": "Not Awake",
- "Apnea Alarm": "Apnea Alarm",
- "Antisnoring": "Antisnoring",
- "Before Alarm": "Before Alarm",
- "Snore Detected": "Snore Detected",
- "Talk Detected": "Talk Detected",
- "Cough Detected": "Cough Detected",
- "Baby Cry Detected": "Baby Cry Detected",
- "Laugh Detected": "Laugh Detected",
- "Alarm Rescheduled": "Alarm Rescheduled",
- "None": "None"
- }
- }
- }
+{
+ "title": "sleepd - Sleep As Android Status",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Configuration for sleepd - Sleep As Android Status",
+ "description": "Configure the basic settings for the sleepd integration.",
+ "data": {
+ "name": "Name for Sensor",
+ "topic_template": "MQTT Topic for Sleep As Android Events",
+ "qos": "Quality of Service (QoS) for MQTT",
+ "awake_duration": "Awake Duration",
+ "sleep_duration": "Asleep Duration",
+ "awake_states": "Awake States*",
+ "sleep_states": "Asleep States*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "sleepd Integration Settings",
+ "description": "Configure the basic settings for the sleepd integration.",
+ "data": {
+ "name": "Name for Sensor",
+ "topic_template": "MQTT Topic (from Sleep As Android)",
+ "qos": "MQTT Quality of Service (QoS)",
+ "awake_duration": "Awake Duration",
+ "sleep_duration": "Asleep Duration",
+ "awake_states": "Awake States*",
+ "sleep_states": "Asleep States*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Unknown",
+ "Sleep Tracking Started": "Sleep Tracking Started",
+ "Sleep Tracking Stopped": "Sleep Tracking Stopped",
+ "Sleep Tracking Paused": "Sleep Tracking Paused",
+ "Sleep Tracking Resumed": "Sleep Tracking Resumed",
+ "Alarm Snoozed": "Alarm Snoozed",
+ "Snooze Canceled": "Snooze Canceled",
+ "Time for Bed": "Time for Bed",
+ "Alarm Alert Started": "Alarm Alert Started",
+ "Alarm Dismissed": "Alarm Dismissed",
+ "Skip Next Alarm": "Skip Next Alarm",
+ "Show Skip Next Alarm": "Show Skip Next Alarm",
+ "REM": "REM",
+ "Smart Period": "Smart Period",
+ "Before Smart Period": "Before Smart Period",
+ "Lullaby Start": "Lullaby Start",
+ "Lullaby Stop": "Lullaby Stop",
+ "Lullaby Volume Down": "Lullaby Volume Down",
+ "Deep Sleep": "Deep Sleep",
+ "Light Sleep": "Light Sleep",
+ "Awake": "Awake",
+ "Not Awake": "Not Awake",
+ "Apnea Alarm": "Apnea Alarm",
+ "Antisnoring": "Antisnoring",
+ "Before Alarm": "Before Alarm",
+ "Snore Detected": "Snore Detected",
+ "Talk Detected": "Talk Detected",
+ "Cough Detected": "Cough Detected",
+ "Baby Cry Detected": "Baby Cry Detected",
+ "Laugh Detected": "Laugh Detected",
+ "Alarm Rescheduled": "Alarm Rescheduled",
+ "None": "None"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/es.json b/custom_components/sleepd/translations/es.json
similarity index 89%
rename from custom_components/saas/translations/es.json
rename to custom_components/sleepd/translations/es.json
index c600e23..fcb2dd0 100644
--- a/custom_components/saas/translations/es.json
+++ b/custom_components/sleepd/translations/es.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Estado de Sleep As Android",
- "config": {
- "step": {
- "user": {
- "title": "Configuración para SAAS - Estado de Sleep As Android",
- "description": "Configura los ajustes básicos para la integración de SAAS.",
- "data": {
- "name": "Nombre para el Sensor",
- "topic_template": "Tema MQTT para Eventos de Sleep As Android",
- "qos": "Calidad de Servicio (QoS) para MQTT",
- "awake_duration": "Duración Despierto",
- "sleep_duration": "Duración Durmiendo",
- "awake_states": "Estados Despierto*",
- "sleep_states": "Estados Durmiendo*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "Configuración de Integración SAAS",
- "description": "Configura los ajustes básicos para la integración de SAAS.",
- "data": {
- "name": "Nombre para el Sensor",
- "topic_template": "Tema MQTT (de Sleep As Android)",
- "qos": "Calidad de Servicio (QoS) de MQTT",
- "awake_duration": "Duración Despierto",
- "sleep_duration": "Duración Durmiendo",
- "awake_states": "Estados Despierto*",
- "sleep_states": "Estados Durmiendo*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Desconocido",
- "Sleep Tracking Started": "Seguimiento del Sueño Iniciado",
- "Sleep Tracking Stopped": "Seguimiento del Sueño Detenido",
- "Sleep Tracking Paused": "Seguimiento del Sueño Pausado",
- "Sleep Tracking Resumed": "Seguimiento del Sueño Reanudado",
- "Alarm Snoozed": "Alarma en Snooze",
- "Snooze Canceled": "Snooze Cancelado",
- "Time for Bed": "Hora de Dormir",
- "Alarm Alert Started": "Alerta de Alarma Iniciada",
- "Alarm Dismissed": "Alarma Desactivada",
- "Skip Next Alarm": "Saltar Próxima Alarma",
- "Show Skip Next Alarm": "Mostrar Saltar Próxima Alarma",
- "REM": "REM",
- "Smart Period": "Periodo Inteligente",
- "Before Smart Period": "Antes del Periodo Inteligente",
- "Lullaby Start": "Inicio de Canción de Cuna",
- "Lullaby Stop": "Fin de Canción de Cuna",
- "Lullaby Volume Down": "Bajar Volumen de Canción de Cuna",
- "Deep Sleep": "Sueño Profundo",
- "Light Sleep": "Sueño Ligero",
- "Awake": "Despierto",
- "Not Awake": "No Despierto",
- "Apnea Alarm": "Alarma de Apnea",
- "Antisnoring": "Antirronquidos",
- "Before Alarm": "Antes de la Alarma",
- "Snore Detected": "Ronquido Detectado",
- "Talk Detected": "Habla Detectada",
- "Cough Detected": "Tos Detectada",
- "Baby Cry Detected": "Llanto de Bebé Detectado",
- "Laugh Detected": "Risa Detectada",
- "Alarm Rescheduled": "Alarma Re-programada",
- "None": "Ninguno"
- }
- }
- }
+{
+ "title": "sleepd - Estado de Sleep As Android",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Configuración para sleepd - Estado de Sleep As Android",
+ "description": "Configura los ajustes básicos para la integración de sleepd.",
+ "data": {
+ "name": "Nombre para el Sensor",
+ "topic_template": "Tema MQTT para Eventos de Sleep As Android",
+ "qos": "Calidad de Servicio (QoS) para MQTT",
+ "awake_duration": "Duración Despierto",
+ "sleep_duration": "Duración Durmiendo",
+ "awake_states": "Estados Despierto*",
+ "sleep_states": "Estados Durmiendo*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "Configuración de Integración sleepd",
+ "description": "Configura los ajustes básicos para la integración de sleepd.",
+ "data": {
+ "name": "Nombre para el Sensor",
+ "topic_template": "Tema MQTT (de Sleep As Android)",
+ "qos": "Calidad de Servicio (QoS) de MQTT",
+ "awake_duration": "Duración Despierto",
+ "sleep_duration": "Duración Durmiendo",
+ "awake_states": "Estados Despierto*",
+ "sleep_states": "Estados Durmiendo*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Desconocido",
+ "Sleep Tracking Started": "Seguimiento del Sueño Iniciado",
+ "Sleep Tracking Stopped": "Seguimiento del Sueño Detenido",
+ "Sleep Tracking Paused": "Seguimiento del Sueño Pausado",
+ "Sleep Tracking Resumed": "Seguimiento del Sueño Reanudado",
+ "Alarm Snoozed": "Alarma en Snooze",
+ "Snooze Canceled": "Snooze Cancelado",
+ "Time for Bed": "Hora de Dormir",
+ "Alarm Alert Started": "Alerta de Alarma Iniciada",
+ "Alarm Dismissed": "Alarma Desactivada",
+ "Skip Next Alarm": "Saltar Próxima Alarma",
+ "Show Skip Next Alarm": "Mostrar Saltar Próxima Alarma",
+ "REM": "REM",
+ "Smart Period": "Periodo Inteligente",
+ "Before Smart Period": "Antes del Periodo Inteligente",
+ "Lullaby Start": "Inicio de Canción de Cuna",
+ "Lullaby Stop": "Fin de Canción de Cuna",
+ "Lullaby Volume Down": "Bajar Volumen de Canción de Cuna",
+ "Deep Sleep": "Sueño Profundo",
+ "Light Sleep": "Sueño Ligero",
+ "Awake": "Despierto",
+ "Not Awake": "No Despierto",
+ "Apnea Alarm": "Alarma de Apnea",
+ "Antisnoring": "Antirronquidos",
+ "Before Alarm": "Antes de la Alarma",
+ "Snore Detected": "Ronquido Detectado",
+ "Talk Detected": "Habla Detectada",
+ "Cough Detected": "Tos Detectada",
+ "Baby Cry Detected": "Llanto de Bebé Detectado",
+ "Laugh Detected": "Risa Detectada",
+ "Alarm Rescheduled": "Alarma Re-programada",
+ "None": "Ninguno"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/fr.json b/custom_components/sleepd/translations/fr.json
similarity index 89%
rename from custom_components/saas/translations/fr.json
rename to custom_components/sleepd/translations/fr.json
index 30becb7..a51d5cb 100644
--- a/custom_components/saas/translations/fr.json
+++ b/custom_components/sleepd/translations/fr.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Statut de Sleep As Android",
- "config": {
- "step": {
- "user": {
- "title": "Configuration pour SAAS - Statut de Sleep As Android",
- "description": "Configurez les paramètres de base pour l'intégration de SAAS.",
- "data": {
- "name": "Nom pour le Capteur",
- "topic_template": "Sujet MQTT pour les Événements de Sleep As Android",
- "qos": "Qualité de Service (QoS) pour MQTT",
- "awake_duration": "Durée Éveillé",
- "sleep_duration": "Durée Endormi",
- "awake_states": "États Éveillé*",
- "sleep_states": "États Endormi*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "Paramètres d'Intégration SAAS",
- "description": "Configurez les paramètres de base pour l'intégration de SAAS.",
- "data": {
- "name": "Nom pour le Capteur",
- "topic_template": "Sujet MQTT (de Sleep As Android)",
- "qos": "Qualité de Service (QoS) de MQTT",
- "awake_duration": "Durée Éveillé",
- "sleep_duration": "Durée Endormi",
- "awake_states": "États Éveillé*",
- "sleep_states": "États Endormi*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Inconnu",
- "Sleep Tracking Started": "Suivi du Sommeil Commencé",
- "Sleep Tracking Stopped": "Suivi du Sommeil Arrêté",
- "Sleep Tracking Paused": "Suivi du Sommeil en Pause",
- "Sleep Tracking Resumed": "Suivi du Sommeil Repris",
- "Alarm Snoozed": "Alarme en Snooze",
- "Snooze Canceled": "Snooze Annulé",
- "Time for Bed": "Heure du Coucher",
- "Alarm Alert Started": "Alerte d'Alarme Commencée",
- "Alarm Dismissed": "Alarme Dismissed",
- "Skip Next Alarm": "Passer la Prochaine Alarme",
- "Show Skip Next Alarm": "Montrer Passer la Prochaine Alarme",
- "REM": "REM",
- "Smart Period": "Période Intelligente",
- "Before Smart Period": "Avant la Période Intelligente",
- "Lullaby Start": "Début de Berceuse",
- "Lullaby Stop": "Fin de Berceuse",
- "Lullaby Volume Down": "Diminuer le Volume de la Berceuse",
- "Deep Sleep": "Sommeil Profond",
- "Light Sleep": "Sommeil Léger",
- "Awake": "Éveillé",
- "Not Awake": "Pas Éveillé",
- "Apnea Alarm": "Alarme d'Apnée",
- "Antisnoring": "Anti-ronflement",
- "Before Alarm": "Avant l'Alarme",
- "Snore Detected": "Ronflement Détecté",
- "Talk Detected": "Parole Détectée",
- "Cough Detected": "Toux Détectée",
- "Baby Cry Detected": "Pleurs de Bébé Détectés",
- "Laugh Detected": "Rire Détecté",
- "Alarm Rescheduled": "Alarme Re-programmée",
- "None": "Aucun"
- }
- }
- }
+{
+ "title": "sleepd - Statut de Sleep As Android",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Configuration pour sleepd - Statut de Sleep As Android",
+ "description": "Configurez les paramètres de base pour l'intégration de sleepd.",
+ "data": {
+ "name": "Nom pour le Capteur",
+ "topic_template": "Sujet MQTT pour les Événements de Sleep As Android",
+ "qos": "Qualité de Service (QoS) pour MQTT",
+ "awake_duration": "Durée Éveillé",
+ "sleep_duration": "Durée Endormi",
+ "awake_states": "États Éveillé*",
+ "sleep_states": "États Endormi*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "Paramètres d'Intégration sleepd",
+ "description": "Configurez les paramètres de base pour l'intégration de sleepd.",
+ "data": {
+ "name": "Nom pour le Capteur",
+ "topic_template": "Sujet MQTT (de Sleep As Android)",
+ "qos": "Qualité de Service (QoS) de MQTT",
+ "awake_duration": "Durée Éveillé",
+ "sleep_duration": "Durée Endormi",
+ "awake_states": "États Éveillé*",
+ "sleep_states": "États Endormi*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Inconnu",
+ "Sleep Tracking Started": "Suivi du Sommeil Commencé",
+ "Sleep Tracking Stopped": "Suivi du Sommeil Arrêté",
+ "Sleep Tracking Paused": "Suivi du Sommeil en Pause",
+ "Sleep Tracking Resumed": "Suivi du Sommeil Repris",
+ "Alarm Snoozed": "Alarme en Snooze",
+ "Snooze Canceled": "Snooze Annulé",
+ "Time for Bed": "Heure du Coucher",
+ "Alarm Alert Started": "Alerte d'Alarme Commencée",
+ "Alarm Dismissed": "Alarme Dismissed",
+ "Skip Next Alarm": "Passer la Prochaine Alarme",
+ "Show Skip Next Alarm": "Montrer Passer la Prochaine Alarme",
+ "REM": "REM",
+ "Smart Period": "Période Intelligente",
+ "Before Smart Period": "Avant la Période Intelligente",
+ "Lullaby Start": "Début de Berceuse",
+ "Lullaby Stop": "Fin de Berceuse",
+ "Lullaby Volume Down": "Diminuer le Volume de la Berceuse",
+ "Deep Sleep": "Sommeil Profond",
+ "Light Sleep": "Sommeil Léger",
+ "Awake": "Éveillé",
+ "Not Awake": "Pas Éveillé",
+ "Apnea Alarm": "Alarme d'Apnée",
+ "Antisnoring": "Anti-ronflement",
+ "Before Alarm": "Avant l'Alarme",
+ "Snore Detected": "Ronflement Détecté",
+ "Talk Detected": "Parole Détectée",
+ "Cough Detected": "Toux Détectée",
+ "Baby Cry Detected": "Pleurs de Bébé Détectés",
+ "Laugh Detected": "Rire Détecté",
+ "Alarm Rescheduled": "Alarme Re-programmée",
+ "None": "Aucun"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/it.json b/custom_components/sleepd/translations/it.json
similarity index 90%
rename from custom_components/saas/translations/it.json
rename to custom_components/sleepd/translations/it.json
index c0e05d0..58651b7 100644
--- a/custom_components/saas/translations/it.json
+++ b/custom_components/sleepd/translations/it.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Stato di Sleep As Android",
- "config": {
- "step": {
- "user": {
- "title": "Configurazione per SAAS - Stato di Sleep As Android",
- "description": "Configura le impostazioni di base per l'integrazione SAAS.",
- "data": {
- "name": "Nome per Sensore",
- "topic_template": "Topic MQTT per Eventi Sleep As Android",
- "qos": "Quality of Service (QoS) per MQTT",
- "awake_duration": "Durata Sveglio",
- "sleep_duration": "Durata Addormentato",
- "awake_states": "Stati di Veglia*",
- "sleep_states": "Stati di Sonno*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "Impostazioni di Integrazione SAAS",
- "description": "Configura le impostazioni di base per l'integrazione SAAS.",
- "data": {
- "name": "Nome per Sensore",
- "topic_template": "Topic MQTT (da Sleep As Android)",
- "qos": "Quality of Service (QoS) MQTT",
- "awake_duration": "Durata Sveglio",
- "sleep_duration": "Durata Addormentato",
- "awake_states": "Stati di Veglia*",
- "sleep_states": "Stati di Sonno*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Sconosciuto",
- "Sleep Tracking Started": "Inizio Monitoraggio del Sonno",
- "Sleep Tracking Stopped": "Fine Monitoraggio del Sonno",
- "Sleep Tracking Paused": "Monitoraggio del Sonno in Pausa",
- "Sleep Tracking Resumed": "Ripresa Monitoraggio del Sonno",
- "Alarm Snoozed": "Allarme Posticipato",
- "Snooze Canceled": "Posticipo Annullato",
- "Time for Bed": "Ora di Andare a Letto",
- "Alarm Alert Started": "Inizio Allarme",
- "Alarm Dismissed": "Allarme Disattivato",
- "Skip Next Alarm": "Salta il Prossimo Allarme",
- "Show Skip Next Alarm": "Mostra 'Salta il Prossimo Allarme'",
- "REM": "REM",
- "Smart Period": "Periodo Smart",
- "Before Smart Period": "Prima del Periodo Smart",
- "Lullaby Start": "Inizio Ninna Nanna",
- "Lullaby Stop": "Fine Ninna Nanna",
- "Lullaby Volume Down": "Diminuzione Volume Ninna Nanna",
- "Deep Sleep": "Sonno Profondo",
- "Light Sleep": "Sonno Leggero",
- "Awake": "Sveglio",
- "Not Awake": "Non Sveglio",
- "Apnea Alarm": "Allarme Apnea",
- "Antisnoring": "Antirussamento",
- "Before Alarm": "Prima dell'Allarme",
- "Snore Detected": "Russamento Rilevato",
- "Talk Detected": "Conversazione Rilevata",
- "Cough Detected": "Tosse Rilevata",
- "Baby Cry Detected": "Pianto del Bambino Rilevato",
- "Laugh Detected": "Risata Rilevata",
- "Alarm Rescheduled": "Allarme Riprogrammato",
- "None": "Nessuno"
- }
- }
- }
+{
+ "title": "sleepd - Stato di Sleep As Android",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Configurazione per sleepd - Stato di Sleep As Android",
+ "description": "Configura le impostazioni di base per l'integrazione sleepd.",
+ "data": {
+ "name": "Nome per Sensore",
+ "topic_template": "Topic MQTT per Eventi Sleep As Android",
+ "qos": "Quality of Service (QoS) per MQTT",
+ "awake_duration": "Durata Sveglio",
+ "sleep_duration": "Durata Addormentato",
+ "awake_states": "Stati di Veglia*",
+ "sleep_states": "Stati di Sonno*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "Impostazioni di Integrazione sleepd",
+ "description": "Configura le impostazioni di base per l'integrazione sleepd.",
+ "data": {
+ "name": "Nome per Sensore",
+ "topic_template": "Topic MQTT (da Sleep As Android)",
+ "qos": "Quality of Service (QoS) MQTT",
+ "awake_duration": "Durata Sveglio",
+ "sleep_duration": "Durata Addormentato",
+ "awake_states": "Stati di Veglia*",
+ "sleep_states": "Stati di Sonno*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Sconosciuto",
+ "Sleep Tracking Started": "Inizio Monitoraggio del Sonno",
+ "Sleep Tracking Stopped": "Fine Monitoraggio del Sonno",
+ "Sleep Tracking Paused": "Monitoraggio del Sonno in Pausa",
+ "Sleep Tracking Resumed": "Ripresa Monitoraggio del Sonno",
+ "Alarm Snoozed": "Allarme Posticipato",
+ "Snooze Canceled": "Posticipo Annullato",
+ "Time for Bed": "Ora di Andare a Letto",
+ "Alarm Alert Started": "Inizio Allarme",
+ "Alarm Dismissed": "Allarme Disattivato",
+ "Skip Next Alarm": "Salta il Prossimo Allarme",
+ "Show Skip Next Alarm": "Mostra 'Salta il Prossimo Allarme'",
+ "REM": "REM",
+ "Smart Period": "Periodo Smart",
+ "Before Smart Period": "Prima del Periodo Smart",
+ "Lullaby Start": "Inizio Ninna Nanna",
+ "Lullaby Stop": "Fine Ninna Nanna",
+ "Lullaby Volume Down": "Diminuzione Volume Ninna Nanna",
+ "Deep Sleep": "Sonno Profondo",
+ "Light Sleep": "Sonno Leggero",
+ "Awake": "Sveglio",
+ "Not Awake": "Non Sveglio",
+ "Apnea Alarm": "Allarme Apnea",
+ "Antisnoring": "Antirussamento",
+ "Before Alarm": "Prima dell'Allarme",
+ "Snore Detected": "Russamento Rilevato",
+ "Talk Detected": "Conversazione Rilevata",
+ "Cough Detected": "Tosse Rilevata",
+ "Baby Cry Detected": "Pianto del Bambino Rilevato",
+ "Laugh Detected": "Risata Rilevata",
+ "Alarm Rescheduled": "Allarme Riprogrammato",
+ "None": "Nessuno"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/ja.json b/custom_components/sleepd/translations/ja.json
similarity index 87%
rename from custom_components/saas/translations/ja.json
rename to custom_components/sleepd/translations/ja.json
index 52dcaa6..6cb23ca 100644
--- a/custom_components/saas/translations/ja.json
+++ b/custom_components/sleepd/translations/ja.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - 睡眠如 Android 狀態",
- "config": {
- "step": {
- "user": {
- "title": "SAAS - 睡眠如 Android 狀態配置",
- "description": "配置 SAAS 整合的基本設置。",
- "data": {
- "name": "感應器名稱",
- "topic_template": "睡眠如 Android 事件的 MQTT 主題",
- "qos": "MQTT 的服務質量 (QoS)",
- "awake_duration": "清醒持續時間",
- "sleep_duration": "睡眠持續時間",
- "awake_states": "清醒狀態*",
- "sleep_states": "睡眠狀態*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "SAAS 整合設置",
- "description": "配置 SAAS 整合的基本設置。",
- "data": {
- "name": "感應器名稱",
- "topic_template": "MQTT 主題(來自睡眠如 Android)",
- "qos": "MQTT 服務質量 (QoS)",
- "awake_duration": "清醒持續時間",
- "sleep_duration": "睡眠持續時間",
- "awake_states": "清醒狀態*",
- "sleep_states": "睡眠狀態*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "未知",
- "Sleep Tracking Started": "開始追蹤睡眠",
- "Sleep Tracking Stopped": "停止追蹤睡眠",
- "Sleep Tracking Paused": "暫停追蹤睡眠",
- "Sleep Tracking Resumed": "恢復追蹤睡眠",
- "Alarm Snoozed": "鬧鐘貪睡",
- "Snooze Canceled": "取消貪睡",
- "Time for Bed": "該睡覺了",
- "Alarm Alert Started": "鬧鐘警報開始",
- "Alarm Dismissed": "鬧鐘解除",
- "Skip Next Alarm": "跳過下一個鬧鐘",
- "Show Skip Next Alarm": "顯示跳過下一個鬧鐘",
- "REM": "REM",
- "Smart Period": "智能期間",
- "Before Smart Period": "在智能期間之前",
- "Lullaby Start": "搖籃曲開始",
- "Lullaby Stop": "搖籃曲停止",
- "Lullaby Volume Down": "搖籃曲音量下降",
- "Deep Sleep": "深度睡眠",
- "Light Sleep": "淺度睡眠",
- "Awake": "清醒",
- "Not Awake": "未清醒",
- "Apnea Alarm": "呼吸暫停警報",
- "Antisnoring": "防打鼾",
- "Before Alarm": "在鬧鐘之前",
- "Snore Detected": "檢測到打鼾",
- "Talk Detected": "檢測到說話",
- "Cough Detected": "檢測到咳嗽",
- "Baby Cry Detected": "檢測到嬰兒哭聲",
- "Laugh Detected": "檢測到笑聲",
- "Alarm Rescheduled": "鬧鐘重新安排",
- "None": "無"
- }
- }
- }
+{
+ "title": "sleepd - 睡眠如 Android 狀態",
+ "config": {
+ "step": {
+ "user": {
+ "title": "sleepd - 睡眠如 Android 狀態配置",
+ "description": "配置 sleepd 整合的基本設置。",
+ "data": {
+ "name": "感應器名稱",
+ "topic_template": "睡眠如 Android 事件的 MQTT 主題",
+ "qos": "MQTT 的服務質量 (QoS)",
+ "awake_duration": "清醒持續時間",
+ "sleep_duration": "睡眠持續時間",
+ "awake_states": "清醒狀態*",
+ "sleep_states": "睡眠狀態*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "sleepd 整合設置",
+ "description": "配置 sleepd 整合的基本設置。",
+ "data": {
+ "name": "感應器名稱",
+ "topic_template": "MQTT 主題(來自睡眠如 Android)",
+ "qos": "MQTT 服務質量 (QoS)",
+ "awake_duration": "清醒持續時間",
+ "sleep_duration": "睡眠持續時間",
+ "awake_states": "清醒狀態*",
+ "sleep_states": "睡眠狀態*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "未知",
+ "Sleep Tracking Started": "開始追蹤睡眠",
+ "Sleep Tracking Stopped": "停止追蹤睡眠",
+ "Sleep Tracking Paused": "暫停追蹤睡眠",
+ "Sleep Tracking Resumed": "恢復追蹤睡眠",
+ "Alarm Snoozed": "鬧鐘貪睡",
+ "Snooze Canceled": "取消貪睡",
+ "Time for Bed": "該睡覺了",
+ "Alarm Alert Started": "鬧鐘警報開始",
+ "Alarm Dismissed": "鬧鐘解除",
+ "Skip Next Alarm": "跳過下一個鬧鐘",
+ "Show Skip Next Alarm": "顯示跳過下一個鬧鐘",
+ "REM": "REM",
+ "Smart Period": "智能期間",
+ "Before Smart Period": "在智能期間之前",
+ "Lullaby Start": "搖籃曲開始",
+ "Lullaby Stop": "搖籃曲停止",
+ "Lullaby Volume Down": "搖籃曲音量下降",
+ "Deep Sleep": "深度睡眠",
+ "Light Sleep": "淺度睡眠",
+ "Awake": "清醒",
+ "Not Awake": "未清醒",
+ "Apnea Alarm": "呼吸暫停警報",
+ "Antisnoring": "防打鼾",
+ "Before Alarm": "在鬧鐘之前",
+ "Snore Detected": "檢測到打鼾",
+ "Talk Detected": "檢測到說話",
+ "Cough Detected": "檢測到咳嗽",
+ "Baby Cry Detected": "檢測到嬰兒哭聲",
+ "Laugh Detected": "檢測到笑聲",
+ "Alarm Rescheduled": "鬧鐘重新安排",
+ "None": "無"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/ko.json b/custom_components/sleepd/translations/ko.json
similarity index 87%
rename from custom_components/saas/translations/ko.json
rename to custom_components/sleepd/translations/ko.json
index 9d71829..3c60b8c 100644
--- a/custom_components/saas/translations/ko.json
+++ b/custom_components/sleepd/translations/ko.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Sleep As Android 상태",
- "config": {
- "step": {
- "user": {
- "title": "SAAS - Sleep As Android 상태 설정",
- "description": "SAAS 통합의 기본 설정을 구성합니다.",
- "data": {
- "name": "센서 이름",
- "topic_template": "Sleep As Android 이벤트의 MQTT 주제",
- "qos": "MQTT의 서비스 품질(QoS)",
- "awake_duration": "깨어 있는 시간",
- "sleep_duration": "수면 시간",
- "awake_states": "깨어 있는 상태*",
- "sleep_states": "수면 상태*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "SAAS 통합 설정",
- "description": "SAAS 통합의 기본 설정을 구성합니다.",
- "data": {
- "name": "센서 이름",
- "topic_template": "Sleep As Android에서의 MQTT 주제",
- "qos": "MQTT의 서비스 품질(QoS)",
- "awake_duration": "깨어 있는 시간",
- "sleep_duration": "수면 시간",
- "awake_states": "깨어 있는 상태*",
- "sleep_states": "수면 상태*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "알 수 없음",
- "Sleep Tracking Started": "수면 추적 시작",
- "Sleep Tracking Stopped": "수면 추적 중지",
- "Sleep Tracking Paused": "수면 추적 일시 중지",
- "Sleep Tracking Resumed": "수면 추적 재개",
- "Alarm Snoozed": "알람 스누즈",
- "Snooze Canceled": "스누즈 취소",
- "Time for Bed": "침대 시간",
- "Alarm Alert Started": "알람 경고 시작",
- "Alarm Dismissed": "알람 해제",
- "Skip Next Alarm": "다음 알람 건너뛰기",
- "Show Skip Next Alarm": "다음 알람 건너뛰기 표시",
- "REM": "REM",
- "Smart Period": "스마트 기간",
- "Before Smart Period": "스마트 기간 이전",
- "Lullaby Start": "자장가 시작",
- "Lullaby Stop": "자장가 중지",
- "Lullaby Volume Down": "자장가 볼륨 다운",
- "Deep Sleep": "깊은 잠",
- "Light Sleep": "얕은 잠",
- "Awake": "깨어 있음",
- "Not Awake": "깨어 있지 않음",
- "Apnea Alarm": "무호흡 알람",
- "Antisnoring": "코골이 방지",
- "Before Alarm": "알람 이전",
- "Snore Detected": "코골이 감지됨",
- "Talk Detected": "대화 감지됨",
- "Cough Detected": "기침 감지됨",
- "Baby Cry Detected": "아기 울음소리 감지됨",
- "Laugh Detected": "웃음소리 감지됨",
- "Alarm Rescheduled": "알람 재스케줄",
- "None": "없음"
- }
- }
- }
+{
+ "title": "sleepd - Sleep As Android 상태",
+ "config": {
+ "step": {
+ "user": {
+ "title": "sleepd - Sleep As Android 상태 설정",
+ "description": "sleepd 통합의 기본 설정을 구성합니다.",
+ "data": {
+ "name": "센서 이름",
+ "topic_template": "Sleep As Android 이벤트의 MQTT 주제",
+ "qos": "MQTT의 서비스 품질(QoS)",
+ "awake_duration": "깨어 있는 시간",
+ "sleep_duration": "수면 시간",
+ "awake_states": "깨어 있는 상태*",
+ "sleep_states": "수면 상태*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "sleepd 통합 설정",
+ "description": "sleepd 통합의 기본 설정을 구성합니다.",
+ "data": {
+ "name": "센서 이름",
+ "topic_template": "Sleep As Android에서의 MQTT 주제",
+ "qos": "MQTT의 서비스 품질(QoS)",
+ "awake_duration": "깨어 있는 시간",
+ "sleep_duration": "수면 시간",
+ "awake_states": "깨어 있는 상태*",
+ "sleep_states": "수면 상태*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "알 수 없음",
+ "Sleep Tracking Started": "수면 추적 시작",
+ "Sleep Tracking Stopped": "수면 추적 중지",
+ "Sleep Tracking Paused": "수면 추적 일시 중지",
+ "Sleep Tracking Resumed": "수면 추적 재개",
+ "Alarm Snoozed": "알람 스누즈",
+ "Snooze Canceled": "스누즈 취소",
+ "Time for Bed": "침대 시간",
+ "Alarm Alert Started": "알람 경고 시작",
+ "Alarm Dismissed": "알람 해제",
+ "Skip Next Alarm": "다음 알람 건너뛰기",
+ "Show Skip Next Alarm": "다음 알람 건너뛰기 표시",
+ "REM": "REM",
+ "Smart Period": "스마트 기간",
+ "Before Smart Period": "스마트 기간 이전",
+ "Lullaby Start": "자장가 시작",
+ "Lullaby Stop": "자장가 중지",
+ "Lullaby Volume Down": "자장가 볼륨 다운",
+ "Deep Sleep": "깊은 잠",
+ "Light Sleep": "얕은 잠",
+ "Awake": "깨어 있음",
+ "Not Awake": "깨어 있지 않음",
+ "Apnea Alarm": "무호흡 알람",
+ "Antisnoring": "코골이 방지",
+ "Before Alarm": "알람 이전",
+ "Snore Detected": "코골이 감지됨",
+ "Talk Detected": "대화 감지됨",
+ "Cough Detected": "기침 감지됨",
+ "Baby Cry Detected": "아기 울음소리 감지됨",
+ "Laugh Detected": "웃음소리 감지됨",
+ "Alarm Rescheduled": "알람 재스케줄",
+ "None": "없음"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/nl.json b/custom_components/sleepd/translations/nl.json
similarity index 89%
rename from custom_components/saas/translations/nl.json
rename to custom_components/sleepd/translations/nl.json
index 2164d9d..b9178ed 100644
--- a/custom_components/saas/translations/nl.json
+++ b/custom_components/sleepd/translations/nl.json
@@ -1,75 +1,75 @@
-{
- "title": "Configuratie voor SAAS - Sleep As Android Status",
- "config": {
- "step": {
- "user": {
- "title": "Configuratie voor SAAS - Sleep As Android Status",
- "description": "Configureer de basisinstellingen voor de SAAS-integratie.",
- "data": {
- "name": "Naam voor Sensor",
- "topic_template": "MQTT-onderwerp voor Sleep As Android Gebeurtenissen",
- "qos": "Quality of Service (QoS) voor MQTT",
- "awake_duration": "Wakker Duur",
- "sleep_duration": "Slaapduur",
- "awake_states": "Wakker Staten*",
- "sleep_states": "Slaap Staten*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "SAAS-Integratie-Instellingen",
- "description": "Configureer de basisinstellingen voor de SAAS-integratie.",
- "data": {
- "name": "Naam voor Sensor",
- "topic_template": "MQTT-Onderwerp (van Sleep As Android)",
- "qos": "MQTT Quality of Service (QoS)",
- "awake_duration": "Wakker Duur",
- "sleep_duration": "Slaapduur",
- "awake_states": "Wakker Staten*",
- "sleep_states": "Slaap Staten*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Onbekend",
- "Sleep Tracking Started": "Slaaptracking Gestart",
- "Sleep Tracking Stopped": "Slaaptracking Gestopt",
- "Sleep Tracking Paused": "Slaaptracking Gepauzeerd",
- "Sleep Tracking Resumed": "Slaaptracking Hervat",
- "Alarm Snoozed": "Alarm Gesnoozed",
- "Snooze Canceled": "Snooze Geannuleerd",
- "Time for Bed": "Tijd om te Gaan Slapen",
- "Alarm Alert Started": "Alarm Alert Gestart",
- "Alarm Dismissed": "Alarm Afgeslagen",
- "Skip Next Alarm": "Volgende Alarm Overslaan",
- "Show Skip Next Alarm": "Toon 'Volgende Alarm Overslaan'",
- "REM": "REM",
- "Smart Period": "Slimme Periode",
- "Before Smart Period": "Voor Slimme Periode",
- "Lullaby Start": "Slaapliedje Start",
- "Lullaby Stop": "Slaapliedje Stop",
- "Lullaby Volume Down": "Slaapliedje Volume Omlaag",
- "Deep Sleep": "Diepe Slaap",
- "Light Sleep": "Lichte Slaap",
- "Awake": "Wakker",
- "Not Awake": "Niet Wakker",
- "Apnea Alarm": "Apneu Alarm",
- "Antisnoring": "Antisnurken",
- "Before Alarm": "Voor Alarm",
- "Snore Detected": "Snurken Gedetecteerd",
- "Talk Detected": "Gesprek Gedetecteerd",
- "Cough Detected": "Hoesten Gedetecteerd",
- "Baby Cry Detected": "Baby Huilen Gedetecteerd",
- "Laugh Detected": "Lachen Gedetecteerd",
- "Alarm Rescheduled": "Alarm Herpland",
- "None": "Geen"
- }
- }
- }
+{
+ "title": "Configuratie voor sleepd - Sleep As Android Status",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Configuratie voor sleepd - Sleep As Android Status",
+ "description": "Configureer de basisinstellingen voor de sleepd-integratie.",
+ "data": {
+ "name": "Naam voor Sensor",
+ "topic_template": "MQTT-onderwerp voor Sleep As Android Gebeurtenissen",
+ "qos": "Quality of Service (QoS) voor MQTT",
+ "awake_duration": "Wakker Duur",
+ "sleep_duration": "Slaapduur",
+ "awake_states": "Wakker Staten*",
+ "sleep_states": "Slaap Staten*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "sleepd-Integratie-Instellingen",
+ "description": "Configureer de basisinstellingen voor de sleepd-integratie.",
+ "data": {
+ "name": "Naam voor Sensor",
+ "topic_template": "MQTT-Onderwerp (van Sleep As Android)",
+ "qos": "MQTT Quality of Service (QoS)",
+ "awake_duration": "Wakker Duur",
+ "sleep_duration": "Slaapduur",
+ "awake_states": "Wakker Staten*",
+ "sleep_states": "Slaap Staten*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Onbekend",
+ "Sleep Tracking Started": "Slaaptracking Gestart",
+ "Sleep Tracking Stopped": "Slaaptracking Gestopt",
+ "Sleep Tracking Paused": "Slaaptracking Gepauzeerd",
+ "Sleep Tracking Resumed": "Slaaptracking Hervat",
+ "Alarm Snoozed": "Alarm Gesnoozed",
+ "Snooze Canceled": "Snooze Geannuleerd",
+ "Time for Bed": "Tijd om te Gaan Slapen",
+ "Alarm Alert Started": "Alarm Alert Gestart",
+ "Alarm Dismissed": "Alarm Afgeslagen",
+ "Skip Next Alarm": "Volgende Alarm Overslaan",
+ "Show Skip Next Alarm": "Toon 'Volgende Alarm Overslaan'",
+ "REM": "REM",
+ "Smart Period": "Slimme Periode",
+ "Before Smart Period": "Voor Slimme Periode",
+ "Lullaby Start": "Slaapliedje Start",
+ "Lullaby Stop": "Slaapliedje Stop",
+ "Lullaby Volume Down": "Slaapliedje Volume Omlaag",
+ "Deep Sleep": "Diepe Slaap",
+ "Light Sleep": "Lichte Slaap",
+ "Awake": "Wakker",
+ "Not Awake": "Niet Wakker",
+ "Apnea Alarm": "Apneu Alarm",
+ "Antisnoring": "Antisnurken",
+ "Before Alarm": "Voor Alarm",
+ "Snore Detected": "Snurken Gedetecteerd",
+ "Talk Detected": "Gesprek Gedetecteerd",
+ "Cough Detected": "Hoesten Gedetecteerd",
+ "Baby Cry Detected": "Baby Huilen Gedetecteerd",
+ "Laugh Detected": "Lachen Gedetecteerd",
+ "Alarm Rescheduled": "Alarm Herpland",
+ "None": "Geen"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/pl.json b/custom_components/sleepd/translations/pl.json
similarity index 90%
rename from custom_components/saas/translations/pl.json
rename to custom_components/sleepd/translations/pl.json
index 7cf84d9..7c99f42 100644
--- a/custom_components/saas/translations/pl.json
+++ b/custom_components/sleepd/translations/pl.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Status Sleep As Android",
- "config": {
- "step": {
- "user": {
- "title": "Konfiguracja dla SAAS - Status Sleep As Android",
- "description": "Konfiguracja podstawowych ustawień dla integracji SAAS.",
- "data": {
- "name": "Nazwa dla czujnika",
- "topic_template": "Temat MQTT dla zdarzeń Sleep As Android",
- "qos": "Jakość usługi (QoS) dla MQTT",
- "awake_duration": "Czas czuwania",
- "sleep_duration": "Czas snu",
- "awake_states": "Stany czuwania*",
- "sleep_states": "Stany snu*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "Ustawienia integracji SAAS",
- "description": "Konfiguracja podstawowych ustawień dla integracji SAAS.",
- "data": {
- "name": "Nazwa dla czujnika",
- "topic_template": "Temat MQTT (od Sleep As Android)",
- "qos": "Jakość usługi (QoS) MQTT",
- "awake_duration": "Czas czuwania",
- "sleep_duration": "Czas snu",
- "awake_states": "Stany czuwania*",
- "sleep_states": "Stany snu*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Nieznane",
- "Sleep Tracking Started": "Rozpoczęto śledzenie snu",
- "Sleep Tracking Stopped": "Zatrzymano śledzenie snu",
- "Sleep Tracking Paused": "Wstrzymano śledzenie snu",
- "Sleep Tracking Resumed": "Wznowiono śledzenie snu",
- "Alarm Snoozed": "Alarm w drzemce",
- "Snooze Canceled": "Drzemka anulowana",
- "Time for Bed": "Czas na sen",
- "Alarm Alert Started": "Rozpoczęto alarm",
- "Alarm Dismissed": "Alarm wyłączony",
- "Skip Next Alarm": "Pomiń następny alarm",
- "Show Skip Next Alarm": "Pokaż pomiń następny alarm",
- "REM": "REM",
- "Smart Period": "Inteligentny okres",
- "Before Smart Period": "Przed inteligentnym okresem",
- "Lullaby Start": "Rozpoczęcie kołysanki",
- "Lullaby Stop": "Zakończenie kołysanki",
- "Lullaby Volume Down": "Zmniejsz głośność kołysanki",
- "Deep Sleep": "Głęboki sen",
- "Light Sleep": "Lekki sen",
- "Awake": "Czuwanie",
- "Not Awake": "Nie czuwa",
- "Apnea Alarm": "Alarm apnei",
- "Antisnoring": "Przeciw chrapaniu",
- "Before Alarm": "Przed alarmem",
- "Snore Detected": "Wykryto chrapanie",
- "Talk Detected": "Wykryto mówienie",
- "Cough Detected": "Wykryto kaszel",
- "Baby Cry Detected": "Wykryto płacz dziecka",
- "Laugh Detected": "Wykryto śmiech",
- "Alarm Rescheduled": "Alarm został przesunięty",
- "None": "Brak"
- }
- }
- }
+{
+ "title": "sleepd - Status Sleep As Android",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Konfiguracja dla sleepd - Status Sleep As Android",
+ "description": "Konfiguracja podstawowych ustawień dla integracji sleepd.",
+ "data": {
+ "name": "Nazwa dla czujnika",
+ "topic_template": "Temat MQTT dla zdarzeń Sleep As Android",
+ "qos": "Jakość usługi (QoS) dla MQTT",
+ "awake_duration": "Czas czuwania",
+ "sleep_duration": "Czas snu",
+ "awake_states": "Stany czuwania*",
+ "sleep_states": "Stany snu*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "Ustawienia integracji sleepd",
+ "description": "Konfiguracja podstawowych ustawień dla integracji sleepd.",
+ "data": {
+ "name": "Nazwa dla czujnika",
+ "topic_template": "Temat MQTT (od Sleep As Android)",
+ "qos": "Jakość usługi (QoS) MQTT",
+ "awake_duration": "Czas czuwania",
+ "sleep_duration": "Czas snu",
+ "awake_states": "Stany czuwania*",
+ "sleep_states": "Stany snu*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Nieznane",
+ "Sleep Tracking Started": "Rozpoczęto śledzenie snu",
+ "Sleep Tracking Stopped": "Zatrzymano śledzenie snu",
+ "Sleep Tracking Paused": "Wstrzymano śledzenie snu",
+ "Sleep Tracking Resumed": "Wznowiono śledzenie snu",
+ "Alarm Snoozed": "Alarm w drzemce",
+ "Snooze Canceled": "Drzemka anulowana",
+ "Time for Bed": "Czas na sen",
+ "Alarm Alert Started": "Rozpoczęto alarm",
+ "Alarm Dismissed": "Alarm wyłączony",
+ "Skip Next Alarm": "Pomiń następny alarm",
+ "Show Skip Next Alarm": "Pokaż pomiń następny alarm",
+ "REM": "REM",
+ "Smart Period": "Inteligentny okres",
+ "Before Smart Period": "Przed inteligentnym okresem",
+ "Lullaby Start": "Rozpoczęcie kołysanki",
+ "Lullaby Stop": "Zakończenie kołysanki",
+ "Lullaby Volume Down": "Zmniejsz głośność kołysanki",
+ "Deep Sleep": "Głęboki sen",
+ "Light Sleep": "Lekki sen",
+ "Awake": "Czuwanie",
+ "Not Awake": "Nie czuwa",
+ "Apnea Alarm": "Alarm apnei",
+ "Antisnoring": "Przeciw chrapaniu",
+ "Before Alarm": "Przed alarmem",
+ "Snore Detected": "Wykryto chrapanie",
+ "Talk Detected": "Wykryto mówienie",
+ "Cough Detected": "Wykryto kaszel",
+ "Baby Cry Detected": "Wykryto płacz dziecka",
+ "Laugh Detected": "Wykryto śmiech",
+ "Alarm Rescheduled": "Alarm został przesunięty",
+ "None": "Brak"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/pt.json b/custom_components/sleepd/translations/pt.json
similarity index 89%
rename from custom_components/saas/translations/pt.json
rename to custom_components/sleepd/translations/pt.json
index 592e132..6a27d51 100644
--- a/custom_components/saas/translations/pt.json
+++ b/custom_components/sleepd/translations/pt.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Status do Sleep As Android",
- "config": {
- "step": {
- "user": {
- "title": "Configuração para SAAS - Status do Sleep As Android",
- "description": "Configure as configurações básicas para a integração SAAS.",
- "data": {
- "name": "Nome para Sensor",
- "topic_template": "Tópico MQTT para Eventos do Sleep As Android",
- "qos": "Qualidade de Serviço (QoS) para MQTT",
- "awake_duration": "Duração Acordado",
- "sleep_duration": "Duração Adormecido",
- "awake_states": "Estados Acordado*",
- "sleep_states": "Estados Adormecido*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "Configurações de Integração SAAS",
- "description": "Configure as configurações básicas para a integração SAAS.",
- "data": {
- "name": "Nome para Sensor",
- "topic_template": "Tópico MQTT (do Sleep As Android)",
- "qos": "Qualidade de Serviço (QoS) MQTT",
- "awake_duration": "Duração Acordado",
- "sleep_duration": "Duração Adormecido",
- "awake_states": "Estados Acordado*",
- "sleep_states": "Estados Adormecido*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Desconhecido",
- "Sleep Tracking Started": "Monitoramento do Sono Iniciado",
- "Sleep Tracking Stopped": "Monitoramento do Sono Parado",
- "Sleep Tracking Paused": "Monitoramento do Sono Pausado",
- "Sleep Tracking Resumed": "Monitoramento do Sono Retomado",
- "Alarm Snoozed": "Alarme Adiado",
- "Snooze Canceled": "Adiamento Cancelado",
- "Time for Bed": "Hora de Dormir",
- "Alarm Alert Started": "Alerta de Alarme Iniciado",
- "Alarm Dismissed": "Alarme Desligado",
- "Skip Next Alarm": "Pular Próximo Alarme",
- "Show Skip Next Alarm": "Mostrar 'Pular Próximo Alarme'",
- "REM": "REM",
- "Smart Period": "Período Inteligente",
- "Before Smart Period": "Antes do Período Inteligente",
- "Lullaby Start": "Início de Canção de Ninar",
- "Lullaby Stop": "Fim de Canção de Ninar",
- "Lullaby Volume Down": "Diminuir Volume da Canção de Ninar",
- "Deep Sleep": "Sono Profundo",
- "Light Sleep": "Sono Leve",
- "Awake": "Acordado",
- "Not Awake": "Não Acordado",
- "Apnea Alarm": "Alarme de Apneia",
- "Antisnoring": "Antirronco",
- "Before Alarm": "Antes do Alarme",
- "Snore Detected": "Ronco Detectado",
- "Talk Detected": "Conversa Detectada",
- "Cough Detected": "Tosse Detectada",
- "Baby Cry Detected": "Choro de Bebê Detectado",
- "Laugh Detected": "Risada Detectada",
- "Alarm Rescheduled": "Alarme Remarcado",
- "None": "Nenhum"
- }
- }
- }
+{
+ "title": "sleepd - Status do Sleep As Android",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Configuração para sleepd - Status do Sleep As Android",
+ "description": "Configure as configurações básicas para a integração sleepd.",
+ "data": {
+ "name": "Nome para Sensor",
+ "topic_template": "Tópico MQTT para Eventos do Sleep As Android",
+ "qos": "Qualidade de Serviço (QoS) para MQTT",
+ "awake_duration": "Duração Acordado",
+ "sleep_duration": "Duração Adormecido",
+ "awake_states": "Estados Acordado*",
+ "sleep_states": "Estados Adormecido*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "Configurações de Integração sleepd",
+ "description": "Configure as configurações básicas para a integração sleepd.",
+ "data": {
+ "name": "Nome para Sensor",
+ "topic_template": "Tópico MQTT (do Sleep As Android)",
+ "qos": "Qualidade de Serviço (QoS) MQTT",
+ "awake_duration": "Duração Acordado",
+ "sleep_duration": "Duração Adormecido",
+ "awake_states": "Estados Acordado*",
+ "sleep_states": "Estados Adormecido*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Desconhecido",
+ "Sleep Tracking Started": "Monitoramento do Sono Iniciado",
+ "Sleep Tracking Stopped": "Monitoramento do Sono Parado",
+ "Sleep Tracking Paused": "Monitoramento do Sono Pausado",
+ "Sleep Tracking Resumed": "Monitoramento do Sono Retomado",
+ "Alarm Snoozed": "Alarme Adiado",
+ "Snooze Canceled": "Adiamento Cancelado",
+ "Time for Bed": "Hora de Dormir",
+ "Alarm Alert Started": "Alerta de Alarme Iniciado",
+ "Alarm Dismissed": "Alarme Desligado",
+ "Skip Next Alarm": "Pular Próximo Alarme",
+ "Show Skip Next Alarm": "Mostrar 'Pular Próximo Alarme'",
+ "REM": "REM",
+ "Smart Period": "Período Inteligente",
+ "Before Smart Period": "Antes do Período Inteligente",
+ "Lullaby Start": "Início de Canção de Ninar",
+ "Lullaby Stop": "Fim de Canção de Ninar",
+ "Lullaby Volume Down": "Diminuir Volume da Canção de Ninar",
+ "Deep Sleep": "Sono Profundo",
+ "Light Sleep": "Sono Leve",
+ "Awake": "Acordado",
+ "Not Awake": "Não Acordado",
+ "Apnea Alarm": "Alarme de Apneia",
+ "Antisnoring": "Antirronco",
+ "Before Alarm": "Antes do Alarme",
+ "Snore Detected": "Ronco Detectado",
+ "Talk Detected": "Conversa Detectada",
+ "Cough Detected": "Tosse Detectada",
+ "Baby Cry Detected": "Choro de Bebê Detectado",
+ "Laugh Detected": "Risada Detectada",
+ "Alarm Rescheduled": "Alarme Remarcado",
+ "None": "Nenhum"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/pue.json b/custom_components/sleepd/translations/pue.json
similarity index 87%
rename from custom_components/saas/translations/pue.json
rename to custom_components/sleepd/translations/pue.json
index b4fac33..bb3dbda 100644
--- a/custom_components/saas/translations/pue.json
+++ b/custom_components/sleepd/translations/pue.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - 睡眠如 Android 狀態",
- "config": {
- "step": {
- "user": {
- "title": "SAAS - 睡眠如 Android 狀態配置",
- "description": "配置 SAAS 整合的基本設置。",
- "data": {
- "name": "感應器名稱",
- "topic_template": "睡眠如 Android 事件的 MQTT 主題",
- "qos": "MQTT 的服務質量 (QoS)",
- "awake_duration": "清醒持續時間",
- "sleep_duration": "睡眠持續時間",
- "awake_states": "清醒狀態*",
- "sleep_states": "睡眠狀態*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "SAAS 整合設置",
- "description": "配置 SAAS 整合的基本設置。",
- "data": {
- "name": "感應器名稱",
- "topic_template": "MQTT 主題(來自睡眠如 Android)",
- "qos": "MQTT 服務質量 (QoS)",
- "awake_duration": "清醒持續時間",
- "sleep_duration": "睡眠持續時間",
- "awake_states": "清醒狀態*",
- "sleep_states": "睡眠狀態*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "未知",
- "Sleep Tracking Started": "開始追蹤睡眠",
- "Sleep Tracking Stopped": "停止追蹤睡眠",
- "Sleep Tracking Paused": "暫停追蹤睡眠",
- "Sleep Tracking Resumed": "恢復追蹤睡眠",
- "Alarm Snoozed": "鬧鐘貪睡",
- "Snooze Canceled": "取消貪睡",
- "Time for Bed": "該睡覺了",
- "Alarm Alert Started": "鬧鐘警報開始",
- "Alarm Dismissed": "鬧鐘解除",
- "Skip Next Alarm": "跳過下一個鬧鐘",
- "Show Skip Next Alarm": "顯示跳過下一個鬧鐘",
- "REM": "REM",
- "Smart Period": "智能期間",
- "Before Smart Period": "在智能期間之前",
- "Lullaby Start": "搖籃曲開始",
- "Lullaby Stop": "搖籃曲停止",
- "Lullaby Volume Down": "搖籃曲音量下降",
- "Deep Sleep": "深度睡眠",
- "Light Sleep": "淺度睡眠",
- "Awake": "清醒",
- "Not Awake": "未清醒",
- "Apnea Alarm": "呼吸暫停警報",
- "Antisnoring": "防打鼾",
- "Before Alarm": "在鬧鐘之前",
- "Snore Detected": "檢測到打鼾",
- "Talk Detected": "檢測到說話",
- "Cough Detected": "檢測到咳嗽",
- "Baby Cry Detected": "檢測到嬰兒哭聲",
- "Laugh Detected": "檢測到笑聲",
- "Alarm Rescheduled": "鬧鐘重新安排",
- "None": "無"
- }
- }
- }
+{
+ "title": "sleepd - 睡眠如 Android 狀態",
+ "config": {
+ "step": {
+ "user": {
+ "title": "sleepd - 睡眠如 Android 狀態配置",
+ "description": "配置 sleepd 整合的基本設置。",
+ "data": {
+ "name": "感應器名稱",
+ "topic_template": "睡眠如 Android 事件的 MQTT 主題",
+ "qos": "MQTT 的服務質量 (QoS)",
+ "awake_duration": "清醒持續時間",
+ "sleep_duration": "睡眠持續時間",
+ "awake_states": "清醒狀態*",
+ "sleep_states": "睡眠狀態*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "sleepd 整合設置",
+ "description": "配置 sleepd 整合的基本設置。",
+ "data": {
+ "name": "感應器名稱",
+ "topic_template": "MQTT 主題(來自睡眠如 Android)",
+ "qos": "MQTT 服務質量 (QoS)",
+ "awake_duration": "清醒持續時間",
+ "sleep_duration": "睡眠持續時間",
+ "awake_states": "清醒狀態*",
+ "sleep_states": "睡眠狀態*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "未知",
+ "Sleep Tracking Started": "開始追蹤睡眠",
+ "Sleep Tracking Stopped": "停止追蹤睡眠",
+ "Sleep Tracking Paused": "暫停追蹤睡眠",
+ "Sleep Tracking Resumed": "恢復追蹤睡眠",
+ "Alarm Snoozed": "鬧鐘貪睡",
+ "Snooze Canceled": "取消貪睡",
+ "Time for Bed": "該睡覺了",
+ "Alarm Alert Started": "鬧鐘警報開始",
+ "Alarm Dismissed": "鬧鐘解除",
+ "Skip Next Alarm": "跳過下一個鬧鐘",
+ "Show Skip Next Alarm": "顯示跳過下一個鬧鐘",
+ "REM": "REM",
+ "Smart Period": "智能期間",
+ "Before Smart Period": "在智能期間之前",
+ "Lullaby Start": "搖籃曲開始",
+ "Lullaby Stop": "搖籃曲停止",
+ "Lullaby Volume Down": "搖籃曲音量下降",
+ "Deep Sleep": "深度睡眠",
+ "Light Sleep": "淺度睡眠",
+ "Awake": "清醒",
+ "Not Awake": "未清醒",
+ "Apnea Alarm": "呼吸暫停警報",
+ "Antisnoring": "防打鼾",
+ "Before Alarm": "在鬧鐘之前",
+ "Snore Detected": "檢測到打鼾",
+ "Talk Detected": "檢測到說話",
+ "Cough Detected": "檢測到咳嗽",
+ "Baby Cry Detected": "檢測到嬰兒哭聲",
+ "Laugh Detected": "檢測到笑聲",
+ "Alarm Rescheduled": "鬧鐘重新安排",
+ "None": "無"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/ru.json b/custom_components/sleepd/translations/ru.json
similarity index 91%
rename from custom_components/saas/translations/ru.json
rename to custom_components/sleepd/translations/ru.json
index fbbed4a..4b7d130 100644
--- a/custom_components/saas/translations/ru.json
+++ b/custom_components/sleepd/translations/ru.json
@@ -1,10 +1,10 @@
{
- "title": "SAAS - Статус Sleep As Android",
+ "title": "sleepd - Статус Sleep As Android",
"config": {
"step": {
"user": {
- "title": "Конфигурация для SAAS - Статус Sleep As Android",
- "description": "Настройка основных параметров для интеграции SAAS.",
+ "title": "Конфигурация для sleepd - Статус Sleep As Android",
+ "description": "Настройка основных параметров для интеграции sleepd.",
"data": {
"name": "Имя для датчика",
"topic_template": "Тема MQTT для событий Sleep As Android",
@@ -20,8 +20,8 @@
"options": {
"step": {
"init": {
- "title": "Настройки интеграции SAAS",
- "description": "Настройка основных параметров для интеграции SAAS.",
+ "title": "Настройки интеграции sleepd",
+ "description": "Настройка основных параметров для интеграции sleepd.",
"data": {
"name": "Имя для датчика",
"topic_template": "Тема MQTT (от Sleep As Android)",
diff --git a/custom_components/saas/translations/sv.json b/custom_components/sleepd/translations/sv.json
similarity index 89%
rename from custom_components/saas/translations/sv.json
rename to custom_components/sleepd/translations/sv.json
index 5c6ed52..5b944e7 100644
--- a/custom_components/saas/translations/sv.json
+++ b/custom_components/sleepd/translations/sv.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Sleep As Android Status",
- "config": {
- "step": {
- "user": {
- "title": "Konfiguration för SAAS - Sleep As Android Status",
- "description": "Konfigurera de grundläggande inställningarna för SAAS-integrationen.",
- "data": {
- "name": "Namn för Sensor",
- "topic_template": "MQTT Ämne för Sleep As Android Händelser",
- "qos": "Kvalitet på Tjänst (QoS) för MQTT",
- "awake_duration": "Vaken Varaktighet",
- "sleep_duration": "Sovande Varaktighet",
- "awake_states": "Vakna Tillstånd*",
- "sleep_states": "Sovande Tillstånd*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "SAAS Integrationsinställningar",
- "description": "Konfigurera de grundläggande inställningarna för SAAS-integrationen.",
- "data": {
- "name": "Namn för Sensor",
- "topic_template": "MQTT Ämne (från Sleep As Android)",
- "qos": "MQTT Kvalitet på Tjänst (QoS)",
- "awake_duration": "Vaken Varaktighet",
- "sleep_duration": "Sovande Varaktighet",
- "awake_states": "Vakna Tillstånd*",
- "sleep_states": "Sovande Tillstånd*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "Okänd",
- "Sleep Tracking Started": "Sömnmätning Startad",
- "Sleep Tracking Stopped": "Sömnmätning Stoppad",
- "Sleep Tracking Paused": "Sömnmätning Pausad",
- "Sleep Tracking Resumed": "Sömnmätning Återupptagen",
- "Alarm Snoozed": "Alarm Snoozed",
- "Snooze Canceled": "Snooze Avbruten",
- "Time for Bed": "Dags att Gå och Lägga Sig",
- "Alarm Alert Started": "Alarmvarning Startad",
- "Alarm Dismissed": "Alarm Avvisat",
- "Skip Next Alarm": "Hoppa över Nästa Alarm",
- "Show Skip Next Alarm": "Visa 'Hoppa över Nästa Alarm'",
- "REM": "REM",
- "Smart Period": "Smart Period",
- "Before Smart Period": "Före Smart Period",
- "Lullaby Start": "Vaggvisa Start",
- "Lullaby Stop": "Vaggvisa Stopp",
- "Lullaby Volume Down": "Vaggvisa Volym Ner",
- "Deep Sleep": "Djup Sömn",
- "Light Sleep": "Lätt Sömn",
- "Awake": "Vaken",
- "Not Awake": "Inte Vaken",
- "Apnea Alarm": "Apné Alarm",
- "Antisnoring": "Antisnarkning",
- "Before Alarm": "Före Alarm",
- "Snore Detected": "Snarkning Upptäckt",
- "Talk Detected": "Prat Upptäckt",
- "Cough Detected": "Hosta Upptäckt",
- "Baby Cry Detected": "Bebisgråt Upptäckt",
- "Laugh Detected": "Skratt Upptäckt",
- "Alarm Rescheduled": "Alarm Omplanerat",
- "None": "Ingen"
- }
- }
- }
+{
+ "title": "sleepd - Sleep As Android Status",
+ "config": {
+ "step": {
+ "user": {
+ "title": "Konfiguration för sleepd - Sleep As Android Status",
+ "description": "Konfigurera de grundläggande inställningarna för sleepd-integrationen.",
+ "data": {
+ "name": "Namn för Sensor",
+ "topic_template": "MQTT Ämne för Sleep As Android Händelser",
+ "qos": "Kvalitet på Tjänst (QoS) för MQTT",
+ "awake_duration": "Vaken Varaktighet",
+ "sleep_duration": "Sovande Varaktighet",
+ "awake_states": "Vakna Tillstånd*",
+ "sleep_states": "Sovande Tillstånd*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "sleepd Integrationsinställningar",
+ "description": "Konfigurera de grundläggande inställningarna för sleepd-integrationen.",
+ "data": {
+ "name": "Namn för Sensor",
+ "topic_template": "MQTT Ämne (från Sleep As Android)",
+ "qos": "MQTT Kvalitet på Tjänst (QoS)",
+ "awake_duration": "Vaken Varaktighet",
+ "sleep_duration": "Sovande Varaktighet",
+ "awake_states": "Vakna Tillstånd*",
+ "sleep_states": "Sovande Tillstånd*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "Okänd",
+ "Sleep Tracking Started": "Sömnmätning Startad",
+ "Sleep Tracking Stopped": "Sömnmätning Stoppad",
+ "Sleep Tracking Paused": "Sömnmätning Pausad",
+ "Sleep Tracking Resumed": "Sömnmätning Återupptagen",
+ "Alarm Snoozed": "Alarm Snoozed",
+ "Snooze Canceled": "Snooze Avbruten",
+ "Time for Bed": "Dags att Gå och Lägga Sig",
+ "Alarm Alert Started": "Alarmvarning Startad",
+ "Alarm Dismissed": "Alarm Avvisat",
+ "Skip Next Alarm": "Hoppa över Nästa Alarm",
+ "Show Skip Next Alarm": "Visa 'Hoppa över Nästa Alarm'",
+ "REM": "REM",
+ "Smart Period": "Smart Period",
+ "Before Smart Period": "Före Smart Period",
+ "Lullaby Start": "Vaggvisa Start",
+ "Lullaby Stop": "Vaggvisa Stopp",
+ "Lullaby Volume Down": "Vaggvisa Volym Ner",
+ "Deep Sleep": "Djup Sömn",
+ "Light Sleep": "Lätt Sömn",
+ "Awake": "Vaken",
+ "Not Awake": "Inte Vaken",
+ "Apnea Alarm": "Apné Alarm",
+ "Antisnoring": "Antisnarkning",
+ "Before Alarm": "Före Alarm",
+ "Snore Detected": "Snarkning Upptäckt",
+ "Talk Detected": "Prat Upptäckt",
+ "Cough Detected": "Hosta Upptäckt",
+ "Baby Cry Detected": "Bebisgråt Upptäckt",
+ "Laugh Detected": "Skratt Upptäckt",
+ "Alarm Rescheduled": "Alarm Omplanerat",
+ "None": "Ingen"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/custom_components/saas/translations/zh.json b/custom_components/sleepd/translations/zh.json
similarity index 87%
rename from custom_components/saas/translations/zh.json
rename to custom_components/sleepd/translations/zh.json
index 3ca0f23..5bf714f 100644
--- a/custom_components/saas/translations/zh.json
+++ b/custom_components/sleepd/translations/zh.json
@@ -1,75 +1,75 @@
-{
- "title": "SAAS - Sleep As Android 状态",
- "config": {
- "step": {
- "user": {
- "title": "SAAS - Sleep As Android 状态配置",
- "description": "配置 SAAS 集成的基本设置。",
- "data": {
- "name": "传感器名称",
- "topic_template": "Sleep As Android 事件的 MQTT 主题",
- "qos": "MQTT 的服务质量 (QoS)",
- "awake_duration": "清醒持续时间",
- "sleep_duration": "睡眠持续时间",
- "awake_states": "清醒状态*",
- "sleep_states": "睡眠状态*"
- }
- }
- }
- },
- "options": {
- "step": {
- "init": {
- "title": "SAAS 集成设置",
- "description": "配置 SAAS 集成的基本设置。",
- "data": {
- "name": "传感器名称",
- "topic_template": "Sleep As Android 的 MQTT 主题",
- "qos": "MQTT 的服务质量 (QoS)",
- "awake_duration": "清醒持续时间",
- "sleep_duration": "睡眠持续时间",
- "awake_states": "清醒状态*",
- "sleep_states": "睡眠状态*"
- }
- }
- }
- },
- "entity": {
- "sensor": {
- "state": {
- "Unknown": "未知",
- "Sleep Tracking Started": "开始睡眠跟踪",
- "Sleep Tracking Stopped": "停止睡眠跟踪",
- "Sleep Tracking Paused": "暂停睡眠跟踪",
- "Sleep Tracking Resumed": "恢复睡眠跟踪",
- "Alarm Snoozed": "闹钟贪睡",
- "Snooze Canceled": "取消贪睡",
- "Time for Bed": "该睡觉了",
- "Alarm Alert Started": "闹钟警报开始",
- "Alarm Dismissed": "闹钟解除",
- "Skip Next Alarm": "跳过下一个闹钟",
- "Show Skip Next Alarm": "显示跳过下一个闹钟",
- "REM": "REM",
- "Smart Period": "智能周期",
- "Before Smart Period": "在智能周期之前",
- "Lullaby Start": "开始摇篮曲",
- "Lullaby Stop": "停止摇篮曲",
- "Lullaby Volume Down": "降低摇篮曲音量",
- "Deep Sleep": "深度睡眠",
- "Light Sleep": "浅睡",
- "Awake": "清醒",
- "Not Awake": "未清醒",
- "Apnea Alarm": "呼吸暂停警报",
- "Antisnoring": "防打鼾",
- "Before Alarm": "在闹钟之前",
- "Snore Detected": "检测到打鼾",
- "Talk Detected": "检测到说话",
- "Cough Detected": "检测到咳嗽",
- "Baby Cry Detected": "检测到婴儿哭声",
- "Laugh Detected": "检测到笑声",
- "Alarm Rescheduled": "闹钟重新安排",
- "None": "无"
- }
- }
- }
+{
+ "title": "sleepd - Sleep As Android 状态",
+ "config": {
+ "step": {
+ "user": {
+ "title": "sleepd - Sleep As Android 状态配置",
+ "description": "配置 sleepd 集成的基本设置。",
+ "data": {
+ "name": "传感器名称",
+ "topic_template": "Sleep As Android 事件的 MQTT 主题",
+ "qos": "MQTT 的服务质量 (QoS)",
+ "awake_duration": "清醒持续时间",
+ "sleep_duration": "睡眠持续时间",
+ "awake_states": "清醒状态*",
+ "sleep_states": "睡眠状态*"
+ }
+ }
+ }
+ },
+ "options": {
+ "step": {
+ "init": {
+ "title": "sleepd 集成设置",
+ "description": "配置 sleepd 集成的基本设置。",
+ "data": {
+ "name": "传感器名称",
+ "topic_template": "Sleep As Android 的 MQTT 主题",
+ "qos": "MQTT 的服务质量 (QoS)",
+ "awake_duration": "清醒持续时间",
+ "sleep_duration": "睡眠持续时间",
+ "awake_states": "清醒状态*",
+ "sleep_states": "睡眠状态*"
+ }
+ }
+ }
+ },
+ "entity": {
+ "sensor": {
+ "state": {
+ "Unknown": "未知",
+ "Sleep Tracking Started": "开始睡眠跟踪",
+ "Sleep Tracking Stopped": "停止睡眠跟踪",
+ "Sleep Tracking Paused": "暂停睡眠跟踪",
+ "Sleep Tracking Resumed": "恢复睡眠跟踪",
+ "Alarm Snoozed": "闹钟贪睡",
+ "Snooze Canceled": "取消贪睡",
+ "Time for Bed": "该睡觉了",
+ "Alarm Alert Started": "闹钟警报开始",
+ "Alarm Dismissed": "闹钟解除",
+ "Skip Next Alarm": "跳过下一个闹钟",
+ "Show Skip Next Alarm": "显示跳过下一个闹钟",
+ "REM": "REM",
+ "Smart Period": "智能周期",
+ "Before Smart Period": "在智能周期之前",
+ "Lullaby Start": "开始摇篮曲",
+ "Lullaby Stop": "停止摇篮曲",
+ "Lullaby Volume Down": "降低摇篮曲音量",
+ "Deep Sleep": "深度睡眠",
+ "Light Sleep": "浅睡",
+ "Awake": "清醒",
+ "Not Awake": "未清醒",
+ "Apnea Alarm": "呼吸暂停警报",
+ "Antisnoring": "防打鼾",
+ "Before Alarm": "在闹钟之前",
+ "Snore Detected": "检测到打鼾",
+ "Talk Detected": "检测到说话",
+ "Cough Detected": "检测到咳嗽",
+ "Baby Cry Detected": "检测到婴儿哭声",
+ "Laugh Detected": "检测到笑声",
+ "Alarm Rescheduled": "闹钟重新安排",
+ "None": "无"
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/hacs.json b/hacs.json
index 3d49d92..dee2135 100644
--- a/hacs.json
+++ b/hacs.json
@@ -1,4 +1,4 @@
{
- "name": "SAAS - Sleep As Android Status",
+ "name": "sleepd - Sleep As Android Status",
"render_readme": true
}