Skip to content

1. Sensor Overview ​

Model catalog ​

Search for these models in ThinkLink by name or ID.

Model typeNameid_namePlatform model ID
RPC[AQ3485 SET] paraAQ3485_21306_set87551394432684037
RPC[AQ3485 GET] paraaq3485_21306_get88240163909537797
TemplateAQ348588241088917147653
Thing Model[AQ3485]aq3485_2130687554295540486149
Thing Model[AQ-21306-AQ3485资产] 区域聚合aq3485_asset_21306119677174411063297

The AQ3485 is a dual-channel temperature sensor manufactured by AoQing (奥青). It uses a Modbus-RTU / RS-485 interface to simultaneously read refrigerator temperature and defrost temperature from a cold-storage unit. This integration connects the sensor to the ThinkLink platform via a KC21 (battery-powered) DTU, with optional COV (change-of-value) triggered uplinks.

Integration details: model AQ3485, business code 21306, template name AQ3485.


2. Product Features ​

  • Dual-channel temperature acquisition: refrigerator temperature + defrost temperature
  • RS-485 interface, Modbus-RTU protocol
  • Default slave address 0x01, baud rate 9600, 8N1
  • Independent COV thresholds for each temperature channel
  • Low power design — battery-powered KC21 DTU

3. Applications ​

The AQ3485 is suited for the following scenarios:

  • Cold cabinet monitoring in supermarkets and convenience stores
  • Refrigeration room and defrost temperature monitoring in cold-storage warehouses
  • Cold chain logistics temperature management
  • Cold storage equipment monitoring in food and pharmaceutical industries

4. Data Collector ​

4.1 Hardware Specifications ​

This solution uses the KC21 (battery version) DTU.

  • Model: KC21
  • Interface: RS-485
  • Power supply: Battery
  • LoRaWAN Class: A

4.2 Wiring ​

Power and Communication Interface ​

The KC21 battery version supplies power to the sensor over the RS-485 bus:

  • KC21 A terminal → RS-485A (sensor)
  • KC21 B terminal → RS-485B (sensor)

Sensor Interface ​

The AQ3485 uses a standard RS-485 interface with default settings: 9600 baud, 8N1, no parity. Connect directly to the KC21 RS-485 port.


5. Data Acquisition ​

This solution reads the following Modbus registers:

  • 0x0000: Refrigerator temperature (Int16BE, × 0.1 °C)
  • 0x0001: Defrost temperature (Int16BE, × 0.1 °C)

Platform parameter address conventions:

  • Upload interval: App address 70
  • Acquisition interval: App address 74
  • Power-on delay: App address 38

5.1 Register Map ​

Address (hex)DescriptionData TypeNotes
0x0000Refrigerator temperatureInt16BE (signed, big-endian)Raw value × 0.1 = actual temperature (°C)
0x0001Defrost temperatureInt16BE (signed, big-endian)Raw value × 0.1 = actual temperature (°C)

6. EdgeBus Model ​

6.1 EB Configuration ​

ParameterValue
name"AQ3485"
port21
version"0x85"
dataType"0x03"
upPeriodIndex70
periodIndex (acquisition)74
BaudRate9600
StopBits1
DataBits8
CheckbitNONE
Batterytrue
BzType21306
BzVersion12
SwVersion31

6.2 EB Code ​

typescript
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} from "@EBSDK/otaConfig";
////////////////////////////////////////////////////////////////////////////////////////
const eventInfo:UserConfUPItem[]=[
    {
        name:"AQ3485",port:21, version:"0x85",dataType:"0x03",upPeriodIndex:70,
        quInfo:[
            {
            protocol:"modbus",code:"0x03", periodIndex:74,//addr:"0x01",
            indexAPP:150, indexCMD:0, copySize:1,isLast:false,//period:"900s",payIndex:3,ackAddrIndex:0,
            listVal:[
                { start: "1", end: "1" ,covType:"Int16BE",covAppIndex:110},  //冷藏室温度,refrigerator_temp,coefficient=0.1
                { start: "2", end: "2" ,covType:"Int16BE",covAppIndex:112}   //融霜温度,defrost_temp,coefficient=0.1
                ]
            }
        ]
    }
]
let otaConfig = getOtaConfig({
    SwVersion:31,
    BaudRate: 9600,
    StopBits: 1,
    DataBits: 8,
    Checkbit: CheckbitEnum.NONE,
    Battery: true,
    ConfirmDuty: 60,
    BzType: 21306,
    BzVersion: 12
})
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 Notes ​

EB logic summary:

  • Uplinks are sent on port 21.
  • A single query event reads registers 0x0000 and 0x0001 in one Modbus FC03 request (2 contiguous registers, 4 bytes total).
  • Upload interval and acquisition interval are separated:
    • App address 70 = upload interval
    • App address 74 = acquisition interval
  • COV triggers: refrigerator temperature (App 110) and defrost temperature (App 112) each have independent COV thresholds. An uplink is triggered immediately when a temperature change exceeds its threshold.
  • The Modbus slave address is managed by App parameter 150 and can be changed at runtime.
  • Data format: Int16BE (signed, big-endian); divide by 10 to get temperature in °C.

7. Thing Model ​

7.1 Thing Model Information ​

Telemetry Thing Model

  • Name: [AQ3485]
  • id Name: aq3485_21306
frameInfo: { port: 21, dataLen: -1, rssi: true, battery: 4 }
tagList:   [{ index: 0, tag: 0x85 }, { index: 1, tag: 0x03 }]

Uplink frame field layout (business data starts at byte 6):

Offset (index)FieldTypeUnitDescription
0versionuint8—Protocol version, fixed 0x85
1dataTypeuint8—Business type, fixed 0x03
2covStatusuint8—COV trigger status
3statusuint8—Query event status
4batteryuint8—Battery level (4-byte encoded)
5addruint8—Modbus slave address
6–7humidityInt16BE°C × 0.1Refrigerator temperature (field_name: humidity)
8–9temperatureInt16BE°C × 0.1Defrost temperature (field_name: temperature)

Field naming note: The humidity field contains refrigerator temperature, and temperature contains defrost temperature. These names reflect legacy platform registration and do not affect functionality.

7.3 Thing Model Script ​

7.3.1 Telemetry Thing Model Script ​

javascript
import {PayloadParser} from '#tklHelper';

function payload_parser({device, msg, thingModelId, noticeAttrs}) {
let    port=msg?.userdata?.port || null;
    let frameInfo={
        port:21, dataLen:-1,rssi:true,battery:4,
        tagList:[{   index:0, tag:0x85}, {   index:1, tag:0x03}]
    }
    let appInfo = [
        {   name: "humidity", field_name: "humidity", unit:"℃", index: 6, type: "int16BE",coefficient:0.1,decimal:1},
        {   name: "temperature", field_name: "temperature", unit:"℃", index: 8, type: "int16BE",coefficient:0.1,decimal:1},
    ]
    let paraInfo= {
        app_70: {name: "periodUP", field_name: "periodUP", unit: "s",  type: "uint32LE"},
        app_74: {name: "periodRead", field_name: "periodRead", unit: "s", type: "uint32LE"},
        app_110: {name: "cov_temperature", field_name: "cov_temperature", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
        app_112: {name: "cov_humidity", field_name: "cov_humidity", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
        app_150: {name: "addr", field_name: "addr", unit: "", type: "uint8"},
    }
    let pdata={}
    let tdata={}
    let payParser=new PayloadParser({
        device:device,
        msg:msg,
        frameInfo:frameInfo,
        appInfo:appInfo,
        paraInfo:paraInfo,
    })
    if (port===214) {
        pdata=payParser.paras()
        tdata=null
    }else  {
        tdata= payParser.telemetry()
        pdata=null
    }
    return {
        telemetry_data: tdata,
        server_attrs: null,
        shared_attrs: pdata
    }
}

8. Third-Party Platform Data Subscription ​

8.1 MQTT Topic ​

/v32/{Organization Account}/tkl/up/telemetry/{eui}

8.2 Example Payload ​

json
{
    "eui": "6353012af10a9331",
    "active_time": "2026-02-05T08:35:48.000Z",
    "thingModelId": "87554295540486149",
    "thingModelIdName": "aq3485_21306",
    "telemetry_data": {
        "snr": 10.5,
        "rssi": -65,
        "battery": 3.21,
        "humidity": -5.2,
        "temperature": 18.3
    }
}

Notes:

  • thingModelId uses the platform-assigned value (87554295540486149).
  • thingModelIdName maps to the telemetry thing model aq3485_21306.
  • humidity represents refrigerator temperature (°C); example value -5.2 °C is a typical cold-storage reading.
  • temperature represents defrost temperature (°C); example value 18.3 °C represents ambient temperature during a defrost cycle.

9. RPC ​

9.1 RPC Names ​

Set Parameters RPC

  • Name: [AQ3485 SET] para
  • id Name: AQ3485_21306_set

Get Parameters RPC

  • Name: [AQ3485 GET] para
  • id Name: aq3485_21306_get

9.2 Parameter Definition ​

App AddressParameter Namefield_nameUnitTypeDescription
app_38pwron_delaypwron_delaymsuint16lePower-on delay before querying the sensor
app_70periodUPperiodUPsuint32LEUpload interval
app_74periodReadperiodReadsuint32LEAcquisition interval
app_110cov_temperaturecov_temperature°Cint16BEDefrost temp COV threshold (× 0.1 °C)
app_112cov_humiditycov_humidity°Cint16BERefrigerator temp COV threshold (× 0.1 °C)
app_150addraddr—uint8Modbus slave address (default: 1)

9.3 RPC Scripts ​

Set Parameters RPC ​

javascript
import {RPCHelper, Utils} from '#tklHelper';
import {Buffer} from "buffer";

function rpc_script({device, params, alarms, logger}) {
let paraDef= {
        app_38: { name: "pwron_delay", field_name: "pwron_delay", unit: "ms", index: 38, type: "uint16le" },
        app_70: {name: "periodUP", field_name: "periodUP", unit: "s",  type: "uint32LE"},
        app_74: {name: "periodRead", field_name: "periodRead", unit: "s", type: "uint32LE"},
        app_110: {name: "cov_temperature", field_name: "cov_temperature", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
        app_112: {name: "cov_humidity", field_name: "cov_humidity", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
        app_150: {name: "addr", field_name: "addr", 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+redoBuffer.length);
    frames.writeBuffer.copy(dnBuffer,0)
    frames.readBuffer.copy(dnBuffer,frames.writeBuffer.length)
    redoBuffer.copy(dnBuffer,frames.writeBuffer.length+frames.readBuffer.length);
    logger.info("set para")
    let msg=RPCHelper.makeMSG({
        msgType:Utils.msgType.paras,
        device:device,
        dnBuffer:dnBuffer,
        sleepTime:0,
    })
    return [msg]
}

Get Parameters RPC ​

javascript
import {RPCHelper, Utils} from '#tklHelper';

function rpc_script({device, params, alarms, logger}) {
let paraDef= {
        app_38: { name: "pwron_delay", field_name: "pwron_delay", unit: "ms", index: 38, type: "uint16le" },
        app_70: {name: "periodUP", field_name: "periodUP", unit: "s",  type: "uint32LE"},
        app_74: {name: "periodRead", field_name: "periodRead", unit: "s", type: "uint32LE"},
        app_110: {name: "cov_temperature", field_name: "cov_temperature", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
        app_112: {name: "cov_humidity", field_name: "cov_humidity", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
        app_150: {name: "addr", field_name: "addr", 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 ​

Search for the following template in the ThinkLink platform: AQ3485

Or browse by business type: 21306 / Dual-Channel Temperature Sensor / RS-485 Modbus Cold-Storage Monitoring


11. Additional Notes ​

  1. Field naming: The humidity field contains refrigerator temperature; temperature contains defrost temperature. These names stem from legacy platform registration.
  2. Manufacturer default communication settings: address 1, baud rate 9600, 8 data bits, no parity, 1 stop bit.
  3. COV thresholds: cov_temperature (app_110) applies to defrost temperature; cov_humidity (app_112) applies to refrigerator temperature. Both are in units of 0.1 °C — a threshold of 10 means 1.0 °C.
  4. Power-on delay: pwron_delay (app_38) is the wait time in milliseconds after KC21 powers on before the first Modbus query is issued.