View unanswered posts | View active topics It is currently Wed May 22, 2013 3:52 pm



Reply to topic  [ 29 posts ]  Go to page: 1, 2  Next
 AD2USB parser? and modify variable based on info? 
Author Message

Joined: Mar 31, 2008
Posts: 738
Post AD2USB parser? and modify variable based on info?
I am getting an AD2USB ademco alarm interface. It would be good to be able to parse the strings that come from the unit so that one can know if the alarm has been properly set, disarmed, etc.

Unfortunately I know nothing about parsers except in the most general terms. Is there a standard applescript "parser formula" or script that one can just plug in the parameters of the string types that are received and what each specific string should represent?

For implementation I'm thinking, for instance, that if the string representing "alarm set - stay" is received, a trigger would fire changing an "alarm state" variable to "alarm set - stay", which could be displayed on a control page.

any thoughts/help would be appreciated!


Thu Jun 10, 2010 2:11 pm
Profile

Joined: Mar 31, 2008
Posts: 738
Post Re: AD2USB parser? and modify variable based on info?
Berkinet posted the following on the NuTech forum:

*************
The following message is what I see after sending the Arm-Stay sequence to my panel:
Code:
[010100011000--------],060,[f70000ff106002002c020000000000],"ARMED ***AWAY***May Exit Now  60"
Sean's last post should point you towards the information you need to understand this message.

Regarding AppleScript. The issue is not as simple as just writing something in AppleScript, you need to know how to write AppleScripts that can be used by Serial-Bridge. I am sure that the only place you will find that kind of help will be on the Indigo Serial-Bridge forum. In the past there have been several discussions about using Serial-Bridge to parse a wide range of input formats. I have attached the sample script that is distributed with Serial-Bridge.

***************

looking at what is output by the board, the final section is all that is needed. It seems like it should be possible to simply ignore the preceeding comma delimited sections and capture/paste the text to a variable?


Thu Jun 10, 2010 10:20 pm
Profile
User avatar

Joined: Nov 18, 2008
Posts: 1721
Location: Berkeley, CA
Post Re: AD2USB parser? and modify variable based on info?
hamw wrote:For implementation I'm thinking, for instance, that if the string representing "alarm set - stay" is received, a trigger would fire changing an "alarm state" variable to "alarm set - stay", which could be displayed on a control page. !

If you only want to know the state of the alarm panel (armed or not) then you need only look at the first three positions in section 1 of the ad2usb message string. These are decoded as:
100 = READY
010 = ARMED AWAY
001 = ARMED HOME


Fri Jun 11, 2010 11:25 am
Profile

Joined: Mar 31, 2008
Posts: 738
Post Re: AD2USB parser? and modify variable based on info?
Having the text display in a variable field is a lot more useful since WAF is of the essence.


Fri Jun 11, 2010 11:57 am
Profile
User avatar

Joined: Nov 18, 2008
Posts: 1721
Location: Berkeley, CA
Post Re: AD2USB parser? and modify variable based on info?
hamw wrote:Having the text display in a variable field is a lot more useful since WAF is of the essence.

I think you are confusing what is displayed on a Control Page with the series of actions that set the display. You want to do the following:

1) In Serial Bridge: Parse a message stream to determine what state your alarm is in. This is most easily done by testing a 3 byte string for 3 values (It is much easier to test a fixed length string with a small set of possible values than a longer string with many possible values). In pseudocode:
Code: Select all
if string is "100" then
  set an indigo variable to "Ready"
elseif string is "010" then
  set an indigo variable to "Away"
elseif string is "001"
  set an indigo variable to "Stay"
else
  there is an error
endif

2) Next, In Indigo (probably an embedded AppleScript) now that you have an Indigo variable which contains the current alarm state you can either display the variable's actual value, or use that value to select another more descriptive message. For example (again in pseudocode):
Code: Select all
if alarm_variable is "Ready" then
  set the DisplayMessage to "The alarm is disarmed"
elseif alarm_variable is "Away" then
  set the DisplayMessage to "The alarm is ARMED AWAY"
elseif etc. etc.

Of course, instead of displaying a text message, you could also display an image that indicated the alarm's state (even higher WAF).


Fri Jun 11, 2010 12:29 pm
Profile

Joined: Mar 31, 2008
Posts: 738
Post Re: AD2USB parser? Serial Bridge Gurus help?
With a lot of patient help from Berkinet, Sean M and the guys over at the NuTech forum, the AD2USB is functioning correctly and I can now arm and disarm the Ademco from the iPhone. I'm hoping that we can get feedback working so that a variable can be modified to show the state of the alarm. It is my impression that the most basic approach would be to parse the alarm state (the first 3 numbers, 000=alarm off, 010=armed away, 001=armed away) and feed the value into a variable. The changed variable would initiate one of three triggers (alarm off, armed stay, armed away) which would set the iPhone displayed variable to the appropriate state.

Could I ask for help from the Serial Bridge Gurus to hopefully put together a parser? Berkinet posted some ideas just above, and here's some info from Sean Matthews at the NuTech site:

http://www.nutech.com/index.php?option= ... mitstart=0
Code: Select all

if not armed
   if ad2usbmessage.Substring(2,1) = '1'
     Announce "ARMED"
     armed = true
   end
end

if armed
   if ad2usbmessage.Substring(2,1) = '0'
     Announce "DISARMED"
     armed = false
   end
end


The basic idea is you can determin ARMED home/away etc by just looking at the 0 or 1 in section #1

Section #1 is provided by ad2usb by parsing the data as shown in section #3 or the raw panel data. Section #4 is your "TEXT" data as seen on your alpha keypads. It can vary from panel to panel but most standard messages are the same like a zone fault.

I did start reading up on indigo and Apple Script last night to see what issues exist. Seems like version 5 will solve lots of the extensibility issues with the embedded python scripting.


and some info re the datastream:


Code: Select all
Firmware documentation V1.0f.24

Output Format
All lines that start with ! are information
All other lines are real panel data or debug ( see @ keyboard command )
Each line ends with a CR LF also known as rn  or chr(10),chr(13)

In a normal panel output message the data has 4 sections.

Section #1 the bit fields easy to parse interpretations of the raw panel code.
Each bit can be one of three states. 0 = Off 1 = On - = Unknown or float
Example: [01010001000---------]
  Position #1  = READY
  Position #2  = ARMED AWAY
  Position #3  = ARMED HOME
  Position #4  = BACK LIGHT
  Position #5  = Programming Mode
  Position #6  = Beep 1-3 ( 3 = beep 3 times )
  Position #7  = A ZONE OR ZONES ARE BYPASSED
  Position #8  = AC Power
  Position #9  = CHIME MODE
  Position #10 = ALARM WAS TRIGGERED (Sticky Bit)
  Position #11 = ALARM BELL
  Position #12 = BATTERY LOW
  Position #13 - #20 unused

Section #2 Numeric indicator if message is zone 3 fault this will be 03

Section #3 Raw panel binary message data
Example: [f70000000000800c0c020000]
  This is the raw panel binary message data.

Section #4 Alpha Keypad Message
Example: "****DISARMED****  ZONES FAULTED "
   This is in quotes and is the message that is displayed on an alpha keypad.

Here is a full message from a vista 50p

[01000001000---------],e5,[f707000600e5800c0c020000],"ARMED ***AWAY***** ALL SECURE **"
[001000010000--------],10,[f70700060010808c08020000],"ARMED ***STAY**  ZONE BYPASSED  "

Keyboard Commands
= reboot
$ oscilloscope watching the DO line #1
@ Diagnostic bit setting #2
% 4800 baud hard switch
^ 2400 baud hard switch
! Configure device


#1 only available on revision 1.5 carrier mod wires can
   be used to revise a 1.0 board to a 1.5 board but require
   a very steady hand to wire onto the small chip on the
   bottom of the board.

#2 Diagnostic bits must be entered as base 10 values
    1 Start bit ( will trigger a strobe on PIN C0 when
      a start bit is detected on the software UART).
    2 Stop bit ( will trigger a strobe on PIN C0 when
      a stop bit is detected on the software UART).
    4 Parity bit ( will trigger a strobe on PIN C0
      when a parity bit is detected on the software UART).
    8 Data bit ( will trigger a strobe on PIN C0 when a
      data bit is detected on the software UART).
   16 Raw RX Data dump will dump raw data as seen by
      the software uart to the serial port on the DO line of the panel.     
   32 Raw TX Data dump will dump raw data as seen by
      the software uart to the serial port on the DI line of the panel.     
   64 Error bit will strobe PIN C0 when a framing error
      is detected by the software UART.
  128 Will strobe PIN C1 ever time our UART interrupt fires.
  256 Will strobe PIN C0 when we detect the DO line has
      produced a LONG HIGH state as part of the polling
      window monitoring.
  512 Will strobe PIN C0 when we detect our first low
      state on the DO line.
 1024 Will output the size of the polling window to the
      serial port.



Thanks very much!!


Last edited by hamw on Fri Jul 09, 2010 1:21 pm, edited 1 time in total.



Sat Jun 19, 2010 9:14 am
Profile

Joined: Mar 31, 2008
Posts: 738
Post Re: AD2USB parser? and modify variable based on info?
Deleted this stuff as it was not the right approach. See next post.


Last edited by hamw on Fri Jul 09, 2010 1:21 pm, edited 2 times in total.



Tue Jul 06, 2010 7:24 pm
Profile

Joined: Mar 31, 2008
Posts: 738
Post Re: AD2USB parser? and modify variable based on info?
Am slowwwwwly figuring something out. I pinched the following script from the DSC security alarm script (viewtopic.php?f=6&t=875&start=15) and modded it a little. It actually appears to work a bit, as it updates two variables, alarmstate and alarmserial, but just once and then hangs. The problem is a -2753 error which I think is at the "set value" section--the "value" remains in purple once compiled. What should be there? I tried "state" but that just threw another code.


set value of variable "alarmstate" to commandDescription
set value of variable "alarmserial" to commandString

Also, I'd like to capture the final bits of the description as here:

[01000001000---------],e5,[f707000600e5800c0c020000],"ARMED ***AWAY***** ALL SECURE **"

that give the state directly, basically char 52 on. I tried "set commandData to (characters 60 through -3 of commandString as string)" but no luck. I think I need to somehow account for the commas?

Code: Select all
-----------
--

(*
    --Serial process script for Serial Bridge
    --by M. Bendikson
    --mods by dtich
    --mods by HFTobeason

    --This script reads Hex message data broadcast from a DSC PC4401 serial interface board and logs the parsed value to IndigoServer, repeating until fatal error.
    *)

property commandString : ""
property commandCodes : {"100 Disarmed", "010 Armed Away", "001 Armed Stay"}

on MyProcessSerialData(connectionName)
   tell application "Serial Bridge"
      -- this will block until at least 1 byte is available
      wait for data from source connectionName
      set byteRead to read byte from source connectionName
      if byteRead is 13 or byteRead is 10 then -- CR=Hex 0D=ASCII 13 / LF=Hex 0A=ASCII 10
         if commandString is not "" then
            set commandDescription to my MyParse(characters 2 through 4 of commandString as string)
            set commandData to (characters 60 through -3 of commandString as string)
            tell application "IndigoServer"
               
               -- set value of variable "alarmstate" to commandDescription
               set value of variable "alarmstate" to commandDescription
               set value of variable "alarmserial" to commandString
               -- set value of variable "alarmserial" to commandString
            end tell
            set commandString to ""
         end if
      else
         set charRead to ASCII character byteRead
         set commandString to commandString & charRead
      end if
   end tell
end MyProcessSerialData

on startCommunication(connectionName)
   tell application "Serial Bridge"
      try
         set bufferDumpStr to (read string from source connectionName)
         log "dumping rs232 buffer: " & bufferDumpStr
      end try
      -- Loop forever: wait for data, read it, process it, and optionally send
      -- out serial data.
      --
      -- We do not want our script to return or exit since Serial Bridge
      -- only calls our script on launch (or when the Reload Script button
      -- is pressed).
      repeat while true
         try
            set maxTimeoutDelay to 8947848 -- 103.56 days (hex 0x00888888)
            with timeout of maxTimeoutDelay seconds
               my MyProcessSerialData(connectionName)
            end timeout
         on error number errNum
            if errNum is -1712 then
               log "timeout waiting for serial data" using type "Error"
            else if errNum is -1708 then
               log "AppleEvent not handled" using type "Error"
               --return -- fatal error; exit script processing
            else if errNum is -128 then
               log "connection script aborted" using type "Error"
               return -- fatal error; exit script processing
            else
               log "error " & errNum & " inside MyProcessSerialData()" using type "Error"
               --return -- maybe fatal error; exit script processing
            end if
         end try
      end repeat
   end tell
end startCommunication

on MyParse(commandString)
   repeat with x from 1 to count of commandCodes
      if word 1 of item x of commandCodes is commandString then
         return (characters 5 through -1 of item x of commandCodes as string)
      end if
   end repeat
end MyParse
(* The above read verbs all have an optional argument, "timeout after",
             * to specify how long to wait in milliseconds for the data if it is not
             * currently available. If no timeout argument is present, then a
             * timeout error will be immediately thrown if there is not enough
             * data present to fulfill the request.
             *)

-----------------------------------------------------------------------------
(* To send data use the "send to source" verb. You can either send
             * a single byte, multiple bytes as a list, or a string. To send a single byte:
             *)




Thanks again for any advice!


Thu Jul 08, 2010 9:04 pm
Profile

Joined: Mar 31, 2008
Posts: 738
Post Re: AD2USB parser? and modify variable based on info?
Might be part of the issue here. When Terminal is reading the AD2USB with nothing going on, the lines come in very regularly:

Code: Select all
[100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "
[100000011000--------],018,[f71300000018001c28021f00000000],"****DISARMED****  READY TO ARM  "
!Sending.done
[001100011000--------],018,[f71300000018038c28021f00000000],"  ARMED STAY 1   ZONE BYPASSED  "
[100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "
[001100011000--------],018,[f71300000018008c28021f00000000],"  ARMED STAY 1   ZONE BYPASSED  "
[100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "


However, as soon as the Serial Bridge connection is turned on, the lines go completely out of order, missing characters and running together:

Code: Select all
[100000011000--------],018,[f71300000018001c28021f00000000],"****DISARMED****  READY TO ARM  "
[100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "
000-------],018180000[100000011000--------],0c0,[2802000000],"****DISA"
--------],018,[f70000180028021f00"
[100000011000--------],0c0,[0000c01f000000],"****DISARMED****  READY TO ARM  --------],0181300001800000011000--------],0c0,[f704000000c000281f00000000],"****DISARMED****  READY TO ARM  [100000011000018,[f7130000001800],"****DISARMED****  READY TO ARM  "
0011000--------],0c0,[f704000000c000021f00],"****DISARMED****  READY TO ARM  "
[100000011000--------],18,[f71800000000],"****DISARMED****  READY TO ARM  --------],0c0,[f70400001c],"****DISARME"
--------],0180000128021f],"****DISARMED****  READY TO ARM  "
0011000--------],0c0f70000c00000000000],"****DISARMED****  READY TO ARM  "
[100000011000--------],018,[f71300000018001c28021f00000000],"****DISARMED****  READY TO ARM  "
[100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "


So although the parser does work, perhaps it is not possible to parse this particular data stream given the effects of SB on its format. The parser is looking for specific sequences, and when it sees different sequences because all the characters are out of sequence, it throws an error.

If the parser could recognize the pattern when the datastream is giving the panel alphanumeric reading, maybe it could then capture that specific information to put in the variable.

It might be suggested that the Terminal connection and the SB connection can't be on at the same time, and that's why the lines are out of whack, but even with the Terminal connection closed the parser hangs shortly after it begins.


Sat Jul 10, 2010 3:55 pm
Profile
User avatar

Joined: Nov 18, 2008
Posts: 1721
Location: Berkeley, CA
Post Re: AD2USB parser? and modify variable based on info?
The problem you are seeing has to do with synchronization. The alarm messages are of fixed length, but for some reason, a message may not be sent all at once. This results in a single logical message being spread across two physical (\n separated) lines. You need to get the lines back together again.

Here is an example, simplified for this discussion, that I wrote in Perl.
We start by reading an alarm message into $string, then:
Code: Select all
$inString = $inString . $string;
if ($inString =~ /\n/) {
        @strings = split(/\n/, $inString, 2);
        $rawData = @strings[0];
        $inString = @strings[1];
        $inString =~ s/\n//g;
}
In English, it does...
Code: Select all
concatenate (join) whatever we have saved in $inString with the message just read ($string)
If the message ($inString) contains a newline (\n), then
        split the message into 2 parts at the newline character
        call part 1 $rawData
        call part 2 $inString (replacing the old value of $inString)
        remove any newlines from $inString
Continue processing using the data saved in $rawData and any leftover data ($inString) will be added to the front of the next message read, etc, etc.

You will need to do something like this in AppleScript. I couldn't find a convenient example, maybe someone else on here has one, or can provide you with a few pointers - otherwise I'll see if I can put something together.


Last edited by berkinet on Sun Jul 11, 2010 6:28 pm, edited 1 time in total.



Sat Jul 10, 2010 4:34 pm
Profile
User avatar

Joined: Nov 18, 2008
Posts: 1721
Location: Berkeley, CA
Post Re: AD2USB parser? and modify variable based on info?
BTW, You will also need to filter out lines that are generated by the ad2usb alarm interface. These trpically start with "!"


Sat Jul 10, 2010 4:36 pm
Profile

Joined: Mar 31, 2008
Posts: 738
Post Re: AD2USB parser? and modify variable based on info?
stripping most of the stuff from the connection script as here:

Code: Select all
on MyProcessSerialData(connectionName)
   tell application "Serial Bridge"
      
      wait for data from source connectionName to count 60 
      
      set restOfString to read string from source connectionName
      log "rest of string = " & restOfString using type "Sample"
      
   end tell
end MyProcessSerialData


yields more organized data, which appears to begin as it should on each line. Even the motion detector triggering did not upset it. I tried to incorporate "sample" instead of byteread into the parsing script but got lots of errors. Characters 2-4, 100 or 010 or 001 following

Sample rest of string = "


represent the alarm state which the parser recognizes to update the variable. Capturing characters might help get us on the right track?


Code: Select all
11Jul, 2010 7:39:35 PM
  Sample           rest of string = "
[100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM 
  Sample           rest of string = "
[100000011000--------],029,[f71300000029001c28021f00000000],"****DISARMED****  READY TO ARM 

11Jul, 2010 7:39:47 PM
  Sample           rest of string = "
[100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "
[100000011000--------],029,[f71300000029001c28021f00000000],"****DISARMED****  READY TO ARM  "

  Sample           rest of string = [100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "


11Jul, 2010 7:39:56 PM
  Sample           rest of string = [100000011000--------],029,[f71300000029001c28021f00000000],"****DISARMED****  READY TO ARM  "
[100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "

  Sample           rest of string = [100000011000--------],029,[f71300000029001c28021f00000000],"****DISARMED****  READY TO ARM  "


11Jul, 2010 7:40:02 PM
  Sample           rest of string = !RFX:0216067,04
[100000011000--------],0c0,[f704000000c0001c28021f00000000

11Jul, 2010 7:40:04 PM
  Sample           rest of string = ],"****DISARMED****  READY TO ARM  "
[100000011000--------],029,[f71300
  Sample           rest of string = 000029001c28021f00000000],"****DISARMED****  READY TO ARM  "


11Jul, 2010 7:40:09 PM
  Sample           rest of string = [100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "


11Jul, 2010 7:40:13 PM
  Sample           rest of string = [100000011000--------],029,[f71300000029001c28021f00000000],"****DISARMED****  READY TO ARM  "
[000000011000--------],029,[f71300000029000028021f00000000],"FAULT 029 2ND   FLOOR MOTION    "


11Jul, 2010 7:40:16 PM
  Sample           rest of string = [100000011000--------],0c0,[f704000000c0001c28021f00000000],"****DISARMED****  READY TO ARM  "


Last edited by hamw on Mon Jul 12, 2010 5:58 am, edited 1 time in total.



Sun Jul 11, 2010 5:49 pm
Profile
User avatar

Joined: Nov 18, 2008
Posts: 1721
Location: Berkeley, CA
Post Re: AD2USB parser? and modify variable based on info?
Waiting for the data may seem to help at first, but, the problem you will eventually run into is that message frequency seems to increase linearly with the number of faulted zones. While a system in "Ready to Arm" state may send a message every 6 to 10 seconds, when you have the doors open on a nice day, or for a party, etc. and 4 or 5 zones are faulted, the messages arrive every second or faster. And, don't forget, you will also be getting raw messages like:"!RFX:0670107,80" from the RF sensors.

Unless you add code to track and "repair" the message chunks, or figure out some other way of guaranteeing that you always get complete messages, your system is bound to give un-predictable results.


Sun Jul 11, 2010 6:14 pm
Profile

Joined: Mar 31, 2008
Posts: 738
Post Re: AD2USB parser? and modify variable based on info?
In copying the DSC script the basics were made a bit more complicated. At a minimum only "alarm state" is needed, so the section:

Code: Select all
 if commandString is not "" then
            set commandDescription to my MyParse(characters 2 through 4 of commandString as string)
            set commandData to (characters 60 through -3 of commandString as string)
            tell application "IndigoServer"
               
               -- set value of variable "alarmstate" to commandDescription
               set value of variable "alarmstate" to commandDescription
               set value of variable "alarmserial" to commandString
               -- set value of variable "alarmserial" to commandString
            end tell
            set commandString to ""
         end if


can be reduced to:

Code: Select all
 if commandString is not "" then
            set commandDescription to my MyParse(characters 2 through 4 of commandString as string)
            tell application "IndigoServer"
               set value of variable "alarmstate" to commandDescription
            end tell
            set commandString to ""
         end if


if that simplifies matters.


Sun Jul 11, 2010 9:33 pm
Profile
User avatar

Joined: Nov 18, 2008
Posts: 1721
Location: Berkeley, CA
Post Re: AD2USB parser? and modify variable based on info?
hamw wrote:...if that simplifies matters.

That simplifies the pattern matching to determine the alarm state. However, if the string you are looking for is not in the right position (chars 2-4) in the message string (because the messages are mixed together), then you cannot easily find the information you are looking for.


Sun Jul 11, 2010 9:55 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 29 posts ]  Go to page: 1, 2  Next

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.   Template designed by STSoftware.