Skip to content

1. Sensor Introduction

Model catalog

Search for these models in ThinkLink by name or ID.

Model typeNameid_namePlatform model ID
RPC[ECS-2280NEO GET] paraecs_2280neo_22101_get80536120831512581
RPC[ECS-2280NEO SET] paraecs_2280neo_22101_set79888011143155717
TemplateECS-2280NEO80533446350344197
Thing Model[ECS-2280NEO]ecs_2280neo_2210179886859227893765
Thing Model[ELITECH-22101-ECS-2280NEO资产] 区域聚合ecs_2280neo_asset_22101119677174411063308
Parameter Thing Model[ECS-2280NEO-PARA]ecs_2280neo_para_2210190829990110695429

The ECS-2280NEO is an Elitech temperature controller. Its business code is 22101, and the template name is ECS-2280NEO.

This controller supports RS-485 communication. Parameters, operating status, and fault status can be read through an upper-level system. It is suitable for medium- and low-temperature pharmaceutical cabinets, kitchen cabinets, supermarket split cabinets, air curtain cabinets, island cabinets, convenience cabinets, wine cabinets, and similar applications.

2. Product Features

The ECS-2280NEO has the following features:

  • AC power supply: 100–240VAC ±10%, 50/60Hz
  • Supports RS-485 communication
  • Supports reading and writing parameters from an upper-level system
  • Supports reading operating status and fault status
  • Supports controller address configuration through Adr
  • Supports group domain address configuration through un1
  • Supports up to 128 nodes on the same network
  • Provides temperature control, status monitoring, and fault alarm capabilities

3. Application Scope

Applicable to:

  • Medium- and low-temperature pharmaceutical cabinets
  • Kitchen cabinets
  • Supermarket split cabinets
  • Air curtain cabinets
  • Island cabinets
  • Convenience cabinets
  • Wine cabinets

4. Integration Information

4.1 Hardware Information

  • Device model: ECS-2280NEO
  • Manufacturer: Elitech
  • Power supply: 100–240VAC ±10%, 50/60Hz
  • Communication method: RS-485
  • Number of network nodes: up to 128 nodes
  • Controller address range: 00–127
  • Group domain address range: 00–127

4.2 Wiring Information

Power and Communication Interfaces

According to the wiring diagram in the manual, the main interfaces include:

  • AC power input: N / L
  • Communication interface: A / B RS-485
  • UPS interface: 12V / GND
  • Other terminals are related to defrosting, cabinet temperature, door switch, condensation, and other wiring.

Sensor Interfaces

The manual shows the following business-related interfaces:

  • Cabinet temperature
  • Defrost
  • Door switch
  • Condensation
  • UPS interface

5. Data Acquisition

In this solution, the following registers are read through Modbus:

  • Function Code 03
    • Register 256: Refrigerated cabinet temperature
    • Register 257: Defrost temperature
  • Function Code 01
    • Read the status bit block and extract:
      • Valve status
      • Fan status
      • Defrost status

5.1 Register Definition

Data ItemFunction CodeAddress DecAddress HexData TypeDescription
Refrigerated cabinet temperature032560x0100int16Refrigerated cabinet temperature, coefficient 0.1
Defrost temperature032570x0101int16Defrost temperature, coefficient 0.1
Controller status015120x0200bit0 = Off, 1 = On
Cabinet temperature probe fault P1015200x0208bit0 = No fault, 1 = Fault
Defrost probe fault P2015210x0209bit0 = No fault, 1 = Fault
High temperature alarm015240x020Cbit0 = No alarm, 1 = Alarm
Low temperature alarm015250x020Dbit0 = No alarm, 1 = Alarm
Defrost status015350x0217bit0 = Off, 1 = On
Door open alarm015360x0218bit0 = No alarm, 1 = Alarm
Fan status015390x021Bbit0 = Off, 1 = On
Refrigeration status / compressor status015420x021Ebit0 = Off, 1 = On
Door status03100x000Abit0 = Closed, 1 = Open

6. EdgeBus

6.1 EB Configuration Parameters

javascript
let otaConfig = getOtaConfig({
    SwVersion:31,
    BaudRate: 9600,
    StopBits: 1,
    DataBits: 8,
    Checkbit: CheckbitEnum.NONE,
    Battery: true,
    ConfirmDuty: 60,
    BzType: 22101,
    BzVersion: 11
})

Key parameter description:

  • Baud rate: 9600
  • Data bits: 8
  • Stop bits: 1
  • Parity: None
  • Battery reporting: Enabled
  • Business type: 22101
  • Business version: 11

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";
////////////////////////////////////////////////////////////////////////////////////////
//manufactory: elitech
const eventInfo:UserConfUPItem[]=[
    {
        name:"ecs_2280neo",port:22, version:"0x86",dataType:"0x01",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: "256", end: "256" ,covType:"Int16BE",covAppIndex:110},  //冷藏室温度,refrigerator_temp,coefficient=0.1
                { start: "257", end: "257" ,covType:"Int16BE",covAppIndex:112}   //融霜温度,defrost_temp,coefficient=0.1
                ]
            },
            {
            protocol:"modbus",code:"0x01",periodIndex:74, //addr:"0x01",
                indexAPP:150, indexCMD:0, copySize:1,isLast:false,//period:"900s",payIndex:3,ackAddrIndex:0,
                cmd:"0x01 01 02 00 00 1F 39 51",
                ack:"0x01 01 04 01 02 03 04 78 C0",
                listTag:[{index:1,val:"1"},{index:2,val:"4"}],
                listVal:[
                    { start: "3", end: "6",covType: "Uint32LE",covAppIndex:114},
                ]
            }
        ]
    }
]
let otaConfig = getOtaConfig({
    SwVersion:31,
    BaudRate: 9600,
    StopBits: 1,
    DataBits: 8,
    Checkbit: CheckbitEnum.NONE,
    Battery: true,
    ConfirmDuty: 60,
    BzType: 22101,
    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

Current EB logic description:

  1. The device uplink port is 22.
  2. The business frame header uses:
    • version = 0x86
    • dataType = 0x01
  3. Function Code 03 is used to read:
    • 256: Refrigerated cabinet temperature
    • 257: Defrost temperature
  4. Function Code 01 is used to read a status block. The command is:
    • 01 01 02 00 00 1F 39 51
    • Start address: 0x0200
    • Quantity: 0x001F
  5. After Function Code 01 returns, EB writes bytes 3–6 of the status data into the application area as Uint32LE.
  6. The thing model then extracts the following from this 32-bit status word:
    • Valve status
    • Fan status
    • Defrost status
  7. upPeriodIndex:70 indicates the uplink reporting period parameter position.
    periodIndex:74 indicates the data acquisition period parameter position.
  8. Parameter meanings:
    • 110: Refrigerated cabinet temperature threshold
    • 112: Defrost temperature threshold
    • 114: Status change threshold
  9. The parameter reporting / parameter response port is 214.

7. Thing Model

7.1 Basic Thing Model Information

Data thing model:

  • Name: [ECS-2280NEO]
  • id Name: ecs_2280neo_22101

Parameter thing model:

  • Name: [ECS-2280NEO-PARA]
  • id Name: ecs_2280neo_para_22101
javascript
let frameInfo={
    port:22, dataLen:14,rssi:true,battery:4,
    tagList:[{ index:0, tag:0x86}, { index:1, tag:0x01}]
}

Field description:

  • port: 22
  • dataLen: 14
  • rssi: true
  • battery: 4
  • Tag positions:
    • index 0 = 0x86
    • index 1 = 0x01

7.3 Corrected Thing Model Script

javascript
let port = msg?.userdata?.port || null;
if (port !== 22) return null;

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

let appInfo = [
    { name: "temp_refrigerator", field_name: "temp_refrigerator", unit: "℃", index: 6, type: "int16BE", coefficient: 0.1, decimal: 1 },
    { name: "temp_defrost", field_name: "temp_defrost", unit: "℃", index: 8, type: "int16BE", coefficient: 0.1, decimal: 1 },
    { name: "status_valve", field_name: "status_valve", unit: "", index: 10, type: "bitLE23-23" },
    { name: "status_fan", field_name: "status_fan", unit: "", index: 10, type: "bitLE27-27" },
    { name: "status_defrost", field_name: "status_defrost", unit: "", index: 10, type: "bitLE30-30" }
];

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

let tdata = payParser.telemetry();

return {
    telemetry_data: tdata,
    server_attrs: null,
    shared_attrs: null
};

8. Third-Party Platform Data Subscription

8.1 MQTT Topic

latex
/v32/{Organization Account}/tkl/up/telemetry/{eui}
json
{
    "eui": "Device EUI",
    "active_time": "2026-03-29T09:00:00.000Z",
    "thingModelId": "Actual ID generated by the platform",
    "thingModelIdName": "ecs_2280neo_22101",
    "telemetry_data": {
        "snr": 0,
        "rssi": 0,
        "battery": 0,
        "temp_refrigerator": -18.5,
        "temp_defrost": -6.0,
        "status_valve": 1,
        "status_fan": 1,
        "status_defrost": 0
    }
}

Description:

  • thingModelId and eui were not included in the provided materials, so they are reserved here as actual platform values.
  • It is recommended to use the unified business naming: ecs_2280neo_22101.
  • The temperature and status values are examples. The field names come from the provided thing model definition.

9. RPC

9.1 RPC Names

The provided RPC names include:

  • ecs_2280neo_22101_set
  • ecs_2280neo_22101_get

9.2 Parameter Definition

javascript
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_temp_refrigerator", field_name: "cov_refrigerator_temp", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
  app_112: {name: "cov_temp_defrost", field_name: "cov_temp_defrost", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
  app_114: {name: "cov_status", field_name: "cov_status", unit: "", type: "uint32BE"},
  app_150: {name: "addr", field_name: "addr_modbus", unit: "", type: "uint8"}
}

Parameter description:

  • period_up: Reporting period
  • period_read: Data acquisition period
  • cov_temp_refrigerator: Change reporting threshold for refrigerated cabinet temperature
  • cov_temp_defrost: Change reporting threshold for defrost temperature
  • cov_status: Status change reporting item
  • addr_modbus: Modbus address

9.3 RPC Code

Set Parameter RPC

javascript
let classMode = (device && device.shared_attrs && device.shared_attrs.class_mode) || "ClassA";
let dnWaitms = classMode === "ClassA" ? 0 : 5000;
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_temp_refrigerator", field_name: "cov_refrigerator_temp", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
    app_112: {name: "cov_temp_defrost", field_name: "cov_temp_defrost", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
    app_114: {name: "cov_status", field_name: "cov_status", unit: "", type: "uint32BE"},
    app_150: {name: "addr", field_name: "addr_modbus", unit: "", type: "uint8"}
}
params.cov_status=1
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=[]
let msgServerAttrs={
    sleepTimeMs: 0,
    type:"modifyAttrs",
    dnMsg: {
        server_attrs:  {
            ecs_2280neo_22101_set: {
                counter:0,
                ms:Date.now(),
                params:params
            }
        }
    }
}
msgQue.push(msgServerAttrs);
let msgPara=RPCHelper.makeMSG({
    msgType:Utils.msgType.paras,
    device:device,
    dnBuffer:dnBuffer,
    sleepTime:0,
    dnWaitms:dnWaitms
})
msgQue.push(msgPara);
if (classMode==="ClassA")  return msgQue
let msgRedo=RPCHelper.makeMSG({
    msgType:Utils.msgType.paras,
    device:device,
    dnBuffer:redoBuffer,
    sleepTime:0,
    dnWaitms:dnWaitms
})
msgQue.push(msgRedo);
return msgQue

Read Parameter RPC

javascript
let classMode = (device && device.shared_attrs && device.shared_attrs.class_mode) || "ClassA";
let dnWaitms = classMode === "ClassA" ? 0 : 5000;
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_temp_refrigerator", field_name: "cov_refrigerator_temp", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
    app_112: {name: "cov_temp_defrost", field_name: "cov_temp_defrost", unit: "℃", type: "int16BE",coefficient:0.1,decimal:1},
    app_114: {name: "cov_status", field_name: "cov_status", unit: "", type: "uint32BE"},
    app_150: {name: "addr", 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=[]
let msgServerAttrs={
    sleepTimeMs: 0,
    type:"modifyAttrs",
    dnMsg: {
        server_attrs:  {
            ecs_2280neo_22101_set: {
                counter:0,
                ms:Date.now(),
                params:params
            }
        }
    }
}
msgQue.push(msgServerAttrs);
let msgPara=RPCHelper.makeMSG({
    msgType:Utils.msgType.paras,
    device:device,
    dnBuffer:dnBuffer,
    sleepTime:0,
    dnWaitms:dnWaitms
})
msgQue.push(msgPara);
if (classMode==="ClassA")  return msgQue
let msgRedo=RPCHelper.makeMSG({
    msgType:Utils.msgType.paras,
    device:device,
    dnBuffer:redoBuffer,
    sleepTime:0,
    dnWaitms:dnWaitms
})
msgQue.push(msgRedo);
return msgQue

10. Template Selection

In the ThinkLink platform, search for the template:

latex
ECS-2280NEO

Or search by business type:

latex
22101

This corresponds to the Elitech ECS-2280NEO temperature controller.