28
28
* Author(s): Dan Halbert for Adafruit Industries
29
29
30
30
"""
31
+ import struct
32
+ import time
33
+
31
34
from bleio import Peripheral , UUID
32
35
from .advertising import SolicitationAdvertisement
33
36
@@ -40,20 +43,26 @@ class CurrentTimeClient:
40
43
41
44
Example::
42
45
43
- from adafruit_ble.current_time_client import SolicitationAdvertisement
46
+ from adafruit_ble.current_time_client import CurrentTimeClient
44
47
45
48
cts_client = CurrentTimeClient()
46
49
cts_client.start_advertising()
47
50
while not cts_client.connected:
48
51
pass
49
- print(cts_client.time)
52
+ cts_client.discover()
53
+ cts_client.pair()
54
+ print(cts_client.current_local_time)
50
55
"""
51
56
52
57
CTS_UUID = UUID (0x1805 )
58
+ CURRENT_TIME_UUID = UUID (0x2A2B )
59
+ LOCAL_TIME_INFORMATION_UUID = UUID (0x2A0F )
53
60
54
61
def __init__ (self , name = "CTSClient" , tx_power = 0 ):
55
62
self ._periph = Peripheral ()
56
63
self ._advertisement = SolicitationAdvertisement (name , (self .CTS_UUID ,), tx_power = tx_power )
64
+ self ._current_time_char = self ._local_time_char = None
65
+
57
66
58
67
def start_advertising (self ):
59
68
"""Start advertising to solicit a central that supports Current Time Service."""
@@ -69,11 +78,66 @@ def connected(self):
69
78
"""True if a central connected to this peripheral."""
70
79
return self ._periph .connected
71
80
81
+ def disconnect (self ):
82
+ """Disconnect from central."""
83
+ self ._periph .disconnect ()
84
+
85
+ def _check_connected (self ):
86
+ if not self .connected :
87
+ raise OSError ("Not connected" )
88
+
72
89
def pair (self ):
73
90
"""Pair with the connected central."""
74
- pass
91
+ self ._check_connected ()
92
+ self ._periph .pair ()
93
+
94
+ def discover (self ):
95
+ """Discover service information."""
96
+ self ._check_connected ()
97
+ self ._periph .discover_remote_services ((self .CTS_UUID ,))
98
+ services = self ._periph .remote_services
99
+ if not services :
100
+ raise OSError ("Unable to discover service" )
101
+ for characteristic in services [0 ].characteristics :
102
+ if characteristic .uuid == self .CURRENT_TIME_UUID :
103
+ self ._current_time_char = characteristic
104
+ elif characteristic .uuid == self .LOCAL_TIME_INFORMATION_UUID :
105
+ self ._local_time_char = characteristic
106
+ if not self ._current_time_char or not self ._local_time_char :
107
+ raise OSError ("Remote service missing needed characteristic" )
108
+
109
+ @property
110
+ def current_time (self ):
111
+ """Get a tuple describing the current time from the server:
112
+ (year, month, day, hour, minute, second, weekday, subsecond, adjust_reason)
113
+ """
114
+ self ._check_connected ()
115
+ if self ._current_time_char :
116
+ # year, month, day, hour, minute, second, weekday, subsecond, adjust_reason
117
+ values = struct .unpack ('<HBBBBBBBB' , self ._current_time_char .value )
118
+ return values
119
+ else :
120
+ raise OSError ("Characteristic not discovered" )
121
+
122
+
123
+ @property
124
+ def local_time_information (self ):
125
+ """Get a tuple of location information from the server:
126
+ (timezone, dst_offset)
127
+ """
128
+ self ._check_connected ()
129
+ if self ._local_time_char :
130
+ # timezone, dst_offset
131
+ values = struct .unpack ('<bB' , self ._local_time_char .value )
132
+ return values
133
+ else :
134
+ raise OSError ("Characteristic not discovered" )
75
135
76
136
@property
77
- def time (self ):
78
- """Get the current time from the server."""
79
- return None
137
+ def struct_time (self ):
138
+ """Return the current time as a `time.struct_time` Day of year and whether DST is in effect
139
+ is not available from Current Time Service, so these are set to -1.
140
+ """
141
+ _ , month , day , hour , minute , second , weekday , _ , _ = self .current_time
142
+ # Bluetooth weekdays count from 1. struct_time counts from 0.
143
+ return time .struct_time ((month , day , hour , minute , second , weekday - 1 , - 1 ))
0 commit comments