Compare commits

..

29 Commits

Author SHA1 Message Date
Paulus Schoutsen
460bd2b3bb Merge pull request #37377 from home-assistant/rc 2020-07-02 14:46:19 -07:00
Paulus Schoutsen
ec690bb369 Bumped version to 0.112.1 2020-07-02 20:15:44 +00:00
starkillerOG
16dae8457a Add DenonAvr missing error message (#37370) 2020-07-02 20:11:54 +00:00
Bram Kragten
38599d2970 Update frontend to 20200702.0 (#37369) 2020-07-02 20:11:53 +00:00
Robert Van Gorkom
5013b7e049 Fix withings bug that grabbed oldest value instead of the newest (#37362)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2020-07-02 20:11:52 +00:00
uvjustin
b21c81656f Use entry.data.get() in forked_daapd config_flow as some entries miss… (#37359) 2020-07-02 20:11:52 +00:00
Robert Van Gorkom
69a5c63b71 Fix gogogate2 issue where non-admin users could not login (#37353) 2020-07-02 20:11:51 +00:00
Markus Bong
9b854bdcd3 Fix devolo sensor subscriber (#37337) 2020-07-02 20:11:50 +00:00
bsmappee
f335127750 Smappee dependency update (#37331) 2020-07-02 20:11:49 +00:00
Courtenay
9131f5fa69 Change log url in config check error notification (#37311) 2020-07-02 20:11:49 +00:00
John Hollowell
976d375a33 Update proxmoxve integration to correctly renew authentication (#37016) 2020-07-02 20:11:48 +00:00
Franck Nijhof
dc8bfb76dc Merge pull request #37280 from home-assistant/rc 2020-07-01 16:47:17 +02:00
Franck Nijhof
96d0ee3153 Bumped version to 0.112.0 2020-07-01 14:38:24 +02:00
Bram Kragten
20c66b1fa3 Updated frontend to 20200701.0 (#37279) 2020-07-01 14:37:20 +02:00
Bram Kragten
3c260c91c8 Revert "Update fritzconnection to 1.3.0" (#37278)
This reverts commit 2f46a81e3e.
2020-07-01 14:37:16 +02:00
Paulus Schoutsen
cce95312a9 Bumped version to 0.112.0b4 2020-06-30 19:43:05 +00:00
Sven-Hendrik Haase
a7be7bcd0a Update fritzconnection to 1.3.0 (#37212)
This effectively fixes an important bug where the graph would go negative because 1.2.0 used the 32-bit counters and 1.3.0 uses 64-bit counters will not realistically go negative any time soon.
2020-06-30 19:42:58 +00:00
J. Nick Koston
a8e86a62a4 Update myq for latest client version requirement (#37104) 2020-06-30 19:42:57 +00:00
Paulus Schoutsen
4c052643ca Bumped version to 0.112.0b3 2020-06-30 00:25:44 +00:00
Paulus Schoutsen
b7a071b23f Updated frontend to 20200629.0 (#37240) 2020-06-30 00:25:37 +00:00
David F. Mulcahey
f0a8e8ea04 Bump ZHA Quirks to 0.0.41 (#37235) 2020-06-30 00:25:36 +00:00
Aaron Bach
caf306799b Fix Tile location accuracy bug (#37233)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2020-06-30 00:25:35 +00:00
definitio
d9a2cc93ba Fixes after PR #36479 (#37230) 2020-06-30 00:25:34 +00:00
Franck Nijhof
dbdd4f0e39 Ensure recorder data integrity and MySQL lock error handling (#37228) 2020-06-30 00:25:34 +00:00
MatthewFlamm
edc44230b4 Fix wind speed change in NWS (#37222) 2020-06-30 00:25:33 +00:00
Rami Mosleh
4d7a468c0e Fix updating ping sensor (#37220) 2020-06-30 00:25:32 +00:00
Aaron Bach
a06595c08d Fix bug where Tile session would expire (#37185) 2020-06-30 00:25:32 +00:00
Alan Tse
ff13b4c6b3 Bump teslajsonpy to 0.9.0 (#37162) 2020-06-30 00:25:31 +00:00
Tom Harris
8a755e790f Fix issue with Insteon devices not responding to device changes (#37160) 2020-06-30 00:25:30 +00:00
30 changed files with 177 additions and 90 deletions

View File

@@ -39,6 +39,13 @@ class ConnectDenonAVR:
or self._receiver.model_name is None
or self._receiver.receiver_type is None
):
_LOGGER.error(
"Missing receiver information: manufacturer '%s', name '%s', model '%s', type '%s'",
self._receiver.manufacturer,
self._receiver.name,
self._receiver.model_name,
self._receiver.receiver_type,
)
return False
_LOGGER.debug(

View File

@@ -80,7 +80,7 @@ class DevoloMultiLevelDeviceEntity(DevoloDeviceEntity):
def _sync(self, message=None):
"""Update the multi level sensor state."""
if message[0].startswith("devolo.MultiLevelSensor"):
if message[0] == self._multi_level_sensor_property.element_uid:
self._state = self._device_instance.multi_level_sensor_property[
message[0]
].value

View File

@@ -133,7 +133,7 @@ class ForkedDaapdFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if user_input is not None:
# check for any entries with same host, abort if found
for entry in self._async_current_entries():
if entry.data[CONF_HOST] == user_input[CONF_HOST]:
if entry.data.get(CONF_HOST) == user_input[CONF_HOST]:
return self.async_abort(reason="already_configured")
validate_result = await self.validate_input(user_input)
if validate_result[0] == "ok": # success

View File

@@ -2,9 +2,7 @@
"domain": "frontend",
"name": "Home Assistant Frontend",
"documentation": "https://www.home-assistant.io/integrations/frontend",
"requirements": [
"home-assistant-frontend==20200626.1"
],
"requirements": ["home-assistant-frontend==20200702.0"],
"dependencies": [
"api",
"auth",
@@ -17,8 +15,6 @@
"system_log",
"websocket_api"
],
"codeowners": [
"@home-assistant/frontend"
],
"codeowners": ["@home-assistant/frontend"],
"quality_scale": "internal"
}
}

View File

@@ -63,7 +63,7 @@ class Gogogate2FlowHandler(ConfigFlow, domain=DOMAIN):
CONF_IP_ADDRESS, default=user_input.get(CONF_IP_ADDRESS, "")
): str,
vol.Required(
CONF_USERNAME, default=user_input.get(CONF_USERNAME, "admin")
CONF_USERNAME, default=user_input.get(CONF_USERNAME, "")
): str,
vol.Required(
CONF_PASSWORD, default=user_input.get(CONF_PASSWORD, "")

View File

@@ -3,6 +3,6 @@
"name": "Gogogate2",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/gogogate2",
"requirements": ["gogogate2-api==1.0.3"],
"requirements": ["gogogate2-api==1.0.4"],
"codeowners": ["@vangorra"]
}

View File

@@ -10,7 +10,7 @@
"step": {
"user": {
"title": "Setup GogoGate2",
"description": "Provide requisite information below. Note: only the 'admin' user is known to work.",
"description": "Provide requisite information below.",
"data": {
"ip_address": "IP Address",
"username": "[%key:common::config_flow::data::username%]",

View File

@@ -325,7 +325,7 @@ async def async_setup(hass, config):
if errors:
_LOGGER.error(errors)
hass.components.persistent_notification.async_create(
"Config error. See [the logs](/developer-tools/logs) for details.",
"Config error. See [the logs](/config/logs) for details.",
"Config validating",
f"{HASS_DOMAIN}.check_config",
)

View File

@@ -112,7 +112,7 @@ async def async_setup(hass: ha.HomeAssistant, config: dict) -> bool:
if errors:
_LOGGER.error(errors)
hass.components.persistent_notification.async_create(
"Config error. See [the logs](/developer-tools/logs) for details.",
"Config error. See [the logs](/config/logs) for details.",
"Config validating",
f"{ha.DOMAIN}.check_config",
)

View File

@@ -2,6 +2,6 @@
"domain": "insteon",
"name": "Insteon",
"documentation": "https://www.home-assistant.io/integrations/insteon",
"requirements": ["pyinsteon==1.0.4"],
"requirements": ["pyinsteon==1.0.5"],
"codeowners": ["@teharris1"]
}

View File

@@ -994,6 +994,9 @@ class MqttAvailability(Entity):
await self._availability_subscribe_topics()
async_dispatcher_connect(self.hass, MQTT_CONNECTED, self.async_mqtt_connect)
async_dispatcher_connect(self.hass, MQTT_DISCONNECTED, self.async_mqtt_connect)
self.async_on_remove(
async_dispatcher_connect(self.hass, MQTT_CONNECTED, self.async_mqtt_connect)
)
async def availability_discovery_update(self, config: dict):
"""Handle updated discovery message."""
@@ -1029,7 +1032,8 @@ class MqttAvailability(Entity):
@callback
def async_mqtt_connect(self):
"""Update state on connection/disconnection to MQTT broker."""
self.async_write_ha_state()
if self.hass.is_running:
self.async_write_ha_state()
async def async_will_remove_from_hass(self):
"""Unsubscribe when removed."""

View File

@@ -2,7 +2,7 @@
"domain": "myq",
"name": "MyQ",
"documentation": "https://www.home-assistant.io/integrations/myq",
"requirements": ["pymyq==2.0.4"],
"requirements": ["pymyq==2.0.5"],
"codeowners": ["@bdraco"],
"config_flow": true,
"homekit": {

View File

@@ -190,17 +190,16 @@ class NWSWeather(WeatherEntity):
@property
def wind_speed(self):
"""Return the current windspeed."""
wind_m_s = None
wind_km_hr = None
if self.observation:
wind_m_s = self.observation.get("windSpeed")
if wind_m_s is None:
wind_km_hr = self.observation.get("windSpeed")
if wind_km_hr is None:
return None
wind_m_hr = wind_m_s * 3600
if self.is_metric:
wind = convert_distance(wind_m_hr, LENGTH_METERS, LENGTH_KILOMETERS)
wind = wind_km_hr
else:
wind = convert_distance(wind_m_hr, LENGTH_METERS, LENGTH_MILES)
wind = convert_distance(wind_km_hr, LENGTH_KILOMETERS, LENGTH_MILES)
return round(wind)
@property

View File

@@ -3,5 +3,5 @@
"name": "Proxmox VE",
"documentation": "https://www.home-assistant.io/integrations/proxmoxve",
"codeowners": ["@k4ds3", "@jhollowe"],
"requirements": ["proxmoxer==1.1.0"]
"requirements": ["proxmoxer==1.1.1"]
}

View File

@@ -1,8 +1,9 @@
"""Purge old data helper."""
from datetime import timedelta
import logging
import time
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.exc import OperationalError, SQLAlchemyError
import homeassistant.util.dt as dt_util
@@ -18,47 +19,46 @@ def purge_old_data(instance, purge_days: int, repack: bool) -> bool:
Cleans up an timeframe of an hour, based on the oldest record.
"""
purge_before = dt_util.utcnow() - timedelta(days=purge_days)
_LOGGER.debug("Purging events before %s", purge_before)
_LOGGER.debug("Purging states and events before target %s", purge_before)
try:
with session_scope(session=instance.get_session()) as session:
# Purge a max of 1 hour, based on the oldest states or events record
batch_purge_before = purge_before
query = session.query(States).order_by(States.last_updated.asc()).limit(1)
states = execute(query, to_native=True, validate_entity_ids=False)
states_purge_before = purge_before
if states:
states_purge_before = min(
purge_before, states[0].last_updated + timedelta(hours=1)
batch_purge_before = min(
batch_purge_before, states[0].last_updated + timedelta(hours=1),
)
deleted_rows_states = (
session.query(States)
.filter(States.last_updated < states_purge_before)
.delete(synchronize_session=False)
)
_LOGGER.debug("Deleted %s states", deleted_rows_states)
query = session.query(Events).order_by(Events.time_fired.asc()).limit(1)
events = execute(query, to_native=True)
events_purge_before = purge_before
if events:
events_purge_before = min(
purge_before, events[0].time_fired + timedelta(hours=1)
batch_purge_before = min(
batch_purge_before, events[0].time_fired + timedelta(hours=1),
)
deleted_rows_events = (
session.query(Events)
.filter(Events.time_fired < events_purge_before)
_LOGGER.debug("Purging states and events before %s", batch_purge_before)
deleted_rows = (
session.query(States)
.filter(States.last_updated < batch_purge_before)
.delete(synchronize_session=False)
)
_LOGGER.debug("Deleted %s events", deleted_rows_events)
_LOGGER.debug("Deleted %s states", deleted_rows)
deleted_rows = (
session.query(Events)
.filter(Events.time_fired < batch_purge_before)
.delete(synchronize_session=False)
)
_LOGGER.debug("Deleted %s events", deleted_rows)
# If states or events purging isn't processing the purge_before yet,
# return false, as we are not done yet.
if (states_purge_before and states_purge_before != purge_before) or (
events_purge_before and events_purge_before != purge_before
):
if batch_purge_before != purge_before:
_LOGGER.debug("Purging hasn't fully completed yet.")
return False
@@ -80,7 +80,21 @@ def purge_old_data(instance, purge_days: int, repack: bool) -> bool:
_LOGGER.debug("Optimizing SQL DB to free space")
instance.engine.execute("OPTIMIZE TABLE states, events, recorder_runs")
except OperationalError as err:
# Retry when one of the following MySQL errors occurred:
# 1205: Lock wait timeout exceeded; try restarting transaction
# 1206: The total number of locks exceeds the lock table size
# 1213: Deadlock found when trying to get lock; try restarting transaction
if instance.engine.driver in ("mysqldb", "pymysql") and err.orig.args[0] in (
1205,
1206,
1213,
):
_LOGGER.info("%s; purge not completed, retrying", err.orig.args[1])
time.sleep(instance.db_retry_wait)
return False
_LOGGER.warning("Error purging history: %s.", err)
except SQLAlchemyError as err:
_LOGGER.warning("Error purging history: %s.", err)
return True

View File

@@ -9,7 +9,7 @@ async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the Safe Mode component."""
persistent_notification.async_create(
hass,
"Home Assistant is running in safe mode. Check [the error log](/developer-tools/logs) to see what went wrong.",
"Home Assistant is running in safe mode. Check [the error log](/config/logs) to see what went wrong.",
"Safe Mode",
)
return True

View File

@@ -5,7 +5,7 @@
"documentation": "https://www.home-assistant.io/integrations/smappee",
"dependencies": ["http"],
"requirements": [
"pysmappee==0.1.0"
"pysmappee==0.1.2"
],
"codeowners": [
"@bsmappee"

View File

@@ -129,11 +129,10 @@ class SpeedTestDataCoordinator(DataUpdateCoordinator):
server_id = self.config_entry.options.get(CONF_SERVER_ID)
self.api.closest.clear()
self.api.get_servers(servers=[server_id])
self.api.get_best_server()
_LOGGER.debug(
"Executing speedtest.net speed test with server_id: %s", self.api.best["id"]
)
self.api.get_best_server()
self.api.download()
self.api.upload()
return self.api.results.dict()

View File

@@ -3,6 +3,6 @@
"name": "Tesla",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/tesla",
"requirements": ["teslajsonpy==0.8.1"],
"requirements": ["teslajsonpy==0.9.0"],
"codeowners": ["@zabuldon", "@alandtse"]
}

View File

@@ -3,7 +3,7 @@ import asyncio
from datetime import timedelta
from pytile import async_login
from pytile.errors import TileError
from pytile.errors import SessionExpiredError, TileError
from homeassistant.const import ATTR_ATTRIBUTION, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import callback
@@ -44,6 +44,9 @@ async def async_setup_entry(hass, config_entry):
"""Get new data from the API."""
try:
return await client.tiles.all()
except SessionExpiredError:
LOGGER.info("Tile session expired; creating a new one")
await client.async_init()
except TileError as err:
raise UpdateFailed(f"Error while retrieving data: {err}")

View File

@@ -84,13 +84,26 @@ class TileDeviceTracker(TileEntity, TrackerEntity):
Value in meters.
"""
return round(
(
self._tile["last_tile_state"]["h_accuracy"]
+ self._tile["last_tile_state"]["v_accuracy"]
state = self._tile["last_tile_state"]
h_accuracy = state.get("h_accuracy")
v_accuracy = state.get("v_accuracy")
if h_accuracy is not None and v_accuracy is not None:
return round(
(
self._tile["last_tile_state"]["h_accuracy"]
+ self._tile["last_tile_state"]["v_accuracy"]
)
/ 2
)
/ 2
)
if h_accuracy is not None:
return h_accuracy
if v_accuracy is not None:
return v_accuracy
return None
@property
def latitude(self) -> float:

View File

@@ -770,8 +770,13 @@ class DataManager:
response = await self._hass.async_add_executor_job(self._api.measure_get_meas)
groups = query_measure_groups(
response, MeasureTypes.ANY, MeasureGroupAttribs.UNAMBIGUOUS
# Sort from oldest to newest.
groups = sorted(
query_measure_groups(
response, MeasureTypes.ANY, MeasureGroupAttribs.UNAMBIGUOUS
),
key=lambda group: group.created.datetime,
reverse=False,
)
return {

View File

@@ -6,7 +6,7 @@
"requirements": [
"bellows==0.17.0",
"pyserial==3.4",
"zha-quirks==0.0.40",
"zha-quirks==0.0.41",
"zigpy-cc==0.4.4",
"zigpy-deconz==0.9.2",
"zigpy==0.21.0",

View File

@@ -1,7 +1,7 @@
"""Constants used by Home Assistant components."""
MAJOR_VERSION = 0
MINOR_VERSION = 112
PATCH_VERSION = "0b2"
PATCH_VERSION = "1"
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER = (3, 7, 0)

View File

@@ -13,7 +13,7 @@ defusedxml==0.6.0
distro==1.5.0
emoji==0.5.4
hass-nabucasa==0.34.7
home-assistant-frontend==20200626.1
home-assistant-frontend==20200702.0
importlib-metadata==1.6.0;python_version<'3.8'
jinja2>=2.11.1
netdisco==2.7.1

View File

@@ -660,7 +660,7 @@ glances_api==0.2.0
gntp==1.0.3
# homeassistant.components.gogogate2
gogogate2-api==1.0.3
gogogate2-api==1.0.4
# homeassistant.components.google
google-api-python-client==1.6.4
@@ -738,7 +738,7 @@ hole==0.5.1
holidays==0.10.2
# homeassistant.components.frontend
home-assistant-frontend==20200626.1
home-assistant-frontend==20200702.0
# homeassistant.components.zwave
homeassistant-pyozw==0.1.10
@@ -1125,7 +1125,7 @@ prometheus_client==0.7.1
protobuf==3.6.1
# homeassistant.components.proxmoxve
proxmoxer==1.1.0
proxmoxer==1.1.1
# homeassistant.components.systemmonitor
psutil==5.7.0
@@ -1388,7 +1388,7 @@ pyialarm==0.3
pyicloud==0.9.7
# homeassistant.components.insteon
pyinsteon==1.0.4
pyinsteon==1.0.5
# homeassistant.components.intesishome
pyintesishome==1.7.5
@@ -1481,7 +1481,7 @@ pymsteams==0.1.12
pymusiccast==0.1.6
# homeassistant.components.myq
pymyq==2.0.4
pymyq==2.0.5
# homeassistant.components.mysensors
pymysensors==0.18.0
@@ -1610,7 +1610,7 @@ pysignalclirestapi==0.3.4
pysma==0.3.5
# homeassistant.components.smappee
pysmappee==0.1.0
pysmappee==0.1.2
# homeassistant.components.smartthings
pysmartapp==0.3.2
@@ -2094,7 +2094,7 @@ temperusb==1.5.3
tesla-powerwall==0.2.11
# homeassistant.components.tesla
teslajsonpy==0.8.1
teslajsonpy==0.9.0
# homeassistant.components.thermoworks_smoke
thermoworks_smoke==0.1.8
@@ -2255,7 +2255,7 @@ zengge==0.2
zeroconf==0.27.1
# homeassistant.components.zha
zha-quirks==0.0.40
zha-quirks==0.0.41
# homeassistant.components.zhong_hong
zhong_hong_hvac==1.0.9

View File

@@ -310,7 +310,7 @@ gios==0.1.1
glances_api==0.2.0
# homeassistant.components.gogogate2
gogogate2-api==1.0.3
gogogate2-api==1.0.4
# homeassistant.components.google
google-api-python-client==1.6.4
@@ -343,7 +343,7 @@ hole==0.5.1
holidays==0.10.2
# homeassistant.components.frontend
home-assistant-frontend==20200626.1
home-assistant-frontend==20200702.0
# homeassistant.components.zwave
homeassistant-pyozw==0.1.10
@@ -670,7 +670,7 @@ pymodbus==2.3.0
pymonoprice==0.3
# homeassistant.components.myq
pymyq==2.0.4
pymyq==2.0.5
# homeassistant.components.nut
pynut2==2.1.2
@@ -715,7 +715,7 @@ pysignalclirestapi==0.3.4
pysma==0.3.5
# homeassistant.components.smappee
pysmappee==0.1.0
pysmappee==0.1.2
# homeassistant.components.smartthings
pysmartapp==0.3.2
@@ -890,7 +890,7 @@ tellduslive==0.10.11
tesla-powerwall==0.2.11
# homeassistant.components.tesla
teslajsonpy==0.8.1
teslajsonpy==0.9.0
# homeassistant.components.toon
toonapi==0.1.0
@@ -961,7 +961,7 @@ ya_ma==0.3.8
zeroconf==0.27.1
# homeassistant.components.zha
zha-quirks==0.0.40
zha-quirks==0.0.41
# homeassistant.components.zha
zigpy-cc==0.4.4

View File

@@ -60,7 +60,7 @@ EXPECTED_OBSERVATION_IMPERIAL = {
),
ATTR_WEATHER_WIND_BEARING: 180,
ATTR_WEATHER_WIND_SPEED: round(
convert_distance(10, LENGTH_METERS, LENGTH_MILES) * 3600
convert_distance(10, LENGTH_KILOMETERS, LENGTH_MILES)
),
ATTR_WEATHER_PRESSURE: round(
convert_pressure(100000, PRESSURE_PA, PRESSURE_INHG), 2
@@ -74,9 +74,7 @@ EXPECTED_OBSERVATION_IMPERIAL = {
EXPECTED_OBSERVATION_METRIC = {
ATTR_WEATHER_TEMPERATURE: 10,
ATTR_WEATHER_WIND_BEARING: 180,
ATTR_WEATHER_WIND_SPEED: round(
convert_distance(10, LENGTH_METERS, LENGTH_KILOMETERS) * 3600
),
ATTR_WEATHER_WIND_SPEED: 10,
ATTR_WEATHER_PRESSURE: round(convert_pressure(100000, PRESSURE_PA, PRESSURE_HPA)),
ATTR_WEATHER_VISIBILITY: round(
convert_distance(10000, LENGTH_METERS, LENGTH_KILOMETERS)

View File

@@ -224,6 +224,6 @@ class TestRecorderPurge(unittest.TestCase):
self.hass.block_till_done()
self.hass.data[DATA_INSTANCE].block_till_done()
assert (
mock_logger.debug.mock_calls[4][1][0]
mock_logger.debug.mock_calls[5][1][0]
== "Vacuuming SQL DB to free space"
)

View File

@@ -1,5 +1,4 @@
"""Tests for the Withings component."""
import time
from typing import Any
from unittest.mock import patch
@@ -40,8 +39,8 @@ PERSON0 = new_profile_config(
MeasureGetMeasGroup(
attrib=MeasureGetMeasGroupAttrib.DEVICE_ENTRY_FOR_USER,
category=MeasureGetMeasGroupCategory.REAL,
created=time.time(),
date=time.time(),
created=arrow.utcnow().shift(hours=-1),
date=arrow.utcnow().shift(hours=-1),
deviceid="DEV_ID",
grpid=1,
measures=(
@@ -87,11 +86,61 @@ PERSON0 = new_profile_config(
),
),
),
MeasureGetMeasGroup(
attrib=MeasureGetMeasGroupAttrib.DEVICE_ENTRY_FOR_USER,
category=MeasureGetMeasGroupCategory.REAL,
created=arrow.utcnow().shift(hours=-2),
date=arrow.utcnow().shift(hours=-2),
deviceid="DEV_ID",
grpid=1,
measures=(
MeasureGetMeasMeasure(type=MeasureType.WEIGHT, unit=0, value=71),
MeasureGetMeasMeasure(
type=MeasureType.FAT_MASS_WEIGHT, unit=0, value=51
),
MeasureGetMeasMeasure(
type=MeasureType.FAT_FREE_MASS, unit=0, value=61
),
MeasureGetMeasMeasure(
type=MeasureType.MUSCLE_MASS, unit=0, value=51
),
MeasureGetMeasMeasure(type=MeasureType.BONE_MASS, unit=0, value=11),
MeasureGetMeasMeasure(type=MeasureType.HEIGHT, unit=0, value=21),
MeasureGetMeasMeasure(
type=MeasureType.TEMPERATURE, unit=0, value=41
),
MeasureGetMeasMeasure(
type=MeasureType.BODY_TEMPERATURE, unit=0, value=41
),
MeasureGetMeasMeasure(
type=MeasureType.SKIN_TEMPERATURE, unit=0, value=21
),
MeasureGetMeasMeasure(
type=MeasureType.FAT_RATIO, unit=-3, value=71
),
MeasureGetMeasMeasure(
type=MeasureType.DIASTOLIC_BLOOD_PRESSURE, unit=0, value=71
),
MeasureGetMeasMeasure(
type=MeasureType.SYSTOLIC_BLOOD_PRESSURE, unit=0, value=101
),
MeasureGetMeasMeasure(
type=MeasureType.HEART_RATE, unit=0, value=61
),
MeasureGetMeasMeasure(type=MeasureType.SP02, unit=-2, value=96),
MeasureGetMeasMeasure(
type=MeasureType.HYDRATION, unit=-2, value=96
),
MeasureGetMeasMeasure(
type=MeasureType.PULSE_WAVE_VELOCITY, unit=0, value=101
),
),
),
MeasureGetMeasGroup(
attrib=MeasureGetMeasGroupAttrib.DEVICE_ENTRY_FOR_USER_AMBIGUOUS,
category=MeasureGetMeasGroupCategory.REAL,
created=time.time(),
date=time.time(),
created=arrow.utcnow(),
date=arrow.utcnow(),
deviceid="DEV_ID",
grpid=1,
measures=(