1. Sensor Introduction
Model catalog
Search for these models in ThinkLink by name or ID.
| Model type | Name | id_name | Platform model ID |
|---|---|---|---|
| RPC | [ECS-2280NEO GET] para | ecs_2280neo_22101_get | 80536120831512581 |
| RPC | [ECS-2280NEO SET] para | ecs_2280neo_22101_set | 79888011143155717 |
| Template | ECS-2280NEO | 80533446350344197 | |
| Thing Model | [ECS-2280NEO] | ecs_2280neo_22101 | 79886859227893765 |
| Thing Model | [ELITECH-22101-ECS-2280NEO资产] 区域聚合 | ecs_2280neo_asset_22101 | 119677174411063308 |
| Parameter Thing Model | [ECS-2280NEO-PARA] | ecs_2280neo_para_22101 | 90829990110695429 |
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
- Read the status bit block and extract:
5.1 Register Definition
| Data Item | Function Code | Address Dec | Address Hex | Data Type | Description |
|---|---|---|---|---|---|
| Refrigerated cabinet temperature | 03 | 256 | 0x0100 | int16 | Refrigerated cabinet temperature, coefficient 0.1 |
| Defrost temperature | 03 | 257 | 0x0101 | int16 | Defrost temperature, coefficient 0.1 |
| Controller status | 01 | 512 | 0x0200 | bit | 0 = Off, 1 = On |
| Cabinet temperature probe fault P1 | 01 | 520 | 0x0208 | bit | 0 = No fault, 1 = Fault |
| Defrost probe fault P2 | 01 | 521 | 0x0209 | bit | 0 = No fault, 1 = Fault |
| High temperature alarm | 01 | 524 | 0x020C | bit | 0 = No alarm, 1 = Alarm |
| Low temperature alarm | 01 | 525 | 0x020D | bit | 0 = No alarm, 1 = Alarm |
| Defrost status | 01 | 535 | 0x0217 | bit | 0 = Off, 1 = On |
| Door open alarm | 01 | 536 | 0x0218 | bit | 0 = No alarm, 1 = Alarm |
| Fan status | 01 | 539 | 0x021B | bit | 0 = Off, 1 = On |
| Refrigeration status / compressor status | 01 | 542 | 0x021E | bit | 0 = Off, 1 = On |
| Door status | 03 | 10 | 0x000A | bit | 0 = Closed, 1 = Open |
6. EdgeBus
6.1 EB Configuration Parameters
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
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:
- The device uplink port is 22.
- The business frame header uses:
version = 0x86dataType = 0x01
- Function Code 03 is used to read:
- 256: Refrigerated cabinet temperature
- 257: Defrost temperature
- 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
- After Function Code 01 returns, EB writes bytes 3–6 of the status data into the application area as
Uint32LE. - The thing model then extracts the following from this 32-bit status word:
- Valve status
- Fan status
- Defrost status
upPeriodIndex:70indicates the uplink reporting period parameter position.periodIndex:74indicates the data acquisition period parameter position.- Parameter meanings:
110: Refrigerated cabinet temperature threshold112: Defrost temperature threshold114: Status change threshold
- 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
7.2 Uplink Frame Structure
let frameInfo={
port:22, dataLen:14,rssi:true,battery:4,
tagList:[{ index:0, tag:0x86}, { index:1, tag:0x01}]
}Field description:
port: 22dataLen: 14rssi: truebattery: 4- Tag positions:
- index 0 =
0x86 - index 1 =
0x01
- index 0 =
7.3 Corrected Thing Model Script
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
/v32/{Organization Account}/tkl/up/telemetry/{eui}8.2 Example Uplink Data
{
"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:
thingModelIdandeuiwere 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_setecs_2280neo_22101_get
9.2 Parameter Definition
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 periodperiod_read: Data acquisition periodcov_temp_refrigerator: Change reporting threshold for refrigerated cabinet temperaturecov_temp_defrost: Change reporting threshold for defrost temperaturecov_status: Status change reporting itemaddr_modbus: Modbus address
9.3 RPC Code
Set Parameter RPC
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 msgQueRead Parameter RPC
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 msgQue10. Template Selection
In the ThinkLink platform, search for the template:
ECS-2280NEOOr search by business type:
22101This corresponds to the Elitech ECS-2280NEO temperature controller.