0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

PyPortal气象站的制作教程

454398 来源:网络整理 作者:网络整理 2019-11-29 10:24 次阅读

概述

将这个紧凑的PyPortal气象站放在您的桌子上或固定在冰箱上,您将永远知道大自然的作用!

使用CircuitPython,该项目可查询Open Weather Maps网站API即可找到您所在位置的当前天气,并与信息图标一起显示。

3D打印盒和磁性衬里可将其安装到冰箱或其他黑色金属表面上。

Adafruit PyPortal-CircuitPython支持的Internet显示

产品ID:4116

PyPortal,我们易于使用的物联网设备这样您就可以在几分钟内为“物联网”创建所有事物。制作自定义触摸屏界面。..

$ 54.95

进货

添加到购物车

USB-A的5V 2A开关电源连接器

产品ID:1994

我们的5V 2A USB电源适配器是为Raspberry Pi,BeagleBone或其他需要耗电的单板计算机供电的理想选择! 。..

$ 7.95

入库价

添加到购物车

USB A/微型电缆-2m

产品ID:2185

这是您的标准USB A-Plugto Micro-USB电缆。它的长度为2米,因此对于那些较长的扩展名,您将拥有足够的绳索。

$ div 4.95

入库价

添加到购物车

其他工具和材料

您可能想为PyPortal Weather Station创建可选的安装盒。为此,您需要:

3D打印机

细丝

PyPortal Case模型文件

M2.5螺钉

如果您无权使用3D打印机,则可以选择使用在线服务(例如3D集线器)按需为您打印。

磁性回销

产品ID:1170

这些磁性回销具有两块:一根带有胶条的金属棒和一块带有两个强稀土磁体的塑料块。将金属栏粘贴到您的FLORA项目上-。..

$ 1.95

存货

添加到购物车

黑色尼龙螺丝和固定套件– M2.5螺纹

产品ID:3299

该M2.5螺丝套件总共380件,是您工作站上的必备工具。您将有足够的空间螺丝,螺母和六角形支脚来助您一臂之力。..

$ 16.95

进货

添加到购物车

Ultimaker 2+ 3D打印机

产品ID:2673

Ultimaker 2+是我们市场上最喜欢的3D打印机之一。这是一台构建良好的开源紧凑型计算机,具有出色的用户体验。每英寸。..

缺货

缺货

PLA灯丝3D打印机-直径2.85毫米-丁香-1千克

产品ID:3733

拥有没有灯丝的3D打印机就像是没有纸张或墨水的普通打印机。虽然许多打印机都带有一些灯丝,但很有可能。..

缺货

缺货股票

安装CircuitPython

CircuitPython是MicroPython的派生版,旨在简化低成本微控制器上的实验和教学。它不需要任何前期桌面软件下载,因此比以往任何时候都更容易获得原型。只需复制并编辑 CIRCUITPY “闪存”驱动器上的文件即可进行迭代。

以下说明将向您展示如何安装CircuitPython。如果您已经安装了CircuitPython,但希望对其进行更新或重新安装,则同样的步骤也适用!

设置CircuitPython快速入门!

请遵循以下快速逐步操作以获取超快速的Python功能:)

通过CircuitPython.org为该板下载最新版本的CircuitPython

点击上面的链接,为PyPortal下载最新版本的CircuitPython。

下载并将其保存到您的桌面(或方便的任何地方)。

使用已知良好的USB电缆将PyPortal插入计算机。

A很多人最终使用仅可充电的USB电缆,这非常令人沮丧!因此,请确保您拥有知道对数据同步有用的USB电缆。

双击中间顶部顶部的重置按钮(洋红色箭头)在板上,您将看到NeoPixel RGB LED(绿色箭头)变为绿色。如果它变成红色,请检查USB电缆,尝试使用另一个USB端口,等等。注意:USB接口旁边的红色小LED指示灯将呈红色闪烁。没关系!

如果第一次双击不起作用,请重试。有时可能需要一些尝试才能使节奏正确!

您将看到一个名为 PORTALBOOT 。

将 adafruit-circuitpython-pyportal- .uf2 文件拖到 PORTALBOOT。

LED将闪烁。然后, PORTALBOOT 驱动器将消失,并且将出现一个名为 CIRCUITPY 的新磁盘驱动器。

如果未在板上添加任何代码,唯一存在的文件是 boot_out.txt 。这是绝对正常的!是时候添加您的 code.py 并开始使用它了!

就这样,您完成了! :)

PyPortal默认文件

单击下面的按钮,下载PyPortal附带的文件的zip。

PyPortal默认文件

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代码

开放天气Maps API密钥

我们将使用OpenWeatherMaps.org通过其API检索天气信息。为此,您需要注册一个帐户并获取您的API密钥。

转到此链接并注册一个免费帐户。注册后,您会收到一封包含API密钥的电子邮件,也称为“ openweather令牌”。

将此密钥复制并粘贴到您的 secrets.py 文件中在CIRCUITPY驱动器的根目录上,因此如下所示:

下载:文件

复制代码

secrets = {

‘ssid’ : ‘your_wifi_ssid’,

‘password’ : ‘your_wifi_password’,

‘openweather_token’ : ‘xxxxxxxxxxxxxxxxxxxxxxxx’

}

secrets = {

‘ssid’ : ‘your_wifi_ssid’,

‘password’ : ‘your_wifi_password’,

‘openweather_token’ : ‘xxxxxxxxxxxxxxxxxxxxxxxx’

}

Adafruit IO时间服务器

为了获取准确的时间,我们的项目将查询Adafruit IO物联网服务的时间。 Adafruit IO是绝对免费的,但是您需要使用Adafruit帐户登录才能使用它。如果您还没有Adafruit登录名,请在此处创建一个登录名。

如果您以前从未使用过Adafruit IO,请查看本指南以获取更多信息。

登录到您的帐户后,您需要在secrets.py文件中放置以下两项信息: Adafruit IO用户名和 Adafruit IO键。前往io.adafruit.com,只需点击Adafruit IO页面左侧的查看AIO密钥链接即可获取此信息。

然后将它们添加到secrets.py文件如下:

下载:文件

复制代码

secrets = {

‘ssid’ : ‘your_wifi_ssid’,

‘password’ : ‘your_wifi_password’,

‘openweather_token’ : ‘xxxxxxxxxxxxxxxxxxxxxxxx’,

‘aio_username’ : ‘_your_aio_username_’,

‘aio_key’ : ‘_your_big_huge_super_long_aio_key_’

}

secrets = {

‘ssid’ : ‘your_wifi_ssid’,

‘password’ : ‘your_wifi_password’,

‘openweather_token’ : ‘xxxxxxxxxxxxxxxxxxxxxxxx’,

‘aio_username’ : ‘_your_aio_username_’,

‘aio_key’ : ‘_your_big_huge_super_long_aio_key_’

}

CircuitPython代码

在下面的嵌入式代码元素中,单击下载:Project Zip 链接,然后保存。 zip压缩文件到您的计算机。

然后解压缩.zip文件,它将解压缩到名为 PyPortal_OpenWeather 的文件夹中。

复制 PyPortal_OpenWeather 目录到PyPortal的 CIRCUITPY 驱动器,然后确保将 openweather.py 文件重命名为 code.py 》,因此它将在PyPortal重新启动时自动运行。

这是 CIRCUITPY 驱动器的最终内容,如下所示:

下载:项目Zip 或 openweather.py | 在Github上查看

复制代码

“”“

This example queries the Open Weather Maps site API to find out the current

weather for your location.。. and display it on a screen!

if you can find something that spits out JSON data, we can display it

”“”

import sys

import time

import board

from adafruit_pyportal import PyPortal

cwd = (“/”+__file__).rsplit(‘/’, 1)[0] # the current working directory (where this file is)

sys.path.append(cwd)

import openweather_graphics # pylint: disable=wrong-import-position

# 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

# Use cityname, country code where countrycode is ISO3166 format.

# E.g. “New York, US” or “London, GB”

LOCATION = “Manhattan, US”

# Set up where we‘ll be fetching data from

DATA_SOURCE = “http://api.openweathermap.org/data/2.5/weather?q=”+LOCATION

DATA_SOURCE += “&appid=”+secrets[’openweather_token‘]

# You’ll need to get a token from openweather.org, looks like ‘b6907d289e10d714a6e88b30761fae22’

DATA_LOCATION = []

# Initialize the pyportal object and let us know what data to fetch and where

# to display it

pyportal = PyPortal(url=DATA_SOURCE,

json_path=DATA_LOCATION,

status_neopixel=board.NEOPIXEL,

default_bg=0x000000)

gfx = openweather_graphics.OpenWeather_Graphics(pyportal.splash, am_pm=True, celsius=False)

localtile_refresh = None

weather_refresh = None

while True:

# only query the online time once per hour (and on first run)

if (not localtile_refresh) or (time.monotonic() - localtile_refresh) 》 3600:

try:

print(“Getting time from internet!”)

pyportal.get_local_time()

localtile_refresh = time.monotonic()

except RuntimeError as e:

print(“Some error occured, retrying! -”, e)

continue

# only query the weather every 10 minutes (and on first run)

if (not weather_refresh) or (time.monotonic() - weather_refresh) 》 600:

try:

value = pyportal.fetch()

print(“Response is”, value)

gfx.display_weather(value)

weather_refresh = time.monotonic()

except RuntimeError as e:

print(“Some error occured, retrying! -”, e)

continue

gfx.update_time()

time.sleep(30) # wait 30 seconds before updating anything again

“”“

This example queries the Open Weather Maps site API to find out the current

weather for your location.。. and display it on a screen!

if you can find something that spits out JSON data, we can display it

”“”

import sys

import time

import board

from adafruit_pyportal import PyPortal

cwd = (“/”+__file__).rsplit(‘/’, 1)[0] # the current working directory (where this file is)

sys.path.append(cwd)

import openweather_graphics # pylint: disable=wrong-import-position

# 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

# Use cityname, country code where countrycode is ISO3166 format.

# E.g. “New York, US” or “London, GB”

LOCATION = “Manhattan, US”

# Set up where we‘ll be fetching data from

DATA_SOURCE = “http://api.openweathermap.org/data/2.5/weather?q=”+LOCATION

DATA_SOURCE += “&appid=”+secrets[’openweather_token‘]

# You’ll need to get a token from openweather.org, looks like ‘b6907d289e10d714a6e88b30761fae22’

DATA_LOCATION = []

# Initialize the pyportal object and let us know what data to fetch and where

# to display it

pyportal = PyPortal(url=DATA_SOURCE,

json_path=DATA_LOCATION,

status_neopixel=board.NEOPIXEL,

default_bg=0x000000)

gfx = openweather_graphics.OpenWeather_Graphics(pyportal.splash, am_pm=True, celsius=False)

localtile_refresh = None

weather_refresh = None

while True:

# only query the online time once per hour (and on first run)

if (not localtile_refresh) or (time.monotonic() - localtile_refresh) 》 3600:

try:

print(“Getting time from internet!”)

pyportal.get_local_time()

localtile_refresh = time.monotonic()

except RuntimeError as e:

print(“Some error occured, retrying! -”, e)

continue

# only query the weather every 10 minutes (and on first run)

if (not weather_refresh) or (time.monotonic() - weather_refresh) 》 600:

try:

value = pyportal.fetch()

print(“Response is”, value)

gfx.display_weather(value)

weather_refresh = time.monotonic()

except RuntimeError as e:

print(“Some error occured, retrying! -”, e)

continue

gfx.update_time()

time.sleep(30) # wait 30 seconds before updating anything again

如果遇到任何错误,例如“ ImportError:没有名为`adafruit_display_text.label`的模块”,请确保将您的库更新到最新版本!

工作原理

PyPortal气象站有几个步骤可为您提供所需的信息!它具有启动屏幕,天气图标和多种用于显示信息的字体。

背景

首先,它将位图图形显示为屏幕的启动背景,直到连接到打开天气地图服务器以获取天气信息。这是 .bmp 格式的320 x 240像素RGB 16位光栅图形。

时间

接下来,该程序通过WiFi连接,通过adafruit.io服务器获取本地时间,该时间将显示在显示屏的右上角。

位置

在 code.py 文件(将从 openweather.py 重命名),您可以在此行中更改要显示天气的位置:

下载:文件

复制代码

# Use cityname, country code where countrycode is ISO3166 format.

# E.g. “New York, US” or “London, GB”

LOCATION = “Manhattan, US” # Use cityname, country code where countrycode is ISO3166 format.

# E.g. “New York, US” or “London, GB”

LOCATION = “Manhattan, US”

API查询和JSON

使用这些信息之后,代码即可将查询发送给看起来像是t的Open Weather Maps API他的:

http://api.openweathermap.org/data/2.5/weather?q=Los Angeles, US&appid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

(所有这些“ x”都是您的令牌)。

此查询完成后,它将返回JSON看起来像这样的文件:

下载:文件

复制代码

{

“coord”: {

“lon”: -118.24,

“lat”: 34.05

},

“weather”: [

{

“id”: 501,

“main”: “Rain”,

“description”: “moderate rain”,

“icon”: “10d”

}

],

“base”: “stations”,

“main”: {

“temp”: 287.42,

“pressure”: 1016,

“humidity”: 50,

“temp_min”: 285.15,

“temp_max”: 289.15

},

“visibility”: 16093,

“wind”: {

“speed”: 3.6,

“deg”: 300

},

“rain”: {

“1h”: 1.52

},

“clouds”: {

“all”: 75

},

“dt”: 1552073935,

“sys”: {

“type”: 1,

“id”: 3514,

“message”: 0.0087,

“country”: “US”,

“sunrise”: 1552054308,

“sunset”: 1552096542

},

“id”: 5368361,

“name”: “Los Angeles”,

“cod”: 200

}

{

“coord”: {

“lon”: -118.24,

“lat”: 34.05

},

“weather”: [

{

“id”: 501,

“main”: “Rain”,

“description”: “moderate rain”,

“icon”: “10d”

}

],

“base”: “stations”,

“main”: {

“temp”: 287.42,

“pressure”: 1016,

“humidity”: 50,

“temp_min”: 285.15,

“temp_max”: 289.15

},

“visibility”: 16093,

“wind”: {

“speed”: 3.6,

“deg”: 300

},

“rain”: {

“1h”: 1.52

},

“clouds”: {

“all”: 75

},

“dt”: 1552073935,

“sys”: {

“type”: 1,

“id”: 3514,

“message”: 0.0087,

“country”: “US”,

“sunrise”: 1552054308,

“sunset”: 1552096542

},

“id”: 5368361,

“name”: “Los Angeles”,

“cod”: 200

}

以下是使用Firefox浏览器的内置工具美化的同一文件(您也可以使用在线代码“美化器”,例如https://codebeautify.org/jsonviewer或http://jsonviewer.stack.hu):

JSON遍历

JSON文件的格式设置使其可以轻松遍历层次结构和解析数据。在其中,您将看到诸如main,description,icon和temp之类的键及其各自的值。因此,以下是气象站需要关注的一些 key:value 对:

“main” : “Rain”

“description” : “moderate rain”

“icon” : “10d”

“temp” : “287.42”

为了从文件中获取此数据,我们需要能够分层描述它们在文件中的位置。例如,这有助于区分‘main’天气状况和包含温度和其他数据的‘main’部分。为了避免名称冲突,我们依靠JSON遍历。

在 openweather_graphics.py 文件中,您将看到如何完成此操作。例如,可以在以下JSON文件层次结构中找到主键:[‘weather’], [0], [‘main’]

这意味着在JSON文件的顶层有一个名为‘weather’的键,该键有一个索引为[0]的子树,然后在其下面为‘main’键。

此过程用于投射温度,天气,描述以及从位图图标目录中显示的图标。

这些是表示的图标:

字体

数据以使用位图字体创建的文本显示为叠加在背景上。这里使用的字体是由Arial字体制成的位图字体。您可以在本指南中了解有关转换类型的更多信息。

PyPortal构造函数

设置pyportal构造函数时,我们将为它们提供以下内容:

url进行查询

json_path遍历并找到我们需要的键:值对

default_bg默认背景色

获取

设置PyPortal之后,我们可以使用pyportal.fetch()进行天气数据的查询和解析,然后将其显示在屏幕上。

解析数据并将其显示为文本或位图的所有繁重工作都在 openweather_graphics.py 代码。

图形

让我们看看 openweather_graphics.py 代码如何将元素放置在屏幕上。在下面,我们可以看到显示的图标和文本。引号中的项目是JSON文件中的键名,它们的值是我们使用CircuitPython label库看到的内容。

下载:Zip项目或 openweather_graphics.py | 在Github上查看

复制代码

import time

import json

import displayio

from adafruit_display_text.label import Label

from adafruit_bitmap_font import bitmap_font

cwd = (“/”+__file__).rsplit(‘/’, 1)[0] # the current working directory (where this file is)

small_font = cwd+“/fonts/Arial-12.bdf”

medium_font = cwd+“/fonts/Arial-16.bdf”

large_font = cwd+“/fonts/Arial-Bold-24.bdf”

class OpenWeather_Graphics(displayio.Group):

def __init__(self, root_group, *, am_pm=True, celsius=True):

super().__init__(max_size=2)

self.am_pm = am_pm

self.celsius = celsius

root_group.append(self)

self._icon_group = displayio.Group(max_size=1)

self.append(self._icon_group)

self._text_group = displayio.Group(max_size=5)

self.append(self._text_group)

self._icon_sprite = None

self._icon_file = None

self.set_icon(cwd+“/weather_background.bmp”)

self.small_font = bitmap_font.load_font(small_font)

self.medium_font = bitmap_font.load_font(medium_font)

self.large_font = bitmap_font.load_font(large_font)

glyphs = b‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,。: ’

self.small_font.load_glyphs(glyphs)

self.medium_font.load_glyphs(glyphs)

self.large_font.load_glyphs(glyphs)

self.large_font.load_glyphs((‘°’,)) # a non-ascii character we need for sure

self.city_text = None

self.time_text = Label(self.medium_font, max_glyphs=8)

self.time_text.x = 200

self.time_text.y = 12

self.time_text.color = 0xFFFFFF

self._text_group.append(self.time_text)

self.temp_text = Label(self.large_font, max_glyphs=6)

self.temp_text.x = 200

self.temp_text.y = 195

self.temp_text.color = 0xFFFFFF

self._text_group.append(self.temp_text)

self.main_text = Label(self.large_font, max_glyphs=20)

self.main_text.x = 10

self.main_text.y = 195

self.main_text.color = 0xFFFFFF

self._text_group.append(self.main_text)

self.description_text = Label(self.small_font, max_glyphs=60)

self.description_text.x = 10

self.description_text.y = 225

self.description_text.color = 0xFFFFFF

self._text_group.append(self.description_text)

def display_weather(self, weather):

weather = json.loads(weather)

# set the icon/background

weather_icon = weather[‘weather’][0][‘icon’]

self.set_icon(cwd+“/icons/”+weather_icon+“.bmp”)

city_name = weather[‘name’] + “, ” + weather[‘sys’][‘country’]

print(city_name)

if not self.city_text:

self.city_text = Label(self.medium_font, text=city_name)

self.city_text.x = 10

self.city_text.y = 12

self.city_text.color = 0xFFFFFF

self._text_group.append(self.city_text)

self.update_time()

main_text = weather[‘weather’][0][‘main’]

print(main_text)

self.main_text.text = main_text

temperature = weather[‘main’][‘temp’] - 273.15 # its.。.in kelvin

print(temperature)

if self.celsius:

self.temp_text.text = “%d °C” % temperature

else:

self.temp_text.text = “%d °F” % ((temperature * 9 / 5) + 32)

description = weather[‘weather’][0][‘description’]

description = description[0].upper() + description[1:]

print(description)

self.description_text.text = description

# “thunderstorm with heavy drizzle”

def update_time(self):

“”“Fetch the time.localtime(), parse it out and update the display text”“”

now = time.localtime()

hour = now[3]

minute = now[4]

format_str = “%d:%02d”

if self.am_pm:

if hour 》= 12:

hour -= 12

format_str = format_str+“ PM”

else:

format_str = format_str+“ AM”

if hour == 0:

hour = 12

time_str = format_str % (hour, minute)

print(time_str)

self.time_text.text = time_str

def set_icon(self, filename):

“”“The background image to a bitmap file.

:param filename: The filename of the chosen icon

”“”

print(“Set icon to ”, filename)

if self._icon_group:

self._icon_group.pop()

if not filename:

return # we‘re done, no icon desired

if self._icon_file:

self._icon_file.close()

self._icon_file = open(filename, “rb”)

icon = displayio.OnDiskBitmap(self._icon_file)

try:

self._icon_sprite = displayio.TileGrid(icon,

pixel_shader=displayio.ColorConverter())

except TypeError:

self._icon_sprite = displayio.TileGrid(icon,

pixel_shader=displayio.ColorConverter(),

position=(0,0))

self._icon_group.append(self._icon_sprite)

import time

import json

import displayio

from adafruit_display_text.label import Label

from adafruit_bitmap_font import bitmap_font

cwd = (“/”+__file__).rsplit(’/‘, 1)[0] # the current working directory (where this file is)

small_font = cwd+“/fonts/Arial-12.bdf”

medium_font = cwd+“/fonts/Arial-16.bdf”

large_font = cwd+“/fonts/Arial-Bold-24.bdf”

class OpenWeather_Graphics(displayio.Group):

def __init__(self, root_group, *, am_pm=True, celsius=True):

super().__init__(max_size=2)

self.am_pm = am_pm

self.celsius = celsius

root_group.append(self)

self._icon_group = displayio.Group(max_size=1)

self.append(self._icon_group)

self._text_group = displayio.Group(max_size=5)

self.append(self._text_group)

self._icon_sprite = None

self._icon_file = None

self.set_icon(cwd+“/weather_background.bmp”)

self.small_font = bitmap_font.load_font(small_font)

self.medium_font = bitmap_font.load_font(medium_font)

self.large_font = bitmap_font.load_font(large_font)

glyphs = b’0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,。: ‘

self.small_font.load_glyphs(glyphs)

self.medium_font.load_glyphs(glyphs)

self.large_font.load_glyphs(glyphs)

self.large_font.load_glyphs((’°‘,)) # a non-ascii character we need for sure

self.city_text = None

self.time_text = Label(self.medium_font, max_glyphs=8)

self.time_text.x = 200

self.time_text.y = 12

self.time_text.color = 0xFFFFFF

self._text_group.append(self.time_text)

self.temp_text = Label(self.large_font, max_glyphs=6)

self.temp_text.x = 200

self.temp_text.y = 195

self.temp_text.color = 0xFFFFFF

self._text_group.append(self.temp_text)

self.main_text = Label(self.large_font, max_glyphs=20)

self.main_text.x = 10

self.main_text.y = 195

self.main_text.color = 0xFFFFFF

self._text_group.append(self.main_text)

self.description_text = Label(self.small_font, max_glyphs=60)

self.description_text.x = 10

self.description_text.y = 225

self.description_text.color = 0xFFFFFF

self._text_group.append(self.description_text)

def display_weather(self, weather):

weather = json.loads(weather)

# set the icon/background

weather_icon = weather[’weather‘][0][’icon‘]

self.set_icon(cwd+“/icons/”+weather_icon+“.bmp”)

city_name = weather[’name‘] + “, ” + weather[’sys‘][’country‘]

print(city_name)

if not self.city_text:

self.city_text = Label(self.medium_font, text=city_name)

self.city_text.x = 10

self.city_text.y = 12

self.city_text.color = 0xFFFFFF

self._text_group.append(self.city_text)

self.update_time()

main_text = weather[’weather‘][0][’main‘]

print(main_text)

self.main_text.text = main_text

temperature = weather[’main‘][’temp‘] - 273.15 # its.。.in kelvin

print(temperature)

if self.celsius:

self.temp_text.text = “%d °C” % temperature

else:

self.temp_text.text = “%d °F” % ((temperature * 9 / 5) + 32)

description = weather[’weather‘][0][’description‘]

description = description[0].upper() + description[1:]

print(description)

self.description_text.text = description

# “thunderstorm with heavy drizzle”

def update_time(self):

“”“Fetch the time.localtime(), parse it out and update the display text”“”

now = time.localtime()

hour = now[3]

minute = now[4]

format_str = “%d:%02d”

if self.am_pm:

if hour 》= 12:

hour -= 12

format_str = format_str+“ PM”

else:

format_str = format_str+“ AM”

if hour == 0:

hour = 12

time_str = format_str % (hour, minute)

print(time_str)

self.time_text.text = time_str

def set_icon(self, filename):

“”“The background image to a bitmap file.

:param filename: The filename of the chosen icon

”“”

print(“Set icon to ”, filename)

if self._icon_group:

self._icon_group.pop()

if not filename:

return # we’re done, no icon desired

if self._icon_file:

self._icon_file.close()

self._icon_file = open(filename, “rb”)

icon = displayio.OnDiskBitmap(self._icon_file)

try:

self._icon_sprite = displayio.TileGrid(icon,

pixel_shader=displayio.ColorConverter())

except TypeError:

self._icon_sprite = displayio.TileGrid(icon,

pixel_shader=displayio.ColorConverter(),

position=(0,0))

self._icon_group.append(self._icon_sprite)

文本位置

取决于背景位图的设计和所显示文本的长度,您可能需要重新定位文本和标题。

PyPortal的显示为宽320像素,高240像素。为了引用屏幕上的这些位置,我们使用x/y坐标系,其中x为水平,y为垂直。

此坐标系的原点是左上角。这意味着放在左上角的像素为(0,0),而位于右下角的像素为(320,240)。

因此,如果您想将订户计数文本向右移动并更靠近在顶部,您的代码对于pyportal构造函数的该部分可能是这样的:text_position=(250, 10)

文本颜色

自定义显示的另一种方法是调整文本的颜色。构造函数中的text_color=0xFFFFFF行显示了操作方法。您需要为要显示的任何颜色使用十六进制值。

在此示例中,您可以使用https://htmlcolorcodes.com/之类的颜色来选择颜色,然后复制十六进制值。它应该是0x0ED9EE

现在,我们来看将PyPortal安装到要显示的盒子中!

PyPortal气象站案例

我决定使用Ruiz Bros.设计的便携式PyPortal箱作为外壳。您可以转到本指南来构建它-通过自己进行3D打印或发送到3DHubs等服务。

我不需要此便携式设备,因此省略了PowerBoost,电池,扬声器和开关。

我使用了所有相同的3D零件,并将安装座拧在一起,然后将顶部和底部卡入到位。

磁铁

我想将PyPortal气象站安装在冰箱上,所以我要固定磁铁。

磁铁

使用一块双面胶带将胶带固定到外壳上,如图所示。

我在我的工作台抽屉,效果很好!是时候将其放在冰箱上并插入电源了!

现在,每30秒,您的气象站将更新为最新信息!
责任编辑:wv

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 气象站
    +关注

    关注

    1

    文章

    710

    浏览量

    15412
收藏 人收藏

    评论

    相关推荐

    便携式气象站:科技与便捷的完美融合

    气象站
    万象环境科技
    发布于 :2024年06月22日 21:14:07

    校园气象站组成与作用

    对于校园气象站,相信很多人都不陌生,主要作用是用于监测气象要素信息。校园气象站作为学校教学研究的器材,可监测校园气象,为学校提供参考数据,也可以锻炼学生的动手能力。对青少年的
    的头像 发表于 10-31 16:28 436次阅读

    #移动气象站# 扬尘监测# 车载气象站 车载扬尘监测站

    监测气象站
    pgz1234
    发布于 :2023年09月18日 08:52:32

    负氧离子在线监测系统# 气象站# #气象监测

    监测气象站
    pgz1234
    发布于 :2023年09月18日 08:50:51

    什么是气象站气象站的简介

    什么是气象站气象站的简介
    的头像 发表于 09-14 16:14 1042次阅读

    气象站是什么设备?功能是什么?

    气象站是什么设备?功能是什么?
    的头像 发表于 09-05 14:38 615次阅读

    校园气象站的功能和作用

    校园气象站是一种用于监测和记录气象数据的设备,下面将从功能和作用两个方面来详细介绍校园气象站。 一、校园气象站的功能 ①气象数据监测 校园
    的头像 发表于 09-01 17:11 609次阅读

    地面气象站:守护地球的气象卫士

    地面气象站
    的头像 发表于 08-31 16:58 386次阅读

    地面气象站——综合监测、实时气象

    地面气象站
    的头像 发表于 08-31 15:55 371次阅读

    关于农林气象站的基本介绍

    关于农林气象站的基本介绍
    的头像 发表于 08-23 16:58 305次阅读

    林业气象站——林业种植气象观测

    林业气象站——林业种植气象观测
    的头像 发表于 08-23 16:32 296次阅读

    为什么要建设校园气象站

    校园气象站
    的头像 发表于 08-21 15:50 321次阅读

    光伏气象站是什么

    光伏气象站作为现代气象观测的重要工具,为气象学、农业、航空、环境科学和能源等领域的研究和应用提供了气象数据,是辅助指导生产生活的重要设施。 传统的手工
    的头像 发表于 08-14 16:36 550次阅读

    自动气象站是什么,自动气象站的功能特点

    自动气象站是一款自动监测记录气象信息的仪器,自动气象站能够自动监测和记录气象信息,如温度、湿度、气压、风速、风向、降水量等,为气象学研究和
    的头像 发表于 07-27 11:10 1104次阅读
    自动<b class='flag-5'>气象站</b>是什么,自动<b class='flag-5'>气象站</b>的功能特点