Tasmota 指纹识别实战:Adafruit-Fingerprint-Tasmota-2.1.0 库的驱动原理、API 与 AS608/R503 集成指南

发布时间:2026/9/12 12:27:25
Tasmota 指纹识别实战:Adafruit-Fingerprint-Tasmota-2.1.0 库的驱动原理、API 与 AS608/R503 集成指南 Tasmota 指纹识别实战Adafruit-Fingerprint-Tasmota-2.1.0 库的驱动原理、API 与 AS608/R503 集成指南【免费下载链接】TasmotaAlternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at项目地址: https://gitcode.com/GitHub_Trending/ta/Tasmota指纹传感器模块AS608 光学式、R503 电容式等内置高算力 DSP 芯片负责图像渲染、特征提取、指纹搜索与比对主机只需通过 TTL 串口收发指令包即可完成拍照、注册Enroll、匹配与库管理最多可在模块板载 FLASH 中存储 162 枚指纹。本文以 Tasmota 仓库中随附的 Adafruit-Fingerprint-Tasmota-2.1.0 库为核心讲解该库的源码结构、结构化串口协议、完整 API、注册/识别/删除/改密等标准流程并延伸到 xsns_79_as608.ino 在 Tasmota 固件中的真实落地GPIO 配置、FpEnroll/FpDelete/FpCount控制台命令与 MQTT JSON 事件输出。读完本文你将能独立完成指纹传感器在 Arduino 类工程中的驱动编写也能在 Tasmota 设备上直接启用指纹门禁功能。一、库的定位与 Tasmota 定制点Adafruit-Fingerprint-Tasmota-2.1.0 是 Adafruit 官方指纹传感器库的 Tasmota 适配分支版本号 2.1.0许可协议为 BSD见 license.txt。与上游库相比它针对 ESP8266/ESP32 做了两处关键修改源码注释中明确记录于 xsns_79_as608.ino用 TasmotaSerial 替换 SoftwareSerial软件串口在 Tasmota 中通过TasmotaSerial统一管理可复用 GPIO 多路复用体系并规避中断冲突补全 ESP32 平台分支凡是上游仅defined(ESP8266)的地方均扩展为defined(ESP8266) || defined(ESP32)。在头文件 Adafruit_Fingerprint.h 中可以看到这一适配的直接证据#include Arduino.h #if defined(__AVR__) || defined(ESP8266) || defined(ESP32) #include TasmotaSerial.h #elif defined(FREEDOM_E300_HIFIVE1) #include SoftwareSerial32.h #define SoftwareSerial SoftwareSerial32 #endif库同时保留了三种串口形态的构造函数兼容绝大多数微控制器平台Adafruit_Fingerprint(TasmotaSerial *ss, uint32_t password 0x0); // 软件串口Tasmota 定制 Adafruit_Fingerprint(HardwareSerial *hs, uint32_t password 0x0); // 硬件串口 Adafruit_Fingerprint(Stream *serial, uint32_t password 0x0); // 任意 Stream第二个参数password为 32 位模块访问口令默认0x0无口令。构造时内部会将theAddress初始化为0xFFFFFFFF即广播地址见 Adafruit_Fingerprint.cpp。仓库目录中还随附了两份传感器硬件手册documentation/ZFM-20_Fingerprint_Module.pdfZFM-20 光学模块规格书与documentation/fingerprint_en.pdf需要核对寄存器地址、颜色代码或包格式细节时可查阅。二、硬件连接只需两根 TTL 串口线README 明确说明这些传感器使用 TTL 串口通信只需 2 根信号线即可与任意微控制器或系统对接。传感器模块内部 DSP 已完成图像渲染、计算、特征查找和搜索主机不承担任何图像处理负担。接线约定以官方示例 enroll.ino 为例传感器引脚主机引脚说明TX绿线RX示例中 pin 2传感器数据输出 → 主机输入RX白线TX示例中 pin 3主机数据输出 → 传感器输入VCC / GND电源 3.3~5V / GND供电与共地软件串口示例SoftwareSerial mySerial(2, 3); // 2 IN from sensor (GREEN), 3 OUT from arduino (WHITE) Adafruit_Fingerprint finger Adafruit_Fingerprint(mySerial);在 Leonardo/M0 等带硬件串口的板子上可直接使用Serial1。在 Tasmota 中则完全由 GPIO 复用体系接管GPIO_AS608_TX/GPIO_AS608_RX两个引脚定义位于 tasmota_template.hGPIO_AS608_TX, GPIO_AS608_RX, // Serial interface AS608 / R503并在 tasmota_template.h 的AGPIO表中注册。初始化时通过PinUsed(GPIO_AS608_RX) PinUsed(GPIO_AS608_TX)同时检测两个引脚是否被分配见 xsns_79_as608.ino。三、串口波特率与模块参数读取begin(baud)在初始化串口前会先延时 1 秒等待模块上电自检完成再按指定波特率打开串口void Adafruit_Fingerprint::begin(uint32_t baudrate) { delay(1000); // one second delay to let the sensor boot up if (hwSerial) hwSerial-begin(baudrate); if (swSerial) swSerial-begin(baudrate); }传感器默认波特率通常为 57600官方示例也统一使用finger.begin(57600)。模块内置寄存器还支持通过setBaudRate()在 9600~115200 之间切换头文件中预定义了全部档位常量Adafruit_Fingerprint.h常量寄存器值波特率FINGERPRINT_BAUDRATE_96000x19600FINGERPRINT_BAUDRATE_192000x219200FINGERPRINT_BAUDRATE_288000x328800FINGERPRINT_BAUDRATE_384000x438400FINGERPRINT_BAUDRATE_480000x548000FINGERPRINT_BAUDRATE_576000x657600FINGERPRINT_BAUDRATE_672000x767200FINGERPRINT_BAUDRATE_768000x876800FINGERPRINT_BAUDRATE_864000x986400FINGERPRINT_BAUDRATE_960000xA96000FINGERPRINT_BAUDRATE_1056000xB105600FINGERPRINT_BAUDRATE_1152000xC115200getParameters()通过FINGERPRINT_READSYSPARAM0x0F命令一次性读取 7 项模块参数并填充到成员变量解析逻辑见 Adafruit_Fingerprint.cppstatus_reg状态寄存器system_id系统标识capacity指纹容量出厂默认 64部分固件为 162security_level安全等级1~5device_addr32 位模块地址packet_len数据包最大长度32/64/128/256 字节映射baud_rate当前波特率寄存器值 × 9600官方示例在setup()中依次执行verifyPassword()→getParameters()→getTemplateCount()把模块状态、容量、安全等级、地址、包长、波特率全部打印出来这是排查接线与波特率问题的最快手段。四、结构化串口协议包格式与校验库与传感器之间通过「结构化数据包」通信所有命令、数据和应答都遵循同一帧格式。Adafruit_Fingerprint_Packet结构体Adafruit_Fingerprint.h定义了帧字段字段长度说明start_code2 字节固定0xEF01FINGERPRINT_STARTCODE高字节先发address4 字节32 位模块地址默认0xFFFFFFFF广播type1 字节包类型命令包 0x1 / 数据包 0x2 / 应答包 0x7 / 数据结束包 0x8length2 字节有效载荷长度 2含校验和dataN 字节载荷最大 64 字节checksum2 字节type length 全部 data 字节之和发送逻辑writeStructuredPacket()Adafruit_Fingerprint.cpp逐字节写出帧头后按sum ((wire_length)8) (wire_length 0xFF) packet.type Σdata[i]计算并追加 2 字节校验和。接收逻辑getStructuredPacket()Adafruit_Fingerprint.cpp则是一个有限状态机先同步0xEF起始码依次收地址、类型、长度和载荷超时返回FINGERPRINT_TIMEOUT帧头不匹配返回FINGERPRINT_BADPACKET默认超时DEFAULTTIMEOUT为 1000 ms。命令发送宏GET_CMD_PACKET/SEND_CMD_PACKET将所有指令统一封装发命令包 → 等应答包 → 返回应答码任一环节失败即返回FINGERPRINT_PACKETRECIEVEERR0x01这是通信出问题时的第一排查信号。五、API 全景与错误码速查5.1 命令码一览头文件定义了完整指令集Adafruit_Fingerprint.h指令常量代码含义FINGERPRINT_GETIMAGE0x01采集指纹图像FINGERPRINT_IMAGE2TZ0x02图像 → 特征文件FINGERPRINT_SEARCH0x04在库中搜索匹配FINGERPRINT_REGMODEL0x05合并特征生成模板FINGERPRINT_STORE0x06存储模板FINGERPRINT_LOAD0x07读取模板FINGERPRINT_UPLOAD0x08上传模板FINGERPRINT_DELETE0x0C删除模板FINGERPRINT_EMPTY0x0D清空指纹库FINGERPRINT_READSYSPARAM0x0F读取系统参数FINGERPRINT_SETPASSWORD0x12设置密码FINGERPRINT_VERIFYPASSWORD0x13校验密码FINGERPRINT_HISPEEDSEARCH0x1B高速搜索FINGERPRINT_TEMPLATECOUNT0x1D读取模板数量FINGERPRINT_AURALEDCONFIG0x35Aura LED 环控制FINGERPRINT_LEDON/LEDOFF0x50 / 0x51板载 LED 开关5.2 应答/错误码速查所有命令统一返回 1 字节应答码Adafruit_Fingerprint.h常量值含义FINGERPRINT_OK0x00命令执行完成FINGERPRINT_PACKETRECIEVEERR0x01接收数据包出错FINGERPRINT_NOFINGER0x02传感器上无手指FINGERPRINT_IMAGEFAIL0x03图像采集失败FINGERPRINT_IMAGEMESS0x06图像过于杂乱特征文件生成失败FINGERPRINT_FEATUREFAIL0x07特征点不足或图像太小FINGERPRINT_NOMATCH0x08指纹不匹配FINGERPRINT_NOTFOUND0x09未找到匹配指纹FINGERPRINT_ENROLLMISMATCH0x0A特征文件合并失败两次采集不一致FINGERPRINT_BADLOCATION0x0BPageID 超出指纹库范围FINGERPRINT_DBRANGEFAIL0x0C模板读取出错或模板无效FINGERPRINT_UPLOADFEATUREFAIL0x0D模板上传出错FINGERPRINT_PACKETRESPONSEFAIL0x0E模块未收到后续数据包FINGERPRINT_UPLOADFAIL0x0F图像上传出错FINGERPRINT_DELETEFAIL0x10模板删除失败FINGERPRINT_DBCLEARFAIL0x11指纹库清空失败FINGERPRINT_PASSFAIL0x13密码校验失败FINGERPRINT_INVALIDIMAGE0x15缺少有效原始图像特征生成失败FINGERPRINT_FLASHERR0x18FLASH 写入出错FINGERPRINT_INVALIDREG0x1A寄存器号无效FINGERPRINT_ADDRCODE0x20地址码FINGERPRINT_PASSVERIFY0x21密码校验通过FINGERPRINT_TIMEOUT0xFF接收超时库内部FINGERPRINT_BADPACKET0xFE坏数据包库内部5.3 公开 API 清单从 Adafruit_Fingerprint.h 可以看到完整公开接口方法作用begin(baud)初始化串口并设置波特率verifyPassword()校验口令并探测模块是否在线getParameters()读取 7 项系统参数getImage()采集指纹图像image2Tz(slot)图像转特征文件slot 1/2createModel()合并两个特征文件生成模板storeModel(id)/loadModel(id)/getModel()模板存/读/上传deleteModel(id)/emptyDatabase()删除单个模板 / 清空整个库fingerSearch(slot)/fingerFastSearch()常规搜索 / 高速搜索结果写入fingerID与confidencegetTemplateCount()查询已存模板数写入templateCountsetPassword(pwd)设置模块访问口令LEDcontrol(...)板载 LED 与 Aura LED 环控制setBaudRate()/setSecurityLevel()/setPacketSize()寄存器级参数写入搜索类方法的两个关键输出成员fingerID为命中位置号confidence为匹配置信度越大越可靠未命中时两者被置为0xFFFF。六、注册Enroll流程三次取像两次入库注册一枚指纹的标准流程是「取像 → 转特征slot 1→ 取像 → 转特征slot 2→ 合并 → 存储」。官方 enroll.ino 完整实现了这一流程核心状态机如下// 1. 等待手指放上并取第一张图像 while (p ! FINGERPRINT_OK) { p finger.getImage(); // FINGERPRINT_NOFINGER 表示还没放手指 } // 2. 图像 → 特征文件放入槽位 1 p finger.image2Tz(1); // 3. 等待手指移开 while (p ! FINGERPRINT_NOFINGER) { p finger.getImage(); } // 4. 同一手指再放一次取第二张图像 → 槽位 2 p finger.image2Tz(2); // 5. 合并两个特征文件生成模板 p finger.createModel(); // FINGERPRINT_ENROLLMISMATCH 两次指纹不一致 // 6. 存储到指定 ID p finger.storeModel(id); // FINGERPRINT_BADLOCATION / FINGERPRINT_FLASHERR示例中id的有效范围是1~127id 0被拒绝。库会跳过相同手指在注册期间的重复匹配。Tasmota 的As608Loop()以 250 ms 周期状态机复刻了这一流程见 xsns_79_as608.ino每个步骤都通过 MQTT 发布FpEnroll状态消息Place finger / Remove finger / Place same finger / Retry / Restart 等。七、识别Match流程搜索与置信度识别流程比注册简单取像 → 转特征 → 搜索。官方 fingerprint.ino 展示了完整实现压缩版getFingerprintIDez()同文件 L149-L163尤其适合直接嵌入业务代码int getFingerprintIDez() { uint8_t p finger.getImage(); if (p ! FINGERPRINT_OK) return -1; p finger.image2Tz(); if (p ! FINGERPRINT_OK) return -1; p finger.fingerFastSearch(); if (p ! FINGERPRINT_OK) return -1; // found a match! return finger.fingerID; // 命中 ID }两种搜索方法的区别Adafruit_Fingerprint.cppfingerFastSearch()发FINGERPRINT_HISPEEDSEARCH0x1B从页 0x0000 搜到 0x00A3即 0~163 页覆盖 162 枚指纹容量fingerSearch(slot)发FINGERPRINT_SEARCH0x04按capacity成员动态计算搜索范围兼容性更好。Tasmota 集成中特意注释了fingerFastSearch()在 R503 上会失败、改用fingerSearch()的实践结论xsns_79_as608.ino这是真实硬件兼容性经验值得移植时注意。八、LED 环控制颜色与呼吸/闪烁特效README 中提到带 Bi-Color LED Ring 的 Rugged Panel Mount 版本R503 系列在识别区周围有一圈 LED 环可设为红、蓝、紫以及渐变、呼吸等效果。库通过两个重载提供控制uint8_t LEDcontrol(bool on); // 板载 LED 开关 uint8_t LEDcontrol(uint8_t control, uint8_t speed, uint8_t coloridx, uint8_t count 0); // Aura LED 环Aura LED 参数Adafruit_Fingerprint.h模式值颜色值FINGERPRINT_LED_BREATHING0x01FINGERPRINT_LED_RED0x01FINGERPRINT_LED_FLASHING0x02FINGERPRINT_LED_BLUE0x02FINGERPRINT_LED_ON0x03FINGERPRINT_LED_PURPLE0x03FINGERPRINT_LED_OFF0x04——FINGERPRINT_LED_GRADUAL_ON0x05——FINGERPRINT_LED_GRADUAL_OFF0x06——官方 ledcontrol.ino 演示了全亮三色切换、红色闪烁 10 次、蓝色持续呼吸、紫色渐亮渐灭等组合count参数控制闪烁/呼吸循环次数0 表示持续。Tasmota 侧将 LED 环与业务状态联动初始化成功时LEDcontrol(FINGERPRINT_LED_BREATHING, 100, AS608_COLOR_INIT, 3)呼吸提示扫描期间熄灯省电检测到手指后GRADUAL_ON渐亮匹配成功保持常亮见 xsns_79_as608.ino 与 L151-L194。AS608_COLOR_INIT/AS608_COLOR_SCAN两个编译期宏默认 1红、3紫可自定义颜色R503 v1.2 还支持 7 色环红蓝紫绿黄青白。九、口令管理与其他库操作9.1 修改模块口令changepassword.ino 展示了口令生命周期先用默认口令0构造并verifyPassword()校验再setPassword(1337)写入新口令此后构造时必须传入Adafruit_Fingerprint(mySerial, 1337)才能继续通信否则将返回FINGERPRINT_PASSFAIL。注意口令是持久化存储在模块 FLASH 中的丢失即无法访问务必妥善记录。9.2 删除与清空delete.ino 调用deleteModel(id)删除单个模板emptyDatabase.ino 调用emptyDatabase()一次性清空全部指纹示例要求确认按键后才执行防止误操作。deleteModel发送FINGERPRINT_DELETE0x0C并携带 4 字节参数ID 高/低字节 0x00 计数 0x01。9.3 寄存器级配置setBaudRate()、setSecurityLevel()、setPacketSize()都通过私有方法writeRegister()写入系统寄存器Adafruit_Fingerprint.cpp寄存器地址常量地址可写值FINGERPRINT_BAUD_REG_ADDR0x4波特率代码 0x1~0xCFINGERPRINT_SECURITY_REG_ADDR0x5安全等级 1~5FINGERPRINT_PACKET_REG_ADDR0x6包长 32/64/128/256 字节安全等级语义头文件注释原文等级 1 误识率最高、拒识率最低等级 5 误识率最低、拒识率最高。实际使用中等级 3 是多数场景的平衡点。注意setBaudRate()底层实现传参存在一个已知小缺陷将新值传给了当前baud_rate成员而非入参见 Adafruit_Fingerprint.cpp如需改波特率建议直接调用writeRegister的等价指令并同步修改主机串口配置。9.4 模板备份与透传show_fingerprint_templates.ino 用于导出/展示已存模板Leo_passthru.ino 则把主机串口与传感器串口做双向透传便于用 PC 串口工具直接调试模块原始协议。十、Tasmota 集成实战AS608/R503 指纹门禁库在 Tasmota 中的消费方是传感器驱动 xsns_79_as608.ino文件头注释明确支持 AS608 光学式与 R503 电容式传感器。10.1 编译开关与宏驱动整体包裹在#ifdef USE_AS608中xsns_79_as608.ino需要在my_user_config.h或user_config_override.h中定义USE_AS608才会编译。可选宏#define USE_AS608 // 启用 AS608/R503 指纹驱动必须 // #define USE_AS608_MESSAGES // 启用详细错误消息默认仅 Done/Unknown/No finger #ifndef AS608_DUPLICATE #define AS608_DUPLICATE 4 // 同一手指匹配后的防抖窗口0.25s × N #endif #ifndef AS608_COLOR_INIT #define AS608_COLOR_INIT 1 // 初始化 LED 颜色红1 蓝2 紫3 绿4 黄5 青6 白7 #endif #ifndef AS608_COLOR_SCAN #define AS608_COLOR_SCAN 3 // 扫描检测 LED 颜色 #endif10.2 引脚配置在 Tasmota 的模块/模板配置中为两个 GPIO 分别分配AS608 TX与AS608 RX对应GPIO_AS608_TX/GPIO_AS608_RX定义见 tasmota_template.h。驱动初始化时二者缺一不可且As608Init()在begin(57600)后调用verifyPassword()探测模块若使用硬件串口As608Serial-hardwareSerial()为真会自动ClaimSerial()防冲突ESP32 上还会记录实际 UART 编号。10.3 控制台命令驱动注册了三个命令xsns_79_as608.ino命令参数行为FpEnroll1~128开始向指定槽位注册指纹进入多步引导状态机FpEnroll 00中止当前注册FpEnroll无参—查询注册状态Active/InactiveFpDelete1~128删除指定 ID 的指纹FpDelete 00清空整个指纹库清空后校验templateCount是否为 0FpCount—返回当前已存储的指纹数量命令实现xsns_79_as608.ino中FpEnroll的 ID 上限为 128对应库容量上限删除与清空都实时回读getTemplateCount()验证结果。10.4 MQTT 事件与规则联动扫描循环每 250 ms 执行一次FUNC_EVERY_250_MSECOND匹配成功后发布{FPrint:{ID:3,Confidence:120}}未匹配时发布{FPrint:NOMATCH}。注册过程中的引导消息以FpEnroll为 JSON 键发布如 Place finger、Remove finger、Place same finger、Retry、Restart 等。因此可以基于 Tasmota 的 Rules 或 Berry 直接联动门锁继电器、Telegram 通知等——例如「FPrint.ID3 时开锁并推送告警」。Web UI 的传感器页还会显示AS608 {finger_id}-{confidence}FUNC_WEB_SENSOR分支。十一、最小可运行示例汇总仓库 examples 目录提供了 8 个可直接烧录的示例示例演示内容enroll完整注册流程取像→转特征→合并→存储fingerprint识别匹配与置信度输出ledcontrolLED 环呼吸/闪烁/渐变控制changepassword修改模块口令delete删除单枚指纹emptyDatabase清空指纹库show_fingerprint_templates模板导出/展示blank最小空壳工程一个可复用的最小 Arduino 骨架组合自官方示例#include Adafruit_Fingerprint.h SoftwareSerial mySerial(2, 3); Adafruit_Fingerprint finger Adafruit_Fingerprint(mySerial); void setup() { Serial.begin(9600); finger.begin(57600); if (!finger.verifyPassword()) { // 探测模块 Serial.println(No sensor found); while (1); } finger.getParameters(); // 读取容量/安全等级等参数 finger.getTemplateCount(); } void loop() { int id getFingerprintIDez(); // -1 未识别 delay(50); }十二、故障排查清单结合错误码与 Tasmota 驱动源码常见问题按优先级排查verifyPassword()返回 false / 一直无响应检查 TX/RX 是否接反传感器 TX 必须接主机 RX确认共地确认波特率默认 57600检查供电是否充足指纹模块瞬时电流较大FINGERPRINT_PACKETRECIEVEERR0x01串口帧校验失败优先怀疑线序、波特率或 Tasmota 侧 GPIO 冲突两个引脚必须同时分配且未被占用FINGERPRINT_IMAGEMESS0x06/FINGERPRINT_FEATUREFAIL0x07手指太湿/太干、按压位置偏移或图像质量差重试并让手指覆盖传感器中心区域FINGERPRINT_ENROLLMISMATCH0x0A两次采集不是同一手指注册流程会回退重试FINGERPRINT_BADLOCATION0x0B存储 ID 超出库容量AS608 驱动限制为 1~128Tasmota 中FpEnroll无响应确认固件已启用USE_AS608且 GPIO 已正确分配重启后观察日志中的AS6: Detected with N fingerprint(s) stored。结语Adafruit-Fingerprint-Tasmota-2.1.0 把复杂的指纹 DSP 交互封装成了清晰的分层结构上层是Adafruit_Fingerprint面向业务的 API注册、识别、删除、LED、口令底层是严谨的EF01结构化数据包协议。在 Tasmota 场景中它又通过 TasmotaSerial 串口抽象与xsns_79_as608.ino驱动层对接把指纹能力暴露为 GPIO 配置、控制台命令与 MQTT 事件使得纯本地、免云端的指纹门禁方案可以在一台 ESP8266/ESP32 设备上直接落地并与 Tasmota 的 Rules、Timers 生态自由组合。【免费下载链接】TasmotaAlternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at项目地址: https://gitcode.com/GitHub_Trending/ta/Tasmota创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询