1. 项目概述打造你的家庭物联网控制中心几年前当我第一次接触家庭自动化时面对的是一堆零散的设备、复杂的协议和难以统一的控制界面。要么是功能单一的智能插座要么是需要复杂编程的传感器模块想要一个能集中显示、又能灵活控制的中枢往往需要自己从零搭建服务器过程繁琐且维护成本高。直到我遇到了 Adafruit FunHouse 这块开发板配合 CircuitPython 和 Adafruit IO 平台才真正找到了一个兼顾灵活性、易用性和美观度的解决方案。这个项目的核心就是利用 Adafruit FunHouse 作为硬件终端在其自带的彩色屏幕上构建一个完全可定制的物联网仪表盘。这个仪表盘并非简单的信息显示器而是一个双向交互的控制中心。它能够从连接的传感器如温湿度、门磁实时读取数据并上传到云端同时也能接收来自云端仪表盘的指令去控制继电器开关灯、调整 NeoPixel 灯带的颜色。所有逻辑都运行在 FunHouse 这块小小的开发板上通过 WiFi 与 Adafruit IO 云服务通信而你在世界任何地方都能通过网页仪表盘看到数据并下发控制命令。它适合谁如果你是一名创客、嵌入式爱好者或者是对智能家居感兴趣、希望摆脱成品设备限制的开发者这个项目再合适不过。它不需要你精通复杂的网络协议或搭建后端服务CircuitPython 的语法接近 Python极易上手Adafruit IO 提供了开箱即用的数据流和可视化组件。整个项目就像搭积木一样将硬件模块、控制逻辑和云端界面连接起来。即使你只有基础的编程知识也能跟随本教程在周末下午搭建起一个属于自己的、功能独特的家庭物联网枢纽。2. 核心硬件与平台选型解析为什么是 Adafruit FunHouse CircuitPython Adafruit IO 这个组合这背后是基于快速原型开发、降低复杂度和提升可维护性等多方面的考量。让我们拆解每一个环节的选择逻辑。2.1 硬件核心Adafruit FunHouse 开发板Adafruit FunHouse 并非一块普通的微控制器板它是一个为家庭自动化场景深度优化的开发平台。选择它意味着我们跳过了大量基础硬件搭建工作。集成度极高板载了 ESP32-S2 WiFi 芯片、3.5英寸彩色触摸屏、温湿度传感器AHT20、气压传感器DPS310、三个电容触摸按钮、五个物理按钮、一个滑动电位器、一个 PIR 运动传感器、一个蜂鸣器以及一串 DotStar RGB LED。这意味着要实现一个基础的环境监测站你几乎不需要连接任何外部传感器。对于本项目我们主要利用其屏幕显示仪表盘、WiFi联网、物理按钮本地交互和传感器采集数据。强大的连接性除了板载资源FunHouse 还提供了 STEMMA QT 连接器。这是一种防反插、即插即用的连接标准极大简化了与外围传感器、执行器的连接。你不需要焊接只需要使用配套的 STEMMA QT 线缆就能像拼乐高一样扩展设备如教程中提到的继电器模块、NeoPixel 灯带等。这保证了项目的整洁性和可扩展性。充足的算力与存储ESP32-S2 主控提供了足够的性能来运行 CircuitPython 解释器、处理传感器数据、驱动屏幕图形并通过 MQTT 协议与云端保持稳定通信。内置的存储也足以存放项目代码和必要的库文件。注意虽然教程提到未来可能支持 PyPortal 等带屏板卡但目前adafruit_dash_display库仅针对 FunHouse 优化。如果你使用其他板卡可能需要自行适配屏幕驱动和布局代码。2.2 软件基石CircuitPython 与相关库在嵌入式开发中我们常面临 C/C 开发周期长、调试困难的问题。CircuitPython 的出现改变了这一局面。极速开发迭代CircuitPython 将板子变成一个名为CIRCUITPY的 U 盘。编写代码只需用任何文本编辑器修改code.py文件保存后板子会自动重启运行新代码。这种“编辑-保存-运行”的循环比传统的“编译-烧录-调试”模式快了几个数量级特别适合原型验证和功能迭代。丰富的硬件抽象库Adafruit 为 CircuitPython 维护了庞大的“驱动”库生态。例如adafruit_funhouse库封装了所有板载硬件的操作adafruit_io库处理与云平台的通信adafruit_minimqtt库实现 MQTT 协议。我们无需关心底层寄存器或通信细节只需调用高级 API如funhouse.peripherals.temperature读取温度io.publish(‘temperature‘, temp_value)上传数据极大提升了开发效率。关键库清单与作用库名称作用本项目中的用途adafruit_funhouseFunHouse 板级支持库管理屏幕、按钮、传感器等所有板载功能adafruit_portalbase带屏设备的基础库adafruit_funhouse的依赖提供显示框架adafruit_dash_display核心仪表盘显示库在 FunHouse 屏幕上绘制和更新仪表盘UIadafruit_ioAdafruit IO 客户端库管理数据流Feed、仪表盘Dashboard连接adafruit_minimqttMQTT 客户端库与 Adafruit IO 的 MQTT 代理进行轻量级通信adafruit_display_text文本显示库在屏幕上渲染文字adafruit_bitmap_font字体库支持自定义字体显示adafruit_requestsHTTP 客户端库用于初始时间同步等 HTTP 请求2.3 云端大脑Adafruit IO 平台物联网项目离不开“云”。Adafruit IO 是一个为物联网设备量身定制的数据托管与可视化平台。数据流Feed这是 Adafruit IO 的核心概念你可以把它理解为一个专属的数据通道。我们为每个需要监控或控制的数据点创建一个 Feed例如temperature、lamp。设备向 Feed 发布数据仪表盘从 Feed 订阅数据。它自动存储历史数据并处理数据的订阅/发布。仪表盘Dashboard数据的可视化界面。你可以通过拖拽方式将不同的“模块”Block如开关、图表、数字显示、颜色选择器等添加到仪表盘上并将每个模块绑定到一个特定的 Feed。这样数据就变成了直观的控件和图表。通信协议MQTT/HTTPAdafruit IO 支持 MQTT 和 HTTP 两种协议。MQTT 特别适合本项目因为它是一种基于发布/订阅模式的轻量级消息协议专为低带宽、高延迟或不稳定的网络环境设计。设备可以长期保持一个到 MQTT 代理的连接有数据时立即推送有命令时即时接收通信效率高功耗相对较低。这正是 FunHouse 作为常电设备理想的通信方式。免费与易用性Adafruit IO 提供免费的入门套餐对于个人项目和小型应用完全足够。其 Web 界面直观大大降低了构建云端监控系统的门槛。三者协作流程FunHouse硬件运行 CircuitPython软件通过adafruit_io和adafruit_minimqtt库将传感器数据发布到 Adafruit IO云端对应的 Feed。同时它订阅那些控制类 Feed如lamp,neopixel。当你在 Adafruit IO 网页仪表盘上操作开关或颜色选择器时指令会通过 MQTT 下发到 FunHouseFunHouse 再控制继电器或灯带执行动作。整个链路清晰、高效、解耦。3. 从零开始的详细搭建流程理论清晰后我们进入实战环节。我将带你一步步完成从硬件上电到仪表盘运行的完整过程。请准备好你的 FunHouse、USB-C 数据线以及可用的 WiFi 网络。3.1 第一步为 FunHouse 刷入 CircuitPythonFunHouse 出厂可能运行其他固件我们需要先将其转换为 CircuitPython 环境。下载固件访问 circuitpython.org/downloads 搜索 “FunHouse”下载最新的.uf2固件文件。.uf2格式是最简单的安装方式。进入 Bootloader 模式使用 USB-C 线连接 FunHouse 和电脑。快速双击板子上的RESET按钮位于 USB-C 口旁边。此时板载的 DotStar LED 会呈现紫色闪烁电脑上会出现一个名为HOUSEBOOT的磁盘驱动器。拖放固件将下载好的.uf2文件直接拖拽或复制到HOUSEBOOT磁盘中。复制完成后HOUSEBOOT磁盘会消失稍等片刻电脑上会出现一个新的名为CIRCUITPY的磁盘。这表明 CircuitPython 已成功刷入。实操心得双击 RESET 键的时机需要练习如果第一次没成功没出现HOUSEBOOT盘多试几次。成功进入 Bootloader 后DotStar LED 的紫色呼吸灯效是一个明确的视觉指示。3.2 第二步配置网络与 Adafruit IO 密钥要让设备上网并连接云端需要配置 WiFi 信息和 Adafruit IO 的访问凭证。CircuitPython 使用一个名为settings.toml的配置文件来安全地管理这些敏感信息。创建/编辑 settings.toml在电脑上打开CIRCUITPY磁盘用文本编辑器如 VS Code, Notepad创建或打开settings.toml文件。填入配置信息将以下内容复制到文件中并替换为你自己的信息。# 你的 WiFi 网络名称和密码 CIRCUITPY_WIFI_SSID 你的WiFi名称 CIRCUITPY_WIFI_PASSWORD 你的WiFi密码 # 你的 Adafruit IO 账户信息注册是免费的 ADAFRUIT_AIO_USERNAME 你的Adafruit IO用户名 ADAFRUIT_AIO_KEY 你的Adafruit IO Active Key # 可选你的时区用于获取本地时间。可从 http://worldtimeapi.org/timezones 查找 TIMEZONE Asia/Shanghai获取 Adafruit IO Key登录 io.adafruit.com 点击右上角的 “My Key”。在弹出的窗口中你会看到Username和Active Key。将它们分别填入上面的配置中。重要安全提示settings.toml文件包含了你的密码和密钥。切勿将此文件上传到 GitHub 等公开代码仓库。在分享项目时只分享code.py等代码文件。3.3 第三步安装必要的 CircuitPython 库CIRCUITPY磁盘里有一个lib文件夹我们需要将项目依赖的库文件放进去。下载库合集访问 circuitpython.org/libraries 下载最新版本的 “Adafruit CircuitPython Library Bundle” 选择.mpy格式的版本体积更小运行更快。提取并复制库解压下载的 zip 文件。根据项目要求我们需要将以下库文件或文件夹从解压包的lib文件夹中复制到CIRCUITPY磁盘的lib文件夹里adafruit_funhouse/(整个文件夹)adafruit_portalbase/(整个文件夹)adafruit_dash_display/(整个文件夹)adafruit_io/(整个文件夹)adafruit_minimqtt/(整个文件夹)adafruit_display_text/(整个文件夹)adafruit_bitmap_font/(整个文件夹)adafruit_requests.mpy(单个文件)adafruit_dps310.mpy(气压传感器驱动)adafruit_ahtx0.mpy(温湿度传感器驱动)adafruit_dotstar.mpy(DotStar LED驱动)simpleio.mpy(简单IO操作用于蜂鸣器)3.4 第四步在 Adafruit IO 上创建数据流与仪表盘这是配置云端部分。我们需要创建与代码对应的数据流和可视化仪表盘。创建数据流Feeds在 Adafruit IO 网站进入 “Feeds” 页面。点击 “New Feed”依次创建以下7个数据流temperature(温度)humidity(湿度)heatindex(体感温度)door(门磁状态)lamp(灯开关)neopixel(灯带颜色)battery(电池电量)创建仪表盘Dashboard并添加模块进入 “Dashboards” 页面创建新仪表盘例如命名为 “Home Hub”。进入该仪表盘点击右上角的齿轮图标选择 “Create New Block”。添加 Toggle 模块选择 “Toggle” 类型关联到lampfeed。设置 On Text 为TrueOff Text 为False标题设为 “Lamp”。添加 Text 模块选择 “Text” 类型关联到temperaturefeed。设置小数位为1勾选 “Show Icon”图标选择 “thermometer”。用同样方法为humidity和heatindex创建 Text 模块图标分别选 “w:humidity” 和 “w:thermometer-exterior”。添加 Color Picker 模块选择 “Color Picker” 类型关联到neopixelfeed。添加 Gauge 模块选择 “Gauge” 类型关联到batteryfeed。设置标题为 “Battery”低电量警告值设为20。添加 Indicator 模块选择 “Indicator” 类型关联到doorfeed。设置标题为 “Door”条件为 “equals 1”表示门开。所有模块添加完成后点击 “Edit Layout” 可以拖拽调整它们的位置和大小排布成你喜欢的布局。3.5 第五步部署并运行项目代码最后一步将大脑程序注入硬件。获取项目代码从 Adafruit 学习系统的项目页面原教程链接下载 “Project Bundle”。解压后你会找到核心的code.py文件。部署代码将code.py文件复制到CIRCUITPY磁盘的根目录覆盖原有的文件。重启与运行复制完成后FunHouse 会自动重启。几秒钟后屏幕应该亮起显示一个包含温度、湿度、体感温度、电池电量如果连接了电池、门状态等信息的仪表盘界面。同时板载的 WiFi LED 应开始闪烁表示正在连接网络和 Adafruit IO。此时打开 Adafruit IO 上你创建的仪表盘网页应该能看到数据正在从 FunHouse 同步上来。尝试点击网页上的 “Lamp” 开关或者调整颜色选择器观察 FunHouse 屏幕上的对应显示是否更新。如果连接了外部继电器和灯带它们也应该响应你的控制。4. 项目代码深度解析与自定义指南仅仅让项目跑起来还不够理解其工作原理才能进行真正的自定义。让我们深入核心代码看看这个物联网枢纽是如何运作的。4.1 代码结构概览主程序code.py通常遵循一个清晰的循环结构我将其概括为以下几个阶段初始化阶段导入库、初始化硬件对象FunHouse、连接 WiFi、连接到 Adafruit IO 的 MQTT 服务。仪表盘UI定义阶段使用adafruit_dash_display库定义屏幕上各个显示元素称为 “Tile”的位置、样式和绑定的数据源即 Adafruit IO 的 Feed。主循环阶段数据发布定期例如每30秒读取板载传感器温湿度、气压数据通过 MQTT 发布到对应的 Adafruit IO Feed。命令处理监听 MQTT 订阅的 Feed如lamp,neopixel。当云端仪表盘有控制指令下发时触发相应的回调函数执行开关继电器、改变灯带颜色等操作。UI更新根据最新的本地或云端数据刷新屏幕上的各个 Tile 的显示内容。本地交互检测板载物理按钮的按压实现本地控制功能如切换显示页面、手动开关灯。4.2 关键代码片段解读让我们看几个核心部分的代码逻辑连接 Adafruit IO 与 MQTT# 初始化 FunHouse 对象它会自动读取 settings.toml 中的配置 funhouse adafruit_funhouse.FunHouse() # 连接到 WiFi funhouse.network.connect() # 初始化 Adafruit IO MQTT 客户端 io adafruit_io.adafruit_io.MQTTClient(funhouse.network._wifi.radio, ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY) # 定义收到消息时的回调函数 def message(client, feed_id, payload): if feed_id ‘lamp‘: # 控制继电器开关 relay.value (payload “True”) elif feed_id ‘neopixel‘: # 解析颜色值并设置 NeoPixel # ... 颜色解析代码 ... # 将回调函数分配给客户端 io.on_message message # 连接到 Adafruit IO MQTT 服务器并订阅感兴趣的 Feed io.connect() io.subscribe(adafruit_io.adafruit_io.MQTTClient.FEEDS[‘lamp‘]) io.subscribe(adafruit_io.adafruit_io.MQTTClient.FEEDS[‘neopixel‘])这段代码建立了设备与云端的双向通信通道。io.subscribe使设备能接收特定 Feed 的更新而io.publish则用于发送数据。定义仪表盘 Tile# 创建 DashDisplay 对象关联到 funhouse 的屏幕和网络 dash adafruit_dash_display.DashDisplay(funhouse.display, funhouse.network) # 添加一个文本 Tile 来显示温度 temp_tile adafruit_dash_display.TileText( x10, y30, # 屏幕坐标 width100, height40, # 区域大小 label_text“Temp:“, # 标签 label_color0xFFFFFF, # 标签颜色 (白色) value_text“--.-“, # 初始值 value_color0x00FF00, # 数值颜色 (绿色) feed_key“temperature“, # 绑定的 Adafruit IO Feed 键名 value_format“{:.1f}°C“, # 数值格式化字符串 ) dash.add_tile(temp_tile, “main_group“) # 将 Tile 添加到名为 “main_group“ 的页面adafruit_dash_display库的核心是Tile对象。每种 Tile文本、图标、滑块等负责显示一种类型的信息。feed_key是关键它将该 Tile 与一个 Adafruit IO Feed 动态绑定。当 Feed 有更新时Tile 会自动刷新显示。4.3 如何添加你自己的设备教程提供了继电器、NeoPixel、电池充电器等示例。添加新设备的通用模式如下在 Adafruit IO 创建新 Feed例如你想增加一个土壤湿度传感器就创建一个soil_moistureFeed。在仪表盘添加对应模块在网页仪表盘上添加一个 Gauge 或 Text 模块绑定到soil_moisture。硬件连接将土壤湿度传感器通过 STEMMA QT 或 GPIO 口连接到 FunHouse。修改代码初始化在代码开头初始化你的传感器对象。数据发布在主循环的数据发布部分添加读取该传感器并发布到soil_moistureFeed 的逻辑。UI 更新在仪表盘定义部分添加一个新的Tile来显示土壤湿度并将其feed_key设为”soil_moisture“。如果是控制类设备命令订阅与处理如果是继电器等执行器需要创建控制 Feed如pump在代码中订阅它并在message回调函数中添加处理pump消息的逻辑。实操心得在修改代码时建议先单独测试传感器读取或执行器控制功能确保硬件和基础驱动工作正常再将其集成到主循环和 MQTT 通信框架中。这样可以有效隔离问题。5. 外围设备连接示例与避坑指南原教程提到了几种外围设备示例。这里我以最常用的继电器控制和NeoPixel 灯带为例详细说明连接和代码集成中的关键点。5.1 继电器控制以控制台灯为例硬件连接 使用STEMMA QT 继电器模块如 Adafruit #3191。用一根 STEMMA QT 线缆一端连接 FunHouse 上的任意一个 STEMMA QT 端口另一端连接继电器模块。将台灯的电源线切断其中一根线串联到继电器的常开NO和公共端COM接口上。代码集成要点初始化继电器在代码中继电器通常被定义为数字输出对象。虽然通过 STEMMA QTI2C连接但继电器模块本质是控制一个GPIO。import board import digitalio relay digitalio.DigitalInOut(board.A0) # 假设继电器信号线接在A0引脚 relay.direction digitalio.Direction.OUTPUTMQTT 回调控制在message函数中处理lampfeed 的消息。def message(client, feed_id, payload): print(f“Received ‘{payload}‘ from ‘{feed_id}‘“) if feed_id ‘lamp‘: # Adafruit IO Toggle 模块发送的是字符串 “True“ 或 “False“ if payload “True“: relay.value True print(“Lamp ON“) else: relay.value False print(“Lamp OFF“)状态同步为了更好的用户体验可以在继电器状态变化时也向lampfeed 发布当前状态确保云端仪表盘开关的显示与实际状态一致。避坑指南继电器模块有高电平触发和低电平触发之分。务必查阅你的继电器模块数据手册。如果接上线后开关逻辑相反即云端点“开”灯反而灭了尝试将代码中的relay.value True改为relay.value False。另外控制大功率电器如 heater务必选择额定电流足够的继电器模块并注意用电安全。5.2 NeoPixel RGB 灯带控制硬件连接 NeoPixel 灯带需要连接 5V 电源、地和数据线。数据线可以连接到 FunHouse 上任意一个标有“~”的 PWM 兼容数字引脚如 D5。重要务必为灯带单独供电FunHouse 板载的 5V 输出电流有限无法驱动较长的灯带。代码集成要点初始化 NeoPixelimport neopixel import board # 假设数据线接在 D5 引脚灯带有30个LED pixels neopixel.NeoPixel(board.D5, 30, brightness0.3, auto_writeFalse)处理颜色选择器消息Adafruit IO 的颜色选择器模块发送的是十六进制颜色字符串如”#FF8800“。def message(client, feed_id, payload): if feed_id ‘neopixel‘: # 移除 ‘#‘ 符号并将十六进制字符串转换为RGB元组 hex_color payload.lstrip(‘#‘) rgb tuple(int(hex_color[i:i2], 16) for i in (0, 2, 4)) # 将颜色应用到所有LED pixels.fill(rgb) pixels.show() print(f“NeoPixel color set to {rgb}“)亮度控制可以通过修改brightness参数或额外创建一个滑块 Feed 来控制亮度在回调函数中动态调整pixels.brightness。避坑指南NeoPixel 对时序要求严格长线传输可能导致信号失真。如果灯带出现乱码或部分不亮尝试1) 在数据线靠近灯带输入端的位置加一个 300-500 欧姆的电阻。2) 在灯带电源正负极之间并联一个 1000µF 的电容以平滑上电冲击。3) 确保电源功率充足电压稳定在5V。6. 常见问题排查与优化技巧在实际部署中你可能会遇到一些问题。以下是我在多次项目中总结的常见问题及其解决方法。6.1 连接与通信问题问题现象可能原因排查步骤与解决方案FunHouse 屏幕显示连接失败/超时1. WiFi 密码错误。2.settings.toml文件格式错误或位置不对。3. 网络信号弱。1. 检查CIRCUITPY盘根目录下的settings.toml确保 SSID 和密码正确且没有多余空格或中文引号。2. 通过串口监视器如 Mu 编辑器、Thonny 或screen /dev/ttyACM0 115200查看具体错误信息。3. 将 FunHouse 靠近路由器测试。Adafruit IO 仪表盘无数据更新1. Adafruit IO 密钥错误或配额超限。2. MQTT 连接断开。3. 代码中 Feed 名称拼写与云端不一致。1. 确认ADAFRUIT_AIO_USERNAME和ADAFRUIT_AIO_KEY正确。免费账户有数据点速率限制检查是否超限。2. 在主循环中增加io.loop()调用以维持 MQTT 心跳并添加重连逻辑。3. 仔细核对代码中publish和subscribe使用的 Feed 键名必须与 Adafruit IO 上创建的完全一致区分大小写。控制指令下发后设备无反应1. MQTT 订阅失败。2. 回调函数message未正确定义或未绑定。3. 硬件连接或初始化错误。1. 在message函数开头加打印语句确认是否收到消息。2. 检查io.on_message message这行代码是否执行。3. 单独写一个测试脚本验证继电器或 NeoPixel 是否能被本地 GPIO 控制排除硬件问题。6.2 性能与稳定性优化添加 MQTT 重连机制网络不稳定是常态。在主循环中捕获 MQTT 异常并实现重连至关重要。last_mqtt_connect time.monotonic() mqtt_connect_interval 60 # 重连间隔秒 while True: try: # 维持 MQTT 连接 io.loop() except (ValueError, RuntimeError, adafruit_minimqtt.MQTTException) as e: print(“MQTT Error, reconnecting...“, e) # 尝试重新连接网络和 MQTT funhouse.network.connect() io.reconnect() time.sleep(5) # 定期执行其他任务如发布传感器数据 if time.monotonic() - last_publish 30: publish_sensor_data() last_publish time.monotonic()合理设置数据发布间隔传感器数据不必每秒上报。对于温湿度30秒甚至1分钟的间隔足以满足大多数家庭监控需求。这能减轻 Adafruit IO 的免费额度压力也降低设备功耗。利用板载按钮实现本地回退即使网络中断设备也应具备基本功能。可以编程让某个物理按钮切换为“本地模式”在此模式下直接读取传感器并在屏幕上显示或通过按钮控制继电器提升系统的鲁棒性。电源管理如果使用电池供电需要优化代码以降低功耗。例如在数据发布间隙可以调用funhouse.enter_light_sleep()让 ESP32-S2 进入轻睡眠模式。对于完全电池供电且数据更新不频繁的场景可以考虑使用深度睡眠但这会断开 WiFi 连接需要根据需求权衡。6.3 扩展思路本项目是一个强大的起点你可以在此基础上进行无限扩展多房间监控部署多个 FunHouse 或更便宜的 ESP32 板卡需适配代码分别监控不同房间数据统一发到同一个 Adafruit IO 账户在一个总览仪表盘中查看。语音集成结合 Home Assistant 或 IFTTT将 Adafruit IO 的 Feed 与 Google Assistant 或 Amazon Alexa 联动实现语音控制。数据持久化与分析Adafruit IO 可以导出数据。你可以定期将数据导出到 CSV然后导入到 Excel、Google Sheets 或更专业的工具如 Grafana 中进行长期趋势分析。自定义 UIadafruit_dash_display库支持自定义位图图标、不同字体和布局。你可以设计更符合家居风格的界面或者为不同的功能场景创建多个页面通过滑动或按钮切换。这个基于 Adafruit FunHouse 的物联网仪表盘项目完美诠释了现代创客项目的精髓利用高度集成的硬件、友好的开发环境和成熟的云服务快速将想法转化为可靠的原型。它不仅仅是一个教程更是一个可扩展的框架。当你理解了数据流Feed、消息协议MQTT和显示框架DashDisplay之间如何协同工作后你就可以摆脱示例的束缚用它去监控花园的土壤湿度、控制鱼缸的灯光循环、或是打造一个个性化的桌面天气信息站。