forked from petrklus/lifx-simple
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlifx_webservice.py
executable file
·125 lines (90 loc) · 3.2 KB
/
lifx_webservice.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
#!/usr/bin/env python
import bottle as btl
import threading
import socket
import time
import tools
import receive
import Queue
# seqnum generator
def get_seq_num_fun():
# workaround for nested function scoping for python 2.7
state = {
"seq_lock" : threading.Lock(),
"seq_num" : 0
}
def _get_seq_num():
with state["seq_lock"]:
state["seq_num"] = (state["seq_num"] + 1) % 256
return state["seq_num"]
return _get_seq_num
@btl.route('/<bulb_ip>/<hue>/<sat>/<bri>/<kel>')
def set_colour(**kwargs):
print kwargs["bulb_ip"]
for key in ["hue", "sat", "bri", "kel"]:
kwargs[key] = float(kwargs[key])
print key, kwargs[key]
command_q.put(kwargs)
return "ENQUEUED"
@btl.route('/hello')
def hello():
return "HELLO"
RETRIES = 10
DELAY = 0.05
UDP_PORT = 56700
UDP_IP = "0.0.0.0" # where to listen
NO_OF_SENDERS = 3
MAX_ACK_AGE = 1 # maximum ACK age
ACKS = [0.0 for _ in xrange(256)]
def packet_listener():
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
try:
response = receive.process_incoming_data(data, addr)
print response
if response["packet_id"] == 45:
ACKS[response["seqnum"]] = time.time()
except Exception, e:
print "Unable to process packet from: {}, (error {})".format(addr, e)
def command_sender():
while True:
try:
kwargs = command_q.get()
seq_num = get_seq_num()
print "seq num", seq_num
ack = False
for i in range(RETRIES):
with send_lock:
sock.sendto(
tools.gen_packet(kwargs["hue"], kwargs["sat"], kwargs["bri"], kwargs["kel"], seq_num),
(kwargs["bulb_ip"], UDP_PORT))
# wait...
time.sleep(DELAY*(i*1.5+1))
# do we have ACK?
if time.time() - ACKS[seq_num] < MAX_ACK_AGE:
ack = True
print "ACK confirmed, no more retries needed"
break
if not ack:
print "Unable to ACK packet with seq num", seq_num
except Exception, e:
print "Unable to process command: {}".format(e)
if __name__ == "__main__":
# testing http://192.168.2.212:8888/192.168.2.222/120/100/100/3500
# UDP functionality
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
get_seq_num = get_seq_num_fun() # initialise sequence number
# listen for lifx packets
sock.bind((UDP_IP, UDP_PORT))
# coordination objects - lock and command queue
send_lock = threading.Lock()
command_q = Queue.Queue(maxsize=5)
t = threading.Thread(target=packet_listener)
t.daemon = True
t.start()
# spawn command sending thread
for _ in xrange(NO_OF_SENDERS):
t = threading.Thread(target=command_sender)
t.daemon = True
t.start()
btl.run(host='0.0.0.0', port=8888)