gshock-api 2.0.2__tar.gz → 2.0.4__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.
- gshock_api-2.0.4/PKG-INFO +120 -0
- gshock_api-2.0.4/README.rst +107 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/pyproject.toml +1 -1
- {gshock_api-2.0.2 → gshock_api-2.0.4}/setup.py +1 -1
- gshock_api-2.0.4/src/gshock_api/app_notification.py +55 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/casio_constants.py +1 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/connection.py +38 -4
- gshock_api-2.0.4/src/gshock_api/device.py +6 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/gshock_api.py +10 -9
- gshock_api-2.0.4/src/gshock_api/iolib/app_notification_io.py +170 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/button_pressed_io.py +0 -1
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/dst_watch_state_io.py +0 -1
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/error_io.py +1 -1
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/message_dispatcher.py +0 -1
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/scanner.py +7 -8
- gshock_api-2.0.4/src/gshock_api.egg-info/PKG-INFO +120 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api.egg-info/SOURCES.txt +3 -1
- gshock_api-2.0.2/PKG-INFO +0 -100
- gshock_api-2.0.2/README.rst +0 -87
- gshock_api-2.0.2/src/gshock_api/core.py +0 -4
- gshock_api-2.0.2/src/gshock_api.egg-info/PKG-INFO +0 -100
- {gshock_api-2.0.2 → gshock_api-2.0.4}/LICENSE.txt +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/setup.cfg +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/__init__.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/alarms.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/cancelable_result.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/configurator.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/event.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/__init__.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/alarms_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/app_info_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/dst_for_world_cities_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/events_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/settings_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/time_adjustement_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/time_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/timer_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/unknown_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/watch_condition_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/watch_name_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/iolib/world_cities_io.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/logger.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/mailsener.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/settings.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/utils.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api/watch_info.py +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api.egg-info/dependency_links.txt +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api.egg-info/not-zip-safe +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api.egg-info/requires.txt +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/src/gshock_api.egg-info/top_level.txt +0 -0
- {gshock_api-2.0.2 → gshock_api-2.0.4}/tests/test_code.py +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gshock_api
|
|
3
|
+
Version: 2.0.4
|
|
4
|
+
Summary: Pythgon API for GShock Watches using BLE
|
|
5
|
+
Home-page: https://github.com/pyscaffold/pyscaffold/
|
|
6
|
+
Author: Ivo Zivkov
|
|
7
|
+
Author-email: Ivo Zivkov <izivkov@gmail.com>
|
|
8
|
+
Platform: any
|
|
9
|
+
Description-Content-Type: text/x-rst
|
|
10
|
+
License-File: LICENSE.txt
|
|
11
|
+
Requires-Dist: requests
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
gshock_api
|
|
15
|
+
================
|
|
16
|
+
|
|
17
|
+
Announcement
|
|
18
|
+
============
|
|
19
|
+
|
|
20
|
+
The library now supports sending application-level notifications to watches that support it, namely:
|
|
21
|
+
|
|
22
|
+
* DW-H5600
|
|
23
|
+
* GBD-H2000
|
|
24
|
+
* GBD-200
|
|
25
|
+
* GBD-100
|
|
26
|
+
* GBD-800
|
|
27
|
+
* GBD-100BAR
|
|
28
|
+
* GBX-100
|
|
29
|
+
|
|
30
|
+
The new API is **send_app_notification** function.
|
|
31
|
+
See the `examples/api_test.py <https://github.com/izivkov/gshock_api/blob/main/src/examples/api_tests.py#L453-L456>`_ file for usage examples.
|
|
32
|
+
|
|
33
|
+
Only the **DW-H5600** watch has been tested. If you have any of the watches supporting notifications, please let me know your findings.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Overview
|
|
37
|
+
========
|
|
38
|
+
This is a **Python API library** for G-Shock watches that support Bluetooth Low Energy (BLE) communication.
|
|
39
|
+
|
|
40
|
+
G(M)W-5600, G(M)W-5000, GA-B2100, GA-B001-1AER, GST-B500, GST-B200, MSG-B100,
|
|
41
|
+
G-B001, GBD-H1000 (Partial support), MRG-B5000, GCW-B5000, GG-B100, ABL-100WE,
|
|
42
|
+
Edifice ECB-30, ECB-10, ECB-20, most Edifice watches, most Protrek models.
|
|
43
|
+
|
|
44
|
+
It can perform the following tasks:
|
|
45
|
+
|
|
46
|
+
- Set watch's time
|
|
47
|
+
- Set Home Time (Home City)
|
|
48
|
+
- Set Alarms
|
|
49
|
+
- Set Reminders
|
|
50
|
+
- Set watch's settings.
|
|
51
|
+
- Get watch's name
|
|
52
|
+
- Get watch's battery level
|
|
53
|
+
- Get Watch's temperature
|
|
54
|
+
- Get/Set watch's Timer
|
|
55
|
+
- Send notifications to watch (supported models)
|
|
56
|
+
|
|
57
|
+
Dependencies
|
|
58
|
+
============
|
|
59
|
+
|
|
60
|
+
This project requires the following Python packages:
|
|
61
|
+
.. code-block:: sh
|
|
62
|
+
|
|
63
|
+
pytz
|
|
64
|
+
bleak
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
So you can install them using the following command:
|
|
68
|
+
.. code-block:: sh
|
|
69
|
+
|
|
70
|
+
pip3 install -r requirements.txt
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
To understand how to use the library, please refer to the **`src/examples`** folder.
|
|
74
|
+
|
|
75
|
+
Virtual Environment Setup
|
|
76
|
+
=========================
|
|
77
|
+
|
|
78
|
+
It is recommended that you create a virtual environment to run the tests:
|
|
79
|
+
|
|
80
|
+
1. Create a virtual environment:
|
|
81
|
+
|
|
82
|
+
.. code-block:: sh
|
|
83
|
+
|
|
84
|
+
# Create a virtual environment
|
|
85
|
+
python3 -m venv venv
|
|
86
|
+
|
|
87
|
+
# Activate it (Mac/Linux)
|
|
88
|
+
source venv/bin/activate
|
|
89
|
+
|
|
90
|
+
# Install dependencies
|
|
91
|
+
pip3 install -e .
|
|
92
|
+
|
|
93
|
+
2. Run the tests:
|
|
94
|
+
|
|
95
|
+
.. code-block:: sh
|
|
96
|
+
|
|
97
|
+
python3 src/examples/api_tests.py [--multi-watch]
|
|
98
|
+
|
|
99
|
+
The optional **`--multi-watch`** parameter forces the library to scan for watches every time it tries to connect to a watch. If not provided,
|
|
100
|
+
the library will try to connect to the last connected watch only. If you have multiple watches, you should use this parameter.
|
|
101
|
+
|
|
102
|
+
The optional **`--multi-watch`** parameter forces the library to scan for watches every time it tries to connect to a watch. If not provided,
|
|
103
|
+
the library will try to connect to the last connected watch only. If you have multiple watches, you should use this parameter.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
Installing the library for your project:
|
|
107
|
+
========================================
|
|
108
|
+
|
|
109
|
+
.. code-block:: sh
|
|
110
|
+
|
|
111
|
+
pip3 install gshock-api
|
|
112
|
+
|
|
113
|
+
See `this project <https://github.com/izivkov/GShockTimeServer>`_ using this library to run a time server for G-Shock watches.
|
|
114
|
+
|
|
115
|
+
See also `this blog <https://digitalsober.wordpress.com/2025/05/05/g-shock-watch-integration-with-sxmo/>`_ for using the library in the `SXMO <https://sxmo.org/>`_ mobile environment.
|
|
116
|
+
|
|
117
|
+
Troubleshooting:
|
|
118
|
+
================
|
|
119
|
+
If your watch cannot connect, and the
|
|
120
|
+
**`--multi-watch`** parameter is not used, remove the **`config.ini`** file and try again.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
gshock_api
|
|
2
|
+
================
|
|
3
|
+
|
|
4
|
+
Announcement
|
|
5
|
+
============
|
|
6
|
+
|
|
7
|
+
The library now supports sending application-level notifications to watches that support it, namely:
|
|
8
|
+
|
|
9
|
+
* DW-H5600
|
|
10
|
+
* GBD-H2000
|
|
11
|
+
* GBD-200
|
|
12
|
+
* GBD-100
|
|
13
|
+
* GBD-800
|
|
14
|
+
* GBD-100BAR
|
|
15
|
+
* GBX-100
|
|
16
|
+
|
|
17
|
+
The new API is **send_app_notification** function.
|
|
18
|
+
See the `examples/api_test.py <https://github.com/izivkov/gshock_api/blob/main/src/examples/api_tests.py#L453-L456>`_ file for usage examples.
|
|
19
|
+
|
|
20
|
+
Only the **DW-H5600** watch has been tested. If you have any of the watches supporting notifications, please let me know your findings.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
Overview
|
|
24
|
+
========
|
|
25
|
+
This is a **Python API library** for G-Shock watches that support Bluetooth Low Energy (BLE) communication.
|
|
26
|
+
|
|
27
|
+
G(M)W-5600, G(M)W-5000, GA-B2100, GA-B001-1AER, GST-B500, GST-B200, MSG-B100,
|
|
28
|
+
G-B001, GBD-H1000 (Partial support), MRG-B5000, GCW-B5000, GG-B100, ABL-100WE,
|
|
29
|
+
Edifice ECB-30, ECB-10, ECB-20, most Edifice watches, most Protrek models.
|
|
30
|
+
|
|
31
|
+
It can perform the following tasks:
|
|
32
|
+
|
|
33
|
+
- Set watch's time
|
|
34
|
+
- Set Home Time (Home City)
|
|
35
|
+
- Set Alarms
|
|
36
|
+
- Set Reminders
|
|
37
|
+
- Set watch's settings.
|
|
38
|
+
- Get watch's name
|
|
39
|
+
- Get watch's battery level
|
|
40
|
+
- Get Watch's temperature
|
|
41
|
+
- Get/Set watch's Timer
|
|
42
|
+
- Send notifications to watch (supported models)
|
|
43
|
+
|
|
44
|
+
Dependencies
|
|
45
|
+
============
|
|
46
|
+
|
|
47
|
+
This project requires the following Python packages:
|
|
48
|
+
.. code-block:: sh
|
|
49
|
+
|
|
50
|
+
pytz
|
|
51
|
+
bleak
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
So you can install them using the following command:
|
|
55
|
+
.. code-block:: sh
|
|
56
|
+
|
|
57
|
+
pip3 install -r requirements.txt
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
To understand how to use the library, please refer to the **`src/examples`** folder.
|
|
61
|
+
|
|
62
|
+
Virtual Environment Setup
|
|
63
|
+
=========================
|
|
64
|
+
|
|
65
|
+
It is recommended that you create a virtual environment to run the tests:
|
|
66
|
+
|
|
67
|
+
1. Create a virtual environment:
|
|
68
|
+
|
|
69
|
+
.. code-block:: sh
|
|
70
|
+
|
|
71
|
+
# Create a virtual environment
|
|
72
|
+
python3 -m venv venv
|
|
73
|
+
|
|
74
|
+
# Activate it (Mac/Linux)
|
|
75
|
+
source venv/bin/activate
|
|
76
|
+
|
|
77
|
+
# Install dependencies
|
|
78
|
+
pip3 install -e .
|
|
79
|
+
|
|
80
|
+
2. Run the tests:
|
|
81
|
+
|
|
82
|
+
.. code-block:: sh
|
|
83
|
+
|
|
84
|
+
python3 src/examples/api_tests.py [--multi-watch]
|
|
85
|
+
|
|
86
|
+
The optional **`--multi-watch`** parameter forces the library to scan for watches every time it tries to connect to a watch. If not provided,
|
|
87
|
+
the library will try to connect to the last connected watch only. If you have multiple watches, you should use this parameter.
|
|
88
|
+
|
|
89
|
+
The optional **`--multi-watch`** parameter forces the library to scan for watches every time it tries to connect to a watch. If not provided,
|
|
90
|
+
the library will try to connect to the last connected watch only. If you have multiple watches, you should use this parameter.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Installing the library for your project:
|
|
94
|
+
========================================
|
|
95
|
+
|
|
96
|
+
.. code-block:: sh
|
|
97
|
+
|
|
98
|
+
pip3 install gshock-api
|
|
99
|
+
|
|
100
|
+
See `this project <https://github.com/izivkov/GShockTimeServer>`_ using this library to run a time server for G-Shock watches.
|
|
101
|
+
|
|
102
|
+
See also `this blog <https://digitalsober.wordpress.com/2025/05/05/g-shock-watch-integration-with-sxmo/>`_ for using the library in the `SXMO <https://sxmo.org/>`_ mobile environment.
|
|
103
|
+
|
|
104
|
+
Troubleshooting:
|
|
105
|
+
================
|
|
106
|
+
If your watch cannot connect, and the
|
|
107
|
+
**`--multi-watch`** parameter is not used, remove the **`config.ini`** file and try again.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gshock_api" # Change to your project name
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.4"
|
|
8
8
|
description = "Pythgon API for GShock Watches using BLE"
|
|
9
9
|
readme = "README.rst"
|
|
10
10
|
authors = [{ name = "Ivo Zivkov", email = "izivkov@gmail.com" }]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
class NotificationType(Enum):
|
|
5
|
+
GENERIC = 0
|
|
6
|
+
PHONE_CALL_URGENT = 1
|
|
7
|
+
PHONE_CALL = 2
|
|
8
|
+
EMAIL = 3
|
|
9
|
+
MESSAGE = 4
|
|
10
|
+
CALENDAR = 5
|
|
11
|
+
EMAIL_SMS = 6
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class AppNotification:
|
|
15
|
+
|
|
16
|
+
type: NotificationType
|
|
17
|
+
timestamp: str
|
|
18
|
+
app: str
|
|
19
|
+
title: str
|
|
20
|
+
text: str
|
|
21
|
+
short_text: str = ""
|
|
22
|
+
|
|
23
|
+
def __post_init__(self):
|
|
24
|
+
max_length_text = 193
|
|
25
|
+
max_length_short_text = 40
|
|
26
|
+
max_combined = 206 # Example combined max in bytes
|
|
27
|
+
|
|
28
|
+
# Truncate individual fields by UTF-8 byte length
|
|
29
|
+
text_bytes = self.text.encode("utf-8")
|
|
30
|
+
if len(text_bytes) > max_length_text:
|
|
31
|
+
self.text = text_bytes[:max_length_text].decode("utf-8", errors="ignore")
|
|
32
|
+
|
|
33
|
+
short_text_bytes = self.short_text.encode("utf-8")
|
|
34
|
+
if len(short_text_bytes) > max_length_short_text:
|
|
35
|
+
self.short_text = short_text_bytes[:max_length_short_text].decode("utf-8", errors="ignore")
|
|
36
|
+
|
|
37
|
+
# Now check combined UTF-8 byte length
|
|
38
|
+
text_bytes = self.text.encode("utf-8")
|
|
39
|
+
short_text_bytes = self.short_text.encode("utf-8")
|
|
40
|
+
total_len = len(text_bytes) + len(short_text_bytes)
|
|
41
|
+
if total_len > max_combined:
|
|
42
|
+
# Only shorten text, not short_text
|
|
43
|
+
allowed_text_bytes = max(0, max_combined - len(short_text_bytes))
|
|
44
|
+
self.text = text_bytes[:allowed_text_bytes].decode("utf-8", errors="ignore")
|
|
45
|
+
|
|
46
|
+
def to_dict(self) -> dict:
|
|
47
|
+
return {
|
|
48
|
+
"type": self.type,
|
|
49
|
+
"timestamp": self.timestamp,
|
|
50
|
+
"app": self.app,
|
|
51
|
+
"title": self.title,
|
|
52
|
+
"text": self.text,
|
|
53
|
+
"short_text": self.short_text,
|
|
54
|
+
}
|
|
55
|
+
|
|
@@ -6,6 +6,7 @@ class CasioConstants:
|
|
|
6
6
|
"26eb002c-b012-49a8-b1f8-394fb2032b0f"
|
|
7
7
|
)
|
|
8
8
|
CASIO_ALL_FEATURES_CHARACTERISTIC_UUID = "26eb002d-b012-49a8-b1f8-394fb2032b0f"
|
|
9
|
+
CASIO_NOTIFICATION_CHARACTERISTIC_UUID = "26eb0030-b012-49a8-b1f8-394fb2032b0f"
|
|
9
10
|
CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID = "26eb0023-b012-49a8-b1f8-394fb2032b0f"
|
|
10
11
|
CASIO_CONVOY_CHARACTERISTIC_UUID = "26eb0024-b012-49a8-b1f8-394fb2032b0f"
|
|
11
12
|
SERIAL_NUMBER_STRING = "00002a25-0000-1000-8000-00805f9b34fb"
|
|
@@ -5,26 +5,43 @@ from gshock_api.casio_constants import CasioConstants
|
|
|
5
5
|
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
|
+
from gshock_api.watch_info import watch_info
|
|
9
|
+
from gshock_api.device import Device
|
|
8
10
|
|
|
9
11
|
class Connection:
|
|
10
|
-
def __init__(self, device):
|
|
12
|
+
def __init__(self, device: Device):
|
|
11
13
|
self.handles_map = self.init_handles_map()
|
|
12
14
|
self.device = device
|
|
13
|
-
self.client = BleakClient(device)
|
|
15
|
+
self.client = BleakClient(device.address)
|
|
16
|
+
self.characteristics_map = {}
|
|
17
|
+
|
|
14
18
|
|
|
15
19
|
def notification_handler(
|
|
16
20
|
self, characteristic: BleakGATTCharacteristic, data: bytearray
|
|
17
21
|
):
|
|
18
22
|
message_dispatcher.MessageDispatcher.on_received(data)
|
|
19
23
|
|
|
24
|
+
async def init_characteristics_map(self):
|
|
25
|
+
"""
|
|
26
|
+
Prints all services and characteristics of the connected BLE device.
|
|
27
|
+
"""
|
|
28
|
+
services = await self.client.get_services()
|
|
29
|
+
for service in services:
|
|
30
|
+
for char in service.characteristics:
|
|
31
|
+
self.characteristics_map[char.uuid] = char.uuid # Store in map
|
|
32
|
+
|
|
20
33
|
async def connect(self):
|
|
21
34
|
try:
|
|
22
35
|
await self.client.connect()
|
|
36
|
+
await self.init_characteristics_map()
|
|
23
37
|
await self.client.start_notify(
|
|
24
38
|
CasioConstants.CASIO_ALL_FEATURES_CHARACTERISTIC_UUID,
|
|
25
39
|
self.notification_handler,
|
|
26
40
|
)
|
|
41
|
+
|
|
42
|
+
watch_info.set_name_and_model(self.device.name)
|
|
27
43
|
return True
|
|
44
|
+
|
|
28
45
|
except Exception as e:
|
|
29
46
|
logger.debug(f"Cannot connect: {e}")
|
|
30
47
|
return False
|
|
@@ -32,10 +49,27 @@ class Connection:
|
|
|
32
49
|
async def disconnect(self):
|
|
33
50
|
await self.client.disconnect()
|
|
34
51
|
|
|
52
|
+
def is_service_supported(self, handle):
|
|
53
|
+
uuid = self.handles_map.get(handle)
|
|
54
|
+
supported = (uuid not in self.characteristics_map)
|
|
55
|
+
print(f"write, service with handle {handle} is supported: {supported}")
|
|
56
|
+
return supported
|
|
57
|
+
|
|
35
58
|
async def write(self, handle, data):
|
|
36
59
|
try:
|
|
60
|
+
uuid = self.handles_map.get(handle)
|
|
61
|
+
if (uuid not in self.characteristics_map):
|
|
62
|
+
logger.error(
|
|
63
|
+
"write failed: handle {} not in characteristics map".format(handle)
|
|
64
|
+
)
|
|
65
|
+
if (handle == 13):
|
|
66
|
+
logger.error(
|
|
67
|
+
"Your watch does not suppot notifications..."
|
|
68
|
+
)
|
|
69
|
+
return
|
|
70
|
+
|
|
37
71
|
await self.client.write_gatt_char(
|
|
38
|
-
|
|
72
|
+
uuid, to_casio_cmd(data)
|
|
39
73
|
)
|
|
40
74
|
except Exception as e:
|
|
41
75
|
logger.debug("write failed with exception: {}".format(e))
|
|
@@ -54,6 +88,7 @@ class Connection:
|
|
|
54
88
|
0x0C
|
|
55
89
|
] = CasioConstants.CASIO_READ_REQUEST_FOR_ALL_FEATURES_CHARACTERISTIC_UUID
|
|
56
90
|
handles_map[0x0E] = CasioConstants.CASIO_ALL_FEATURES_CHARACTERISTIC_UUID
|
|
91
|
+
handles_map[0x0D] = CasioConstants.CASIO_NOTIFICATION_CHARACTERISTIC_UUID
|
|
57
92
|
handles_map[0x11] = CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID
|
|
58
93
|
handles_map[0x14] = CasioConstants.CASIO_CONVOY_CHARACTERISTIC_UUID
|
|
59
94
|
handles_map[0xFF] = CasioConstants.SERIAL_NUMBER_STRING
|
|
@@ -61,5 +96,4 @@ class Connection:
|
|
|
61
96
|
return handles_map
|
|
62
97
|
|
|
63
98
|
async def sendMessage(self, message):
|
|
64
|
-
# await callWriter(self, message)
|
|
65
99
|
await message_dispatcher.MessageDispatcher.send_to_watch(message)
|
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import logging
|
|
3
2
|
import json
|
|
4
3
|
import time
|
|
5
4
|
|
|
6
|
-
# from data_watcher import data_watcher
|
|
7
5
|
from gshock_api.iolib.dst_watch_state_io import DtsState
|
|
8
6
|
from gshock_api.iolib.button_pressed_io import WatchButton
|
|
7
|
+
from gshock_api.iolib.app_notification_io import AppNotificationIO
|
|
8
|
+
|
|
9
9
|
from gshock_api import message_dispatcher
|
|
10
10
|
from gshock_api.utils import (
|
|
11
|
-
to_ascii_string,
|
|
12
11
|
to_hex_string,
|
|
13
|
-
to_int_array,
|
|
14
12
|
to_compact_string,
|
|
15
|
-
clean_str,
|
|
16
13
|
)
|
|
17
14
|
from gshock_api.alarms import alarms_inst
|
|
18
15
|
from gshock_api.event import Event
|
|
19
16
|
from gshock_api.watch_info import watch_info
|
|
20
17
|
|
|
21
|
-
|
|
22
18
|
class GshockAPI:
|
|
23
19
|
"""
|
|
24
20
|
This class contains all the API functions. This should the the main interface to the
|
|
@@ -163,6 +159,9 @@ class GshockAPI:
|
|
|
163
159
|
for item in array_of_dst_watch_state[: watch_info.dstCount]:
|
|
164
160
|
await self.read_and_write(item["function"], item["state"])
|
|
165
161
|
|
|
162
|
+
async def send_app_notification (self, hex_str):
|
|
163
|
+
await self.connection.write(0xD, hex_str)
|
|
164
|
+
|
|
166
165
|
async def read_write_dst_for_world_cities(self):
|
|
167
166
|
array_of_get_dst_for_world_cities = [
|
|
168
167
|
{"function": self.get_dst_for_world_cities, "city_number": 0},
|
|
@@ -451,6 +450,8 @@ class GshockAPI:
|
|
|
451
450
|
result = await message_dispatcher.AppInfoIO.request(self.connection)
|
|
452
451
|
return await result
|
|
453
452
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
453
|
+
async def send_app_notification (self, notification):
|
|
454
|
+
encoded_buffer = AppNotificationIO.encode_notification_packet(notification)
|
|
455
|
+
encrypted_buffer = AppNotificationIO.xor_encode_buffer(encoded_buffer)
|
|
456
|
+
await self.connection.write(0xD, encrypted_buffer)
|
|
457
|
+
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
from gshock_api.app_notification import AppNotification, NotificationType
|
|
2
|
+
|
|
3
|
+
class AppNotificationIO:
|
|
4
|
+
def xor_decode_buffer(buffer: str, key: int = 255) -> bytes:
|
|
5
|
+
"""
|
|
6
|
+
Decodes a hex-encoded buffer using XOR with the given key.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
buffer (str): The hex-encoded buffer as a string.
|
|
10
|
+
key (int): The XOR key to decode the buffer.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
bytes: The XOR-decoded bytes.
|
|
14
|
+
"""
|
|
15
|
+
buffer_bytes = bytes.fromhex(buffer)
|
|
16
|
+
decoded_bytes = bytes(b ^ key for b in buffer_bytes)
|
|
17
|
+
return decoded_bytes
|
|
18
|
+
|
|
19
|
+
def xor_encode_buffer(decoded_bytes: bytes, key: int = 255) -> str:
|
|
20
|
+
"""
|
|
21
|
+
Encodes a buffer using XOR with the given key.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
decoded_bytes (bytes): The original decoded bytes to encode.
|
|
25
|
+
key (int): The XOR key to encode the buffer.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
str: The XOR-encoded buffer as a hex string.
|
|
29
|
+
"""
|
|
30
|
+
encoded_bytes = bytes(b ^ key for b in decoded_bytes)
|
|
31
|
+
return encoded_bytes.hex()
|
|
32
|
+
|
|
33
|
+
def read_length_prefixed_string(buf: bytes, offset: int) -> tuple[str, int]:
|
|
34
|
+
if offset + 2 > len(buf):
|
|
35
|
+
raise ValueError("Not enough data to read length prefix")
|
|
36
|
+
|
|
37
|
+
length = buf[offset]
|
|
38
|
+
if buf[offset + 1] != 0x00:
|
|
39
|
+
raise ValueError("Expected null second byte in length prefix")
|
|
40
|
+
|
|
41
|
+
start = offset + 2
|
|
42
|
+
end = start + length
|
|
43
|
+
if end > len(buf):
|
|
44
|
+
raise ValueError("String length exceeds buffer")
|
|
45
|
+
|
|
46
|
+
string = buf[start:end].decode("utf-8")
|
|
47
|
+
return string, end
|
|
48
|
+
|
|
49
|
+
def decode_notification_packet(buf: bytes) -> AppNotification:
|
|
50
|
+
"""
|
|
51
|
+
Decodes a G-Shock calendar notification buffer into an AppNotification object.
|
|
52
|
+
"""
|
|
53
|
+
offset = 0
|
|
54
|
+
|
|
55
|
+
if len(buf) < 6:
|
|
56
|
+
raise ValueError("Buffer too short")
|
|
57
|
+
|
|
58
|
+
# Read 6-byte header (skip or store if needed)
|
|
59
|
+
offset = 6
|
|
60
|
+
|
|
61
|
+
# Read 1-byte type
|
|
62
|
+
notif_type = buf[offset]
|
|
63
|
+
notif_type_enum = NotificationType(notif_type)
|
|
64
|
+
offset += 1
|
|
65
|
+
|
|
66
|
+
# Read 15-byte ASCII timestamp
|
|
67
|
+
timestamp_raw = buf[offset:offset + 15].decode("ascii")
|
|
68
|
+
offset += 15
|
|
69
|
+
|
|
70
|
+
# Read app name (length-prefixed UTF-8 string)
|
|
71
|
+
app, offset = AppNotificationIO.read_length_prefixed_string(buf, offset)
|
|
72
|
+
|
|
73
|
+
# Read title (length-prefixed UTF-8 string)
|
|
74
|
+
title, offset = AppNotificationIO.read_length_prefixed_string(buf, offset)
|
|
75
|
+
|
|
76
|
+
# Read empty string (length-prefixed UTF-8 string, skip)
|
|
77
|
+
_, offset = AppNotificationIO.read_length_prefixed_string(buf, offset)
|
|
78
|
+
|
|
79
|
+
# Read text (length-prefixed UTF-8 string)
|
|
80
|
+
text, offset = AppNotificationIO.read_length_prefixed_string(buf, offset)
|
|
81
|
+
|
|
82
|
+
# Construct and return AppNotification object
|
|
83
|
+
notification = AppNotification(
|
|
84
|
+
type = notif_type_enum,
|
|
85
|
+
timestamp=timestamp_raw,
|
|
86
|
+
app=app,
|
|
87
|
+
title=title,
|
|
88
|
+
text=text
|
|
89
|
+
)
|
|
90
|
+
return notification
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def write_length_prefixed_string(text: str) -> bytes:
|
|
94
|
+
"""
|
|
95
|
+
Encodes a string as a length-prefixed UTF-8 byte sequence for G-Shock BLE notifications.
|
|
96
|
+
|
|
97
|
+
Structure:
|
|
98
|
+
----------
|
|
99
|
+
[Length: 1 byte][0x00][UTF-8 bytes of string]
|
|
100
|
+
|
|
101
|
+
- Length: Number of bytes in the UTF-8 encoded string (max 255).
|
|
102
|
+
- 0x00: Separator byte (always 0x00).
|
|
103
|
+
- UTF-8 bytes: The actual string data.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
text (str): The string to encode.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
bytes: The encoded length-prefixed UTF-8 byte sequence.
|
|
110
|
+
|
|
111
|
+
Raises:
|
|
112
|
+
ValueError: If the encoded string is longer than 255 bytes.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
encoded = text.encode("utf-8")
|
|
116
|
+
if len(encoded) > 255:
|
|
117
|
+
raise ValueError("Encoded string too long")
|
|
118
|
+
return bytes([len(encoded), 0x00]) + encoded
|
|
119
|
+
|
|
120
|
+
def encode_notification_packet(data: AppNotification) -> bytes:
|
|
121
|
+
"""
|
|
122
|
+
Encodes an AppNotification object into a binary buffer for G-Shock BLE notifications.
|
|
123
|
+
|
|
124
|
+
Message Structure:
|
|
125
|
+
------------------
|
|
126
|
+
The encoded message has the following structure (all fields are concatenated in order):
|
|
127
|
+
|
|
128
|
+
[Header: 6 bytes] +
|
|
129
|
+
[Type: 1 byte] +
|
|
130
|
+
[Timestamp: 15 bytes, ASCII] +
|
|
131
|
+
[App Name: length-prefixed UTF-8 string] +
|
|
132
|
+
[Title: length-prefixed UTF-8 string] +
|
|
133
|
+
[Short Text: length-prefixed UTF-8 string] +
|
|
134
|
+
[Text: length-prefixed UTF-8 string]
|
|
135
|
+
|
|
136
|
+
- Header: Fixed 6-byte value (hex "000000000001").
|
|
137
|
+
- Type: 1 byte, value from NotificationType enum.
|
|
138
|
+
- Timestamp: 15 ASCII characters.
|
|
139
|
+
- App Name, Title, Short Text, Text: Each is encoded as [length (1 byte)][0x00][UTF-8 bytes].
|
|
140
|
+
- The length is the number of bytes in the UTF-8 encoded string (max 255).
|
|
141
|
+
- The second byte is always 0x00 as a separator.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
data (AppNotification): The notification to encode.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
bytes: The encoded binary buffer.
|
|
148
|
+
|
|
149
|
+
Raises:
|
|
150
|
+
TypeError: If data is not an AppNotification instance.
|
|
151
|
+
ValueError: If any string field is too long to encode.
|
|
152
|
+
|
|
153
|
+
Example:
|
|
154
|
+
>>> notif = AppNotification(type=NotificationType.CALENDAR, timestamp="20250516T233000", app="Calendar", title="Meeting", text="Discuss project")
|
|
155
|
+
>>> buf = AppNotificationIO.encode_notification_packet(notif)
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
if not isinstance(data, AppNotification):
|
|
159
|
+
raise TypeError("data must be an AppNotification instance")
|
|
160
|
+
|
|
161
|
+
header = "000000000001"
|
|
162
|
+
result = bytearray()
|
|
163
|
+
result += bytes.fromhex(header)
|
|
164
|
+
result.append(data.type.value)
|
|
165
|
+
result += data.timestamp.encode("ascii")
|
|
166
|
+
result += AppNotificationIO.write_length_prefixed_string(data.app)
|
|
167
|
+
result += AppNotificationIO.write_length_prefixed_string(data.title)
|
|
168
|
+
result += AppNotificationIO.write_length_prefixed_string(data.short_text) # Empty string for the separator
|
|
169
|
+
result += AppNotificationIO.write_length_prefixed_string(data.text)
|
|
170
|
+
return bytes(result)
|
|
@@ -4,12 +4,12 @@ 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
|
-
|
|
7
|
+
from gshock_api.device import Device
|
|
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):
|
|
12
|
+
async def scan(self, device_address=None) -> Device:
|
|
13
13
|
scanner = BleakScanner()
|
|
14
14
|
logger.info("Scanning for devices...")
|
|
15
15
|
|
|
@@ -22,10 +22,9 @@ class Scanner:
|
|
|
22
22
|
logger.info(f"device: {device}")
|
|
23
23
|
if device is None:
|
|
24
24
|
continue
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
# watch_info.
|
|
28
|
-
watch_info.set_name_and_model(device.name)
|
|
25
|
+
|
|
26
|
+
# This is now set after connection in Connection class
|
|
27
|
+
# watch_info.set_name_and_model(device.name)
|
|
29
28
|
|
|
30
29
|
conf.put("device.address", device.address)
|
|
31
30
|
conf.put("device.name", device.name)
|
|
@@ -35,8 +34,8 @@ class Scanner:
|
|
|
35
34
|
device = await scanner.find_device_by_address(
|
|
36
35
|
device_address, sys.float_info.max
|
|
37
36
|
)
|
|
37
|
+
watch_info.set_name_and_model(device.name)
|
|
38
38
|
|
|
39
|
-
return device
|
|
40
|
-
|
|
39
|
+
return Device(device.name, device.address)
|
|
41
40
|
|
|
42
41
|
scanner = Scanner()
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gshock_api
|
|
3
|
+
Version: 2.0.4
|
|
4
|
+
Summary: Pythgon API for GShock Watches using BLE
|
|
5
|
+
Home-page: https://github.com/pyscaffold/pyscaffold/
|
|
6
|
+
Author: Ivo Zivkov
|
|
7
|
+
Author-email: Ivo Zivkov <izivkov@gmail.com>
|
|
8
|
+
Platform: any
|
|
9
|
+
Description-Content-Type: text/x-rst
|
|
10
|
+
License-File: LICENSE.txt
|
|
11
|
+
Requires-Dist: requests
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
gshock_api
|
|
15
|
+
================
|
|
16
|
+
|
|
17
|
+
Announcement
|
|
18
|
+
============
|
|
19
|
+
|
|
20
|
+
The library now supports sending application-level notifications to watches that support it, namely:
|
|
21
|
+
|
|
22
|
+
* DW-H5600
|
|
23
|
+
* GBD-H2000
|
|
24
|
+
* GBD-200
|
|
25
|
+
* GBD-100
|
|
26
|
+
* GBD-800
|
|
27
|
+
* GBD-100BAR
|
|
28
|
+
* GBX-100
|
|
29
|
+
|
|
30
|
+
The new API is **send_app_notification** function.
|
|
31
|
+
See the `examples/api_test.py <https://github.com/izivkov/gshock_api/blob/main/src/examples/api_tests.py#L453-L456>`_ file for usage examples.
|
|
32
|
+
|
|
33
|
+
Only the **DW-H5600** watch has been tested. If you have any of the watches supporting notifications, please let me know your findings.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Overview
|
|
37
|
+
========
|
|
38
|
+
This is a **Python API library** for G-Shock watches that support Bluetooth Low Energy (BLE) communication.
|
|
39
|
+
|
|
40
|
+
G(M)W-5600, G(M)W-5000, GA-B2100, GA-B001-1AER, GST-B500, GST-B200, MSG-B100,
|
|
41
|
+
G-B001, GBD-H1000 (Partial support), MRG-B5000, GCW-B5000, GG-B100, ABL-100WE,
|
|
42
|
+
Edifice ECB-30, ECB-10, ECB-20, most Edifice watches, most Protrek models.
|
|
43
|
+
|
|
44
|
+
It can perform the following tasks:
|
|
45
|
+
|
|
46
|
+
- Set watch's time
|
|
47
|
+
- Set Home Time (Home City)
|
|
48
|
+
- Set Alarms
|
|
49
|
+
- Set Reminders
|
|
50
|
+
- Set watch's settings.
|
|
51
|
+
- Get watch's name
|
|
52
|
+
- Get watch's battery level
|
|
53
|
+
- Get Watch's temperature
|
|
54
|
+
- Get/Set watch's Timer
|
|
55
|
+
- Send notifications to watch (supported models)
|
|
56
|
+
|
|
57
|
+
Dependencies
|
|
58
|
+
============
|
|
59
|
+
|
|
60
|
+
This project requires the following Python packages:
|
|
61
|
+
.. code-block:: sh
|
|
62
|
+
|
|
63
|
+
pytz
|
|
64
|
+
bleak
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
So you can install them using the following command:
|
|
68
|
+
.. code-block:: sh
|
|
69
|
+
|
|
70
|
+
pip3 install -r requirements.txt
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
To understand how to use the library, please refer to the **`src/examples`** folder.
|
|
74
|
+
|
|
75
|
+
Virtual Environment Setup
|
|
76
|
+
=========================
|
|
77
|
+
|
|
78
|
+
It is recommended that you create a virtual environment to run the tests:
|
|
79
|
+
|
|
80
|
+
1. Create a virtual environment:
|
|
81
|
+
|
|
82
|
+
.. code-block:: sh
|
|
83
|
+
|
|
84
|
+
# Create a virtual environment
|
|
85
|
+
python3 -m venv venv
|
|
86
|
+
|
|
87
|
+
# Activate it (Mac/Linux)
|
|
88
|
+
source venv/bin/activate
|
|
89
|
+
|
|
90
|
+
# Install dependencies
|
|
91
|
+
pip3 install -e .
|
|
92
|
+
|
|
93
|
+
2. Run the tests:
|
|
94
|
+
|
|
95
|
+
.. code-block:: sh
|
|
96
|
+
|
|
97
|
+
python3 src/examples/api_tests.py [--multi-watch]
|
|
98
|
+
|
|
99
|
+
The optional **`--multi-watch`** parameter forces the library to scan for watches every time it tries to connect to a watch. If not provided,
|
|
100
|
+
the library will try to connect to the last connected watch only. If you have multiple watches, you should use this parameter.
|
|
101
|
+
|
|
102
|
+
The optional **`--multi-watch`** parameter forces the library to scan for watches every time it tries to connect to a watch. If not provided,
|
|
103
|
+
the library will try to connect to the last connected watch only. If you have multiple watches, you should use this parameter.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
Installing the library for your project:
|
|
107
|
+
========================================
|
|
108
|
+
|
|
109
|
+
.. code-block:: sh
|
|
110
|
+
|
|
111
|
+
pip3 install gshock-api
|
|
112
|
+
|
|
113
|
+
See `this project <https://github.com/izivkov/GShockTimeServer>`_ using this library to run a time server for G-Shock watches.
|
|
114
|
+
|
|
115
|
+
See also `this blog <https://digitalsober.wordpress.com/2025/05/05/g-shock-watch-integration-with-sxmo/>`_ for using the library in the `SXMO <https://sxmo.org/>`_ mobile environment.
|
|
116
|
+
|
|
117
|
+
Troubleshooting:
|
|
118
|
+
================
|
|
119
|
+
If your watch cannot connect, and the
|
|
120
|
+
**`--multi-watch`** parameter is not used, remove the **`config.ini`** file and try again.
|
|
@@ -5,11 +5,12 @@ setup.cfg
|
|
|
5
5
|
setup.py
|
|
6
6
|
src/gshock_api/__init__.py
|
|
7
7
|
src/gshock_api/alarms.py
|
|
8
|
+
src/gshock_api/app_notification.py
|
|
8
9
|
src/gshock_api/cancelable_result.py
|
|
9
10
|
src/gshock_api/casio_constants.py
|
|
10
11
|
src/gshock_api/configurator.py
|
|
11
12
|
src/gshock_api/connection.py
|
|
12
|
-
src/gshock_api/
|
|
13
|
+
src/gshock_api/device.py
|
|
13
14
|
src/gshock_api/event.py
|
|
14
15
|
src/gshock_api/gshock_api.py
|
|
15
16
|
src/gshock_api/logger.py
|
|
@@ -28,6 +29,7 @@ src/gshock_api.egg-info/top_level.txt
|
|
|
28
29
|
src/gshock_api/iolib/__init__.py
|
|
29
30
|
src/gshock_api/iolib/alarms_io.py
|
|
30
31
|
src/gshock_api/iolib/app_info_io.py
|
|
32
|
+
src/gshock_api/iolib/app_notification_io.py
|
|
31
33
|
src/gshock_api/iolib/button_pressed_io.py
|
|
32
34
|
src/gshock_api/iolib/dst_for_world_cities_io.py
|
|
33
35
|
src/gshock_api/iolib/dst_watch_state_io.py
|
gshock_api-2.0.2/PKG-INFO
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: gshock_api
|
|
3
|
-
Version: 2.0.2
|
|
4
|
-
Summary: Pythgon API for GShock Watches using BLE
|
|
5
|
-
Home-page: https://github.com/pyscaffold/pyscaffold/
|
|
6
|
-
Author: Ivo Zivkov
|
|
7
|
-
Author-email: Ivo Zivkov <izivkov@gmail.com>
|
|
8
|
-
Platform: any
|
|
9
|
-
Description-Content-Type: text/x-rst
|
|
10
|
-
License-File: LICENSE.txt
|
|
11
|
-
Requires-Dist: requests
|
|
12
|
-
Dynamic: license-file
|
|
13
|
-
|
|
14
|
-
GShockTimeServer
|
|
15
|
-
================
|
|
16
|
-
|
|
17
|
-
Overview
|
|
18
|
-
========
|
|
19
|
-
GShockTimeServer allows you to set the correct time on your Casio G-Shock watches, including:
|
|
20
|
-
|
|
21
|
-
- `B5600 <https://amzn.to/3Mt68Qb>`__
|
|
22
|
-
- `B5000 <https://amzn.to/4194M13>`__
|
|
23
|
-
- `B2100 <https://amzn.to/3MUDCGY>`__
|
|
24
|
-
|
|
25
|
-
Additionally, this repository provides an API for developing applications for these watches.
|
|
26
|
-
While still a work in progress, you can refer to the ``api_tests.py`` file for usage examples.
|
|
27
|
-
|
|
28
|
-
Usage
|
|
29
|
-
=====
|
|
30
|
-
This app can run on any device with Python and Bluetooth capabilities—from a desktop to a Raspberry Pi Zero.
|
|
31
|
-
It has been tested on Linux but should also work on Windows.
|
|
32
|
-
|
|
33
|
-
.. image:: images/pizero.jpg
|
|
34
|
-
:alt: Pi Zero Running the Server
|
|
35
|
-
:align: center
|
|
36
|
-
|
|
37
|
-
Setting the Time
|
|
38
|
-
----------------
|
|
39
|
-
1. Ensure the app is running on your device.
|
|
40
|
-
2. Short-press the **lower-right** button on your G-Shock watch to connect.
|
|
41
|
-
3. Once connected, the app will automatically set the correct time on your watch.
|
|
42
|
-
4. If **AUTO TIME ADJUSTMENT** is enabled, the watch will sync up to **four times daily**.
|
|
43
|
-
|
|
44
|
-
Dependencies
|
|
45
|
-
============
|
|
46
|
-
|
|
47
|
-
This project requires the following Python packages:
|
|
48
|
-
```
|
|
49
|
-
pytz
|
|
50
|
-
bleak
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
So you can install them using the following command:
|
|
54
|
-
```
|
|
55
|
-
pip3 install -r requirements.txt
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Virtual Environment Setup
|
|
59
|
-
=========================
|
|
60
|
-
To run the server in a virtual environment:
|
|
61
|
-
|
|
62
|
-
1. Create a virtual environment:
|
|
63
|
-
|
|
64
|
-
.. code-block:: sh
|
|
65
|
-
|
|
66
|
-
# Create a virtual environment
|
|
67
|
-
python3 -m venv myenv
|
|
68
|
-
|
|
69
|
-
# Activate it (Mac/Linux)
|
|
70
|
-
source myenv/bin/activate
|
|
71
|
-
|
|
72
|
-
# Install dependencies
|
|
73
|
-
pip3 install -e .
|
|
74
|
-
|
|
75
|
-
2. Run the tests:
|
|
76
|
-
|
|
77
|
-
.. code-block:: sh
|
|
78
|
-
|
|
79
|
-
python3 src/examples/api_tests.py [--multi-watch]
|
|
80
|
-
|
|
81
|
-
3. Run the server:
|
|
82
|
-
|
|
83
|
-
.. code-block:: sh
|
|
84
|
-
|
|
85
|
-
python3 src/examples/gshock_server.py [--multi-watch]
|
|
86
|
-
|
|
87
|
-
The optional **`--multi-watch`** parameter allows you to connect if you have multiple watches.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Installing the library for your project:
|
|
91
|
-
========================================
|
|
92
|
-
|
|
93
|
-
```
|
|
94
|
-
pip3 install gshock-api
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Troubleshooting:
|
|
98
|
-
================
|
|
99
|
-
If your watch cannot connect, and the
|
|
100
|
-
**`--multi-watch`** parameter is not used, remove the **`config.ini`** file and try again.
|
gshock_api-2.0.2/README.rst
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
GShockTimeServer
|
|
2
|
-
================
|
|
3
|
-
|
|
4
|
-
Overview
|
|
5
|
-
========
|
|
6
|
-
GShockTimeServer allows you to set the correct time on your Casio G-Shock watches, including:
|
|
7
|
-
|
|
8
|
-
- `B5600 <https://amzn.to/3Mt68Qb>`__
|
|
9
|
-
- `B5000 <https://amzn.to/4194M13>`__
|
|
10
|
-
- `B2100 <https://amzn.to/3MUDCGY>`__
|
|
11
|
-
|
|
12
|
-
Additionally, this repository provides an API for developing applications for these watches.
|
|
13
|
-
While still a work in progress, you can refer to the ``api_tests.py`` file for usage examples.
|
|
14
|
-
|
|
15
|
-
Usage
|
|
16
|
-
=====
|
|
17
|
-
This app can run on any device with Python and Bluetooth capabilities—from a desktop to a Raspberry Pi Zero.
|
|
18
|
-
It has been tested on Linux but should also work on Windows.
|
|
19
|
-
|
|
20
|
-
.. image:: images/pizero.jpg
|
|
21
|
-
:alt: Pi Zero Running the Server
|
|
22
|
-
:align: center
|
|
23
|
-
|
|
24
|
-
Setting the Time
|
|
25
|
-
----------------
|
|
26
|
-
1. Ensure the app is running on your device.
|
|
27
|
-
2. Short-press the **lower-right** button on your G-Shock watch to connect.
|
|
28
|
-
3. Once connected, the app will automatically set the correct time on your watch.
|
|
29
|
-
4. If **AUTO TIME ADJUSTMENT** is enabled, the watch will sync up to **four times daily**.
|
|
30
|
-
|
|
31
|
-
Dependencies
|
|
32
|
-
============
|
|
33
|
-
|
|
34
|
-
This project requires the following Python packages:
|
|
35
|
-
```
|
|
36
|
-
pytz
|
|
37
|
-
bleak
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
So you can install them using the following command:
|
|
41
|
-
```
|
|
42
|
-
pip3 install -r requirements.txt
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Virtual Environment Setup
|
|
46
|
-
=========================
|
|
47
|
-
To run the server in a virtual environment:
|
|
48
|
-
|
|
49
|
-
1. Create a virtual environment:
|
|
50
|
-
|
|
51
|
-
.. code-block:: sh
|
|
52
|
-
|
|
53
|
-
# Create a virtual environment
|
|
54
|
-
python3 -m venv myenv
|
|
55
|
-
|
|
56
|
-
# Activate it (Mac/Linux)
|
|
57
|
-
source myenv/bin/activate
|
|
58
|
-
|
|
59
|
-
# Install dependencies
|
|
60
|
-
pip3 install -e .
|
|
61
|
-
|
|
62
|
-
2. Run the tests:
|
|
63
|
-
|
|
64
|
-
.. code-block:: sh
|
|
65
|
-
|
|
66
|
-
python3 src/examples/api_tests.py [--multi-watch]
|
|
67
|
-
|
|
68
|
-
3. Run the server:
|
|
69
|
-
|
|
70
|
-
.. code-block:: sh
|
|
71
|
-
|
|
72
|
-
python3 src/examples/gshock_server.py [--multi-watch]
|
|
73
|
-
|
|
74
|
-
The optional **`--multi-watch`** parameter allows you to connect if you have multiple watches.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Installing the library for your project:
|
|
78
|
-
========================================
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
pip3 install gshock-api
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Troubleshooting:
|
|
85
|
-
================
|
|
86
|
-
If your watch cannot connect, and the
|
|
87
|
-
**`--multi-watch`** parameter is not used, remove the **`config.ini`** file and try again.
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: gshock_api
|
|
3
|
-
Version: 2.0.2
|
|
4
|
-
Summary: Pythgon API for GShock Watches using BLE
|
|
5
|
-
Home-page: https://github.com/pyscaffold/pyscaffold/
|
|
6
|
-
Author: Ivo Zivkov
|
|
7
|
-
Author-email: Ivo Zivkov <izivkov@gmail.com>
|
|
8
|
-
Platform: any
|
|
9
|
-
Description-Content-Type: text/x-rst
|
|
10
|
-
License-File: LICENSE.txt
|
|
11
|
-
Requires-Dist: requests
|
|
12
|
-
Dynamic: license-file
|
|
13
|
-
|
|
14
|
-
GShockTimeServer
|
|
15
|
-
================
|
|
16
|
-
|
|
17
|
-
Overview
|
|
18
|
-
========
|
|
19
|
-
GShockTimeServer allows you to set the correct time on your Casio G-Shock watches, including:
|
|
20
|
-
|
|
21
|
-
- `B5600 <https://amzn.to/3Mt68Qb>`__
|
|
22
|
-
- `B5000 <https://amzn.to/4194M13>`__
|
|
23
|
-
- `B2100 <https://amzn.to/3MUDCGY>`__
|
|
24
|
-
|
|
25
|
-
Additionally, this repository provides an API for developing applications for these watches.
|
|
26
|
-
While still a work in progress, you can refer to the ``api_tests.py`` file for usage examples.
|
|
27
|
-
|
|
28
|
-
Usage
|
|
29
|
-
=====
|
|
30
|
-
This app can run on any device with Python and Bluetooth capabilities—from a desktop to a Raspberry Pi Zero.
|
|
31
|
-
It has been tested on Linux but should also work on Windows.
|
|
32
|
-
|
|
33
|
-
.. image:: images/pizero.jpg
|
|
34
|
-
:alt: Pi Zero Running the Server
|
|
35
|
-
:align: center
|
|
36
|
-
|
|
37
|
-
Setting the Time
|
|
38
|
-
----------------
|
|
39
|
-
1. Ensure the app is running on your device.
|
|
40
|
-
2. Short-press the **lower-right** button on your G-Shock watch to connect.
|
|
41
|
-
3. Once connected, the app will automatically set the correct time on your watch.
|
|
42
|
-
4. If **AUTO TIME ADJUSTMENT** is enabled, the watch will sync up to **four times daily**.
|
|
43
|
-
|
|
44
|
-
Dependencies
|
|
45
|
-
============
|
|
46
|
-
|
|
47
|
-
This project requires the following Python packages:
|
|
48
|
-
```
|
|
49
|
-
pytz
|
|
50
|
-
bleak
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
So you can install them using the following command:
|
|
54
|
-
```
|
|
55
|
-
pip3 install -r requirements.txt
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Virtual Environment Setup
|
|
59
|
-
=========================
|
|
60
|
-
To run the server in a virtual environment:
|
|
61
|
-
|
|
62
|
-
1. Create a virtual environment:
|
|
63
|
-
|
|
64
|
-
.. code-block:: sh
|
|
65
|
-
|
|
66
|
-
# Create a virtual environment
|
|
67
|
-
python3 -m venv myenv
|
|
68
|
-
|
|
69
|
-
# Activate it (Mac/Linux)
|
|
70
|
-
source myenv/bin/activate
|
|
71
|
-
|
|
72
|
-
# Install dependencies
|
|
73
|
-
pip3 install -e .
|
|
74
|
-
|
|
75
|
-
2. Run the tests:
|
|
76
|
-
|
|
77
|
-
.. code-block:: sh
|
|
78
|
-
|
|
79
|
-
python3 src/examples/api_tests.py [--multi-watch]
|
|
80
|
-
|
|
81
|
-
3. Run the server:
|
|
82
|
-
|
|
83
|
-
.. code-block:: sh
|
|
84
|
-
|
|
85
|
-
python3 src/examples/gshock_server.py [--multi-watch]
|
|
86
|
-
|
|
87
|
-
The optional **`--multi-watch`** parameter allows you to connect if you have multiple watches.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Installing the library for your project:
|
|
91
|
-
========================================
|
|
92
|
-
|
|
93
|
-
```
|
|
94
|
-
pip3 install gshock-api
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Troubleshooting:
|
|
98
|
-
================
|
|
99
|
-
If your watch cannot connect, and the
|
|
100
|
-
**`--multi-watch`** parameter is not used, remove the **`config.ini`** file and try again.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|