Skip to content

Commit

Permalink
some minor body metrics related changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ronnnnnnnnnnnnn committed Oct 19, 2024
1 parent 876c9b2 commit d3745e1
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 19 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,22 @@ The main class for interacting with the scale.
- `hw_version`: Get the hardware version of the scale (read-only).
- `sw_version`: Get the software version of the scale (read-only).

### `EtekcitySmartFitnessScaleWithBodyMetrics`

An extended version of EtekcitySmartFitnessScale that automatically calculates body metrics.

#### Methods:

- `__init__(self, address: str, notification_callback: Callable[[ScaleData], None], sex: Sex, birthdate: date, height_m: float, display_unit: WeightUnit = None)`
- `async_start()`: Start scanning for and connecting to the scale.
- `async_stop()`: Stop the connection to the scale.

#### Properties:

- `display_unit`: Get or set the display unit (WeightUnit.KG, WeightUnit.LB or WeightUnit.ST). Returns None if the display unit is currently unknown (not set by the user and not yet received from the scale together with a stable weight measurement).
- `hw_version`: Get the hardware version of the scale (read-only).
- `sw_version`: Get the software version of the scale (read-only).

### `WeightUnit`

An enum representing the possible display units:
Expand Down
39 changes: 20 additions & 19 deletions src/etekcity_esf551_ble/body_metrics.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from collections.abc import Callable
from dataclasses import asdict, dataclass
from datetime import date
from enum import IntEnum
from functools import cached_property
Expand All @@ -14,8 +13,10 @@ class Sex(IntEnum):
Female = 1


@dataclass
class BodyMetrics:
"""
Class for calculating various body composition metrics based on weight, height, age, sex, and impedance.
"""
def __init__(self, weight_kg: float, height_m: float, age: int, sex: Sex, impedance: int):
self.weight = weight_kg
self.height = height_m
Expand Down Expand Up @@ -309,17 +310,19 @@ def metabolic_age(self) -> int:
return max(18, self.age + 8 - age_adjustment_factor)


def calc_age(birthday: str) -> int:

def _calc_age(birthdate: date) -> int:
today = date.today()
birthdate = date.fromisoformat(birthday)
years = today.year - birthdate.year
if today.month < birthdate.month or (
today.month == birthdate.month and today.day < birthdate.day
):
if today.month < birthdate.month or (today.month == birthdate.month and today.day < birthdate.day):
years -= 1
return years


def _as_dictionary(obj: BodyMetrics) -> dict[str, int | float]:
return{prop: getattr(obj, prop) for prop in dir(obj) if not prop.startswith('__')}


class EtekcitySmartFitnessScaleWithBodyMetrics(EtekcitySmartFitnessScale):
def __init__(
self,
Expand All @@ -336,22 +339,20 @@ def __init__(
self._original_callback = notification_callback
super().__init__(
address,
lambda data: self.wrapped_notification_callback(
lambda data: self._wrapped_notification_callback(
self._sex, self._birthdate, self._height_m, data
),
display_unit,
)

def wrapped_notification_callback(
def _wrapped_notification_callback(
self, sex: Sex, birthdate: date, height_m: float, data: ScaleData
) -> None:
data.measurements |= asdict(
BodyMetrics(
data.measurements[WEIGHT_KEY],
height_m,
calc_age(birthdate),
sex,
data.measurements[IMPEDANCE_KEY],
)
)
data.measurements |= _as_dictionary(BodyMetrics(
data.measurements[WEIGHT_KEY],
height_m,
_calc_age(birthdate),
sex,
data.measurements[IMPEDANCE_KEY],
))
self._original_callback(data)

0 comments on commit d3745e1

Please sign in to comment.