LogicMachine Forum
ELK M1 Alarm panel - Printable Version

+- LogicMachine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: ELK M1 Alarm panel (/showthread.php?tid=931)



ELK M1 Alarm panel - rocfusion - 07.08.2017

Hi,

Has anyone created a script for the ELK M1 security panel?

Admin is there any example for a non blocking SSL connection?

Is there an example of, 2 ASCII characters, 2-digit checksum. This is the hexadecimal two’s complement of the modulo-256 sum of the ASCII values of all characters in the message excluding the checksum itself and the CR-LF terminator at the end of the message. Permissible characters are ASCII 0-9 and upper case A-F. When all the characters are added to the Checksum, the value should equal 0.

Thanks,


Roger


RE: ELK M1 Alarm panel - admin - 08.08.2017

Here's a basic SSL connection example:
Code:
socket = require('socket') ssl = require('ssl') ip = '192.168.1.1' port = 2601 sock = socket.tcp() sock:settimeout(5) sock:connect(ip, port) sock = ssl.wrap(sock, 'tlsv1') sock:dohandshake()

Checksum calculation:
Code:
function checksum(str)   local sum = 0   for i = 1, #str do     sum = (sum + str:byte(i)) % 256   end   return string.format('%02X', 256 - sum) end



RE: ELK M1 Alarm panel - rocfusion - 12.08.2017

Hi Admin,

Thank you,  the checksum function works.  I am trying to do the reverse and verify the message received has a valid checksum



Code:
function checksum(str)  local sum = 0  for i = 1, #str do    sum = (sum + string.byte(str,i)) % 256  end  x = 256-sum  return string.format('%02X', 256 - sum) end function reversechk(str, cksum)  local sum = tonumber(cksum,16)  log(sum)  for i=1, #str do    sum= (sum + string.byte(str,i))  end  return string.format('%02X', sum) end local message= '16XK403923611081711000' local chksum = checksum(message) log(chksum) -- chksum is 67 -- so the total message is '16XK40392361108171100067' local isok = reversechk(message,chksum) log(isok)


The reversechk function does not return a 0,  what am doing wrong?  I have the reverse calculation in C code,  maybe you can understand what they doing?

Code:
Calculate checksum on received and transmitted ASCII string Example C code program //INT8U is an 8 bit unsigned integer. INT8U itAscRecBuf[82]; //ASCII receive character buffer INT8U AscHexToBin(INT8U, INT8U *); //ASCII hex to binary conversion INT8U AsciiToHex( INT8U); //Ascii to Hex conversion //Calculate checksum on a received ASCII string, return checksum value. //It should equal 0 if good. INT8U CalcCheckSum(void) {     INT8U i,length, cc;     length = AscHexToBin(2, &itAscRecBuf[0]);     //get length value, first two characters          cc = AscHexToBin(2, &itAscRecBuf[length]); //get checksum value at end of string.     for (i=0;i<length ;i++ )         {             cc += itAscRecBuf[i]; //get string value and add it to checksum         }         return(cc);         //good checksum should equal 0 }     //ascii hex to binary, width 1 or 2     INT8U AscHexToBin(INT8U Width, INT8U * DataPtr) //         {             INT8U aVal; // accumulated value             aVal = AsciiToHex(*DataPtr);             DataPtr++;             if (Width == 2)    //two digits wide, else 1 digit wide                 {                     aVal = aVal << 4;                     aVal += AsciiToHex(*DataPtr);                 }             return(aVal);          }     //Ascii to Hex conversion     INT8U AsciiToHex( INT8U Value )         {             switch ( Value )                 {                     case 'A': return( 10 );                     case 'B': return( 11 );                     case 'C': return( 12 );                     case 'D': return( 13 );                     case 'E': return( 14 );                     case 'F': return( 15 );                     default: return( Value - 0x30 );                 }         }


Thanks,

Roger


RE: ELK M1 Alarm panel - admin - 14.08.2017

You don't need a separate function for this, last 2 bytes of the message is the resulting checksum. You can do it like this:
Code:
message = '16XK40392361108171100067' calccs = checksum(message:sub(1, -3)) -- calculated checksum from message data recvcs = message:sub(-2, -1) -- received checksum log(calccs, recvcs)



RE: ELK M1 Alarm panel - rocfusion - 14.08.2017

Hi Admin,

Thank you, I am trying to get the connection working with ssl,  but the connection gets closed.  I want to use copas since this gives more flexibility of building a non-blocking solution.  I have the option also to run code in separate threads. 

Code:
if not ready then  socket = require("socket")  copas = require("copas")  require('ssl')  ready=true  esys = {}    function checksum(str)    local sum = 0    for i = 1, #str do      sum = (sum + string.byte(str,i)) % 256    end    x = 256-sum    return string.format('%02X', 256 - sum)  end    function validchecksum(str)    calccs = checksum(str:sub(1, -3))    -- calculated checksum from message data    recvcs = str:sub(-2, -1)        -- received checksum    return calccs == recvcs        -- when they the same return true  end    --helper functions to round and increment values    function increment(n)    n = n + 1    return n  end    function parse(data)    alert('elk parsing: %s', data)    if(validchecksum(data)==true)then      local response = string.sub(data,3,-5)      alert('elk message is: %s',response)    end  end    function sendElk(command)    skt:send(command)    sleep(1)      end      function init()    alert('running init')  end    function fromKNX(command)    local telegram = string.split(command,',')    alert('from knx %s',command)  end    local server = socket.udp()  server:setsockname("127.0.0.1",33456)  function handler(skts)    skts = copas.wrap(skts)    alert("UDP connection handler")    while true do      local s, err      alert("UDP receiving..")      s, erro = skts:receive(2048)      if not s then        alert("UDP Receive error: %s", erro)        break      end      alert("UDP Received data, bytes: %s",s)      fromKNX(s)    end  end      copas.addserver(server, handler, 1) --[[ co = copas.addthread(function()      while true do          copas.sleep(5) -- wait 5 seconds in case of other events        copas.sleep(-1) -- put the thread to sleep until wakeup is called      end    end)]]-- end if not skt then  -- create tcp client  sslparams = {  mode = "client",  protocol = "sslv3",  key = "crt/ca-key.pem",  certificate = "crt/client.pem",  cafile = "crt/ca-cert.pem",  verify = "peer",  options = {"all", "sslv3"}   }  skt = copas.wrap(socket.tcp(), sslparams)  skt, err = socket.connect('192.168.0.11', 2601)  -- when theres no error connect ok, initialize  if(not err) then    skt:settimeout(0)    -- add receive thread    copas.addthread(function()        while true do          local resp,err = copas.receive(skt)          -- if theres no connection start a new connection          if not resp then            alert("[tcp-client] Receive error: %s", err)            copas.removeserver(skt)            skt = nil            break          end          if(string.find(resp,'^16XK')==false)then -- don't process timer messages            local fd,prtd = pcall(parse,resp)            if(fd==false)then              alert("Error with parsemsg %s ",prtd)            end          end        end      end)    if skt then      alert('[tcp-client] connection ok')      init()      -- error while connecting,    else      if warningfailed then alert('[tcp-client] connection failed (conn): %s', err) end      return    end  else    alert('[tcp-client] error connecting %s',err)    return  end end copas.loop()

What am I doing wrong?

Thanks,


Roger


RE: ELK M1 Alarm panel - admin - 17.08.2017

Replace this part:
Code:
-- create tcp client sslparams = { mode = "client", protocol = "sslv3", key = "crt/ca-key.pem", certificate = "crt/client.pem", cafile = "crt/ca-cert.pem", verify = "peer", options = {"all", "sslv3"} } skt = copas.wrap(socket.tcp(), sslparams) skt, err = socket.connect('192.168.0.11', 2601)

With this:
Code:
skt = socket.tcp() skt:settimeout(5) skt:connect('192.168.0.11', 2601) skt, err = ssl.wrap(skt, 'sslv23') if not err then   skt:dohandshake()   skt = copas.wrap(skt) end



RE: ELK M1 Alarm panel - rocfusion - 17.08.2017

ok thanks, I will try and let you know.

thx

Roger


RE: ELK M1 Alarm panel - rocfusion - 19.08.2017

Hi Admin,

Ok so with a slight modification its now working, see the revised code below.  Question in terms of error handling for the connection will this be sufficient for this client script to reconnect if for whatever reason the connection is lost?

Thanks,

Roger



Code:
if not skt then  skt = socket.tcp()  skt:settimeout(5)  skt:connect('192.168.0.11', 2601)  skt, err = ssl.wrap(skt,'tlsv1')  if not err then    skt:dohandshake()    skt = copas.wrap(skt)    copas.addthread(function()        while true do          local resp,err = copas.receive(skt)          -- if theres no connection start a new connection          if not resp or err ~=nil then            alert("[elk-client] Receive error: %s", err)            copas.removeserver(skt)            skt = nil            break          end          if(string.find(resp,'^16XK')==nil)then            local fd,prtd = pcall(parse,resp)            if(fd==false)then              alert("[elk-client] Error with parsemsg %s ",prtd)            end          else            alert('[elk-client] time message: %s', resp)          end        end      end)  else                  alert("[elk-client] connection error: %s", err)    skt = nil    return  end end



RE: ELK M1 Alarm panel - rocfusion - 22.08.2017

(19.08.2017, 23:32)rocfusion Wrote: Hi Admin,

Ok so with a slight modification its now working, see the revised code below.  Question in terms of error handling for the connection will this be sufficient for this client script to reconnect if for whatever reason the connection is lost?

Thanks,

Roger



Code:
if not skt then  skt = socket.tcp()  skt:settimeout(5)  skt:connect('192.168.0.11', 2601)  skt, err = ssl.wrap(skt,'tlsv1')  if not err then    skt:dohandshake()    skt = copas.wrap(skt)    copas.addthread(function()        while true do          local resp,err = copas.receive(skt)          -- if theres no connection start a new connection          if not resp or err ~=nil then            alert("[elk-client] Receive error: %s", err)            copas.removeserver(skt)            skt = nil            break          end          if(string.find(resp,'^16XK')==nil)then            local fd,prtd = pcall(parse,resp)            if(fd==false)then              alert("[elk-client] Error with parsemsg %s ",prtd)            end          else            alert('[elk-client] time message: %s', resp)          end        end      end)  else                  alert("[elk-client] connection error: %s", err)    skt = nil    return  end end

Hi Admin,  is this ok?
Thx
Roger


RE: ELK M1 Alarm panel - admin - 22.08.2017

Yes, looks fine