1. 项目概述:让MCU开口说话

在物联网项目里,让设备“开口说话”,主动把状态、数据或者告警信息推送到你的手机上,是一个既实用又酷炫的功能。想象一下,家里的温湿度传感器检测到异常高温,能立刻给你发条消息;或者你DIY的智能鱼缸,在水质变差时能及时通知你。这种主动通知的能力,是区分一个“玩具”和一个“实用工具”的关键。

过去,要实现这个功能,你可能需要折腾复杂的MQTT服务器、自己搭建Webhook,或者研究各种云平台繁琐的API。对于资源有限的微控制器(MCU)来说,这无疑增加了开发和维护的复杂度。而LINE Notify这个服务,恰好提供了一个极其简单的解决方案:它本质上就是一个通过HTTP POST请求就能发送消息到LINE聊天室的通道。对于嵌入式开发者,尤其是使用MicroPython的玩家,这简直是天作之合。

MicroPython让我们能在ESP8266、ESP32这类MCU上用Python语法轻松编程,而围绕它生态出现的一些优秀库,则进一步把复杂度封装了起来。就像这个项目里用到的 My_NetHTTP_LINE 库,它的目标非常明确——把“通过WiFi联网,构造HTTP请求,向LINE Notify发送消息”这一系列操作,浓缩成两、三行直观的代码。你不再需要关心HTTP头的构造、URL编码或者连接管理,只需要关注最核心的两件事:你的WiFi密码和LINE令牌(Token)。接下来,我们就从最基础的准备开始,一步步拆解如何让你的MCU变身成一个智能通知器。

2. 前期准备与环境搭建

在写下第一行代码之前,我们需要把“舞台”搭好。这包括硬件设备、软件工具以及关键的云端服务配置。别担心,每一步我都会解释清楚为什么这么做,以及有哪些容易踩坑的地方。

2.1 硬件与软件准备

硬件选择:ESP8266 vs ESP32 核心硬件是一块支持WiFi和MicroPython的MCU开发板。最常见的选择是ESP8266(如NodeMCU、Wemos D1 mini)和ESP32系列。

  • ESP8266 :性价比之王,单核,足以胜任网络连接和简单的消息发送任务。如果你的项目只需要联网发通知,没有其他复杂计算或外设需求,ESP8266完全够用,而且更便宜。
  • ESP32 :功能更强大,双核处理器,主频更高,内存更大,还多了蓝牙功能。如果你的项目未来需要连接更多传感器、处理更复杂的数据,或者需要用到蓝牙,ESP32是更面向未来的选择。

注意 :无论选择哪款,务必确保板子有可靠的USB转串口芯片(如CP2102、CH340),并且驱动已在你的电脑上安装好。连接不稳定是后续一切问题的万恶之源。

软件工具链

  1. MicroPython固件 :你需要将MicroPython解释器“刷入”你的MCU。去MicroPython官网下载对应你板型(如 esp8266-xxx.bin esp32-xxx.bin )的最新稳定版固件。
  2. 烧录工具 :对于ESP系列, esptool.py 是官方的命令行烧录工具,功能强大。如果你更喜欢图形界面,像 Thonny IDE内置的烧录功能或者 Flash Download Tools (乐鑫官方)也不错。
  3. 开发环境(IDE) :强烈推荐 Thonny 。它对MicroPython的支持是“开箱即用”级的。连接板子后,它不仅能直接作为Python编辑器,还能充当一个简单的文件管理器,上传下载文件到MCU的内部文件系统,以及使用其自带的REPL(交互式命令行)进行调试,这对我们后续上传库文件至关重要。
  4. 库文件 :本项目依赖的核心库文件( My_NetHTTP.py My_NetHTTP_LINE.py , 以及可选的 My_Wifi.py )。你需要提前获取这些 .py 文件。

2.2 获取LINE Notify令牌(Token)

这是连接你的代码和LINE账户的“钥匙”。没有它,消息不知道该发给谁。

  1. 访问 LINE Notify 官网 (请自行搜索正确网址),使用你的LINE账户登录。
  2. 点击页面右上角你的头像,进入“个人页面”。
  3. 找到“发行存取令牌”(Issue access token)选项。
  4. 输入一个令牌名称,例如“我的ESP32通知器”。这主要用于你自己识别这个令牌的用途。
  5. 选择消息要发送到的目标。你可以选择“透过1对1聊天接收LINE Notify的通知”,这样消息会单独发给一个名为“LINE Notify”的好友;也可以选择一个你所在的群组,这样所有群成员都能看到设备消息。 出于隐私考虑,建议先使用1对1聊天进行测试。
  6. 点击“发行”。页面上会 一次性 显示一串长字符,这就是你的 LINE_NOTIFY_TOKEN 务必立即复制并妥善保存 ,因为页面刷新后将无法再次查看,只能重新生成。

实操心得 :令牌是最高权限凭证,泄露意味着别人可以用你的令牌任意发消息。因此:

  • 绝对不要 将令牌硬编码在提交到公开仓库的代码中。
  • 在MicroPython中,一个常见的做法是将令牌(以及WiFi密码)保存在一个单独的、名为 secrets.py config.py 的文件里,然后在主程序中导入。上传时只上传主程序,将包含敏感信息的文件通过Thonny等工具单独上传,并确保 .gitignore 文件忽略了它。
  • 令牌可以在LINE Notify个人页面随时作废(失效)和重新生成。

2.3 库文件的上传与管理

原始资料提到了上传库文件到MCU,这里详细展开。MCU运行MicroPython时,需要一个文件系统来存放你的主程序 main.py 和依赖的库文件。我们通过串口连接,用工具将这些文件上传到MCU的闪存中。

使用Thonny上传(推荐给初学者):

  1. 将MCU通过USB线连接电脑,在Thonny中选择正确的端口和解释器(MicroPython ESP32/ESP8266)。
  2. 在Thonny下方窗格,通常可以看到“设备”和“本机”两个文件浏览器。
  3. 在“本机”侧找到你下载好的 My_NetHTTP.py My_NetHTTP_LINE.py 等文件。
  4. 右键点击文件,选择“上传到 /”,或者直接拖拽到“设备”侧的根目录下。
  5. 上传成功后,你可以在MCU的文件系统中看到它们。

使用命令行工具(如 ampy ): 如果你习惯命令行,可以安装 adafruit-ampy 工具。

# 上传单个文件
ampy --port COM3 put My_NetHTTP_LINE.py
# 上传整个目录(谨慎使用)
# ampy --port COM3 put lib/

注意事项

  • 文件命名一致性 :确保你上传的文件名和代码中 import 语句里的名字完全一致,包括大小写。MicroPython的文件系统有时对大小写敏感。
  • 存储空间 :ESP8266的可用文件系统空间可能较小(通常1MB左右),注意不要上传无关的大文件。ESP32则宽裕很多。
  • 库的依赖 My_NetHTTP_LINE.py 依赖于 My_NetHTTP.py (处理基础的HTTP请求)。因此两个文件必须同时存在。 My_Wifi.py 是可选的,如果你用自己的WiFi连接代码,可以不用它。

3. 核心库原理与代码深度解析

现在,硬件就绪,令牌在手,库文件也已上传。让我们深入看看,那神奇的2~3行代码背后,到底发生了什么。理解原理,不仅能帮你更好地使用它,还能在出问题时快速定位。

3.1 My_NetHTTP_LINE 库的工作机制

My_NetHTTP_LINE 库是一个高级封装,它的目标是极致简化。我们看看它可能的核心实现逻辑(以下为概念性代码,并非原库 exact 代码):

# My_NetHTTP_LINE.py 概念性源码分析
import My_NetHTTP # 导入底层HTTP库

class myNotify:
    def __init__(self, token):
        # 保存令牌,并构造LINE Notify API的固定URL
        self.url = "https://notify-api.line.me/api/notify"
        self.headers = {
            "Authorization": "Bearer " + token, # LINE API要求的认证头格式
            "Content-Type": "application/x-www-form-urlencoded"
        }
        # 实例化一个底层的HTTP客户端
        self.http = My_NetHTTP.My_NetHTTP() # 假设My_NetHTTP类名为My_NetHTTP

    def send(self, message, package=None, sticker=None):
        # 构建请求体,最基本的参数是 'message'
        data = "message=" + self._urlencode(message)
        
        # 如果提供了贴图参数,则添加到请求体中
        if package is not None and sticker is not None:
            data += "&stickerPackageId=" + str(package) + "&stickerId=" + str(sticker)
        
        # 调用底层HTTP库的POST方法
        # 这里封装了实际的网络请求、错误处理等复杂细节
        response = self.http.post(self.url, data=data, headers=self.headers)
        # 可能还会检查response状态码(如200成功,401令牌错误等)
        return response

从这段概念代码可以看出,这个库主要做了以下几件事:

  1. 初始化 :接收你的令牌,并组合成LINE API要求的 Authorization: Bearer {token} 请求头格式。这是HTTP协议中一种标准的令牌认证方式。
  2. 消息构造 :将你要发送的文本消息进行URL编码(处理空格、中文等特殊字符),形成 message=你的内容 的标准表单数据格式。
  3. 贴图支持 :如果调用时传入了 package sticker 参数,它会将这两个参数拼接到请求体中。
  4. 发起请求 :最终,它调用更底层的 My_NetHTTP 库,向 https://notify-api.line.me/api/notify 这个固定的API地址,发送一个HTTP POST请求。

那么,底层的 My_NetHTTP 库又做了什么? 它很可能封装了MicroPython标准库 urequests socket 的复杂操作,包括:

  • 建立TCP连接。
  • 按照HTTP协议格式,组装完整的HTTP请求报文(请求行、请求头、空行、请求体)。
  • 处理网络读写超时。
  • 接收服务器的响应并解析状态码和响应体。
  • 处理网络连接异常。

正是这种分层设计,才让顶层的我们能够用 line.send(“Hello”) 这样简单的方式完成通信。

3.2 代码逐行解读与最佳实践

让我们结合一个更完整的示例,逐行分析并融入最佳实践。

# 示例:complete_notify.py
from My_Wifi import myWifi  # 导入WiFi连接库
from My_NetHTTP_LINE import myNotify # 导入LINE通知库
import time

# 1. WiFi连接配置
WIFI_SSID = "你的WiFi名称"
WIFI_PASSWORD = "你的WiFi密码"
LINE_TOKEN = "你的LINE令牌" # 强烈建议从配置文件导入

# 2. 创建WiFi对象并连接
wifi = myWifi()
print("正在连接WiFi...")
if wifi.connect(WIFI_SSID, WIFI_PASSWORD):
    print("WiFi连接成功!")
    
    # 3. 创建LINE通知对象
    line = myNotify(LINE_TOKEN) # 初始化,传入令牌
    
    # 4. 发送纯文本消息
    print("正在发送文本消息...")
    response = line.send("【设备启动通知】ESP32已成功上线,IP地址:" + wifi.get_ip())
    # 这里可以检查response,例如 if response.status_code == 200: ...
    
    # 5. 发送带贴图的消息
    # packageId 和 stickerId 需要从LINE官网查询
    print("正在发送带贴图的消息...")
    line.send("今日天气晴好,一切正常!😊", package=1, sticker=113)
    # 贴图ID 1-113 对应的是“微笑”表情
    
    # 6. 模拟设备运行后发送告警
    time.sleep(5) # 模拟运行5秒
    # 假设这里读取传感器,发现温度过高
    simulated_temperature = 38.5
    if simulated_temperature > 35:
        line.send(f"【高温告警】检测到温度过高:{simulated_temperature}°C!请及时处理。", package=2, sticker=165)
        # 贴图ID 2-165 对应的是“吃惊”或“警告”类表情,更符合告警场景
    
    # 7. 断开WiFi(可选,对于常开设备通常保持连接)
    wifi.disconnect(3) # 参数3可能代表延迟3秒断开
    print("通知发送完毕,WiFi已断开。")
else:
    print("WiFi连接失败,请检查配置。")

关键点解析与最佳实践:

  • WiFi连接判断 if wifi.connect(...): 这是一个好习惯。确保网络连通后再进行后续的网络操作,避免程序因网络问题而崩溃。
  • 令牌管理 :在实际项目中, LINE_TOKEN WIFI_SSID WIFI_PASSWORD 不应直接写在主代码里。创建一个 config.py 文件:
    # config.py
    WIFI_SSID = "my_home_wifi"
    WIFI_PASSWORD = "super_secret_password"
    LINE_TOKEN = "abcdefghijklmnopqrstuvwxyz123456"
    
    在主程序中 import config ,然后使用 config.LINE_TOKEN 。上传代码时,只上传主程序, config.py 通过Thonny单独上传。
  • 消息内容 :消息内容可以动态拼接。如上例中,将获取到的设备IP地址加入通知,使得消息更具信息量。使用f-string(Python 3.6+)或 format() 方法让字符串组合更清晰。
  • 错误处理 :示例中省略了详细的错误处理。在生产代码中,你应该用 try...except 包裹 send 方法,捕获可能发生的网络异常、内存错误等,并记录日志或通过其他途径告警。
  • 贴图的情感化应用 :选择与消息内容情绪相符的贴图,能极大提升通知的友好度和可读性。告警用“紧张”、“吃惊”的贴图,正常报告用“微笑”、“OK”的贴图。

4. 实战进阶:构建一个温湿度监控通知器

理解了基础,我们来做一个更有实际意义的项目:一个基于DHT11/DHT22温湿度传感器和ESP32的监控器,它定期读取环境数据,并在温度或湿度超过阈值时,向LINE发送告警通知。

4.1 硬件连接与依赖库

所需材料:

  • ESP32开发板 x1
  • DHT11或DHT22温湿度传感器 x1
  • 杜邦线若干
  • 微型USB数据线

接线方式(以DHT11为例):

  • DHT11 VCC 引脚 -> ESP32 3.3V
  • DHT11 GND 引脚 -> ESP32 GND
  • DHT11 DATA 引脚 -> ESP32 GPIO 4 (可根据需要更改)

额外的MicroPython库: 除了之前的网络库,我们还需要 dht 库来读取传感器数据。好消息是, dht 通常是MicroPython固件内置的标准库之一,无需额外上传。如果没有,你需要找到 dht.py 文件并上传。

4.2 完整项目代码实现

# main.py - 温湿度监控与LINE告警系统
import time
import dht
from machine import Pin
from My_Wifi import myWifi
from My_NetHTTP_LINE import myNotify

# 1. 配置文件(实际使用时请分离到config.py)
CONFIG = {
    'wifi_ssid': '你的WiFi',
    'wifi_pass': '你的密码',
    'line_token': '你的令牌',
    'sensor_pin': 4,          # DHT数据线连接的GPIO引脚
    'check_interval': 30,     # 检查间隔(秒)
    'temp_threshold_high': 28.0, # 温度告警上限(摄氏度)
    'temp_threshold_low': 10.0,  # 温度告警下限
    'humi_threshold_high': 80.0, # 湿度告警上限(百分比)
    'humi_threshold_low': 20.0   # 湿度告警下限
}

# 2. 初始化硬件与网络
def init_system():
    # 初始化DHT传感器
    dht_sensor = dht.DHT11(Pin(CONFIG['sensor_pin'])) # 使用DHT11,如果是DHT22改为DHT22
    # 初始化WiFi
    wifi = myWifi()
    print("系统初始化...")
    if not wifi.connect(CONFIG['wifi_ssid'], CONFIG['wifi_pass']):
        print("[严重错误] WiFi连接失败,系统停止。")
        # 对于无法联网的设备,可以考虑让LED闪烁报警
        while True:
            time.sleep(1) # 阻塞,等待人工干预或重启
    print(f"WiFi连接成功,IP: {wifi.get_ip()}")
    # 初始化LINE通知器
    line_bot = myNotify(CONFIG['line_token'])
    # 发送系统启动通知
    line_bot.send(f"🌡️ 温湿度监控器已启动 @ {wifi.get_ip()}, 开始监控...")
    return dht_sensor, wifi, line_bot

# 3. 读取传感器数据(包含简单错误处理)
def read_sensor_data(sensor):
    try:
        sensor.measure() # 触发一次测量
        temperature = sensor.temperature()
        humidity = sensor.humidity()
        # DHT11可能返回None或错误值,增加检查
        if temperature is None or humidity is None:
            print("读取传感器数据失败,返回None。")
            return None, None
        # 有时DHT11会读出极端错误值,增加合理性检查
        if -40 < temperature < 80 and 0 <= humidity <= 100:
            return temperature, humidity
        else:
            print(f"传感器数据异常:temp={temperature}, humi={humidity}")
            return None, None
    except OSError as e:
        # 常见的传感器读取超时错误
        print(f"读取传感器时发生OSError: {e}")
        return None, None
    except Exception as e:
        print(f"读取传感器时发生未知错误: {e}")
        return None, None

# 4. 检查阈值并发送通知
def check_and_notify(temp, humi, line_bot, last_alert):
    current_time = time.time()
    message_parts = [] # 用于组合消息
    alert_level = 0 # 告警级别 0:正常,1:警告,2:严重
    
    # 检查温度
    if temp is not None:
        if temp > CONFIG['temp_threshold_high']:
            message_parts.append(f"🔥 温度过高:{temp}°C")
            alert_level = max(alert_level, 2)
        elif temp < CONFIG['temp_threshold_low']:
            message_parts.append(f"❄️ 温度过低:{temp}°C")
            alert_level = max(alert_level, 2)
    else:
        message_parts.append("温度传感器读数无效")
        alert_level = max(alert_level, 1)
        
    # 检查湿度
    if humi is not None:
        if humi > CONFIG['humi_threshold_high']:
            message_parts.append(f"💦 湿度过高:{humi}%")
            alert_level = max(alert_level, 2)
        elif humi < CONFIG['humi_threshold_low']:
            message_parts.append(f"🏜️ 湿度过低:{humi}%")
            alert_level = max(alert_level, 2)
    else:
        message_parts.append("湿度传感器读数无效")
        alert_level = max(alert_level, 1)
    
    # 决定是否发送通知以及发送什么
    if alert_level > 0:
        # 存在告警
        alert_msg = " | ".join(message_parts)
        # 防骚扰机制:相同的告警,至少间隔10分钟才发送一次
        if alert_msg != last_alert.get('msg') or (current_time - last_alert.get('time', 0)) > 600:
            print(f"发送告警:{alert_msg}")
            if alert_level == 2:
                line_bot.send(alert_msg, package=2, sticker=165) # 严重告警用紧张贴图
            else:
                line_bot.send(alert_msg, package=1, sticker=113) # 一般警告用提醒贴图
            last_alert['msg'] = alert_msg
            last_alert['time'] = current_time
    else:
        # 状态正常,可以定期发送一次心跳(例如每小时一次),这里省略以节省消息数
        # if current_time - last_heartbeat > 3600: ...
        #     line_bot.send(f"✅ 状态正常 - 温度:{temp}°C, 湿度:{humi}%")
        pass
    
    return last_alert

# 5. 主循环
def main():
    sensor, wifi, line_bot = init_system()
    last_alert = {'msg': '', 'time': 0} # 记录上一次告警内容和时间
    normal_read_count = 0
    
    while True:
        print(f"\n--- 第{normal_read_count+1}次检查 ---")
        temp, humi = read_sensor_data(sensor)
        
        if temp is not None and humi is not None:
            print(f"当前环境:温度 {temp}°C, 湿度 {humi}%")
            # 更新最后一次告警状态
            last_alert = check_and_notify(temp, humi, line_bot, last_alert)
            normal_read_count += 1
        else:
            print("本次传感器读取失败,跳过检查。")
            # 连续多次失败可以升级为告警
            # error_count += 1
            # if error_count > 5: ...
        
        # 等待下一个检查周期
        time.sleep(CONFIG['check_interval'])

# 运行主程序
if __name__ == '__main__':
    main()

4.3 项目优化与扩展思路

这个基础版本已经可以工作,但还有很大的优化和扩展空间:

  1. 深度睡眠与省电 :如果设备由电池供电,频繁的WiFi连接和传感器读取非常耗电。可以利用ESP32的深度睡眠(Deep Sleep)功能。让设备每隔一段时间(如5分钟)唤醒,连接WiFi、读取传感器、发送通知(如果需要),然后立刻进入深度睡眠。这可以将平均电流从几十mA降至几十μA,极大延长续航。

    from machine import deepsleep
    # 在主循环末尾或发送通知后
    print("进入深度睡眠,{}秒后唤醒。".format(sleep_time_ms // 1000))
    deepsleep(sleep_time_ms) # 单位是毫秒
    
  2. 数据上报与可视化 :除了即时告警,你还可以将数据定期上报到物联网平台(如ThingsBoard、Blynk、或者自建的InfluxDB+ Grafana),用于绘制长期的历史曲线图,分析环境变化趋势。这需要设备具备更稳定的网络连接和更复杂的数据封装能力。

  3. 多通道通知 :不要只依赖LINE。可以集成其他通知方式,比如Telegram Bot、Bark(iOS)、Server酱(微信)等。在 check_and_notify 函数中,可以同时调用多个通知发送函数,实现通知冗余,确保重要告警不被遗漏。

  4. 本地显示与交互 :增加一个OLED屏幕(如SSD1306),实时显示当前的温湿度数据和WiFi状态。再增加一两个按钮,可以手动触发一次读取、切换显示模式,或者进入配置模式(通过Web Server或蓝牙)来修改WiFi密码和阈值,这样就不需要每次都修改代码并重新上传了。

5. 常见问题排查与调试技巧

即使按照步骤操作,你也可能会遇到一些问题。这里汇总了一些常见坑点及其解决方法。

5.1 网络连接类问题

问题现象 可能原因 排查步骤与解决方案
wifi.connect() 始终返回 False 或超时。 1. WiFi SSID/密码错误。
2. 路由器设置了MAC地址过滤或隐藏了SSID。
3. ESP板与路由器距离过远或信号太差。
4. 路由器不支持ESP的某些WiFi模式(较少见)。
1. 仔细核对 SSID和密码,注意大小写和特殊字符。
2. 在路由器后台暂时关闭MAC过滤,或将ESP的MAC地址加入白名单。对于隐藏SSID, myWifi 库可能不支持,需查看其文档或改用标准 network 库手动连接。
3. 将设备靠近路由器测试。
4. 尝试在手机热点下测试,以排除路由器兼容性问题。
连接WiFi成功,但发送LINE消息时失败。 1. 网络临时波动。
2. DNS解析失败(无法解析 notify-api.line.me )。
3. 防火墙或网络策略阻止了对外部HTTPS(443端口)的访问。
1. 增加重试机制。在 send 方法外用 try...except 包裹,失败后延迟几秒重试1-2次。
2. 尝试在代码中先用 urequests.get('http://example.com') 测试是否能访问普通HTTP网站,以排除基础网络问题。
3. 在某些企业或学校网络,访问外部服务可能受限。尝试切换到手机热点网络测试。
设备运行一段时间后网络断开,无法重连。 1. WiFi路由器重启或网络不稳定。
2. ESP32/ESP8266的WiFi驱动或电源管理存在bug,导致长时间运行后断线。
3. 代码中没有断线重连机制。
1. 在主循环中增加网络状态检查。可以定期(如每10次循环)ping一个网关或外网地址,如果失败,则调用 wifi.disconnect() 然后重新执行 wifi.connect()
2. 查阅MicroPython论坛,有时更新到最新稳定版固件可以解决一些已知的驱动问题。
3. 务必实现重连逻辑 ,这是物联网设备稳定性的关键。

5.2 代码与库相关错误

问题现象 可能原因 排查步骤与解决方案
ImportError: no module named 'My_NetHTTP_LINE' 1. 库文件没有上传到MCU。
2. 库文件上传到了错误的目录(如子目录)。
3. 文件名拼写错误(大小写、下划线)。
1. 使用Thonny的文件管理器,确认 My_NetHTTP_LINE.py My_NetHTTP.py 存在于MCU的根目录( / )。
2. 确保 import 语句中的模块名与文件名 完全一致
NameError: name 'myNotify' is not defined from My_NetHTTP_LINE import myNotify 语句执行失败,但错误被忽略或发生在之前。 检查上一条 import 语句是否成功。确保库文件存在且语法正确。可以在REPL中单独执行 from My_NetHTTP_LINE import myNotify 测试。
发送消息后程序崩溃或无响应。 1. 内存不足(尤其在ESP8266上,同时处理字符串和网络请求易发生)。
2. 网络操作阻塞了看门狗(WDT),导致复位。
1. 使用 gc.collect() 在关键操作(如组包大字符串、发送请求)后手动回收内存。
2. 将耗时的网络操作放在 try...finally 块中,或在其中插入短时间的 time.sleep(0) 以喂狗。对于ESP32,可以考虑将网络任务放在另一个核心上运行(需使用 _thread 库)。
能发送文本,但发送贴图失败。 1. packageId stickerId 参数类型错误(应为整数)。
2. 参数值超出了有效范围。
3. 库的 send 方法在处理可选参数时存在bug。
1. 确认传入的参数是整数,如 line.send("msg", package=1, sticker=113)
2. 去LINE官方贴图列表页面,确认你使用的ID组合是有效的、免费的贴图。
3. 尝试发送不带贴图的消息确认基础功能正常。然后检查库文件源码(如果开源),看贴图参数拼接逻辑是否正确。

5.3 LINE API 返回错误

send 方法内部调用失败时,最可能的原因是LINE API返回了错误。虽然 My_NetHTTP_LINE 库可能没有直接暴露详细的错误信息,但我们可以通过修改库文件或使用更底层的 urequests 库来调试。

临时调试方法:

  1. My_NetHTTP_LINE.py send 方法中,找到发送请求和获取响应的代码行(通常是 response = self.http.post(...) )。
  2. 在这行之后,添加打印语句,输出响应的状态码和内容。
    # 在My_NetHTTP_LINE.py的send方法内添加
    print("Status Code:", response.status_code)
    print("Response:", response.text)
    
  3. 重新上传该库文件到MCU并运行你的程序。常见的错误有:
    • 401 :令牌无效或已过期。请重新在LINE Notify官网生成令牌。
    • 400 :请求格式错误,例如消息体过长(LINE Notify限制消息长度)、贴图ID无效等。
    • 429 :请求频率过高。LINE Notify对同一个令牌有发送频率限制(大概每小时1000条左右),请降低发送频率。

调试心法:

  • 分而治之 :遇到问题,先把复杂系统拆开测试。先写一个最简单的脚本,只连WiFi;再写一个脚本,只发LINE文本;最后再组合。
  • 利用REPL :Thonny的REPL是强大的实时调试工具。你可以在里面逐行执行代码,即时查看变量和错误信息。
  • 打印日志 :在关键步骤(连接WiFi前/后、发送消息前/后)添加 print() 语句输出状态,这是嵌入式调试最朴实但最有效的方法。

更多推荐