---
# System prepended metadata

title: Smart Meter Reader Protocol ( Taipei Water )
tags: [Acer]

---

---
tags: 'Acer'
---
Smart Meter Reader Protocol ( Taipei Water ) 
===
## Data Encode
   <font color=red>!!! Important:  
       For image data, we don't need to encode.
       if the bytes number of data is odd, please add one more byte after the data, let it become "EVEN" bytes.
   </font>
   1. Random data(2 bytes)  + data + CRC(2 bytes)
   2. Reverse high & low bytes position before last two bytes(CRC)
   
### Encode Example:
```
Data:  1,2,3,4
Random Seed: 88 72
Encode with Seed :  88,72,89,74,91,76
Add Payload CRC :  88,72,89,74,91,76,228,130
Reverse High/Low Bytes before CRC :  72,88,74,89,76,91,228,130
```
### Decode Example
```
Got payload:  72,88,74,89,76,91,228,130
Reverse Paylod:  88,72,89,74,91,76,228,130
Check CRC, then get data + data CRC :  88,72,89,74,91,76
Decode by xor operation with random seed:  1,2,3,4
```
### NodeJS Code
```
let primer = new (require("./Primer/Primer.js"))();
let data = new Array(1, 2, 3, 4);
console.log("Encode Example:");
console.log("Data: ", data.toString());
let d0 = parseInt(Math.random() * 256);
let d1 = parseInt(Math.random() * 256);
console.log("Random Seed:", d0, d1);
let output = new Array();
output.push(d0);
output.push(d1);
for (let i = 0; i < data.length; i += 2) {
  output.push(d0 ^ data[i]);
  output.push(d1 ^ data[i + 1]);
}
console.log("Encode with Seed : ", output.toString());
primer.makeCRC16(output);
console.log("Add Payload CRC : ", output.toString());
for (let i = 0; i < output.length - 2; i += 2) {
  let tmp = output[i];
  output[i] = output[i + 1];
  output[i + 1] = tmp;
}
console.log("Reverse High/Low Bytes before CRC : ", output.toString());

console.log("\r\nDecode Example:");
console.log("Got payload: ", output.toString());
for (let i = 0; i < output.length - 2; i += 2) {
  let tmp = output[i];
  output[i] = output[i + 1];
  output[i + 1] = tmp;
}
console.log("Reverse Paylod: ", output.toString());
output.pop();
output.pop();
console.log("Check CRC, then get data + data CRC : ", output.toString());
let payload = new Array();
for (let i = 2; i < output.length; i += 2) {
  payload.push(output[0] ^ output[i]);
  payload.push(output[1] ^ output[i + 1]);
}
console.log("Decode by xor operation with random seed: ", payload.toString());
```
## Water Meter
### Protocol
#### Register
##### Request "Protocol Version 0"
```json=
{
    UINT8     commandCode;     // Always be 0x01
    UINT8     MeterNumber[16];
    UINT8     IMEI[16];
    UINT8     IMSI[16];
    INT16     RSRP;   
    INT16     RSRQ; 
    INT16     Battery;         // (value*100)
    UINT32    MeterType;
    UINT8     protocolVersion;  // Always be 0
    UINT16    CRC;
} STC_REGISTER;
```
##### Response "Protocol Version 0"
```json=
{
    UINT8     commandCode;     // Always be 0x02
    UINT8     MeterNumber[16];
    UINT8     IMEI[16];
    UINT8     IMSI[16];
    UINT8     currentTime[6];   // ( YYMMDDHHMMSS in binary)
    UINT8     samplingTime[6];  // ( YYMMDDHHMMSS in binary)
    UINT8     uplinkTime[6];    // ( YYMMDDHHMMSS in binary)
    UINT8     uploadServerIP[16];
    UINT16    uploadServerPort;
    UINT8     imageServerIP[16];
    UINT16    imageServerPort;
    UINT32    samplingPeriod;
    UINT32    uplinkPeriod;
    UINT32    MeterType;
    UINT16    command;       
    UINT8     imageDate[6]; 
    UINT8     reserved;
    UINT16    CRC;
} STC_REGISTER_RESPONSE; 
```
##### Request "Protocol Version 1"
<font color='red'>2020/05/29 新增 Battery 變數,伺服器變更</font>
```json=
{
    UINT8     commandCode;     // Always be 0x01
    UINT8     MeterNumber[16];
    UINT8     IMEI[16];
    UINT8     IMSI[16];
    INT16     RSRP;   
    INT16     RSRQ; 
    INT16     Battery;         // (value*100)
    UINT32    MeterType;
    UINT8     protocolVersion;  // Always be 1
    UINT8     v0;
    UINT8     v1;
    UINT8     v2;
    UINT8     reserved;        // for odd bytes
    UINT16    CRC;
} STC_REGISTER;
```
##### Response "Protocol Version 1"
Same as Response "Protocol Verison 0"

<font color='red'>Request "Protocol Version 2"</font>
```json=
{
    UINT8     commandCode;        // Always be 0x01
    UINT8     MeterNumber[16];
    UINT8     IMEI[16];
    UINT8     IMSI[16];
    INT16     RSRP;   
    INT16     RSRQ; 
    INT16     Battery;            // (value*100)
    UINT32    MeterType;
    UINT8     protocolVersion;    // Always be 2
    UINT8     v0;
    UINT8     v1;
    UINT8     v2;
    UINT8     reserved; 
    UINT16    CRC;
} STC_REGISTER;
```
<font color='red'>Response "Protocol Version 2"</font>
```json=
{
    UINT8     commandCode;     // Always be 0x02
    UINT8     MeterNumber[16];
    UINT8     IMEI[16];
    UINT8     IMSI[16];
    UINT8     currentTime[6];   // ( YYMMDDHHMMSS in binary)
    UINT8     samplingTime[6];  // ( YYMMDDHHMMSS in binary)
    UINT8     uplinkTime[6];    // ( YYMMDDHHMMSS in binary)
    UINT8     uploadServerIP[16];
    UINT16    uploadServerPort;
    UINT8     imageServerIP[16];
    UINT16    imageServerPort;
    UINT32    samplingPeriod;
    UINT32    uplinkPeriod;
    UINT32    MeterType;
    UINT16    command;       
    UINT8     imageDate[6]; 
    UINT8     secondDataServerIP[16]; // if disable, secondServerIP[0] equal 0
    UINT16    secondDataServerPort;         // if disable, secondServerPort equal 0
    UINT8     secondImageServerIP[16]; // if disable, secondServerIP[0] equal 0
    UINT16    secondImageServerPort;         // if disable, secondServerPort equal 0
    UINT8     reserved;
    UINT16    CRC;
} STC_REGISTER_RESPONSE; 
```


#### Commands:
|Code|Name|
|---|---|
|0x00|None|
|0x01|uploadImage|
|0x02|uploadROI|
|0x03|setParameters|

<B>Meter will send "request parameters" if it received command code == 0x03</B>
##### Request Parameters
```json=
{
    UINT8     commandCode;     // Always be 0x0b
    UINT8     MeterNumber[16];
    UINT16    requestVersion;
    UINT8     reserved;
    UINT16    CRC;
} STC_REGISTER_RESPONSE; 
```
##### Response for "requestVersion=0"
```json=
{
    UINT8     commandCode;         // Always be 0x0C
    UINT8     MeterNumber[16];
    UINT16    requestVersion;      // Always be 0x0000
    UINT8     newMeterNumber[16];  // if no change,newMeterNumber[0] equal 0
    UINT8     newRegisterIP[16];   // if no change,newRegisterIP[0] equal 0
    UINT16    newRegisterPort;     // if no change,newRegisterPort equal 0
    FLOAT64   refferenceVolume;    // if no change,refferenceValue equal -1
    UINT8     digitalNumbers;      // if digitalNumbers equal 0, means no change
    UINT32    MeterType;
    UINT8     IntegerNo;
    UINT8     DecimalNo;
    INT16     ROI_Angle;         // if no chagne, digitalNumbers equal 0
    INT32     Max_Flow;          // if no change, fill -1
    
    UINT16    xLeftTop;
    UINT16    yLeftTop;
    UINT16    xRightTop;
    UINT16    yRightTop;
    UINT16    xLeftBottom;
    UINT16    yLeftBottom;
    UINT16    xRightBottom;
    UINT16    yRightBottom;
    UINT8     OCRParameters;    
    UINT8     FontWidth;
    UINT8     FontId;
    UINT8     RoID;
    
    UINT16    xLeftTop;
    UINT16    yLeftTop;
    UINT16    xRightTop;
    UINT16    yRightTop;
    UINT16    xLeftBottom;
    UINT16    yLeftBottom;
    UINT16    xRightBottom;
    UINT16    yRightBottom;
    UINT8     OCRParameters;    
    UINT8     FontWidth;
    UINT8     FontId;
    UINT8     RoID;
    
    ....    
    
    UINT16    command;
    UINT8     imageDate[6];
    UINT16    CRC;
} STC_REGISTER_RESPONSE; 
```
Response of "requestVersion=0" for GT:
```
{
    UINT8     commandCode;        // Always be 0x0C
    UINT8     MeterNumber[16];
    UINT16    requestVersion;     // Always be 0x0000
    UINT8     newMeterNumber[16]; // if no change,newMeterNumber[0] equal 0
    UINT8     newRegisterIP[16];  // if no change,newRegisterIP[0] equal 0
    UINT16    newRegisterPort;    // if no change,newRegisterPort equal 0
    FLOAT64   refferenceVolume; (-1) 
    UINT8     digitalNumbers; (0) 
    UINT32    MeterType; (0)
    UINT8     IntegerNo; (0)
    UINT8     DecimalNo; (0)
    INT16     ROI_Angle; (0)      // if no chagne, digitalNumbers equal 0
    INT32     Max_Flow;  (-1)     // if no change,fill -1
    UINT16    command;
    UINT8     imageDate[6];
    UINT16    CRC;
} STC_REGISTER_RESPONSE;
```

##### Response for "requestVersion=1"
```json=
{
    UINT8     commandCode;         // Always be 0x0C
    UINT8     MeterNumber[16];
    UINT16    requestVersion;      // Always be 0x0000
    UINT8     newMeterNumber[16];  // if no change,newMeterNumber[0] equal 0
    UINT8     newRegisterIP[16];   // if no change,newRegisterIP[0] equal 0
    UINT16    newRegisterPort;     // if no change,newRegisterPort equal 0
    FLOAT64   refferenceVolume;    // if no change,refferenceValue equal -1
    UINT8     digitalNumbers;      // if digitalNumbers equal 0, means no change
    UINT32    MeterType;
    UINT8     IntegerNo;
    UINT8     DecimalNo;
    INT16     ROI_Angle;           // if no chagne, digitalNumbers equal 0
    INT32     Max_Flow;            // if no change, fill -1
    
    UINT16    xLeftTop;
    UINT16    yLeftTop;
    UINT16    xRightTop;
    UINT16    yRightTop;
    UINT16    xLeftBottom;
    UINT16    yLeftBottom;
    UINT16    xRightBottom;
    UINT16    yRightBottom;
    UINT8     OCRParameters;    
    UINT8     FontWidth;
    UINT8     FontId;
    UINT8     RoID;
    
    UINT16    xLeftTop;
    UINT16    yLeftTop;
    UINT16    xRightTop;
    UINT16    yRightTop;
    UINT16    xLeftBottom;
    UINT16    yLeftBottom;
    UINT16    xRightBottom;
    UINT16    yRightBottom;
    UINT8     OCRParameters;    
    UINT8     FontWidth;
    UINT8     FontId;
    UINT8     RoID;
    
    ....    
    
    UINT16    command;
    UINT8     imageDate[6];
    UINT8     secondDataServerIP[16];  // if disable, secondServerIP[0] equal 0
    UINT16    secondDataServerPort;    // if disable, secondServerPort equal 0
    UINT8     secondImageServerIP[16]; // if disable, secondServerIP[0] equal 0
    UINT16    secondImageServerPort;         // if disable, secondServerPort equal 0
    INT16     imageShift_y;        // if no change, equal -1
    UINT16    CRC;
} STC_REGISTER_RESPONSE; 
```
Response of "requestVersion=1" for GT:
```
{
    UINT8     commandCode;        // Always be 0x0C
    UINT8     MeterNumber[16];
    UINT16    requestVersion;     // Always be 0x0000
    UINT8     newMeterNumber[16]; // if no change,newMeterNumber[0] equal 0
    UINT8     newRegisterIP[16];  // if no change,newRegisterIP[0] equal 0
    UINT16    newRegisterPort;    // if no change,newRegisterPort equal 0
    FLOAT64   refferenceVolume; (-1) 
    UINT8     digitalNumbers; (0) 
    UINT32    MeterType; (0)
    UINT8     IntegerNo; (0)
    UINT8     DecimalNo; (0)
    INT16     ROI_Angle; (0)      // if no chagne, digitalNumbers equal 0
    INT32     Max_Flow;  (-1)     // if no change,fill -1
    UINT16    command;
    UINT8     imageDate[6];
    UINT8     secondDataServerIP[16];  // if disable, secondServerIP[0] equal 0
    UINT16    secondDataServerPort;    // if disable, secondServerPort equal 0
    UINT8     secondImageServerIP[16]; // if disable, secondServerIP[0] equal 0
    UINT16    secondImageServerPort;   // if disable, secondServerPort equal 0
    INT16     imageShift_y; (-1)        // no change
    UINT16    CRC;
} STC_REGISTER_RESPONSE;
```

### Data Collector
##### Data Upload
###### Request
```json=
{
    UINT8     commandCode;      // Always be 0x03
    UINT8     MeterNumber[16],
    UINT8     uploadRecords;
    INT16     RSRP;   
    INT16     RSRQ; 
    INT16     Battery; ( Value*100 )
    
    FLOAT64   Volume;
    UINT8     recordTime[6];     // ( YYMMDDHHMMSS in binary )
    
    FLOAT64   Volume;
    UINT8     recordTime;
    ...
    
    UINT16    CRC;
} STC_DATA_REPORT;
```
###### Response
```json=
{
    UINT8     commandCode;      // Always be 0x04
    UINT8     MeterNumber[16];
    UINT8     uploadRecords;
    UINT8     currentTime[6];   // ( YYMMDDHHMMSS in binary )
    UINT8     samplingTime[6];  // ( YYMMDDHHMMSS in binary )
    UINT8     uplinkTime[6];    // ( YYMMDDHHMMSS in binary )
    UINT8     uploadServerIP[16];
    UINT16    uploadServerPort;
    UINT8     imageServerIP[16];
    UINT16    imageServerPort;
    UINT32    samplingPeriod;
    UINT32    uplinkPeriod;
    UINT32    MeterType;
    UINT16    command;          // Mask 0x01: upload image , 0x02: upload ROI
    UINT8     imageDate[6];
    UINT16    CRC;
} STC_DATA_REPORT_RESPONSE;
```
##### Alert Upload
AlertType:
* 0x01: No Battery
* <font color='color'> 0x02: Battery package communication error</font>

###### Request
```json=
{
    UINT8     commandCode;        // Always be 0x05
    UINT8     MeterNumber[16];
    UINT8     alertType;
    FLOAT64   Volume;
    INT16     Battery;            // ( Value*100 )
    INT16     RSRP;   
    INT16     RSRQ;    
    UINT8     currentTime[6];     // ( YYMMDDHHMMSS in binary )
    UINT16    CRC;
}
```
###### Response

```json=
{
    UINT8     commandCode;      // Always be 0x06
    UINT8     alertType;
    UINT8     MeterNumber[16];
    UINT8     currentTime[6];   // ( YYMMDDHHMMSS in binary )
    UINT8     samplingTime[6];  // ( YYMMDDHHMMSS in binary )
    UINT8     uplinkTime[6];    // ( YYMMDDHHMMSS in binary )
    UINT8     uploadServerIP[16];
    UINT16    uploadServerPort;
    UINT8     imageServerIP[16];
    UINT16    imageServerPort;
    UINT32    samplingPeriod;
    UINT32    uplinkPeriod;
    UINT32    MeterType;
    UINT16    command;         // Mask 0x01: upload image , 0x02: upload ROI
    UINT8     imageDate[6];
    UINT16    CRC;
}
```

### Image Collector
#### UDP API: Upload Image
###### Request

 ```json=
{
    UINT8     commandCode;      // Always be 0x07
    UINT8     MeterNumber[16];
    UINT8     captureTime[6];   // ( YYMMDDHHMMSS in binary )
    UINT16    width;
    UINT16    height;
    UINT32    totalSize;        
    UINT16    totalBatchNum;    
    UINT16    batchIndex;
    UINT8     imageType;        // 0: B&W 1: Gray 2: compressed B&W 3: compressed Gray
    UINT8     data[dataSize];   // dataSize=totalSize/totalBatchNum.
    UINT16    CRC;
}
```
###### Response
```json=
{
    UINT8     commandCode;      // Always be 0x08
    UINT8     MeterNumber[16];
    UINT8     captureTime[6];      //  ( YYMMDDHHMMSS in binary )
    UINT16    width;
    UINT16    height;
    UINT32    totalSize;        
    UINT16    totalBatchNum;    
    UINT16    batchIndex;
    UINT8     currentTime[6];   //  ( YYMMDDHHMMSS in binary )
    UINT8     imageType;        // 0: B&W 1: Gray 2: compressed B&W 3: compressed Gray
    UINT16    command;         // Mask 0x01: upload image , 0x02: upload ROI
    UINT8     imageDate[6];
    UINT16    CRC;
}
```

#### UDP API: Upload ROI
###### Request Version 0
 ```json=
{
    UINT8     commandCode;      // Always be 0x09
    UINT8     MeterNumber[16];
    UINT8     protocolVersion;  // Always be 0
    UINT8     reserved;
    UINT8     digitalNumbers;
    UINT32    MeterType;
    UINT8     IntegerNo;
    UINT8     DecimalNo;      
    INT16     imageShift_y;
    
    UINT16    xLeftTop;
    UINT16    yLeftTop;
    UINT16    xRightTop;
    UINT16    yRightTop;
    UINT16    xLeftBottom;
    UINT16    yLeftBottom;
    UINT16    xRightBottom;
    UINT16    yRightBottom;
    UINT8     OCRParameters;    
    UINT8     FontWidth;
    UINT8     FontId;
    UINT8     RoID;
    
    UINT16    xLeftTop;
    UINT16    yLeftTop;
    UINT16    xRightTop;
    UINT16    yRightTop;
    UINT16    xLeftBottom;
    UINT16    yLeftBottom;
    UINT16    xRightBottom;
    UINT16    yRightBottom;
    UINT8     OCRParameters;    
    UINT8     FontWidth;
    UINT8     FontId;
    UINT8     RoID;
    
    ....    
    
    UINT16    CRC;
}
```
###### Response Version 0
```json=
{
    UINT8     commandCode;      // Always be 0x0A
    UINT8     MeterNumber[16];
    UINT8     digitalNumbers;
    UINT32    MeterType;
    UINT8     IntegerNo;
    UINT8     DecimalNo;
    UINT16    command;         // Mask 0x01: upload image , 0x02: upload ROI
    UINT8     imageDate[6];
    UINT16    CRC;
}
```
###### Request Version 1
 ```json=
{
    UINT8     commandCode;      // Always be 0x09
    UINT8     MeterNumber[16];
    UINT8     protocolVersion;  // Always be 0x01
    UINT8     reserved;
    UINT8     digitalNumbers;
    UINT32    MeterType;
    UINT8     IntegerNo;
    UINT8     DecimalNo;   
    INT16     ROI_Angle;        
    INT32     Max_Flow;     
    INT16     imageShift_y;
    
    UINT16    xLeftTop;
    UINT16    yLeftTop;
    UINT16    xRightTop;
    UINT16    yRightTop;
    UINT16    xLeftBottom;
    UINT16    yLeftBottom;
    UINT16    xRightBottom;
    UINT16    yRightBottom;
    UINT8     OCRParameters;    
    UINT8     FontWidth;
    UINT8     FontId;
    UINT8     RoID;
    
    UINT16    xLeftTop;
    UINT16    yLeftTop;
    UINT16    xRightTop;
    UINT16    yRightTop;
    UINT16    xLeftBottom;
    UINT16    yLeftBottom;
    UINT16    xRightBottom;
    UINT16    yRightBottom;
    UINT8     OCRParameters;    
    UINT8     FontWidth;
    UINT8     FontId;
    UINT8     RoID;
    
    ....    
    
    UINT16    CRC;
}
```
###### Response Version 1
```json=
{
    UINT8     commandCode;      // Always be 0x0A
    UINT8     MeterNumber[16];
    UINT8     digitalNumbers;
    UINT32    MeterType;
    UINT8     IntegerNo;
    UINT8     DecimalNo;
    UINT16    command;         // Mask 0x01: upload image , 0x02: upload ROI
    UINT8     imageDate[6];
    UINT16    CRC;
}
```




### IDAM Register
##### Get Device List
 ```json=
{
    UINT8     commandCode;     // Always be 0x10
    UINT8     MeterNumber[16];
    UINT8     IMEI[16];
    UINT8     IMSI[16];
    INT16     RSRP;   
    INT16     RSRQ; 
    INT16     Battery;         // (value*100)
    UINT32    MeterType;
    UINT8     protocolVersion;  // Always be 0 or 1
    UINT8     v0;
    UINT8     v1;
    UINT8     v2;
    UINT8     startIndex;        // for odd bytes
    UINT16    CRC;
}
```
###### Response for protocol version 0
```json=
{
    UINT8     commandCode;      // Always be 0x11
    UINT8     MeterNumber[16];  // UUID for IDAM
    UINT8     currentTime[6];   // ( YYMMDDHHMMSS in binary)
    UINT8     samplingTime[6];  // ( YYMMDDHHMMSS in binary)
    UINT8     uplinkTime[6];    // ( YYMMDDHHMMSS in binary)
    UINT8     uploadServerIP[16];
    UINT16    uploadServerPort;
    UINT8     imageServerIP[16];
    UINT16    imageServerPort;
    UINT32    samplingPeriod;
    UINT32    uplinkPeriod;
    UINT16    command;       
    UINT8     imageDate[6]; 
    UINT32    p2pUploadOffset;            // P2P upload offset
    UINT8     p2pTimeSliceUnit;
    UINT8     neverSleep;
    UINT16    imageTimeSlice;
    UINT16    earlyWakeUp;
    UINT8     totalP2pDevices;
    UINT8     startIndex;
    UINT8     batchDeviceNum;
    UINT8     MeterNumber1[16];
    UINT8     MeterNumber2[16]; 
    ...
    ...
    ... 
    // According to meter numbers, 20 devices max for each batch
    UINT16    CRC;
}
```

###### Response for protocol version 1
```json=
{
    UINT8     commandCode;      // Always be 0x11
    UINT8     MeterNumber[16];  // UUID for IDAM
    UINT8     currentTime[6];   // ( YYMMDDHHMMSS in binary)
    UINT8     samplingTime[6];  // ( YYMMDDHHMMSS in binary)
    UINT8     uplinkTime[6];    // ( YYMMDDHHMMSS in binary)
    UINT8     uploadServerIP[16];
    UINT16    uploadServerPort;
    UINT8     imageServerIP[16];
    UINT16    imageServerPort;
    UINT32    samplingPeriod;
    UINT32    uplinkPeriod;
    UINT16    command;       
    UINT8     imageDate[6]; 
    UINT32    p2pUploadOffset;            // P2P upload offset
    UINT8     p2pTimeSliceUnit;
    UINT8     neverSleep;
    UINT16    imageTimeSlice;
    UINT16    earlyWakeUp;
    UINT8     totalP2pDevices;
    UINT8     offsetP2PID;         // new in Version 1
    UINT8     reserved;            // new in version 1
    UINT8     startIndex;
    UINT8     batchDeviceNum;
    UINT8     MeterNumber1[16];
    UINT8     MeterNumber2[16]; 
    ...
    ...
    ... 
    // According to meter numbers, 20 devices max for each batch
    UINT16    CRC;
}
```


##### upload Device Status
 ```json=
{
    UINT8     commandCode;     // Always be 0x12
    UINT8     MeterNumber[16];
    INT16     RSRP;   
    INT16     RSRQ; 
    INT16     Battery;         // (value*100)
    UINT8     protocolVersion;  // Always be 0
    UINT8     neverSleep;
    UINT8     time[6];
    UINT8     state;
    UINT8     reserved;
    UINT8     deviceNum;
    UINT16    deviceJoinStatus[20];
    UINT16    CRC;
}
```
###### Response
 ```json=
{
    UINT8     commandCode;     // Always be 0x13
    UINT8     neverSleep;
    UINT8     forceSleep;
    UINT8     reboot;
    UINT16    CRC;
}
```