Skip to content

Commit 3f63d29

Browse files
authored
Merge pull request #79 from CoMPaTech/trip_switch
Add reset-trip button
2 parents 3668d57 + 0118057 commit 3f63d29

9 files changed

Lines changed: 110 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,24 @@
22

33
## Changelog
44

5-
### JAN 2024 [no release, just an update]
5+
### Ongoing
6+
7+
- Add multibike support (see 0.4 beta progress)
8+
9+
### JUN 2024 [0.3.2]
10+
11+
- Added trip_reset button
12+
- Released v0.3(.2) as new stable version
13+
14+
### JAN 2024
615

716
- Added to HACS default repository (yay!)
817

918
### DEC 2023 [0.3.1 (alpha/beta]
1019

1120
- Released version 0.3
1221

13-
### DEC 2023 [0.3.0 (alpha/beta]
22+
### DEC 2023 [0.3.0 (alpha/beta)]
1423

1524
- Introduce Lock and Light switches
1625
- Fix UnitOf[X] for future HA compatibility (e.g. TEMP_CELSIUS => UnitOfTemperature.CELSIUS)

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ Do note that the switches do not immediately reflect the status (i.e. they will
3636
After your 'switch' command we do request an API update to check on the status, pending that update the switch might toggle back-n-forth some time.
3737
The light-switch is called 'Light mode' as depending on your bike type it will switch on/off or between 'dim and bright'.
3838

39+
**BETA** As with the `switch` implementation a `button` is added to reset your trip_data.
40+
3941
## If you want more frequent updates
4042

4143
Basically you'll have to trigger (through automations) the updates yourself. But it's the correct way to learn Home Assistant and the method shown below also saves some API calls to Stromer. Basically this will determine if the bike is **unlocked** and if so start frequent updates. The example will also show you how to add a button to immediately start the more frequent updates. And yes, I'm aware we can make blueprints of this, but I'll leave that for now until we have a broader user base and properly tested integration.

custom_components/stromer/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
PLATFORMS: list[Platform] = [
1818
Platform.BINARY_SENSOR,
19+
Platform.BUTTON,
1920
Platform.DEVICE_TRACKER,
2021
Platform.SENSOR,
2122
Platform.SWITCH,
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""Stromer Button component for Home Assistant."""
2+
from __future__ import annotations
3+
4+
from homeassistant.components.button import (
5+
ButtonDeviceClass,
6+
ButtonEntity,
7+
ButtonEntityDescription,
8+
)
9+
from homeassistant.config_entries import ConfigEntry
10+
from homeassistant.core import HomeAssistant
11+
from homeassistant.helpers.entity_platform import AddEntitiesCallback
12+
13+
from .const import DOMAIN, LOGGER
14+
from .coordinator import StromerDataUpdateCoordinator
15+
from .entity import StromerEntity
16+
17+
BUTTONS: tuple[ButtonEntityDescription, ...] = (
18+
ButtonEntityDescription(
19+
key="trip_distance", # (ab)use trip_distance from the bike data to trigger adding button
20+
translation_key="reset_trip_data",
21+
icon="mdi:map-marker-distance",
22+
device_class=ButtonDeviceClass.RESTART,
23+
),
24+
)
25+
26+
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
27+
"""Set up the Stromer Buttons from a config entry."""
28+
coordinator = hass.data[DOMAIN][config_entry.entry_id]
29+
30+
entities = []
31+
for idx, data in enumerate(coordinator.data.bikedata.items()):
32+
for description in BUTTONS:
33+
if data[0] == description.key:
34+
entities.append(StromerButton(coordinator, idx, data, description))
35+
LOGGER.debug("Add %s %s button", data, description.translation_key)
36+
37+
async_add_entities(entities, update_before_add=False)
38+
39+
40+
class StromerButton(StromerEntity, ButtonEntity): # type: ignore[misc]
41+
"""Representation of a Button."""
42+
43+
_attr_has_entity_name = True
44+
45+
entity_description: ButtonEntityDescription
46+
47+
def __init__(
48+
self,
49+
coordinator: StromerDataUpdateCoordinator,
50+
idx: int,
51+
data: dict,
52+
description: ButtonEntityDescription,
53+
):
54+
"""Initialize the sensor."""
55+
super().__init__(coordinator)
56+
self._ent = data[0]
57+
self._coordinator = coordinator
58+
59+
device_id = coordinator.data.bike_id
60+
61+
self.entity_description = description
62+
self._attr_unique_id = f"{device_id}-{description.key}-bu"
63+
64+
async def async_press(self) -> None:
65+
"""Handle the button press."""
66+
if self.entity_description.key == "trip_distance":
67+
await self._coordinator.stromer.stromer_reset_trip_data()

custom_components/stromer/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
"iot_class": "cloud_polling",
99
"issue_tracker": "https://github.com/CoMPaTech/stromer/issues",
1010
"requirements": [],
11-
"version": "0.3.1"
11+
"version": "0.3.2"
1212
}

custom_components/stromer/strings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
}
2424
},
2525
"entity": {
26+
"button": {
27+
"reset_trip_data": {
28+
"name": "Reset trip data"
29+
}
30+
},
2631
"switch": {
2732
"lock": {
2833
"name": "Lock"

custom_components/stromer/stromer.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Stromer module for Home Assistant Core."""
22

3-
__version__ = "0.1.0"
3+
__version__ = "0.1.1"
44

55
import json
66
import logging
@@ -194,6 +194,18 @@ async def stromer_call_light(self, state: str) -> None:
194194
log = "API call light returns: %s" % ret
195195
LOGGER.debug(log)
196196

197+
async def stromer_reset_trip_data(self) -> None:
198+
"""Reset the trip data through the API."""
199+
endpoint = f"bike/id/{self.bike_id}/trip_data/"
200+
url = f"{self.base_url}/rapi/mobile/v4.1/{endpoint}"
201+
if self._api_version == "v3":
202+
url = f"{self.base_url}/rapi/mobile/v2/{endpoint}"
203+
204+
headers = {"Authorization": f"Bearer {self._token}"}
205+
res = await self._websession.delete(url, headers=headers)
206+
if res.status != 204:
207+
raise ApiError
208+
197209
async def stromer_call_api(self, endpoint: str) -> Any:
198210
"""Retrieve data from the API."""
199211
url = f"{self.base_url}/rapi/mobile/v4.1/{endpoint}"

custom_components/stromer/translations/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
}
2424
},
2525
"entity": {
26+
"button": {
27+
"reset_trip_data": {
28+
"name": "Reset trip data"
29+
}
30+
},
2631
"switch": {
2732
"lock": {
2833
"name": "Lock"

custom_components/stromer/translations/nl.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
}
2424
},
2525
"entity": {
26+
"button": {
27+
"reset_trip_data": {
28+
"name": "Reset trip data"
29+
}
30+
},
2631
"switch": {
2732
"lock": {
2833
"name": "Slot"

0 commit comments

Comments
 (0)