AppleScript to set EZX10RF parameters

Posted on
Wed Jan 30, 2008 7:50 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

George:

Here is what is in the log:

Jan 30, 2008 6:48:35 PM
Script Ready to send raw insteon
Script Unable to verify command
Error 0C.AF.7D raw insteon command; send failed (no acknowledgment)
Error 0C.AF.7D raw insteon command; send failed (no acknowledgment)
Error 0C.AF.7D raw insteon command; send failed (no acknowledgment)

bob

Posted on
Wed Jan 30, 2008 8:38 pm
gmusser offline
Posts: 290
Joined: Feb 12, 2005
Location: New Jersey

(No subject)

Ah, one problem was that the script hard-coded my own EZX10RF's address. Try this version.
George

Code: Select all
--Second crack at a script to set the X10 filter on the EZX10RF module
--by George Musser

--Version history
--2 - 28 Jan 08
--3 - 30 Jan 08 - added scan for EZX10RF address

--Running the script clears the X10 filter table and then sets the codes listed in the global array.
--It does *not* create new device links or X10-to-Insteon mappings. To do that, I first need to
--figure out how to do link management.

--The routine has some error-checking, but doesn't work well if there's noise on the line.

--To save you grief, I've commented out two lines that actually do the dirty work, so that you
--can test the script for yourself before setting it loose on your EZX10RF.

--EZX10RF memory map and Insteon command set is available at http://www.simplehomenet.com/Downloads/EZX10RF%20Command%20Set.pdf

--Here's the list of X10 address to allow through.

property X10list : {"A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10", "A11", "A12", "E4"}

main()

on main()
   set addressEZ to my findEZ()
   if addressEZ is not "" then
      --comment this back in when you're ready!
      --clearFlags(addr)
      repeat with currentX10address in X10list
         setFlag(currentX10address, true, addressEZ)
      end repeat
   end if
end main

on findEZ()
   tell application "IndigoServer"
      set addressEZ to ""
      repeat with currentDevice in devices
         if model of currentDevice is "EZX10RF Wireless Sensor Receiver" then
            set addressEZ to address of currentDevice
            exit repeat
         end if
      end repeat
   end tell
   return addressEZ
end findEZ

on clearFlags(addr)
   tell application "IndigoServer"
      
      --set starting memory address for subsequent commands
      send insteon raw cmd1 40 cmd2 0 to address addr -- high byte
      send insteon raw cmd1 43 cmd2 6 to address addr -- low byte (starting with house code B for now)
      
      --cycle through the 2-byte registers associated with each X10 house code and clear them
      repeat 32 times
         
         --poke in a 0 value, which turns off filtering for all the unit codes         
         set ack to my getAck(41, 0, addr)
         
         --make sure it cleared properly
         if ack is not 0 then
            log "Unable to verify command"
            exit repeat
         end if
         
      end repeat
      
   end tell
end clearFlags


--here's a kludge to get the ACK code after sending raw Insteon commands
--this requires complete quiet on the power line

on getAck(byte1, byte2, addr)
   tell application "IndigoServer"
      
      --the ulterior purpose of this log command is to ensure that a time stamp doesn't contaminate
      --the ACK line
      log "Ready to send raw insteon"
      
      --here we actually send the command
      send insteon raw cmd1 byte1 cmd2 byte2 to address addr
      
      try
         set ackDec to -1
         
         --wait for the ack to come through
         repeat 8 times
            
            --grab the most recent line of the log
            --unfortunately, the date and time sometimes get mixed in
            set latestLogLine to build event log list line count 1
            
            --is it what we're looking for?
            --is there a better way of doing this?
            if second word of latestLogLine is "INSTEON" then
               if fourth word of latestLogLine is "raw" then
                  if my Hex2Dec(text 54 thru 55 of latestLogLine) is byte1 then
                     if my Hex2Dec(text 57 thru 58 of latestLogLine) is byte2 then
                        set ackDec to my Hex2Dec(last word of latestLogLine)
                        exit repeat
                     end if
                  end if
               end if
            end if
            delay 0.25
         end repeat
         
         if ackDec < 0 or ackDec > 255 then
            return -1
         else
            return ackDec
         end if
      on error
         return -1
      end try
   end tell
end getAck


--set a specific X10 flag on or off
--to enable a unit code, poke a 1 bit at the bit corresponding to the unit
--e.g. 4 corresponds to unit code 3

on setFlag(X10address, newFlag, addr)
   tell application "IndigoServer"
      
      --first, check the arguments
      if class of X10address is not string or class of newFlag is not boolean then return -1
      
      --second, parse the X10 address
      set houseASCIICode to text 1 of X10address
      set houseCode to offset of houseASCIICode in "ABCDEFGHIJKLMNOP"
      if length of X10address is 1 then
         return -1
      else if length of X10address is 2 then
         set unitCode to text 2 of X10address as number
      else
         set unitCode to text 2 thru 3 of X10address as number
      end if
      
      --third, do some error-checking
      if houseCode < 1 or houseCode > 16 or unitCode < 1 or unitCode > 16 then return -1
      
      --fourth, convert to an offset within the EZX10RF table
      set memoryIndex to 2 + houseCode * 2
      if unitCode ≤ 8 then
         set unitCode to unitCode - 1
      else
         set memoryIndex to memoryIndex + 1
         set unitCode to unitCode - 9
      end if
      
      --fifth, read the existing byte
      set reflectedAddress to my getAck(40, 0, addr) -- address MSB
      if reflectedAddress is not 0 then return -1
      set currentByte to my getAck(43, memoryIndex, addr) -- address LSB
      if currentByte is -1 then return -1
      
      --sixth, mask in the new flag value
      set mask to (2 ^ unitCode) as integer
      if newFlag then
         set newByte to my BitwiseOr(currentByte, mask)
      else
         set newByte to my BitWiseAnd(currentByte, my BitwiseNot(mask))
      end if
      
      --seventh, write the byte
      --when you're ready, comment this in and the debug line out
      --send insteon raw cmd1 41 cmd2 newByte to address addr
      
      tell application "Script Editor"
         display dialog "address " & memoryIndex & ", old value " & currentByte & ", new value " & newByte
      end tell
   end tell
end setFlag


--can someone tell me why AppleScript doesn't already have the following operators?
on BitwiseOr(i, j)
   return (do shell script "perl -e 'printf(\"%d\"," & i & "|" & j & ")'") as number
end BitwiseOr

on BitWiseAnd(i, j)
   return (do shell script "perl -e 'printf(\"%d\"," & i & "&" & j & ")'") as number
end BitWiseAnd

on BitwiseNot(i)
   return 256 + (do shell script "perl -e 'printf(\"%d\",~" & i & ")'") as number
end BitwiseNot

--AppleScript stupidly doesn't have native functions for handling hexadecimal, but here's an elegant workaround from http://bbs.applescript.net/viewtopic.php?id=19442
on Hex2Dec(s)
   return (do shell script "perl -e 'printf(hex(\"" & s & "\"))'") as number
end Hex2Dec

Posted on
Wed Jan 30, 2008 10:30 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

I plugged in the address of my EZX10RF and I still get the error:
Can't get text 1 of "A1 as in the Event Log:
tell current application
do shell script "perl -e 'printf(hex(\"29\"))'"
"41"
do shell script "perl -e 'printf(hex(\"00\"))'"
"0"
do shell script "perl -e 'printf(hex(\"00\"))'"
"0"
"Can't get text 1 of \"A1\"."


With your latest script to have the script find the address I get the error:
The variable addr is not defined like so from the Event Log;
get model of item 20 of every device
"EZX10RF Wireless Sensor Receiver"
get address of item 20 of every device
"05.92.97"
"The variable addr is not defined."

regards,

bob

Posted on
Wed Jan 30, 2008 10:48 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

George;

Using the script with the manual entry for the EZ address;

OK I got it, you need to change the word "text" to "character" in these lines:
--second, parse the X10 address
set houseASCIICode to character 1 of X10address
set houseCode to offset of houseASCIICode in "ABCDEFGHIJKLMNOP"
if length of X10address is 1 then
return -1
else if length of X10address is 2 then
set unitCode to character 2 of X10address as number
else
set unitCode to characters 2 thru 3 of X10address as number
end if


I think it's working - I'll keep testing and post results.

Thanks,

bob

Posted on
Wed Jan 30, 2008 11:24 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

George,

Your script is working as long as I don't use an X10 address over 9 in the property X10List once I get to 10 I get an error;

tell application "IndigoServer"
offset of "A" in "ABCDEFGHIJKLMNOP"
1
"Can't make {\"1\", \"0\"} into type number."


regards,
bob

Posted on
Wed Jan 30, 2008 11:58 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

George,

I think I have it. The change to the code below seems to work..... but for some reason it doesn't always write correctly for example if I select the property X10 list to A1 to A16 it writes to the register FF FF but if I then do B1 to B16 one time it writes EF EF then when I try it again it writes FF FF FF, maybe it is not clearing the register before writing? I'll work on it some more later.

bob

--second, parse the X10 address
set houseASCIICode to character 1 of X10address
set houseCode to offset of houseASCIICode in "ABCDEFGHIJKLMNOP"
if length of X10address is 1 then
return -1
else if length of X10address is 2 then
set unitCode to character 2 of X10address as number
else if length of X10address is 3 then
set unitCode to characters 2 thru 3 of X10address as string
end if

Posted on
Thu Jan 31, 2008 7:02 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

George,

Sometimes it writes to the register OK and other times not. For example I have the X10 List as {"A1", "A2", "A3"}, I run the script and the display dialog says;
address 4, old value 0, new value 1
address 4, old value 1, new value 3
address 4, old value 3, new value 7

so the address 0004-0005 should read 07 00 but reads 07 07 07

bob

Posted on
Thu Jan 31, 2008 9:06 pm
gmusser offline
Posts: 290
Joined: Feb 12, 2005
Location: New Jersey

(No subject)

Hmm, I think the problem right now is the use of the "character" statement -- extracting a substring from a string is done with "text". Can you change those back to "text" and let me know the error message you get? We can then debug it from there.
George

Posted on
Thu Jan 31, 2008 9:16 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

George,

The error I get is "Can't get text 1 of \"A1\"." as from the Event Log below;

tell current application
do shell script "perl -e 'printf(hex(\"29\"))'"
"41"
do shell script "perl -e 'printf(hex(\"00\"))'"
"0"
do shell script "perl -e 'printf(hex(\"00\"))'"
"0"
"Can't get text 1 of \"A1\"."

bob

Posted on
Sun Feb 10, 2008 8:22 pm
matt (support) offline
Site Admin
User avatar
Posts: 21418
Joined: Jan 27, 2003
Location: Texas

Re: AppleScript to set EZX10RF parameters

Hi George and Bob,

Give the latest 3.0 beta (16) a try. It has a new AppleScript verb that you'll probably want to use:
Code: Select all
tell app "IndigoServer"
   send insteon remote poke to address "0e.60.2f" at memory location MEM_ADDR_HERE byte list {1, 2, 3, 4, 5}
end tell

Regards,
Matt

Posted on
Sun Feb 10, 2008 8:24 pm
matt (support) offline
Site Admin
User avatar
Posts: 21418
Joined: Jan 27, 2003
Location: Texas

(No subject)

gmusser wrote:
Hi Matt,
How do I virtually press the PowerLinc set button from AppleScript? The EZX10RF has a command to enter linking mode, but I need to know what to do on the PowerLinc side to complete it.
George

With the latest 3.0 beta (16) try:
Code: Select all
tell app "IndigoServer"
   send insteon powerlinc set button
end tell

Matt

Posted on
Mon Mar 24, 2008 9:46 pm
gmusser offline
Posts: 290
Joined: Feb 12, 2005
Location: New Jersey

(No subject)

Cool! But I can't type in the EZ address -- my Mac beeps when I try to do so.
George

Posted on
Mon Mar 24, 2008 9:51 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

As soon as you select one of the buttons it should fill in your address for you.

bob

Posted on
Mon Mar 24, 2008 10:41 pm
bob offline
User avatar
Posts: 500
Joined: Jun 14, 2006

(No subject)

changed the app to load the EZX10RF address on start-up

http://www.duc.scrapping.cc/home_auto/ezfilter.shtml

Posted on
Tue Mar 25, 2008 7:44 pm
gmusser offline
Posts: 290
Joined: Feb 12, 2005
Location: New Jersey

(No subject)

OK, it fills in the EZX10RF Insteon address properly -- how did it find it? Does this require a certain naming convention in the Indigo database?

But I get an AppleScript Error: "The variable EZX10RF_address is not defined. (-2753)"

George

Who is online

Users browsing this forum: No registered users and 11 guests