6 Commits

Author SHA1 Message Date
ryanbdclark
4b90ce0d61 Update CHANGELOG.md 2024-03-27 15:53:56 +00:00
RyanClark123
50c55dcfd3 Add binary sensor, correct interval input
### Feature
*Base station on added as binary sensor

### Fix
* Bumping pyowletapi to 2024.3.2
* UI config now allows you to set interval to 5 seconds, previously the minimum was 10
2024-03-27 15:51:12 +00:00
ryanbdclark
faefd0b18b Update info.md 2023-11-23 15:42:11 +00:00
ryanbdclark
1192b833ca Update README.md 2023-11-23 15:41:37 +00:00
ryanbdclark
d440fed621 Update CHANGELOG.md 2023-11-23 15:41:03 +00:00
RyanClark123
50fe1a8765 Support for V2 sock added
### Feature
* Support added for V2 sock
* Added tests for binary sensors
### Fix
* Bumping pyowletapi to 2023.11.4 to allow V2 support
* Refactoring
* Corrected spelling of sock disconnected sensor
2023-11-23 15:38:35 +00:00
19 changed files with 1603 additions and 134 deletions

View File

@@ -1,6 +1,23 @@
# Changelog # Changelog
<!--next-version-placeholder--> <!--next-version-placeholder-->
##2024.3.1
### Feature
* Base station on added as binary sensor ([`50c55dc`](https://github.com/ryanbdclark/owlet/commit/50c55dcfd30d15027155a8f1d05340238501522d))
### Fix
* Bumping pyowletapi to 2024.3.2 ([`50c55dc`](https://github.com/ryanbdclark/owlet/commit/50c55dcfd30d15027155a8f1d05340238501522d))
* UI config now allows you to set interval to 5 seconds, previously the minimum was 10 ([`50c55dc`](https://github.com/ryanbdclark/owlet/commit/50c55dcfd30d15027155a8f1d05340238501522d))
##2023.11.2 (2023-11-23)
### Feature
* Support added for V2 sock ([`50fe1a8`](https://github.com/ryanbdclark/owlet/commit/50fe1a87656b7d6413d06f06f3650fd0bfb48e02))
* Added tests for binary sensors ([`50fe1a8`](https://github.com/ryanbdclark/owlet/commit/50fe1a87656b7d6413d06f06f3650fd0bfb48e02))
### Fix
* Bumping pyowletapi to 2023.11.4 to allow V2 support ([`50fe1a8`](https://github.com/ryanbdclark/owlet/commit/50fe1a87656b7d6413d06f06f3650fd0bfb48e02))
* Refactoring ([`50fe1a8`](https://github.com/ryanbdclark/owlet/commit/50fe1a87656b7d6413d06f06f3650fd0bfb48e02))
* Corrected spelling of sock disconnected sensor ([`50fe1a8`](https://github.com/ryanbdclark/owlet/commit/50fe1a87656b7d6413d06f06f3650fd0bfb48e02))
## 2023.11.1 (2023-11-16) ## 2023.11.1 (2023-11-16)
### Fix ### Fix
* Bumping pyowletapi to 2023.11.1 ([`3acf847`](https://github.com/ryanbdclark/owlet/commit/3acf8473526665382b44ef6325d708a6c62fff45)) * Bumping pyowletapi to 2023.11.1 ([`3acf847`](https://github.com/ryanbdclark/owlet/commit/3acf8473526665382b44ef6325d708a6c62fff45))

View File

@@ -8,13 +8,11 @@
[![hacs][hacsbadge]][hacs] [![hacs][hacsbadge]][hacs]
[![Project Maintenance][maintenance-shield]][user_profile] [![Project Maintenance][maintenance-shield]][user_profile]
A custom component for the Owlet smart sock, currently this only supports the owlet smart sock 3. A custom component for the Owlet smart sock
If you have a smart sock 2 and would like to contribute then please do so.
## Installation ## Installation
1. Use [HACS](https://hacs.xyz/docs/setup/download), in `HACS > Integrations > Explore & Add Repositories` search for "Owlet". After adding this `https://github.com/ryanbdclark/owlet` as a custom repository. 1. Use [HACS](https://hacs.xyz/docs/setup/download), in `HACS > Integrations > Explore & Add Repositories` search for "Owlet".
2. Restart Home Assistant. 2. Restart Home Assistant.
3. [![Add Integration][add-integration-badge]][add-integration] or in the HA UI go to "Settings" -> "Devices & Services" then click "+" and search for "Owlet Smart Sock". 3. [![Add Integration][add-integration-badge]][add-integration] or in the HA UI go to "Settings" -> "Devices & Services" then click "+" and search for "Owlet Smart Sock".
@@ -47,4 +45,4 @@ This integration provides the following entities:
[releases]: https://github.com/ryanbdclark/owlet/releases [releases]: https://github.com/ryanbdclark/owlet/releases
[user_profile]: https://github.com/ryanbdclark [user_profile]: https://github.com/ryanbdclark
[add-integration]: https://my.home-assistant.io/redirect/config_flow_start?domain=owlet [add-integration]: https://my.home-assistant.io/redirect/config_flow_start?domain=owlet
[add-integration-badge]: https://my.home-assistant.io/badges/config_flow_start.svg [add-integration-badge]: https://my.home-assistant.io/badges/config_flow_start.svg

View File

@@ -48,11 +48,21 @@ SENSORS: tuple[OwletBinarySensorEntityDescription, ...] = (
translation_key="low_ox_alrt", translation_key="low_ox_alrt",
device_class=BinarySensorDeviceClass.SOUND, device_class=BinarySensorDeviceClass.SOUND,
), ),
OwletBinarySensorEntityDescription(
key="critical_oxygen_alert",
translation_key="crit_ox_alrt",
device_class=BinarySensorDeviceClass.SOUND,
),
OwletBinarySensorEntityDescription( OwletBinarySensorEntityDescription(
key="low_battery_alert", key="low_battery_alert",
translation_key="low_batt_alrt", translation_key="low_batt_alrt",
device_class=BinarySensorDeviceClass.SOUND, device_class=BinarySensorDeviceClass.SOUND,
), ),
OwletBinarySensorEntityDescription(
key="critical_battery_alert",
translation_key="crit_batt_alrt",
device_class=BinarySensorDeviceClass.SOUND,
),
OwletBinarySensorEntityDescription( OwletBinarySensorEntityDescription(
key="lost_power_alert", key="lost_power_alert",
translation_key="lost_pwr_alrt", translation_key="lost_pwr_alrt",
@@ -73,6 +83,11 @@ SENSORS: tuple[OwletBinarySensorEntityDescription, ...] = (
translation_key="awake", translation_key="awake",
icon="mdi:sleep", icon="mdi:sleep",
), ),
OwletBinarySensorEntityDescription(
key="base_station_on",
translation_key="base_on",
device_class=BinarySensorDeviceClass.POWER,
),
) )
@@ -90,9 +105,10 @@ async def async_setup_entry(
for sensor in SENSORS: for sensor in SENSORS:
if sensor.key in coordinator.sock.properties: if sensor.key in coordinator.sock.properties:
sensors.append(OwletBinarySensor(coordinator, sensor)) sensors.append(OwletBinarySensor(coordinator, sensor))
async_add_entities(sensors) async_add_entities(sensors)
class OwletBinarySensor(OwletBaseEntity, BinarySensorEntity): class OwletBinarySensor(OwletBaseEntity, BinarySensorEntity):
"""Representation of an Owlet binary sensor.""" """Representation of an Owlet binary sensor."""

View File

@@ -12,7 +12,6 @@ from pyowletapi.exceptions import (
OwletEmailError, OwletEmailError,
OwletPasswordError, OwletPasswordError,
) )
from pyowletapi.sock import Sock
import voluptuous as vol import voluptuous as vol
from homeassistant import config_entries, exceptions from homeassistant import config_entries, exceptions
@@ -86,10 +85,8 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
title=user_input[CONF_USERNAME], title=user_input[CONF_USERNAME],
data={ data={
CONF_REGION: user_input[CONF_REGION], CONF_REGION: user_input[CONF_REGION],
CONF_USERNAME: user_input[CONF_PASSWORD], CONF_USERNAME: user_input[CONF_USERNAME],
CONF_API_TOKEN: token[CONF_API_TOKEN], **token,
CONF_OWLET_EXPIRY: token[CONF_OWLET_EXPIRY],
CONF_OWLET_REFRESH: token[CONF_OWLET_REFRESH],
}, },
options={CONF_SCAN_INTERVAL: POLLING_INTERVAL}, options={CONF_SCAN_INTERVAL: POLLING_INTERVAL},
) )
@@ -168,7 +165,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
vol.Required( vol.Required(
CONF_SCAN_INTERVAL, CONF_SCAN_INTERVAL,
default=self.config_entry.options.get(CONF_SCAN_INTERVAL), default=self.config_entry.options.get(CONF_SCAN_INTERVAL),
): vol.All(vol.Coerce(int), vol.Range(min=10)), ): vol.All(vol.Coerce(int), vol.Range(min=5)),
} }
) )

View File

@@ -5,7 +5,7 @@ DOMAIN = "owlet"
CONF_OWLET_EXPIRY = "expiry" CONF_OWLET_EXPIRY = "expiry"
CONF_OWLET_REFRESH = "refresh" CONF_OWLET_REFRESH = "refresh"
SUPPORTED_VERSIONS = [3] SUPPORTED_VERSIONS = [2, 3]
POLLING_INTERVAL = 5 POLLING_INTERVAL = 5
MANUFACTURER = "Owlet Baby Care" MANUFACTURER = "Owlet Baby Care"
SLEEP_STATES = {0: "unknown", 1: "awake", 8: "light_sleep", 15: "deep_sleep"} SLEEP_STATES = {0: "unknown", 1: "awake", 8: "light_sleep", 15: "deep_sleep"}

View File

@@ -36,7 +36,7 @@ class OwletCoordinator(DataUpdateCoordinator):
update_interval=timedelta(seconds=interval), update_interval=timedelta(seconds=interval),
) )
self.sock = sock self.sock = sock
self.config_entry = entry self.config_entry: ConfigEntry = entry
async def _async_update_data(self) -> None: async def _async_update_data(self) -> None:
"""Fetch the data from the device.""" """Fetch the data from the device."""

View File

@@ -2,7 +2,7 @@
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.entity import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
from .coordinator import OwletCoordinator from .coordinator import OwletCoordinator
from .const import DOMAIN, MANUFACTURER from .const import DOMAIN, MANUFACTURER
@@ -23,7 +23,7 @@ class OwletBaseEntity(CoordinatorEntity[OwletCoordinator], Entity):
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
"""Return the device info of the device""" """Return the device info of the device."""
return DeviceInfo( return DeviceInfo(
identifiers={(DOMAIN, self.sock.serial)}, identifiers={(DOMAIN, self.sock.serial)},
name="Owlet Baby Care Sock", name="Owlet Baby Care Sock",

View File

@@ -9,7 +9,7 @@
"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==2023.11.1" "pyowletapi==2024.3.2"
], ],
"version": "2023.11.1" "version": "2024.3.1"
} }

View File

@@ -160,7 +160,7 @@ class OwletSensor(OwletBaseEntity, SensorEntity):
return self.sock.properties[self.entity_description.key] return self.sock.properties[self.entity_description.key]
@property @property
def options(self) -> list[str]: def options(self) -> list[str] | None:
"""Set options for sleep state.""" """Set options for sleep state."""
if self.entity_description.key != "sleep_state": if self.entity_description.key != "sleep_state":
return None return None

View File

@@ -54,20 +54,29 @@
"low_ox_alrt": { "low_ox_alrt": {
"name": "Low oxygen alert" "name": "Low oxygen alert"
}, },
"crit_ox_alrt": {
"name": "Critical oxygen alert"
},
"low_batt_alrt": { "low_batt_alrt": {
"name": "Low battery alert" "name": "Low battery alert"
}, },
"crit_batt_alrt": {
"name": "Critical battery alert"
},
"lost_pwr_alrt": { "lost_pwr_alrt": {
"name": "Lost power alert" "name": "Lost power alert"
}, },
"sock_discon_alrt": { "sock_discon_alrt": {
"name": "Sock diconnected alert" "name": "Sock disconnected alert"
}, },
"sock_off": { "sock_off": {
"name": "Sock off" "name": "Sock off"
}, },
"awake": { "awake": {
"name": "Awake" "name": "Awake"
},
"base_on": {
"name": "Base station on"
} }
}, },
"sensor": { "sensor": {

View File

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

View File

@@ -54,20 +54,29 @@
"low_ox_alrt": { "low_ox_alrt": {
"name": "Low oxygen alert" "name": "Low oxygen alert"
}, },
"crit_ox_alrt": {
"name": "Critical oxygen alert"
},
"low_batt_alrt": { "low_batt_alrt": {
"name": "Low battery alert" "name": "Low battery alert"
}, },
"crit_batt_alrt": {
"name": "Critical battery alert"
},
"lost_pwr_alrt": { "lost_pwr_alrt": {
"name": "Lost power alert" "name": "Lost power alert"
}, },
"sock_discon_alrt": { "sock_discon_alrt": {
"name": "Sock diconnected alert" "name": "Sock disconnected alert"
}, },
"sock_off": { "sock_off": {
"name": "Sock off" "name": "Sock off"
}, },
"awake": { "awake": {
"name": "Awake" "name": "Awake"
},
"base_on": {
"name": "Base station on"
} }
}, },
"sensor": { "sensor": {

View File

@@ -8,9 +8,7 @@
[![hacs][hacsbadge]][hacs] [![hacs][hacsbadge]][hacs]
[![Project Maintenance][maintenance-shield]][user_profile] [![Project Maintenance][maintenance-shield]][user_profile]
A custom component for the Owlet smart sock, currently this only supports the owlet smart sock 3. A custom component for the Owlet smart sock
If you have a smart sock 2 and would like to contribute then please do so.
## Installation ## Installation
@@ -34,4 +32,4 @@ If you have a smart sock 2 and would like to contribute then please do so.
[releases]: https://github.com/ryanbdclark/owlet/releases [releases]: https://github.com/ryanbdclark/owlet/releases
[user_profile]: https://github.com/ryanbdclark [user_profile]: https://github.com/ryanbdclark
[add-integration]: https://my.home-assistant.io/redirect/config_flow_start?domain=owlet [add-integration]: https://my.home-assistant.io/redirect/config_flow_start?domain=owlet
[add-integration-badge]: https://my.home-assistant.io/badges/config_flow_start.svg [add-integration-badge]: https://my.home-assistant.io/badges/config_flow_start.svg

View File

@@ -1052,4 +1052,4 @@
"expiry": 200, "expiry": 200,
"refresh": "new_refresh_token" "refresh": "new_refresh_token"
} }
} }

1211
tests/fixtures/update_properties_v2.json vendored Normal file

File diff suppressed because it is too large Load Diff

188
tests/test_binary_sensor.py Normal file
View File

@@ -0,0 +1,188 @@
"""Test Owlet Sensor."""
from __future__ import annotations
from homeassistant.core import HomeAssistant
from . import async_init_integration
async def test_sensors_asleep(hass: HomeAssistant) -> None:
"""Test sensor values."""
await async_init_integration(
hass, properties_fixture="update_properties_asleep.json"
)
assert len(hass.states.async_all("binary_sensor")) == 10
assert hass.states.get("binary_sensor.owlet_baby_care_sock_charging").state == "off"
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_high_heart_rate_alert"
).state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_heart_rate_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_high_oxygen_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_oxygen_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_battery_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_lost_power_alert").state
== "off"
)
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_sock_disconnected_alert"
).state
== "off"
)
assert hass.states.get("binary_sensor.owlet_baby_care_sock_sock_off").state == "off"
assert hass.states.get("binary_sensor.owlet_baby_care_sock_awake").state == "off"
async def test_sensors_awake(hass: HomeAssistant) -> None:
"""Test sensor values."""
await async_init_integration(
hass, properties_fixture="update_properties_awake.json"
)
assert len(hass.states.async_all("binary_sensor")) == 10
assert hass.states.get("binary_sensor.owlet_baby_care_sock_charging").state == "off"
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_high_heart_rate_alert"
).state
== "on"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_heart_rate_alert").state
== "on"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_high_oxygen_alert").state
== "on"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_oxygen_alert").state
== "on"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_battery_alert").state
== "on"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_lost_power_alert").state
== "on"
)
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_sock_disconnected_alert"
).state
== "off"
)
assert hass.states.get("binary_sensor.owlet_baby_care_sock_sock_off").state == "off"
assert hass.states.get("binary_sensor.owlet_baby_care_sock_awake").state == "on"
async def test_sensors_charging(hass: HomeAssistant) -> None:
"""Test sensor values."""
await async_init_integration(
hass, properties_fixture="update_properties_charging.json"
)
assert len(hass.states.async_all("binary_sensor")) == 10
assert hass.states.get("binary_sensor.owlet_baby_care_sock_charging").state == "on"
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_high_heart_rate_alert"
).state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_heart_rate_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_high_oxygen_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_oxygen_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_battery_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_lost_power_alert").state
== "off"
)
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_sock_disconnected_alert"
).state
== "off"
)
assert hass.states.get("binary_sensor.owlet_baby_care_sock_sock_off").state == "off"
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_awake").state == "unknown"
)
async def test_sensors_v2(hass: HomeAssistant) -> None:
"""Test sensor values."""
await async_init_integration(hass, properties_fixture="update_properties_v2.json")
assert len(hass.states.async_all("binary_sensor")) == 9
assert hass.states.get("binary_sensor.owlet_baby_care_sock_charging").state == "off"
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_high_heart_rate_alert"
).state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_heart_rate_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_oxygen_alert").state
== "off"
)
assert (
hass.states.get("binary_sensor.owlet_baby_care_sock_low_battery_alert").state
== "off"
)
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_critical_battery_alert"
).state
== "off"
)
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_critical_oxygen_alert"
).state
== "off"
)
assert (
hass.states.get(
"binary_sensor.owlet_baby_care_sock_sock_disconnected_alert"
).state
== "off"
)
assert hass.states.get("binary_sensor.owlet_baby_care_sock_sock_off").state == "off"

View File

@@ -70,7 +70,7 @@ async def test_flow_wrong_password(hass: HomeAssistant) -> None:
user_input=CONF_INPUT, user_input=CONF_INPUT,
) )
assert result["type"] == FlowResultType.FORM assert result["type"] == FlowResultType.FORM
assert result["errors"] == {"base": "invalid_password"} assert result["errors"] == {"password": "invalid_password"}
async def test_flow_wrong_email(hass: HomeAssistant) -> None: async def test_flow_wrong_email(hass: HomeAssistant) -> None:
@@ -88,7 +88,7 @@ async def test_flow_wrong_email(hass: HomeAssistant) -> None:
user_input=CONF_INPUT, user_input=CONF_INPUT,
) )
assert result["type"] == FlowResultType.FORM assert result["type"] == FlowResultType.FORM
assert result["errors"] == {"base": "invalid_email"} assert result["errors"] == {"username": "invalid_email"}
async def test_flow_credentials_error(hass: HomeAssistant) -> None: async def test_flow_credentials_error(hass: HomeAssistant) -> None:
@@ -193,7 +193,7 @@ async def test_reauth_invalid_password(hass: HomeAssistant) -> None:
assert result["type"] == FlowResultType.FORM assert result["type"] == FlowResultType.FORM
assert result["step_id"] == "reauth_confirm" assert result["step_id"] == "reauth_confirm"
assert result["errors"] == {"base": "invalid_password"} assert result["errors"] == {"password": "invalid_password"}
async def test_reauth_unknown_error(hass: HomeAssistant) -> None: async def test_reauth_unknown_error(hass: HomeAssistant) -> None:

View File

@@ -43,7 +43,7 @@ async def test_async_setup_entry(hass: HomeAssistant) -> None:
entities = er.async_entries_for_device(entity_registry, device_entry.id) entities = er.async_entries_for_device(entity_registry, device_entry.id)
assert len(entities) == 8 assert len(entities) == 18
await entry.async_unload(hass) await entry.async_unload(hass)

View File

@@ -107,3 +107,20 @@ async def test_sensors_charging(hass: HomeAssistant) -> None:
== "unknown" == "unknown"
) )
assert hass.states.get("sensor.owlet_baby_care_sock_sleep_state").state == "unknown" assert hass.states.get("sensor.owlet_baby_care_sock_sleep_state").state == "unknown"
async def test_sensors_v2(hass: HomeAssistant) -> None:
"""Test sensor values."""
await async_init_integration(hass, properties_fixture="update_properties_v2.json")
assert len(hass.states.async_all("sensor")) == 4
assert (
hass.states.get("sensor.owlet_baby_care_sock_battery_percentage").state == "29"
)
assert hass.states.get("sensor.owlet_baby_care_sock_heart_rate").state == "145"
assert hass.states.get("sensor.owlet_baby_care_sock_o2_saturation").state == "99"
assert (
hass.states.get("sensor.owlet_baby_care_sock_signal_strength").state == "98.0"
)