1
1
# Copyright (c) 2015-2019 Volodymyr Shymanskyy. See the file LICENSE for copying permission.
2
2
3
- _VERSION = "0.2.1 "
3
+ __version__ = "1.0.0 "
4
4
5
5
import struct
6
6
import time
15
15
gettime = lambda : int (time .time () * 1000 )
16
16
17
17
def dummy (* args ):
18
- pass
18
+ pass
19
19
20
20
MSG_RSP = const (0 )
21
21
MSG_LOGIN = const (2 )
@@ -46,64 +46,52 @@ def dummy(*args):
46
46
/ _ )/ /_ _____ / /__
47
47
/ _ / / // / _ \\ / '_/
48
48
/____/_/\\ _, /_//_/_/\\ _\\
49
- /___/ for Python v""" + _VERSION + " (" + sys .platform + ")\n " )
49
+ /___/ for Python v""" + __version__ + " (" + sys .platform + ")\n " )
50
50
51
- class BlynkProtocol :
52
- def __init__ (self , auth , heartbeat = 10 , buffin = 1024 , log = None ):
53
- self .callbacks = {}
51
+ class EventEmitter :
52
+ def __init__ (self ):
53
+ self ._cbks = {}
54
+
55
+ def on (self , evt , f = None ):
56
+ if f :
57
+ self ._cbks [evt ] = f
58
+ else :
59
+ def D (f ):
60
+ self ._cbks [evt ] = f
61
+ return f
62
+ return D
63
+
64
+ def emit (self , evt , * a , ** kv ):
65
+ if evt in self ._cbks :
66
+ self ._cbks [evt ](* a , ** kv )
67
+
68
+
69
+ class BlynkProtocol (EventEmitter ):
70
+ def __init__ (self , auth , tmpl_id = None , fw_ver = None , heartbeat = 50 , buffin = 1024 , log = None ):
71
+ EventEmitter .__init__ (self )
54
72
self .heartbeat = heartbeat * 1000
55
73
self .buffin = buffin
56
74
self .log = log or dummy
57
75
self .auth = auth
76
+ self .tmpl_id = tmpl_id
77
+ self .fw_ver = fw_ver
58
78
self .state = DISCONNECTED
59
79
self .connect ()
60
80
61
- # These are mainly for backward-compatibility you can use "blynk.on()" instead
62
- def ON (blynk , evt ):
63
- return blynk .on (evt )
64
- def VIRTUAL_READ (blynk , pin ):
65
- return blynk .on ("readV" + str (pin ))
66
- def VIRTUAL_WRITE (blynk , pin ):
67
- return blynk .on ("V" + str (pin ))
68
-
69
- def on (blynk , evt , func = None ):
70
- if func :
71
- blynk .callbacks [evt ] = func
72
- return
73
-
74
- class Decorator :
75
- def __init__ (self , func ):
76
- self .func = func
77
- blynk .callbacks [evt ] = func
78
- def __call__ (self ):
79
- return self .func ()
80
- return Decorator
81
-
82
- def emit (self , evt , * a , ** kv ):
83
- self .log ("Event:" , evt , "->" , * a )
84
- if evt in self .callbacks :
85
- self .callbacks [evt ](* a , ** kv )
86
-
87
81
def virtual_write (self , pin , * val ):
88
82
self ._send (MSG_HW , 'vw' , pin , * val )
89
83
84
+ def send_internal (self , pin , * val ):
85
+ self ._send (MSG_INTERNAL , pin , * val )
86
+
90
87
def set_property (self , pin , prop , * val ):
91
88
self ._send (MSG_PROPERTY , pin , prop , * val )
92
89
93
90
def sync_virtual (self , * pins ):
94
91
self ._send (MSG_HW_SYNC , 'vr' , * pins )
95
92
96
- def notify (self , msg ):
97
- self ._send (MSG_NOTIFY , msg )
98
-
99
- def tweet (self , msg ):
100
- self ._send (MSG_TWEET , msg )
101
-
102
- def log_event (self , event , descr = None ):
103
- if descr == None :
104
- self ._send (MSG_EVENT_LOG , event )
105
- else :
106
- self ._send (MSG_EVENT_LOG , event , descr )
93
+ def log_event (self , * val ):
94
+ self ._send (MSG_EVENT_LOG , * val )
107
95
108
96
def _send (self , cmd , * args , ** kwargs ):
109
97
if 'id' in kwargs :
@@ -170,13 +158,20 @@ def process(self, data=None):
170
158
if dlen == STA_SUCCESS :
171
159
self .state = CONNECTED
172
160
dt = now - self .lastSend
173
- self ._send (MSG_INTERNAL , 'ver' , _VERSION , 'h-beat' , self .heartbeat // 1000 , 'buff-in' , self .buffin , 'dev' , 'python' )
161
+ info = ['ver' , __version__ , 'h-beat' , self .heartbeat // 1000 , 'buff-in' , self .buffin , 'dev' , 'python' ]
162
+ if self .tmpl_id :
163
+ info .extend (['tmpl' , self .tmpl_id ])
164
+ info .extend (['fw-type' , self .tmpl_id ])
165
+ if self .fw_ver :
166
+ info .extend (['fw' , self .fw_ver ])
167
+ self ._send (MSG_INTERNAL , * info )
174
168
try :
175
169
self .emit ('connected' , ping = dt )
176
170
except TypeError :
177
171
self .emit ('connected' )
178
172
else :
179
173
if dlen == STA_INVALID_TOKEN :
174
+ self .emit ("invalid_auth" )
180
175
print ("Invalid auth token" )
181
176
return self .disconnect ()
182
177
else :
@@ -203,7 +198,9 @@ def process(self, data=None):
203
198
self .emit ("readV" + args [1 ])
204
199
self .emit ("readV*" , args [1 ])
205
200
elif cmd == MSG_INTERNAL :
206
- self .emit ("int_" + args [1 ], args [2 :])
201
+ self .emit ("internal:" + args [0 ], args [1 :])
202
+ elif cmd == MSG_REDIRECT :
203
+ self .emit ("redirect" , args [0 ], int (args [1 ]))
207
204
else :
208
205
print ("Unexpected command: " , cmd )
209
206
return self .disconnect ()
@@ -212,21 +209,42 @@ def process(self, data=None):
212
209
213
210
class Blynk (BlynkProtocol ):
214
211
def __init__ (self , auth , ** kwargs ):
215
- self .server = kwargs .pop ('server' , 'blynk-cloud.com' )
216
- self .port = kwargs .pop ('port' , 80 )
212
+ self .insecure = kwargs .pop ('insecure' , False )
213
+ self .server = kwargs .pop ('server' , 'blynk.cloud' )
214
+ self .port = kwargs .pop ('port' , 80 if self .insecure else 443 )
217
215
BlynkProtocol .__init__ (self , auth , ** kwargs )
216
+ self .on ('redirect' , self .redirect )
217
+
218
+ def redirect (self , server , port ):
219
+ self .server = server
220
+ self .port = port
221
+ self .disconnect ()
222
+ self .connect ()
218
223
219
224
def connect (self ):
225
+ print ('Connecting to %s:%d...' % (self .server , self .port ))
220
226
try :
221
- self .conn = socket .socket ()
222
- self .conn .connect (socket .getaddrinfo (self .server , self .port )[0 ][4 ])
227
+ s = socket .socket ()
228
+ s .connect (socket .getaddrinfo (self .server , self .port )[0 ][4 ])
229
+ s .setsockopt (socket .IPPROTO_TCP , socket .TCP_NODELAY , 1 )
230
+ if self .insecure :
231
+ self .conn = s
232
+ else :
233
+ try :
234
+ import ssl
235
+ ssl_context = ssl .create_default_context ()
236
+ self .conn = ssl_context .wrap_socket (sock = s , server_hostname = self .server )
237
+ except ImportError :
238
+ import ussl
239
+ self .conn = ussl .wrap_socket (s , server_hostname = self .server )
240
+
223
241
try :
224
242
self .conn .settimeout (eval ('0.05' ))
225
243
except :
226
244
self .conn .settimeout (0 )
227
245
BlynkProtocol .connect (self )
228
246
except :
229
- raise ValueError ('Connection with the Blynk server %s:%d failed' % (self .server , self .port ))
247
+ raise Exception ('Connection with the Blynk server %s:%d failed' % (self .server , self .port ))
230
248
231
249
def _write (self , data ):
232
250
#print('<', data.hex())
0 commit comments