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.

Multiple event-scripts in 1 script
#1
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
Reply
#2
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
Reply
#3
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 Smile
BR
Mr.D
Reply
#4
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
Reply
#5
Hi Erwin,
This almost gets me all the way Smile
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
Reply
#6
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
Reply
#7
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
Reply
#8
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
Reply
#9
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
Reply
#10
Hi,

My mistake (:

Remove line 40 as this is not valid (remain of testing).

BR,

Erwin
Reply
#11
Hi,

We are getting closer Smile
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
Reply
#12
Hi,

Yes it's now octal, i will check tonight as today i have a day off (:

BR,

Erwin
Reply
#13
Hi Erwin,

Thanks!
Enjoy your day off Smile

Mr.D
Reply
#14
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
Reply
#15
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
Reply
#16
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)
Reply
#17
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
Reply
#18
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 Smile). UTF16 is converted to hex which does not need escaping as well.
Reply
#19
(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 Smile). 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
Reply
#20
Thank you guys!!!
This works perfectly! Smile

BR,
Mr.D
Reply


Forum Jump: