2
2
# Copyright (c) 2015-2019 Volodymyr Shymanskyy.
3
3
# See the file LICENSE for copying permission.
4
4
5
- __version__ = '0.2.5 '
5
+ __version__ = '0.2.6 '
6
6
7
- try :
8
- import usocket as socket
9
- import utime as time
10
- import ustruct as struct
11
- import uselect as select
12
- from micropython import const
13
-
14
- ticks_ms = time .ticks_ms
15
- sleep_ms = time .sleep_ms
16
-
17
- IOError = OSError
18
- except ImportError :
19
- import socket
20
- import time
21
- import struct
22
- import select
23
-
24
- const = lambda x : x
25
- ticks_ms = lambda : int (time .time () * 1000 )
26
- sleep_ms = lambda x : time .sleep (x // 1000 )
7
+ import socket
8
+ import ssl
9
+ import struct
10
+ import time
27
11
28
12
LOGO = """
29
13
___ __ __
@@ -37,6 +21,14 @@ def stub_log(*args):
37
21
pass
38
22
39
23
24
+ def ticks_ms ():
25
+ return int (time .time () * 1000 )
26
+
27
+
28
+ def sleep_ms (ms ):
29
+ time .sleep (ms // 1000 )
30
+
31
+
40
32
class BlynkError (Exception ):
41
33
pass
42
34
@@ -48,32 +40,32 @@ def __init__(self, server, port):
48
40
49
41
50
42
class Protocol (object ):
51
- MSG_RSP = const ( 0 )
52
- MSG_LOGIN = const ( 2 )
53
- MSG_PING = const ( 6 )
54
- MSG_TWEET = const ( 12 )
55
- MSG_EMAIL = const ( 13 )
56
- MSG_NOTIFY = const ( 14 )
57
- MSG_BRIDGE = const ( 15 )
58
- MSG_HW_SYNC = const ( 16 )
59
- MSG_INTERNAL = const ( 17 )
60
- MSG_PROPERTY = const ( 19 )
61
- MSG_HW = const ( 20 )
62
- MSG_REDIRECT = const ( 41 )
63
- MSG_HEAD_LEN = const ( 5 )
64
-
65
- STATUS_INVALID_TOKEN = const ( 9 )
66
- STATUS_NO_DATA = const ( 17 )
67
- STATUS_OK = const ( 200 )
68
- VPIN_MAX_NUM = const ( 32 )
69
-
70
- _msg_id = 1
43
+ MSG_RSP = 0
44
+ MSG_LOGIN = 2
45
+ MSG_PING = 6
46
+ MSG_TWEET = 12
47
+ MSG_EMAIL = 13
48
+ MSG_NOTIFY = 14
49
+ MSG_BRIDGE = 15
50
+ MSG_HW_SYNC = 16
51
+ MSG_INTERNAL = 17
52
+ MSG_PROPERTY = 19
53
+ MSG_HW = 20
54
+ MSG_REDIRECT = 41
55
+ MSG_HEAD_LEN = 5
56
+
57
+ STATUS_INVALID_TOKEN = 9
58
+ STATUS_NO_DATA = 17
59
+ STATUS_OK = 200
60
+ VPIN_MAX_NUM = 32
61
+
62
+ _msg_id = 0
71
63
72
64
def _get_msg_id (self , ** kwargs ):
73
65
if 'msg_id' in kwargs :
74
66
return kwargs ['msg_id' ]
75
67
self ._msg_id += 1
76
- return self ._msg_id if self ._msg_id <= 0xFFFF else 1
68
+ return self ._msg_id if self ._msg_id <= 0xFFFF else 0
77
69
78
70
def _pack_msg (self , msg_type , * args , ** kwargs ):
79
71
data = ('\0 ' .join ([str (curr_arg ) for curr_arg in args ])).encode ('utf-8' )
@@ -134,40 +126,35 @@ def internal_msg(self, *args):
134
126
135
127
136
128
class Connection (Protocol ):
137
- SOCK_MAX_TIMEOUT = const ( 5 )
129
+ SOCK_MAX_TIMEOUT = 5
138
130
SOCK_TIMEOUT = 0.05
139
- EAGAIN = const (11 )
140
- ETIMEDOUT = const (60 )
141
- RETRIES_TX_DELAY = const (2 )
142
- RETRIES_TX_MAX_NUM = const (3 )
143
- RECONNECT_SLEEP = const (1 )
144
- TASK_PERIOD_RES = const (50 )
145
- DISCONNECTED = const (0 )
146
- CONNECTING = const (1 )
147
- AUTHENTICATING = const (2 )
148
- AUTHENTICATED = const (3 )
131
+ SOCK_SSL_TIMEOUT = 1
132
+ EAGAIN = 11
133
+ ETIMEDOUT = 60
134
+ RETRIES_TX_DELAY = 2
135
+ RETRIES_TX_MAX_NUM = 3
136
+ RECONNECT_SLEEP = 1
137
+ TASK_PERIOD_RES = 50
138
+ DISCONNECTED = 0
139
+ CONNECTING = 1
140
+ AUTHENTICATING = 2
141
+ AUTHENTICATED = 3
149
142
150
143
_state = None
151
144
_socket = None
152
145
_last_rcv_time = 0
153
146
_last_ping_time = 0
154
147
_last_send_time = 0
155
148
156
- def __init__ (self , token , server = 'blynk-cloud.com' , port = 80 , heartbeat = 10 , rcv_buffer = 1024 , log = stub_log ):
149
+ def __init__ (self , token , server = 'blynk-cloud.com' , port = 80 , ssl_cert = None , heartbeat = 10 , rcv_buffer = 1024 ,
150
+ log = stub_log ):
157
151
self .token = token
158
152
self .server = server
159
153
self .port = port
160
154
self .heartbeat = heartbeat
161
155
self .rcv_buffer = rcv_buffer
162
156
self .log = log
163
-
164
- def _set_socket_timeout (self , timeout ):
165
- if getattr (self ._socket , 'settimeout' , None ):
166
- self ._socket .settimeout (timeout )
167
- else :
168
- p = select .poll ()
169
- p .register (self ._socket )
170
- p .poll (int (timeout * 1000 ))
157
+ self .ssl_cert = ssl_cert
171
158
172
159
def send (self , data ):
173
160
retries = self .RETRIES_TX_MAX_NUM
@@ -182,13 +169,13 @@ def send(self, data):
182
169
def receive (self , length , timeout ):
183
170
d_buff = b''
184
171
try :
185
- self ._set_socket_timeout (timeout )
172
+ self ._socket . settimeout (timeout )
186
173
d_buff += self ._socket .recv (length )
187
174
if len (d_buff ) >= length :
188
175
d_buff = d_buff [:length ]
189
176
return d_buff
190
177
except (IOError , OSError ) as err :
191
- if str ( err ) == 'timed out' :
178
+ if 'timed out' in str ( err ) :
192
179
return b''
193
180
if str (self .EAGAIN ) in str (err ) or str (self .ETIMEDOUT ) in str (err ):
194
181
return b''
@@ -213,7 +200,16 @@ def _get_socket(self):
213
200
self ._state = self .CONNECTING
214
201
self ._socket = socket .socket ()
215
202
self ._socket .connect (socket .getaddrinfo (self .server , self .port )[0 ][4 ])
216
- self ._set_socket_timeout (self .SOCK_TIMEOUT )
203
+ self ._socket .settimeout (self .SOCK_TIMEOUT )
204
+ if self .ssl_cert :
205
+ # system’s default CA certificates case
206
+ if self .ssl_cert == "default" :
207
+ self .ssl_cert = None
208
+ self .log ('Using SSL socket...' )
209
+ ssl_context = ssl .create_default_context (cafile = self .ssl_cert )
210
+ ssl_context .verify_mode = ssl .CERT_REQUIRED
211
+ self ._socket .settimeout (self .SOCK_SSL_TIMEOUT )
212
+ self ._socket = ssl_context .wrap_socket (sock = self ._socket , server_hostname = self .server )
217
213
self .log ('Connected to blynk server' )
218
214
except Exception as g_exc :
219
215
raise BlynkError ('Connection with the Blynk server failed: {}' .format (g_exc ))
@@ -250,7 +246,7 @@ def connected(self):
250
246
251
247
252
248
class Blynk (Connection ):
253
- _CONNECT_TIMEOUT = const ( 30 ) # 30sec
249
+ _CONNECT_TIMEOUT = 30 # 30sec
254
250
_VPIN_WILDCARD = '*'
255
251
_VPIN_READ = 'read v'
256
252
_VPIN_WRITE = 'write v'
@@ -300,6 +296,7 @@ def disconnect(self, err_msg=None):
300
296
self ._state = self .DISCONNECTED
301
297
if err_msg :
302
298
self .log ('[ERROR]: {}\n Connection closed' .format (err_msg ))
299
+ self ._msg_id = 0
303
300
time .sleep (self .RECONNECT_SLEEP )
304
301
305
302
def virtual_write (self , v_pin , * val ):
@@ -351,11 +348,11 @@ def process(self, msg_type, msg_id, msg_len, msg_args):
351
348
elif msg_type == self .MSG_PING :
352
349
self .send (self .response_msg (self .STATUS_OK , msg_id = msg_id ))
353
350
elif msg_type in (self .MSG_HW , self .MSG_BRIDGE , self .MSG_INTERNAL ):
354
- if msg_type == self .MSG_INTERNAL and len (msg_args ) >= const ( 2 ) :
351
+ if msg_type == self .MSG_INTERNAL and len (msg_args ) >= 2 :
355
352
self .call_handler ("{}{}" .format (self ._INTERNAL , msg_args [0 ]), msg_args [1 :])
356
- elif len (msg_args ) >= const ( 3 ) and msg_args [0 ] == 'vw' :
353
+ elif len (msg_args ) >= 3 and msg_args [0 ] == 'vw' :
357
354
self .call_handler ("{}{}" .format (self ._VPIN_WRITE , msg_args [1 ]), int (msg_args [1 ]), msg_args [2 :])
358
- elif len (msg_args ) == const ( 2 ) and msg_args [0 ] == 'vr' :
355
+ elif len (msg_args ) == 2 and msg_args [0 ] == 'vr' :
359
356
self .call_handler ("{}{}" .format (self ._VPIN_READ , msg_args [1 ]), int (msg_args [1 ]))
360
357
361
358
def read_response (self , timeout = 0.5 ):
0 commit comments