yudao-cloud 开发指南 yudao-cloud 开发指南
  • 萌新必读
  • 后端手册
  • 微服务手册
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 前端手册 Vue 3.x
  • 前端手册 Vben 5.x
  • 前端手册 Vue 2.x
  • 前端手册 Admin Uniapp
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
视频教程
  • Vue3 + element-plus (opens new window)
  • Vue3 + vben5(ant-design-vue、element-plus) (opens new window)
  • Vue2 + element-ui (opens new window)
单体版 (opens new window)
作者博客 (opens new window)
GitHub (opens new window)
  • 萌新必读
  • 后端手册
  • 微服务手册
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 前端手册 Vue 3.x
  • 前端手册 Vben 5.x
  • 前端手册 Vue 2.x
  • 前端手册 Admin Uniapp
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
视频教程
  • Vue3 + element-plus (opens new window)
  • Vue3 + vben5(ant-design-vue、element-plus) (opens new window)
  • Vue2 + element-ui (opens new window)
单体版 (opens new window)
作者博客 (opens new window)
GitHub (opens new window)
  • 萌新必读

    • 简介
    • 交流群
    • 视频教程
    • 功能列表
    • 快速启动(后端项目)
    • 快速启动(前端项目)
    • 接口文档
    • 技术选型
    • 项目结构
    • 代码热加载
    • 一键改包
    • 迁移模块(适合新项目)
    • 删除功能(以租户为例)
    • 表结构变更(版本升级)
    • 国产信创数据库(DM 达梦、大金、OpenGauss、瀚高、OceanBase、TiDB、GaussDB、PolarDB、神通、Vastbase、MogDB、TongRDS、CacheDB)
    • 面试题、简历模版、简历优化
    • 项目外包
  • 后端手册

    • 新建服务
    • 代码生成【单表】(新增功能)
    • 代码生成【主子表】
    • 代码生成(树表)
    • 代码生成(移动端)
    • 功能权限
    • 数据权限
    • 用户体系
    • 三方登录
    • OAuth 2.0(SSO 单点登录)
    • SaaS 多租户【字段隔离】
    • SaaS 多租户【数据库隔离】
    • WebSocket 实时通信
    • 异常处理(错误码)
    • 参数校验、时间传参
    • 分页实现
    • VO 对象转换、数据翻译
    • 文件存储(上传下载)
    • Excel 导入导出
    • 操作日志、访问日志、异常日志
    • MyBatis 数据库
    • MyBatis 联表&分页查询
    • 多数据源(读写分离)、事务
    • Redis 缓存
    • 本地缓存
    • 异步任务
    • 分布式锁
    • 幂等性(防重复提交)
    • 请求限流(RateLimiter)
    • HTTP 接口签名(防篡改)
    • HTTP 接口加解密
    • 单元测试
    • 验证码
    • 工具类 Util
    • 数据库文档
  • 微服务手册

    • 微服务调试(必读)
    • 注册中心 Nacos
    • 配置中心 Nacos
    • 服务网关 Spring Cloud Gateway
    • 服务调用 Feign
    • 定时任务 XXL Job
    • 消息队列(内存)
    • 消息队列(Redis)
    • 消息队列(RocketMQ)
    • 消息队列(RabbitMQ)
    • 消息队列(Kafka)
    • 消息队列(Cloud)
    • 分布式事务 Seata
    • 服务保障 Sentinel
    • 分库分表
  • 工作流手册

    • 工作流演示
    • 功能开启
    • 工作流(达梦适配)
    • 审批接入(流程表单)
    • 审批接入(业务表单)
    • 流程设计器(BPMN)
    • 流程设计器(钉钉、飞书)
    • 选择审批人、发起人自选
    • 会签、或签、依次审批
    • 流程发起、取消、重新发起
    • 审批通过、不通过、驳回
    • 审批加签、减签
    • 审批转办、委派、抄送
    • 执行监听器、任务监听器
    • 流程表达式
    • 流程审批通知
    • 移动端审批
  • 大屏手册

    • 报表设计器
    • 大屏设计器
  • 支付手册

    • 功能开启
    • 支付宝支付接入
    • 微信公众号支付接入
    • 微信小程序支付接入
    • 支付宝、微信退款接入
    • 支付宝转账接入
    • 微信转账接入
    • 钱包充值、支付、退款
    • 模拟支付、退款
    • 移动端支付管理
  • 会员手册

    • 功能开启
    • 微信公众号登录
    • 微信小程序登录
    • 微信小程序订阅消息
    • 微信小程序码
    • 会员用户、标签、分组
    • 会员等级、积分、签到
    • 移动端会员管理
  • 商城手册

    • 商城演示
    • 功能开启
    • 商城装修
    • 在线客服
    • 【商品】商品分类
    • 【商品】商品属性
    • 【商品】商品 SPU 与 SKU
    • 【商品】商品评价
    • 【交易】购物车
    • 【交易】交易订单
    • 【交易】售后退款
    • 【交易】快递发货
    • 【交易】门店自提
    • 【交易】分销返佣
    • 【营销】优惠劵
    • 【营销】积分商城
    • 【营销】拼团活动
    • 【营销】秒杀活动
    • 【营销】砍价活动
    • 【营销】满减送活动
    • 【营销】限时折扣
    • 【营销】内容管理
    • 【统计】会员、商品、交易统计
    • 移动端商城管理
  • ERP手册

    • ERP 演示
    • 功能开启
    • 【产品】产品信息、分类、单位
    • 【库存】产品库存、库存明细
    • 【库存】其它入库、其它出库
    • 【库存】库存调拨、库存盘点
    • 【采购】采购订单、入库、退货
    • 【销售】销售订单、出库、退货
    • 【财务】采购付款、销售收款
    • 移动端 ERP
  • CRM手册

    • CRM 演示
    • 功能开启
    • 【线索】线索管理
    • 【客户】客户管理、公海客户
    • 【商机】商机管理、商机状态
    • 【合同】合同管理、合同提醒
    • 【回款】回款管理、回款计划
    • 【产品】产品管理、产品分类
    • 【通用】数据权限
    • 【通用】跟进记录、待办事项
    • 移动端 CRM
  • AI大模型手册

    • AI 大模型演示
    • 功能开启
    • AI 聊天对话
    • AI 绘画创作
    • AI 知识库(RAG)
    • AI 音乐创作
    • AI 写作助手
    • AI 思维导图
    • AI 工具(function calling)
    • AI 工作流
    • Dify 工作流
    • FastGPT 工作流
    • Coze 智能体
    • 推理模式(thinking)
    • 联网搜索
    • MCP Client 客户端
    • MCP Server 服务端
    • 【模型接入】Claude
    • 【模型接入】OpenAI
    • 【模型接入】通义千问
    • 【模型接入】DeepSeek
    • 【模型接入】字节豆包
    • 【模型接入】腾讯混元
    • 【模型接入】硅基流动
    • 【模型接入】MiniMax
    • 【模型接入】月之暗面
    • 【模型接入】百川智能
    • 【模型接入】文心一言
    • 【模型接入】LLAMA
    • 【模型接入】智谱 GLM
    • 【模型接入】讯飞星火
    • 【模型接入】微软 OpenAI
    • 【模型接入】谷歌 Gemini
    • 【模型接入】Stable Diffusion
    • 【模型接入】Midjourney
    • 【模型接入】Suno
    • 【模型接入】Grok
    • 【模型接入】阶跃星辰
    • 移动端 AI 大模型
  • IoT物联网手册

    • 功能开启
    • 产品管理
    • 设备管理
    • 物模型配置
    • 设备网关与子设备
    • 设备动态注册
    • 设备影子
    • 消息透传与数据解析
      • 1. 功能概述
        • 1.1 透传方法
        • 1.2 哪些消息会执行脚本
        • 1.3 上行的处理结果
        • 1.4 下行的处理结果
      • 2. 配置
        • 2.1 开启网关的脚本开关
        • 2.2 数据存储
      • 3. 编写脚本
        • 3.1 decode(ctx)
        • 3.2 encode(ctx)
        • 3.3 完整示例
        • 3.4 运行约束
      • 4. 管理后台
        • 4.1 产品数据解析
        • 4.2 脚本调试
        • 4.3 透传下发
        • 4.4 设备消息
        • 4.5 接口
      • 5. 快速体验(MQTT)
      • 6. 各协议的透传入口
        • 6.1 协议差异
        • 6.2 Modbus
      • 7. 常见问题
    • 设备接入(概述)
    • 设备接入(HTTP 协议)
    • 设备接入(MQTT 协议)
    • 设备接入(EMQX 协议)
    • 设备接入(TCP 协议)
    • 设备接入(UDP 协议)
    • 设备接入(WebSocket 协议)
    • 设备接入(CoAP 协议)
    • 设备接入(Modbus Client 模式)
    • 设备接入(Modbus Server 模式)
    • 设备接入(自定义协议)
    • 场景联动
    • 数据流转
    • 告警配置
    • OTA 固件升级
    • 移动端 IoT 物联网
  • MES手册

    • MES 演示
    • 功能开启
    • 【基础】物料产品、分类、计量单位
    • 【基础】客户管理、供应商管理
    • 【基础】车间设置、工作站设置
    • 【基础】编码规则
    • 【生产】工序设置、工艺流程
    • 【生产】生产工单
    • 【生产】生产排产、工序流转卡
    • 【生产】生产报工
    • 【生产】安灯配置、安灯呼叫
    • 【生产】工作记录
    • 【仓库】仓库与库区库位、条码赋码、SN码
    • 【仓库】批次管理、库存现有量、库存事务
    • 【仓库】到货通知、采购入库、采购退货
    • 【仓库】生产领料、生产退料、物料消耗
    • 【仓库】产品产出、产品入库
    • 【仓库】发货通知、销售出库、销售退货
    • 【仓库】外协发料、外协入库
    • 【仓库】其他入库、其他出库
    • 【仓库】调拨单、装箱管理
    • 【仓库】库存盘点
    • 【质量】检测项设置、常见缺陷
    • 【质量】质检方案
    • 【质量】来料检验(IQC)
    • 【质量】过程检验(IPQC)
    • 【质量】出货检验(OQC)
    • 【质量】退货检验(RQC)
    • 【质量】待检任务、检验结果、缺陷记录
    • 【设备】设备类型、设备台账
    • 【设备】点检保养项目、点检保养方案
    • 【设备】点检记录、保养记录、维修单
    • 【工具】工具类型、工装夹具台账
    • 【排班】班组设置、节假日设置
    • 【排班】排班计划、排班日历
    • 移动端 MES
  • WMS手册

    • WMS 演示
    • 功能开启
    • 【基础】仓库
    • 【基础】商品、SKU、分类、品牌
    • 【基础】往来企业(供应商、客户)
    • 【库存】库存记录、流水、统计
    • 【单据】入库
    • 【单据】出库
    • 【单据】移库
    • 【单据】盘库
    • 【其它】WMS、MES、ERP 对比
    • 移动端 WMS
  • HRM人力资源

    • HRM 演示
    • 功能开启
    • 【组织】工作台、组织架构
    • 【员工】员工管理
    • 【招聘】招聘管理
    • 【考勤】考勤管理
    • 【社保】社保管理
    • 【薪资】计薪设置、薪资档案
    • 【薪资】月度工资、工资条
    • 【绩效】绩效模板、绩效计划
    • 【绩效】绩效考核、绩效档案
    • 移动端 HRM
  • FMS财务管理

    • FMS 演示
    • 功能开启
    • 【设置】账套管理、财务参数、财务指标
    • 【设置】币别、科目、辅助核算、初始余额
    • 【设置】凭证字、常用摘要、凭证模板
    • 【凭证】凭证管理
    • 【账簿】账簿管理
    • 【报表】财务报表
    • 【结账】期末结账
    • 移动端 FMS
  • PMS项目管理

    • PMS 演示
    • 功能开启
    • 【项目中心】工作台与项目管理
    • 【项目中心】项目详情与迭代
    • 【项目中心】工作项与协作
    • 【知识中心】知识库管理
    • 【知识中心】文档与协作
    • 移动端 PMS
  • OA协同办公

    • OA 演示
    • 功能开启
    • 【协作】日程、任务、计划与汇报
    • 【协作】公告、讨论、通讯录与笔记
    • 【办公】企业邮箱
    • 【办公】企业云盘
    • 【行政】办公用品、用印管理
    • 【行政】会议室、车辆管理
    • 【流程】公文管理
    • 【流程】出差、费用报销
    • 【流程】考勤、请假、加班、转正与离职
    • 移动端 OA
  • IM即时通讯手册

    • IM 演示
    • 功能开启
    • 【好友】好友关系、好友申请
    • 【群聊】群组、群成员、入群申请
    • 【消息】私聊、群聊、频道消息
    • 【频道】频道、频道素材
    • 【内容】表情、敏感词
    • 【通话】语音通话、视频通话、共享屏幕
    • 【WebSocket】实时推送与离线消息
    • 移动端 IM 即时通讯
  • 公众号手册

    • 功能开启
    • 公众号接入
    • 公众号粉丝
    • 公众号标签
    • 公众号消息
    • 模版消息
    • 自动回复
    • 公众号菜单
    • 公众号素材
    • 公众号图文
    • 公众号统计
    • 移动端公众号管理
  • 系统手册

    • 短信配置
    • 邮件配置
    • 站内信配置
    • Webhook(钉钉、飞书、企微)
    • 数据脱敏
    • 敏感词
    • 地区 & IP 库
  • 运维手册

    • 开发环境
    • Linux 部署
    • Docker 部署
    • Jenkins 部署
    • 宝塔部署
    • 1Panel 部署
    • Docker Compose 部署
    • Kubernetes 部署
    • HTTPS 证书
    • 服务监控
    • Tomcat WAR 部署
    • 东方通服务器部署(TongWeb、TongHttpServer)
    • 宝兰德服务器部署(BES AppServer)
    • 内网穿透
  • 前端手册 Vue 3.x

    • 开发规范
    • 菜单路由
    • Icon 图标
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
    • CRUD 组件
    • 国际化
    • IDE 调试
    • 代码格式化
  • 前端手册 Vben 5.x

    • 开发规范
    • 菜单路由
    • 图标、主题、国际化
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
    • IDE 调试
    • 代码格式化
  • 前端手册 Vue 2.x

    • 开发规范
    • 菜单路由
    • Icon 图标
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
  • 前端手册 Admin Uniapp

    • 开发规范
    • 菜单路由
    • 图标、主题、国际化
    • 字典数据
    • 系统组件
    • 通用方法
    • IDE 调试
    • 代码格式化
    • 运行发布
  • 更新日志

    • 【v2026-10】
    • 【v2026-09】
    • 【v2026-08】
    • 【v2026-07】
    • 【v2026-06】
    • 【v2026-05】
    • 【v2026-04】
    • 【v2026-03】
    • 【v2026-01】
    • 【v2025-12】
    • 【v2025-11】
    • 【v2025-10】
    • 【v2025-09】
    • 【v2025-08】
  • 开发指南
  • IoT物联网手册
芋道源码
2026-10-28
目录

消息透传与数据解析

推荐阅读:

  • 《设备接入(概述)》 — 了解 IotDeviceMessage 消息格式
  • 《设备接入(MQTT 协议)》 — 下文的快速体验使用 MQTT 协议
  • 《阿里云物联网平台 —— JavaScript 数据解析脚本模板和示例》 (opens new window)
  • 《阿里云物联网平台 —— 编写数据解析脚本解析设备透传数据》 (opens new window)

很多设备不会发送标准的 JSON 消息,只会收发自定义的二进制帧(例如 AA 01 00 FA 3C)。消息透传与数据解析,用来接入这类设备:

  • 消息透传(raw):设备把原始字节发到网关的透传入口,平台原样保存;平台也可以把原始字节原样下发给设备
  • 数据解析:为产品配置一段 JavaScript 脚本,decode 把上行的原始字节解析为标准消息,encode 把下行的属性设置、服务调用编码为字节

例如:

  • 温湿度传感器上报 5 个字节,解析为 thing.property.post 属性上报,之后与标准设备一样保存属性、触发场景联动
  • 管理后台对设备「属性设置」,由脚本编码为设备能识别的控制帧
  • 还没写好脚本时,先透传接入,在「设备消息」中查看设备实际发送的原始帧(HEX)

整体流程如下:

上行:设备 ──原始字节──▶ 网关透传入口 ──decode(ctx)──▶ 一条标准消息(带原始帧)──▶ 平台
                                        └─ 未启用脚本 / 返回 null ──▶ thing.raw.post(只带原始帧)

下行:thing.property.set、thing.service.invoke ──encode(ctx)──▶ {bytes} 透传写出 / {standard: true} 按原格式下发
      thing.raw.push(管理后台透传下发) ─────────────────────▶ 原样写出,不经过脚本

脚本由 yudao-module-iot-gateway 网关模块执行;脚本的保存、调试由 yudao-module-iot-server 模块提供,两者共用 yudao-module-iot-core 中的 IotScriptUtils 脚本契约(入参构造、输出校验)。

# 1. 功能概述

# 1.1 透传方法

method 方向 说明
thing.raw.post 上行 透传上报:没有解析为业务消息的原始帧。只能由网关的透传入口生成,设备不能通过标准 JSON 发送,管理后台也不能模拟
thing.raw.push 下行 透传下发:管理后台「模拟设备 → 透传下发」发送,原样写出给设备,不经过 encode

两者的原始字节都保存在消息的 raw 字段(Base64),「设备消息」中按 HEX 展示。解析成功的业务消息,同样带有 raw 字段。

# 1.2 哪些消息会执行脚本

不是所有消息都经过脚本,只有下表中「执行」的几种情况:

场景 是否执行脚本
设备通过透传入口上报的原始字节(见「6. 各协议的透传入口」) 执行 decode
平台下发的 thing.property.set、thing.service.invoke 请求 执行 encode
Modbus 设备对 encode 编码下发的指令的响应 执行 decode(带 ctx.request)
设备通过标准主题、路径上报的 JSON 消息 不执行,保持原有处理
thing.raw.push 透传下发 不执行,原样写出;Modbus 设备的响应直接记录为回复
其它下行:各类 _reply 回复、配置推送、OTA、设备影子、拓扑等 不执行,按原协议的标准格式下发
连接认证、动态注册等 不执行

因此,使用脚本的设备如需 OTA、设备影子 等功能,仍按该协议原有的标准消息格式收发,能否使用取决于该协议原有的支持能力。

# 1.3 上行的处理结果

每次透传上报,最多投递一条消息:

情况 结果
网关的脚本开关关闭(默认),或产品脚本停用、未配置 投递一条 thing.raw.post,只带原始帧
decode 返回一条消息 投递这条业务消息,raw 字段带上原始帧
decode 返回 null、undefined,或脚本没有定义 decode 投递一条 thing.raw.post,只带原始帧
脚本执行出错、超时、繁忙或已熔断、输出不合法 不投递任何消息,只在网关日志中记录(HTTP、CoAP 在响应中返回错误码)

注意:透传上报解析出的消息,平台不会自动回复 _reply(例如 thing.property.post_reply)。

# 1.4 下行的处理结果

thing.property.set、thing.service.invoke 下行时,网关按产品脚本的 encode 决定如何下发:

情况 结果
网关的脚本开关关闭,或产品脚本停用、未配置 按原协议的标准格式下发
encode 返回 { bytes: [...] } 按协议透传写出这些字节
encode 返回 { standard: true } 按原协议的标准格式下发
encode 返回 null、undefined,或没有定义 encode 不下发,只在网关日志中记录(不会改为按标准格式下发)
脚本执行出错、超时、输出不合法 不下发,只在网关日志中记录

网关脚本开关开启时,同一设备的指令按收到的顺序依次处理,每个设备最多排队 256 条,超出的指令丢弃并记录日志。

传输确认 ≠ 业务结果

  • 管理后台「属性设置」「透传下发」提示成功,只表示平台已把指令交给网关,不代表设备已收到;网关写出成功,也只表示已写入设备连接(MQTT 为 publish 已提交)。
  • MQTT 透传上报的 PUBACK,只表示网关已处理完本次上报,不代表脚本解析成功。
  • HTTP、CoAP 透传上报的最终响应,是网关对本次解析、投递的反馈:成功时 code 为 0、data.messageId 为投递的消息编号,失败时返回错误码(见「6.1 协议差异」),可据此排查。CoAP 的 CON 请求先收到的空 ACK 只是传输确认,结果以之后的分离响应为准。
  • 以上都不代表平台已处理完这条消息,也不代表设备已执行完成。设备的执行结果,需要设备回执:decode 返回带 code 的回执(见「3.1 decode」),或 Modbus 的实际响应,才会出现在「设备消息」中。网关判定的失败(设备离线、写出失败、Modbus 超时或断线等)只记录网关日志,不会生成失败回复。

# 2. 配置

# 2.1 开启网关的脚本开关

在网关的 application.yaml 中开启,默认关闭:

yudao:
  iot:
    gateway:
      script:
        enabled: true                         # 是否开启数据解析脚本,默认 false
        deadline: 2s                          # 截止时间,默认 2s
        exec-budget: 500ms                    # 单次脚本执行的时间预算,默认 500ms
        max-instructions: 1000000             # 单次脚本执行的指令上限,默认 1000000
        max-pending-commands-per-device: 256  # 每个设备最多排队的下行指令数,默认 256

对应 IotGatewayProperties.ScriptProperties 配置类,一般只需修改 enabled。

① deadline:只作用于透传上报和脚本的处理,标准 JSON 消息、thing.raw.push 不受影响:

  • 透传上报:从网关收到开始计算,覆盖排队、执行 decode;投递前已超过时不投递(开关关闭时也会核对排队时间)。HTTP、CoAP 也在这个时间内应答
  • encode:从网关收到下行指令开始计算,覆盖按设备排队、执行 encode;写出前已超过时不下发,之后的网络写出不受它限制
  • Modbus 设备响应的 decode:从收到响应开始计算;超过时不记录回复

截止时间只在投递、写出之前检查,已经开始的投递或写出不会撤销。因此 HTTP、CoAP 返回超时后,消息仍可能已投递,有副作用的操作不宜盲目重试。

② exec-budget:单次脚本的执行时间,与 deadline 剩余的时间取较早者。

③ 开关关闭时:透传上报只记录 thing.raw.post,下行指令按标准格式下发,thing.raw.push 照常原样写出。

④ 管理后台的脚本保存、调试,在平台(yudao-module-iot-server)执行,不受这个网关开关影响。

# 2.2 数据存储

产品的数据解析脚本,保存在 iot_product 表;网关随设备信息缓存使用:

字段 类型 说明
script_content TEXT 数据解析脚本,JavaScript ES5,UTF-8 不超过 32KB
script_enabled BIT(1) 是否启用,默认关闭

设备消息的原始帧,保存在时序库设备消息表 device_message 的 raw 列(原始字节的 Base64),由对应的 Mapper 建表:

  • TDengine:raw VARCHAR(8192),见 IotDeviceMessageMapper.xml 的 createSTable
  • IoTDB:raw STRING FIELD,见 IotDeviceMessageIoTDBMapper.xml 的 createTable

# 3. 编写脚本

脚本使用 JavaScript ES5 语法,定义 decode(ctx)、encode(ctx) 两个函数,可以只定义其中一个。函数名与入参和阿里云不同,不能直接复制阿里云的脚本。

# 3.1 decode(ctx)

上行时调用,ctx 的字段如下:

字段 说明
direction 固定为 decode
protocol 协议类型,例如 mqtt、tcp、modbus_tcp_client
productKey 产品标识
deviceName 设备名称(脚本调试时固定为 debug-device)
receivedAt 接收时间,毫秒时间戳
bytes 原始字节,无符号整数数组,每个元素 0~255
hex 原始字节的 HEX 字符串,大写、无空格
request 仅 Modbus 透传事务的响应才有:原请求的 { method, requestId, params },普通上行没有该字段

返回值为一条标准消息对象(不要再包一层 messages、result),或者 null:

字段 说明
method 必填。上报只能是 thing.property.post、thing.event.post
params 上报时必填,必须是对象。属性上报为 { 标识符: 值 },事件上报为 { identifier, value, time? }
requestId 可选,不超过 50 个字符;不填时由平台生成
code 可选,整数。有值时表示回执:method 只能是 thing.property.set、thing.service.invoke,且必须带 requestId
msg 可选,回执的说明,不超过 256 个字符
data 可选,回执的数据

① 不能返回 id、deviceId、raw 等其它字段,消息编号、时间、设备身份、原始帧都由平台设置。

② params、data 序列化后各不超过 8192 字节(UTF-8),事件的 identifier 为 1~100 个字符。

③ 如果设备会回执下行指令,可以在 decode 中返回回执,例如 { method: 'thing.property.set', requestId: '...', code: 0 }。requestId 需与下发的请求一致(可在 encode 时把 ctx.message.requestId 编进帧里),「设备消息」中的请求才能与回执配对。

# 3.2 encode(ctx)

下发 thing.property.set、thing.service.invoke 请求时调用,ctx 的字段如下:

字段 说明
direction 固定为 encode
protocol 协议类型
productKey 产品标识
deviceName 设备名称
message 下行指令 { method, requestId, params }。属性设置的 params 为 { 标识符: 值 },服务调用为 { identifier, inputParams }

返回值三选一:

  • { bytes: [...] }:透传写出的字节,每个元素为 0~255 的整数。Modbus 协议必须是合法的请求 PDU(见「6.2 Modbus」),其它协议为 1~4096 字节
  • { standard: true }:这条指令按原协议的标准格式下发
  • null:不下发

bytes 和 standard 只能返回一个,也不能带其它字段。

# 3.3 完整示例

假设设备使用如下的帧格式:

方向 帧 说明
上行 AA 01 + 温度(2 字节)+ 湿度(1 字节) 属性上报。温度为 int16 大端,单位 0.1℃;湿度为 uint8,单位 %
上行 AA 02 + 告警级别(1 字节) 告警事件
下行 AA 81 + 开关(1 字节) 设置开关:00 关、01 开

对应的产品物模型有:属性 temperature(float)、humidity(int)、power(bool,读写),事件 alarm(输出参数 level,int)。脚本如下:

/**
 * 上行:原始字节 → 一条标准消息;返回 null 表示没有业务消息(记录为 thing.raw.post)
 */
function decode(ctx) {
  var b = ctx.bytes; // 无符号字节数组,每个元素 0~255
  if (b.length < 2 || b[0] !== 0xAA) {
    return null;
  }
  // AA 01:属性上报
  if (b[1] === 0x01 && b.length >= 5) {
    var t = (b[2] << 8) | b[3];
    if (t > 0x7FFF) {
      t -= 0x10000; // int16 负数
    }
    return {
      method: 'thing.property.post',
      params: {
        temperature: t / 10,
        humidity: b[4]
      }
    };
  }
  // AA 02:告警事件
  if (b[1] === 0x02 && b.length >= 3) {
    return {
      method: 'thing.event.post',
      params: {
        identifier: 'alarm',
        value: { level: b[2] },
        time: ctx.receivedAt
      }
    };
  }
  return null;
}

/**
 * 下行:thing.property.set、thing.service.invoke → 下发的字节
 */
function encode(ctx) {
  var msg = ctx.message;
  if (msg.method === 'thing.property.set' && msg.params && msg.params.power !== undefined) {
    return { bytes: [0xAA, 0x81, Number(msg.params.power) ? 1 : 0] };
  }
  // 其它指令,按原协议的标准格式下发
  return { standard: true };
}

例如,上行 AA 01 00 FA 3C 解析为:

{
  "method": "thing.property.post",
  "params": {
    "temperature": 25,
    "humidity": 60
  }
}

下行属性设置 { "power": 1 },编码为 AA 81 01。

# 3.4 运行约束

① 语法:ES5(Rhino 引擎)。不要使用箭头函数、class、模板字符串等 ES6+ 语法;没有 console、Buffer、TextDecoder、setTimeout 等宿主对象,也不能访问任何 Java 类。

② 无状态:每次调用都在新的作用域中重新执行脚本的顶层代码,调用之间不能保存状态;Array.prototype 等标准对象不能修改。

③ 大小:脚本 UTF-8 不超过 32KB;透传上报的原始字节 1~4096 字节;脚本返回值序列化后不超过 65536 个字符。

④ 执行预算:单次执行不超过 500ms(exec-budget)、100 万条指令(max-instructions),递归深度不超过 64 层,超过按超时或出错处理。

⑤ 熔断:同一脚本(按内容区分)在一个网关节点 1 分钟内超时 3 次,该节点之后的调用直接拒绝。修改脚本内容、或重启网关后恢复。

⑥ 脚本与网关运行在同一个 JVM 中,以上约束只限制执行时间和调用方式,不是进程级的资源隔离。

# 4. 管理后台

本节截图均为示例:使用「3.3 完整示例」的脚本和示例数据。

# 4.1 产品数据解析

对应 [IoT 物联网 -> 设备接入 -> 产品管理] 菜单,进入产品详情的「数据解析」Tab。对应前端项目的文件:

  • Vue3:src/views/iot/product/product/detail/ProductDetailsScript.vue
  • Vben Antd / Ele:apps/web-antd、apps/web-ele 下的 src/views/iot/product/product/detail/modules/script.vue
  • Admin Uniapp:src/pages-iot/product/product/components/script-section.vue

管理后台 - 产品数据解析(示例)

① 保存并生效:只保存脚本内容,不改变启用状态。保存时检查长度和语法(只编译,不执行),有语法错误时提示行号。

② 启用 / 停用:只修改启用状态,启用的是已保存的内容。启用时脚本内容不能为空;清空脚本内容,需要先停用。

③ 恢复为已保存内容:放弃编辑区未保存的修改。脚本没有草稿、历史版本,未保存的修改只保留在当前页面。

④ 已保存内容:展示已保存内容的 SHA-256 前 12 位,与网关熔断日志中的 hash(...) 对应,便于确认是哪一版脚本。

生效时间

保存、启用、停用后,不是立即对设备生效:网关按设备在本地缓存设备信息(包括产品的脚本),缓存写入 1 分钟后,下一次访问时才异步刷新,刷新完成前仍使用旧的脚本。测试时,可以重启网关立即生效。

# 4.2 脚本调试

「数据解析」Tab 右侧的调试面板,执行当前编辑区的内容(未保存也可以)。调试不保存脚本、不发送给设备、不修改属性,使用与网关相同的运行约束和输出校验。

管理后台 - 脚本调试(示例)

① 上行解码:输入原始字节的 HEX(允许空格,1~4096 字节),展示解析出的消息。返回 null 时提示「无业务消息」,实际上报时记录为 thing.raw.post。

② 下行编码:输入下行指令 JSON,method 只能是 thing.property.set、thing.service.invoke,展示下发方式及输出的 HEX。返回 null 时提示 ENCODE_EMPTY。

③ 失败类型:ERROR 脚本出错(带行号)、TIMEOUT 超时、REJECTED 调试繁忙或已熔断、OUTPUT_INVALID 输出不合法、ENCODE_EMPTY 未生成下行数据。

调试时 ctx.deviceName 固定为 debug-device,ctx.protocol 为产品的协议类型。

# 4.3 透传下发

进入设备详情的「模拟设备」Tab,切换到「透传下发」,输入载荷 HEX 后发送,下发 thing.raw.push。对应 Vue3 的 DeviceDetailsSimulator.vue 文件。

管理后台 - 透传下发(示例)

① 字节原样写出给设备,不经过 encode,也不受网关脚本开关影响。

② HTTP、CoAP 协议的产品不支持透传下发。

③ 普通协议为 1~4096 字节;Modbus 协议填写 PDU(功能码 + 数据,不含从站地址、CRC、MBAP),5~253 字节,写操作会二次确认功能码和地址。

④ 「模拟设备」不提供透传上报的模拟。验证 decode,请使用「4.2 脚本调试」,或参考「5. 快速体验」用真实客户端上报。

# 4.4 设备消息

进入设备详情的「设备消息」Tab,「原始帧(HEX)」列展示消息的 raw 字段,可以复制;支持按「有原始帧」「无原始帧」筛选。对应 Vue3 的 DeviceDetailsMessage.vue 文件。

管理后台 - 原始帧消息(示例数据)

消息 原始帧
透传上报解析出的业务消息、thing.raw.post 设备上报的原始字节
thing.raw.push 透传下发 下发的字节
Modbus 透传事务的回复 设备响应的 PDU
encode 编码下发的属性设置、服务调用 无:记录的是平台下发的标准指令,不含编码后的字节

# 4.5 接口

接口 说明 权限
PUT /iot/product/update-script 更新数据解析脚本(只修改提交的 scriptContent、scriptEnabled) iot:product:update
POST /iot/product/debug-script 调试数据解析脚本 iot:product:update
POST /iot/device/message/send 发送消息;method 为 thing.raw.push 时,params 为 { "payload": "Base64" } iot:device:message-send,透传下发另需 iot:device:message-raw-send
GET /iot/device/message/page 设备消息分页;raw=true 只看有原始帧的消息 iot:device:message-query

# 5. 快速体验(MQTT)

下面以 MQTT 协议的直连设备为例,使用 MQTTX (opens new window) 模拟设备,跑通「透传上报 → 解析 → 属性设置编码 → 透传下发」。

请将主题中的 {productKey}、{deviceName} 替换为实际值。

① 准备物模型:在 MQTT 产品的「物模型(功能定义)」中,新增「3.3 完整示例」中的属性 temperature、humidity、power(事件 alarm 可选)。也可以把脚本中的标识符,改为产品已有的属性。

② 开启网关开关:按「2.1 开启网关的脚本开关」设置 enabled: true,重启网关。

③ 配置脚本:进入产品详情的「数据解析」Tab,粘贴「3.3 完整示例」的脚本,点击「保存并生效」,再点击「启用」。

④ 调试脚本:在右侧调试面板中验证:

  • 上行解码,输入 AA 01 00 FA 3C,解析出 temperature 为 25、humidity 为 60 的属性上报
  • 下行编码,输入 {"method": "thing.property.set", "requestId": "debug-1", "params": {"power": 1}},输出 HEX 为 AA8101

⑤ 连接设备:按 《设备接入(MQTT 协议)》 的「4.1 连接认证」连接设备,并订阅 /sys/{productKey}/{deviceName}/thing/raw/push 主题。如果网关在 ③ 之前已经访问过该设备,等待约 1 分钟让网关刷新缓存,或重启网关。

⑥ 透传上报:发布到 /sys/{productKey}/{deviceName}/thing/raw/post 主题,Payload 格式选择 Hex,内容为 AA0100FA3C。

  • 「设备消息」中出现一条 thing.property.post,原始帧为 AA 01 00 FA 3C
  • 「物模型数据」中,temperature 为 25、humidity 为 60

再发布一个脚本不认识的帧,例如 AA09,「设备消息」中出现一条只带原始帧的 thing.raw.post。

⑦ 属性设置:在「模拟设备 → 下行指令调试 → 属性设置」中,设置 power 为 1,MQTTX 在 raw/push 主题收到字节 AA 81 01(按 Hex 查看)。

⑧ 透传下发:在「模拟设备 → 透传下发」中,输入 AA 7F 发送,MQTTX 在 raw/push 主题收到原样的 AA 7F。「设备消息」中出现一条带原始帧的 thing.raw.push。

# 6. 各协议的透传入口

透传入口与标准消息的入口相互独立:设备通过标准主题、路径发送的 JSON 消息,处理方式不变;标准路径也不接受 thing.raw.post、thing.raw.push 方法。

# 6.1 协议差异

协议 透传上报 透传下行 设备侧的应答
MQTT 发布到 /sys/{productKey}/{deviceName}/thing/raw/post 发布到 /sys/{productKey}/{deviceName}/thing/raw/push,QoS 1 处理完成后回 PUBACK,与解析是否成功无关
EMQX 同 MQTT 主题,经 EMQX 转发给网关 同 MQTT,经 EMQX 发布 由 EMQX 应答;多条透传上报并行处理,不保证顺序
HTTP POST /topic/sys/{productKey}/{deviceName}/thing/raw/post,Content-Type: application/octet-stream,Authorization 携带 Token 不支持 同一请求内响应:成功返回 data.messageId,失败返回错误码
CoAP POST /topic/sys/{productKey}/{deviceName}/thing/raw/post,Content-Format 为 42(application/octet-stream),Option 2088 携带 Token 不支持 CON 请求先回空 ACK,再分离响应结果;超过截止时间返回超时错误码
TCP 认证时 params.mode 传 raw,之后该连接的每一帧(仍按配置的拆包器切分)都是原始字节 按拆包器加帧后写出;非透传连接不支持 无
UDP 报文 49 52 01 + Token 长度(2 字节大端)+ Token(UTF-8)+ 原始字节 报文 49 52 01 00 00 + 原始字节,发往设备会话的地址 无
WebSocket text 帧认证后,binary 帧为原始字节 binary 帧 无
Modbus 无透传上报,轮询按原有点位配置处理 写出 PDU,网关负责封装帧 设备的实际响应,见「6.2 Modbus」

① HTTP、CoAP 透传上报失败时返回的错误码,例如 1051003101 处理超时、1051003102 脚本繁忙或已熔断、1051003103 输出不合法、1051003100 执行失败。

② TCP 认证消息示例(仍使用 JSON 序列化),其它字段见 《设备接入(TCP 协议)》:

{
  "method": "auth",
  "params": {
    "clientId": "...",
    "username": "...",
    "password": "...",
    "mode": "raw"
  }
}

透传连接建议使用 length_field 或 fixed_length 拆包器,避免原始字节中出现分隔符。

③ 各协议的连接认证、Token 获取等,参见对应的协议文档:HTTP、MQTT、EMQX、TCP、UDP、WebSocket、CoAP、Modbus Client、Modbus Server。

# 6.2 Modbus

Modbus Client、Modbus Server 的透传下行,内容都是 PDU(功能码 + 数据),不带从站地址、CRC、MBAP,由网关按设备配置封装。

① PDU 规则:5~253 字节,功能码只能是 01、02、03、04、05、06、0F、10,并校验数量、字节数(例如读寄存器数量 1~125)。透传下发、encode 的输出都按这个规则校验。

② 事务:每个连接最多 32 个透传请求在途或排队;超时沿用原有配置(Modbus Client 为设备连接配置的超时时间,Modbus Server 为 request-timeout)。

③ 设备响应:

  • thing.raw.push:直接把设备响应的 PDU 作为回复,异常响应(功能码最高位为 1)的回复带错误码
  • encode 下发的指令:用 encode 时的脚本执行 decode,ctx.request 为原请求,必须返回 method、requestId 与原请求一致的回执,否则不记录回复
  • 超时、断线、写出失败等网关判定的失败,只记录网关日志

例如,用「写单个寄存器」设置开关,并解析响应:

function encode(ctx) {
  var msg = ctx.message;
  if (msg.method === 'thing.property.set' && msg.params && msg.params.power !== undefined) {
    // 06:写单个寄存器,地址 0x0001,值 0 / 1
    return { bytes: [0x06, 0x00, 0x01, 0x00, Number(msg.params.power) ? 1 : 0] };
  }
  return { standard: true }; // 其它指令,按点位配置下发
}

function decode(ctx) {
  if (!ctx.request) {
    return null;
  }
  var ok = (ctx.bytes[0] & 0x80) === 0; // 功能码最高位为 1 表示异常响应
  return {
    method: ctx.request.method,
    requestId: ctx.request.requestId,
    code: ok ? 0 : 500,
    msg: ok ? '成功' : 'Modbus 异常码 ' + ctx.bytes[1]
  };
}

# 7. 常见问题

现象 排查
透传上报只看到 thing.raw.post 网关脚本开关未开启;产品脚本未启用;decode 返回了 null;网关缓存还没刷新(见「4.1」的生效时间)
透传上报后,设备消息中什么都没有 脚本出错、超时、输出不合法或已熔断,查看网关日志中的 [sendRawMessage];HTTP、CoAP 查看响应中的错误码
属性设置提示成功,设备没有收到 encode 返回 null 或出错、设备离线、TCP 连接不是透传连接,查看网关日志中的 [encodeDownstreamCommand]、[writeRawMessage]
设备收到的是 JSON,不是字节 网关脚本开关未开启、产品脚本未启用,或 encode 返回了 { standard: true }
设备收不到 property/post_reply 透传上报解析出的消息,平台不自动回复
Modbus 透传下发提示 PDU 不合法 只填写 PDU(功能码 + 数据),不要带从站地址、CRC、MBAP
保存、调试提示繁忙或已熔断 平台的调试执行器繁忙(同时最多执行 2 个、排队 4 个)或已熔断,稍后重试;仍然失败时,修改脚本内容或重启平台
网关日志提示脚本熔断 脚本 1 分钟内超时 3 次,检查是否有死循环、大循环,修改脚本内容后恢复
设备影子
设备接入(概述)

← 设备影子 设备接入(概述)→

Theme by Vdoing | Copyright © 2019-2026 芋道源码 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×