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.

ELK M1 Alarm panel
#1
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
Reply
#2
Here's a basic SSL connection example:
Code:
1234567891011
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:
1234567
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
Reply
#3
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:
12345678910111213141516171819202122232425
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:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
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
Reply
#4
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:
1234
message = '16XK40392361108171100067' calccs = checksum(message:sub(1, -3)) -- calculated checksum from message data recvcs = message:sub(-2, -1) -- received checksum log(calccs, recvcs)
Reply
#5
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:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
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
Reply
#6
Replace this part:
Code:
12345678910111213
-- 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:
12345678
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
Reply
#7
ok thanks, I will try and let you know.

thx

Roger
Reply
#8
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:
12345678910111213141516171819202122232425262728293031323334
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
Reply
#9
(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:
12345678910111213141516171819202122232425262728293031323334
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
Reply
#10
Yes, looks fine
Reply


Forum Jump: