概述
想為您的房間添加獨特的照明嗎?
一個簡單的解決方案是添加幾個具有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文章
10瀏覽量
9413
發布評論請先 登錄
相關推薦
評論