Modbus TCP Server / Galaxy panel gateway
This tutorial will guide you in setting up HSYCO as a gateway to enable communication between Modbus TCP and one of the security panels integrated into HSYCO. HSYCO will act as a Modbus TCP server.
To access HSYCO Manager open a browser and type the URL:
https://192.168.1.50/hsycoserver/manager
The IP address and the URLKey written above are the default ones
Add a security control panel I/O Server
Follow these steps of this tutorial:
Remember to set the Galaxy I/O Server attribute startupevents to true.
Add a Modbus Tcp server I/O Server
1. Go back to the Manager splash screen
2. Click on Settings.
3. Add a new I/O server.
4. Click the type input field.
5. Type "mod"
6. Select Modbus TCP Server.
7. Select the name input field.
8. Assign a unique name to the I/O server, for example "mserver"
9. Click the port input field.
10. Type "502", the default Modbus port.
11. Click "Confirm"
12. Click on the Options icon.
13. Add a new option.
14. Click the option field.
15. Select "eventslog".
16. Click the value input field.
17. Select "true".
18. Click "Confirm".
19. Close the Options popup.
20. Click "Save Apply & restart".
21. Confirm by clicking the Save button.
Check the connection status
1. Let’s now check the connection status of the I/O Servers we just added. Go back to the Manager splash screen and click on Status Browser.
2. Click the "Filter" field to search for the connection datapoint.
3. Type "galaxy.conn"
4. If the datapoint ‘galaxy.connection’ is equal to ‘online,’ this means that the Galaxy I/O server is successfully connected to HSYCO.
EVENTS scripting
1. From the Manager splash screen select Code Editor.
2. Click "New Events File"
3. Give a name to your script, for example: "gateway.txt"
4. Click "New File"
5. Now it's time to write some lines of code.
For further information about the logic of EVENTS programming, read EVENTS programming quickstart
Let's start with some simple functions:
#copy the status of a zone of the security panel to a Modbus register (Holding Register)
io galaxy.z1.alarm = 1 : io mserver.1.1.hr = "ushort:"1
io galaxy.z1.alarm = 0 : io mserver.1.1.hr = "ushort:"0
#copy the status of a zone of the security panel to a Modbus register (Coil)
io galaxy.z2.alarm = 1 : io mserver.1.10.co = "bit:"1
io galaxy.z2.alarm = 0 : io mserver.1.10.co = "bit:"0
#when a Modbus register is set to 1/0, arm/disarm a security panel program
io mserver.1.20.hr = 1 : io galaxy.g1.armed = tot
io mserver.1.20.hr = 0 : io galaxy.g1.armed = 0
Click ‘Save’ in the upper right corner to activate this script.
The complete list of all the datapoints generated by an I/O Server is available in the Integrations section.
You can use Javascript as well. For example, this code automatically keeps the status of a Galaxy panel aligned with a series of registers in a Modbus TCP Server.
First, a JS code to create and keep updated the Modbus register table:
#********************************************************
# ************** GATEWAY GALAXY MODBUS ******************
#********************************************************
# Initialization
init: {
// MODBUS GATEWAY ADDRESS
var unitid = "1";
//used for testing purposes
programTimerRepeat("galaxytest", 15);
}
function ioEvent(name, value): {
# if and event comes from galaxy
if (name.startsWith("galaxy") == true ){
messageLog("GATEWAY GL - event from central: " + name + " / value: " + value );
var register = "";
if (name.startsWith("galaxy.g")){
var register = (name.split(".")[1]).replace("g","");
if (name.endsWith(".armed")){
//dp example: galaxy.g1.armed = 0,tot,part
//register 1-32
//0=disarmed, 1=tot, 2=part
messageLog("GATEWAY GL - group armed - T1.1 register: " + register + " | status: " + value);
if (value == "0"){
ioSet("mserver."+unitid+"."+register+".hr", "ushort:0");
} else if (value == "tot"){
ioSet("mserver."+unitid+"."+register+".hr", "ushort:1");
} else if (value == "part"){
ioSet("mserver."+unitid+"."+register+".hr", "ushort:2");
}
} else if (name.endsWith(".alarm")){
register = (register * 1) + 100;
//dp example: galaxy.g1.alarm = 0,1,reset
//register 101-132
//0=no alarm, 1=alarm, 2=reset
messageLog("GATEWAY GL - group alarm - T1.2 register: " + register + " | status: " + value);
if (value == "0"){
ioSet("mserver."+unitid+"."+register+".hr", "ushort:0");
} else if (value == "1"){
ioSet("mserver."+unitid+"."+register+".hr", "ushort:1");
} else if (value == "reset"){
ioSet("mserver."+unitid+"."+register+".hr", "ushort:2");
}
} else if (name.endsWith(".ready")){
register = (register * 1) + 200;
//dp example: galaxy.g1.ready = 0,1
//register 201-232
//0=not ready 1=ready
messageLog("GATEWAY GL - group ready - T1.3 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
}
} else if (name.startsWith("galaxy.o")){
var register = (name.split(".")[1]).replace("o","");
if (name.endsWith(".active")){
register = (register * 1) + 500;
//dp example: galaxy.o1.active = 0,1
//register 501-756
//0=not active, 1=active
messageLog("GATEWAY GL - output active - T2.1 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
}
} else if (name.startsWith("galaxy.z")){
var register = (name.split(".")[1]).replace("z","");
if (name.endsWith(".open")){
register = (register * 1) + 0;
//dp example: galaxy.z1.open = 0,1
//register 1001-5158
//0=not open, 1=open
messageLog("GATEWAY GL - zone open - T3.1 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
} else if (name.endsWith(".alarm")){
register = (register * 1) - + 9000;
//dp example: galaxy.z1.alarm = 0,1
//register 10001-14158
//0=no alarm, 1=alarm
messageLog("GATEWAY GL - zone alarm - T3.2 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
} else if (name.endsWith(".bypassed")){
register = (register * 1) + 19000;
//dp example: galaxy.z1.bypassed = 0,1
//register 20001-24158
//0=no bypassed, 1=bypassed
messageLog("GATEWAY GL - zone bypassed - T3.3 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
} else if (name.endsWith(".tamper")){
register = (register * 1) + 29000;
//dp example: galaxy.z1.tamper = 0,1
//register 30001-34158
//0=no tamper, 1=tamper
messageLog("GATEWAY GL - zone tamper - T3.4 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
} else if (name.endsWith(".fault")){
register = (register * 1) + 39000;
//dp example: galaxy.z1.fault = 0,1
//register 40001-44158
//0=no fault, 1=fault
messageLog("GATEWAY GL - zone fault - T3.5 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
} else if (name.endsWith(".masked")){
register = (register * 1) + 49000;
//dp example: galaxy.z1.masked = 0,1
//register 50001-54158
//0=no masked, 1=masked
messageLog("GATEWAY GL - zone masked - T3.6 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
} else if (name.endsWith(".resistance")){
register = (register * 1) + 59000;
//dp example: galaxy.z1.resistance = 0,1
//register 60001-64158
//0=no resistance problem, 1=resistance problem
messageLog("GATEWAY GL - zone resistance - T3.7 register: " + register + " | status: " + value);
ioSet("mserver."+unitid+"."+register+".hr", "ushort:" + value);
}
} else if (name.startsWith("galaxy.connection")){
//register 65200 = 1 online
if (value == "online"){
ioSet("mserver."+unitid+".65200.hr", "ushort:1");
} else {
ioSet("mserver."+unitid+".65200.hr", "ushort:2");
}
}
} else if (name.startsWith("mserver.")){
//commands
//messageLog("GATEWAY GL - T10.1 - mserver: " + name + "|" + value);
var splt = name.split(".");
var uid = splt[1];
var reg = splt[2] * 1;
// if the unit id is correct
if (uid == unitid){
// groups commands
if (reg >= 64 && reg <= 95){
var prog = (reg * 1) - 63;
//messageLog("GATEWAY GL - T10.1 - program arming: " + prog + " / new value: " + value);
if (value == "0"){
// then disarm
ioSet("galaxy.g" + prog + ".armed", "0");
messageLog("GATEWAY GL - T10.1 - program: " + prog + " disarm");
} else if (value == "1"){
// then arm tot
ioSet("galaxy.g" + prog + ".armed", "tot");
messageLog("GATEWAY GL - T10.1 - program arm tot: " + prog);
} else if (value == "2"){
// then arm part
ioSet("galaxy.g" + prog + ".armed", "part");
messageLog("GATEWAY GL - T10.1 - program arm part: " + prog);
} else if (value == "3"){
// then arm abort
ioSet("galaxy.g" + prog + ".armed", "abort");
messageLog("GATEWAY GL - T10.1 - program arm abort: " + prog);
} else if (value == "4"){
// then arm force
ioSet("galaxy.g" + prog + ".armed", "force");
messageLog("GATEWAY GL - T10.1 - program arm force: " + prog);
}
} else if (reg >= 164 && reg <= 195){
var prog = (reg * 1) - 163;
//messageLog("GATEWAY GL - T10.1 - program reset: " + prog + " / new value: " + value);
if (value == "1"){
// then reset
ioSet("galaxy.g" + prog + ".reset", "1");
messageLog("GATEWAY GL - T10.2 - program: " + prog + " reset");
}
} else if (reg >= 15001 && reg <= 19158){
var zone = (reg * 1) - 14000;
//messageLog("GATEWAY GL - T10.3 - zone bypass: " + zone + " / new value: " + value);
if (value == "1" || value == "0"){
ioSet("galaxy.z" + zone + ".bypassed", value);
messageLog("GATEWAY GL - T10.3 - zone: " + zone + " bypassed: " + value);
}
} else if (reg >= 601 && reg <= 856){
var out = (reg * 1) - 600;
//messageLog("GATEWAY GL - T10.6 - output control:" + out + " / new value: " + value);
if (value == "1" || value == "0"){
ioSet("galaxy.o" + out + ".active", value);
messageLog("GATEWAY GL - T10.3 - out: " + out + " active: " + value);
}
}
}
}
}
#subscribe to registers used to send commands to the galaxy panel
io mserver.connection = online or time : {
//groups arm/disarm
for (var i = 64; i <= 95; i++) {
ioSet("mserver."+unitid+"."+i+".hr", "subscribe:short");
}
//groups reset
for (var i = 164; i <= 195; i++) {
ioSet("mserver."+unitid+"."+i+".hr", "subscribe:short");
}
//zones enable disable
for (var i = 15001; i <= 19158; i++) {
sleep(2);
ioSet("mserver."+unitid+"."+i+".hr", "subscribe:short");
}
//outpus active
for (var i = 601; i <= 856; i++) {
sleep(2);
ioSet("mserver."+unitid+"."+i+".hr", "subscribe:short");
}
//connection status
ioSet("mserver."+unitid+".65200.hr", "subscribe:short");
}
MODBUS tables
Supported Modbus functions, Modbus TCP/IP
03: Read Holding Registers
06: Write Single Register
T1.1 Groups armed
Modbus address | Info |
---|---|
1 | Group status 1 |
2 | Group status 2 |
3 | Group status 3 |
4 | Group status 4 |
... | ... |
32 | Group status 32 |
Values: 0=disarmed, 1=tot, 2=part
T1.2 Groups alarms
Modbus address | Info |
---|---|
101 | Group alarm 1 |
102 | Group alarm 2 |
103 | Group alarm 3 |
104 | Group alarm 4 |
... | ... |
132 | Group alarm 32 |
Values: 0=no alarms, 1=alarms
T1.3 Groups ready
Modbus address | Info |
---|---|
201 | Group ready 1 |
202 | Group ready 2 |
203 | Group ready 3 |
204 | Group ready 4 |
... | ... |
232 | Group ready 32 |
Values: 0=not ready, 1=ready
T2.1 Outputs active
Modbus address | Info |
---|---|
501 | Output active 1 |
502 | Output active 2 |
503 | Output active 3 |
504 | Output active 4 |
... | ... |
756 | Output active 256 |
Values: 0=not active, 1=active
T3.1 Zones open
Modbus address | Info |
---|---|
1001 | Zone open 1 |
1002 | Zone open 2 |
1003 | Zone open 3 |
1004 | Zone open 4 |
... | ... |
5158 | Zone open 4158 |
Values: 0=not open, 1=open
T3.2 Zones alarm
Modbus address | Info |
---|---|
10001 | Zone open 1 |
10002 | Zone open 2 |
10003 | Zone open 3 |
10004 | Zone open 4 |
... | ... |
15158 | Zone open 4158 |
Values: 0=not in alarm, 1=alarm
T3.3 Zones bypassed
Modbus address | Info |
---|---|
20001 | Zone bypassed 1 |
20002 | Zone bypassed 2 |
20003 | Zone bypassed 3 |
20004 | Zone bypassed 4 |
... | ... |
25158 | Zone bypassed 4158 |
Values: 0=not bypassed, 1=bypassed
T3.4 Zones tamper
Modbus address | Info |
---|---|
30001 | Zone tamper 1 |
30002 | Zone tamper 2 |
30003 | Zone tamper 3 |
30004 | Zone tamper 4 |
... | ... |
35158 | Zone tamper 4158 |
Values: 0=not tampered, 1=tampered
T3.5 Zones fault
Modbus address | Info |
---|---|
40001 | Zone fault 1 |
40002 | Zone fault 2 |
40003 | Zone fault 3 |
40004 | Zone fault 4 |
... | ... |
45158 | Zone fault 4158 |
Values: 0=not in fault, 1=fault
T3.6 Zones masked
Modbus address | Info |
---|---|
50001 | Zone fault 1 |
50002 | Zone fault 2 |
50003 | Zone fault 3 |
50004 | Zone fault 4 |
... | ... |
55158 | Zone fault 4156 |
Values: 0=not masked, 1=masked
T3.7 Zones resistance
Modbus address | Info |
---|---|
60001 | Zone resistance 1 |
60002 | Zone resistance 2 |
60003 | Zone resistance 3 |
60004 | Zone resistance 4 |
... | ... |
65158 | Zone resistance 4158 |
Connection status
Modbus address | Info |
---|---|
65200 | Connection status |
Values: 0=the Galaxy panel is not communicating with HSYCO, 1=the Galaxy panel in online
T10.1 Groups command arm table
Modbus address | Info |
---|---|
64 | Group arm 1 |
65 | Group arm 2 |
66 | Group arm 3 |
67 | Group arm 4 |
... | ... |
95 | Group arm 32 |
Values: 0=disarm, 1=arm tot, 2=arm part, 3=abort, 4=force
T10.2 Groups command reset table
Modbus address | Info |
---|---|
164 | Group reset 1 |
165 | Group reset 2 |
166 | Group reset 3 |
167 | Group reset 4 |
... | ... |
195 | Group reset 32 |
Values: 1=reset
T10.3 Zones command bypass table
Modbus address | Info |
---|---|
15001 | Zone bypass 1 |
15002 | Zone bypass 2 |
15003 | Zone bypass 3 |
15004 | Zone bypass 4 |
... | ... |
19158 | Zone bypass 4158 |
Values: 0=remove bypass, 1=bypass
T10.6 Outputs command active table
Modbus address | Info |
---|---|
601 | Output active 1 |
602 | Output active 2 |
603 | Output active 3 |
604 | Output active 4 |
... | ... |
856 | Output active 256 |
Values: 0=de-activate, 1=activate