@jotiotech/node-red-sia-premise-device 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/icon.png +0 -0
- package/icon.svg +9 -0
- package/package.json +23 -0
- package/src/SIA_device.html +44 -0
- package/src/SIA_device.js +240 -0
- package/src/SIA_server.html +75 -0
- package/src/SIA_server.js +127 -0
- package/src/siacodes.csv +280 -0
package/README.md
ADDED
package/icon.png
ADDED
|
Binary file
|
package/icon.svg
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48">
|
|
2
|
+
<path d="
|
|
3
|
+
m 24 26.05 M 9 45 Q 7.8 45 6.9 44.1 Q 6 43.2 6 42 V 5 q 0 -1.2 0.9 -2.1 q 0.9 -0.9 2.1 -0.9 h 30 q 1.2 0 2.1 0.9 q 0.9 0.9 0.9 2.1 V 25.7 Q 41.3 25.3 40.55 25.075 Q 39.8 24.85 39 24.65 V 5 H 9 V 42 H 24.3 Q 24.65 42.85 25.05 43.575 T 26 45 Z M 34.65 47 L 34.4 44.6 Q 33.4 44.3 32.35 43.725 Q 31.3 43.15 30.65 42.45 L 28.55 43.45 L 26.8 40.75 L 28.7 39.25 Q 28.45 38.1 28.45 37.175 Q 28.45 36.25 28.7 35.1 L 26.8 33.6 L 28.55 30.85 L 30.65 31.85 Q 31.3 31.25 32.35 30.65 Q 33.4 30.05 34.4 29.75 L 34.65 27.3 H 37.65 L 37.95 29.75 Q 38.95 30.05 40 30.65 Q 41.05 31.25 41.7 31.85 L 43.8 30.85 L 45.55 33.6 L 43.65 35.1 Q 43.9 36.25 43.9 37.175 Q 43.9 38.1 43.65 39.25 L 45.55 40.75 L 43.8 43.45 L 41.7 42.45 Q 41.05 43.15 40 43.725 Q 38.95 44.3 37.95 44.6 L 37.65 47 Z M 36.15 42.25 Q 38.35 42.25 39.8 40.8 Q 41.25 39.35 41.25 37.15 T 39.8 33.5 Q 38.35 32.05 36.15 32.05 T 32.5 33.5 Q 31.05 34.95 31.05 37.15 T 32.5 40.8 Q 33.95 42.25 36.15 42.25 Z
|
|
4
|
+
" />
|
|
5
|
+
</svg>
|
|
6
|
+
|
|
7
|
+
<!--
|
|
8
|
+
M24 21.05ZM9 40q-1.2 0-2.1-.9Q6 38.2 6 37V7q0-1.2.9-2.1Q7.8 4 9 4h30q1.2 0 2.1.9.9.9.9 2.1v13.7q-.7-.4-1.45-.625-.75-.225-1.55-.425V7H9v28.15q2.95-2.75 6.675-4.475Q19.4 28.95 23.75 28.9q-.2.7-.3 1.45-.1.75-.1 1.55-3.15.1-6.1 1.275-2.95 1.175-5.5 3.375V37H24.3q.35.85.75 1.575T26 40Zm15.1-15.05q.4 0 .775-.025t.775-.125q.95-1.3 2.175-2.375Q29.05 21.35 30.5 20.65q.25-.6.375-1.25T31 18.05q0-2.9-2-4.9-2-2-4.9-2-2.9 0-4.9 2-2 2-2 4.9 0 2.9 2 4.9 2 2 4.9 2Zm0-3q-1.6 0-2.75-1.15t-1.15-2.75q0-1.6 1.15-2.75t2.75-1.15q1.6 0 2.75 1.15T28 18.05q0 1.6-1.15 2.75t-2.75 1.15ZM34.65 42l-.25-2.4q-1-.3-2.05-.875-1.05-.575-1.7-1.275l-2.1 1-1.75-2.7 1.9-1.5q-.25-1.15-.25-2.075 0-.925.25-2.075l-1.9-1.5 1.75-2.75 2.1 1q.65-.6 1.7-1.2 1.05-.6 2.05-.9l.25-2.45h3l.3 2.45q1 .3 2.05.9 1.05.6 1.7 1.2l2.1-1 1.75 2.75-1.9 1.5q.25 1.15.25 2.075 0 .925-.25 2.075l1.9 1.5-1.75 2.7-2.1-1q-.65.7-1.7 1.275-1.05.575-2.05.875l-.3 2.4Zm1.5-4.75q2.2 0 3.65-1.45 1.45-1.45 1.45-3.65T39.8 28.5q-1.45-1.45-3.65-1.45T32.5 28.5q-1.45 1.45-1.45 3.65t1.45 3.65q1.45 1.45 3.65 1.45Z
|
|
9
|
+
-->
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jotiotech/node-red-sia-premise-device",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"engines": {
|
|
5
|
+
"node": ">=12.0.0"
|
|
6
|
+
},
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"description": "",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"retry": "^0.13.1"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"node-red",
|
|
14
|
+
"parsing"
|
|
15
|
+
],
|
|
16
|
+
"node-red": {
|
|
17
|
+
"version": ">=1.0.0",
|
|
18
|
+
"nodes": {
|
|
19
|
+
"SIA_device": "src/SIA_device.js",
|
|
20
|
+
"SIA_server": "src/SIA_server.js"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType('SIA-device', {
|
|
3
|
+
category: 'common',
|
|
4
|
+
color: '#0B99D8',
|
|
5
|
+
defaults: {
|
|
6
|
+
name: { value: "" },
|
|
7
|
+
server: { value: "", type: "SIA-server", required: true }, // This will
|
|
8
|
+
},
|
|
9
|
+
align: 'left',
|
|
10
|
+
icon: "icon.png",
|
|
11
|
+
inputs: 1,
|
|
12
|
+
outputs: 0,
|
|
13
|
+
label: function () {
|
|
14
|
+
return this.name || "SIA Device";
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<style>
|
|
22
|
+
|
|
23
|
+
.input-button-wrap>input {
|
|
24
|
+
width: 100% !important;
|
|
25
|
+
}
|
|
26
|
+
select {
|
|
27
|
+
width: 100% !important;
|
|
28
|
+
}
|
|
29
|
+
.editor-button {
|
|
30
|
+
height: 30px;
|
|
31
|
+
padding: 0 10px;
|
|
32
|
+
}
|
|
33
|
+
</style>
|
|
34
|
+
|
|
35
|
+
<script type="text/x-red" data-template-name="SIA-device">
|
|
36
|
+
<div class="form-row">
|
|
37
|
+
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
38
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
39
|
+
</div>
|
|
40
|
+
<div class="form-row">
|
|
41
|
+
<label for="node-input-server"><i class="icon-globe"></i> <span data-i18n="modbus-contrib.label.server"></span></label>
|
|
42
|
+
<input type="text" id="node-input-server">
|
|
43
|
+
</div>
|
|
44
|
+
</script>
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// const { Iconv } = require('iconv');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module.exports = function (RED) {
|
|
5
|
+
const tableCRC = [
|
|
6
|
+
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
|
|
7
|
+
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
|
|
8
|
+
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
|
|
9
|
+
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
|
|
10
|
+
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
|
|
11
|
+
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
|
|
12
|
+
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
|
|
13
|
+
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
|
|
14
|
+
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
|
|
15
|
+
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
|
|
16
|
+
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
|
|
17
|
+
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
|
|
18
|
+
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
|
|
19
|
+
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
|
|
20
|
+
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
|
|
21
|
+
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
|
|
22
|
+
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
|
|
23
|
+
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
|
|
24
|
+
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
|
|
25
|
+
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
|
|
26
|
+
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
|
|
27
|
+
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
|
|
28
|
+
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
|
|
29
|
+
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
|
|
30
|
+
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
|
|
31
|
+
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
|
|
32
|
+
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
|
|
33
|
+
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
|
|
34
|
+
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
|
|
35
|
+
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
|
|
36
|
+
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
|
|
37
|
+
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const deviceMap = new Map();
|
|
41
|
+
const crypto = require('crypto');
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
function SIADeviceNode(config) {
|
|
46
|
+
RED.nodes.createNode(this, config);
|
|
47
|
+
|
|
48
|
+
// TODO: eventually we should disconnect from the server after each message as there shouldn't be a high volume of messages
|
|
49
|
+
const server = RED.nodes.getNode(config.server);
|
|
50
|
+
|
|
51
|
+
const siaConfig = server.getSIAConfig();
|
|
52
|
+
console.log('SIA Config:', siaConfig);
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
server.connect();
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
function utf8toWin1252(str) {
|
|
60
|
+
tmpBuf = Buffer.from(str, 'utf8');
|
|
61
|
+
return tmpBuf.toString('latin1');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function calculateCRCIBM16(str){
|
|
65
|
+
data = new Buffer.from(str);
|
|
66
|
+
let len = data.length;
|
|
67
|
+
let buffer = 0;
|
|
68
|
+
let crc;
|
|
69
|
+
while (len--) {
|
|
70
|
+
crc = ((crc >>> 8) ^ (tableCRC[(crc ^ (data[buffer++])) & 0xff]));
|
|
71
|
+
}
|
|
72
|
+
return crc.toString(16).padStart(4, '0').toUpperCase();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function encrypt(encryptionType, encryptionKey, str) {
|
|
76
|
+
try {
|
|
77
|
+
const encryptionKeyBuf = new Buffer.from(encryptionKey, 'hex');
|
|
78
|
+
let iv = new Buffer.alloc(16);
|
|
79
|
+
iv.fill(0);
|
|
80
|
+
let cipher = crypto.createCipheriv(encryptionType, encryptionKeyBuf, iv);
|
|
81
|
+
cipher.setAutoPadding(false);
|
|
82
|
+
let encoded = cipher.update(str, 'utf8', 'hex');
|
|
83
|
+
encoded += cipher.final('hex');
|
|
84
|
+
return (encoded ? encoded : undefined);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
function generateTimestamp(){
|
|
92
|
+
const now = new Date();
|
|
93
|
+
|
|
94
|
+
// Pad single-digit numbers with a leading zero
|
|
95
|
+
const pad = (num) => num.toString().padStart(2, '0');
|
|
96
|
+
|
|
97
|
+
const hours = pad(now.getHours());
|
|
98
|
+
const minutes = pad(now.getMinutes());
|
|
99
|
+
const seconds = pad(now.getSeconds());
|
|
100
|
+
const month = pad(now.getMonth() + 1); // Months are 0-indexed
|
|
101
|
+
const day = pad(now.getDate());
|
|
102
|
+
const year = now.getFullYear();
|
|
103
|
+
|
|
104
|
+
return `_${hours}:${minutes}:${seconds},${month}-${day}-${year}`;
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function generatePadding(data){
|
|
109
|
+
buffer = new Buffer.from(data); // we need to get byte length of the message body, not string length
|
|
110
|
+
let msgLength = buffer.length;
|
|
111
|
+
|
|
112
|
+
let padding = '';
|
|
113
|
+
if(msgLength % 16 !== 0){
|
|
114
|
+
const paddingNeeded = 15 - (msgLength % 16);
|
|
115
|
+
// generate random uppercase letters (only letters) for paddingNeeded
|
|
116
|
+
for(let i=0; i<paddingNeeded; i++){
|
|
117
|
+
const randomChar = String.fromCharCode(65 + Math.floor(Math.random() * 26));
|
|
118
|
+
padding += randomChar;
|
|
119
|
+
}
|
|
120
|
+
// generate byte array
|
|
121
|
+
console.log('Padding needed:', paddingNeeded, 'Generated padding:', padding);
|
|
122
|
+
return padding+'|';
|
|
123
|
+
}else
|
|
124
|
+
return '';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
function validateHexString(str, strName, minLength, maxLength){ // NOTE LGTM
|
|
129
|
+
if(str.length < minLength || str.length > maxLength){
|
|
130
|
+
console.error(`${strName} must be between ${minLength} and ${maxLength} characters long`);
|
|
131
|
+
return false;
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if(str.length !=0 && !/^[0-9A-Fa-f]+$/.test(str)){
|
|
136
|
+
console.error(`${strName} must be hexadecimal characters only (0-9, A-F)`);
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function iterateMsgCount(id){ // NOTE LGTM
|
|
143
|
+
if(!deviceMap.has(id)){
|
|
144
|
+
deviceMap.set(id, 1);
|
|
145
|
+
}else{
|
|
146
|
+
let count = deviceMap.get(id);
|
|
147
|
+
count = (count % 9999) + 1; // wrap around at 999
|
|
148
|
+
deviceMap.set(id, count);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// utf8toWin1252("a test ñ");
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
this.on('input', message => {
|
|
156
|
+
// const payload = message.payload;
|
|
157
|
+
|
|
158
|
+
let payload = {
|
|
159
|
+
"account" : "AABBCC",
|
|
160
|
+
"accountPrefix" : "5678"
|
|
161
|
+
}
|
|
162
|
+
siaConfig.receiverNumber = "1234";
|
|
163
|
+
|
|
164
|
+
const deviceAccount = payload.account;
|
|
165
|
+
const deviceAccountPrefix = payload.accountPrefix || '0';
|
|
166
|
+
|
|
167
|
+
// INPUT VALIDATION
|
|
168
|
+
|
|
169
|
+
if(!validateHexString(deviceAccount, 'Device account', 3, 16)) return;
|
|
170
|
+
if(!validateHexString(deviceAccountPrefix, 'Device account prefix', 1, 6)) return;
|
|
171
|
+
if(!validateHexString(siaConfig.receiverNumber, 'Receiver number', 0, 6)) return;
|
|
172
|
+
|
|
173
|
+
const deviceIdentifier = 'L'+ deviceAccountPrefix + '#' + deviceAccount;
|
|
174
|
+
|
|
175
|
+
iterateMsgCount(deviceIdentifier);
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
// PART: <"id"><seq><Rrcvr><Lpref><#acct>[
|
|
179
|
+
let messageBodyStart = '"'; // <"id"><seq><Rrcvr><Lpref><#acct>[
|
|
180
|
+
if(siaConfig.encryptionEnabled)
|
|
181
|
+
messageBodyStart += '*';
|
|
182
|
+
|
|
183
|
+
messageBodyStart += 'SIA-DCS"' // ID placeholder
|
|
184
|
+
messageBodyStart += deviceMap.get(deviceIdentifier).toString().padStart(4, '0'); // message sequence number
|
|
185
|
+
if(siaConfig.receiverNumber.length >0)
|
|
186
|
+
messageBodyStart += 'R'+siaConfig.receiverNumber;
|
|
187
|
+
messageBodyStart += deviceIdentifier;
|
|
188
|
+
messageBodyStart += '[';
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
// PART: #<acct>|<data>][<extende data>]
|
|
192
|
+
let messageBodyData = '#'+deviceAccount + '|'; // <pad>|...data...][x…data…]
|
|
193
|
+
|
|
194
|
+
// data format
|
|
195
|
+
// (N)(id-number)(DCS)(zone)
|
|
196
|
+
// there's also a format of group-zone
|
|
197
|
+
|
|
198
|
+
// messageBodyData += "NFA"; //
|
|
199
|
+
messageBodyData += "Nri129/FA1234"; //
|
|
200
|
+
// optional extended data can be added here, for example
|
|
201
|
+
|
|
202
|
+
// PART: ]<timestamp>, finalization of body
|
|
203
|
+
let messageBody = ''; // <"id"><seq><Rrcvr><Lpref><#acct>[<pad>|...data...][x…data…]<timestamp>
|
|
204
|
+
let timestamp = generateTimestamp(); // TODO: this should be optional
|
|
205
|
+
|
|
206
|
+
if(siaConfig.encryptionEnabled){ // everything past [ till <CR> is to be encrypted
|
|
207
|
+
let toEncrypt = messageBodyData+']'+timestamp;
|
|
208
|
+
toEncrypt = generatePadding(toEncrypt) + toEncrypt;
|
|
209
|
+
messageBody = messageBodyStart + encrypt(siaConfig.encryptionType, siaConfig.encryptionKey, toEncrypt);
|
|
210
|
+
}else{
|
|
211
|
+
messageBody += messageBodyStart;
|
|
212
|
+
messageBody += messageBodyData;
|
|
213
|
+
messageBody += ']'; // end of data fields
|
|
214
|
+
// optional extended data
|
|
215
|
+
messageBody += timestamp;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Append <LF><crc><>
|
|
219
|
+
msgCount = (new Buffer.from(messageBody)).length;
|
|
220
|
+
|
|
221
|
+
let msg = '\n'; // <LF><crc><0LLL><"id"><seq><Rrcvr><Lpref><#acct>[<pad>|...data...][x…data…]<timestamp><CR>
|
|
222
|
+
msg += calculateCRCIBM16(messageBody); // CRC is 4 ASCII characters
|
|
223
|
+
msg += '0'+msgCount.toString(16).toUpperCase().padStart(3, '0'); // Carriage return
|
|
224
|
+
msg += messageBody;
|
|
225
|
+
msg += '\r';
|
|
226
|
+
|
|
227
|
+
// let hexMsg = '';
|
|
228
|
+
// for(let i=0; i<msg.length; i++){
|
|
229
|
+
// hexMsg += msg.charCodeAt(i).toString(16).padStart(2, '0').toUpperCase() + ' ';
|
|
230
|
+
// }
|
|
231
|
+
// console.log('Final message in hex: ', hexMsg);
|
|
232
|
+
|
|
233
|
+
server.connect();
|
|
234
|
+
server.write(msg);
|
|
235
|
+
server.close();
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
RED.nodes.registerType('SIA-device', SIADeviceNode);
|
|
240
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) since the year 2016 Klaus Landsdorf (http://plus4nodered.com/)
|
|
3
|
+
Copyright 2016 - Jason D. Harper, Argonne National Laboratory
|
|
4
|
+
Copyright 2015,2016 - Mika Karaila, Valmet Automation Inc.
|
|
5
|
+
All rights reserved.
|
|
6
|
+
node-red-contrib-modbus
|
|
7
|
+
|
|
8
|
+
@author <a href="mailto:klaus.landsdorf@bianco-royal.de">Klaus Landsdorf</a> (Bianco Royal)
|
|
9
|
+
-->
|
|
10
|
+
<script type="text/javascript">
|
|
11
|
+
RED.nodes.registerType('SIA-server', {
|
|
12
|
+
category: 'config',
|
|
13
|
+
defaults: {
|
|
14
|
+
|
|
15
|
+
name: { value: "" },
|
|
16
|
+
receiverHost: { value: "", required: true },
|
|
17
|
+
receiverPort: { value: "", required: true },
|
|
18
|
+
receiverNumber : { value: ""},
|
|
19
|
+
encryptionKey: { value: ""},
|
|
20
|
+
},
|
|
21
|
+
label: function () {
|
|
22
|
+
return this.name || 'sia-server@' + this.receiverHost;
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
oneditprepare: function () {
|
|
26
|
+
let previous = null;
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
if(this.encryptionKey == null){
|
|
30
|
+
this.encryptionKey = "";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let allowedLengths = [0, 32, 48, 64];
|
|
34
|
+
if(!allowedLengths.includes(this.encryptionKey.length)){
|
|
35
|
+
Node.error('Encryption key must be empty or 128, 192, 256 bits long in HEX');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if(!/^[0-9A-Fa-f]+$/.test(this.encryptionKey)){ // hexadecimal characters only
|
|
39
|
+
Node.error('Encryption key must be in hexadecimal characters only (0-9, A-F)');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
// check if encryptionKey is 128 bit 192 or 256 bit long
|
|
45
|
+
// encryptionKey needs to be a hex string
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<script type="text/x-red" data-template-name="SIA-server">
|
|
54
|
+
<div class="form-row">
|
|
55
|
+
<label for="node-config-input-name"><i class="icon-tag"></i> Name</label>
|
|
56
|
+
<input type="text" id="node-config-input-name" placeholder="Name">
|
|
57
|
+
</div>
|
|
58
|
+
<div class="form-row">
|
|
59
|
+
<label for="node-config-input-receiverHost">Receiver IP</label>
|
|
60
|
+
<input type="text" id="node-config-input-receiverHost" placeholder="Receiver Host">
|
|
61
|
+
</div>
|
|
62
|
+
<div class="form-row">
|
|
63
|
+
<label for="node-config-input-receiverPort">Receiver Port</label>
|
|
64
|
+
<input type="number" id="node-config-input-receiverPort" placeholder="Receiver Port">
|
|
65
|
+
</div>
|
|
66
|
+
<div class="form-row">
|
|
67
|
+
<label for="node-config-input-receiverNumber">Receiver Number</label>
|
|
68
|
+
<input type="number" id="node-config-input-receiverNumber" placeholder="Receiver Number">
|
|
69
|
+
</div>
|
|
70
|
+
<div class="form-row">
|
|
71
|
+
<label for="node-config-input-encryptionKey">Encryption Key</label>
|
|
72
|
+
<input type="password" id="node-config-input-encryptionKey" placeholder="SIA Password">
|
|
73
|
+
</div>
|
|
74
|
+
</script>
|
|
75
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
'use strict';
|
|
3
|
+
// SOURCE-MAP-REQUIRED
|
|
4
|
+
|
|
5
|
+
const Net = require('node:net');
|
|
6
|
+
const Retry = require('retry');
|
|
7
|
+
|
|
8
|
+
function SIAServer(config) {
|
|
9
|
+
RED.nodes.createNode(this, config);
|
|
10
|
+
|
|
11
|
+
this.receiverHost = config.receiverHost;
|
|
12
|
+
this.receiverPort = Number.parseInt(config.receiverPort);
|
|
13
|
+
this.receiverNumber = config.receiverNumber || '';
|
|
14
|
+
// This.siaAccount = config.siaAccount;
|
|
15
|
+
// this.siaAccountPrefix = config.siaAccountPrefix || 'L0';
|
|
16
|
+
this.encryptionKey = config.encryptionKey || '';
|
|
17
|
+
this.encryptionEnabled = this.encryptionKey.length > 0;
|
|
18
|
+
|
|
19
|
+
switch (this.encryptionKey.length) {
|
|
20
|
+
case 32:
|
|
21
|
+
this.encryptionType = 'aes-128-cbc';
|
|
22
|
+
break;
|
|
23
|
+
case 48:
|
|
24
|
+
this.encryptionType = 'aes-192-cbc';
|
|
25
|
+
break;
|
|
26
|
+
case 64:
|
|
27
|
+
this.encryptionType = 'aes-256-cbc';
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
const client = new Net.Socket();
|
|
36
|
+
|
|
37
|
+
process.on('uncaughtException', error => {
|
|
38
|
+
console.error('Uncaught Exception:', error);
|
|
39
|
+
client.destroy();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
this.connect = function () {
|
|
43
|
+
// If(!client.destroyed && client.readyState == 'open') {
|
|
44
|
+
// console.log('Already connected to SIA server at ' + this.receiverHost + ':' + this.receiverPort);
|
|
45
|
+
// return;
|
|
46
|
+
// }
|
|
47
|
+
|
|
48
|
+
if (!this.receiverHost || !this.receiverPort) {
|
|
49
|
+
console.error('Receiver host or port not set');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log('Connecting to SIA server at', this.receiverHost, this.receiverPort);
|
|
54
|
+
|
|
55
|
+
const operation = Retry.operation({
|
|
56
|
+
retries: 5,
|
|
57
|
+
factor: 2,
|
|
58
|
+
minTimeout: 1000,
|
|
59
|
+
maxTimeout: 20_000,
|
|
60
|
+
randomize: true,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const tmpRef = this;
|
|
64
|
+
|
|
65
|
+
let errorListener = null;
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
const connectCallback = () => {
|
|
69
|
+
console.log('Connected to SIA server at', tmpRef.receiverHost, tmpRef.receiverPort);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
operation.attempt(currentAttempt => {
|
|
73
|
+
|
|
74
|
+
if (errorListener) { // will not be active on first attempt
|
|
75
|
+
client.off('error', errorListener);
|
|
76
|
+
client.off('connect', connectCallback);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
errorListener = error => {
|
|
80
|
+
console.log(`Connection error: ${error.message}`);
|
|
81
|
+
if (operation.retry(error)) {
|
|
82
|
+
console.log(`Retrying connection to SIA server, attempt number: ${currentAttempt}`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
console.error('Failed to connect to SIA server:', error);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
client.once('error', errorListener);
|
|
90
|
+
|
|
91
|
+
client.connect(tmpRef.receiverPort, tmpRef.receiverHost, connectCallback);
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
this.getSIAConfig = function () {
|
|
96
|
+
return {
|
|
97
|
+
receiverNumber: this.receiverNumber,
|
|
98
|
+
encryptionKey: this.encryptionKey,
|
|
99
|
+
encryptionEnabled: this.encryptionEnabled,
|
|
100
|
+
encryptionType: this.encryptionType,
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
this.write = function (data) {
|
|
105
|
+
if (!client.destroyed && client.readyState == 'open') {
|
|
106
|
+
console.log('Sending data to SIA server:', data);
|
|
107
|
+
client.write(data);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
this.close = function () {
|
|
112
|
+
if (!client.destroyed) {
|
|
113
|
+
client.end();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Handle sending of data
|
|
118
|
+
// handle failure to connect
|
|
119
|
+
// payload won't be prepared here but in SIA device
|
|
120
|
+
|
|
121
|
+
// client.write('Hello, server.');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
RED.nodes.registerType('SIA-server', SIAServer);
|
|
125
|
+
|
|
126
|
+
/* istanbul ignore next */
|
|
127
|
+
};
|
package/src/siacodes.csv
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
AN,ANALOG RESTORAL
|
|
2
|
+
AR,AC RESTORAL
|
|
3
|
+
AS,ANALOG SERVICE
|
|
4
|
+
AT,AC TROUBLE
|
|
5
|
+
BA,BURGLARY ALARM
|
|
6
|
+
BB,BURGLARY BYPASS
|
|
7
|
+
BC,BURGLARY CANCEL
|
|
8
|
+
BD,SWINGER TROUBLE
|
|
9
|
+
BE,SWINGER TRBL RESTORE
|
|
10
|
+
BH,BURG ALARM RESTORE
|
|
11
|
+
BJ,BURG TROUBLE RESTORE
|
|
12
|
+
BM,BURG ALARM CROSS PNT
|
|
13
|
+
BR,BURGLARY RESTORAL
|
|
14
|
+
BS,BURGLARY SUPERVISORY
|
|
15
|
+
BT,BURGLARY TROUBLE
|
|
16
|
+
BU,BURGLARY UNBYPASS
|
|
17
|
+
BV,BURGLARY VERIFIED
|
|
18
|
+
BX,BURGLARY TEST
|
|
19
|
+
BZ,MISSING SUPERVISION
|
|
20
|
+
CA,AUTOMATIC CLOSING
|
|
21
|
+
CD,CLOSING DELINQUENT
|
|
22
|
+
CE,CLOSING EXTEND
|
|
23
|
+
CF,FORCED CLOSING
|
|
24
|
+
CG,CLOSE AREA
|
|
25
|
+
CI,FAIL TO CLOSE
|
|
26
|
+
CJ,LATE CLOSE
|
|
27
|
+
CK,EARLY CLOSE
|
|
28
|
+
CL,CLOSING REPORT
|
|
29
|
+
CM,MISSING AL-RECNT CLS
|
|
30
|
+
CP,AUTOMATIC CLOSING
|
|
31
|
+
CR,RECENT CLOSING
|
|
32
|
+
CS,CLOSE KEY SWITCH
|
|
33
|
+
CT,LATE TO OPEN
|
|
34
|
+
CW,WAS FORCE ARMED
|
|
35
|
+
CZ,POINT CLOSING
|
|
36
|
+
DA,CARD ASSIGNED
|
|
37
|
+
DB,CARD DELETED
|
|
38
|
+
DC,ACCESS CLOSED
|
|
39
|
+
DD,ACCESS DENIED
|
|
40
|
+
DE,REQUEST TO ENTER
|
|
41
|
+
DF,DOOR FORCED
|
|
42
|
+
DG,ACCESS GRANTED
|
|
43
|
+
DH,DOOR LEFT OPEN-RSTRL
|
|
44
|
+
DJ,DOOR FORCED-TROUBLE
|
|
45
|
+
DK,ACCESS LOCKOUT
|
|
46
|
+
DL,DOOR LEFT OPEN-ALARM
|
|
47
|
+
DM,DOOR LEFT OPEN-TRBL
|
|
48
|
+
DN,DOOR LEFT OPEN
|
|
49
|
+
DO,ACCESS OPEN
|
|
50
|
+
DP,ACCESS DENIED-BAD TM
|
|
51
|
+
DQ,ACCESS DENIED-UN ARM
|
|
52
|
+
DR,DOOR RESTORAL
|
|
53
|
+
DS,DOOR STATION
|
|
54
|
+
DT,ACCESS TROUBLE
|
|
55
|
+
DU,DEALER ID#
|
|
56
|
+
DV,ACCESS DENIED-UN ENT
|
|
57
|
+
DW,ACCESS DENIED-INTRLK
|
|
58
|
+
DX,REQUEST TO EXIT
|
|
59
|
+
DY,DOOR LOCKED
|
|
60
|
+
DZ,ACCESS CLOSED STATE
|
|
61
|
+
EA,EXIT ALARM
|
|
62
|
+
EE,EXIT_ERROR
|
|
63
|
+
ER,EXPANSION RESTORAL
|
|
64
|
+
ET,EXPANSION TROUBLE
|
|
65
|
+
EX,EXTRNL DEVICE STATE
|
|
66
|
+
EZ,MISSING ALARM-EXT ER
|
|
67
|
+
FA,FIRE ALARM
|
|
68
|
+
FB,FIRE BYPASS
|
|
69
|
+
FC,FIRE CANCEL
|
|
70
|
+
FH,FIRE ALARM RESTORE
|
|
71
|
+
FI,FIRE TEST BEGIN
|
|
72
|
+
FJ,FIRE TROUBLE RESTORE
|
|
73
|
+
FK,FIRE TEST END
|
|
74
|
+
FM,FIRE ALARM CROSS PNT
|
|
75
|
+
FR,FIRE RESTORAL
|
|
76
|
+
FS,FIRE SUPERVISORY
|
|
77
|
+
FT,FIRE TROUBLE
|
|
78
|
+
FU,FIRE UNBYPASS
|
|
79
|
+
FX,FIRE TEST
|
|
80
|
+
FY,MISSING FIRE TROUBLE
|
|
81
|
+
FZ,MISSING FIRE SPRV
|
|
82
|
+
GA,GAS ALARM
|
|
83
|
+
GB,GAS BYPASS
|
|
84
|
+
GH,GAS ALARM RESTORE
|
|
85
|
+
GJ,GAS TROUBLE RESTORE
|
|
86
|
+
GR,GAS RESTORAL
|
|
87
|
+
GS,GAS SUPERVISORY
|
|
88
|
+
GT,GAS TROUBLE
|
|
89
|
+
GU,GAS UNBYPASS
|
|
90
|
+
GX,GAS TEST
|
|
91
|
+
HA,HOLDUP ALARM
|
|
92
|
+
HB,HOLDUP BYPASS
|
|
93
|
+
HH,HOLDUP ALARM RESTORE
|
|
94
|
+
HJ,HOLDUP TRBL RESTORE
|
|
95
|
+
HR,HOLDUP RESTORAL
|
|
96
|
+
HS,HOLDUP SUPERVISORY
|
|
97
|
+
HT,HOLDUP TROUBLE
|
|
98
|
+
HU,HOLDUP UNBYPASS
|
|
99
|
+
IA,EQPMT FAIL CONDITION
|
|
100
|
+
IR,EQPMT FAIL RESTORE
|
|
101
|
+
JA,USER CODE TAMPER
|
|
102
|
+
JD,DATE CHANGED
|
|
103
|
+
JH,HOLIDAY CHANGED
|
|
104
|
+
JK,LATCHKEY ALERT
|
|
105
|
+
JL,LOG THRESHOLD
|
|
106
|
+
JO,LOG OVERFLOW
|
|
107
|
+
JP,USER ON PREMISES
|
|
108
|
+
JR,SCHEDULE EXECUTED
|
|
109
|
+
JS,SCHEDULE CHANGED
|
|
110
|
+
JT,TIME CHANGED
|
|
111
|
+
JV,USER CODE CHANGED
|
|
112
|
+
JX,USER CODE DELETED
|
|
113
|
+
JY,USER CODE ADDED
|
|
114
|
+
JZ,USER LEVEL SET
|
|
115
|
+
KA,HEAT ALARM
|
|
116
|
+
KB,HEAT BYPASS
|
|
117
|
+
KH,HEAT ALARM RESTORE
|
|
118
|
+
KJ,HEAT TROUBLE RESTORE
|
|
119
|
+
KR,HEAT RESTORAL
|
|
120
|
+
KS,HEAT SUPERVISORY
|
|
121
|
+
KT,HEAT TROUBLE
|
|
122
|
+
KU,HEAT UNBYPASS
|
|
123
|
+
L_,LISTEN IN + SECONDS
|
|
124
|
+
LB,LOCAL PROG. BEGIN
|
|
125
|
+
LD,LOCAL PROG. DENIED
|
|
126
|
+
LE,LISTEN IN ENDED
|
|
127
|
+
LF,LISTEN IN BEGIN
|
|
128
|
+
LR,PHONE LINE RESTORAL
|
|
129
|
+
LS,LOCAL PROG. SUCCESS
|
|
130
|
+
LT,PHONE LINE TROUBLE
|
|
131
|
+
LU,LOCAL PROG. FAIL
|
|
132
|
+
LX,LOCAL PROG. ENDED
|
|
133
|
+
MA,MEDICAL ALARM
|
|
134
|
+
MB,MEDICAL BYPASS
|
|
135
|
+
MH,MEDIC ALARM RESTORE
|
|
136
|
+
MJ,MEDICAL TRBL RESTORE
|
|
137
|
+
MR,MEDICAL RESTORAL
|
|
138
|
+
MS,MEDICAL SUPERVISORY
|
|
139
|
+
MT,MEDICAL TROUBLE
|
|
140
|
+
MU,MEDICAL UNBYPASS
|
|
141
|
+
NA,NO ACTIVITY
|
|
142
|
+
NC,NETWORK CONDITION
|
|
143
|
+
NF,FORCED PERIMETER ARM
|
|
144
|
+
NL,PERIMETER ARMED
|
|
145
|
+
NR,NETWORK RESTORAL
|
|
146
|
+
NS,ACTIVITY RESUMED
|
|
147
|
+
NT,NETWORK FAILURE
|
|
148
|
+
OA,AUTOMATIC OPENING
|
|
149
|
+
OC,CANCEL REPORT
|
|
150
|
+
OG,OPEN AREA
|
|
151
|
+
OH,EARLY TO OPN FROM AL
|
|
152
|
+
OI,FAIL TO OPEN
|
|
153
|
+
OJ,LATE OPEN
|
|
154
|
+
OK,EARLY OPEN
|
|
155
|
+
OL,LATE TO OPEN FROM AL
|
|
156
|
+
OP,OPENING REPORT
|
|
157
|
+
OR,DISARM FROM ALARM
|
|
158
|
+
OS,OPEN KEY SWITCH
|
|
159
|
+
OT,LATE TO CLOSE
|
|
160
|
+
OZ,POINT OPENING
|
|
161
|
+
PA,PANIC ALARM
|
|
162
|
+
PB,PANIC BYPASS
|
|
163
|
+
PH,PANIC ALARM RESTORE
|
|
164
|
+
PJ,PANIC TRBL RESTORE
|
|
165
|
+
PR,PANIC RESTORAL
|
|
166
|
+
PS,PANIC SUPERVISORY
|
|
167
|
+
PT,PANIC TROUBLE
|
|
168
|
+
PU,PANIC UNBYPASS
|
|
169
|
+
QA,EMERGENCY ALARM
|
|
170
|
+
QB,EMERGENCY BYPASS
|
|
171
|
+
QH,EMRGCY ALARM RESTORE
|
|
172
|
+
QJ,EMRGCY TRBL RESTORE
|
|
173
|
+
QR,EMERGENCY RESTORAL
|
|
174
|
+
QS,EMRGCY SUPERVISORY
|
|
175
|
+
QT,EMERGENCY TROUBLE
|
|
176
|
+
QU,EMERGENCY UNBYPASS
|
|
177
|
+
RA,RMOTE PROG CALL FAIL
|
|
178
|
+
RB,REMOTE PROG. BEGIN
|
|
179
|
+
RC,RELAY CLOSE
|
|
180
|
+
RD,REMOTE PROG. DENIED
|
|
181
|
+
RN,REMOTE RESET
|
|
182
|
+
RO,RELAY OPEN
|
|
183
|
+
RP,AUTOMATIC TEST
|
|
184
|
+
RR,RESTORE POWER
|
|
185
|
+
RS,REMOTE PROG. SUCCESS
|
|
186
|
+
RT,DATA LOST
|
|
187
|
+
RU,REMOTE PROG. FAIL
|
|
188
|
+
RX,MANUAL TEST
|
|
189
|
+
RY,TEST OFF NORMAL
|
|
190
|
+
SA,SPRINKLER ALARM
|
|
191
|
+
SB,SPRINKLER BYPASS
|
|
192
|
+
SH,SPRKLR ALARM RESTORE
|
|
193
|
+
SJ,SPRKLR TRBL RESTORE
|
|
194
|
+
SR,SPRINKLER RESTORAL
|
|
195
|
+
SS,SPRINKLER SUPERVISRY
|
|
196
|
+
ST,SPRINKLER TROUBLE
|
|
197
|
+
SU,SPRINKLER UNBYPASS
|
|
198
|
+
TA,TAMPER ALARM
|
|
199
|
+
TB,TAMPER BYPASS
|
|
200
|
+
TC,ALL POINTS TESTED
|
|
201
|
+
TE,TEST END
|
|
202
|
+
TH,TAMPER ALRM RESTORE
|
|
203
|
+
TJ,TAMPER TRBL RESTORE
|
|
204
|
+
TP,WALK TEST POINT
|
|
205
|
+
TR,TAMPER RESTORAL
|
|
206
|
+
TS,TEST START
|
|
207
|
+
TT,TAMPER TROUBLE
|
|
208
|
+
TU,TAMPER UNBYPASS
|
|
209
|
+
TX,TEST REPORT
|
|
210
|
+
UA,UNTYPED ZONE ALARM
|
|
211
|
+
UB,UNTYPED ZONE BYPASS
|
|
212
|
+
UH,UNTYPD ALARM RESTORE
|
|
213
|
+
UJ,UNTYPED TRBL RESTORE
|
|
214
|
+
UR,UNTYPED ZONE RESTORE
|
|
215
|
+
US,UNTYPED ZONE SUPRVRY
|
|
216
|
+
UT,UNTYPED ZONE TROUBLE
|
|
217
|
+
UU,UNTYPED ZONE UNBYPSS
|
|
218
|
+
UX,UNDEFINED ALARM
|
|
219
|
+
UY,UNTYPED MISSING TRBL
|
|
220
|
+
UZ,UNTYPED MISSING ALRM
|
|
221
|
+
VI,PRINTER PAPER IN
|
|
222
|
+
VO,PRINTER PAPER OUT
|
|
223
|
+
VR,PRINTER RESTORE
|
|
224
|
+
VT,PRINTER TROUBLE
|
|
225
|
+
VX,PRINTER TEST
|
|
226
|
+
VY,PRINTER ONLINE
|
|
227
|
+
VZ,PRINTER OFFLINE
|
|
228
|
+
WA,WATER ALARM
|
|
229
|
+
WB,WATER BYPASS
|
|
230
|
+
WH,WATER ALARM RESTORE
|
|
231
|
+
WJ,WATER TRBL RESTORE
|
|
232
|
+
WR,WATER RESTORAL
|
|
233
|
+
WS,WATER SUPERVISORY
|
|
234
|
+
WT,WATER TROUBLE
|
|
235
|
+
WU,WATER UNBYPASS
|
|
236
|
+
XA,EXTRA ACCNT REPORT
|
|
237
|
+
XE,EXTRA POINT
|
|
238
|
+
XF,EXTRA RF POINT
|
|
239
|
+
XH,RF INTERFERENCE RST
|
|
240
|
+
XI,SENSOR RESET
|
|
241
|
+
XJ,RF RCVR TAMPER RST
|
|
242
|
+
XL,LOW RF SIGNAL
|
|
243
|
+
XM,MISSING ALRM-X POINT
|
|
244
|
+
XQ,RF INTERFERENCE
|
|
245
|
+
XR,TRANS. BAT. RESTORAL
|
|
246
|
+
XS,RF RECEIVER TAMPER
|
|
247
|
+
XT,TRANS. BAT. TROUBLE
|
|
248
|
+
XW,FORCED POINT
|
|
249
|
+
XX,FAIL TO TEST
|
|
250
|
+
YA,BELL FAULT
|
|
251
|
+
YB,BUSY SECONDS
|
|
252
|
+
YC,COMMUNICATIONS FAIL
|
|
253
|
+
YD,RCV LINECARD TROUBLE
|
|
254
|
+
YE,RCV LINECARD RESTORE
|
|
255
|
+
YF,PARA CHECKSUM FAIL
|
|
256
|
+
YG,PARAMETER CHANGED
|
|
257
|
+
YH,BELL RESTORED
|
|
258
|
+
YI,OVERCURRENT TROUBLE
|
|
259
|
+
YJ,OVERCURRENT RESTORE
|
|
260
|
+
YK,COMM. RESTORAL
|
|
261
|
+
YM,SYSTEM BATT MISSING
|
|
262
|
+
YN,INVALID REPORT
|
|
263
|
+
YO,UNKNOWN MESSAGE
|
|
264
|
+
YP,PWR SUPPLY TROUBLE
|
|
265
|
+
YQ,PWR SUPPLY RESTORE
|
|
266
|
+
YR,SYSTEM BAT. RESTORAL
|
|
267
|
+
YS,COMMUNICATIONS TRBL
|
|
268
|
+
YT,SYSTEM BAT. TROUBLE
|
|
269
|
+
YW,WATCHDOG RESET
|
|
270
|
+
YX,SERVICE REQUIRED
|
|
271
|
+
YY,STATUS REPORT
|
|
272
|
+
YZ,SERVICE COMPLETED
|
|
273
|
+
ZA,FREEZE ALARM
|
|
274
|
+
ZB,FREEZE BYPASS
|
|
275
|
+
ZH,FREEZE ALARM RESTORE
|
|
276
|
+
ZJ,FREEZE TRBL RESTORE
|
|
277
|
+
ZR,FREEZE RESTORAL
|
|
278
|
+
ZS,FREEZE SUPERVISORY
|
|
279
|
+
ZT,FREEZE TROUBLE
|
|
280
|
+
ZU,FREEZE UNBYPASS
|