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: 8199
Threads: 43
Joined: Jun 2015
Reputation:
473
Here's a basic SSL connection example:
Code:
1 2 3 4 5 6 7 8 9 10 11
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:
1 2 3 4 5 6 7
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
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 )
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
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: 8199
Threads: 43
Joined: Jun 2015
Reputation:
473
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:
1 2 3 4
message =
'16XK40392361108171100067'
calccs =
checksum (
message :
sub (
1 , -
3 ))
recvcs =
message :
sub (-
2 , -
1 )
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
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 ))
recvcs =
str :
sub (-
2 , -
1 )
return calccs ==
recvcs
end
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 )
end
if not skt then
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 )
if (
not err )
then
skt :
settimeout (
0 )
copas.addthread (
function ()
while true do
local resp ,
err =
copas.receive (
skt )
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
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 ()
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: 8199
Threads: 43
Joined: Jun 2015
Reputation:
473
Replace this part:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
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:
1 2 3 4 5 6 7 8
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
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 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
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 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: 8199
Threads: 43
Joined: Jun 2015
Reputation:
473