This repository was archived by the owner on Mar 5, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
366 lines (292 loc) · 9.56 KB
/
Copy pathmain.py
File metadata and controls
366 lines (292 loc) · 9.56 KB
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
import machine
import time
import rp2
from lib.tplink_lightbulb import TPLinkLightbulb
import network
import socket
import json
### CONFIG ###
## Web server
server_web = True
server_web_port = 80
## Lightbulb
ip_address = 'IP_ADDRESS_OF_LIGHTBULB_HERE'
## Access Point (station)
ssid = 'SSID_HERE'
key = 'KEY_HERE'
### END ###
### LED ###
led = machine.Pin('LED', machine.Pin.OUT)
'''
LED status codes:
-- Light switch
- 2, false = light on
- 3, false = light off
-- Light status
- 2, true = light on
- 3, true = light off
-- Brightness
- 4, false = 50%
- 5, false = 100%
- 6, false = light must turned on to set brightness
-- Reconnect to network
- 1, false = initiating connection
- 2, false = end of connection setup
-- Reset
- 7, false = hard reset
-- All
- 4, true = error with general network access
- 5, true = error while sending action
- 6, true = error while connecting to access point
'''
def led_flash(amount = 1, hold = False):
delay = 0.1
if hold:
delay = 0.2
for i in range(amount):
if i > 0:
time.sleep(delay)
led.on()
time.sleep(delay)
led.off()
### END ###
### NETWORKING ###
def network_connect():
led_flash(1)
nic = network.WLAN(network.STA_IF)
nic.active(True)
nic.config(pm=network.WLAN.PM_PERFORMANCE)
nic.connect(ssid, key)
max_wait = 10
while max_wait > 0:
if nic.status() < 0 or nic.status() >= 3:
break
max_wait -= 1
print('Waiting for connection...')
time.sleep(3)
'''
Possible nic.status() values:
-3 = CYW43_LINK_BADAUTH
-2 = CYW43_LINK_NONET
-1 = CYW43_LINK_FAIL
0 = CYW43_LINK_DOWN
1 = CYW43_LINK_JOIN
2 = CYW43_LINK_NOIP
3 = CYW43_LINK_UP
'''
if nic.status() != 3:
print('Failed to connect: {0}'.format(nic.status()))
# -1 status can come up at times
led_flash(6, True)
else:
print('Connected')
status = nic.ifconfig()
print('IP: {0}'.format(status[0]))
print("Connected to network: {0}".format(nic.isconnected()))
print("IFCONFIG: {0}".format(str(nic.ifconfig())))
led_flash(2)
### END ###
### TPLINK LIGHTBULB INIT ###
tpl_light = TPLinkLightbulb(ip_address)
def light_brightness_toggle():
action_result = None
brightness_level = tpl_light.sysinfo()
if brightness_level is not None:
if 'system' not in brightness_level: return
if 'get_sysinfo' not in brightness_level['system']: return
if 'light_state' not in brightness_level['system']['get_sysinfo']: return
if 'brightness' not in brightness_level['system']['get_sysinfo']['light_state']:
print('Light must be on to apply brightness changes')
led_flash(6)
return action_result
key_brightness = brightness_level['system']['get_sysinfo']['light_state']['brightness']
if key_brightness == 50:
action = tpl_light.brightness(100)
if action is not None:
led_flash(5)
action_result = True
else:
led_flash(5, True)
else:
action = tpl_light.brightness(50)
if action is not None:
led_flash(4)
action_result = False
else:
led_flash(5, True)
else:
led_flash(5, True)
return action_result
def light_switch():
print('Getting current light state...')
switch_new_state = None
state = tpl_light.switch_state()
if state:
print('Turning light off...')
action = tpl_light.switch(False)
if action is not None:
switch_new_state = False
led_flash(3)
else:
led_flash(5, True)
elif state == False:
print('Turning light on...')
action = tpl_light.switch(True)
if action is not None:
switch_new_state = True
led_flash(2)
else:
led_flash(5, True)
elif state == None:
print('Light switch timeout')
led_flash(5, True)
return switch_new_state
def light_state():
state = tpl_light.switch_state()
if state:
print('Light is on')
led_flash(2, True)
elif state == False:
print('Light is off')
led_flash(3, True)
elif state == None:
print('Light state timeout')
led_flash(5, True)
return state
### END ###
# Initialize variables to store press time and button state
press_time = 0
button_pressed = False
action_running = False
# Initialize the timer variable
timer = None
# Function to initialize the timer
def start_timer():
global timer
timer = machine.Timer()
timer.init(period=50, mode=machine.Timer.PERIODIC, callback=check_bootsel_button)
# Function to deinitialize the timer
def stop_timer():
global timer
if timer is not None:
timer.deinit()
def button_actions(time, button_released = True):
global action_running
action_running = True
'''
Action list
0 - 500 ms (release) = toggle power
501 - 1000 ms (release) = power state
1001 - 3000 ms (release) = toggle between brightness 50% and 100%
3001 - 5000 ms (release) = reconnect to network
5001+ ms (hold) = hard reset -- release button while LED flashes to reset, or it will go into UF2 bootloader
'''
if time > 5000 and button_released == False:
led_flash(7)
machine.reset()
elif time > 3000 and time <= 5000 and button_released:
network_connect()
elif time > 1000 and time <= 3000 and button_released:
light_brightness_toggle()
elif time > 500 and time <= 1000 and button_released:
light_state()
elif time >= 0 and time <= 500 and button_released:
light_switch()
action_running = False
# Check BOOTSEL button state
def check_bootsel_button(timer):
global press_time, button_pressed, action_running
if action_running: return
if rp2.bootsel_button():
# BOOTSEL button pressed
if not button_pressed:
# If it was not already pressed
press_time = time.ticks_ms()
button_pressed = True
# Calculate and print the hold duration
hold_duration = time.ticks_diff(time.ticks_ms(), press_time)
print("BOOTSEL button held for:", hold_duration, "ms")
button_actions(hold_duration, False)
else:
# BOOTSEL button released
if button_pressed:
# If it was previously pressed
hold_duration = time.ticks_diff(time.ticks_ms(), press_time)
print("BOOTSEL button was held for:", hold_duration, "ms")
button_pressed = False
button_actions(hold_duration)
### WEB SERVER ###
def web_server():
response = ""
addr = socket.getaddrinfo('0.0.0.0', server_web_port)[0][-1]
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(1)
print('Listening on', addr)
# Listen for connections
while True:
try:
cl, addr = s.accept()
print('Client connected from: {0}'.format(addr))
request = cl.recv(1024)
print(request)
json_response = False
response = "Invalid request -- refer to documentation"
request = str(request)
light_toggle = request.find('/light/toggle')
brightness_toggle = request.find('/light/brightness/toggle')
system_info = request.find('/light/details')
if light_toggle == 6:
state = light_switch()
if state:
response = "On"
elif state == False:
response = "Off"
else:
response = "Error"
if brightness_toggle == 6:
state = light_brightness_toggle()
if state:
response = "100%"
elif state == False:
response = "50%"
else:
response = "Error"
if system_info == 6:
system_info = tpl_light.sysinfo()
if system_info is not None:
response = system_info["system"]["get_sysinfo"]
json_response = True
else:
response = "Error"
if json_response:
response = json.dumps(response, separators=(",", ":"))
response = str(response)
content_type = 'application/json; charset=utf-8'
else:
content_type = 'text/html'
response_headers = [
'HTTP/1.1 200 OK',
'Content-Type: {0}'.format(content_type),
'Content-Length: {0}'.format(len(response)),
'Connection: keep-alive',
'Keep-Alive: timeout=5'
]
cl.send('{0}\r\n\r\n'.format('\r\n'.join(response_headers)))
cl.send(response)
cl.close()
except OSError as e:
cl.close()
print('Connection closed')
### END ###
def main():
network_connect()
led_flash(3)
start_timer()
if server_web:
web_server()
while True:
time.sleep(1) # Sleep to reduce CPU usage
if __name__ == '__main__':
main()