Add files via upload

0.0.3
Updated Wake Status sensor logic.
This commit is contained in:
sudoxnym 2024-05-10 19:34:59 -06:00 committed by GitHub
parent 2503c51dcc
commit 0ce35b4cab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 2000 additions and 0 deletions

View file

@ -0,0 +1,46 @@
import logging
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from .const import DOMAIN
from homeassistant.helpers.dispatcher import async_dispatcher_connect
_logger = logging.getLogger(__name__)
async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the SAAS - Sleep As Android Status component."""
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Set up a config entry."""
hass.data.setdefault(DOMAIN, {})
# Use hass.data[DOMAIN][entry.entry_id] instead of entry.options
if entry.entry_id in hass.data[DOMAIN]:
hass.data[DOMAIN][entry.entry_id] = hass.data[DOMAIN][entry.entry_id]
else:
hass.data[DOMAIN][entry.entry_id] = entry.data # Use entry.data instead of entry.options
# Forward the setup to the sensor platform
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, "sensor")
)
# Define a coroutine function to reload the entry
async def reload_entry():
await hass.config_entries.async_reload(entry.entry_id)
# Listen for the reload signal and reload the integration when it is received
async_dispatcher_connect(hass, f"{DOMAIN}_reload_{entry.entry_id}", reload_entry)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
# Remove the sensor platform
await hass.config_entries.async_forward_entry_unload(entry, "sensor")
# Ensure hass.data[DOMAIN] is a dictionary before popping
if isinstance(hass.data.get(DOMAIN, {}), dict):
if entry.entry_id in hass.data[DOMAIN]:
hass.data[DOMAIN].pop(entry.entry_id)
return True

View file

@ -0,0 +1,95 @@
import logging
import traceback
import voluptuous as vol
from .const import DOMAIN, CONF_NAME, CONF_TOPIC, CONF_QOS, 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
from homeassistant import config_entries
from homeassistant.core import callback
from voluptuous import Schema, Required, In
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send
_logger = logging.getLogger(__name__)
class MyConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH
async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
errors = {}
if user_input is not None:
return self.async_create_entry(title=user_input[CONF_NAME], data=user_input)
return self.async_show_form(
step_id="user",
data_schema=Schema(
{
Required(CONF_NAME): str,
Required(CONF_TOPIC): str,
Required(CONF_QOS, default=0): In([0, 1, 2]),
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),
}
),
errors=errors,
)
@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow for this handler."""
return OptionsFlowHandler(config_entry)
class OptionsFlowHandler(config_entries.OptionsFlow):
"""Handle options."""
def __init__(self, config_entry):
"""Initialize options flow."""
self.config_entry = config_entry
async def async_step_init(self, user_input=None):
"""Manage the options."""
_logger.debug("Entering async_step_init with user_input: %s", user_input)
try:
# Fetch the initial configuration data
current_data = self.hass.data[DOMAIN].get(self.config_entry.entry_id, self.config_entry.options)
_logger.debug("Current data fetched: %s", current_data)
if user_input is not None:
# Replace current_data with user_input
updated_data = user_input
_logger.debug("User input is not None, updated data: %s", updated_data)
_logger.debug("Updating entry with updated data: %s", updated_data)
if updated_data is not None:
self.hass.data[DOMAIN][self.config_entry.entry_id] = updated_data # Save updated data
self.config_entry.data = updated_data # Update the config entry data
self.hass.config_entries.async_update_entry(self.config_entry, data=updated_data) # Update the entry data
# Send a signal to reload the integration
async_dispatcher_send(self.hass, f"{DOMAIN}_reload_{self.config_entry.entry_id}")
return self.async_create_entry(title="", data=updated_data)
_logger.debug("User input is None, showing form with current_data: %s", current_data)
return self.async_show_form(step_id="init", data_schema=self.get_data_schema(current_data))
except Exception as e:
_logger.error("Error in async_step_init: %s", str(e))
return self.async_abort(reason=str(e))
def get_data_schema(self, current_data):
return Schema(
{
Required(CONF_NAME, default=current_data.get(CONF_NAME, "")): str,
Required(CONF_TOPIC, default=current_data.get(CONF_TOPIC, "")): str,
Required(CONF_QOS, default=current_data.get(CONF_QOS, 0)): In([0, 1, 2]),
Required(CONF_AWAKE_DURATION, default=current_data.get(CONF_AWAKE_DURATION, DEFAULT_AWAKE_DURATION)): int,
Required(CONF_SLEEP_DURATION, default=current_data.get(CONF_SLEEP_DURATION, DEFAULT_SLEEP_DURATION)): int,
Required(CONF_AWAKE_STATES, default=current_data.get(CONF_AWAKE_STATES, DEFAULT_AWAKE_STATES)): cv.multi_select(AVAILABLE_STATES),
Required(CONF_SLEEP_STATES, default=current_data.get(CONF_SLEEP_STATES, DEFAULT_SLEEP_STATES)): cv.multi_select(AVAILABLE_STATES),
}
)

View file

@ -0,0 +1,135 @@
"""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_QOS = "qos" # Quality of Service
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
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"},
}
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()}
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",
'rem': "REM",
'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"
}

View file

@ -0,0 +1,11 @@
{
"domain": "saas",
"name": "SAAS - Sleep As Android Status",
"codeowners": ["@sudoxnym"],
"config_flow": true,
"dependencies": ["mqtt"],
"documentation": "https://www.github.com/sudoxnym/saas",
"iot_class": "local_push",
"issue_tracker": "https://www.github.com/sudoxnym/saas/issues",
"version": "0.0.2"
}

View file

@ -0,0 +1,588 @@
import asyncio
import json
from datetime import timedelta, datetime
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.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
import logging
import time
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.DEBUG)
class SAASSensor(Entity):
"""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()
async def message_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json = json.loads(msg.payload)
_LOGGER.info(f"Received MQTT message: {msg_json}")
# Extract the EVENT field
event = msg_json.get('event')
if event is None:
_LOGGER.warning(f"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()
#else:
#_LOGGER.warning(f"No mapping found for event '{event}'")
# Subscribe to the topic from the user input
await async_subscribe(self._hass, self._hass.data[DOMAIN][self.entry_id][CONF_TOPIC], message_received)
class SAASAlarmEventSensor(Entity):
"""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._time = None
self.entry_id = entry_id
@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,
}
async def async_added_to_hass(self):
"""Run when entity about to be added."""
await super().async_added_to_hass()
async def message_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json = json.loads(msg.payload)
_LOGGER.info(f"Received MQTT message: {msg_json}")
# Extract the EVENT field
event = msg_json.get('event')
if event is None:
_LOGGER.warning(f"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)
class SAASSoundSensor(Entity):
"""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.entry_id = entry_id
@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,
}
async def async_added_to_hass(self):
"""Run when entity about to be added."""
await super().async_added_to_hass()
async def message_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json = json.loads(msg.payload)
_LOGGER.info(f"Received MQTT message: {msg_json}")
# Extract the EVENT field
event = msg_json.get('event')
if event is None:
#_LOGGER.warning(f"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, "None") # Default to "None" if no mapping found
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 message_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json = json.loads(msg.payload)
_LOGGER.info(f"Received MQTT message: {msg_json}")
# Extract the EVENT field
event = msg_json.get('event')
if event is None:
_LOGGER.warning(f"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, "None") # Default to "None" if no mapping found
if new_state is not None:
self._state = new_state
self.async_schedule_update_ha_state()
#else:
#_LOGGER.warning(f"No mapping found for event '{event}'")
class SAASSleepTrackingSensor(Entity):
"""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()
async def message_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json = json.loads(msg.payload)
_LOGGER.info(f"Received MQTT message: {msg_json}")
# Extract the EVENT field
event = msg_json.get('event')
if event is None:
#_LOGGER.warning(f"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, "None") # Default to "None" if no mapping found
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)
class SAASDisturbanceSensor(Entity):
"""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.entry_id = entry_id
@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,
}
async def async_added_to_hass(self):
"""Run when entity about to be added."""
await super().async_added_to_hass()
async def message_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json = json.loads(msg.payload)
_LOGGER.info(f"Received MQTT message: {msg_json}")
# Extract the EVENT field
event = msg_json.get('event')
if event is None:
#_LOGGER.warning(f"No 'event' key in the MQTT message: {msg_json}")
return
# Use the mapping to convert the event to the corresponding state
new_state = DISTURBANCE_MAPPING.get(event, "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)
class SAASLullabySensor(Entity):
"""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()
async def message_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json = json.loads(msg.payload)
_LOGGER.info(f"Received MQTT message: {msg_json}")
# Extract the EVENT field
event = msg_json.get('event')
if event is None:
#_LOGGER.warning(f"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, "None") # Default to "None" if no mapping found
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)
class SAASWakeStatusSensor(Entity):
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_bucket = []
self.sleep_bucket = []
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
@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')}: 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')}: 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')}: Event {event} could not be mapped to a known state. Setting sensor state to 'Unknown'.")
# If the mapped value is in the awake states, add it to the awake bucket and clear the sleep bucket
if mapped_value in self.awake_states:
self.awake_bucket.append((mapped_value, now))
self.sleep_bucket = []
_LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')}: Mapped value {mapped_value} is in awake states. Adding to awake bucket and clearing sleep bucket.")
# If the mapped value is in the sleep states, add it to the sleep bucket and clear the awake bucket
elif mapped_value in self.sleep_states:
self.sleep_bucket.append((mapped_value, now))
self.awake_bucket = []
_LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')}: Mapped value {mapped_value} is in sleep states. Adding to sleep bucket and clearing awake bucket.")
except Exception as e:
_LOGGER.error(f"Error processing message: {e}")
async def async_update(self, _=None):
"""Update the state."""
now = dt_util.utcnow()
# If any message in the awake bucket has reached the awake duration, set the state to "Awake"
if self.awake_bucket and any(now - timestamp >= self.awake_duration for _, timestamp in self.awake_bucket):
if self._state != "Awake":
_LOGGER.debug("State changed to 'Awake'")
self._state = "Awake"
# If any message in the sleep bucket has reached the sleep duration, set the state to "Asleep"
elif self.sleep_bucket and any(now - timestamp >= self.sleep_duration for _, timestamp in self.sleep_bucket):
if self._state != "Asleep":
_LOGGER.debug("State changed to 'Asleep'")
self._state = "Asleep"
# Remove messages from the awake bucket that are older than the awake duration and log if a message is removed
self.awake_bucket = [(val, timestamp) for val, timestamp in self.awake_bucket if now - timestamp < self.awake_duration or _LOGGER.debug("Removed message from awake bucket.") is None]
# Remove messages from the sleep bucket that are older than the sleep duration and log if a message is removed
self.sleep_bucket = [(val, timestamp) for val, timestamp in self.sleep_bucket if now - timestamp < self.sleep_duration or _LOGGER.debug("Removed message from sleep bucket.") is None]
# Log the contents of the awake bucket if it is not empty
if self.awake_bucket:
_LOGGER.debug(f"Awake bucket: {self.awake_bucket}")
# Log the contents of the sleep bucket if it is not empty
if self.sleep_bucket:
_LOGGER.debug(f"Sleep bucket: {self.sleep_bucket}")
async def interval_callback(self, _):
"""Wrapper function for async_track_time_interval."""
# Call the async_update method to update the state
await self.async_update()
async def async_added_to_hass(self):
"""Run when entity about to be added."""
await super().async_added_to_hass()
# Schedule the interval callback to run every second
async_track_time_interval(
self.hass,
self.interval_callback,
timedelta(seconds=1)
)
# 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_setup_entry(hass, entry, async_add_entities):
"""Set up the SAAS sensor platform from a config entry."""
name = hass.data[DOMAIN][entry.entry_id].get(CONF_NAME, "Default Name")
topic = hass.data[DOMAIN][entry.entry_id].get(CONF_TOPIC)
awake_states = hass.data[DOMAIN][entry.entry_id].get(CONF_AWAKE_STATES)
sleep_states = hass.data[DOMAIN][entry.entry_id].get(CONF_SLEEP_STATES)
awake_duration = hass.data[DOMAIN][entry.entry_id].get(CONF_AWAKE_DURATION)
sleep_duration = hass.data[DOMAIN][entry.entry_id].get(CONF_SLEEP_DURATION)
entities = [
SAASSensor(hass, name, STATE_MAPPING, entry_id),
SAASAlarmEventSensor(hass, name, ALARM_EVENT_MAPPING, 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),
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()
async_add_entities(entities)
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),
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),
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()
async_add_entities(entities)

View file

@ -0,0 +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": "لا شيء"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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": "無"
}
}
}
}

View file

@ -0,0 +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": "없음"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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": "無"
}
}
}
}

View file

@ -0,0 +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": "Нет"
}
}
}
}

View file

@ -0,0 +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"
}
}
}
}

View file

@ -0,0 +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": "无"
}
}
}
}