Skip to content

Commit 857be86

Browse files
committed
♻️ rafactor bluetooth manager, handle connecting state
1 parent 99525f3 commit 857be86

3 files changed

Lines changed: 65 additions & 62 deletions

File tree

pypetkitapi/bluetooth.py

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,28 @@ async def check_relay_availability(self, fountain_id: int) -> bool:
8484
return False
8585
return True
8686

87+
async def _request_ble_api(
88+
self,
89+
endpoint: PetkitEndpoint,
90+
fountain: "WaterFountain",
91+
extra_data: dict | None = None,
92+
):
93+
"""API Bluetooth request method"""
94+
data = {
95+
"bleId": fountain.id,
96+
"type": fountain.device_nfo.type, # type: ignore[union-attr]
97+
"mac": fountain.mac,
98+
}
99+
if extra_data:
100+
data.update(extra_data)
101+
102+
return await self.client.req.request(
103+
method=HTTPMethod.POST,
104+
url=endpoint,
105+
data=data,
106+
headers=await self.client.get_session_id(),
107+
)
108+
87109
async def open_ble_connection(self, fountain_id: int) -> bool:
88110
"""Open a BLE connection to the given fountain_id.
89111
:param fountain_id: The ID of the fountain to open the BLE connection for.
@@ -94,51 +116,44 @@ async def open_ble_connection(self, fountain_id: int) -> bool:
94116
if water_fountain.ble_connection_state == BluetoothState.CONNECTED:
95117
_LOGGER.debug("BLE connection already established (id %s)", fountain_id)
96118
return True
97-
# ToDo : BluetoothState.CONNECTING must be managed
98-
water_fountain.ble_connection_state = BluetoothState.NOT_CONNECTED
99-
if not await self.check_relay_availability(fountain_id):
100-
_LOGGER.debug("BLE relay not available (id: %s).", fountain_id)
101-
return False
102-
response = await self.client.req.request(
103-
method=HTTPMethod.POST,
104-
url=PetkitEndpoint.BLE_CONNECT,
105-
data={
106-
"bleId": fountain_id,
107-
"type": water_fountain.device_nfo.type, # type: ignore[union-attr]
108-
"mac": water_fountain.mac,
109-
},
110-
headers=await self.client.get_session_id(),
111-
)
112-
if response != {"state": 1}:
113-
_LOGGER.debug("Unable to open a BLE connection (id %s)", fountain_id)
114-
return False
119+
120+
if water_fountain.ble_connection_state == BluetoothState.CONNECTING:
121+
_LOGGER.debug("BLE connection already in progress (id %s).", fountain_id)
122+
else:
123+
if not await self.check_relay_availability(fountain_id):
124+
_LOGGER.debug("BLE relay not available (id: %s).", fountain_id)
125+
water_fountain.ble_connection_state = BluetoothState.NOT_CONNECTED
126+
return False
127+
128+
response = await self._request_ble_api(
129+
PetkitEndpoint.BLE_CONNECT, water_fountain
130+
)
131+
if response != {"state": 1}:
132+
_LOGGER.debug("Unable to open a BLE connection (id %s)", fountain_id)
133+
water_fountain.ble_connection_state = BluetoothState.NOT_CONNECTED
134+
return False
135+
136+
water_fountain.ble_connection_state = BluetoothState.CONNECTING
137+
115138
for attempt in range(BLE_CONNECT_ATTEMPT):
116139
_LOGGER.debug(
117-
"BLE connection... %s/%s (id %s)",
140+
"BLE connection... attempt: %s (id %s)",
118141
attempt,
119-
BLE_CONNECT_ATTEMPT,
120142
fountain_id,
121143
)
122-
response = await self.client.req.request(
123-
method=HTTPMethod.POST,
124-
url=PetkitEndpoint.BLE_POLL,
125-
data={
126-
"bleId": fountain_id,
127-
"type": water_fountain.device_nfo.type, # type: ignore[union-attr]
128-
"mac": water_fountain.mac,
129-
},
130-
headers=await self.client.get_session_id(),
144+
response = await self._request_ble_api(
145+
PetkitEndpoint.BLE_POLL, water_fountain
131146
)
132-
if response == 0:
147+
if response == BluetoothState.CONNECTING:
133148
# Wait for 4 seconds before polling again, connection is still in progress
134149
await asyncio.sleep(4)
135-
elif response == -1:
150+
elif response == BluetoothState.ERROR:
136151
_LOGGER.debug("Failed to establish BLE connection (id %s)", fountain_id)
137152
water_fountain.last_ble_poll = datetime.now().strftime(
138153
"%Y-%m-%dT%H:%M:%S.%f"
139154
)
140155
return False
141-
elif response == 1:
156+
elif response == BluetoothState.CONNECTED:
142157
_LOGGER.debug(
143158
"BLE connection established successfully (id %s)", fountain_id
144159
)
@@ -164,20 +179,14 @@ async def close_ble_connection(self, fountain_id: int) -> None:
164179

165180
if water_fountain.ble_connection_state != BluetoothState.CONNECTED:
166181
_LOGGER.debug(
167-
"BLE connection not established. Cannot close (id %s)", fountain_id
182+
"BLE connection not established. Cannot close (id %s) State is=%s",
183+
fountain_id,
184+
water_fountain.ble_connection_state,
168185
)
169186
return
170187

171-
await self.client.req.request(
172-
method=HTTPMethod.POST,
173-
url=PetkitEndpoint.BLE_CANCEL,
174-
data={
175-
"bleId": fountain_id,
176-
"type": water_fountain.device_nfo.type, # type: ignore[union-attr]
177-
"mac": water_fountain.mac,
178-
},
179-
headers=await self.client.get_session_id(),
180-
)
188+
await self._request_ble_api(PetkitEndpoint.BLE_CANCEL, water_fountain)
189+
water_fountain.ble_connection_state = BluetoothState.NOT_CONNECTED
181190
_LOGGER.debug("BLE connection closed successfully (id %s)", fountain_id)
182191

183192
async def get_ble_cmd_data(
@@ -229,17 +238,10 @@ async def send_ble_command(self, fountain_id: int, command: FountainAction) -> b
229238
cmd_code, cmd_data = await self.get_ble_cmd_data(
230239
list(command_data), water_fountain.ble_counter
231240
)
232-
response = await self.client.req.request(
233-
method=HTTPMethod.POST,
234-
url=PetkitEndpoint.BLE_CONTROL_DEVICE,
235-
data={
236-
"bleId": water_fountain.id,
237-
"cmd": cmd_code,
238-
"data": cmd_data,
239-
"mac": water_fountain.mac,
240-
"type": water_fountain.device_nfo.type, # type: ignore[union-attr]
241-
},
242-
headers=await self.client.get_session_id(),
241+
response = await self._request_ble_api(
242+
PetkitEndpoint.BLE_CONTROL_DEVICE,
243+
water_fountain,
244+
extra_data={"cmd": cmd_code, "data": cmd_data},
243245
)
244246
if response != 1:
245247
_LOGGER.error("Failed to send BLE command (id %s)", fountain_id)

pypetkitapi/const.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,14 @@ class RecordType(StrEnum):
151151

152152

153153
class BluetoothState(IntEnum):
154-
"""Possible states of a Bluetooth connection."""
155-
156-
NO_STATE = 0
157-
NOT_CONNECTED = 1
158-
CONNECTING = 2
159-
CONNECTED = 3
160-
ERROR = 4
154+
"""Possible states of a Bluetooth connection.
155+
Same value as returned by Petkit API
156+
"""
157+
158+
CONNECTING = 0
159+
CONNECTED = 1
160+
ERROR = -1
161+
NOT_CONNECTED = 2
161162

162163

163164
class PetkitEndpoint(StrEnum):

pypetkitapi/water_fountain_container.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class WaterFountain(BaseModel):
164164
water_pump_run_time: int | None = Field(None, alias="waterPumpRunTime")
165165
device_records: list[WaterFountainRecord] | None = None
166166
device_nfo: Device | None = None
167-
ble_connection_state: int = 0
167+
ble_connection_state: int = 2
168168
ble_counter: int = 0
169169
last_ble_poll: str | None = None
170170

0 commit comments

Comments
 (0)