-
Notifications
You must be signed in to change notification settings - Fork 4
/
weixind.py
381 lines (299 loc) · 11.2 KB
/
weixind.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: weixind.py
# Author: Liang Cha<ckmx945@gmail.com>
# CreateDate: 2014-05-15
import os
import web
import time
import hashlib
import urllib
import urllib2
import thread
import re
##from lxml import etree
from xml.etree import ElementTree
from weixin import WeiXinClient
from lyric import LyricClient
from weixin import getUserByName
#from yeelink import YeeLinkClient
_TOKEN = '352202198801050537'
_URLS = (
'/*', 'WeixinServer',
)
def _check_hash(data):
signature = data.signature
## print 'signature:',signature
timestamp = data.timestamp
nonce = data.nonce
list = [_TOKEN, timestamp, nonce]
list.sort()
sha1 = hashlib.sha1()
map(sha1.update, list)
hashcode = sha1.hexdigest()
## print 'hashcode:',hashcode
if hashcode == signature:
return True
return False
def _get_user_info(wc):
req = wc.user.get._get(next_openid = None)
count = req.count
total = req.total
data = req.data
id_list = data.openid
while count < total:
if next_openid in data.openid:
break
req = wc.user.get._get(next_openid = None)
count += req.count
data = req.data
next_openid = req.next_openid
id_list.extend(data.openid)
info_list = []
for open_id in id_list:
req = wc.user.info._get(openid=open_id, lang='zh_CN')
name ='%s' %(req.nickname)
place = '%s,%s,%s' %(req.country, req.province, req.city)
sex = '%s' %(u'男') if (req.sex == 1) else u'女'
info_list.append({'name':name, 'place':place, 'sex':sex})
return info_list
def _arduino_client(data):
import select
import socket
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.setblocking(False)
inputs = [c]
c.connect(('192.168.1.20', 6666))
c.sendall(data)
readable, writeable, exceptional = select.select(inputs, [], [], 2)
if not readable:
return '{"errno": -1, "msg":"wait response timeout."}'
else:
return c.recv(1024)
def _take_snapshot(addr, port, client):
url = 'http://%s:%d/?action=snapshot' %(addr, port)
req = urllib2.Request(url)
try:
resp = urllib2.urlopen(req, timeout = 2)
except urllib2.HTTPError, e:
print e
return None
return client.media.upload.file(type='image', pic=resp)
def _do_event_subscribe(server, fromUser, toUser, doc):
words = u'''当前为搜歌词模式, 请输入 【歌曲名】
或者 【歌曲名】 【歌手】 搜索指定的歌词 ! '''
return server._reply_text(fromUser, toUser, words)
def _do_event_unsubscribe(server, fromUser, toUser, doc):
return server._reply_text(fromUser, toUser, u'bye!')
def _do_event_SCAN(server, fromUser, toUser, doc):
pass
def _do_event_LOCATION(server, fromUser, toUser, doc):
pass
def _do_event_CLICK(server, fromUser, toUser, doc):
key = doc.find('EventKey').text
try:
return _weixin_click_table[key](server, fromUser, toUser, doc)
except KeyError, e:
print '_do_event_CLICK: %s' %e
return server._reply_text(fromUser, toUser, u'Unknow click: '+key)
_weixin_event_table = {
'subscribe' : _do_event_subscribe,
'unsbscribe' : _do_event_unsubscribe,
'SCAN' : _do_event_SCAN,
'LOCATION' : _do_event_LOCATION,
'CLICK' : _do_event_CLICK,
}
def _do_click_V1001_USER_LIST(server, fromUser, toUser, doc):
reply_msg = ''
user_list = _get_user_info(server.client)
for user in user_list:
reply_msg += '%s|%s|%s\n' %(user['name'], user['place'], user['sex'])
return server._reply_text(fromUser, toUser, reply_msg)
def _do_click_V1001_YELLOW_CHICK(server, fromUser, toUser, doc):
pass
def _do_click_V1001_MODE_GECI(server, fromUser, toUser, doc):
user = getUserByName(fromUser)
user.mode == 'geci'
reply_msg = '用户当前为搜歌词模式'
return server._reply_text(fromUser, toUser, reply_msg)
def _do_click_V1001_LED_ON(server, fromUser, toUser, doc):
data = '{"name":"digitalWrite", "para":{"pin":7, "value":1}}'
buf = _arduino_client(data)
errno = eval(buf)['errno']
reply_msg = None
if errno == 0:
reply_msg = '成功点亮'
elif errno == -1:
reply_msg = eval[buf]['msg']
else:
reply_msg = '点亮失败'
return server._reply_text(fromUser, toUser, reply_msg)
def _do_click_V1001_LED_OFF(server, fromUser, toUser, doc):
data = '{"name":"digitalWrite", "para":{"pin":7, "value":0}}'
buf = _arduino_client(data)
errno = eval(buf)['errno']
reply_msg = None
if errno == 0:
reply_msg = '成功关闭'
elif errno == -1:
reply_msg = eval[buf]['msg']
else:
reply_msg = '关闭失败'
return server._reply_text(fromUser, toUser, reply_msg)
def _dew_point_fast(t, h):
import math
a = 17.27
b = 237.7
temp = (a * t) / (b + t) + math.log(h / 100);
td = (b * temp) / (a - temp);
return td
def _do_click_SNAPSHOT(server, fromUser, toUser, doc):
data = _take_snapshot('192.168.1.10', 24567, server.client)
if data == None:
return server._reply_text(fromUser, toUser, 'snapshot fail.')
return server._reply_image(fromUser, toUser, data.media_id)
def _do_click_V1001_TEMPERATURES(server, fromUser, toUser, doc):
data = '{"name":"environment", "para":{"pin":2}}'
buf = _arduino_client(data)
data = eval(buf)
errno = data['errno']
reply_msg = None
if errno == 0:
t = data['resp']['t']
h = data['resp']['h']
td = _dew_point_fast(t, h)
reply_msg = "室内温度: %.2f℃\n室内湿度: %.2f\n室内露点: %.2f" %(t, h, td)
else:
reply_msg = data['msg']
return server._reply_text(fromUser, toUser, reply_msg)
_weixin_click_table = {
'V1001_USER_LIST' : _do_click_V1001_USER_LIST,
'V1001_YELLOW_CHICK' : _do_click_V1001_YELLOW_CHICK,
'V1001_LED_ON' : _do_click_V1001_LED_ON,
'V1001_LED_OFF' : _do_click_V1001_LED_OFF,
'V1001_TEMPERATURES' : _do_click_V1001_TEMPERATURES,
'V1001_MODE_GECI' : _do_click_V1001_MODE_GECI,
'V1001_SNAPSHOT' : _do_click_SNAPSHOT
}
class WeixinServer:
app_root = os.path.dirname(__file__)
templates_root = os.path.join(app_root, 'templates')
render = web.template.render(templates_root)
wc_client = WeiXinClient('wxe3da4718bc1a9a18', \
'2238eb7e0a13748039ec31f0309bbf68', fc = True, path = '.')
lyric_client = LyricClient()
def __init__(self):
self.wc_client.request_access_token()
def deal_with_text_impl(self, fromUser, toUser, content):
user = getUserByName(fromUser)
if user.mode == 'geci':
return self.lyric_client.deal_with_text_impl(fromUser, toUser, content, self.wc_client)
else:
pass
return '当前不处于歌词模式'
def _recv_text(self, fromUser, toUser, doc):
content = doc.find('Content').text
reply_msg = self.deal_with_text_impl(fromUser, toUser, content)
return self._reply_text(fromUser, toUser, reply_msg)
def _recv_event(self, fromUser, toUser, doc):
event = doc.find('Event').text
try:
return _weixin_event_table[event](self, fromUser, toUser, doc)
except KeyError, e:
print '_recv_event: %s' %e
return self._reply_text(fromUser, toUser, u'Unknow event: '+event)
def _recv_image(self, fromUser, toUser, doc):
url = doc.find('PicUrl').text
req = urllib2.Request(url)
try:
resp = urllib2.urlopen(req, timeout = 2)
# print self.yee.image.upload('10296', '16660', fd = resp)
except urllib2.HTTPError, e:
print e
return self._reply_text(fromUser, toUser, u'upload fail.')
view = 'http://www.yeelink.net/devices/10296'
return self._reply_text(fromUser, toUser, u'upload to:'+view)
def _recv_voice(self, fromUser, toUser, doc):
cmd = doc.find('Recognition').text;
if cmd is None:
return self._reply_text(fromUser, toUser, u'no Recognition, no command');
if cmd == u'开灯':
return _do_click_V1001_LED_ON(self, fromUser, toUser, doc)
elif cmd == u'关灯':
return _do_click_V1001_LED_OFF(self, fromUser, toUser, doc)
elif cmd == u'温度':
return _do_click_V1001_TEMPERATURES(self, fromUser, toUser, doc)
else:
return self._reply_text(fromUser, toUser, u'Unknow command: ' + cmd);
def _recv_video(self, fromUser, toUser, doc):
pass
def _recv_location(self, fromUser, toUser, doc):
pass
def _recv_link(self, fromUser, toUser, doc):
pass
def _reply_text(self, toUser, fromUser, msg):
return self.render.reply_text(toUser, fromUser, int(time.time()), msg)
def _reply_image(self, toUser, fromUser, media_id):
return self.render.reply_image(toUser, fromUser, int(time.time()), media_id)
def GET(self):
data = web.input()
## print 'get data:',data
if _check_hash(data):
return data.echostr
def POST(self):
str_xml = web.data()
## print 'str_xml:',str_xml
doc = ElementTree.fromstring(str_xml)
msgType = doc.find('MsgType').text
fromUser = doc.find('FromUserName').text
toUser = doc.find('ToUserName').text
if msgType == 'text':
return self._recv_text(fromUser, toUser, doc)
if msgType == 'event':
return self._recv_event(fromUser, toUser, doc)
if msgType == 'image':
return self._recv_image(fromUser, toUser, doc)
if msgType == 'voice':
return self._recv_voice(fromUser, toUser, doc)
if msgType == 'video':
return self._recv_video(fromUser, toUser, doc)
if msgType == 'location':
return self._recv_location(fromUser, toUser, doc)
if msgType == 'link':
return self._recv_link(fromUser, toUser, doc)
else:
return self._reply_text(fromUser, toUser, u'Unknow msg:' + msgType)
web.config.debug = False
application = web.application(_URLS, globals()).wsgifunc()
if __name__ == "__main__":
#import wsgi
from bottle import run
run(app=application, host='0.0.0.0', port=80)
## weixin_s = weixinserver()
## str_xml = ''' <xml>
## <ToUserName><![CDATA[toUser]]></ToUserName>
## <FromUserName><![CDATA[fromUser]]></FromUserName>
## <CreateTime>1348831860</CreateTime>
## <MsgType><![CDATA[text]]></MsgType>
## <Content><![CDATA[ 龙的传人 ]]></Content>
## <MsgId>1234567890123456</MsgId>
## </xml>'''
## doc = ElementTree.fromstring(str_xml)
## weixin_s._recv_text("wgb", "me", doc)
##
## import time
## time.sleep(3)
## content = raw_input("input:")
##
## str_xml = ''' <xml>
## <ToUserName><![CDATA[toUser]]></ToUserName>
## <FromUserName><![CDATA[fromUser]]></FromUserName>
## <CreateTime>1348831860</CreateTime>
## <MsgType><![CDATA[text]]></MsgType>
## <Content><![CDATA[ 1 ]]></Content>
## <MsgId>1234567890123456</MsgId>
## </xml>'''
## doc = ElementTree.fromstring(str_xml)
## weixin_s._recv_text("wgb", "me", doc)
##
## content = raw_input("input:")