Posts: 200
Threads: 60
Joined: Jun 2015
Reputation:
7
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
Posts: 7760
Threads: 42
Joined: Jun 2015
Reputation:
447
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
Posts: 200
Threads: 60
Joined: Jun 2015
Reputation:
7
12.08.2017, 23:21
(This post was last modified: 12.08.2017, 23:22 by rocfusion.)
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
Posts: 7760
Threads: 42
Joined: Jun 2015
Reputation:
447
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)
Posts: 200
Threads: 60
Joined: Jun 2015
Reputation:
7
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
Posts: 7760
Threads: 42
Joined: Jun 2015
Reputation:
447
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
Posts: 200
Threads: 60
Joined: Jun 2015
Reputation:
7
ok thanks, I will try and let you know.
thx
Roger
Posts: 200
Threads: 60
Joined: Jun 2015
Reputation:
7
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
Posts: 200
Threads: 60
Joined: Jun 2015
Reputation:
7
(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
Posts: 7760
Threads: 42
Joined: Jun 2015
Reputation:
447
|