15 Commits

Author SHA1 Message Date
ryanbdclark
975e98c337 Update CHANGELOG.md 2025-04-11 13:35:12 +01:00
RyanClark123
268365ccd4 Bumping pyowletapi
### Fix
* Bumping pyowletapi to 2025.4.0
2025-04-11 13:34:11 +01:00
ryanbdclark
ac9c8c6111 Update manifest.json
Added documentation link
2025-04-05 21:42:48 +01:00
ryanbdclark
4fa40f8621 Update manifest.json
Remove documentation link
2025-04-05 21:38:38 +01:00
RyanClark123
dd17aca283 Merge branch 'main' of https://github.com/ryanbdclark/owlet 2024-10-10 11:23:35 +01:00
RyanClark123
91578464de Refactoring
### Fix
* Refactoring
* Changed switch to follow a more homeassistant pattern and allow for easier addition of future switches
2024-10-10 11:23:30 +01:00
ryanbdclark
e28b9ddf3e Update CHANGELOG.md 2024-10-09 20:55:37 +01:00
RyanClark123
f63e0a6dfe Added base station as a switch
### Feature
* Base station has now been removed from binary sensors and added as a switch
2024-10-09 20:51:05 +01:00
RyanClark123
82823be1c8 Bump pyowletapi
### Fix
* Bump pyowletapi to 2024.10.1
2024-10-09 20:03:14 +01:00
RyanClark123
14787e03c4 Correct strings for password and connection error
### Fix
* Fix strings for password and connection error in all languages
2024-10-09 16:31:45 +01:00
RyanClark123
0991eb31d9 Add state class
### Fix
* Add state class to battery minutes and O2 saturation 10 minute average
2024-10-09 15:19:28 +01:00
RyanClark123
ad91a851fc Update changelog and version
Update changelog and version
2024-09-26 10:18:03 +01:00
ryanbdclark
339dc43d6d Merge pull request #18 from Julien80/patch-1
Add translation fr
2024-09-26 10:14:03 +01:00
Julien80
f3c853e2d7 Add translation fr 2024-09-26 10:26:00 +02:00
ryanbdclark
dfc2ffc0e1 Update hacs.json 2024-07-09 07:29:05 +01:00
13 changed files with 363 additions and 119 deletions

View File

@@ -1,6 +1,22 @@
# Changelog # Changelog
<!--next-version-placeholder--> <!--next-version-placeholder-->
## 2025.4.0 (2025-04-0)
### Fix
* Bumping pyowletapi to 2025.4.0 ([`268365c`](https://github.com/ryanbdclark/owlet/commit/268365ccd428418dd5707f0569ce738b54a12fdd))
## 2024.10.1 (2024-10-09)
### Feature
* Base station has now been removed from binary sensors and added as a switch ([`f63e0a6`](https://github.com/ryanbdclark/owlet/commit/f63e0a6dfeab1a05ba09ef3e0087cb404ba0dac4))
### Fix
* Bump pyowletapi to 2024.10.1 ([`82823be`](https://github.com/ryanbdclark/owlet/commit/82823be1c8265d2b9431771136853febef648650))
* Fix strings for password and connection error in all languages ([`14787e0`](https://github.com/ryanbdclark/owlet/commit/14787e03c4d275f46f446921a3ee133fc7cfd1b1))
* Add state class to battery minutes and O2 saturation 10 minute average ([`0991eb3`](https://github.com/ryanbdclark/owlet/commit/0991eb31d919f3ee9f65ece793166d7ee3e33c38))
## 2024.9.1 (2024-09-26)
### Feature
* Now includes French translation, thanks [`@Julien80`](https://github.com/Julien80) ([`f3c853e`](https://github.com/ryanbdclark/owlet/commit/f3c853e2d7243d766889f2d18c718819da30e4be))
## 2024.6.1 (2024-06-17) ## 2024.6.1 (2024-06-17)
### Fix ### Fix
* Bumping pyowletapi to 2024.6.1 to resolve setup errors ([`52710ba`](https://github.com/ryanbdclark/owlet/commit/52710ba7de53fd07195537c2a5fd2f95bc7dfd1a)) * Bumping pyowletapi to 2024.6.1 to resolve setup errors ([`52710ba`](https://github.com/ryanbdclark/owlet/commit/52710ba7de53fd07195537c2a5fd2f95bc7dfd1a))

View File

@@ -30,7 +30,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import CONF_OWLET_EXPIRY, CONF_OWLET_REFRESH, DOMAIN, SUPPORTED_VERSIONS from .const import CONF_OWLET_EXPIRY, CONF_OWLET_REFRESH, DOMAIN, SUPPORTED_VERSIONS
from .coordinator import OwletCoordinator from .coordinator import OwletCoordinator
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR] PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR, Platform.SWITCH]
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View File

@@ -92,12 +92,6 @@ SENSORS: tuple[OwletBinarySensorEntityDescription, ...] = (
device_class=BinarySensorDeviceClass.POWER, device_class=BinarySensorDeviceClass.POWER,
available_during_charging=True, available_during_charging=True,
), ),
OwletBinarySensorEntityDescription(
key="base_station_on",
translation_key="base_on",
device_class=BinarySensorDeviceClass.POWER,
available_during_charging=True,
),
) )
@@ -112,9 +106,11 @@ async def async_setup_entry(
sensors = [] sensors = []
for coordinator in coordinators: for coordinator in coordinators:
for sensor in SENSORS: sensors = [
if sensor.key in coordinator.sock.properties: OwletBinarySensor(coordinator, sensor)
sensors.append(OwletBinarySensor(coordinator, sensor)) for sensor in SENSORS
if sensor.key in coordinator.sock.properties
]
if OwletAwakeSensor.entity_description.key in coordinator.sock.properties: if OwletAwakeSensor.entity_description.key in coordinator.sock.properties:
sensors.append(OwletAwakeSensor(coordinator)) sensors.append(OwletAwakeSensor(coordinator))
@@ -146,13 +142,6 @@ class OwletBinarySensor(OwletBaseEntity, BinarySensorEntity):
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return true if the binary sensor is on.""" """Return true if the binary sensor is on."""
if self.entity_description.key == "sleep_state":
if self.sock.properties["charging"]:
return None
if state in [8, 15]:
state = False
else:
state = True
return self.sock.properties[self.entity_description.key] return self.sock.properties[self.entity_description.key]
@@ -177,4 +166,4 @@ class OwletAwakeSensor(OwletBinarySensor):
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return true if the binary sensor is on.""" """Return true if the binary sensor is on."""
return False if self.sock.properties[self.entity_description.key] in [8, 15] else True return self.sock.properties[self.entity_description.key] not in [8, 15]

View File

@@ -1,4 +1,5 @@
"""Config flow for Owlet Smart Sock integration.""" """Config flow for Owlet Smart Sock integration."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Mapping from collections.abc import Mapping
@@ -15,19 +16,17 @@ from pyowletapi.exceptions import (
import voluptuous as vol import voluptuous as vol
from homeassistant import config_entries, exceptions from homeassistant import config_entries, exceptions
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry, ConfigFlowResult
from homeassistant.const import ( from homeassistant.const import (
CONF_API_TOKEN,
CONF_PASSWORD, CONF_PASSWORD,
CONF_REGION, CONF_REGION,
CONF_SCAN_INTERVAL, CONF_SCAN_INTERVAL,
CONF_USERNAME, CONF_USERNAME,
) )
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import CONF_OWLET_EXPIRY, CONF_OWLET_REFRESH, DOMAIN, POLLING_INTERVAL from .const import DOMAIN, POLLING_INTERVAL
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -51,7 +50,7 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def async_step_user( async def async_step_user(
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
) -> FlowResult: ) -> ConfigFlowResult:
"""Handle the initial step.""" """Handle the initial step."""
errors: dict[str, str] = {} errors: dict[str, str] = {}
if user_input is not None: if user_input is not None:
@@ -101,7 +100,9 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Get the options flow for this handler.""" """Get the options flow for this handler."""
return OptionsFlowHandler(config_entry) return OptionsFlowHandler(config_entry)
async def async_step_reauth(self, user_input: Mapping[str, Any]) -> FlowResult: async def async_step_reauth(
self, user_input: Mapping[str, Any]
) -> ConfigFlowResult:
"""Handle reauth.""" """Handle reauth."""
self.reauth_entry = self.hass.config_entries.async_get_entry( self.reauth_entry = self.hass.config_entries.async_get_entry(
self.context["entry_id"] self.context["entry_id"]
@@ -110,7 +111,7 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def async_step_reauth_confirm( async def async_step_reauth_confirm(
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
) -> FlowResult: ) -> ConfigFlowResult:
"""Dialog that informs the user that reauth is required.""" """Dialog that informs the user that reauth is required."""
assert self.reauth_entry is not None assert self.reauth_entry is not None
errors: dict[str, str] = {} errors: dict[str, str] = {}
@@ -130,7 +131,9 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self.reauth_entry, data={**entry_data, **token} self.reauth_entry, data={**entry_data, **token}
) )
await self.hass.config_entries.async_reload(self.reauth_entry.entry_id) await self.hass.config_entries.async_reload(
self.reauth_entry.entry_id
)
return self.async_abort(reason="reauth_successful") return self.async_abort(reason="reauth_successful")
@@ -155,7 +158,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
async def async_step_init( async def async_step_init(
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
) -> FlowResult: ) -> ConfigFlowResult:
"""Handle options flow.""" """Handle options flow."""
if user_input is not None: if user_input is not None:
return self.async_create_entry(title="", data=user_input) return self.async_create_entry(title="", data=user_input)

View File

@@ -1,11 +1,11 @@
"""Base class for Owlet entities.""" """Base class for Owlet entities."""
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.helpers.device_registry import DeviceInfo
from .coordinator import OwletCoordinator
from .const import DOMAIN, MANUFACTURER from .const import DOMAIN, MANUFACTURER
from .coordinator import OwletCoordinator
class OwletBaseEntity(CoordinatorEntity[OwletCoordinator], Entity): class OwletBaseEntity(CoordinatorEntity[OwletCoordinator], Entity):

View File

@@ -5,11 +5,11 @@
"@ryanbdclark" "@ryanbdclark"
], ],
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/owlet", "documentation":"https://github.com/ryanbdclark/owlet",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"issue_tracker": "https://github.com/ryanbdclark/owlet/issues", "issue_tracker": "https://github.com/ryanbdclark/owlet/issues",
"requirements": [ "requirements": [
"pyowletapi==2024.6.1" "pyowletapi==2025.4.0"
], ],
"version": "2024.6.1" "version": "2025.4.0"
} }

View File

@@ -63,6 +63,7 @@ SENSORS: tuple[OwletSensorEntityDescription, ...] = (
translation_key="batterymin", translation_key="batterymin",
native_unit_of_measurement=UnitOfTime.MINUTES, native_unit_of_measurement=UnitOfTime.MINUTES,
device_class=SensorDeviceClass.DURATION, device_class=SensorDeviceClass.DURATION,
state_class=SensorStateClass.MEASUREMENT,
available_during_charging=False, available_during_charging=False,
), ),
OwletSensorEntityDescription( OwletSensorEntityDescription(
@@ -114,13 +115,18 @@ async def async_setup_entry(
sensors = [] sensors = []
for coordinator in coordinators: for coordinator in coordinators:
for sensor in SENSORS: sensors = [
if sensor.key in coordinator.sock.properties: OwletSensor(coordinator, sensor)
sensors.append(OwletSensor(coordinator, sensor)) for sensor in SENSORS
if sensor.key in coordinator.sock.properties
]
if OwletSleepSensor.entity_description.key in coordinator.sock.properties: if OwletSleepSensor.entity_description.key in coordinator.sock.properties:
sensors.append(OwletSleepSensor(coordinator)) sensors.append(OwletSleepSensor(coordinator))
if OwletOxygenAverageSensor.entity_description.key in coordinator.sock.properties: if (
OwletOxygenAverageSensor.entity_description.key
in coordinator.sock.properties
):
sensors.append(OwletOxygenAverageSensor(coordinator)) sensors.append(OwletOxygenAverageSensor(coordinator))
async_add_entities(sensors) async_add_entities(sensors)
@@ -187,6 +193,7 @@ class OwletOxygenAverageSensor(OwletSensor):
native_unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
icon="mdi:leaf", icon="mdi:leaf",
available_during_charging=False, available_during_charging=False,
state_class=SensorStateClass.MEASUREMENT,
) )
def __init__( def __init__(
@@ -199,8 +206,14 @@ class OwletOxygenAverageSensor(OwletSensor):
@property @property
def available(self) -> bool: def available(self) -> bool:
"""Return if entity is available.""" """Return if entity is available."""
return super().available and ( return (
not self.sock.properties["charging"] super().available
or self.entity_description.available_during_charging and (
) and (self.sock.properties["oxygen_10_av"] >= 0 and self.sock.properties["oxygen_10_av"] <= 100) not self.sock.properties["charging"]
or self.entity_description.available_during_charging
)
and (
self.sock.properties["oxygen_10_av"] >= 0
and self.sock.properties["oxygen_10_av"] <= 100
)
)

View File

@@ -74,9 +74,6 @@
}, },
"awake": { "awake": {
"name": "Awake" "name": "Awake"
},
"base_on": {
"name": "Base station on"
} }
}, },
"sensor": { "sensor": {
@@ -116,6 +113,11 @@
"movementbucket": { "movementbucket": {
"name": "Movement bucket" "name": "Movement bucket"
} }
},
"switch": {
"base_on": {
"name": "Base station on"
}
} }
} }
} }

View File

@@ -0,0 +1,94 @@
"""Support for Owlet switches."""
from __future__ import annotations
from collections.abc import Callable, Coroutine
from dataclasses import dataclass
from datetime import timedelta
from typing import Any
from pyowletapi.sock import Sock
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .coordinator import OwletCoordinator
from .entity import OwletBaseEntity
SCAN_INTERVAL = timedelta(seconds=5)
PARALLEL_UPDATES = 0
@dataclass(frozen=True, kw_only=True)
class OwletSwitchEntityDescription(SwitchEntityDescription):
"""Describes Owlet switch entity."""
turn_on_fn: Callable[[Sock], Callable[[bool], Coroutine[Any, Any, None]]]
turn_off_fn: Callable[[Sock], Callable[[bool], Coroutine[Any, Any, None]]]
available_during_charging: bool
SWITCHES: tuple[OwletSwitchEntityDescription, ...] = (
OwletSwitchEntityDescription(
key="base_station_on",
translation_key="base_on",
turn_on_fn=lambda sock: (lambda state: sock.control_base_station(state)),
turn_off_fn=lambda sock: (lambda state: sock.control_base_station(state)),
available_during_charging=False,
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Owlet switch based on a config entry."""
coordinators: OwletCoordinator = hass.data[DOMAIN][config_entry.entry_id].values()
switches = []
for coordinator in coordinators:
switches = [OwletBaseSwitch(coordinator, switch) for switch in SWITCHES]
async_add_entities(switches)
class OwletBaseSwitch(OwletBaseEntity, SwitchEntity):
"""Defines a Owlet switch."""
entity_description: OwletSwitchEntityDescription
def __init__(
self,
coordinator: OwletCoordinator,
description: OwletSwitchEntityDescription,
) -> None:
"""Initialize owlet switch platform."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{self.sock.serial}-{description.key}"
self._attr_is_on = False
@property
def available(self) -> bool:
"""Return if entity is available."""
return super().available and (
not self.sock.properties["charging"]
or self.entity_description.available_during_charging
)
@property
def is_on(self) -> bool:
"""Return if switch is on or off."""
return self.sock.properties[self.entity_description.key]
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the switch."""
await self.entity_description.turn_on_fn(self.sock)(True)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the switch."""
await self.entity_description.turn_off_fn(self.sock)(False)

View File

@@ -1,90 +1,86 @@
{ {
"config": { "config": {
"step": {
"user": {
"data": {
"region": "Region",
"username": "Email",
"password": "[%key:common::config_flow::data::password%]"
}
},
"reauth_confirm": {
"title": "Reauthentiaction required for Owlet",
"data": {
"password": "[%key:common::config_flow::data::password%]"
}
}
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_email": "Entered email address is incorrect",
"invalid_password": "Entered password is incorrect",
"invalid_credentials": "Entered credentials are incorrect",
"unknown": "Unknown error occured"
},
"abort": { "abort": {
"already_configured": "Device already configured", "already_configured": "Device already configured",
"reauth_successful": "Reauthentication successful" "reauth_successful": "Reauthentication successful"
} },
}, "error": {
"options": { "cannot_connect": "Failed to connect",
"invalid_credentials": "Entered credentials are incorrect",
"invalid_email": "Entered email address is incorrect",
"invalid_password": "Entered password is incorrect",
"unknown": "Unknown error occured"
},
"step": { "step": {
"init": { "reauth_confirm": {
"title": "Configure options for Owlet",
"data": { "data": {
"pollinterval": "Polling interval in seconds, min 10" "password": "Password"
},
"title": "Reauthentiaction required for Owlet"
},
"user": {
"data": {
"password": "Password",
"region": "Region",
"username": "Email"
} }
} }
} }
}, },
"entity": { "entity": {
"binary_sensor": { "binary_sensor": {
"awake": {
"name": "Awake"
},
"charging": { "charging": {
"name": "Charging" "name": "Charging"
}, },
"high_hr_alrt": {
"name": "High heart rate alert"
},
"low_hr_alrt": {
"name": "Low heart rate alert"
},
"high_ox_alrt": {
"name": "High oxygen alert"
},
"low_ox_alrt": {
"name": "Low oxygen alert"
},
"crit_ox_alrt": {
"name": "Critical oxygen alert"
},
"low_batt_alrt": {
"name": "Low battery alert"
},
"crit_batt_alrt": { "crit_batt_alrt": {
"name": "Critical battery alert" "name": "Critical battery alert"
}, },
"crit_ox_alrt": {
"name": "Critical oxygen alert"
},
"high_hr_alrt": {
"name": "High heart rate alert"
},
"high_ox_alrt": {
"name": "High oxygen alert"
},
"lost_pwr_alrt": { "lost_pwr_alrt": {
"name": "Lost power alert" "name": "Lost power alert"
}, },
"low_batt_alrt": {
"name": "Low battery alert"
},
"low_hr_alrt": {
"name": "Low heart rate alert"
},
"low_ox_alrt": {
"name": "Low oxygen alert"
},
"sock_discon_alrt": { "sock_discon_alrt": {
"name": "Sock disconnected alert" "name": "Sock disconnected alert"
}, },
"sock_off": { "sock_off": {
"name": "Sock off" "name": "Sock off"
},
"awake": {
"name": "Awake"
},
"base_on": {
"name": "Base station on"
} }
}, },
"sensor": { "sensor": {
"batterymin": {
"name": "Battery remaining"
},
"batterypercent": { "batterypercent": {
"name": "Battery percentage" "name": "Battery percentage"
}, },
"signalstrength": { "heartrate": {
"name": "Signal strength" "name": "Heart rate"
},
"movement": {
"name": "Movement"
},
"movementbucket": {
"name": "Movement bucket"
}, },
"o2saturation": { "o2saturation": {
"name": "O2 saturation" "name": "O2 saturation"
@@ -92,11 +88,8 @@
"o2saturation10a": { "o2saturation10a": {
"name": "O2 saturation 10 minute average" "name": "O2 saturation 10 minute average"
}, },
"heartrate": { "signalstrength": {
"name": "Heart rate" "name": "Signal strength"
},
"batterymin": {
"name": "Battery remaining"
}, },
"skintemp": { "skintemp": {
"name": "Skin temperature" "name": "Skin temperature"
@@ -104,17 +97,26 @@
"sleepstate": { "sleepstate": {
"name": "Sleep state", "name": "Sleep state",
"state": { "state": {
"unknown": "Unknown",
"awake": "Awake", "awake": "Awake",
"deep_sleep": "Deep sleep",
"light_sleep": "Light sleep", "light_sleep": "Light sleep",
"deep_sleep": "Deep sleep" "unknown": "Unknown"
} }
}, }
"movement": { },
"name": "Movement" "switch": {
}, "base_on": {
"movementbucket": { "name": "Base station on"
"name": "Movement bucket" }
}
},
"options": {
"step": {
"init": {
"data": {
"pollinterval": "Polling interval in seconds, min 10"
},
"title": "Configure options for Owlet"
} }
} }
} }

View File

@@ -0,0 +1,123 @@
{
"config": {
"step": {
"user": {
"data": {
"region": "Région",
"username": "Email",
"password": "Mot de passe"
}
},
"reauth_confirm": {
"title": "Réauthentification requise pour Owlet",
"data": {
"password": "Mot de passe"
}
}
},
"error": {
"cannot_connect": "N'a pas réussi à se connecter",
"invalid_email": "L'adresse e-mail saisie est incorrecte",
"invalid_password": "Le mot de passe saisi est incorrect",
"invalid_credentials": "Les informations d'identification saisies sont incorrectes",
"unknown": "Une erreur inconnue est survenue"
},
"abort": {
"already_configured": "Appareil déjà configuré",
"reauth_successful": "Réauthentification réussie"
}
},
"options": {
"step": {
"init": {
"title": "Configurer les options pour Owlet",
"data": {
"pollinterval": "Intervalle de sondage en secondes, minimum 10"
}
}
}
},
"entity": {
"binary_sensor": {
"charging": {
"name": "En charge"
},
"high_hr_alrt": {
"name": "Alerte fréquence cardiaque élevée"
},
"low_hr_alrt": {
"name": "Alerte fréquence cardiaque basse"
},
"high_ox_alrt": {
"name": "Alerte oxygène élevé"
},
"low_ox_alrt": {
"name": "Alerte oxygène faible"
},
"crit_ox_alrt": {
"name": "Alerte oxygène critique"
},
"low_batt_alrt": {
"name": "Alerte batterie faible"
},
"crit_batt_alrt": {
"name": "Alerte batterie critique"
},
"lost_pwr_alrt": {
"name": "Alerte perte d'alimentation"
},
"sock_discon_alrt": {
"name": "Alerte chaussette déconnectée"
},
"sock_off": {
"name": "Chaussette retirée"
},
"awake": {
"name": "Réveillé"
}
},
"sensor": {
"batterypercent": {
"name": "Pourcentage de batterie"
},
"signalstrength": {
"name": "Force du signal"
},
"o2saturation": {
"name": "Saturation O2"
},
"o2saturation10a": {
"name": "Moyenne de saturation O2 sur 10 minutes"
},
"heartrate": {
"name": "Fréquence cardiaque"
},
"batterymin": {
"name": "Autonomie de la batterie restante"
},
"skintemp": {
"name": "Température de la peau"
},
"sleepstate": {
"name": "État de sommeil",
"state": {
"unknown": "Inconnu",
"awake": "Réveillé",
"light_sleep": "Sommeil léger",
"deep_sleep": "Sommeil profond"
}
},
"movement": {
"name": "Mouvement"
},
"movementbucket": {
"name": "Seuil de mouvement"
}
},
"switch": {
"base_on": {
"name": "Station de base allumée"
}
}
}
}

View File

@@ -5,18 +5,18 @@
"data": { "data": {
"region": "Region", "region": "Region",
"username": "Email", "username": "Email",
"password": "[%key:common::config_flow::data::password%]" "password": "Password"
} }
}, },
"reauth_confirm": { "reauth_confirm": {
"title": "Reauthentiaction required for Owlet", "title": "Reauthentiaction required for Owlet",
"data": { "data": {
"password": "[%key:common::config_flow::data::password%]" "password": "Password"
} }
} }
}, },
"error": { "error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "cannot_connect": "Failed to connect",
"invalid_email": "Entered email address is incorrect", "invalid_email": "Entered email address is incorrect",
"invalid_password": "Entered password is incorrect", "invalid_password": "Entered password is incorrect",
"invalid_credentials": "Entered credentials are incorrect", "invalid_credentials": "Entered credentials are incorrect",
@@ -74,9 +74,6 @@
}, },
"awake": { "awake": {
"name": "Awake" "name": "Awake"
},
"base_on": {
"name": "Base station on"
} }
}, },
"sensor": { "sensor": {
@@ -116,6 +113,11 @@
"movementbucket": { "movementbucket": {
"name": "Movement bucket" "name": "Movement bucket"
} }
},
"switch": {
"base_on": {
"name": "Base station on"
}
} }
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"name": "Owlet", "name": "Owlet",
"hacs": "1.32.1", "hacs": "1.32.1",
"homeassistant": "2023.04.1", "homeassistant": "2024.1",
"zip_release": true, "zip_release": true,
"filename": "owlet.zip" "filename": "owlet.zip"
} }