电子说
概述
想为您的房间添加独特的照明吗?
一个简单的解决方案是添加几个具有WiFi功能的LED智能灯泡 》。这些灯泡具有高能效,并具有各种形状,大小和颜色,以适合您的空间。较小的灯泡可用于重点照明或照明,而较大的灯泡则更强大,可照亮整个房间!
这些类型的灯泡非常受欢迎-并且
在本指南中,您将把PyPortal变成一个能够选择和设置多个光源的智能照明控制器
LIFX系列智能-bulbs(src:https://www.lifx.com/pages/about)
与流行的Phillips Hue等更复杂的智能照明系统不同,LIFX灯是设置非常简单。每盏灯都有自己的wifi无线电(可能是基于ESP32或ESP8266的东西?我们从拆解后的照片中看不到)并连接到您的WiFi网络。
最值得注意的是LIFX指示灯的亮点在于它们提供了完善的HTTP API,类似于Adafruit IO HTTP API。这意味着您可以使用PyPortal轻松地与它进行交互。
如果您正在寻找一种方法来使用PyPortal交互式地控制房间的照明,请遵循!
》
CircuitPython代码
CircuitPython非常适合构建物联网项目。该项目使用ESP32SPI CircuitPython库,该库可以将ESP32用作WiFi协处理器,以将Web请求发送到LIFX HTTP远程控制API。
我们还为CircuitPython构建了一个LIFX帮助器模块,以便与这些指示灯非常容易。
您可以快速更新代码,而无需在设备上编译和存储WiFi和API密钥。这意味着每当您将PyPortal移至另一个网络时,都无需编辑代码和重新上传-只需更新文件并进行设置即可。
PyPortal
向PyPortal问好!使用触摸屏显示构建物联网项目的最简单方法!确保阅读PyPortal入门指南并浏览页面。它可以帮助您使用CircuitPython和一些演示代码进行设置!
先决条件指南
如果您不熟悉CircuitPython,请花点时间浏览以下指南以获取您已开始学习并加快速度:
欢迎使用CircuitPython
零件
本指南只需要一个PyPortal-不需要其他传感器或外部电路!
Adafruit PyPortal-CircuitPython支持的Internet显示
产品ID:4116
PyPortal,我们易于使用的物联网设备,可让您在数分钟内为“物联网”创建所有东西。制作自定义触摸屏界面。..
$ 54.95
进货
添加到购物车
1 x USB电缆
USB电缆-USB A到Micro-B-3英尺长
添加到购物车
这两个和PyPortal都在AdaBox 011中站立:
AdaBox011-PyPortal
产品ID:4061
借助PyPortal,您可以走到办公桌外-到达星星和更远的地方!该ADABOX具有易于使用的新型IoT设备,可让您自定义和创建。..
缺货
缺货
PyPortal CircuitPython设置
要在CircuitPython中使用PyPortal的所有出色功能,必须首先安装许多库。本页涵盖了该过程。
Adafruit CircuitPython捆绑包
下载Adafruit CircuitPython库捆绑包。您可以在此处找到最新版本:
最新的Adafruit CircuitPython库包
下载 adafruit-circuitpython-bundle-4。 x-mpy-*。zip 捆绑zip文件,然后解压缩同名文件夹。在内部,您会找到一个 lib 文件夹。您有两个选择:
您可以将 lib 文件夹添加到您的 CIRCUITPY 驱动器中。这将确保您拥有所有驱动程序。但是这将占用8 MB磁盘上的一堆空间
根据需要添加每个库,这将减少空间使用量,但您需要
至少,我们推荐以下库,实际上我们比推荐的要多。基本上是必需的。因此,立即抓住它们并将它们安装到 CIRCUITPY/lib !
adafruit_esp32spi -这是一个库,可通过ESP32进行互联网访问使用(您猜对了!)SPI传输。 Internet所需的任何东西都需要使用它
adafruit_requests -该库使我们能够执行HTTP请求并从服务器获取响应。 GET/POST/PUT/PATCH-它们都在这里!
adafruit_pyportal -这是我们友好的包装器库,可处理很多项目,显示图形和文本,从互联网上获取数据。
adafruit_touchscreen -一个用于从电阻式触摸屏读取触摸的库。
adafruit_cursorcontrol -用于读取PyGamer和PyBadge游戏杆和按钮的库。为您处理所有图形,按钮阅读和操纵杆移动。
adafruit_io -该库有助于将PyPortal连接到我们的免费数据记录和查看服务
adafruit_imageload -任何图形所需的图像显示助手!
adafruit_display_text -毫不奇怪,它在屏幕上显示文本
adafruit_bitmap_font -我们拥有精美的字体支持,并且易于制作新字体。该库读取并解析字体文件。
adafruit_slideshow -用于制作图像幻灯片-方便快速显示图形和声音
neopixel -用于控制板载新像素
adafruit_adt7410 -用于从板载Analog Devices ADT7410精密温度传感器读取温度的库
adafruit_sdcard -支持从板载SD卡插槽中读取/写入数据。
adafruit_bus_device -对I2C/SPI的低级支持
Internet连接!
一旦您安装了CircuitPython安装程序和库,我们就可以将您的电路板连接到Internet。请注意,目前不支持访问企业级安全的WiFi网络,仅支持需要SSID和密码的WiFi网络。
要建立连接,您需要先创建一个秘密文件。
什么是机密文件?
我们希望人们在构建CircuitPython WiFi小部件时共享大量项目。我们要避免的是人们不小心共享了他们的密码或秘密令牌和API密钥。因此,我们设计了所有示例,以使用 CIRCUITPY 驱动器中的secrets.py文件来保存秘密/私有/自定义数据。这样,您就可以共享您的主项目,而不必担心意外共享私有内容。
您的 secrets.py 文件应如下所示:
下载:文件
复制代码
# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it
secrets = {
‘ssid’ : ‘home ssid’,
‘password’ : ‘my password’,
‘timezone’ : “America/New_York”, # http://worldtimeapi.org/timezones
‘github_token’ : ‘fawfj23rakjnfawiefa’,
‘hackaday_token’ : ‘h4xx0rs3kret’,
}
# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it
secrets = {
‘ssid’ : ‘home ssid’,
‘password’ : ‘my password’,
‘timezone’ : “America/New_York”, # http://worldtimeapi.org/timezones
‘github_token’ : ‘fawfj23rakjnfawiefa’,
‘hackaday_token’ : ‘h4xx0rs3kret’,
}
Inside是一个名为secrets的python字典,每个条目都有一行。每个条目都有一个条目名称(例如‘ssid’),然后是一个冒号以将其与条目键‘home ssid’分开,最后是一个逗号,
至少您需要ssid和password用于您的本地WiFi设置。在创建项目时,您可能需要更多的令牌和密钥,只需一次添加一行即可。例如,请参见其他令牌,例如用于访问github或hackaday API的令牌。其他非机密数据(例如您的时区)也可以在此处,仅因为其称为机密的信息并不意味着您不能在其中包含常规的自定义数据!
有关正确的时区字符串,请查看http://worldtimeapi.org/timezones,请记住,如果未列出您的城市,请在同一时区中查找城市,例如,波士顿,纽约,费城,华盛顿特区和迈阿密都与纽约位于同一时间。
当然,不要共享您的 secrets.py -将其保存在GitHub,Discord或其他项目共享站点之外。
连接到WiFi
好,现在您已设置好机密-您可以连接到Internet。让我们使用ESP32SPI和Requests库-您需要访问CircuitPython捆绑包并安装:
adafruit_bus_device
adafruit_esp32spi
adafruit_requests
neopixel
进入您的lib文件夹。完成后,使用Mu或您喜欢的编辑器加载以下示例:
下载:项目邮编或 esp32spi_simpletest.py | 在Github上查看
复制代码
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
print(“ESP32 SPI webclient test”)
TEXT_URL = “http://wifitest.adafruit.com/testwifi/index.html”
JSON_URL = “http://api.coindesk.com/v1/bpi/currentprice/USD.json”
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
requests.set_socket(socket, esp)
if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
print(“ESP32 found and in idle mode”)
print(“Firmware vers.”, esp.firmware_version)
print(“MAC addr:”, [hex(i) for i in esp.MAC_address])
for ap in esp.scan_networks():
print(“ %s RSSI: %d” % (str(ap[‘ssid’], ‘utf-8’), ap[‘rssi’]))
print(“Connecting to AP.。.”)
while not esp.is_connected:
try:
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
except RuntimeError as e:
print(“could not connect to AP, retrying: ”,e)
continue
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
print(“My IP address is”, esp.pretty_ip(esp.ip_address))
print(“IP lookup adafruit.com: %s” % esp.pretty_ip(esp.get_host_by_name(“adafruit.com”)))
print(“Ping google.com: %d ms” % esp.ping(“google.com”))
#esp._debug = True
print(“Fetching text from”, TEXT_URL)
r = requests.get(TEXT_URL)
print(‘-’*40)
print(r.text)
print(‘-’*40)
r.close()
print()
print(“Fetching json from”, JSON_URL)
r = requests.get(JSON_URL)
print(‘-’*40)
print(r.json())
print(‘-’*40)
r.close()
print(“Done!”)
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
print(“ESP32 SPI webclient test”)
TEXT_URL = “http://wifitest.adafruit.com/testwifi/index.html”
JSON_URL = “http://api.coindesk.com/v1/bpi/currentprice/USD.json”
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
requests.set_socket(socket, esp)
if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
print(“ESP32 found and in idle mode”)
print(“Firmware vers.”, esp.firmware_version)
print(“MAC addr:”, [hex(i) for i in esp.MAC_address])
for ap in esp.scan_networks():
print(“ %s RSSI: %d” % (str(ap[‘ssid’], ‘utf-8’), ap[‘rssi’]))
print(“Connecting to AP.。.”)
while not esp.is_connected:
try:
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
except RuntimeError as e:
print(“could not connect to AP, retrying: ”,e)
continue
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
print(“My IP address is”, esp.pretty_ip(esp.ip_address))
print(“IP lookup adafruit.com: %s” % esp.pretty_ip(esp.get_host_by_name(“adafruit.com”)))
print(“Ping google.com: %d ms” % esp.ping(“google.com”))
#esp._debug = True
print(“Fetching text from”, TEXT_URL)
r = requests.get(TEXT_URL)
print(‘-’*40)
print(r.text)
print(‘-’*40)
r.close()
print()
print(“Fetching json from”, JSON_URL)
r = requests.get(JSON_URL)
print(‘-’*40)
print(r.json())
print(‘-’*40)
r.close()
print(“Done!”)
,并将其保存到您的板上,名称为code.py。
第一个连接示例不使用机密文件-您将首先输入SSID/密码来验证连接性!
然后转到此行
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
并更改MY_SSID_NAME和 MY_SSID_PASSWORD 设置为您的访问点名称和密码,并将其保留在‘’引号内。 (此示例不使用机密文件,但它也非常独立,因此,如果其他事情似乎不起作用,则可以始终重新加载该文件。您应该获得如下内容:
示例代码。..
使用SPI端口和3个控制引脚通过SPI初始化ESP32:
下载:文件
复制代码
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
告诉我们的requests库我们正在使用的套接字的类型(套接字类型随连接类型而变化-在此示例中,我们将使用adafruit_esp32spi_socket)。还将接口设置为
下载:文件
复制代码
esp requests
验证找到ESP32,检查固件和MAC地址
下载:文件
复制代码
requests.set_socket(socket, esp) requests.set_socket(socket, esp)
扫描它可以看到的所有访问点,并打印出名称和信号强度:
下载:文件
复制代码
if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
print(“ESP32 found and in idle mode”)
print(“Firmware vers.”, esp.firmware_version)
print(“MAC addr:”, [hex(i) for i in esp.MAC_address]) if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
print(“ESP32 found and in idle mode”)
print(“Firmware vers.”, esp.firmware_version)
print(“MAC addr:”, [hex(i) for i in esp.MAC_address])
连接到我们在此处定义的AP,然后打印出来本地IP地址,尝试进行域名查找并ping google.com以检查网络连接(请注意,有时ping失败或需要一段时间,这没什么大不了的)
下载:文件
复制代码
for ap in esp.scan_networks():
print(“ %s RSSI: %d” % (str(ap[‘ssid’], ‘utf-8’), ap[‘rssi’])) for ap in esp.scan_networks():
print(“ %s RSSI: %d” % (str(ap[‘ssid’], ‘utf-8’), ap[‘rssi’]))
好的,现在我们进入真正有趣的部分。使用SAMD51或其他大容量RAM(超过32 KB)设备,我们可以做很多巧妙的事情。例如,我们可以像请求一样实现一个接口,这使得获取数据非常简单
从Web URL调用 print(“Connecting to AP.。.”)
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
print(“My IP address is”, esp.pretty_ip(esp.ip_address))
print(“IP lookup adafruit.com: %s” % esp.pretty_ip(esp.get_host_by_name(“adafruit.com”)))
print(“Ping google.com: %d ms” % esp.ping(“google.com”))
中读取所有文本-您可以传入 print(“Connecting to AP.。.”)
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
print(“My IP address is”, esp.pretty_ip(esp.ip_address))
print(“IP lookup adafruit.com: %s” % esp.pretty_ip(esp.get_host_by_name(“adafruit.com”)))
print(“Ping google.com: %d ms” % esp.ping(“google.com”))
用于SSL连接的URL
下载:文件
复制代码
requests.get https
或者,如果数据使用结构化JSON,则可以获取json pre -解析为可以轻松查询或遍历的Python字典。 (同样,仅适用于nRF52840,M4和其他高RAM板)
下载:文件
复制代码
TEXT_URL = “http://wifitest.adafruit.com/testwifi/index.html”
print(“Fetching text from”, TEXT_URL)
r = requests.get(TEXT_URL)
print(‘-’*40)
print(r.text)
print(‘-’*40)
r.close() TEXT_URL = “http://wifitest.adafruit.com/testwifi/index.html”
print(“Fetching text from”, TEXT_URL)
r = requests.get(TEXT_URL)
print(‘-’*40)
print(r.text)
print(‘-’*40)
r.close()
Requests
我们已经为Web接口编写了一个类似请求的库,名为Adafruit_CircuitPython_Requests。该库允许您发送HTTP/1.1请求,而无需“设计”它们,并提供了有用的方法来解析服务器的响应。
下载:Project Zip 或 requests_simpletest.py | 在Github上查看
复制代码
JSON_URL = “http://api.coindesk.com/v1/bpi/currentprice/USD.json”
print(“Fetching json from”, JSON_URL)
r = requests.get(JSON_URL)
print(‘-’*40)
print(r.json())
print(‘-’*40)
r.close() JSON_URL = “http://api.coindesk.com/v1/bpi/currentprice/USD.json”
print(“Fetching json from”, JSON_URL)
r = requests.get(JSON_URL)
print(‘-’*40)
print(r.json())
print(‘-’*40)
r.close()
代码首先设置ESP32SPI接口。然后,它使用ESP32 # adafruit_requests usage with an esp32spi_socket
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
print(“Connecting to AP.。.”)
while not esp.is_connected:
try:
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
except RuntimeError as e:
print(“could not connect to AP, retrying: ”,e)
continue
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
# Initialize a requests object with a socket and esp32spi interface
requests.set_socket(socket, esp)
TEXT_URL = “http://wifitest.adafruit.com/testwifi/index.html”
JSON_GET_URL = “http://httpbin.org/get”
JSON_POST_URL = “http://httpbin.org/post”
print(“Fetching text from %s”%TEXT_URL)
response = requests.get(TEXT_URL)
print(‘-’*40)
print(“Text Response: ”, response.text)
print(‘-’*40)
response.close()
print(“Fetching JSON data from %s”%JSON_GET_URL)
response = requests.get(JSON_GET_URL)
print(‘-’*40)
print(“JSON Response: ”, response.json())
print(‘-’*40)
response.close()
data = ‘31F’
print(“POSTing data to {0}: {1}”.format(JSON_POST_URL, data))
response = requests.post(JSON_POST_URL, data=data)
print(‘-’*40)
json_resp = response.json()
# Parse out the ‘data’ key from json_resp dict.
print(“Data received from server:”, json_resp[‘data’])
print(‘-’*40)
response.close()
json_data = {“Date” : “July 25, 2019”}
print(“POSTing data to {0}: {1}”.format(JSON_POST_URL, json_data))
response = requests.post(JSON_POST_URL, json=json_data)
print(‘-’*40)
json_resp = response.json()
# Parse out the ‘json’ key from json_resp dict.
print(“JSON Data received from server:”, json_resp[‘json’])
print(‘-’*40)
response.close()
和# adafruit_requests usage with an esp32spi_socket
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
print(“Connecting to AP.。.”)
while not esp.is_connected:
try:
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
except RuntimeError as e:
print(“could not connect to AP, retrying: ”,e)
continue
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
# Initialize a requests object with a socket and esp32spi interface
requests.set_socket(socket, esp)
TEXT_URL = “http://wifitest.adafruit.com/testwifi/index.html”
JSON_GET_URL = “http://httpbin.org/get”
JSON_POST_URL = “http://httpbin.org/post”
print(“Fetching text from %s”%TEXT_URL)
response = requests.get(TEXT_URL)
print(‘-’*40)
print(“Text Response: ”, response.text)
print(‘-’*40)
response.close()
print(“Fetching JSON data from %s”%JSON_GET_URL)
response = requests.get(JSON_GET_URL)
print(‘-’*40)
print(“JSON Response: ”, response.json())
print(‘-’*40)
response.close()
data = ‘31F’
print(“POSTing data to {0}: {1}”.format(JSON_POST_URL, data))
response = requests.post(JSON_POST_URL, data=data)
print(‘-’*40)
json_resp = response.json()
# Parse out the ‘data’ key from json_resp dict.
print(“Data received from server:”, json_resp[‘data’])
print(‘-’*40)
response.close()
json_data = {“Date” : “July 25, 2019”}
print(“POSTing data to {0}: {1}”.format(JSON_POST_URL, json_data))
response = requests.post(JSON_POST_URL, json=json_data)
print(‘-’*40)
json_resp = response.json()
# Parse out the ‘json’ key from json_resp dict.
print(“JSON Data received from server:”, json_resp[‘json’])
print(‘-’*40)
response.close()
对象初始化request对象。
下载:文件
复制代码
socket esp
带有请求的HTTP GET
代码向Adafruit的WiFi测试网站-http:/发出HTTP GET请求/wifitest.adafruit.com/testwifi/index.html。
为此,我们会将URL传递到import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
print(“Connecting to AP.。.”)
while not esp.is_connected:
try:
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
except RuntimeError as e:
print(“could not connect to AP, retrying: ”,e)
continue
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
# Initialize a requests object with a socket and esp32spi interface
requests.set_socket(socket, esp)。我们还将将来自服务器的响应保存到名为import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
print(“Connecting to AP.。.”)
while not esp.is_connected:
try:
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
except RuntimeError as e:
print(“could not connect to AP, retrying: ”,e)
continue
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
# Initialize a requests object with a socket and esp32spi interface
requests.set_socket(socket, esp)的变量。
尽管我们从服务器请求数据,但我们还是希望服务器回应。由于我们已经保存了服务器的requests.get(),因此可以将其读回。对我们来说幸运的是,请求将服务器的响应自动解码为人类可读的文本,您可以通过调用response将其读回。
最后,我们将执行一些操作通过调用response进行清理。这样会关闭,删除和收集响应的数据。
下载:文件
复制代码
response.text response.close()
一些服务器使用文本响应,而某些服务器则使用由属性-值对组成的json格式的数据进行响应。/p》
CircuitPython_Requests可以将来自服务器的JSON格式的响应转换为CPython print(“Fetching text from %s”%TEXT_URL)
response = requests.get(TEXT_URL)
print(‘-’*40)
print(“Text Response: ”, response.text)
print(‘-’*40)
response.close()对象。
我们还可以获取和解析 json 数据。我们将发送HTTP Get到一个我们知道的URL,该URL返回一个json格式的响应(而不是文本数据)。
然后,代码调用print(“Fetching text from %s”%TEXT_URL)
response = requests.get(TEXT_URL)
print(‘-’*40)
print(“Text Response: ”, response.text)
print(‘-’*40)
response.close()将响应转换为一个CPython dict.。
下载:文件
复制代码
response.json() dict
带有请求的HTTP POST
请求还可以通过调用print(“Fetching JSON data from %s”%JSON_GET_URL)
response = requests.get(JSON_GET_URL)
print(‘-’*40)
print(“JSON Response: ”, response.json())
print(‘-’*40)
response.close()方法(向其传递一个print(“Fetching JSON data from %s”%JSON_GET_URL)
response = requests.get(JSON_GET_URL)
print(‘-’*40)
print(“JSON Response: ”, response.json())
print(‘-’*40)
response.close()值)将数据发布到服务器。
下载:文件
复制代码
requests.post data
您还可以通过将data = ‘31F’
print(“POSTing data to {0}: {1}”.format(JSON_POST_URL, data))
response = requests.post(JSON_POST_URL, data=data)
print(‘-’*40)
json_resp = response.json()
# Parse out the ‘data’ key from json_resp dict.
print(“Data received from server:”, json_resp[‘data’])
print(‘-’*40)
response.close()传递到data = ‘31F’
print(“POSTing data to {0}: {1}”.format(JSON_POST_URL, data))
response = requests.post(JSON_POST_URL, data=data)
print(‘-’*40)
json_resp = response.json()
# Parse out the ‘data’ key from json_resp dict.
print(“Data received from server:”, json_resp[‘data’])
print(‘-’*40)
response.close()方法中,将json格式的数据发布到服务器。
下载:文件
复制代码
json_data requests.post
高级请求使用情况
要发送自定义HTTP, aders,将响应解析为原始字节,还是在CircuitPython代码中处理响应的http状态代码?
我们已经编写了一个示例来显示下面的请求模块的高级用法。
下载:项目Zip 或 requests_advanced.py | 在Github上查看
复制代码
json_data = {“Date” : “July 25, 2019”}
print(“POSTing data to {0}: {1}”.format(JSON_POST_URL, json_data))
response = requests.post(JSON_POST_URL, json=json_data)
print(‘-’*40)
json_resp = response.json()
# Parse out the ‘json’ key from json_resp dict.
print(“JSON Data received from server:”, json_resp[‘json’])
print(‘-’*40)
response.close()
json_data = {“Date” : “July 25, 2019”}
print(“POSTing data to {0}: {1}”.format(JSON_POST_URL, json_data))
response = requests.post(JSON_POST_URL, json=json_data)
print(‘-’*40)
json_resp = response.json()
# Parse out the ‘json’ key from json_resp dict.
print(“JSON Data received from server:”, json_resp[‘json’])
print(‘-’*40)
response.close()
WiFi Manager
这个最简单的示例可行,但有点挑剔-您需要不断检查WiFi状态,并具有许多循环来管理连接和断开连接。对于更高级的用途,我们建议使用WiFiManager对象。它将为您包装连接/状态/请求循环-如果WiFi掉线,则重新连接,如果ESP32进入不良状态,则重置ESP32,等等。
这是一个更高级的示例,其中显示了WiFi管理器以及如何使用一些额外的标题发布数据:
下载:Project Zip 或 esp32spi_aio_post.py | 在Github上查看
复制代码
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
print(“Connecting to AP.。.”)
while not esp.is_connected:
try:
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
except RuntimeError as e:
print(“could not connect to AP, retrying: ”,e)
continue
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
# Initialize a requests object with a socket and esp32spi interface
requests.set_socket(socket, esp)
JSON_GET_URL = “http://httpbin.org/get”
# Define a custom header as a dict.
headers = {“user-agent” : “blinka/1.0.0”}
print(“Fetching JSON data from %s.。.”%JSON_GET_URL)
response = requests.get(JSON_GET_URL, headers=headers)
print(‘-’*60)
json_data = response.json()
headers = json_data[‘headers’]
print(“Response‘s Custom User-Agent Header: {0}”.format(headers[’User-Agent‘]))
print(’-‘*60)
# Read Response’s HTTP status code
print(“Response HTTP Status Code: ”, response.status_code)
print(‘-’*60)
# Read Response, as raw bytes instead of pretty text
print(“Raw Response: ”, response.content)
# Close, delete and collect the response data
response.close()
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
print(“Connecting to AP.。.”)
while not esp.is_connected:
try:
esp.connect_AP(b‘MY_SSID_NAME’, b‘MY_SSID_PASSWORD’)
except RuntimeError as e:
print(“could not connect to AP, retrying: ”,e)
continue
print(“Connected to”, str(esp.ssid, ‘utf-8’), “ RSSI:”, esp.rssi)
# Initialize a requests object with a socket and esp32spi interface
requests.set_socket(socket, esp)
JSON_GET_URL = “http://httpbin.org/get”
# Define a custom header as a dict.
headers = {“user-agent” : “blinka/1.0.0”}
print(“Fetching JSON data from %s.。.”%JSON_GET_URL)
response = requests.get(JSON_GET_URL, headers=headers)
print(‘-’*60)
json_data = response.json()
headers = json_data[‘headers’]
print(“Response‘s Custom User-Agent Header: {0}”.format(headers[’User-Agent‘]))
print(’-‘*60)
# Read Response’s HTTP status code
print(“Response HTTP Status Code: ”, response.status_code)
print(‘-’*60)
# Read Response, as raw bytes instead of pretty text
print(“Raw Response: ”, response.content)
# Close, delete and collect the response data
response.close()
您会在这里注意到,我们使用secrets.py文件来管理我们的SSID信息。 wifimanager被赋予了ESP32对象,密码和一个用于指示状态的新像素。
请注意,您需要在密码文件中添加一些其他信息,以便代码可以查询Adafruit IO API:
import time
import board
import busio
from digitalio import DigitalInOut
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
print(“ESP32 SPI webclient test”)
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print(“WiFi secrets are kept in secrets.py, please add them there!”)
raise
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
“”“Use below for Most Boards”“”
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) # Uncomment for Most Boards
“”“Uncomment below for ItsyBitsy M4”“”
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
# Uncomment below for an externally defined RGB LED
# import adafruit_rgbled
# from adafruit_esp32spi import PWMOut
# RED_LED = PWMOut.PWMOut(esp, 26)
# GREEN_LED = PWMOut.PWMOut(esp, 27)
# BLUE_LED = PWMOut.PWMOut(esp, 25)
# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
counter = 0
while True:
try:
print(“Posting data.。.”, end=‘’)
data = counter
feed = ‘test’
payload = {‘value’:data}
response = wifi.post(
“https://io.adafruit.com/api/v2/”+secrets[‘aio_username’]+“/feeds/”+feed+“/data”,
json=payload,
headers={“X-AIO-KEY”:secrets[‘aio_key’]})
print(response.json())
response.close()
counter = counter + 1
print(“OK”)
except (ValueError, RuntimeError) as e:
print(“Failed to get data, retrying ”, e)
wifi.reset()
continue
response = None
time.sleep(15)
import time
import board
import busio
from digitalio import DigitalInOut
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
print(“ESP32 SPI webclient test”)
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print(“WiFi secrets are kept in secrets.py, please add them there!”)
raise
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
“”“Use below for Most Boards”“”
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) # Uncomment for Most Boards
“”“Uncomment below for ItsyBitsy M4”“”
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
# Uncomment below for an externally defined RGB LED
# import adafruit_rgbled
# from adafruit_esp32spi import PWMOut
# RED_LED = PWMOut.PWMOut(esp, 26)
# GREEN_LED = PWMOut.PWMOut(esp, 27)
# BLUE_LED = PWMOut.PWMOut(esp, 25)
# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
counter = 0
while True:
try:
print(“Posting data.。.”, end=‘’)
data = counter
feed = ‘test’
payload = {‘value’:data}
response = wifi.post(
“https://io.adafruit.com/api/v2/”+secrets[‘aio_username’]+“/feeds/”+feed+“/data”,
json=payload,
headers={“X-AIO-KEY”:secrets[‘aio_key’]})
print(response.json())
response.close()
counter = counter + 1
print(“OK”)
except (ValueError, RuntimeError) as e:
print(“Failed to get data, retrying ”, e)
wifi.reset()
continue
response = None
time.sleep(15)
您可以转到adafruit.io查看AIO密钥链接获取这两个值并将它们添加到secrets文件中,该文件现在看起来像这样:
下载:文件
复制代码
aio_username aio_key
下一步,设置一个名为Adafruit IO提要# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it
secrets = {
‘ssid’ : ‘_your_ssid_’,
‘password’ : ‘_your_wifi_password_’,
‘timezone’ : “America/Los_Angeles”, # http://worldtimeapi.org/timezones
‘aio_username’ : ‘_your_aio_username_’,
‘aio_key’ : ‘_your_aio_key_’,
}
如果您不知道如何设置供稿,请遵循此页面并在设置名为。
然后,我们可以有一个简单的循环,用于将数据发布到Adafruit IO,而无需处理连接或初始化硬件!
在Adafruit.io上查看您的测试数据,每次Cir时,您都会看到该值增加cuitPython板向其发布数据!
使用CircuitPython编写PyPortal代码
LIFX访问令牌
所有对LIFX灯泡的请求都需要一个访问令牌。
导航 到 LIFX帐户设置页上,命名访问令牌,并进行独特的设置,然后点击生成。
然后,将此令牌复制到文件或安全的地方-当您离开此页面时,您将不能再次查看它。
CircuitPython库安装
首先请确保您正在运行最新版本的
下一步,您需要安装必要的库才能使用硬件-仔细按照以下步骤从Adafruit的CircuitPython库中查找并安装这些库与您的CircuitPython版本匹配。 PyPortal至少需要CircuitPython版本4.0.0。
在继续之前,请确保您开发板的 lib 文件夹已复制了以下文件和文件夹 。
p》
adafruit_lifx
adastrong_bitmap_font
adafruit_bus_device
adafruit_button
adafruit_display_shapes
adafruit_display_text
》 adafruit_esp32spi
adafruit_touchscreen
neopixel
秘密文件设置
如果尚未设置 CIRCUITPY 驱动器中的 secrets.py 文件并使用该文件连接到Internet,请按照本指南进行操作,并在成功连接到Internet后返回此页面。/p》
添加您生成的LIFX访问令牌到 secrets.py 文件:
下载:文件
复制代码
secrets = {
‘ssid’ : ‘_your_wifi_ssid_’,
‘password : ’_your_wifi_password_‘,
’lifx_token‘ : ’_your_really_long_lifx_token_‘
} secrets = {
’ssid‘ : ’_your_wifi_ssid_‘,
’password : ‘_your_wifi_password_’,
‘lifx_token’ : ‘_your_really_long_lifx_token_’
}
添加CircuitPython代码和项目资产
在下面的嵌入式代码元素中,单击下载:Project Zip 链接,然后保存。压缩文件。
然后,解压缩.zip文件,它将解压缩到名为 pyportal_lifx_controller 的文件夹中。
将 pyportal_lifx_controller 目录的内容复制到PyPortal的 CIRCUITPY 驱动器。
下载:Project Zip 或 code.py | 查看Github
复制代码
“”“
PyPortal Smart Lighting Controller
-------------------------------------------------------------
https://learn.adafruit.com/pyportal-smart-lighting-controller
Brent Rubell for Adafruit Industries, 2019
”“”
import board
import displayio
from adafruit_bitmap_font import bitmap_font
from adafruit_button import Button
import adafruit_touchscreen
from digitalio import DigitalInOut
import busio
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
# import lifx library
import adafruit_lifx
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print(“WiFi secrets are kept in secrets.py, please add them there!”)
raise
# ESP32 SPI
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
# These pins are used as both analog and digital! XL, XR and YU must be analog
# and digital capable. YD just need to be digital
ts = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR,
board.TOUCH_YD, board.TOUCH_YU,
calibration=((5200, 59000), (5800, 57000)),
size=(320, 240))
# Set this to your LIFX personal access token in secrets.py
# (to obtain a token, visit: https://cloud.lifx.com/settings)
lifx_token = secrets[‘lifx_token’]
# Initialize the LIFX API Helper
lifx = adafruit_lifx.LIFX(wifi, lifx_token)
# Set these to your LIFX light selector (https://api.developer.lifx.com/docs/selectors)
lifx_lights = [‘label:Lamp’, ‘label:Bedroom’]
# set default light properties
current_light = lifx_lights[0]
light_brightness = 1.0
# Make the display context
button_group = displayio.Group(max_size=20)
board.DISPLAY.show(button_group)
# preload the font
print(‘loading font.。.’)
font = bitmap_font.load_font(“/fonts/Arial-12.bdf”)
glyphs = b‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,。: ’
font.load_glyphs(glyphs)
# button properties
BUTTON_WIDTH = 60
BUTTON_HEIGHT = 60
buttons = []
# button fill colors (from https://api.developer.lifx.com/docs/colors)
button_colors = {‘red’:0xFF0000, ‘white’:0xFFFFFF,
‘orange’:0xFF9900, ‘yellow’:0xFFFF00,
‘green’:0x00FF00, ‘blue’:0x0000FF,
‘purple’:0x9900FF, ‘pink’: 0xFF00FF}
print(‘loading buttons.。.’)
# list of color buttons and their properties
color_btn = [
{‘name’:‘red’, ‘pos’:(15, 80), ‘color’:button_colors[‘red’]},
{‘name’:‘white’, ‘pos’:(85, 80), ‘color’:button_colors[‘white’]},
{‘name’:‘orange’, ‘pos’:(155, 80), ‘color’:button_colors[‘orange’]},
{‘name’:‘yellow’, ‘pos’:(225, 80), ‘color’:button_colors[‘yellow’]},
{‘name’:‘pink’, ‘pos’:(15, 155), ‘color’:button_colors[‘pink’]},
{‘name’:‘green’, ‘pos’:(85, 155), ‘color’:button_colors[‘green’]},
{‘name’:‘blue’, ‘pos’:(155, 155), ‘color’:button_colors[‘blue’]},
{‘name’:‘purple’, ‘pos’:(225, 155), ‘color’:button_colors[‘purple’]}
]
# generate color buttons from color_btn list
for i in color_btn:
button = Button(x=i[‘pos’][0], y=i[‘pos’][1],
width=BUTTON_WIDTH, height=BUTTON_HEIGHT, name=i[‘name’],
fill_color=i[‘color’], style=Button.ROUNDRECT)
buttons.append(button)
# light property buttons and their properties
prop_btn = [
{‘name’:‘onoff’, ‘pos’:(15, 15), ‘label’:‘on/off’},
{‘name’:‘up’, ‘pos’:(75, 15), ‘label’:‘+’},
{‘name’:‘down’, ‘pos’:(135, 15), ‘label’:‘-’},
{‘name’:‘lamp’, ‘pos’:(195, 15), ‘label’:‘lamp’},
{‘name’:‘room’, ‘pos’:(245, 15), ‘label’:‘room’}
]
# generate property buttons from prop_btn list
for i in prop_btn:
button = Button(name=i[‘name’], x=i[‘pos’][0], y=i[‘pos’][1],
width=40, height=40, label=i[‘label’],
label_font=font, style=Button.SHADOWROUNDRECT)
buttons.append(button)
# add buttons to the group
for b in buttons:
button_group.append(b.group)
while True:
touch = ts.touch_point
if touch:
for i, button in enumerate(buttons):
if button.contains(touch):
button.selected = True
if button.name == ‘lamp’:
current_light = lifx_lights[0]
print(‘Switching to ’, current_light)
elif button.name == ‘room’:
current_light = lifx_lights[1]
print(‘Switching to ’, current_light)
elif button.name == ‘onoff’:
print(‘Toggling {0}。..’.format(current_light))
lifx.toggle_light(current_light)
elif button.name == ‘up’:
light_brightness += 0.25
print(‘Setting {0} brightness to {1}’.format(current_light, light_brightness))
lifx.set_brightness(current_light, light_brightness)
elif button.name == ‘down’:
light_brightness -= 0.25
print(‘Setting {0} brightness to {1}’.format(current_light, light_brightness))
lifx.set_brightness(current_light, light_brightness)
else:
print(‘Setting {0} color to {1}’.format(current_light, button.name))
lifx.set_color(current_light, ‘on’, button.name, light_brightness)
button.selected = False
else:
button.selected = False
“”“
PyPortal Smart Lighting Controller
-------------------------------------------------------------
https://learn.adafruit.com/pyportal-smart-lighting-controller
Brent Rubell for Adafruit Industries, 2019
”“”
import board
import displayio
from adafruit_bitmap_font import bitmap_font
from adafruit_button import Button
import adafruit_touchscreen
from digitalio import DigitalInOut
import busio
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
# import lifx library
import adafruit_lifx
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print(“WiFi secrets are kept in secrets.py, please add them there!”)
raise
# ESP32 SPI
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
# These pins are used as both analog and digital! XL, XR and YU must be analog
# and digital capable. YD just need to be digital
ts = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR,
board.TOUCH_YD, board.TOUCH_YU,
calibration=((5200, 59000), (5800, 57000)),
size=(320, 240))
# Set this to your LIFX personal access token in secrets.py
# (to obtain a token, visit: https://cloud.lifx.com/settings)
lifx_token = secrets[‘lifx_token’]
# Initialize the LIFX API Helper
lifx = adafruit_lifx.LIFX(wifi, lifx_token)
# Set these to your LIFX light selector (https://api.developer.lifx.com/docs/selectors)
lifx_lights = [‘label:Lamp’, ‘label:Bedroom’]
# set default light properties
current_light = lifx_lights[0]
light_brightness = 1.0
# Make the display context
button_group = displayio.Group(max_size=20)
board.DISPLAY.show(button_group)
# preload the font
print(‘loading font.。.’)
font = bitmap_font.load_font(“/fonts/Arial-12.bdf”)
glyphs = b‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,。: ’
font.load_glyphs(glyphs)
# button properties
BUTTON_WIDTH = 60
BUTTON_HEIGHT = 60
buttons = []
# button fill colors (from https://api.developer.lifx.com/docs/colors)
button_colors = {‘red’:0xFF0000, ‘white’:0xFFFFFF,
‘orange’:0xFF9900, ‘yellow’:0xFFFF00,
‘green’:0x00FF00, ‘blue’:0x0000FF,
‘purple’:0x9900FF, ‘pink’: 0xFF00FF}
print(‘loading buttons.。.’)
# list of color buttons and their properties
color_btn = [
{‘name’:‘red’, ‘pos’:(15, 80), ‘color’:button_colors[‘red’]},
{‘name’:‘white’, ‘pos’:(85, 80), ‘color’:button_colors[‘white’]},
{‘name’:‘orange’, ‘pos’:(155, 80), ‘color’:button_colors[‘orange’]},
{‘name’:‘yellow’, ‘pos’:(225, 80), ‘color’:button_colors[‘yellow’]},
{‘name’:‘pink’, ‘pos’:(15, 155), ‘color’:button_colors[‘pink’]},
{‘name’:‘green’, ‘pos’:(85, 155), ‘color’:button_colors[‘green’]},
{‘name’:‘blue’, ‘pos’:(155, 155), ‘color’:button_colors[‘blue’]},
{‘name’:‘purple’, ‘pos’:(225, 155), ‘color’:button_colors[‘purple’]}
]
# generate color buttons from color_btn list
for i in color_btn:
button = Button(x=i[‘pos’][0], y=i[‘pos’][1],
width=BUTTON_WIDTH, height=BUTTON_HEIGHT, name=i[‘name’],
fill_color=i[‘color’], style=Button.ROUNDRECT)
buttons.append(button)
# light property buttons and their properties
prop_btn = [
{‘name’:‘onoff’, ‘pos’:(15, 15), ‘label’:‘on/off’},
{‘name’:‘up’, ‘pos’:(75, 15), ‘label’:‘+’},
{‘name’:‘down’, ‘pos’:(135, 15), ‘label’:‘-’},
{‘name’:‘lamp’, ‘pos’:(195, 15), ‘label’:‘lamp’},
{‘name’:‘room’, ‘pos’:(245, 15), ‘label’:‘room’}
]
# generate property buttons from prop_btn list
for i in prop_btn:
button = Button(name=i[‘name’], x=i[‘pos’][0], y=i[‘pos’][1],
width=40, height=40, label=i[‘label’],
label_font=font, style=Button.SHADOWROUNDRECT)
buttons.append(button)
# add buttons to the group
for b in buttons:
button_group.append(b.group)
while True:
touch = ts.touch_point
if touch:
for i, button in enumerate(buttons):
if button.contains(touch):
button.selected = True
if button.name == ‘lamp’:
current_light = lifx_lights[0]
print(‘Switching to ’, current_light)
elif button.name == ‘room’:
current_light = lifx_lights[1]
print(‘Switching to ’, current_light)
elif button.name == ‘onoff’:
print(‘Toggling {0}。..’.format(current_light))
lifx.toggle_light(current_light)
elif button.name == ‘up’:
light_brightness += 0.25
print(‘Setting {0} brightness to {1}’.format(current_light, light_brightness))
lifx.set_brightness(current_light, light_brightness)
elif button.name == ‘down’:
light_brightness -= 0.25
print(‘Setting {0} brightness to {1}’.format(current_light, light_brightness))
lifx.set_brightness(current_light, light_brightness)
else:
print(‘Setting {0} color to {1}’.format(current_light, button.name))
lifx.set_color(current_light, ‘on’, button.name, light_brightness)
button.selected = False
else:
button.selected = False
这是 CIRCUITPY 的最终内容驱动器将如下所示:
设置代码
使用代码之前,您需要将 code.py 文件修改为添加一个标签来指定您要控制的灯。
LIFX使用称为选择器的标识符来识别与您的帐户关联的灯。通过选择器,您可以使用灯光的唯一标识符,位置(卧室,工作台,客厅)或照明组。为简单起见,本指南假定您将标签用作选择器。
查找灯泡的标签:
导航至LIFX应用,然后选择要控制的灯光。
点击齿轮图标以显示灯光的详细设置。
灯光的名称是灯光的标签。
下一步,修改 code.py 中的lifx_lights变量,以包含来自应用程序的标签。
例如,如果要添加一个名为 workbench 的新LIFX灯泡,则将代码 from
lifx_lights = [‘label:lamp’, ‘label:Main Room’]更改为
到
lifx_lights = [‘label:lamp’, ‘label:workbench’]
请确保包含label: 之前
有关使用LIFX灯光选择器的更多信息,请在此处查看有关此主题的API文档。
代码用法
从Mu编辑器中,单击“串行”按钮以打开REPL。您应该在加载界面时看到REPL显示代码的状态。
通过点击要控制的灯光的名称来选择灯光。如果未选择任何灯光,则代码将默认为列表。
点击/off按钮以切换所选灯的电源。请记住,LIFX灯会保存状态-如果您之前将灯设置为红色并关闭,则它会以相同的颜色打开。
按钮在向LIFX API发出请求时会反转颜色。 请求完成后,按钮将变回其原始颜色。
如果您遇到灯光不响应的问题:向下滚动到下面的诊断错误部分。
点击颜色按钮会将灯光设置为按钮的填充颜色,其亮度由 + 或-按钮指定。
注意:我们在本指南中使用了颜色名称来设置不同的颜色。 LIFX HTTP远程控制API允许您超越基本颜色-您可以通过指定色相,饱和度,亮度,开尔文或十六进制值来设置灯泡的颜色。
接下来,我们来看看加载到PyPortal上的代码
代码演练
导入库
下载:文件
复制代码
import board
import displayio
from adafruit_bitmap_font import bitmap_font
from adafruit_button import Button
import adafruit_touchscreen
from digitalio import DigitalInOut
import busio
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
# import lifx library
import adafruit_lifx import board
import displayio
from adafruit_bitmap_font import bitmap_font
from adafruit_button import Button
import adafruit_touchscreen
from digitalio import DigitalInOut
import busio
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
# import lifx library
import adafruit_lifx
代码首先导入运行智能照明控制器所需的所有库。
注意一个特殊的adafruit_lifx库。为了与LIFX API进行通信,我们编写了一个名为CircuitPython_LIFX的CircuitPython帮助器模块。该模块向LIFX API服务器发出HTTP请求(或“对话”),以便与灯泡进行交互。
有关HTTP工作原理的更多信息,请查看我们的All Internet of有关此主题的内容指南。
配置PyPortal
下载:文件
复制代码
# ESP32 SPI
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
# These pins are used as both analog and digital! XL, XR and YU must be analog
# and digital capable. YD just need to be digital
ts = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR,
board.TOUCH_YD, board.TOUCH_YU,
calibration=((5200, 59000), (5800, 57000)),
size=(320, 240)) # ESP32 SPI
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
# These pins are used as both analog and digital! XL, XR and YU must be analog
# and digital capable. YD just need to be digital
ts = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR,
board.TOUCH_YD, board.TOUCH_YU,
calibration=((5200, 59000), (5800, 57000)),
size=(320, 240))
下一部分代码从 secrets.py 文件中获取信息,包括wifi配置和LIFX Access令牌。然后,它建立ESP32的SPI连接,以与PyPortal一起使用。 wifi对象也在此处设置-稍后在代码中用于与LIFX API通信。
配置LIFX帮助器模块
下载:文件
复制代码
# Set this to your LIFX personal access token in secrets.py
# (to obtain a token, visit: https://cloud.lifx.com/settings)
lifx_token = secrets[‘lifx_token’]
# Initialize the LIFX API Helper
lifx = adafruit_lifx.LIFX(wifi, lifx_token)
# Set these to your LIFX light selector (https://api.developer.lifx.com/docs/selectors)
lifx_lights = [‘label:Lamp’, ‘label:Bedroom’]
# set default light properties
current_light = lifx_lights[0]
light_brightness = 1.0 # Set this to your LIFX personal access token in secrets.py
# (to obtain a token, visit: https://cloud.lifx.com/settings)
lifx_token = secrets[‘lifx_token’]
# Initialize the LIFX API Helper
lifx = adafruit_lifx.LIFX(wifi, lifx_token)
# Set these to your LIFX light selector (https://api.developer.lifx.com/docs/selectors)
lifx_lights = [‘label:Lamp’, ‘label:Bedroom’]
# set default light properties
current_light = lifx_lights[0]
light_brightness = 1.0
秘密中的lifx_token条目是设置为新变量lifx_token,并与之前创建的wifi对象一起传递到LIFX帮助器中。
然后,代码设置了两个灯的列表(由其选择器标识) 。在此代码的后面,这些灯链接到按钮,以便该代码可以识别正在切换的灯。
此外,还设置了默认的灯亮度100%,以及一个current_light变量。
按钮设置
下载:文件
复制代码
# Make the display context
button_group = displayio.Group(max_size=20)
board.DISPLAY.show(button_group)
# preload the font
print(‘loading font.。.’)
font = bitmap_font.load_font(“/fonts/Arial-12.bdf”)
glyphs = b‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,。: ’
font.load_glyphs(glyphs)
# button properties
BUTTON_WIDTH = 60
BUTTON_HEIGHT = 60
buttons = [] # Make the display context
button_group = displayio.Group(max_size=20)
board.DISPLAY.show(button_group)
# preload the font
print(‘loading font.。.’)
font = bitmap_font.load_font(“/fonts/Arial-12.bdf”)
glyphs = b‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,。: ’
font.load_glyphs(glyphs)
# button properties
BUTTON_WIDTH = 60
BUTTON_HEIGHT = 60
buttons = []
在代码可以创建按钮之前,它需要创建一个displayio组来容纳它们。在这里-代码选择一种字体,预加载了字形,并为BUTTON_WIDTH和BUTTON_HEIGHT设置按钮属性。
按钮生成
下载:文件
复制代码
# list of color buttons and their properties
color_btn = [
{‘name’:‘red’, ‘pos’:(15, 80), ‘color’:button_colors[‘red’]},
{‘name’:‘white’, ‘pos’:(85, 80), ‘color’:button_colors[‘white’]},
{‘name’:‘orange’, ‘pos’:(155, 80), ‘color’:button_colors[‘orange’]},
{‘name’:‘yellow’, ‘pos’:(225, 80), ‘color’:button_colors[‘yellow’]},
{‘name’:‘pink’, ‘pos’:(15, 155), ‘color’:button_colors[‘pink’]},
{‘name’:‘green’, ‘pos’:(85, 155), ‘color’:button_colors[‘green’]},
{‘name’:‘blue’, ‘pos’:(155, 155), ‘color’:button_colors[‘blue’]},
{‘name’:‘purple’, ‘pos’:(225, 155), ‘color’:button_colors[‘purple’]}
]
# generate color buttons from color_btn list
for i in color_btn:
button = Button(x=i[‘pos’][0], y=i[‘pos’][1],
width=BUTTON_WIDTH, height=BUTTON_HEIGHT, name=i[‘name’],
fill_color=i[‘color’], style=Button.ROUNDRECT)
buttons.append(button)
# light property buttons and their properties
prop_btn = [
{‘name’:‘onoff’, ‘pos’:(15, 15), ‘label’:‘on/off’},
{‘name’:‘up’, ‘pos’:(75, 15), ‘label’:‘+’},
{‘name’:‘down’, ‘pos’:(135, 15), ‘label’:‘-’},
{‘name’:‘lamp’, ‘pos’:(195, 15), ‘label’:‘lamp’},
{‘name’:‘room’, ‘pos’:(245, 15), ‘label’:‘room’}
]
# generate property buttons from prop_btn list
for i in prop_btn:
button = Button(name=i[‘name’], x=i[‘pos’][0], y=i[‘pos’][1],
width=40, height=40, label=i[‘label’],
label_font=font, style=Button.SHADOWROUNDRECT)
buttons.append(button)
# add buttons to the group
for b in buttons:
button_group.append(b.group) # list of color buttons and their properties
color_btn = [
{‘name’:‘red’, ‘pos’:(15, 80), ‘color’:button_colors[‘red’]},
{‘name’:‘white’, ‘pos’:(85, 80), ‘color’:button_colors[‘white’]},
{‘name’:‘orange’, ‘pos’:(155, 80), ‘color’:button_colors[‘orange’]},
{‘name’:‘yellow’, ‘pos’:(225, 80), ‘color’:button_colors[‘yellow’]},
{‘name’:‘pink’, ‘pos’:(15, 155), ‘color’:button_colors[‘pink’]},
{‘name’:‘green’, ‘pos’:(85, 155), ‘color’:button_colors[‘green’]},
{‘name’:‘blue’, ‘pos’:(155, 155), ‘color’:button_colors[‘blue’]},
{‘name’:‘purple’, ‘pos’:(225, 155), ‘color’:button_colors[‘purple’]}
]
# generate color buttons from color_btn list
for i in color_btn:
button = Button(x=i[‘pos’][0], y=i[‘pos’][1],
width=BUTTON_WIDTH, height=BUTTON_HEIGHT, name=i[‘name’],
fill_color=i[‘color’], style=Button.ROUNDRECT)
buttons.append(button)
# light property buttons and their properties
prop_btn = [
{‘name’:‘onoff’, ‘pos’:(15, 15), ‘label’:‘on/off’},
{‘name’:‘up’, ‘pos’:(75, 15), ‘label’:‘+’},
{‘name’:‘down’, ‘pos’:(135, 15), ‘label’:‘-’},
{‘name’:‘lamp’, ‘pos’:(195, 15), ‘label’:‘lamp’},
{‘name’:‘room’, ‘pos’:(245, 15), ‘label’:‘room’}
]
# generate property buttons from prop_btn list
for i in prop_btn:
button = Button(name=i[‘name’], x=i[‘pos’][0], y=i[‘pos’][1],
width=40, height=40, label=i[‘label’],
label_font=font, style=Button.SHADOWROUNDRECT)
buttons.append(button)
# add buttons to the group
for b in buttons:
button_group.append(b.group)
下一段代码将为浅色和属性。
首先,创建与按钮属性相对应的词典项目列表。 color_btn列表包含按钮的信息,例如按钮的名称,在显示器上的位置以及十六进制颜色值。 prop_btn列表包含按钮的名称,位置和文本标签。
然后,按钮从列表中生成,并附加到button列表中。将所有按钮都添加到button列表后,它们将被一对一地附加到displayio button_group。
主循环
下载:文件
复制代码
while True:
touch = ts.touch_point
if touch:
for i, button in enumerate(buttons):
if button.contains(touch):
button.selected = True while True:
touch = ts.touch_point
if touch:
for i, button in enumerate(buttons):
if button.contains(touch):
button.selected = True
主循环检查是否屏幕被触摸。如果是,它将搜索button列表中的哪个按钮被触摸。
确定按钮后,将切换按钮的selected属性-反转按钮的颜色,直到操作已执行。这样,您正在创建视觉状态指示器。
下载:文件
复制代码
if button.name == ‘lamp’:
current_light = lifx_lights[0]
print(‘Switching to ’, current_light)
elif button.name == ‘room’:
current_light = lifx_lights[1]
print(‘Switching to ’, current_light) if button.name == ‘lamp’:
current_light = lifx_lights[0]
print(‘Switching to ’, current_light)
elif button.name == ‘room’:
current_light = lifx_lights[1]
print(‘Switching to ’, current_light)
然后,代码根据其功能检查按钮的名称(它的作用)。如果按钮的名称是灯或房间,则将current_light切换为按钮的值。
每当主循环中的代码向LIFX API发送数据以对灯执行操作时, ,它使用current_light变量选择灯光。
下载:文件
复制代码
elif button.name == ‘onoff’:
print(‘Toggling {0}。..’.format(current_light))
lifx.toggle_light(current_light)
elif button.name == ‘up’:
light_brightness += 0.25
print(‘Setting {0} brightness to {1}’.format(current_light, light_brightness))
lifx.set_brightness(current_light, light_brightness)
elif button.name == ‘down’:
light_brightness -= 0.25
print(‘Setting {0} brightness to {1}’.format(current_light, light_brightness))
lifx.set_brightness(current_light, light_brightness)
else:
print(‘Setting {0} color to {1}’.format(current_light, button.name))
lifx.set_color(current_light, ‘on’, button.name, light_brightness)
button.selected = False elif button.name == ‘onoff’:
print(‘Toggling {0}。..’.format(current_light))
lifx.toggle_light(current_light)
elif button.name == ‘up’:
light_brightness += 0.25
print(‘Setting {0} brightness to {1}’.format(current_light, light_brightness))
lifx.set_brightness(current_light, light_brightness)
elif button.name == ‘down’:
light_brightness -= 0.25
print(‘Setting {0} brightness to {1}’.format(current_light, light_brightness))
lifx.set_brightness(current_light, light_brightness)
else:
print(‘Setting {0} color to {1}’.format(current_light, button.name))
lifx.set_color(current_light, ‘on’, button.name, light_brightness)
button.selected = False
其余代码使用根据按钮的名称执行操作= 1》帮助程序模块。
按下开/关按钮-代码调用adafruit_lifx并传入lifx.toggle_light。
此按钮对应于LIFX远程API中定义的“切换电源”端点。
按下亮度按钮(+或-)时,代码将通过current_light和current_light转换为light_brightness。此外,每次按下按钮lifx.set_brightness时,递增或递减1/4。
此按钮对应于LIFX远程API中定义的“设置状态”端点。
如果按钮的名称与预定义的名称不对应,我们将使用按钮的名称作为传递给light_brightness的颜色来设置颜色。
此按钮对应于LIFX远程API中定义的“设置状态”端点。
您不受button_colors列表中定义的颜色的限制-您可以调整/混合颜色并将这些值发送到LIFX灯,请查看其网站上的颜色文档。
最后,代码将其selected属性设置为false,将其恢复为原始颜色以表示已执行操作。
进一步!
本指南仅刮擦了LIFX Light Remote HTTP API的表面。还有更多的端点,选项和效果可以使用。如果您有兴趣了解它的工作原理(更深层次),请查看帮助器库的存储库中的lifx.set_color文件。保持LIFX API网站在另一个选项卡中打开(作为参考)可能会有所帮助。
如果最终向库中添加了功能-感谢GitHub存储库上的拉取请求!
责任编辑:wv
全部0条评论
快来发表一下你的评论吧 !