1. Sensor Overview
Model catalog
Search for these models in ThinkLink by name or ID.
| Model type | Name | id_name | Platform model ID |
|---|---|---|---|
| RPC | [DSOD705 GET] para | dsod705_get_22107 | 100637692055785477 |
| RPC | [DSOD705 SET] para | dsod705_set_22107 | 100638082046365701 |
| Template | DSOD705-22107 | 100638935071330309 | |
| Parameter Thing Model | [DSOD705-PARA] | dsod705_para_22107 | 100632408214212613 |
| Thing Model | [DSOD705] | dsod_22107 | 100631632184086533 |
| Thing Model | [DSOD-22107-DSOD705资产] 区域聚合 | dsod_asset_22107 | 119677174411063306 |
The DSOD705 is a non-contact water surface oil spill detection sensor provided by DISEN. The device is based on the ultraviolet fluorescence detection principle. It emits ultraviolet pulses toward the water surface, excites oil substances to generate fluorescence, and determines whether oil contamination exists on the water surface through photoelectric reception and data processing.
This sensor is mainly used for real-time detection of oil pollution, oil leakage, oil spills, and floating oil on water surfaces. It can detect various petroleum-based substances, including crude oil, diesel, fuel oil, engine oil, lubricating oil, gasoline, aviation kerosene, and more.
The device supports RS-485 / Modbus RTU output. It can be connected to a LoRaWAN network through the KC11 data collector, and the ThinkLink platform can then perform data parsing, visualization, alarm processing, and forwarding to third-party systems.
2. Product Features
The main features of the DSOD705 are as follows:
1. Non-contact detection
The sensor is installed above the water surface and does not need to directly contact the measured water body. This helps reduce oil adhesion, biofouling, and manual cleaning maintenance.
2. Ultraviolet fluorescence detection principle
The sensor uses the natural fluorescence characteristics of oil substances for detection, making it suitable for identifying petroleum pollutants on water surfaces.
3. High sensitivity
It can detect oil films with a thickness as low as approximately 1 μm, making it suitable for early oil spill warning.
4. All-weather online monitoring
The sensor supports continuous 24-hour monitoring and is not affected by daytime or nighttime lighting conditions.
5. RS-485 / Modbus RTU output
It can be easily connected to industrial data acquisition systems, monitoring systems, or converted to LoRaWAN reporting through KC11.
6. Alarm linkage support
The device itself supports relay output, which can be used for local alarms or linkage control.
7. High protection rating
According to the manual, the device has high protection capability such as IP66/IP67 or IP68, making it suitable for outdoor and complex industrial environments.
8. Low-power operation
The device has low power consumption. The manual indicates that DC power consumption is less than 2 W, while some descriptions also mention low-power operation below 10 W.
3. Application Scope
The DSOD705 is suitable for online water surface oil pollution monitoring in industrial and environmental applications. Typical application scenarios include:
- Oil production enterprises
- Ships
- Offshore platforms
- Ports and terminals
- Petrochemical plants
- Oil storage stations and oil depots
- Power stations / power plants
- Gas compressor stations
- Wastewater treatment plants
- Rivers and lakes
- Industrial drainage outlets
- Water environment safety monitoring scenarios
4. Data Collector Information
4.1 Hardware Information
This solution uses KC11 as the RS-485 data acquisition and LoRaWAN access device.
| Item | Description |
|---|---|
| Data acquisition device model | KC11 |
| Interface type | RS-485 |
| Uplink communication | LoRaWAN |
| Power supply | 220 V power supply |
| Connected sensor | DSOD705 water surface oil spill detection sensor |
| Protocol | Modbus RTU |
| Default serial port parameters | 9600 bps, 8 data bits, 1 stop bit, no parity |
4.2 Wiring Information
Power and Communication Interface
The cable definition of the DSOD705 sensor is as follows:
| Wire Color | Function |
|---|---|
| Red wire | Power +, +24 VDC |
| Black wire | Power -, GND |
| Yellow-green wire | RS-485 A / 485_A |
| White wire | RS-485 B / 485_B |
| Blue wire | Relay + |
| Green wire | Relay - |
| Brown wire | 4-20 mA + |
| Gray wire | 4-20 mA - |
| Bare wire | Shield |
In this solution, the following interfaces are mainly used:
| DSOD705 | KC11 / External Power Supply |
|---|---|
| Red wire +24 V | Positive terminal of external 24 VDC power supply |
| Black wire GND | Negative terminal of external 24 VDC power supply |
| Yellow-green wire 485_A | KC11 RS-485 A |
| White wire 485_B | KC11 RS-485 B |
| Shield | Recommended to be grounded or handled according to on-site EMC requirements |
Sensor Interface
This solution uses the RS-485 / Modbus RTU interface of the DSOD705 for data acquisition.
The 4-20 mA and relay interfaces are not used as the main data acquisition path in this solution. They can be independently connected to a local control or alarm system according to on-site requirements.
5. Data Acquisition
In this solution, the following register is read through Modbus:
| Acquisition Content | Function Code | Start Address | Register Quantity | Data Type | Description |
|---|---|---|---|---|---|
| Sensor value | 0x04 | 0x0000 | 2 | Float, DCBA / Little Endian | Reads the water surface oil spill detection value |
KC11 periodically reads the DSOD705 input registers 0x0000 ~ 0x0001 through EdgeBus logic. The read result is parsed as FloatLE and reported to ThinkLink as the oil field.
5.1 Register Definition
Read-only Registers
| Register Address | Length | R/W | Data Type | Description |
|---|---|---|---|---|
| 0x0000 | 2 | R | Float(DCBA) | Read sensor value |
| 0x0001 | 2 | R | Float(DCBA) | Read sensor temperature |
| 0x0010 | 6 | R | ASCII-HEX | Read sensor SN value |
| 0x0016 | 2 | R | HEX | Read sensor hardware and software version |
Note: In the integration code, the actual read range is 0x0000 ~ 0x0001, meaning two registers are read to form one floating-point value for obtaining the oil contamination detection value.
Holding Registers
| Register Address | Length | R/W | Data Type | Description |
|---|---|---|---|---|
| 0x0000 | 1 | R/W | Short | Read / set current sensor address, range 1-247 |
| 0x0001 | 1 | R/W | Short | Baud rate: 0=4800, 1=9600, 2=19200, 3=56000, 4=57600, 5=115200 |
| 0x0002 | 1 | R/W | Short | Detection interval time, unit: ms |
| 0x0006 | 2 | R/W | Float(DCBA) | Distance from sensor to water surface, unit: m |
| 0x0010 | 1 | R/W | Short | Relay control switch, 0=Off, 1=On |
| 0x0012 | 2 | R/W | Float(DCBA) | Relay control maximum value |
| 0x0014 | 2 | R/W | Float(DCBA) | Relay control minimum value |
| 0x0016 | 2 | R/W | Float(DCBA) | Relay action delay time, unit: ms |
| 0x0020 | 1 | R/W | Short | 4-20 mA output mode |
| 0x0022 | 2 | R/W | Float(DCBA) | Sensor value corresponding to 4 mA current |
| 0x0024 | 2 | R/W | Float(DCBA) | Sensor value corresponding to 20 mA current |
| 0x0026 | 1 | R/W | Short | 4 mA current calibration value, range 7900-9900 |
| 0x0027 | 1 | R/W | Short | 20 mA current calibration value, range 1700-3700 |
| 0x0030 | 2 | R/W | Float(DCBA) | Sensor K value |
| 0x0032 | 2 | R/W | Float(DCBA) | Sensor B value |
5.2 Status Bit Definition
In this solution, EdgeBus / PayloadParser generates a status field named status. The current script uses the following status judgment:
| Status Bit | Judgment Method | Meaning |
|---|---|---|
| bit1 | (status & 0x02) === 0x02 | Modbus acquisition timeout |
When a timeout status is detected, the thing model script retains the previous telemetry data frame of the device and only updates the status field. This prevents platform-side business data from being cleared due to the current acquisition timeout.
6. EdgeBus Model
The DSOD705 itself is an RS-485 / Modbus RTU sensor, not a native LoRaWAN device. Therefore, KC11’s built-in EdgeBus logic is required to complete Modbus acquisition and LoRaWAN reporting.
6.1 EB Configuration Parameters
| Parameter | Value |
|---|---|
| EB name | dsod705 |
| LoRaWAN Port | 22 |
| Version | 0x86 |
| DataType | 0x07 |
| Business code BzType | 22107 |
| Business version BzVersion | 11 |
| Serial baud rate | 9600 |
| Data bits | 8 |
| Stop bits | 1 |
| Parity | NONE |
| Modbus function code | 0x04 |
| Modbus address | Stored at APP parameter address 150 |
| Upload period parameter | APP parameter address 70 |
| Acquisition period parameter | APP parameter address 74 |
| COV parameter | APP parameter address 110 |
| Acquisition register | 0x0000 ~ 0x0001 |
| COV type | FloatLE |
Parameter description:
- The upload period and acquisition period are configured separately.
- The upload period is stored at APP parameter address 70.
- The acquisition period is stored at APP parameter address 74.
- The acquisition period must be shorter than the upload period.
- The COV parameter is stored at APP parameter address 110.
- The Modbus address is stored at APP parameter address 150.
6.2 EB Code
import {Buffer} from "buffer";
import {buildOtaFile} from "@EBSDK/run";
import {LoraUpEvent} from "@EBSDK/EBCompiler/all_variable";
import {EBModel} from "@EBSDK/EBCompiler/EBModel/EBModel";
import {EventInfoItem} from "@EBSDK/EBCompiler/plugins/EBHelper";
import type {UserConfUPItem} from "@EBSDK/EBCompiler/plugins/EBHelper";
import {CheckbitEnum, getOtaConfig, HwTypeEnum, UpgrdTypeEnum} 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}, //covAppIndex:
]
}
]
}
]
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)
}
buildOtaFile(import.meta.url, otaConfig, MODBUS_TT)6.3 Description
The current EB logic is described as follows:
- KC11 communicates with the DSOD705 through the RS-485 interface.
- The serial port parameters are 9600, 8N1, meaning 9600 bps, 8 data bits, 1 stop bit, and no parity.
- The EB logic uses Modbus function code
0x04to read input registers. - The read address range is
0x0000 ~ 0x0001, with a total of 2 registers used to parse one FloatLE value. - The acquisition result is reported through LoRaWAN Port 22 as the oil spill detection value.
- The upload period is controlled by APP parameter address 70.
- The acquisition period is controlled by APP parameter address 74.
- The COV change threshold is controlled by APP parameter address 110.
- The Modbus slave address is controlled by APP parameter address 150.
- The business code is 22107, and the business version is 11.
7. Thing Model
7.1 Basic Thing Model Information
Data Thing Model
| Item | Description |
|---|---|
| Name | DSOD705 |
| id Name | dsod_22107 |
| LoRaWAN Port | 22 |
| Data length | 16 |
| RSSI | Supported |
| Battery field | index 4 |
| Business identifier Tag | 0x86 |
| Data type Tag | 0x07 |
Parameter Thing Model
| Item | Description |
|---|---|
| Name | DSOD705-PARA |
| id Name | dsod705_para_22107 |
| Parameter reporting Port | 214 |
| RPC name | dsod705_set_para_22107 |
7.2 Uplink Frame Structure
Data Uplink Frame
| Byte Position | Content |
|---|---|
| index 0 | Tag: 0x86 |
| index 1 | Tag: 0x07 |
| index 4 | Battery |
| index 6 | oil, FloatLE |
| Others | EdgeBus status, RSSI, and other auxiliary fields |
Data Field Definition
| Field Name | field_name | Unit | Index | Type | Coefficient | Decimal Places |
|---|---|---|---|---|---|---|
| oil | oil | % | 6 | floatLE | 1 | 2 |
Parameter Field Definition
| APP Parameter Address | Field Name | field_name | Unit | Type | Description |
|---|---|---|---|---|---|
| 70 | period_up | period_up | S | uint32le | Upload period |
| 74 | period_read | period_read | S | uint32le | Acquisition period |
| 110 | cov_oil | cov_oil | % | floatLE | COV threshold of oil spill detection value |
| 150 | addr_modbus | addr_modbus | uint8 | Modbus slave address |
7.3 Thing Model Script
Data Thing Model Script
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
}Parameter Thing Model Script
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. Third-party Platform Data Subscription
8.1 MQTT Topic
/v32/{Organization Account}/tkl/up/telemetry/{eui}8.2 Example Reported Data
{
"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
}
}Field Description
| Field | Meaning |
|---|---|
| eui | LoRaWAN terminal EUI |
| active_time | Data reporting time |
| thingModelId | Thing model ID |
| thingModelIdName | Thing model name |
| snr | LoRaWAN signal-to-noise ratio |
| rssi | LoRaWAN signal strength |
| battery | Device battery / power status field |
| oil | DSOD705 oil spill detection value, unit: % |
| status | EdgeBus / Modbus acquisition status |
9. RPC
9.1 RPC Name
This solution includes two RPCs:
| RPC Function | Name | id Name |
|---|---|---|
| Set parameters | DSOD705 SET para | dsod705_set_22107 |
| Read parameters | DSOD705 GET para | dsod705_get_22107 |
The internal RPC name used for parameter setting is:
dsod705_set_para_221079.2 Parameter Definition
| Parameter | field_name | APP Address | Unit | Type | Description |
|---|---|---|---|---|---|
| period_up | period_up | 70 | S | uint32le | Upload period |
| period_read | period_read | 74 | S | uint32le | Acquisition period |
| cov_oil | cov_oil | 110 | % | floatLE | COV threshold of oil contamination detection value |
| addr_modbus | addr_modbus | 150 | uint8 | Modbus slave address |
Parameter setting recommendations:
period_readshould be smaller thanperiod_up.addr_modbusshould be consistent with the actual Modbus address of the DSOD705 sensor.cov_oilis used to control the change reporting threshold of the oil contamination detection value and can be configured according to on-site sensitivity requirements for oil contamination detection.
9.3 RPC Code
Parameter Setting 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 msgQueParameter Reading 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. Template Selection
In the ThinkLink platform, search for the template:
DSOD705Or search for the thing model id Name:
dsod_22107For the parameter thing model, search:
dsod705_para_22107For RPC, search:
dsod705_set_22107
dsod705_get_22107Alternatively, search by business type:
Water surface oil spill detection
Non-contact oil spill detection
RS-485 oil spill sensor
Modbus RTU water quality / environmental monitoring
LoRaWAN industrial sensor access