Skip to content

Commit 4d37fb5

Browse files
author
Marty
committed
add uyeelight
1 parent 14f6a6f commit 4d37fb5

File tree

5 files changed

+370
-6
lines changed

5 files changed

+370
-6
lines changed

esp01_lcd1602.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# https://github.com/dhylands/python_lcd/blob/master/lcd/lcd_api.py
2+
from time import sleep_ms, ticks_ms
3+
from machine import I2C, Pin
4+
from i2c_lcd import I2cLcd
5+
6+
# The PCF8574 has a jumper selectable address: 0x20 - 0x27
7+
DEFAULT_I2C_ADDR = 0x3F
8+
9+
def test_main():
10+
"""Test function for verifying basic functionality."""
11+
print("Running test_main")
12+
i2c = I2C(scl=Pin(0), sda=Pin(2), freq=100000)
13+
lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, 2, 16)
14+
lcd.putstr("It Works!\nSecond Line")
15+
sleep_ms(3000)
16+
lcd.clear()
17+
count = 0
18+
while True:
19+
lcd.move_to(0, 0)
20+
lcd.putstr("%7d" % (ticks_ms() // 1000))
21+
sleep_ms(1000)
22+
count += 1
23+
if count % 10 == 3:
24+
print("Turning backlight off")
25+
lcd.backlight_off()
26+
if count % 10 == 4:
27+
print("Turning backlight on")
28+
lcd.backlight_on()
29+
if count % 10 == 5:
30+
print("Turning display off")
31+
lcd.display_off()
32+
if count % 10 == 6:
33+
print("Turning display on")
34+
lcd.display_on()
35+
if count % 10 == 7:
36+
print("Turning display & backlight off")
37+
lcd.backlight_off()
38+
lcd.display_off()
39+
if count % 10 == 8:
40+
print("Turning display & backlight on")
41+
lcd.backlight_on()
42+
lcd.display_on()
43+
44+
#if __name__ == "__main__":
45+
test_main()

getLibrary.py

+2
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ def exe(dir):
226226
Res.exe('lib/hmc5883l.py') # 三軸加速
227227
Res.exe('lib/mlx90614.py') #額溫
228228
Res.exe('lib/i2c_lcd.py') #LCD
229+
Res.exe('lib/uyeelight.py') #LCD
230+
Res.exe('lib/lcd_api.py') #LCD
229231
Res.exe('lib/heltec/sx127x.py') #LoRa
230232
Res.exe('lib/dfplayer.py') #MP3
231233
Res.exe('lib/scanplayer.py') #MP3

lib/uyeelight.py

+248
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
import usocket as socket
2+
import json
3+
4+
5+
class YeeLightException(Exception):
6+
pass
7+
8+
9+
class EFFECT:
10+
SMOOTH = "smooth"
11+
SUDDEN = "sudden"
12+
13+
14+
class MODE:
15+
NORMAL = 0
16+
CT_MODE = 1
17+
RGB_MODE = 2
18+
HSV_MODE = 3
19+
COLOR_FLOW_MODE = 4
20+
NIGHT_LIGHT_MODE = 5
21+
22+
23+
class ACTION:
24+
LED_RECOVER_STATE = 0
25+
LED_STAY = 1
26+
LED_TURN_OFF = 2
27+
28+
29+
class SCENE_CLASS:
30+
COLOR = "color"
31+
HSV = "hsv"
32+
CT = "ct"
33+
AUTO_DELAY_OFF = "auto_delay_off"
34+
35+
36+
class SET_ADJUST_ACTION:
37+
INCREASE = "increase"
38+
DECREASE = "decrease"
39+
CIRCLE = "circle"
40+
41+
42+
class SET_ADJUST_PROP:
43+
BRIGHT = "bright"
44+
CT = "ct"
45+
COLOR = "color"
46+
47+
48+
""" API DOCS: https://www.yeelight.com/download/Yeelight_Inter-Operation_Spec.pdf """
49+
50+
51+
class Bulb():
52+
def __init__(self, ip, port=55443, debug=False):
53+
self.cmd_id = 0
54+
self._ip = ip
55+
self._port = port
56+
self.debug = debug
57+
58+
@property
59+
def get_ip(self):
60+
return self._ip
61+
62+
@property
63+
def get_port(self):
64+
return self._port
65+
66+
def turn_on(self, effect=EFFECT.SUDDEN, duration=30, mode=MODE.NORMAL):
67+
return self._handle_response(self._send_message("set_power",
68+
["on", effect, duration, mode]))
69+
70+
def turn_off(self, effect=EFFECT.SUDDEN, duration=30, mode=MODE.NORMAL):
71+
return self._handle_response(self._send_message("set_power",
72+
["off", effect, duration, mode]))
73+
74+
def toggle(self):
75+
return self._handle_response(self._send_message("toggle"))
76+
77+
@property
78+
def is_on(self):
79+
result = self._handle_response(self._send_message("get_prop", ["power"]))
80+
return result[0] == "on"
81+
82+
def change_color_temperature(self, color_temp_val, effect=EFFECT.SUDDEN, duration=30):
83+
"""
84+
:param color_temp_val: between 1700 and 6500K
85+
"""
86+
return self._handle_response(self._send_message("set_ct_abx",
87+
[color_temp_val, effect, duration]))
88+
89+
def set_rgb(self, r, g, b, effect=EFFECT.SUDDEN, duration=30):
90+
"""
91+
:param r: red
92+
:param g: green
93+
:param b: blue
94+
"""
95+
rgb = (r * 65536) + (g * 256) + b
96+
return self._handle_response(self._send_message("set_rgb",
97+
[rgb, effect, duration]))
98+
99+
def set_hsv(self, hue, sat, effect=EFFECT.SUDDEN, duration=30):
100+
"""
101+
:param hue: ranges from 0 to 359
102+
:param sat: ranges from 0 to 100
103+
"""
104+
return self._handle_response(self._send_message("set_hsv",
105+
[hue, sat, effect, duration]))
106+
107+
def set_brightness(self, brightness, effect=EFFECT.SUDDEN, duration=30):
108+
"""
109+
:param brightness: between 1 and 100
110+
"""
111+
return self._handle_response(self._send_message("set_bright",
112+
[brightness, effect, duration]))
113+
114+
def save_current_state(self):
115+
return self._handle_response(self._send_message("set_default"))
116+
117+
def start_color_flow(self, count, flow_expression, action=ACTION.LED_RECOVER_STATE):
118+
"""
119+
:param count: is the total number of visible state changing before color flow
120+
stopped. 0 means infinite loop on the state changing.
121+
:param flow_expression: is the expression of the state changing series (see API docs)
122+
:param action: is the action taken after the flow is stopped.
123+
0 means smart LED recover to the state before the color flow started.
124+
1 means smart LED stay at the state when the flow is stopped.
125+
2 means turn off the smart LED after the flow is stopped.
126+
"""
127+
return self._handle_response(self._send_message("start_cf",
128+
[count, action, flow_expression]))
129+
130+
def stop_color_flow(self):
131+
return self._handle_response(self._send_message("stop_cf"))
132+
133+
def set_scene(self, val1, val2, val3, opt=SCENE_CLASS.COLOR):
134+
"""
135+
:param val1: :param val2: :param val3: are class specific. (see API docs)
136+
:param opt: can be "color", "hsv", "ct", "cf", "auto_delay_off".
137+
"color" means change the smart LED to specified color and brightness.
138+
"hsv" means change the smart LED to specified color and brightness.
139+
"ct" means change the smart LED to specified ct and brightness.
140+
"cf" means start a color flow in specified fashion.
141+
"auto_delay_off" means turn on the smart LED to specified
142+
brightness and start a sleep timer to turn off the light after the specified minutes.
143+
"""
144+
return self._handle_response(self._send_message("set_scene",
145+
[opt, val1, val2, val3]))
146+
147+
def sleep_timer(self, time_minutes, type=0):
148+
return self._handle_response(self._send_message("cron_add",
149+
[type, time_minutes]))
150+
151+
def get_background_job(self, type=0):
152+
return self._handle_response(self._send_message("cron_get",
153+
[type]))
154+
155+
def delete_background_job(self, type=0):
156+
return self._handle_response(self._send_message("cron_del",
157+
[type]))
158+
159+
def set_adjust(self, action=SET_ADJUST_ACTION.INCREASE, prop=SET_ADJUST_PROP.BRIGHT):
160+
"""
161+
:param action: the direction of the adjustment. The valid value can be:
162+
"increase": increase the specified property
163+
"decrease": decrease the specified property
164+
"circle": increase the specified property, after it reaches the max
165+
value, go back to minimum value.
166+
:param prop: the property to adjust. The valid value can be:
167+
"bright": adjust brightness.
168+
"ct": adjust color temperature.
169+
"color": adjust color. (When “prop" is “color", the “action" can only
170+
be “circle", otherwise, it will be deemed as invalid request.)
171+
"""
172+
return self._handle_response(self._send_message("set_adjust",
173+
[action, prop]))
174+
175+
def adjust_brightness(self, percentage, duration=30):
176+
"""
177+
:param percentage: the percentage to be adjusted. The range is: -100 ~ 100
178+
"""
179+
return self._handle_response(self._send_message("adjust_bright",
180+
[percentage, duration]))
181+
182+
def adjust_color_temperature(self, percentage, duration=30):
183+
"""
184+
:param percentage: the percentage to be adjusted. The range is: -100 ~ 100
185+
"""
186+
return self._handle_response(self._send_message("adjust_ct",
187+
[percentage, duration]))
188+
189+
def adjust_color(self, percentage, duration=30):
190+
"""
191+
:param percentage: the percentage to be adjusted. The range is: -100 ~ 100
192+
"""
193+
return self._handle_response(self._send_message("adjust_color",
194+
[percentage, duration]))
195+
196+
def set_music(self, host, port, enable=True):
197+
"""
198+
:param host: the IP address of the music server.
199+
:param port: the TCP port music application is listening on.
200+
:param enable: 0: turn off music mode.
201+
1: turn on music mode.
202+
"""
203+
return self._handle_response(self._send_message("set_music",
204+
[1 if enable else 0, host, port]))
205+
206+
def set_name(self, name):
207+
"""
208+
:param name: the name of the device
209+
"""
210+
return self._handle_response(self._send_message("set_name",
211+
[name]))
212+
213+
def _send_message(self, method, params=None):
214+
if params is None:
215+
params = []
216+
217+
self.cmd_id += 1
218+
219+
message = '{{"id": {id}, "method": "{method}", "params": {params}}}\r\n'. \
220+
format(id=self.cmd_id, method=method, params=json.dumps(params))
221+
222+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
223+
224+
try:
225+
sock.connect((self.get_ip, self.get_port))
226+
sock.send(message.encode())
227+
recv_data = sock.recv(1024)
228+
except socket.timeout:
229+
return ""
230+
finally:
231+
sock.close()
232+
233+
return recv_data
234+
235+
def _handle_response(self, response):
236+
response = json.loads(response.decode('utf-8'))
237+
238+
if self.debug:
239+
print(response)
240+
241+
if "params" in response:
242+
return response["params"]
243+
elif "id" in response and not "error" in response:
244+
return response["result"]
245+
elif "error" in response:
246+
raise YeeLightException(response["error"])
247+
else:
248+
raise YeeLightException("Unknown Exception occurred.")

lib/webduino.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def blink(self,peroid):
6868
self.timer.init(period=_p_, mode=Timer.PERIODIC, callback=self.run)
6969

7070
class WiFi:
71-
71+
onlineCallback = None
7272
def disconnect():
7373
WiFi.sta.disconnect()
7474

@@ -89,13 +89,14 @@ def checkConnection(t):
8989
WiFi.connect(WiFi.ssid,WiFi.pwd)
9090
debug.print("!!!! online callback... !!!!")
9191

92-
def connect(ssid="ttt",pwd="webduino"):
92+
def connect(ssid="webduino.io",pwd="webduino"):
9393
WiFi.ssid = ssid
9494
WiFi.pwd = pwd
9595
WiFi.sta = sta_if = network.WLAN(network.STA_IF)
9696
sta_if.active(True)
9797
debug.print('connecting to network...')
98-
WiFi.onlineCallback(False)
98+
if(WiFi.onlineCallback is not None):
99+
WiFi.onlineCallback(False)
99100
if not sta_if.isconnected():
100101
try:
101102
sta_if.connect(ssid,pwd)
@@ -109,12 +110,13 @@ def connect(ssid="ttt",pwd="webduino"):
109110
cnt = 0
110111
debug.print("retry connect...")
111112
WiFi.ip = WiFi.sta.ifconfig()[0];
112-
WiFi.onlineCallback(True)
113+
if(WiFi.onlineCallback is not None):
114+
WiFi.onlineCallback(True)
113115
WiFi.startKeepConnect()
114116
return True
115117

116118
def ip():
117-
print(Wifi.sta.ifconfig())
119+
return WiFi.sta.ifconfig()
118120

119121
class MQTT():
120122

@@ -145,4 +147,4 @@ def checkMsg():
145147
try:
146148
MQTT.client.check_msg()
147149
except:
148-
pass
150+
pass

0 commit comments

Comments
 (0)