Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
24.04.2017, 17:33
(This post was last modified: 24.04.2017, 17:34 by Mr.D.)
Hi,
I need help to write a script (don't know which one is best for this task).
I have magnets in doors and windows which is connected to the house alarm. I would like to write a script that sends a SMS telling me which door or window has been opened/closed. Each window/door has its own group address. I know I could write an Event-Script for each group address, but I am trying to avoid creating too many scripts.
This is a typical Even-Script that could be created for each window/door, but is there a way I could collect all scripts in one, and send different SMS depending on which door/window has been opened/closed?
if grp.getvalue('Status - Alarm - On/Off') == true then
require('socket.http')
socket.http.TIMEOUT = 1
socket.http.request('http://wwwwwwwww')
end
Thanks for your help.
BR
Mr.D
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
24.04.2017, 21:46
(This post was last modified: 24.04.2017, 21:51 by Erwin van der Zwart.)
Hi,
Add tags to the objects you want to monitor, and create a event based script that is linked to that tag and insert this to the event script:
Code: if event.getvalue() == true then
-- Perform action with dynamic name
log('value of ' .. grp.find(event.dst).name .. ' is true')
end
Where the log is now you can put your command to alert, mail, push or sms your string with the object name that triggers the event.
BR,
Erwin
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
Hi Erwin,
Thanks for your reply and help.
I am still a bit in the dark. The reason is that I send SMS by using Clickatell, and the message is part of an HTTP command. So I am struggling to get this ('value of ' .. grp.find(event.dst).name .. ' is true') a part of my http command. Also since I use Scandinavian language I need to translate the text to unicode...
Is there a way to create a solution that send a unique http command, based on which ('value of ' .. grp.find(event.dst).name .. ' is true') is triggered?
PS thank you for being so active on this forum and contributing and sharing your knowledge
BR
Mr.D
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
Hi,
Can you test if this is working?
Code: -- Perform action only on value true
if event.getvalue() == true then
-- Load lib
require('ssl.https')
require('socket.url')
-- Set parameters
APIUser = 'YOUR_API_USERTOKEN'
APIPassw = 'YOUR_API_PASSWORD'
APIId = 'YOUR_API_ID'
Sender = '123456789'
PhoneNumber = '987654321'
SMSText = socket.url.escape('value of ' .. grp.find(event.dst).name .. ' is true')
-- Build URL
url = "https://api.clickatell.com/http/sendmsg?user="..APIUser.."&password="..APIPassw.."&api_id="..APIId.."&from=+"..Sender.."&to="..PhoneNumber.."&text="..SMSText
-- Send Request
res, code, headers, status = ssl.https.request(url)
end
BR,
Erwin
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
04.05.2017, 15:21
(This post was last modified: 04.05.2017, 20:35 by Mr.D.)
Hi Erwin,
This almost gets me all the way
I get the right object in my SMS but Clickatell does not support letters like æ å ø and inn my objects and text I use these letters.
Therefor I need something like this:
('value of ' .. grp.find(event.dst).name .. ' is true') = (value of 1/1/1 is true) = 7093784523049875240897562 (this being unicode which supports åæø)
When using your script I need the SMSText parameter to use the 7093784523049875240897562 instead of (value of 1/1/1 is true).
ex.
if the ('value of ' .. grp.find(event.dst).name .. ' is true') comes up with 'value of 1/1/1 is true' the correspondent to that would be '1234', if it came up with 'value of 2/2/2 is true', the correspondent would be '5678'.
I hope this make sense, and if so, is there a way of doing this?
Thanks
Mr.D
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
04.05.2017, 23:17
(This post was last modified: 05.05.2017, 00:00 by Erwin van der Zwart.)
Hi,
You probably need octal unicode, but this script includes DEC, OCTAL and HTML formatting of UTF8:
Try this:
Code: function utf8tounicode(utf8str)
assert(type(utf8str) == "string")
local res, seq, val = {}, 0, nil
for i = 1, #utf8str do
local c = string.byte(utf8str, i)
if seq == 0 then
table.insert(res, val)
seq = c < 0x80 and 1 or c < 0xE0 and 2 or c < 0xF0 and 3 or
c < 0xF8 and 4 or c < 0xFC and 5 or c < 0xFE and 6 or
log("invalid UTF-8 character sequence")
val = bit.band(c, 2^(8-seq) - 1)
else
val = bit.bor(bit.lshift(val, 6), bit.band(c, 0x3F))
end
seq = seq - 1
end
table.insert(res, val)
resoct = {}
reshtml = {}
for i , object in ipairs(res) do
table.insert(resoct, '0' .. string.format("%o", object))
table.insert(reshtml, '&#' .. object .. ';')
end
return {res,table.concat(res),resoct,table.concat(resoct),reshtml,table.concat(reshtml)}
end
mytext = 'åæø'
result = utf8tounicode(mytext)
log(result)
log(result[1]) -- Table with separate dec results
log(result[2]) -- concatinated dec result table as string
log(result[3]) -- Table with separate oct results
log(result[4]) -- concatinated oct result table as string
log(result[5]) -- Table with separate html results
log(result[6]) -- concatinated html result table as string
BR,
Erwin
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
Hi Erwin,
Thank you for the script, just one question...
How and where do I use this with the clickatell script you helped me with above...?
BR
Mr.D
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
05.05.2017, 09:44
(This post was last modified: 05.05.2017, 09:47 by Erwin van der Zwart.)
Hi,
Try this:
Code: function utf8tounicode(utf8str)
assert(type(utf8str) == "string")
local res, seq, val = {}, 0, nil
for i = 1, #utf8str do
local c = string.byte(utf8str, i)
if seq == 0 then
table.insert(res, val)
seq = c < 0x80 and 1 or c < 0xE0 and 2 or c < 0xF0 and 3 or
c < 0xF8 and 4 or c < 0xFC and 5 or c < 0xFE and 6 or
log("invalid UTF-8 character sequence")
val = bit.band(c, 2^(8-seq) - 1)
else
val = bit.bor(bit.lshift(val, 6), bit.band(c, 0x3F))
end
seq = seq - 1
end
table.insert(res, val)
resoct = {}
reshtml = {}
for i , object in ipairs(res) do
table.insert(resoct, '0' .. string.format("%o", object))
table.insert(reshtml, '&#' .. object .. ';')
end
return {res,table.concat(res),resoct,table.concat(resoct),reshtml,table.concat(reshtml)}
end
-- Perform action only on value true
if event.getvalue() == true then
-- Load lib
require('ssl.https')
require('socket.url')
-- Set parameters
APIUser = 'YOUR_API_USERTOKEN'
APIPassw = 'YOUR_API_PASSWORD'
APIId = 'YOUR_API_ID'
Sender = '123456789'
PhoneNumber = '987654321'
Unicodetable = utf8tounicode(Eventname)
SMSText = socket.url.escape('value of ' .. grp.find(event.dst).name .. ' is true')
-- Convert SMS text to unicode
Unicodetable = utf8tounicode(SMSText)
SMSText = Unicodetable[4]
-- Build URL
url = "https://api.clickatell.com/http/sendmsg?user="..APIUser.."&password="..APIPassw.."&api_id="..APIId.."&from=+"..Sender.."&to="..PhoneNumber.."&text="..SMSText.."&unicode=1"
-- Send Request
res, code, headers, status = ssl.https.request(url)
end
BR,
Erwin
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
05.05.2017, 10:33
(This post was last modified: 05.05.2017, 10:34 by Mr.D.)
Hi Erwin,
I tried this, but it does not seem to work.
When using this script no SMS is generated.
Just to try and problem solve I tried removing the Function script on top and the following from the below:
Unicodetable = utf8tounicode(Eventname)
-- Convert SMS text to unicode
Unicodetable = utf8tounicode(SMSText)
SMSText = Unicodetable[4]
So the clickatell part seems to be working, but the conversion/funtion part must not work as intended...
BR
Mr.D
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
Hi,
My mistake (:
Remove line 40 as this is not valid (remain of testing).
BR,
Erwin
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
Hi,
We are getting closer
But it seems like the conversion uses the wrong kind of unicode.... it works fine if I remove the "unicode=1" from the url. But the result is a long string of numbers that don't mean anything...
Clickatell has a text to unicode converter and I have compared the two strings generated from the converter and your script The result are different.
On the text to unicode converter Clickatell have on their webpage it says "Converted output (UTF-16BE)", does this mean anything to you?
I saw in your previous code/comment it stated UTF8...
BR
Mr.D
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
Hi,
Yes it's now octal, i will check tonight as today i have a day off (:
BR,
Erwin
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
Hi Erwin,
Thanks!
Enjoy your day off
Mr.D
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
Hi,
I checked some things and the function utf8tounicode returns utf-32 (codepoint), octal and html unicode.
So basicly you need a codepoint to utf-16 big endian convert function to make it work.
I searched the web for 1 but without results. Maybe admin can help you on this.
BR,
Erwin
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
Hi Erwin,
Is it possible with a work around...
By using the Text to Unicode converter on the clickatell website, I can translate the different text into the correct unicode format.
So lets say that the text I went to send is already in Unicode format. If that was the case, then I would have to find a way to send the right text/unicode, depending on what object triggered the event.
So lets say that the object 1/1/1 was the event.dst, then I would send text_A = 12345, if object 2/2/2 was the event.dst then text_B = 67890 is to be sent.
It is not as sexy, but it might do the job....?
Thanks for your help!
BR,
Mr.D
Posts: 7763
Threads: 42
Joined: Jun 2015
Reputation:
447
Try this, it only handles 1 and 2 byte utf8 characters, but this should be enough for your case:
Code: function utf8cps(str)
local codepoints = {}
local len = #str
local i = 1
while i <= len do
local c = str:byte(i, i)
if c > 0 and c <= 127 then
codepoints[ #codepoints + 1 ] = c
i = i + 1
elseif c >= 194 and c <= 223 then
local c2 = str:byte(i + 1, i + 1) or 0
local cp = bit.bor(bit.lshift(c - 0xC0, 6), c2 - 0x80)
codepoints[ #codepoints + 1 ] = cp
i = i + 2
elseif c >= 224 and c <= 239 then
i = i + 3
elseif c >= 240 and c <= 244 then
i = i + 4
end
end
return codepoints
end
function toutf16hex(str)
local cps = utf8cps(str)
local res = {}
for _, cp in ipairs(cps) do
res[ #res + 1 ] = string.format('%04x', cp)
end
return table.concat(res)
end
encoded =toutf16hex('This is a test')
alert(encoded)
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
08.05.2017, 08:20
(This post was last modified: 08.05.2017, 09:10 by Erwin van der Zwart.)
Hi,
Thanks Admin!
Then your code should be like this:
Code: function utf8cps(str)
local codepoints = {}
local len = #str
local i = 1
while i <= len do
local c = str:byte(i, i)
if c > 0 and c <= 127 then
codepoints[ #codepoints + 1 ] = c
i = i + 1
elseif c >= 194 and c <= 223 then
local c2 = str:byte(i + 1, i + 1) or 0
local cp = bit.bor(bit.lshift(c - 0xC0, 6), c2 - 0x80)
codepoints[ #codepoints + 1 ] = cp
i = i + 2
elseif c >= 224 and c <= 239 then
i = i + 3
elseif c >= 240 and c <= 244 then
i = i + 4
end
end
return codepoints
end
function toutf16hex(str)
local cps = utf8cps(str)
local res = {}
for _, cp in ipairs(cps) do
res[ #res + 1 ] = string.format('%04x', cp)
end
return table.concat(res)
end
-- Perform action only on value true
if event.getvalue() == true then
-- Load lib
require('ssl.https')
-- Set parameters
APIUser = 'YOUR_API_USERTOKEN'
APIPassw = 'YOUR_API_PASSWORD'
APIId = 'YOUR_API_ID'
Sender = '123456789'
PhoneNumber = '987654321'
SMSText = 'value of ' .. grp.find(event.dst).name .. ' is true'
-- Convert SMS text to UTF-16BE
SMSText = toutf16hex(SMSText)
-- Build URL
url = "https://api.clickatell.com/http/sendmsg?user="..APIUser.."&password="..APIPassw.."&api_id="..APIId.."&from=+"..Sender.."&to="..PhoneNumber.."&text="..SMSText.."&unicode=1"
-- Send Request
res, code, headers, status = ssl.https.request(url)
end
BR,
Erwin
Posts: 7763
Threads: 42
Joined: Jun 2015
Reputation:
447
Erwin, you don't need to escape text before convertion to UTF16, otherwise it will not work at all (I've edited your code already ). UTF16 is converted to hex which does not need escaping as well.
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
08.05.2017, 09:09
(This post was last modified: 08.05.2017, 09:11 by Erwin van der Zwart.)
(08.05.2017, 08:44)admin Wrote: Erwin, you don't need to escape text before convertion to UTF16, otherwise it will not work at all (I've edited your code already ). UTF16 is converted to hex which does not need escaping as well.
Thanks!, then we also don't need the require('socket.url') (:
(removed it already from sample)
BR,
Erwin
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
Thank you guys!!!
This works perfectly!
BR,
Mr.D
|