busylib 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of busylib might be problematic. Click here for more details.

busylib/client.py CHANGED
@@ -29,9 +29,24 @@ class BusyBar:
29
29
  Main library class for interacting with the Busy Bar API.
30
30
  """
31
31
 
32
- def __init__(self, addr: str):
33
- self.base_url = f"http://{addr}"
32
+ def __init__(
33
+ self,
34
+ addr: str | None = None,
35
+ *,
36
+ token: str | None = None,
37
+ ) -> None:
38
+ if addr is None and token is None:
39
+ self.base_url = "http://10.0.4.20"
40
+ elif addr is None:
41
+ self.base_url = "https://proxy.dev.busy.app"
42
+ elif addr is not None:
43
+ if "://" not in addr:
44
+ addr = f"http://{addr}"
45
+ self.base_url = addr
46
+
34
47
  self.client = requests.Session()
48
+ if token is not None:
49
+ self.client.headers["Authorization"] = f"Bearer {token}"
35
50
 
36
51
  def __enter__(self):
37
52
  return self
@@ -67,9 +82,7 @@ class BusyBar:
67
82
  return response.text
68
83
 
69
84
  def get_version(self) -> types.VersionInfo:
70
- response = self.client.get(
71
- urllib.parse.urljoin(self.base_url, "/api/v0/version")
72
- )
85
+ response = self.client.get(urllib.parse.urljoin(self.base_url, "/api/version"))
73
86
  data = self._handle_response(response)
74
87
  return types.VersionInfo(**data)
75
88
 
@@ -81,7 +94,7 @@ class BusyBar:
81
94
  params["name"] = name
82
95
 
83
96
  response = self.client.post(
84
- urllib.parse.urljoin(self.base_url, "/api/v0/update"),
97
+ urllib.parse.urljoin(self.base_url, "/api/update"),
85
98
  params=params,
86
99
  data=firmware_data,
87
100
  headers={"Content-Type": "application/octet-stream"},
@@ -90,9 +103,7 @@ class BusyBar:
90
103
  return types.SuccessResponse(**data)
91
104
 
92
105
  def get_status(self) -> types.Status:
93
- response = self.client.get(
94
- urllib.parse.urljoin(self.base_url, "/api/v0/status")
95
- )
106
+ response = self.client.get(urllib.parse.urljoin(self.base_url, "/api/status"))
96
107
  data = self._handle_response(response)
97
108
 
98
109
  system = None
@@ -112,14 +123,14 @@ class BusyBar:
112
123
 
113
124
  def get_system_status(self) -> types.StatusSystem:
114
125
  response = self.client.get(
115
- urllib.parse.urljoin(self.base_url, "/api/v0/status/system")
126
+ urllib.parse.urljoin(self.base_url, "/api/status/system")
116
127
  )
117
128
  data = self._handle_response(response)
118
129
  return types.StatusSystem(**data)
119
130
 
120
131
  def get_power_status(self) -> types.StatusPower:
121
132
  response = self.client.get(
122
- urllib.parse.urljoin(self.base_url, "/api/v0/status/power")
133
+ urllib.parse.urljoin(self.base_url, "/api/status/power")
123
134
  )
124
135
  data = self._handle_response(response)
125
136
 
@@ -130,7 +141,7 @@ class BusyBar:
130
141
 
131
142
  def write_storage_file(self, path: str, data: bytes) -> types.SuccessResponse:
132
143
  response = self.client.post(
133
- urllib.parse.urljoin(self.base_url, "/api/v0/storage/write"),
144
+ urllib.parse.urljoin(self.base_url, "/api/storage/write"),
134
145
  params={"path": path},
135
146
  data=data,
136
147
  headers={"Content-Type": "application/octet-stream"},
@@ -140,14 +151,14 @@ class BusyBar:
140
151
 
141
152
  def read_storage_file(self, path: str) -> bytes:
142
153
  response = self.client.get(
143
- urllib.parse.urljoin(self.base_url, "/api/v0/storage/read"),
154
+ urllib.parse.urljoin(self.base_url, "/api/storage/read"),
144
155
  params={"path": path},
145
156
  )
146
157
  return self._handle_response(response, as_bytes=True)
147
158
 
148
159
  def list_storage_files(self, path: str) -> types.StorageList:
149
160
  response = self.client.get(
150
- urllib.parse.urljoin(self.base_url, "/api/v0/storage/list"),
161
+ urllib.parse.urljoin(self.base_url, "/api/storage/list"),
151
162
  params={"path": path},
152
163
  )
153
164
  data = self._handle_response(response)
@@ -163,7 +174,7 @@ class BusyBar:
163
174
 
164
175
  def remove_storage_file(self, path: str) -> types.SuccessResponse:
165
176
  response = self.client.delete(
166
- urllib.parse.urljoin(self.base_url, "/api/v0/storage/remove"),
177
+ urllib.parse.urljoin(self.base_url, "/api/storage/remove"),
167
178
  params={"path": path},
168
179
  )
169
180
  data = self._handle_response(response)
@@ -171,7 +182,7 @@ class BusyBar:
171
182
 
172
183
  def create_storage_directory(self, path: str) -> types.SuccessResponse:
173
184
  response = self.client.post(
174
- urllib.parse.urljoin(self.base_url, "/api/v0/storage/mkdir"),
185
+ urllib.parse.urljoin(self.base_url, "/api/storage/mkdir"),
175
186
  params={"path": path},
176
187
  )
177
188
  data = self._handle_response(response)
@@ -181,7 +192,7 @@ class BusyBar:
181
192
  self, app_id: str, filename: str, data: bytes
182
193
  ) -> types.SuccessResponse:
183
194
  response = self.client.post(
184
- urllib.parse.urljoin(self.base_url, "/api/v0/assets/upload"),
195
+ urllib.parse.urljoin(self.base_url, "/api/assets/upload"),
185
196
  params={"app_id": app_id, "file": filename},
186
197
  data=data,
187
198
  headers={"Content-Type": "application/octet-stream"},
@@ -191,7 +202,7 @@ class BusyBar:
191
202
 
192
203
  def delete_app_assets(self, app_id: str) -> types.SuccessResponse:
193
204
  response = self.client.delete(
194
- urllib.parse.urljoin(self.base_url, "/api/v0/assets/upload"),
205
+ urllib.parse.urljoin(self.base_url, "/api/assets/upload"),
195
206
  params={"app_id": app_id},
196
207
  )
197
208
  data = self._handle_response(response)
@@ -201,7 +212,7 @@ class BusyBar:
201
212
  self, display_data: types.DisplayElements
202
213
  ) -> types.SuccessResponse:
203
214
  response = self.client.post(
204
- urllib.parse.urljoin(self.base_url, "/api/v0/display/draw"),
215
+ urllib.parse.urljoin(self.base_url, "/api/display/draw"),
205
216
  json=_serialize_for_json(display_data),
206
217
  headers={"Content-Type": "application/json"},
207
218
  )
@@ -210,14 +221,14 @@ class BusyBar:
210
221
 
211
222
  def clear_display(self) -> types.SuccessResponse:
212
223
  response = self.client.delete(
213
- urllib.parse.urljoin(self.base_url, "/api/v0/display/draw")
224
+ urllib.parse.urljoin(self.base_url, "/api/display/draw")
214
225
  )
215
226
  data = self._handle_response(response)
216
227
  return types.SuccessResponse(**data)
217
228
 
218
229
  def get_display_brightness(self) -> types.DisplayBrightnessInfo:
219
230
  response = self.client.get(
220
- urllib.parse.urljoin(self.base_url, "/api/v0/display/brightness")
231
+ urllib.parse.urljoin(self.base_url, "/api/display/brightness")
221
232
  )
222
233
  data = self._handle_response(response)
223
234
  return types.DisplayBrightnessInfo(**data)
@@ -232,7 +243,7 @@ class BusyBar:
232
243
  params["back"] = back
233
244
 
234
245
  response = self.client.post(
235
- urllib.parse.urljoin(self.base_url, "/api/v0/display/brightness"),
246
+ urllib.parse.urljoin(self.base_url, "/api/display/brightness"),
236
247
  params=params,
237
248
  )
238
249
  data = self._handle_response(response)
@@ -240,7 +251,7 @@ class BusyBar:
240
251
 
241
252
  def play_audio(self, app_id: str, path: str) -> types.SuccessResponse:
242
253
  response = self.client.post(
243
- urllib.parse.urljoin(self.base_url, "/api/v0/audio/play"),
254
+ urllib.parse.urljoin(self.base_url, "/api/audio/play"),
244
255
  params={"app_id": app_id, "path": path},
245
256
  )
246
257
  data = self._handle_response(response)
@@ -248,21 +259,21 @@ class BusyBar:
248
259
 
249
260
  def stop_audio(self) -> types.SuccessResponse:
250
261
  response = self.client.delete(
251
- urllib.parse.urljoin(self.base_url, "/api/v0/audio/play")
262
+ urllib.parse.urljoin(self.base_url, "/api/audio/play")
252
263
  )
253
264
  data = self._handle_response(response)
254
265
  return types.SuccessResponse(**data)
255
266
 
256
267
  def get_audio_volume(self) -> types.AudioVolumeInfo:
257
268
  response = self.client.get(
258
- urllib.parse.urljoin(self.base_url, "/api/v0/audio/volume")
269
+ urllib.parse.urljoin(self.base_url, "/api/audio/volume")
259
270
  )
260
271
  data = self._handle_response(response)
261
272
  return types.AudioVolumeInfo(**data)
262
273
 
263
274
  def set_audio_volume(self, volume: float) -> types.SuccessResponse:
264
275
  response = self.client.post(
265
- urllib.parse.urljoin(self.base_url, "/api/v0/audio/volume"),
276
+ urllib.parse.urljoin(self.base_url, "/api/audio/volume"),
266
277
  params={"volume": volume},
267
278
  )
268
279
  data = self._handle_response(response)
@@ -270,29 +281,15 @@ class BusyBar:
270
281
 
271
282
  def send_input_key(self, key: types.InputKey) -> types.SuccessResponse:
272
283
  response = self.client.post(
273
- urllib.parse.urljoin(self.base_url, "/api/v0/input"),
284
+ urllib.parse.urljoin(self.base_url, "/api/input"),
274
285
  params={"key": key.value},
275
286
  )
276
287
  data = self._handle_response(response)
277
288
  return types.SuccessResponse(**data)
278
289
 
279
- def enable_wifi(self) -> types.SuccessResponse:
280
- response = self.client.post(
281
- urllib.parse.urljoin(self.base_url, "/api/v0/wifi/enable")
282
- )
283
- data = self._handle_response(response)
284
- return types.SuccessResponse(**data)
285
-
286
- def disable_wifi(self) -> types.SuccessResponse:
287
- response = self.client.post(
288
- urllib.parse.urljoin(self.base_url, "/api/v0/wifi/disable")
289
- )
290
- data = self._handle_response(response)
291
- return types.SuccessResponse(**data)
292
-
293
290
  def get_wifi_status(self) -> types.StatusResponse:
294
291
  response = self.client.get(
295
- urllib.parse.urljoin(self.base_url, "/api/v0/wifi/status")
292
+ urllib.parse.urljoin(self.base_url, "/api/wifi/status")
296
293
  )
297
294
  data = self._handle_response(response)
298
295
 
@@ -316,7 +313,7 @@ class BusyBar:
316
313
 
317
314
  def connect_wifi(self, config: types.ConnectRequestConfig) -> types.SuccessResponse:
318
315
  response = self.client.post(
319
- urllib.parse.urljoin(self.base_url, "/api/v0/wifi/connect"),
316
+ urllib.parse.urljoin(self.base_url, "/api/wifi/connect"),
320
317
  json=_serialize_for_json(config),
321
318
  headers={"Content-Type": "application/json"},
322
319
  )
@@ -325,14 +322,14 @@ class BusyBar:
325
322
 
326
323
  def disconnect_wifi(self) -> types.SuccessResponse:
327
324
  response = self.client.post(
328
- urllib.parse.urljoin(self.base_url, "/api/v0/wifi/disconnect")
325
+ urllib.parse.urljoin(self.base_url, "/api/wifi/disconnect")
329
326
  )
330
327
  data = self._handle_response(response)
331
328
  return types.SuccessResponse(**data)
332
329
 
333
330
  def scan_wifi_networks(self) -> types.NetworkResponse:
334
331
  response = self.client.get(
335
- urllib.parse.urljoin(self.base_url, "/api/v0/wifi/networks")
332
+ urllib.parse.urljoin(self.base_url, "/api/wifi/networks")
336
333
  )
337
334
  data = self._handle_response(response)
338
335
 
@@ -353,7 +350,20 @@ class BusyBar:
353
350
 
354
351
  def get_screen_frame(self, display: int) -> bytes:
355
352
  response = self.client.get(
356
- urllib.parse.urljoin(self.base_url, "/api/v0/screen"),
353
+ urllib.parse.urljoin(self.base_url, "/api/screen"),
357
354
  params={"display": display},
358
355
  )
359
356
  return self._handle_response(response, as_bytes=True)
357
+ def ble_enable(self) -> types.SuccessResponse:
358
+ response = self.client.post(
359
+ urllib.parse.urljoin(self.base_url, "/api/ble/enable")
360
+ )
361
+ data = self._handle_response(response)
362
+ return types.SuccessResponse(**data)
363
+
364
+ def ble_disable(self) -> types.SuccessResponse:
365
+ response = self.client.post(
366
+ urllib.parse.urljoin(self.base_url, "/api/ble/disable")
367
+ )
368
+ data = self._handle_response(response)
369
+ return types.SuccessResponse(**data)
busylib/types.py CHANGED
@@ -2,19 +2,18 @@ import dataclasses
2
2
  import enum
3
3
  import typing as tp
4
4
 
5
+ class WifiState(enum.Enum):
6
+ DISCONNECTED = "disconnected"
7
+ CONNECTED = "connected"
5
8
 
6
9
  class WifiSecurityMethod(enum.Enum):
7
10
  OPEN = "Open"
8
11
  WPA = "WPA"
9
12
  WPA2 = "WPA2"
10
13
  WEP = "WEP"
11
- WPA_ENTERPRISE = "WPA (Enterprise)"
12
- WPA2_ENTERPRISE = "WPA2 (Enterprise)"
13
14
  WPA_WPA2 = "WPA/WPA2"
14
15
  WPA3 = "WPA3"
15
16
  WPA2_WPA3 = "WPA2/WPA3"
16
- WPA3_ENTERPRISE = "WPA3 (Enterprise)"
17
- WPA2_WPA3_ENTERPRISE = "WPA2/WPA3 (Enterprise)"
18
17
 
19
18
 
20
19
  class WifiIpMethod(enum.Enum):
@@ -33,12 +32,6 @@ class PowerState(enum.Enum):
33
32
  CHARGED = "charged"
34
33
 
35
34
 
36
- class WifiState(enum.Enum):
37
- DISABLED = "disabled"
38
- ENABLED = "enabled"
39
- CONNECTED = "connected"
40
-
41
-
42
35
  class ElementType(enum.Enum):
43
36
  FILE = "file"
44
37
  DIR = "dir"
@@ -80,10 +73,7 @@ class Error:
80
73
 
81
74
  @dataclasses.dataclass(frozen=True)
82
75
  class VersionInfo:
83
- branch: str
84
- version: str
85
- build_date: str
86
- commit_hash: str
76
+ api_semver: str
87
77
 
88
78
 
89
79
  @dataclasses.dataclass(frozen=True)
@@ -190,6 +180,9 @@ class Network:
190
180
  class StatusResponse:
191
181
  state: WifiState | None = None
192
182
  ssid: str | None = None
183
+ bssid: str | None = None
184
+ channel: int | None = None
185
+ rssi: int | None = None
193
186
  security: WifiSecurityMethod | None = None
194
187
  ip_config: WifiIpConfig | None = None
195
188
 
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: busylib
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Python library for Busy Bar API
5
- Author-email: Valerii Lisai <v.lisai@flipperdevices.com>
6
- Project-URL: Homepage, https://github.com/busy-app/busylib
7
- Project-URL: Repository, https://github.com/busy-app/busylib
5
+ Author-email: flipperdevices <pypi@flipperdevices.com>
6
+ Project-URL: Homepage, https://github.com/busy-app/busylib-py
7
+ Project-URL: Repository, https://github.com/busy-app/busylib-py
8
8
  Project-URL: Documentation, https://busylib.readthedocs.io
9
9
  Classifier: Development Status :: 3 - Alpha
10
10
  Classifier: Intended Audience :: Developers
@@ -0,0 +1,9 @@
1
+ busylib/__init__.py,sha256=7CQFe1iS-QRVAVlufLarG0MXEjkbqZht_DI2kUvsHz0,28
2
+ busylib/client.py,sha256=9Xv_1wGSj4UL4GxN_DUsOoaoK3kMjyEI2x7vAZkTQKc,13078
3
+ busylib/exceptions.py,sha256=DHYoEXGdADXSxcgLq7BWqq_865J0LsMysZL-Wuip2wc,210
4
+ busylib/types.py,sha256=NRN5K-z86KhzREkO7AWtxGQqK067sQFTJ07CszBCZAQ,4063
5
+ busylib-0.3.0.dist-info/licenses/LICENSE,sha256=aJO9BQGuVb1fvGzHcgWYiwcC9kEFyD-FBb8SPO-ATJ4,1071
6
+ busylib-0.3.0.dist-info/METADATA,sha256=A22FG9UibubAY5BW5fRl0x4TdnpHCqaxp0O2niPd_EQ,5518
7
+ busylib-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ busylib-0.3.0.dist-info/top_level.txt,sha256=tXeqg2EVVj4E8-ywimkxRzuCJq2HqMXA0571IB15PDA,8
9
+ busylib-0.3.0.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- busylib/__init__.py,sha256=7CQFe1iS-QRVAVlufLarG0MXEjkbqZht_DI2kUvsHz0,28
2
- busylib/client.py,sha256=l-gMVPP5X9m0IGqnjMjKPUo-olw4nf2cHvgz7DtdIjw,12746
3
- busylib/exceptions.py,sha256=DHYoEXGdADXSxcgLq7BWqq_865J0LsMysZL-Wuip2wc,210
4
- busylib/types.py,sha256=AGNd39jN5Rn5fI9kk5Ugk-4fr3JeXQpka2YEFeEWKNw,4223
5
- busylib-0.1.0.dist-info/licenses/LICENSE,sha256=aJO9BQGuVb1fvGzHcgWYiwcC9kEFyD-FBb8SPO-ATJ4,1071
6
- busylib-0.1.0.dist-info/METADATA,sha256=v8QccaMsA439sMQYg5hrQ9dAcDmIZKXuPHts6UnDIcc,5514
7
- busylib-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- busylib-0.1.0.dist-info/top_level.txt,sha256=tXeqg2EVVj4E8-ywimkxRzuCJq2HqMXA0571IB15PDA,8
9
- busylib-0.1.0.dist-info/RECORD,,