This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Paradox EVO192 integration
#1
The following scripts integrate Paradox EVO192 security panel. Paradox PRT3 printer module is used to connect the security panel to LM5 through RS232 serial port.
Thanks our forum member rebooter for contribution! Wink

guardZoneStatus library:


Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
function guardzonefunction(zonenumber, zonestatus)   guardZones = {   [255255] = 'An empty zone has arrived',   [01] = 'The main entrance. Motion Sensor.',    [02] = 'The cabinet. Motion Sensor.',   [03] = 'The garage. Motion Sensor.',   [04] = 'The stairs. Motion Sensor.',   [05] = 'The living room. Motion Sensor.',   [06] = 'The dining room. Motion Sensor.',   [07] = 'The kitchen. Motion Sensor.',   [08] = 'Garage entrance. Motion Sensor.',   [09] = 'The main entrance. Window Break Sensor ',   [10] = 'The cabinet. Window Break Sensor ',   [11] = 'The garage. Window Break Sensor ',   [13] = 'Living room. Window Break Sensor ',   [14] = 'Dining room. Window Break Sensor ',   [15] = 'The kitchen. Window Break Sensor ',   [16] = 'The garage door. Reed switch ',   [17] = 'The main entrance. Reed switch ',   [18] = 'Dining room. Curtain',   [19] = 'Boiler room. Motion Sensor.',   [20] = 'The boiler room. Window jammer   [21] = 'Cinema hall. Motion Sensor',   [22] = 'Pantry. Motion Sensor',   [24] = 'SPA room. Motion Sensor',   [25] = 'Children's 1. Motion sensor',   [26] = 'Hall 2 floor. Motion Sensor.',   [27] = 'Children's 2. Motion sensor',   [28] = 'Master bedroom. Motion Sensor',   [30] = 'Pajar basement',   [31] = 'Fire 1st floor',   [32] = 'Fire 2nd floor',   [33] = 'Fire Sauna',   [34] = 'Fire attic',   [35] = 'Server fire',   [36] = 'Under the stairs',   [50] = 'House is armed',   [51] = 'House is disarmed', } -- Arming with mast   zonename = guardZones[zonenumber] -- log ("Zone Nr triggered: "..zonenumber.." status: "..zonestatus.." "..zonename) -- log(zonename) -- log(zonestatus) -- log(guardZones[zonenumber])   if zonestatus == 'closed' then     status = 1   elseif zonestatus == 'opened' then     status = 0   end       if zonenumber == 1 then             grp.update('8/0/1', status)     elseif zonenumber == 2 then --   zonename = guardZones[zonenumber]           grp.update('8/0/2', status)     elseif zonenumber == 3 then           grp.update('8/0/3', status)     elseif zonenumber == 4 then           grp.update('8/0/4', status)     elseif zonenumber == 5 then           grp.update('8/0/5', status)     elseif zonenumber == 6 then           grp.update('8/0/6', status)     elseif zonenumber == 7 then           grp.update('8/0/7', status)     elseif zonenumber == 8 then           grp.update('8/0/8', status)     elseif zonenumber == 9 then           grp.update('8/0/9', status)     elseif zonenumber == 10 then           grp.update('8/0/10', status)     elseif zonenumber == 11 then           grp.update('8/0/11', status)     elseif zonenumber == 13 then           grp.update('8/0/13', status)     elseif zonenumber == 14 then           grp.update('8/0/14', status)     elseif zonenumber == 15 then           grp.update('8/0/15', status)     elseif zonenumber == 16 then           grp.update('8/0/16', status)     elseif zonenumber == 17 then           grp.update('8/0/17', status)     elseif zonenumber == 18 then           grp.update('8/0/18', status)     elseif zonenumber == 19 then           grp.update('8/0/19', status)     elseif zonenumber == 20 then           grp.update('8/0/20', status)     elseif zonenumber == 21 then           grp.update('8/0/21', status)     elseif zonenumber == 22 then           grp.update('8/0/22', status)     elseif zonenumber == 24 then           grp.update('8/0/24', status)     elseif zonenumber == 25 then           grp.update('8/0/25', status)     elseif zonenumber == 26 then           grp.update('8/0/26', status)     elseif zonenumber == 27 then           grp.update('8/0/27', status)     elseif zonenumber == 28 then           grp.update('8/0/28', status)     elseif zonenumber == 30 then           grp.update('8/0/30', status)     elseif zonenumber == 31 then           grp.update('8/0/31', status)     elseif zonenumber == 32 then           grp.update('8/0/32', status)     elseif zonenumber == 33 then           grp.update('8/0/33', status)     elseif zonenumber == 34 then           grp.update('8/0/34', status)     elseif zonenumber == 35 then           grp.update('8/0/35', status)     elseif zonenumber == 36 then           grp.update('8/0/36', status)     -- process the status of security panel     -- if armed then switch off lights in whole house     elseif zonenumber == 50 then     if grp.getvalue('0/5/8') == false then       --    grp.update('0/5/5', status) --lights off       grp.update('0/5/8', status) --security panel status     end    elseif zonenumber == 51 then      if grp.getvalue('0/5/8') then           grp.update('0/5/8', status) --security panel status     end     elseif zonenumber == 255255 then     log("An empty zone has arrived")     end --if zonenumber end



RS232 communication script:

Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
require('user.guardZoneStatus') if not port then   require('serial')   port = serial.open('/dev/RS232', { baudrate = 9600, parity = 'none', databits = '8', stopbits = '1'})   port:flush()   line = '' end char = port:read(1, 1) if char then   if char == '\r' then     line = line:trim()     --log(line)    -- mail('info@something.com', 'Installation X', line)   --  loghex(line)     zone = tonumber(string.sub(line,-2))     if zone == nil  then       zone = 255255      -- log("An empty zone has arrived")         end --   if (zone > 1) or (zone <37 ) then     if (string.match(line,'opened')) == ('opened') then       zoneStatus = 'opened'       armstatus = grp.getvalue('0/5/8') --reading current status of security system -- log(armstatus)     if armstatus == true then     grp.update('0/5/8', false) -- write those which are not armed     end     else       zoneStatus = 'closed'     end -- string.match       -- parsing logs for setting to alarm       if (string.match(line,'Arming')) == ('Arming') then         zoneStatus = 'closed'         zone = 50     --  elseif (string.match(line,'  in')) == ('  in') then     --    zoneStatus = 'closed'     --    zone = 50     elseif (string.match(line,'ode entere')) == ('ode entere') then         zoneStatus = 'opened'           zone = 51     end -- string.match       guardzonefunction(zone,zoneStatus)   --  end -- test for zone nember 1 - 36     line = ''   else     line = line .. char   end  -- if char '\r' end
Reply
#2
Hello!

Here is my updated communication script. Maybe this helps someone...
It allows to see zone status, get info about areas (if there is trouble in some area and if area is open or not), arm/disarm etc...
Also it polls every minute area status.


Residential script (EVO192 communication, sleep interval 0 seconds):
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
require('user.guardZoneStatus') require('user.guardAreaStatus') if not port then   require('serial')   port = serial.open('/dev/RS232', { baudrate = 9600, parity = 'none', databits = '8', stopbits = '1'})   port:flush()   line = '' end control_house_security_ga = '10/1/0'                --area1 security status group address control_woodstorage_security_ga = '10/1/1'    --area2 security status group address security_code = '1234' char = port:read(1, 1) --log(char) if char then   if char == '\r' then     line = line:trim()     --log(line)         event = string.sub(line,1,2)    -- log(event)     if event == 'G0' then       eventnr = tonumber(string.sub(line,6,-5))             area = tonumber(string.sub(line,10,-1))       eventngr = tonumber(string.sub(line,2,4))       if zone == nil  then         zone = 255255             end       guardzonefunction(eventngr,eventnr,area)     elseif event == 'RA' then       area = tonumber(string.sub(line,3,5))       securitystatus_1 = string.sub(line,6,6)       areastatus_1 = string.sub(line,7,7)       areastatus_2 = string.sub(line,8,8)       areastatus_3 = string.sub(line,9,9)       areastatus_4 = string.sub(line,10,10)       areastatus_5 = string.sub(line,11,11)       areastatus_6 = string.sub(line,12,12)       guardareafunction(area,securitystatus_1,areastatus_1,areastatus_2,areastatus_3,areastatus_4,areastatus_5,areastatus_6  )     end     line = ''   else     line = line .. char   end  else   request = grp.getvalue('32/5/0')    --scheduled script changes object to true every minute. !!!ADD SCHEDULED SCRIPT!!!   if request then     port:write('RA001\r')                --send area1 status request command     os.sleep(0.5)     port:write('RA002\r')                --send area2 status request command     grp.update('32/5/0', false)   end   house_arm_disarm = grp.getvalue(control_house_security_ga)                        --1-Arm; 2-Force arm; 3-Stay arm; 4-Instant arm; 5-Disarm   if house_arm_disarm == 1 then     port:write('AA001A'..security_code..'\r')     grp.update(control_house_security_ga, 0)   elseif house_arm_disarm == 2 then     port:write('AA001F'..security_code..'\r')     grp.update(control_house_security_ga, 0)   elseif house_arm_disarm == 3 then     port:write('AA001S'..security_code..'\r')     grp.update(control_house_security_ga, 0)   elseif house_arm_disarm == 4 then     port:write('AA001I'..security_code..'\r')     grp.update(control_house_security_ga, 0)   elseif house_arm_disarm == 5 then     port:write('AD001'..security_code..'\r')     grp.update(control_house_security_ga, 0)   end     woodstorage_arm_disarm = grp.getvalue(control_woodstorage_security_ga)    --1-Arm; 2-Force arm; 3-Stay arm; 4-Instant arm; 5-Disarm   if woodstorage_arm_disarm == 1 then     port:write('AA002A'..security_code..'\r')     grp.update(control_woodstorage_security_ga, 0)   elseif woodstorage_arm_disarm == 2 then     port:write('AA002F'..security_code..'\r')     grp.update(control_woodstorage_security_ga, 0)   elseif woodstorage_arm_disarm == 3 then     port:write('AA002S'..security_code..'\r')     grp.update(control_woodstorage_security_ga, 0)   elseif woodstorage_arm_disarm == 4 then     port:write('AA002I'..security_code..'\r')     grp.update(control_woodstorage_security_ga, 0)   elseif woodstorage_arm_disarm == 5 then     port:write('AD002'..security_code..'\r')     grp.update(control_woodstorage_security_ga, 0)   end end

User library:

Script name: guardAreaStatus
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
function guardareafunction(areanumber, areastatus, areastatus1, areastatus2, areastatus3, areastatus4, areastatus5, areastatus6 ) --what must be process RA001DOONOOO; RA - Request area; 001 - Area number; D - Disarmed/Armed/Force armed/Stay armed/Instant armed; O - Zone in memory/Ok; O - Troube/Ok; N - Not ready/Ok; O - In programming/Ok; O - In alarm/Ok; O - Strobe/Ok   house_area_status_ga = '10/0/0'   woodstorage_area_status_ga = '10/0/1'     house_area_trouble_ga = '10/3/0'   woodstorage_area_trouble_ga = '10/3/1'     house_area_not_ready_ga = '10/3/2'   woodstorage_area_not_ready = '10/3/3'     house_area_alarm_ga    = '10/2/0'   woodstorage_area_alarm_ga = '10/2/1'     if areastatus == 'D' then     if areanumber == 1 then       grp.write(house_area_status_ga, 0)     elseif areanumber == 2 then       grp.write(woodstorage_area_status_ga, 0)     end   elseif areastatus == 'A' then     if areanumber == 1 then         grp.update(house_area_status_ga, 1)     elseif areanumber == 2 then       grp.update(woodstorage_area_status_ga, 1)     end   elseif areastatus == 'F' then     if areanumber == 1 then         grp.update(house_area_status_ga, 2)     elseif areanumber == 2 then       grp.update(woodstorage_area_status_ga, 2)     end   elseif areastatus == 'S' then     if areanumber == 1 then         grp.update(house_area_status_ga, 3)     elseif areanumber == 2 then       grp.update(woodstorage_area_status_ga, 3)     end   elseif areastatus == 'I' then     if areanumber == 1 then         grp.update(house_area_status_ga, 4)     elseif areanumber == 2 then       grp.update(woodstorage_area_status_ga, 4)     end   end     if areastatus2 == 'T' then     if areanumber == 1 then       grp.update(house_area_trouble_ga, true)     elseif areanumber == 2 then       grp.update(woodstorage_area_trouble_ga, true)     end   elseif areastatus2 == 'O' then     if areanumber == 1 then       grp.update(house_area_trouble_ga, false)     elseif areanumber == 2 then       grp.update(woodstorage_area_trouble_ga, false)     end   end     if areastatus3 == 'N' then     if areanumber == 1 then       grp.update(house_area_not_ready_ga, true)     elseif areanumber == 2 then       grp.update(woodstorage_area_not_ready, true)     end   elseif areastatus3 == 'O' then     if areanumber == 1 then       grp.update(house_area_not_ready_ga, false)     elseif areanumber == 2 then       grp.update(woodstorage_area_not_ready, false)     end   end     if areastatus5 == 'A' then     if areanumber == 1 then       grp.update(house_area_alarm_ga, true)     elseif areanumber == 2 then       grp.update(woodstorage_area_alarm_ga, true)     end   elseif areastatus5 == 'O' then     if areanumber == 1 then       grp.update(house_area_alarm_ga, false)     elseif areanumber == 2 then       grp.update(woodstorage_area_alarm_ga, false)     end   end   end
Script name: guardZoneStatus

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
function guardzonefunction( eventgroup,eventnumber,areanumber)   guardZones = {   [255255] = 'An empty zone has arrived',   [01] = 'Tehnoruum PIR.',    [02] = '1k Trepihall PIR.',   [03] = 'Kontor PIR.',   [04] = 'Esik PIR.',   [05] = 'Elutuba PIR.',   [06] = 'Magamistuba PIR.',   [07] = 'Garderoob PIR.',   [08] = 'Kuur PIR.',   [09] = 'Mona PIR ',   [10] = 'Cara PIR  ',   [11] = '2k Trepihall PIR ',   [12] = 'Tehnoruumi Suits ',      [13] = '1 Trepihall Suit ',   [14] = 'Kontori Suits ',   [15] = 'Esiku Suits ',   [16] = 'Elutoa Suits ',   [17] = 'Magamistoa Suits ',   [18] = 'Garderoob Suits',   [19] = 'Mona Suits',   [20] = 'Cara Suits',   [21] = '2 Trepihall Suit',   [22] = '2k Elutoa Suits',   [23] = 'Kuuri Uks',   [24] = 'Kontori Aken',   [25] = 'Peauks',   [26] = 'Köögi Aken.',   [27] = 'Terrassi Uks',   [28] = '1k Vannitoa Uks',   [29] = '1k Vannitoa Aken',   [30] = 'Magamistoa Aken',   [31] = 'Kuuri Aken',   [32] = 'Mona 1 Aken',   [33] = 'Cara 1 Aken',   [34] = '2k Vannitoa Aken',   [35] = '2k Elutuba M',   [36] = 'Mona 2 Aken',   [37] = 'Cara 2 Aken',   [38] = 'Valvekilp', }   house_area_status_ga = '10/0/0'   woodstorage_area_status_ga = '10/0/1'     house_area_alarm_ga    = '10/2/0'   woodstorage_area_alarm_ga = '10/2/1'     house_area_exit_delay_ga = '10/0/2'   house_area_entry_delay_ga = '10/0/3'     woodstorage_area_exit_delay_ga = '10/0/4'   woodstorage_area_entry_delay_ga = '10/0/5'   if eventgroup == 0 or eventgroup == 1 then     if eventgroup == 0 then       grp.update('10/4/'..eventnumber, false)     elseif eventgroup == 1 then       grp.update('10/4/'..eventnumber, true)     end   elseif eventgroup == 13 then     if areanumber == 1 then       grp.update(house_area_status_ga, 0)     elseif areanumber == 2 then       grp.update(woodstorage_area_status_ga, 0)     end   elseif eventgroup == 64 then     if eventnumber == 0 then       if areanumber == 1 then         grp.update(house_area_status_ga, 1)       elseif areanumber == 2 then         grp.update(woodstorage_area_status_ga, 1)       end     elseif eventnumber == 1 then       if areanumber == 1 then         grp.update(house_area_status_ga, 2)       elseif areanumber == 2 then         grp.update(woodstorage_area_status_ga, 2)       end     elseif eventnumber == 2 then       if areanumber == 1 then         grp.update(house_area_status_ga, 3)       elseif areanumber == 2 then         grp.update(woodstorage_area_status_ga, 3)       end     elseif eventnumber == 3 then       if areanumber == 1 then         grp.update(house_area_status_ga, 4)       elseif areanumber == 2 then         grp.update(woodstorage_area_status_ga, 4)       end     elseif eventnumber == 4 or eventnumber == 5 or eventnumber == 6 or eventnumber == 7 then       if areanumber == 1 then         grp.update(house_area_alarm_ga, true)       elseif areanumber == 2 then         grp.update(woodstorage_area_alarm_ga, true)       end     end   elseif eventgroup == 65 then     if eventnumber == 1 then       if areanumber == 1 then         grp.update(house_area_exit_delay_ga, true)       elseif areanumber == 2 then         grp.update(woodstorage_area_exit_delay_ga, true)       end     elseif eventnumber == 2 then       if areanumber == 1 then         grp.update(house_area_entry_delay_ga, true)       elseif areanumber == 2 then         grp.update(woodstorage_area_entry_delay_ga, true)       end     elseif eventnumber == 0 then       if areanumber == 1 then         grp.update(house_area_entry_delay_ga, false)         grp.update(house_area_exit_delay_ga, false)       elseif areanumber == 2 then         grp.update(woodstorage_area_entry_delay_ga, false)         grp.update(woodstorage_area_exit_delay_ga, false)       end     end   end end
Resident script for communication check (EVO192 Communication check, sleep interval 10s):

Code:
1234567891011121314
last_timestamp = grp.find("10/0/0").updatetime --Area1 status (status is polled every minute from security system) communication_error = grp.getvalue('10/3/4') now = os.microtime() if (now - last_timestamp) >= 120 then --if object hasn't updated on last 120s then generate communication error   if communication_error == false then     grp.update('10/3/4', true)   end else   if grp.getvalue('10/3/4')==true then     grp.update('10/3/4', false)   end end

Here is UI:
       
Reply
#3
Another update to get integration done about 1 minute.

Now my script reads out all arealabels and zone labels (You don't need to know anything about EVO program). Also creates automatically group objects. I tested it couple days ago in my new project and really, integration takes about 1-2 minutes.  Cool
What you probably need to do is edit zone labels to more understandable form (paradox allows enter only 16 characters for area and zone name).

Program needs one main group address range (example 10/x/x)

Group address structure is like this:
Code:
12345678910111213141516171819202122232425262728293031323334353637383940
security_main_ga = '10/' --'3-level' = main/middle/sub. Make sure that 10/0/0 - 10/7/X group addresses are not used. System creates objects automatically. 10/0/1 - Area 1 security status [0-DISARMED, 1-ARMED, 2-FORCE ARMED, 3-STAY ARMED, 4-INSTANT ARMED] ... 10/0/8 - Area 8 security status 10/0/11 - Area 1 exit delay     ... 10/0/18 - Area 8 exit delay 10/0/21 - Area 1 entry delay ... 10/0/28 - Area 8 entry delay 10/0/31 - Area 1 alarm status ... 10/0/38 - Area 8 alarm status 10/0/41 - Area 1 trouble ... 10/0/48 - Area 8 trouble 10/0/51 - Area 1 not ready ... 10/0/58 - Area 8 not ready 10/1/1 - Area 1 control        [1-ARM, 2-FORCE ARM, 3-STAY ARM, 4-INSTANT ARM, 5-DISARM] ... 10/1/8 - Area 8 control 10/2/1 - Zone 1 status ... 10/2/xxx - Zone xxx status

All what you need to change is in resident script (group addresses).

Resident script (EVO192 communication, sleep interval 0):
Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
require('user.guardZoneStatus') require('user.guardAreaStatus') require('user.guardAreaLabels') require('user.guardZoneLabels') command_enum = {   [1] = 'A',    [2] = 'F',   [3] = 'S',   [4] = 'I', } if not port then   require('serial')   port = serial.open('/dev/RS232', { baudrate = 9600, parity = 'none', databits = '8', stopbits = '1'})   port:flush()   line = '' end security_main_ga = '10/'           --'3-level' = main/middle/sub. Make sure that 10/0/0 - 10/7/X group addresses are not used. System creates objects automatically. security_code = '1234' request_area_status_ga = '32/5/0'  --Create scheduled script for this one. Write true every minute. request_zone_labels_ga = '32/5/3'  --You need to change this to true only one time or if security zones are changed.                                    --This also activates group address generation.                                    --Make sure that zone label is not "Zone 001, Zone 002 etc because these zone names gonna be ignored. request_area_labels_ga = '32/5/4'  --You need to change this to true only one time or if security areas are changed.                                    --This also activates group address generation.                                    --Make sure that area label is not "Area 001, Area 002 etc because these area names gonna be ignored. request_zone_name_count = 50       --how many zones will be scanned to get zone labels. active_areas = 1                   --How many areas are polled periodically. Starts on first area. char = port:read(1, 1) --log(char) if char then   if char == '\r' then     line = line:trim()     log(line)         event = string.sub(line,1,2)    -- log(event)     if event == 'G0' then       eventnr = tonumber(string.sub(line,6,-5))             area = tonumber(string.sub(line,10,-1))       eventngr = tonumber(string.sub(line,2,4))       guardzonefunction(eventngr,eventnr,area,security_main_ga)     elseif event == 'RA' then       area = tonumber(string.sub(line,3,5))       securitystatus_1 = string.sub(line,6,6)       areastatus_1 = string.sub(line,7,7)       areastatus_2 = string.sub(line,8,8)       areastatus_3 = string.sub(line,9,9)       areastatus_4 = string.sub(line,10,10)       areastatus_5 = string.sub(line,11,11)       areastatus_6 = string.sub(line,12,12)       guardareafunction(area,securitystatus_1,areastatus_1,areastatus_2,areastatus_3,areastatus_4,areastatus_5,areastatus_6,security_main_ga  )     elseif event == 'AL' then       area = tonumber(string.sub(line,3,5))       name = string.sub(line,6,16)       guardarealabelfunction(area, name,security_main_ga)     elseif event == 'ZL' then       zone = tonumber(string.sub(line,3,5))       name = string.sub(line,6,16)       guardzonelabelfunction(zone, name,security_main_ga)     end     line = ''   else     line = line .. char   end  else   request = grp.getvalue(request_area_status_ga)    --scheduled script changes object to true every minute   if request then     for i = 1, active_areas, 1 do             port:write('RA00'.. i .. '\r')                --send area1 status request command         os.sleep(0.2)       if i==active_areas then             grp.update(request_area_status_ga, false)       end     end   end     request_area_names = grp.getvalue(request_area_labels_ga)   if request_area_names then     for i = 1, 8, 1 do         port:write('AL00'..tostring(i)..'\r')         os.sleep(0.2)     end       grp.update(request_area_labels_ga, false)   end     request_zone_names = grp.getvalue(request_zone_labels_ga)   if request_zone_names then     for i = 1, request_zone_name_count, 1 do       if i<10 then           port:write('ZL00'..tostring(i)..'\r')           os.sleep(0.2)       else         port:write('ZL0'..tostring(i)..'\r')           os.sleep(0.2)       end     end   grp.update(request_zone_labels_ga, false)   end   for i = 1, active_areas, 1 do     exist = grp.alias(security_main_ga .. '1/' .. i)       if exist ~= nil then       AreaControl = grp.getvalue(security_main_ga .. '1/' .. i)     --1-Arm; 2-Force arm; 3-Stay arm; 4-Instant arm; 5-Disarm       if AreaControl ~=0 then         if AreaControl ~= 5 then           port:write('AA00' .. i .. command_enum[AreaControl] .. security_code ..'\r')           grp.update(security_main_ga .. '1/' .. i, 0)         else           port:write('AD00' .. i .. security_code ..'\r')           grp.update(security_main_ga .. '1/' .. i, 0)           end           end     end     end end

User library (guardAreaLabels):
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
function guardarealabelfunction(areanumber, areaname, security_main_ga)      if areaname ~= ('Area ' .. tonumber(areanumber)) then     for i = 1, 7, 1 do       if i==1 then         exist = grp.alias(security_main_ga .. '0/' .. tonumber(areanumber))         if exist == nil then           address = grp.create({             datatype = dt.uint8,             address = security_main_ga .. '0/' .. tonumber(areanumber),               name = areaname .. ' security status',             comment = 'Automatically created object - Security Area '.. tonumber(areanumber),             units = '',             tags = { },           })         end       elseif i==2 then         exist = grp.alias(security_main_ga .. '0/' .. tonumber(areanumber)+10)         if exist == nil then           address = grp.create({             datatype = dt.bool,             address = security_main_ga .. '0/' .. tonumber(areanumber)+10,               name = areaname .. ' exit delay',               comment = 'Automatically created object - Security Area '.. tonumber(areanumber) .. ' exit delay',             units = '',             tags = { },           })         end       elseif i==3 then         exist = grp.alias(security_main_ga .. '0/' .. tonumber(areanumber)+20)         if exist == nil then           address = grp.create({             datatype = dt.bool,             address = security_main_ga .. '0/' .. tonumber(areanumber)+20,               name = areaname .. ' entry delay',               comment = 'Automatically created object - Security Area '.. tonumber(areanumber) .. ' entry delay',             units = '',             tags = { },           })         end       elseif i==4 then         exist = grp.alias(security_main_ga .. '0/' .. tonumber(areanumber)+30)         if exist == nil then           address = grp.create({             datatype = dt.bool,             address = security_main_ga .. '0/' .. tonumber(areanumber)+30,               name = areaname .. ' alarm status',               comment = 'Automatically created object - Security Area '.. tonumber(areanumber) .. ' alarm status',             units = '',             tags = { },           })         end       elseif i==5 then         exist = grp.alias(security_main_ga .. '0/' .. tonumber(areanumber)+40)         if exist == nil then           address = grp.create({             datatype = dt.bool,             address = security_main_ga .. '0/' .. tonumber(areanumber)+40,               name = areaname .. ' trouble',               comment = 'Automatically created object - Security Area '.. tonumber(areanumber) .. ' trouble',             units = '',             tags = { },           })         end       elseif i==6 then         exist = grp.alias(security_main_ga .. '0/' .. tonumber(areanumber)+50)         if exist == nil then           address = grp.create({             datatype = dt.bool,             address = security_main_ga .. '0/' .. tonumber(areanumber)+50,               name = areaname .. ' not ready',               comment = 'Automatically created object - Security Area '.. tonumber(areanumber) .. ' not ready',             units = '',             tags = { },           })         end       elseif i==7 then         exist = grp.alias(security_main_ga .. '1/' .. tonumber(areanumber))         if exist == nil then           address = grp.create({             datatype = dt.uint8,             address = security_main_ga .. '1/' .. tonumber(areanumber),               name = 'Control ' .. areaname,               comment = 'Automatically created object - Control Security Area '.. tonumber(areanumber),             units = '',             tags = { },           })         end       end     end   end end

User library (guardAreaStatus):
Code:
1234567891011121314151617181920212223242526272829303132
function guardareafunction(areanumber, areastatus, areastatus1, areastatus2, areastatus3, areastatus4, areastatus5, areastatus6, security_main_ga ) --what must be process RA001DOONOOO; RA - Request area; 001 - Area number; D - Disarmed/Armed/Force armed/Stay armed/Instant armed; O - Zone in memory/Ok; O - Troube/Ok; N - Not ready/Ok; O - In programming/Ok; O - In alarm/Ok; O - Strobe/Ok     if areastatus == 'D' then     grp.write(security_main_ga .. '0/' .. areanumber , 0)   elseif areastatus == 'A' then     grp.update(security_main_ga .. '0/' .. areanumber , 1)   elseif areastatus == 'F' then     grp.update(security_main_ga .. '0/' .. areanumber , 2)   elseif areastatus == 'S' then     grp.update(security_main_ga .. '0/' .. areanumber , 3)   elseif areastatus == 'I' then     grp.update(security_main_ga .. '0/' .. areanumber , 4)   end     if areastatus2 == 'T' then     grp.update(security_main_ga .. '0/' .. areanumber+40 , true)   elseif areastatus2 == 'O' then     grp.update(security_main_ga .. '0/' .. areanumber+40 , false)   end     if areastatus3 == 'N' then     grp.update(security_main_ga .. '0/' .. areanumber+50 , true)   elseif areastatus3 == 'O' then     grp.update(security_main_ga .. '0/' .. areanumber+50 , false)   end     if areastatus5 == 'A' then     grp.update(security_main_ga .. '0/' .. areanumber+30 , true)   elseif areastatus5 == 'O' then     grp.update(security_main_ga .. '0/' .. areanumber+30 , false)   end end

User library (guardZoneLabels):
Code:
12345678910111213141516171819202122232425262728293031323334353637383940
function guardzonelabelfunction(zonenumber, zonename, security_main_ga)     exist = grp.alias(security_main_ga .. '2/'.. tonumber(zonenumber))   if exist == nil then     if zonenumber<10 then       if zonename ~= ('Zone 00' .. tonumber(zonenumber)) then         address = grp.create({           datatype = dt.bool,           address = security_main_ga .. '2/'.. tonumber(zonenumber),           name = zonename,             comment = 'Automatically created object - Zone '.. tonumber(zonenumber),           units = '',           tags = { },         })       end     elseif zonenumber>=10 and zonenumber<100 then       if zonename ~= ('Zone 0' .. tonumber(zonenumber)) then         address = grp.create({           datatype = dt.bool,           address = security_main_ga .. '2/'.. tonumber(zonenumber),           name = zonename,             comment = 'Automatically created object - Zone '.. tonumber(zonenumber),           units = '',           tags = { },         })       end     elseif zonenumber>=100 then       if zonename ~= ('Zone ' .. tonumber(zonenumber)) then         address = grp.create({           datatype = dt.bool,           address = security_main_ga .. '2/'.. tonumber(zonenumber),           name = zonename,             comment = 'Automatically created object - Zone '.. tonumber(zonenumber),           units = '',           tags = { },         })       end     end   end end

User library (guardZoneStatus):
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
function guardzonefunction( eventgroup,eventnumber,areanumber,security_main_ga)   if eventgroup == 0 or eventgroup == 1 then     if eventgroup == 0 then       grp.update(security_main_ga .. '2/'..eventnumber, false)     elseif eventgroup == 1 then       grp.update(security_main_ga .. '2/'..eventnumber, true)     end   elseif eventgroup == 5 then -- disarm     grp.update(security_main_ga .. '0/' .. areanumber , 0)     grp.update(security_main_ga .. '0/' .. areanumber+10,false)         --reset exit delay     grp.update(security_main_ga .. '0/' .. areanumber+20 , false)        --reset entry delay   elseif eventgroup == 13 then -- disarm     grp.update(security_main_ga .. '0/' .. areanumber , 0)     grp.update(security_main_ga .. '0/' .. areanumber+10,false)         --reset exit delay     grp.update(security_main_ga .. '0/' .. areanumber+20 , false)        --reset entry delay   elseif eventgroup == 64 then --     if eventnumber == 0 then         grp.write(security_main_ga .. '0/' .. areanumber , 1)       grp.update(security_main_ga .. '0/' .. areanumber+10,false)         --reset exit delay         grp.update(security_main_ga .. '0/' .. areanumber+20 , false)        --reset entry delay     elseif eventnumber == 1 then       grp.write(security_main_ga .. '0/' .. areanumber , 2)       grp.update(security_main_ga .. '0/' .. areanumber+10,false)         --reset exit delay         grp.update(security_main_ga .. '0/' .. areanumber+20 , false)        --reset entry delay     elseif eventnumber == 2 then       grp.write(security_main_ga .. '0/' .. areanumber , 3)       grp.update(security_main_ga .. '0/' .. areanumber+10,false)         --reset exit delay         grp.update(security_main_ga .. '0/' .. areanumber+20 , false)        --reset entry delay     elseif eventnumber == 3 then      grp.write(security_main_ga .. '0/' .. areanumber , 4)       grp.update(security_main_ga .. '0/' .. areanumber+10,false)         --reset exit delay         grp.update(security_main_ga .. '0/' .. areanumber+20 , false)        --reset entry delay     elseif eventnumber == 4 or eventnumber == 5 or eventnumber == 6 or eventnumber == 7 then       grp.update(security_main_ga .. '0/' .. areanumber+30 , true)     end   elseif eventgroup == 65 then     if eventnumber == 1 then       grp.update(security_main_ga .. '0/' .. areanumber+10 , true)     elseif eventnumber == 2 then       grp.update(security_main_ga .. '0/' .. areanumber+20 , true)     elseif eventnumber == 0 then       grp.update(security_main_ga .. '0/' .. areanumber+10 , false)       grp.update(security_main_ga .. '0/' .. areanumber+20 , false)     end   end end

After you request area and zone names, give it some time to scan and create group objects. Mine needed about 15-20 seconds (1 area, 50 zones)...

All objects what are created automatically they have also object comment "Automatically created object - Security Area X", "Automatically created object - Zone XX" etc..
Reply
#4
Hi, thank you for this script! I'm investigating the best possible way to integrate a security system with KNX in my next project. Satel has INT-KNX-2, which is great, but it has certain limitations (e.g. only 64 addresses). There are some pricey 3rd party modules for DSC. And there is Paradox with PRT3 and pricey 3rd party modules again, or using Logic Machine alternatively. The last option I like the most, because I'll probably put a Logic Machine into the project anyways.

Two questions:
1. Does this script work with the newer Paradox serial module? PRT3 is now discontinued and replaced.
2. Are zone changes reported imidiately? For example if a motion sensor detects motion, is this reported on the same second?
Reply
#5
(01.12.2020, 21:05)mishoboss Wrote: Hi, thank you for this script! I'm investigating the best possible way to integrate a security system with KNX in my next project. Satel has INT-KNX-2, which is great, but it has certain limitations (e.g. only 64 addresses). There are some pricey 3rd party modules for DSC. And there is Paradox with PRT3 and pricey 3rd party modules again, or using Logic Machine alternatively. The last option I like the most, because I'll probably put a Logic Machine into the project anyways.

Two questions:
1. Does this script work with the newer Paradox serial module? PRT3 is now discontinued and replaced.
2. Are zone changes reported imidiately? For example if a motion sensor detects motion, is this reported on the same second?

Hi!

I definitelly should choose LM to integrate security system. You have no limits when using LM. Can program whatever you want. 

Answers:
1. I havent tested it but if all commands are the same then it will work.
2. Yes, this is realtime info. In one project I am using movement from security as triger and switch lights when brightness is below setpoint.
Reply
#6
Hi, is there a way to control Paradox PGMs (outputs)?
Reply
#7
(26.06.2021, 05:27)mishoboss Wrote: Hi, is there a way to control Paradox PGMs (outputs)?

I didn't find any straight solution because there is no command to control PGM output directly. PGM output is meant to control via some statements inside paradox.

But, this solution should work (haven't tested it by myself) but paradox uses this solution with RF remotes.
You can try to use utility key and create this kind of configuration (picture 1 attached). I think there is possible to create similar configuration in BabyWare also.

In LM add this code in residential script to test it out:

Code:
123456789101112131415
  utility_key1_grp_addr = 'x/x/x' -- turn PGM on group address   utility_key2_grp_addr = 'x/x/x' -- turn PGM off group address   utility_key1 = grp.getvalue(utility_key1_grp_addr) -- PGM on   utility_key2 = grp.getvalue(utility_key2_grp_addr) -- PGM off     if utility_key1==true or utility_key1==1 then      port:write('UK001\r')      grp.update(utility_key1_grp_addr, false)      os.sleep(0.2)   elseif utility_key2==true or utility_key2==1 then      port:write('UK002\r')      grp.update(utility_key2_grp_addr, false)      os.sleep(0.2)   end

enable log(event) in residential script to see if command is accepted.

Unfortunately there is no request/status command to see what is PGM state.

Hope this helps.

Attached Files Thumbnail(s)
   
Reply
#8
Hello. Everything is perfect but I see that the connection is through RS-232 port. My initial question is if there is some possibility to manage a alarm central through http connection. This kind of central usually include web server.
Thank you.
Reply
#9
Hi!

Thanks for your work, @fleeceable! If I can make this work it would save me a lot of work Smile

For now I'm receiving only nill and a <?> character as you can see in the attachment.

I think the problem may be in the PTR3 options. Can you please give me some pointers how to solve this?


BR,
André Neves

Attached Files Thumbnail(s)
       
Reply
#10
Check the baudrate settings. All examples here use 9600, but your device is set to 19200.
Reply
#11
(22.02.2022, 12:09)admin Wrote: Check the baudrate settings. All examples here use 9600, but your device is set to 19200.

Hi,

It is at 9600. I just made the print after a test at 19200.
Reply
#12
ASCII protocol should only contain printable characters. Since you are getting <?> (unprintable character) it means that there's something wrong on the communication level.
Reply
#13
You can also try to switch Tx and Rx cables on logic side.
Another way to test that your PRT3 module (and paradox program) works is to use RS232 to USB converter and connect PRT3 to computer. Then use Docklight (https://docklight.de/) program. If all settings are correct you should see some data on Docklight terminal...

I have used that Logic library on 4 sites and all works great.
Reply
#14
(11.03.2022, 11:51)fleeceable Wrote: You can also try to switch Tx and Rx cables on logic side.
Another way to test that your PRT3 module (and paradox program) works is to use RS232 to USB converter and connect PRT3 to computer. Then use Docklight (https://docklight.de/) program. If all settings are correct you should see some data on Docklight terminal...

I have used that Logic library on 4 sites and all works great.

Problem solved!

It was a bad wire connection inside the DB9 connector. The gnd wire was disconected.

This library is great and helped a lot. THanks.
Reply
#15
(18.07.2020, 14:37)fleeceable Wrote: ..

Nice work! Thanks... 
Unfortunatelly PRP3 ASCII Protocol missing a way to bypass zones Sad
Reply
#16
It is hard to understand why Paradox did not include Bypass function on the PRT3.
They have it with the IP module... Everyone should send an update request to Paradox to have it added to the PRT3. It takes numbers to get results.
Reply
#17
Hi! Right now the D (disarmed) status is mapped to number 0 and the disarm control is mapped to number 5. I need disarm control and status to be mapped to the same number, for example 5. So I thought it would be easy to remap those here:

if areastatus == 'D' then
grp.update(security_main_ga .. '0/' .. areanumber , 5)
elseif areastatus == 'A' then
grp.update(security_main_ga .. '0/' .. areanumber , 1)
elseif areastatus == 'F' then
grp.update(security_main_ga .. '0/' .. areanumber , 2)
elseif areastatus == 'S' then
grp.update(security_main_ga .. '0/' .. areanumber , 3)
elseif areastatus == 'I' then
grp.update(security_main_ga .. '0/' .. areanumber , 4)
end

And added the fifth option here:


command_enum = {
[1] = 'A',
[2] = 'F',
[3] = 'S',
[4] = 'I',
[5] = 'D',
}

However DISARMED status is still reported as 0 instead of 5 right after disarming, or it's even not reported at all in some cases. I've scheduled a script to call request_area_status_ga = true every minute and this one successfully updates it to 5. So it works, just not right after DISARMING for some reason. All other controls successfully update the status, it's just the disarm one that is the issue. What I'm missing here?
Reply
#18
Are you overriding existing object or did you create virtual status?
------------------------------
Ctrl+F5
Reply
#19
(22.04.2024, 08:47)mishoboss Wrote: Hi! Right now the D (disarmed) status is mapped to number 0 and the disarm control is mapped to number 5. I need disarm control and status to be mapped to the same number, for example 5. So I thought it would be easy to remap those here:

if areastatus == 'D' then
    grp.update(security_main_ga .. '0/' .. areanumber , 5)
  elseif areastatus == 'A' then
    grp.update(security_main_ga .. '0/' .. areanumber , 1)
  elseif areastatus == 'F' then
    grp.update(security_main_ga .. '0/' .. areanumber , 2)
  elseif areastatus == 'S' then
    grp.update(security_main_ga .. '0/' .. areanumber , 3)
  elseif areastatus == 'I' then
    grp.update(security_main_ga .. '0/' .. areanumber , 4)
  end

And added the fifth option here:


command_enum = {
  [1] = 'A', 
  [2] = 'F',
  [3] = 'S',
  [4] = 'I',
  [5] = 'D',
}

However DISARMED status is still reported as 0 instead of 5 right after disarming, or it's even not reported at all in some cases. I've scheduled a script to call request_area_status_ga = true every minute and this one successfully updates it to 5. So it works, just not right after DISARMING for some reason. All other controls successfully update the status, it's just the disarm one that is the issue. What I'm missing here?

You need to change this to get 5 for disarm:

user.guardZoneStatus
Code:
12345678
  elseif eventgroup == 5 then -- user code entered on keypad     grp.update(security_main_ga .. '0/' .. areanumber , 0) ------<<<<<CHANGE THIS TO 5     grp.update(security_main_ga .. '0/' .. areanumber+10,false)         --reset exit delay     grp.update(security_main_ga .. '0/' .. areanumber+20 , false)        --reset entry delay   elseif eventgroup == 13 or  eventgroup == 14  then -- disarm with master or user code     grp.update(security_main_ga .. '0/' .. areanumber , 0) ------<<<<<CHANGE THIS TO 5     grp.update(security_main_ga .. '0/' .. areanumber+10,false)         --reset exit delay     grp.update(security_main_ga .. '0/' .. areanumber+20 , false)        --reset entry delay

Also you don't need to change  "command_enum" because that is used only to send right arming command (usual arm, force arm, stay arm etc). If AreaControl variable is 5 then it gonna disarm on either way. Check residential script line 104.
Reply
#20
Hi,

Does anyone have tried to use Virtual Inputs from the PRT3 module?

I have configured and enabled the Virtual Input 1 of the PRT3 though BabyWare.

The main goal is to use a sensor that is connected to a KNX system and write the state to a Virtual Input on the EVO192 Paradox side.

I send this command to Open the Virtual Input 1
port:write('VO001\r')

I send this command to Close the Virtual Input 1
port:write('VC001\r')

But in the BabyWare I can't see the Zone that I have configured with the Virtual Input 1 Opening, it's always Closed.

I don't know if I am doing some bad configuration on the PRT3 in the BabyWare.

I have read the manual configuration of the PRT3 and I think that I am sending the right command.
Reply


Forum Jump: