22107-DSOD705 溢油监测 通过EdgeBus 接入ThinkLink

1. 传感器简介

DSOD705 是一款 非接触式水面溢油检测传感器 ,由地森合志 / DISEN 提供。设备基于 紫外荧光检测原理,通过向水面发射紫外脉冲,激发油类物质产生荧光,并通过光电接收与数据处理模块判断水面是否存在油污。

该传感器主要用于实时检测水面油污、漏油、溢油和浮油,可检测原油、柴油、燃料油、机油、润滑油、汽油、航空煤油等多种石油类物质。设备支持 RS-485 / Modbus RTU 输出,可通过 KC11 采集器接入 LoRaWAN 网络,再由 ThinkLink 平台完成数据解析、展示、告警和第三方系统转发。


2. 产品特点

DSOD705 的主要特点如下:

  1. 非接触式检测
    传感器安装在水面上方,无需直接接触被测水体,可减少油污附着、生物附着和人工清洗维护。
  2. 紫外荧光检测原理
    利用油类物质的天然荧光特性进行检测,适合识别水面石油类污染物。
  3. 高灵敏度
    可检测低至约 1 μm 厚度的油膜,适合早期溢油预警。
  4. 全天候在线监测
    支持 24 小时连续监测,不受白天或夜晚光照条件限制。
  5. RS-485 / Modbus RTU 输出
    便于接入工业现场采集系统、监控系统或通过 KC11 转换为 LoRaWAN 上报。
  6. 支持报警联动
    设备本体支持继电器输出,可用于本地报警或联动控制。
  7. 高防护等级
    说明书中描述设备具有 IP66/IP67 或 IP68 高防护能力,适合户外和复杂工业环境使用。
  8. 低功耗运行
    设备功耗低,说明书中标注直流功耗小于 2 W,部分说明中也提到低功耗运行小于 10 W。

3. 适用范围

DSOD705 适用于工业与环境领域的水面油污在线监测,典型应用场景包括:

  • 石油开采企业
  • 船舶
  • 海上平台
  • 港口码头
  • 石油化工厂
  • 储油站、油库
  • 电力站 / 发电厂
  • 气体压缩站
  • 污水处理厂
  • 河道、湖泊
  • 工业排水口
  • 水环境安全监测场景

4. 采集器信息

4.1 硬件信息

本方案采用 KC11 作为 RS-485 数据采集与 LoRaWAN 接入设备。

|--------|--------------------------|
| 项目 | 内容 |
| 采集设备型号 | KC11 |
| 接口类型 | RS-485 |
| 上行通信 | LoRaWAN |
| 供电方式 | 220 V 供电 |
| 接入传感器 | DSOD705 水面溢油检测传感器 |
| 协议 | Modbus RTU |
| 默认串口参数 | 9600 bps,8 数据位,1 停止位,无校验 |

4.2 接线信息

电源与通讯接口

DSOD705 传感器线缆定义如下:

|------|------------------|
| 线色 | 功能 |
| 红色线 | 电源 +,+24 VDC |
| 黑色线 | 电源 -,GND |
| 黄绿色线 | RS-485 A / 485_A |
| 白色线 | RS-485 B / 485_B |
| 蓝色线 | 继电器 + |
| 绿色线 | 继电器 - |
| 棕色线 | 4-20 mA + |
| 灰色线 | 4-20 mA - |
| 裸露线 | 屏蔽层 |

本方案中主要使用以下接口:

|------------|-------------------|
| DSOD705 | KC11 / 外部电源 |
| 红色线 +24 V | 外部 24 VDC 电源正极 |
| 黑色线 GND | 外部 24 VDC 电源负极 |
| 黄绿色线 485_A | KC11 RS-485 A |
| 白色线 485_B | KC11 RS-485 B |
| 屏蔽层 | 建议接地或按现场 EMC 要求处理 |

传感器接口

本方案使用 DSOD705 的 RS-485 / Modbus RTU 接口进行数据采集。

4-20 mA 和继电器接口在本方案中不作为主要数据采集链路使用,可根据现场需求独立接入本地控制或报警系统。


5. 数据采集

本方案中,通过 Modbus 读取以下寄存器:

|------|------|--------|-------|----------------------------|-----------|
| 采集内容 | 功能码 | 起始地址 | 寄存器数量 | 数据类型 | 说明 |
| 传感器值 | 0x04 | 0x0000 | 2 | Float,DCBA / Little Endian | 读取水面溢油检测值 |

KC11 通过 EdgeBus 逻辑周期性读取 DSOD705 的输入寄存器 0x0000 ~ 0x0001,读取结果按照 FloatLE 方式解析,并作为 oil 字段上报至 ThinkLink。

5.1 寄存器定义

只读寄存器

|--------|----|----|-------------|--------------|
| 寄存器地址 | 长度 | 读写 | 数据类型 | 内容说明 |
| 0x0000 | 2 | R | Float(DCBA) | 读取传感器值 |
| 0x0001 | 2 | R | Float(DCBA) | 读取传感器温度 |
| 0x0010 | 6 | R | ASCII-HEX | 读取传感器 SN 值 |
| 0x0016 | 2 | R | HEX | 读取传感器硬件和软件版本 |

注:对接代码中实际读取的是 0x0000 ~ 0x0001,即读取 2 个寄存器组成一个浮点数,用于得到油污检测值。

保持寄存器

|--------|----|-----|-------------|----------------------------------------------------|
| 寄存器地址 | 长度 | 读写 | 数据类型 | 内容说明 |
| 0x0000 | 1 | R/W | Short | 读取 / 设置当前传感器地址,范围 1-247 |
| 0x0001 | 1 | R/W | Short | 波特率:0=4800,1=9600,2=19200,3=56000,4=57600,5=115200 |
| 0x0002 | 1 | R/W | Short | 检测间隔时间,单位 ms |
| 0x0006 | 2 | R/W | Float(DCBA) | 传感器到水面距离,单位 m |
| 0x0010 | 1 | R/W | Short | 继电器控制开关,0=关闭,1=开启 |
| 0x0012 | 2 | R/W | Float(DCBA) | 继电器控制最大值 |
| 0x0014 | 2 | R/W | Float(DCBA) | 继电器控制最小值 |
| 0x0016 | 2 | R/W | Float(DCBA) | 继电器动作延迟时间,单位 ms |
| 0x0020 | 1 | R/W | Short | 4-20 mA 输出模式 |
| 0x0022 | 2 | R/W | Float(DCBA) | 电流 4 mA 对应传感器值 |
| 0x0024 | 2 | R/W | Float(DCBA) | 电流 20 mA 对应传感器值 |
| 0x0026 | 1 | R/W | Short | 电流 4 mA 校准值,范围 7900-9900 |
| 0x0027 | 1 | R/W | Short | 电流 20 mA 校准值,范围 1700-3700 |
| 0x0030 | 2 | R/W | Float(DCBA) | 传感器 K 值 |
| 0x0032 | 2 | R/W | Float(DCBA) | 传感器 B 值 |

5.2 状态位定义

本方案中,EdgeBus / PayloadParser 会产生状态字段 status。当前脚本中使用以下状态判断:

|------|----------------------------|-------------|
| 状态位 | 判断方式 | 含义 |
| bit1 | (status & 0x02) === 0x02 | Modbus 采集超时 |

当检测到超时状态时,物模型脚本会保留设备上一帧遥测数据,仅更新 status 状态字段,避免因本次采集超时导致平台侧业务数据被清空。


6. EdgeBus 模型

DSOD705 本身是 RS-485 / Modbus RTU 传感器,不是原生 LoRaWAN 设备,因此需要通过 KC11 内置 EdgeBus 逻辑完成 Modbus 采集和 LoRaWAN 上报。

6.1 EB 配置参数

|----------------|------------------|
| 参数 | 值 |
| EB 名称 | dsod705 |
| LoRaWAN Port | 22 |
| Version | 0x86 |
| DataType | 0x07 |
| 业务代码 BzType | 22107 |
| 业务版本 BzVersion | 11 |
| 串口波特率 | 9600 |
| 数据位 | 8 |
| 停止位 | 1 |
| 校验位 | NONE |
| Modbus 功能码 | 0x04 |
| Modbus 地址 | 保存于 APP 参数地址 150 |
| 上传周期参数 | APP 参数地址 70 |
| 采集周期参数 | APP 参数地址 74 |
| COV 参数 | APP 参数地址 110 |
| 采集寄存器 | 0x0000 ~ 0x0001 |
| COV 类型 | FloatLE |

参数说明:

  • 上传周期和采集周期分开设置。
  • 上传周期保存在 APP 参数地址 70
  • 采集周期保存在 APP 参数地址 74
  • 需要保证采集周期小于上传周期。
  • COV 参数保存在 APP 参数地址 110
  • Modbus 地址保存在 APP 参数地址 150

6.2 EB 代码

复制代码
import {Buffer} from "buffer";
import {buildOtaFile} from "@EBSDK/run";
import {EBModel, EventInfoItem, LoraUpEvent, UpgrdTypeEnum, UserConfUPItem} from "@EBSDK/EBCompiler/all_variable";
import {CheckbitEnum, getOtaConfig, HwTypeEnum} from "@EBSDK/otaConfig";

////////////////////////////////////////////////////////////////////////////////////////

const eventInfo:UserConfUPItem[]=[
    {
        name:"dsod705",
        port:22,
        version:"0x86",
        dataType:"0x07",
        upPeriodIndex:70,
        quInfo:[
            {
                protocol:"modbus",
                code:"0x04",
                periodIndex:74,
                // addr:"0x01",
                indexAPP:150,
                indexCMD:0,
                copySize:1,
                isLast:false,
                // period:"900s",
                // payIndex:3,
                // ackAddrIndex:0,
                listVal:[
                    {
                        start: "0x0000",
                        end: "0x0001",
                        covType:"FloatLE",
                        covAppIndex:110
                    },
                ]
            }
        ]
    }
]

let otaConfig = getOtaConfig({
    BaudRate: 9600,
    StopBits: 1,
    DataBits: 8,
    Checkbit: CheckbitEnum.NONE,
    Battery: false,
    ConfirmDuty: 60,
    BzType: 22107,
    BzVersion: 11
})

const MODBUS_TT = (ebModel: EBModel) => {
    for (let i=0; i<eventInfo.length; i++){
        let event=new EventInfoItem(eventInfo[i]);
        event.upEventSetup()
        event.eventInstall()
    }
    return JSON.stringify(ebModel, null, 2)
}

6.3 说明

当前 EB 逻辑说明:

  1. KC11 通过 RS-485 接口与 DSOD705 通信。
  2. 串口参数为 9600, 8N1,即 9600 bps、8 数据位、1 停止位、无校验。
  3. EB 逻辑使用 Modbus 功能码 0x04 读取输入寄存器。
  4. 读取地址范围为 0x0000 ~ 0x0001,共 2 个寄存器,用于解析一个 FloatLE 数据。
  5. 采集结果作为溢油检测值,通过 LoRaWAN Port 22 上报。
  6. 上传周期由 APP 参数地址 70 控制。
  7. 采集周期由 APP 参数地址 74 控制。
  8. COV 变化阈值由 APP 参数地址 110 控制。
  9. Modbus 从站地址由 APP 参数地址 150 控制。
  10. 业务代码为 22107,业务版本为 11

7. 物模型

7.1 物模型基本信息

数据物模型

|--------------|------------|
| 项目 | 内容 |
| 名称 | DSOD705 |
| id Name | dsod_22107 |
| LoRaWAN Port | 22 |
| 数据长度 | 16 |
| RSSI | 支持 |
| 电池字段 | index 4 |
| 业务标识 Tag | 0x86 |
| 数据类型 Tag | 0x07 |

参数物模型

|-----------|------------------------|
| 项目 | 内容 |
| 名称 | DSOD705-PARA |
| id Name | dsod705_para_22107 |
| 参数上报 Port | 214 |
| RPC 名称 | dsod705_set_para_22107 |

7.2 上行帧结构

数据上行帧

|---------|-----------------------|
| 字节位置 | 内容 |
| index 0 | Tag:0x86 |
| index 1 | Tag:0x07 |
| index 4 | Battery |
| index 6 | oil,FloatLE |
| 其他 | EdgeBus 状态、RSSI 等辅助字段 |

数据字段定义:

|-----|------------|----|-------|---------|----|-----|
| 字段名 | field_name | 单位 | index | 类型 | 系数 | 小数位 |
| oil | oil | % | 6 | floatLE | 1 | 2 |

参数字段定义

|----------|-------------|-------------|----|----------|--------------|
| APP 参数地址 | 字段名 | field_name | 单位 | 类型 | 说明 |
| 70 | period_up | period_up | S | uint32le | 上传周期 |
| 74 | period_read | period_read | S | uint32le | 采集周期 |
| 110 | cov_oil | cov_oil | % | floatLE | 溢油检测值 COV 阈值 |
| 150 | addr_modbus | addr_modbus | | uint8 | Modbus 从站地址 |

7.3 物模型脚本

数据物模型脚本
复制代码
let port = msg?.userdata?.port || null;
if (port != 22) return null

let frameInfo = {
    port: 22,
    dataLen: 16,
    rssi: true,
    battery: 4,
    tagList: [
        { index: 0, tag: 0x86 },
        { index: 1, tag: 0x07 }
    ]
}

let appInfo = [
    {
        name: "oil",
        field_name: "oil",
        unit: "%",
        index: 6,
        type: "floatLE",
        coefficient: 1,
        decimal: 2
    },
]

let payParser = new PayloadParser({
    device: device,
    msg: msg,
    frameInfo: frameInfo,
    appInfo: appInfo,
})

let tdata = payParser.telemetry()

if (tdata == undefined) {
    return null
}

if ((tdata?.status & 0x02) === 0x02) { // time out, just update the status.
    const status = tdata.status
    tdata = { ...(device.telemetry_data?.[thingModelId] ?? {}) }
    tdata.status = status
}

return {
    telemetry_data: tdata,
    server_attrs: null,
    shared_attrs: null
}
参数物模型脚本
复制代码
let port = msg?.userdata?.port || null;
const rpcName = "dsod705_set_para_22107";

let paraDef = {
    app_70: {
        name: "period_up",
        field_name: "period_up",
        unit: "S",
        type: "uint32le"
    },
    app_74: {
        name: "period_read",
        field_name: "period_read",
        unit: "S",
        type: "uint32le"
    },
    app_110: {
        name: "cov_oil",
        field_name: "cov_oil",
        unit: "%",
        type: "floatLE",
        decimal: 1
    },
    app_150: {
        name: "addr_modbus",
        field_name: "addr_modbus",
        unit: "",
        type: "uint8"
    }
}

if (port !== 214) {
    let checkData = Utils.paraCheck(rpcName, device.server_attrs, device.shared_attrs)
    return {
        server_attrs: checkData.sdata,
        action: checkData.action,
    }
}

let pdata = (new PayloadParser({
    device: device,
    msg: msg,
    paraInfo: paraDef,
})).paras()

let checkData = Utils.paraCheck(rpcName, pdata)

return {
    telemetry_data: pdata,
    server_attrs: checkData.sdata,
    shared_attrs: pdata,
    action: checkData.action,
}

8. 第三方平台数据订阅

8.1 MQTT Topic

复制代码
/v32/{Organization Account}/tkl/up/telemetry/{eui}

8.2 上报示例数据

复制代码
{
    "eui": "6353012af10a9331",
    "active_time": "2026-02-05T08:35:48.000Z",
    "thingModelId": "dsod_22107",
    "thingModelIdName": "DSOD705",
    "telemetry_data": {
        "snr": 13.5,
        "rssi": -51,
        "battery": 3.37,
        "oil": 12.34,
        "status": 0
    }
}

字段说明:

|------------------|-----------------------|
| 字段 | 含义 |
| eui | LoRaWAN 终端 EUI |
| active_time | 数据上报时间 |
| thingModelId | 物模型 ID |
| thingModelIdName | 物模型名称 |
| snr | LoRaWAN 信噪比 |
| rssi | LoRaWAN 信号强度 |
| battery | 设备电池 / 电源状态字段 |
| oil | DSOD705 溢油检测值,单位 % |
| status | EdgeBus / Modbus 采集状态 |


9. RPC

9.1 RPC 名称

本方案包含两个 RPC:

|--------|------------------|-------------------|
| RPC 功能 | 名称 | id Name |
| 设置参数 | DSOD705 SET para | dsod705_set_22107 |
| 读取参数 | DSOD705 GET para | dsod705_get_22107 |

其中设置参数使用的内部 RPC 名称为:

复制代码
dsod705_set_para_22107

9.2 参数定义

|-------------|-------------|--------|----|----------|--------------|
| 参数 | field_name | APP 地址 | 单位 | 类型 | 说明 |
| period_up | period_up | 70 | S | uint32le | 上传周期 |
| period_read | period_read | 74 | S | uint32le | 采集周期 |
| cov_oil | cov_oil | 110 | % | floatLE | 油污检测值 COV 阈值 |
| addr_modbus | addr_modbus | 150 | | uint8 | Modbus 从站地址 |

参数设置建议:

  • period_read 应小于 period_up
  • addr_modbus 应与 DSOD705 传感器实际 Modbus 地址一致。
  • cov_oil 用于控制油污检测值变化上报阈值,可根据现场油污检测灵敏度需求配置。

9.3 RPC 代码

设置参数 RPC
复制代码
let classMode = (device && device.shared_attrs && device.shared_attrs.class_mode) || "ClassA";
const rpcName = "dsod705_set_para_22107"

let paraDef = {
    app_70: {
        name: "period_up",
        field_name: "period_up",
        unit: "S",
        type: "uint32le"
    },
    app_74: {
        name: "period_read",
        field_name: "period_read",
        unit: "S",
        type: "uint32le"
    },
    app_110: {
        name: "cov_oil",
        field_name: "cov_oil",
        unit: "%",
        type: "floatLE",
        decimal: 1
    },
    app_150: {
        name: "addr_modbus",
        field_name: "addr_modbus",
        unit: "",
        type: "uint8"
    }
}

let frames = RPCHelper.buildFrame({
    paraDef: paraDef,
    params: params
});

let redoBuffer = RPCHelper.redo()

let dnBuffer = Buffer.alloc(frames.writeBuffer.length + frames.readBuffer.length);

frames.writeBuffer.copy(dnBuffer, 0)
frames.readBuffer.copy(dnBuffer, frames.writeBuffer.length)

logger.info("set para")

let msgQue = Utils.makeParaSetMSG({
    device: device,
    classMode: classMode,
    rpcName: rpcName,
    params: params,
    paraDownBuffer: dnBuffer,
    extraAppBuffer: redoBuffer
})

if (msgQue.length == 0) return null

return msgQue
读取参数 RPC
复制代码
let paraDef = {
    app_70: {
        name: "period_up",
        field_name: "period_up",
        unit: "S",
        type: "uint32le"
    },
    app_74: {
        name: "period_read",
        field_name: "period_read",
        unit: "S",
        type: "uint32le"
    },
    app_110: {
        name: "cov_oil",
        field_name: "cov_oil",
        unit: "%",
        type: "floatLE",
        decimal: 1
    },
    app_150: {
        name: "addr_modbus",
        field_name: "addr_modbus",
        unit: "",
        type: "uint8"
    }
}

let frames = RPCHelper.buildFrame({
    paraDef: paraDef,
    params: params
});

let msg = RPCHelper.makeMSG({
    msgType: Utils.msgType.paras,
    device: device,
    dnBuffer: frames.readBuffer,
    sleepTime: 0,
})

return [msg]

10. 模板选择

在 ThinkLink 平台中搜索模板:

复制代码
DSOD705

或搜索物模型 id Name:

复制代码
dsod_22107

参数物模型可搜索:

复制代码
dsod705_para_22107

RPC 可搜索:

复制代码
dsod705_set_22107
dsod705_get_22107

或按业务类型查找:

复制代码
水面溢油检测
非接触式溢油检测
RS-485 溢油传感器
Modbus RTU 水质 / 环境监测
LoRaWAN 工业传感器接入
相关推荐
2401_873479406 小时前
物联网设备管理中,IP查询工具怎么评估IP安全性?
物联网·tcp/ip·servlet
互联网推荐官7 小时前
上海APP开发公司的技术路径选择:从架构设计到工程落地
大数据·人工智能·物联网·软件工程
MetrixAeroCore9 小时前
智能机器人出海刚需:国际物联卡补齐跨境通信短板
物联网
olivesun889 小时前
20万元 · 1年期 · A股组合投资方案
大数据·人工智能·物联网
qq_4112624211 小时前
四博 AI 智能音箱三模联网技术方案
物联网·ai
ManThink Technology12 小时前
KS31 4-20mA 模拟量采集器通过LoRaWAN 接入ThinkLink
人工智能·物联网
Rubin智造社12 小时前
04月25日AI每日参考:谷歌豪掷400亿押注Anthropic,DeepSeek V4横空出世
大数据·人工智能·物联网·comfyui·deepseek v4·谷歌anthropic投资·meta亚马逊芯片
MetrixAeroCore15 小时前
跨境企业破局通信难题:国际物联网卡+定制物联网方案,赋能全球业务落地
物联网
七夜zippoe15 小时前
DolphinDB MQTT数据接入:物联网消息订阅
物联网·mqtt·队列·dolphindb·消息接入