gshock-api 2.0.4__tar.gz → 2.0.6__tar.gz

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.
Files changed (49) hide show
  1. {gshock_api-2.0.4/src/gshock_api.egg-info → gshock_api-2.0.6}/PKG-INFO +1 -1
  2. {gshock_api-2.0.4 → gshock_api-2.0.6}/pyproject.toml +3 -2
  3. {gshock_api-2.0.4 → gshock_api-2.0.6}/setup.cfg +2 -2
  4. {gshock_api-2.0.4 → gshock_api-2.0.6}/setup.py +1 -1
  5. gshock_api-2.0.6/src/gshock_api/cancelable_result.py +23 -0
  6. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/connection.py +25 -17
  7. gshock_api-2.0.6/src/gshock_api/exceptions.py +9 -0
  8. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/gshock_api.py +1 -1
  9. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/alarms_io.py +2 -5
  10. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/app_info_io.py +2 -6
  11. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/button_pressed_io.py +2 -8
  12. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/dst_for_world_cities_io.py +2 -5
  13. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/dst_watch_state_io.py +3 -5
  14. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/events_io.py +2 -7
  15. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/settings_io.py +2 -7
  16. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/time_adjustement_io.py +3 -8
  17. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/time_io.py +0 -1
  18. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/timer_io.py +3 -8
  19. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/watch_condition_io.py +2 -9
  20. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/watch_name_io.py +2 -3
  21. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/world_cities_io.py +2 -5
  22. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/message_dispatcher.py +0 -1
  23. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/scanner.py +4 -7
  24. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/watch_info.py +0 -2
  25. {gshock_api-2.0.4 → gshock_api-2.0.6/src/gshock_api.egg-info}/PKG-INFO +1 -1
  26. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api.egg-info/SOURCES.txt +1 -1
  27. gshock_api-2.0.4/src/gshock_api/cancelable_result.py +0 -38
  28. gshock_api-2.0.4/src/gshock_api/device.py +0 -6
  29. {gshock_api-2.0.4 → gshock_api-2.0.6}/LICENSE.txt +0 -0
  30. {gshock_api-2.0.4 → gshock_api-2.0.6}/README.rst +0 -0
  31. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/__init__.py +0 -0
  32. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/alarms.py +0 -0
  33. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/app_notification.py +0 -0
  34. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/casio_constants.py +0 -0
  35. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/configurator.py +0 -0
  36. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/event.py +0 -0
  37. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/__init__.py +0 -0
  38. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/app_notification_io.py +0 -0
  39. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/error_io.py +0 -0
  40. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/iolib/unknown_io.py +0 -0
  41. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/logger.py +0 -0
  42. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/mailsener.py +0 -0
  43. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/settings.py +0 -0
  44. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api/utils.py +0 -0
  45. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api.egg-info/dependency_links.txt +0 -0
  46. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api.egg-info/not-zip-safe +0 -0
  47. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api.egg-info/requires.txt +0 -0
  48. {gshock_api-2.0.4 → gshock_api-2.0.6}/src/gshock_api.egg-info/top_level.txt +0 -0
  49. {gshock_api-2.0.4 → gshock_api-2.0.6}/tests/test_code.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gshock_api
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: Pythgon API for GShock Watches using BLE
5
5
  Home-page: https://github.com/pyscaffold/pyscaffold/
6
6
  Author: Ivo Zivkov
@@ -1,10 +1,11 @@
1
1
  [build-system]
2
- requires = ["setuptools", "wheel"]
2
+ # requires = ["setuptools", "wheel"]
3
3
  build-backend = "setuptools.build_meta"
4
+ requires = ["setuptools>=61.0"]
4
5
 
5
6
  [project]
6
7
  name = "gshock_api" # Change to your project name
7
- version = "2.0.4"
8
+ version = "2.0.6"
8
9
  description = "Pythgon API for GShock Watches using BLE"
9
10
  readme = "README.rst"
10
11
  authors = [{ name = "Ivo Zivkov", email = "izivkov@gmail.com" }]
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
- name = GShockTimeServer
3
- description = Add a short description here!
2
+ name = gshock-api
3
+ description = API for G-Shock watches via Bluetooth Low Energy (BLE)
4
4
  author = Ivo Zivkov
5
5
  author_email = izivkov@gmail.com
6
6
  license = MIT
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='gshock_api',
5
- version='2.0.4',
5
+ version='2.0.6',
6
6
  package_dir={'': 'src'},
7
7
  packages=find_packages(where='src'),
8
8
  install_requires=[
@@ -0,0 +1,23 @@
1
+ import asyncio
2
+ from typing import Any
3
+ from gshock_api.exceptions import GShockConnectionError
4
+
5
+ class CancelableResult:
6
+ def __init__(self, timeout: float = 3.0):
7
+ self._timeout = timeout
8
+ self._future: asyncio.Future[Any] = asyncio.Future()
9
+
10
+ async def get_result(self) -> Any:
11
+ try:
12
+ result = await asyncio.wait_for(self._future, timeout=self._timeout)
13
+ return result
14
+ except asyncio.TimeoutError as e:
15
+ if not self._future.done():
16
+ self._future.set_result('') # or raise an exception instead
17
+ raise GShockConnectionError(f"Timeout occured wait for response from the watch: {e}") from e
18
+
19
+ def set_result(self, result: Any) -> None:
20
+ if not self._future.done():
21
+ self._future.set_result(result)
22
+
23
+ cancelable_result = CancelableResult()
@@ -6,16 +6,17 @@ from gshock_api import message_dispatcher
6
6
  from gshock_api.utils import to_casio_cmd
7
7
  from gshock_api.logger import logger
8
8
  from gshock_api.watch_info import watch_info
9
- from gshock_api.device import Device
9
+ from bleak.backends.device import BLEDevice
10
+ from gshock_api.scanner import scanner
11
+ from gshock_api.exceptions import GShockConnectionError
10
12
 
11
13
  class Connection:
12
- def __init__(self, device: Device):
14
+ def __init__(self, address = None):
13
15
  self.handles_map = self.init_handles_map()
14
- self.device = device
15
- self.client = BleakClient(device.address)
16
+ self.address = address
17
+ self.client: BleakClient = None
16
18
  self.characteristics_map = {}
17
19
 
18
-
19
20
  def notification_handler(
20
21
  self, characteristic: BleakGATTCharacteristic, data: bytearray
21
22
  ):
@@ -25,25 +26,31 @@ class Connection:
25
26
  """
26
27
  Prints all services and characteristics of the connected BLE device.
27
28
  """
28
- services = await self.client.get_services()
29
+ services = self.client.services
29
30
  for service in services:
30
31
  for char in service.characteristics:
31
32
  self.characteristics_map[char.uuid] = char.uuid # Store in map
32
33
 
33
- async def connect(self):
34
+ async def connect(self) -> bool:
34
35
  try:
36
+ # Scan for device if address not provided
37
+ device = await scanner.scan(device_address=self.address if self.address else None)
38
+ self.address = device.address # Always update with actual device found
39
+
40
+ self.client = BleakClient(self.address)
35
41
  await self.client.connect()
42
+
36
43
  await self.init_characteristics_map()
44
+
37
45
  await self.client.start_notify(
38
46
  CasioConstants.CASIO_ALL_FEATURES_CHARACTERISTIC_UUID,
39
47
  self.notification_handler,
40
48
  )
41
-
42
- watch_info.set_name_and_model(self.device.name)
49
+
43
50
  return True
44
-
51
+
45
52
  except Exception as e:
46
- logger.debug(f"Cannot connect: {e}")
53
+ logger.info(f"[GShock Connect] Connection failed: {e}")
47
54
  return False
48
55
 
49
56
  async def disconnect(self):
@@ -52,30 +59,31 @@ class Connection:
52
59
  def is_service_supported(self, handle):
53
60
  uuid = self.handles_map.get(handle)
54
61
  supported = (uuid not in self.characteristics_map)
55
- print(f"write, service with handle {handle} is supported: {supported}")
56
62
  return supported
57
63
 
58
64
  async def write(self, handle, data):
59
65
  try:
60
66
  uuid = self.handles_map.get(handle)
67
+
61
68
  if (uuid not in self.characteristics_map):
62
- logger.error(
69
+ logger.info(
63
70
  "write failed: handle {} not in characteristics map".format(handle)
64
71
  )
65
72
  if (handle == 13):
66
- logger.error(
73
+ logger.info(
67
74
  "Your watch does not suppot notifications..."
68
75
  )
69
76
  return
70
-
77
+
71
78
  await self.client.write_gatt_char(
72
79
  uuid, to_casio_cmd(data)
73
80
  )
81
+
74
82
  except Exception as e:
75
- logger.debug("write failed with exception: {}".format(e))
83
+ logger.info("write failed with exception: {}".format(e))
84
+ raise GShockConnectionError(f"Unable to connect to G-Shock device: {e}") from e
76
85
 
77
86
  async def request(self, request):
78
- logger.info("write: {}".format(request))
79
87
  await self.write(0xC, request)
80
88
 
81
89
  def init_handles_map(self):
@@ -0,0 +1,9 @@
1
+ # gshock_api/exceptions.py
2
+
3
+ class GShockError(Exception):
4
+ """Base exception for all G-Shock errors."""
5
+ pass
6
+
7
+ class GShockConnectionError(GShockError):
8
+ """Raised when BLE connection to G-Shock device fails."""
9
+ pass
@@ -231,7 +231,7 @@ class GshockAPI:
231
231
 
232
232
  async def _get_alarms(self):
233
233
  result = await message_dispatcher.AlarmsIO.request(self.connection)
234
- return await result
234
+ return result
235
235
 
236
236
  async def set_alarms(self, alarms):
237
237
  """Sets alarms to the watch. Up to 5 alarms are supported on the watch.
@@ -9,14 +9,12 @@ from gshock_api.casio_constants import CasioConstants
9
9
 
10
10
  CHARACTERISTICS = CasioConstants.CHARACTERISTICS
11
11
 
12
-
13
12
  class AlarmsIO:
14
13
  result: CancelableResult = None
15
14
  connection = None
16
15
 
17
16
  @staticmethod
18
17
  async def request(connection):
19
- await connection.request("GET_ALARMS")
20
18
  AlarmsIO.connection = connection
21
19
 
22
20
  alarms_inst.clear()
@@ -27,9 +25,8 @@ class AlarmsIO:
27
25
  async def _get_alarms(connection):
28
26
  await connection.sendMessage("""{ "action": "GET_ALARMS"}""")
29
27
 
30
- loop = asyncio.get_running_loop()
31
- AlarmsIO.result = loop.create_future()
32
- return AlarmsIO.result
28
+ AlarmsIO.result = CancelableResult()
29
+ return await AlarmsIO.result.get_result()
33
30
 
34
31
  @staticmethod
35
32
  async def send_to_watch(message=""):
@@ -15,13 +15,11 @@ class AppInfoIO:
15
15
 
16
16
  @staticmethod
17
17
  async def request(connection):
18
- logger.info(f"AppInfoIO request")
19
18
  AppInfoIO.connection = connection
20
19
  await connection.request("22")
21
20
 
22
- loop = asyncio.get_running_loop()
23
- AppInfoIO.result = loop.create_future()
24
- return AppInfoIO.result
21
+ AppInfoIO.result = CancelableResult()
22
+ return AppInfoIO.result.get_result()
25
23
 
26
24
  @staticmethod
27
25
  async def send_to_watch(connection):
@@ -29,8 +27,6 @@ class AppInfoIO:
29
27
 
30
28
  @staticmethod
31
29
  def on_received(data):
32
- logger.info(f"AppInfoIO onReceived")
33
-
34
30
  def set_app_info(data: str):
35
31
  # App info:
36
32
  # This is needed to re-enable button D (Lower-right) after the watch has been reset or BLE has been cleared.
@@ -26,9 +26,8 @@ class ButtonPressedIO:
26
26
  ButtonPressedIO.connection = connection
27
27
  await connection.request("10")
28
28
 
29
- loop = asyncio.get_running_loop()
30
- ButtonPressedIO.result = loop.create_future()
31
- return ButtonPressedIO.result
29
+ ButtonPressedIO.result = CancelableResult()
30
+ return ButtonPressedIO.result.get_result()
32
31
 
33
32
  @staticmethod
34
33
  async def send_to_watch(connection):
@@ -36,14 +35,10 @@ class ButtonPressedIO:
36
35
 
37
36
  @staticmethod
38
37
  async def send_to_watch_set(data):
39
- logger.info(f"TimerIO sendToWatchSet: {data}")
40
-
41
38
  await ButtonPressedIO.connection.write(0x000E, data)
42
39
 
43
40
  @staticmethod
44
41
  def on_received(data):
45
- logger.info(f"ButtonPressedIO onReceived")
46
-
47
42
  def button_pressed_callback(data):
48
43
  """
49
44
  RIGHT BUTTON: 0x10 17 62 07 38 85 CD 7F ->04<- 03 0F FF FF FF FF 24 00 00 00
@@ -57,7 +52,6 @@ class ButtonPressedIO:
57
52
  if len(data) >= 19:
58
53
  ble_int_arr = to_int_array(to_hex_string(data))
59
54
  button_indicator = ble_int_arr[8]
60
- logger.info(f"Buttom code pressed: ${button_indicator}")
61
55
  ret = (
62
56
  WatchButton.LOWER_LEFT
63
57
  if (button_indicator == 0 or button_indicator == 1)
@@ -14,14 +14,12 @@ class DstForWorldCitiesIO:
14
14
 
15
15
  @staticmethod
16
16
  async def request(connection, city_number: int):
17
- logger.info(f"DstForWorldCitiesIO request")
18
17
  DstForWorldCitiesIO.connection = connection
19
18
  key = "1e0{}".format(city_number)
20
19
  await connection.request(key)
21
20
 
22
- loop = asyncio.get_running_loop()
23
- DstForWorldCitiesIO.result = loop.create_future()
24
- return DstForWorldCitiesIO.result
21
+ DstForWorldCitiesIO.result = CancelableResult()
22
+ return DstForWorldCitiesIO.result.get_result()
25
23
 
26
24
  @staticmethod
27
25
  async def send_to_watch(connection):
@@ -29,5 +27,4 @@ class DstForWorldCitiesIO:
29
27
 
30
28
  @staticmethod
31
29
  def on_received(data):
32
- logger.info(f"DstForWorldCitiesIO onReceived")
33
30
  DstForWorldCitiesIO.result.set_result(data)
@@ -20,14 +20,13 @@ class DstWatchStateIO:
20
20
 
21
21
  @staticmethod
22
22
  async def request(connection, state: DtsState):
23
- logger.info(f"DstWatchStateIO request")
24
23
  DstWatchStateIO.connection = connection
25
24
  key = f"1d0{state.value}"
26
25
  await connection.request(key)
27
26
 
28
- loop = asyncio.get_running_loop()
29
- DstWatchStateIO.result = loop.create_future()
30
- return DstWatchStateIO.result
27
+ DstWatchStateIO.result = CancelableResult()
28
+ return DstWatchStateIO.result.get_result()
29
+
31
30
 
32
31
  @staticmethod
33
32
  async def send_to_watch(connection):
@@ -35,5 +34,4 @@ class DstWatchStateIO:
35
34
 
36
35
  @staticmethod
37
36
  def on_received(data):
38
- logger.info(f"DstWatchStateIO onReceived")
39
37
  DstWatchStateIO.result.set_result(data)
@@ -41,20 +41,16 @@ class EventsIO:
41
41
 
42
42
  @staticmethod
43
43
  async def request(connection, event_number):
44
- logger.info(f"EventsIO request")
45
44
  EventsIO.connection = connection
46
45
 
47
46
  await connection.request("30{}".format(event_number)) # reminder title
48
47
  await connection.request("31{}".format(event_number)) # reminder time
49
48
 
50
- loop = asyncio.get_running_loop()
51
- EventsIO.result = loop.create_future()
52
- return EventsIO.result
49
+ EventsIO.result = CancelableResult()
50
+ return EventsIO.result.get_result()
53
51
 
54
52
  @staticmethod
55
53
  async def send_to_watch_set(message):
56
- logger.info(f"EventsIO sendToWatchSet: {message}")
57
-
58
54
  def reminder_title_from_json(reminder_json):
59
55
  title_str = reminder_json.get("title")
60
56
  return to_byte_array(title_str, 18)
@@ -342,7 +338,6 @@ class EventsIO:
342
338
 
343
339
  reminder_json = json.loads(reminder_time_to_json(data[2:]))
344
340
  reminder_json.update(EventsIO.title)
345
- logger.info(reminder_json)
346
341
  EventsIO.result.set_result(reminder_json)
347
342
 
348
343
  @staticmethod
@@ -16,25 +16,20 @@ class SettingsIO:
16
16
 
17
17
  @staticmethod
18
18
  async def request(connection):
19
- logger.info(f"TimerIO request")
20
19
  SettingsIO.connection = connection
21
20
  await connection.request("13")
22
21
 
23
- loop = asyncio.get_running_loop()
24
- SettingsIO.result = loop.create_future()
25
- return SettingsIO.result
22
+ SettingsIO.result = CancelableResult()
23
+ return SettingsIO.result.get_result()
26
24
 
27
25
  @staticmethod
28
26
  def send_to_watch(message):
29
- logger.info(f"SettingsIO sendToWatch: {message}")
30
27
  SettingsIO.connection.write(
31
28
  0x000C, bytearray([CHARACTERISTICS["CASIO_SETTING_FOR_BASIC"]])
32
29
  )
33
30
 
34
31
  @staticmethod
35
32
  async def send_to_watch_set(message):
36
- logger.info(f"SettingsIO sendToWatchSet: {message}")
37
-
38
33
  def encode(settings):
39
34
  mask_24_hours = 0b00000001
40
35
  MASK_BUTTON_TONE_OFF = 0b00000010
@@ -20,27 +20,23 @@ class TimeAdjustmentIO:
20
20
 
21
21
  @staticmethod
22
22
  async def request(connection):
23
- logger.info(f"TimerIO request")
24
23
  TimeAdjustmentIO.connection = connection
25
24
  await connection.request("11")
26
25
 
27
- loop = asyncio.get_running_loop()
28
- TimeAdjustmentIO.result = loop.create_future()
29
- return TimeAdjustmentIO.result
26
+ TimeAdjustmentIO.result = CancelableResult()
27
+ return TimeAdjustmentIO.result.get_result()
28
+
30
29
 
31
30
  @staticmethod
32
31
  def send_to_watch(message):
33
- logger.info(f"TimeAdjustmentIO sendToWatch: {message}")
34
32
  TimeAdjustmentIO.connection.write(
35
33
  0x000C, bytearray([CHARACTERISTICS["TIME_ADJUSTMENT"]])
36
34
  )
37
35
 
38
36
  @staticmethod
39
37
  async def send_to_watch_set(message):
40
- logger.info(f"TimeAdjustmentIO sendToWatchSet: {message}")
41
38
 
42
39
  if TimeAdjustmentIO.original_value == None:
43
- logging.error("Error: Must call get before set")
44
40
  return ErrorIO.request("Error: Must call get before set")
45
41
 
46
42
  time_adjustment = json.loads(message).get("timeAdjustment") == "True"
@@ -61,7 +57,6 @@ class TimeAdjustmentIO:
61
57
 
62
58
  @staticmethod
63
59
  def on_received(message):
64
- logger.info(f"TimeAdjustmentIO onReceived: {message}")
65
60
  TimeAdjustmentIO.original_value = to_hex_string(
66
61
  message
67
62
  ) # save original message
@@ -32,7 +32,6 @@ class TimeIO:
32
32
  @staticmethod
33
33
  async def send_to_watch_set(message):
34
34
  date_time_ms = int(json.loads(message).get("value"))
35
- logger.info("date_time_ms: {}".format(date_time_ms))
36
35
  date_time = datetime.datetime.fromtimestamp(date_time_ms / 1000.0)
37
36
  time_data = TimeEncoder.prepare_current_time(date_time)
38
37
  time_command = to_hex_string(
@@ -16,13 +16,12 @@ class TimerIO:
16
16
 
17
17
  @staticmethod
18
18
  async def request(connection):
19
- logger.info(f"TimerIO request")
20
19
  TimerIO.connection = connection
21
20
  await connection.request("18")
22
21
 
23
- loop = asyncio.get_running_loop()
24
- TimerIO.result = loop.create_future()
25
- return TimerIO.result
22
+ TimerIO.result = CancelableResult()
23
+ return TimerIO.result.get_result()
24
+
26
25
 
27
26
  @staticmethod
28
27
  async def send_to_watch(connection):
@@ -30,8 +29,6 @@ class TimerIO:
30
29
 
31
30
  @staticmethod
32
31
  async def send_to_watch_set(data):
33
- logger.info(f"TimerIO sendToWatchSet: {data}")
34
-
35
32
  def encode(seconds_str):
36
33
  in_seconds = int(seconds_str)
37
34
  hours = in_seconds // 3600
@@ -53,8 +50,6 @@ class TimerIO:
53
50
 
54
51
  @staticmethod
55
52
  def on_received(data):
56
- logger.info(f"TimerIO onReceived")
57
-
58
53
  def decode_value(data: str) -> str:
59
54
  timer_int_array = data
60
55
 
@@ -19,13 +19,11 @@ class WatchConditionIO:
19
19
 
20
20
  @staticmethod
21
21
  async def request(connection):
22
- logger.info(f"WatchConditionIO request")
23
22
  WatchConditionIO.connection = connection
24
23
  await connection.request("28")
25
24
 
26
- loop = asyncio.get_running_loop()
27
- WatchConditionIO.result = loop.create_future()
28
- return WatchConditionIO.result
25
+ WatchConditionIO.result = CancelableResult()
26
+ return WatchConditionIO.result.get_result()
29
27
 
30
28
  @staticmethod
31
29
  async def send_to_watch(connection):
@@ -33,16 +31,11 @@ class WatchConditionIO:
33
31
 
34
32
  @staticmethod
35
33
  def on_received(data):
36
- logger.info(f"WatchConditionIO onReceived")
37
-
38
34
  def decode_value(data: str) -> WatchConditionIO.WatchConditionValue:
39
35
  int_arr = list(map(int, data))
40
36
  bytes_data = bytes(int_arr[1:])
41
37
 
42
38
  if len(bytes_data) >= 2:
43
- # Battery level between 15 and 20 for B2100 and between 12 and 19 for B5600. Scale accordingly to %
44
- logger.info(f"battery level row value: {int(bytes_data[0])}")
45
-
46
39
  battery_level_lower_limit = watch_info.batteryLevelLowerLimit
47
40
  battery_level_upper_limit = watch_info.batteryLevelUpperLimit
48
41
 
@@ -15,9 +15,8 @@ class WatchNameIO:
15
15
  WatchNameIO.connection = connection
16
16
  await connection.request("23")
17
17
 
18
- loop = asyncio.get_running_loop()
19
- WatchNameIO.result = loop.create_future()
20
- return WatchNameIO.result
18
+ WatchNameIO.result = CancelableResult()
19
+ return WatchNameIO.result.get_result()
21
20
 
22
21
  @staticmethod
23
22
  def on_received(data):
@@ -13,15 +13,13 @@ class WorldCitiesIO:
13
13
 
14
14
  @staticmethod
15
15
  async def request(connection, cityNumber: int):
16
- logger.info(f"DstWatchStateIO request")
17
16
  WorldCitiesIO.connection = connection
18
17
  key = "1f0{}".format(cityNumber)
19
18
 
20
19
  await connection.request(key)
21
20
 
22
- loop = asyncio.get_running_loop()
23
- WorldCitiesIO.result = loop.create_future()
24
- return WorldCitiesIO.result
21
+ WorldCitiesIO.result = CancelableResult()
22
+ return WorldCitiesIO.result.get_result()
25
23
 
26
24
  @staticmethod
27
25
  async def send_to_watch(connection):
@@ -29,5 +27,4 @@ class WorldCitiesIO:
29
27
 
30
28
  @staticmethod
31
29
  def on_received(data):
32
- logger.info(f"WorldCitiesIO onReceived")
33
30
  WorldCitiesIO.result.set_result(data)
@@ -72,7 +72,6 @@ class MessageDispatcher:
72
72
  if key not in MessageDispatcher.data_received_messages:
73
73
  logger.info(f"Unknown key: {key}")
74
74
  else:
75
- logger.info(f"Found key: {MessageDispatcher.data_received_messages[key]}")
76
75
  MessageDispatcher.data_received_messages[key](data)
77
76
 
78
77
  # Usage example
@@ -4,14 +4,13 @@ from bleak import BleakScanner
4
4
  from gshock_api.configurator import conf
5
5
  from gshock_api.watch_info import watch_info
6
6
  from gshock_api.logger import logger
7
- from gshock_api.device import Device
7
+ from bleak.backends.device import BLEDevice
8
8
 
9
9
  class Scanner:
10
10
  CASIO_SERVICE_UUID = "00001804-0000-1000-8000-00805f9b34fb"
11
11
 
12
- async def scan(self, device_address=None) -> Device:
12
+ async def scan(self, device_address=None) -> BLEDevice:
13
13
  scanner = BleakScanner()
14
- logger.info("Scanning for devices...")
15
14
 
16
15
  if device_address is None:
17
16
  while True:
@@ -19,12 +18,10 @@ class Scanner:
19
18
  lambda d, ad: d.name and d.name.lower().startswith("casio"),
20
19
  timeout=5 * 60.0,
21
20
  )
22
- logger.info(f"device: {device}")
23
21
  if device is None:
24
22
  continue
25
23
 
26
- # This is now set after connection in Connection class
27
- # watch_info.set_name_and_model(device.name)
24
+ watch_info.set_name_and_model(device.name)
28
25
 
29
26
  conf.put("device.address", device.address)
30
27
  conf.put("device.name", device.name)
@@ -36,6 +33,6 @@ class Scanner:
36
33
  )
37
34
  watch_info.set_name_and_model(device.name)
38
35
 
39
- return Device(device.name, device.address)
36
+ return device
40
37
 
41
38
  scanner = Scanner()
@@ -202,8 +202,6 @@ class WatchInfo:
202
202
  if len(parts) > 1:
203
203
  self.shortName = parts[1]
204
204
 
205
- logger.info(f"============> self.shortName: ${self.shortName}")
206
-
207
205
  # *** Order matters. Start with the longest shortName first. ***
208
206
  if self.shortName.startswith("MSG"):
209
207
  self.model = WATCH_MODEL.MSG
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gshock_api
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: Pythgon API for GShock Watches using BLE
5
5
  Home-page: https://github.com/pyscaffold/pyscaffold/
6
6
  Author: Ivo Zivkov
@@ -10,8 +10,8 @@ src/gshock_api/cancelable_result.py
10
10
  src/gshock_api/casio_constants.py
11
11
  src/gshock_api/configurator.py
12
12
  src/gshock_api/connection.py
13
- src/gshock_api/device.py
14
13
  src/gshock_api/event.py
14
+ src/gshock_api/exceptions.py
15
15
  src/gshock_api/gshock_api.py
16
16
  src/gshock_api/logger.py
17
17
  src/gshock_api/mailsener.py
@@ -1,38 +0,0 @@
1
- import asyncio
2
- from typing import Any
3
-
4
- class CancelableResult:
5
- def __init__(self, timeout: float = 5.0):
6
- self._timeout = timeout
7
- self._future: asyncio.Future[Any] = asyncio.Future()
8
-
9
- async def get_result(self) -> Any:
10
- try:
11
- return await asyncio.wait_for(self._future, timeout=self._timeout)
12
- except asyncio.TimeoutError:
13
- if not self._future.done():
14
- self._future.set_result('')
15
- return await self._future
16
-
17
- def set_result(self, result: Any) -> None:
18
- if not self._future.done():
19
- self._future.set_result(result)
20
-
21
- # Example usage
22
- async def main():
23
- cancelable_result = CancelableResult(timeout=5)
24
-
25
- # Simulate some async work that might or might not set a result
26
- async def some_async_work():
27
- await asyncio.sleep(3) # Change this to 6 to test the timeout
28
- cancelable_result.set_result('Result after async work')
29
-
30
- await asyncio.gather(some_async_work(), asyncio.sleep(6))
31
-
32
- final_result = await cancelable_result.get_result()
33
- print(f'Final result: "{final_result}"')
34
-
35
- # Run the main coroutine
36
- # asyncio.run(main())
37
-
38
- cancelable_result = CancelableResult()
@@ -1,6 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
- @dataclass
4
- class Device:
5
- name: str
6
- address: str
File without changes
File without changes