我正在加入到UPnP设备(WeMo运动传感器)上的事件中。我首先向设备发送HTTP订阅请求,设备应该开始向我发送指定地址的事件通知。那部分工作正常(除了我收到太多通知;即使状态没有改变,但是对于不同的线程它是一个不同的问题)
如果我在一个单独的python进程上运行keepListening函数,一切正常。但是,当我将该函数作为线程运行时,它不起作用;
import socket
import requests
from threading import Thread
def keepListening(): #running this function on a separate process works
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.settimeout(600)
sock.bind(('192.168.10.231',1234))
sock.listen(5)
while 1:
notification = ''
try:
conn, addr = sock.accept()
conn.setblocking(1)
notification= conn.recv(1024)
conn.sendall(r'''HTTP/1.1 200 OK
Content-Type: text/plain
''')
except Exception as er:
print er
print notification
x = Thread(target=keepListening)
x.start()
message = {
'CALLBACK': '<http://192.168.10.231:1234>',
'NT': 'upnp:event',
'TIMEOUT': 'Second-600',
'HOST': '192.168.10.159:49153'}
k = requests.request('SUBSCRIBE','http://192.168.10.159:49153/upnp/event/basicevent1',headers=message)
print k
# keep doing other important works
每个事件通知必须以200 OK回复回复,否则设备不会发送进一步通知;事实上我学到了很多东西。我怀疑的可能是愚蠢的,当在线程中运行时,与单独的进程相反,回复消息不会及时发送,因此设备不会发送任何消息。更多通知。 值得一提的是,即使我在线程中运行该功能,我确实订阅后的初始通知(设备必须根据UPnP协议强制在订阅后立即发送初始通知),但我没有得到进一步的通知(表明我的200 OK回复没有正确通过;我确实在wireshark中看到了它)
关于在线程中运行函数(而不是单独的进程)可能有什么不同的想法让它失败?
谢谢。
答案 0 :(得分:0)
我认为,发生的事情是,在线程变为活动状态并开始侦听接口之前,您最终会发送订阅请求。因此设备无法连接到插座。
答案 1 :(得分:0)
前几天我有一个wemo运动传感器,开关和RaspberryPi,所以我开始修补。
该脚本订阅了wemo-device的“binaryState”-event。 每次事件发生时,它都会打印出一个“警报”(你可以在那里做其他事情)。 250秒后,它会续订订阅。
要根据需要调整脚本,您必须更改IP:
localIp:您的计算机
remoteIp:wemo传感器或开关的ip
我是python的新手(3天前开始),所以脚本可能需要一些修改,但它可以工作。
import socket
import threading
import requests
host = ''
port = 1234
localIp = '<http://192.168.1.32:1234>' # local IP of your computer
remoteIp = '192.168.1.47:49153' # the ip of the wemo device
global uid # stores the uuid of the event
uid = ''
class client(threading.Thread):
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
self.data = ""
def run(self):
global uid
while True:
self.data = self.data + self.conn.recv(1024)
if self.data.endswith(u"\r\n"):
print self.data # data from the wemo device
uidPos = self.data.find("uuid")
if uidPos != -1: # data contains the uuid of the event
uid = self.data[uidPos+5:uidPos+41]
if "<BinaryState>1</BinaryState>" in self.data:
print "ALERT ------------------------------------------Alert"
# NOTIFICATION !
if "/e:propertyset" in self.data:
self.conn.sendall('HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n\r\n')
return
self.data = ""
def send_msg(self,msg):
self.conn.send(msg)
def close(self):
self.conn.close()
class connectionThread(threading.Thread):
def __init__(self, host, port):
super(connectionThread, self).__init__()
try:
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.bind((host,port))
self.s.listen(5)
except socket.error:
print 'Failed to create socket'
sys.exit()
self.clients = []
def run(self):
while True:
print uid
conn, address = self.s.accept()
c = client(conn)
c.start()
print '[+] Client connected: {0}'.format(address[0])
def main():
get_conns = connectionThread(host, port)
get_conns.start()
print get_conns.clients
while True:
try:
response = raw_input()
except KeyboardInterrupt:
sys.exit()
def setCalback():
global uid
threading.Timer(250.0, setCalback).start()
if uid == "": # no uuid set so we subscribe to the event
eventSubscribe()
else: # uuid is set, so we renew the subsciption
eventRefresh()
def eventSubscribe(): # subscribe to the wemo-event
message = {
'CALLBACK': localIp,
'NT': 'upnp:event',
'TIMEOUT': 'Second-300',
'HOST': remoteIp}
k = requests.request('SUBSCRIBE', "http://"+remoteIp+'/upnp/event/basicevent1',headers=message)
print k
def eventRefresh() # refresh the subscription with the known uuid
myuid = "uuid:"+uid
message = {
'SID': myuid,
'TIMEOUT': 'Second-300',
'HOST': remoteIp }
k = requests.request('SUBSCRIBE',"http://"+remoteIp+'/upnp/event/basicevent1',headers=message)
print k
if __name__ == '__main__':
threading.Timer(2.0, setCalback).start() # wait 2 sec. then subscribe to the service
main()