Difference between revisions of "Insteon PLM Ruby Code 373"

From LinuxMCE
Jump to: navigation, search
Line 3: Line 3:
  
 
def mainStart() ## This is called FIRST, reruns cannot call this.
 
def mainStart() ## This is called FIRST, reruns cannot call this.
 +
  #Register Message Interceptor
 +
  @interceptor = Command.new(device_.devid_, -1000, 1, 5, 37)
 +
  @interceptor.params_[2] = device_.devid_.to_s
 +
  SendCommand(@interceptor)
 
   #Get the PLM Database
 
   #Get the PLM Database
 
   sendGetLink
 
   sendGetLink
Line 8: Line 12:
 
   log('Finding Children..')
 
   log('Finding Children..')
 
   device_.childdevices_.each{|c| $children[device_.childdevices_[c.to_s.to_i].devdata_[12].chomp.lstrip.rstrip] = c.to_s.to_i}
 
   device_.childdevices_.each{|c| $children[device_.childdevices_[c.to_s.to_i].devdata_[12].chomp.lstrip.rstrip] = c.to_s.to_i}
   $children.keys.each{|c| log(c + ' = ' + $children[c].to_s)}
+
   $children.keys.each{|c| log(c + ' = ' + $children[c].to_s)
 +
  }
 
   log('reading stored Child configuration:')
 
   log('reading stored Child configuration:')
  
 
   $children.keys.each{|c|
 
   $children.keys.each{|c|
 
     #Get each Childs configuration
 
     #Get each Childs configuration
     getdeviceconfig(c) #
+
    $state[c] = 0
 +
     getdeviceconfig(c) #
 +
 
 
     #the above getdeviceconfig packs $configparams array
 
     #the above getdeviceconfig packs $configparams array
 
     log('Configuration for ' + c + ' = ' + $configparams.inspect.to_s)
 
     log('Configuration for ' + c + ' = ' + $configparams.inspect.to_s)
Line 22: Line 29:
 
   $children.keys.each{|c| sendGetChildStatus(c)}
 
   $children.keys.each{|c| sendGetChildStatus(c)}
 
   SndIns()
 
   SndIns()
 +
 
end
 
end
 
def mainRestart()
 
def mainRestart()
#We have hashes already set up.
+
  #We have hashes already set up.
$childdatabases.each_key{|@insteonID|
+
  $childdatabases.each_key{|@insteonID|
sendGetChildStatus(@insteonID)}
+
    $state[@insteonID] = 0
SndIns()
+
    sendGetChildStatus(@insteonID)}
 +
  SndIns()
 
end
 
end
  
Line 68: Line 77:
 
   else
 
   else
 
     $configparams = @configstring.unpack('a16' * (@configstring.length / 16))
 
     $configparams = @configstring.unpack('a16' * (@configstring.length / 16))
 
+
    $devicetemplate[insteonid] = getdevicetemplate($configparams[0][0..1], $configparams[0][2..3])
 
   end
 
   end
 
   #log($yellow + 'getdeviceconfig:' + $configparams.inspect + $grey)
 
   #log($yellow + 'getdeviceconfig:' + $configparams.inspect + $grey)
Line 150: Line 159:
 
     #log('sendRemoteGetNet:added to queue:' + param.inspect)
 
     #log('sendRemoteGetNet:added to queue:' + param.inspect)
 
     if $wAIT == true
 
     if $wAIT == true
       $cmdqueue.insert(x + 1, param)
+
       $cmdqueue.insert(x + 1, param)
 
     else
 
     else
 
       $cmdqueue.insert(x,param)
 
       $cmdqueue.insert(x,param)
 
     end
 
     end
  
   
+
 
 
   end
 
   end
 
end
 
end
Line 168: Line 177:
 
   case param['Response']
 
   case param['Response']
 
     # Standard RESPONSES (to commands)
 
     # Standard RESPONSES (to commands)
   when 'GetRevision' # Special Response
+
   when 'GetRevision' # Special Response
 
     log('-----|---------GetRevision:' + param['Parameter1'])
 
     log('-----|---------GetRevision:' + param['Parameter1'])
  
   when 'GetLatLong' # Special Response
+
   when 'GetLatLong' # Special Response
 
     log('-----|---------GetLatLong: Lat=' + param['Lat'] + ', Long=' + param['Long'])
 
     log('-----|---------GetLatLong: Lat=' + param['Lat'] + ', Long=' + param['Long'])
  
 
   when 'SetLatLong'
 
   when 'SetLatLong'
     if param['Parameter1'] = 'True' then
+
     if param['Parameter1'] == 'True' then
 
       log('-----|---------SetLatLong: Ok')
 
       log('-----|---------SetLatLong: Ok')
 
     else
 
     else
Line 184: Line 193:
 
   when 'SetTimeZone'
 
   when 'SetTimeZone'
  
   when 'GetClock' # Special Response
+
   when 'GetClock' # Special Response
  
 
   when 'SetClock'
 
   when 'SetClock'
Line 199: Line 208:
 
     cmdComplete
 
     cmdComplete
 
     SndIns()
 
     SndIns()
   when 'LstTimers' # Special Response
+
   when 'LstTimers' # Special Response
  
  
Line 206: Line 215:
 
   when 'AddTimer'
 
   when 'AddTimer'
  
   when 'GetTimer'   # Special Response
+
   when 'GetTimer' # Special Response
  
 
   when 'SetTimer'
 
   when 'SetTimer'
Line 212: Line 221:
 
   when 'DelTimer'
 
   when 'DelTimer'
  
   when 'GetVersion' # Special Response
+
   when 'GetVersion' # Special Response
  
 
   when 'SndGrp'
 
   when 'SndGrp'
Line 219: Line 228:
 
     ### BUG FOUND ### When the EZBridge receives a command from an EXTERNAL source
 
     ### BUG FOUND ### When the EZBridge receives a command from an EXTERNAL source
 
     ### ie not from this device, cmdqueue will be nil, and the code below
 
     ### ie not from this device, cmdqueue will be nil, and the code below
     ### fails. Have to check against that.
+
     ### fails. Have to check against that.
 
     if $cmdqueue.length > 0
 
     if $cmdqueue.length > 0
 
       #First, check the response to make sure the command made it ok.
 
       #First, check the response to make sure the command made it ok.
 
       if param['Parameter9'].to_i == 6 #Ack received
 
       if param['Parameter9'].to_i == 6 #Ack received
#log('Sending to ProcessACK')
+
        #log('Sending to ProcessACK')
         processACK(param)
+
         processACK(param)
 
       else # NACK received - command failed.
 
       else # NACK received - command failed.
 
         log('Command NACKED')
 
         log('Command NACKED')
Line 233: Line 242:
 
     end
 
     end
 
   when 'SndX10'
 
   when 'SndX10'
log('Response detected for SndX10')
+
    log('Response detected for SndX10')
 
     if param['Parameter5'].to_i == 6 #ack
 
     if param['Parameter5'].to_i == 6 #ack
log('X10 Command Successfull')
+
      log('X10 Command Successfull')
  
cmdComplete
+
      cmdComplete
        SndIns()
+
      SndIns()
else
+
    else
log('X10 Command FAILED')
+
      log('X10 Command FAILED')
cmdComplete
+
      cmdComplete
        SndIns()
+
      SndIns()
  
 
     end
 
     end
Line 268: Line 277:
 
       ### FINISHED WITH GetLnk
 
       ### FINISHED WITH GetLnk
 
       checkChildRecordsinPLM()
 
       checkChildRecordsinPLM()
 +
      SndIns()
 
     end
 
     end
 
   when 'GetNext'
 
   when 'GetNext'
Line 282: Line 292:
 
       # childrens insteon ID is in the PLM
 
       # childrens insteon ID is in the PLM
 
       checkChildRecordsinPLM()
 
       checkChildRecordsinPLM()
SndIns()
+
      # now, to make sure that all the records in the PLM are sensed as children
 +
     
 +
      SndIns()
 
     end
 
     end
  
Line 292: Line 304:
 
     else
 
     else
 
       log('SetCfg NACKED')
 
       log('SetCfg NACKED')
     end  
+
     end
 
   when 'GetLnkData'
 
   when 'GetLnkData'
  
Line 308: Line 320:
 
     SndIns()
 
     SndIns()
  
   when 'GetCfg' # Special Response
+
   when 'GetCfg' # Special Response
  
   when 'LstMacros' # Special Response
+
   when 'LstMacros' # Special Response
  
 
   when 'ClrMacros'
 
   when 'ClrMacros'
Line 316: Line 328:
 
   when 'AddMacro'
 
   when 'AddMacro'
  
   when 'GetMacro' # Special Response
+
   when 'GetMacro' # Special Response
  
 
   when 'SetMacro'
 
   when 'SetMacro'
Line 322: Line 334:
 
   when 'DelMacro'
 
   when 'DelMacro'
  
   when 'LstDevices' # Special Response
+
   when 'LstDevices' # Special Response
  
 
   when 'ClrDevices'
 
   when 'ClrDevices'
Line 328: Line 340:
 
   when 'AddDevice'
 
   when 'AddDevice'
  
   when 'GetDevice' # Special Response
+
   when 'GetDevice' # Special Response
  
 
   when 'SetDevice'
 
   when 'SetDevice'
Line 351: Line 363:
  
 
     # Response Messages
 
     # Response Messages
   when 'InsExtMsg'  
+
   when 'InsExtMsg'
  
 
   when 'InsStdMsg'
 
   when 'InsStdMsg'
Line 358: Line 370:
 
       #log('REROUTING to processExternalCommand(param)')
 
       #log('REROUTING to processExternalCommand(param)')
 
       processExternalCommand(param)
 
       processExternalCommand(param)
     when 0x1 #Assign to Group  
+
     when 0x1 #Assign to Group
 
       ### This is a broadcast message sent
 
       ### This is a broadcast message sent
 
       # from a PING command
 
       # from a PING command
Line 365: Line 377:
 
       ### BUG HERE
 
       ### BUG HERE
 
       #have to check flags to see if this is a broadcast message
 
       #have to check flags to see if this is a broadcast message
       log('Checking if this is a broadcast message')
+
       log('Checking if this is a broadcast message')
 
       log('Flags:' + param['Parameter9'])
 
       log('Flags:' + param['Parameter9'])
 
       if (param['Parameter9'].hex & 0x80) == 0x80
 
       if (param['Parameter9'].hex & 0x80) == 0x80
Line 371: Line 383:
 
         #recvComplete
 
         #recvComplete
 
         processDeviceInfo(param)
 
         processDeviceInfo(param)
       
+
 
 
         # check to see if current cmd is for this broadcast..
 
         # check to see if current cmd is for this broadcast..
 
         log('Current Command:' + $cmdqueue[0]['Parameter5'])
 
         log('Current Command:' + $cmdqueue[0]['Parameter5'])
Line 391: Line 403:
 
       log('Caught PING Message from Device')
 
       log('Caught PING Message from Device')
 
       $currentcmd = 1
 
       $currentcmd = 1
+
 
 
     when 0x11 # ON
 
     when 0x11 # ON
 
       log('Caught Insteon ON from INTERNAL source')
 
       log('Caught Insteon ON from INTERNAL source')
Line 400: Line 412:
 
       insID = insHb + "." + insMb + "." + insLb
 
       insID = insHb + "." + insMb + "." + insLb
 
       myDevFrom = $children[insID]
 
       myDevFrom = $children[insID]
log('Current DIM level:' + param['Parameter11'])
+
      log('Current DIM level:' + param['Parameter11'])
  
reportStatus(myDevFrom, hextopercent(param['Parameter11']))
+
      reportStatus(myDevFrom, hextopercent(param['Parameter11']))
  
 
       $currentcmd = 0
 
       $currentcmd = 0
Line 414: Line 426:
 
       insID = insHb + "." + insMb + "." + insLb
 
       insID = insHb + "." + insMb + "." + insLb
 
       myDevFrom = $children[insID]
 
       myDevFrom = $children[insID]
reportStatus(myDevFrom, 0)
+
      reportStatus(myDevFrom, 0)
  
 
       $currentcmd = 0
 
       $currentcmd = 0
Line 437: Line 449:
 
       log($blue + 'Configuration is:' + getdeltafromconfig(insID) + $grey)
 
       log($blue + 'Configuration is:' + getdeltafromconfig(insID) + $grey)
 
       if delta == getdeltafromconfig(insID)
 
       if delta == getdeltafromconfig(insID)
if $children[insID] != nil
+
        if $children[insID] != nil
        myDevFrom = $children[insID]
+
          myDevFrom = $children[insID]
        myDevTo = -1000 #DCE Router
+
          myDevTo = -1000 #DCE Router
        myPriority = 1
+
          myPriority = 1
        myType = 2 #Event
+
          myType = 2 #Event
  
        #Send an EVENT to report STATE ONLY if database has not changed
+
          #Send an EVENT to report STATE ONLY if database has not changed
# AND child exists in pluto
+
          # AND child exists in pluto
reportStatus(myDevFrom, hextopercent(param['Parameter11']))
+
          reportStatus(myDevFrom, hextopercent(param['Parameter11']))
end
+
        end
 
       else
 
       else
 
         log('Databse CHANGED -getting remote database')
 
         log('Databse CHANGED -getting remote database')
 
         #here, I have to WIPE the databse
 
         #here, I have to WIPE the databse
 
         # to prepare it for new data
 
         # to prepare it for new data
### here is where the DAMN CONFIG was reset!!!
+
        ### here is where the DAMN CONFIG was reset!!!
oldconfigstring = $childdatabases[insID][0]
+
        oldconfigstring = $childdatabases[insID][0]
 
         $childdatabases[insID] = [oldconfigstring]
 
         $childdatabases[insID] = [oldconfigstring]
 
         log('Setting Database Config')
 
         log('Setting Database Config')
Line 468: Line 480:
 
       SndIns()
 
       SndIns()
 
     when 0x2B # peek
 
     when 0x2B # peek
### BUG HERE... have to verify response is a PEEK command
+
      ### BUG HERE... have to verify response is a PEEK command
#response command is stored in parameter10
+
      #response command is stored in parameter10
if param['Parameter10'].hex == 0x2B # this is the peek command
+
      if param['Parameter10'].hex == 0x2B # this is the peek command
      cmdComplete
+
        cmdComplete
      log('Received PEEK from remote Device! DATA=' + param['Parameter11'])
+
        log('Received PEEK from remote Device! DATA=' + param['Parameter11'])
      checkPeekData(param)
+
        checkPeekData(param)
      $currentcmd = 0
+
        $currentcmd = 0
      SndIns()
+
        SndIns()
else
+
      else
log('Waiting for remote PEEK response, but got :' + param['Parameter10'])
+
        log('Waiting for remote PEEK response, but got :' + param['Parameter10'])
end
+
      end
 
     else
 
     else
 
     end
 
     end
Line 484: Line 496:
 
   when 'X10Msg'
 
   when 'X10Msg'
 
     log($purple + 'X10 Message Received' + $grey)
 
     log($purple + 'X10 Message Received' + $grey)
if param['Parameter4'].hex == 0x00
+
    if param['Parameter4'].hex == 0x00
log('This byte is a House/Unit Code')
+
      log('This byte is a House/Unit Code')
hn = param['Parameter3'][0].chr
+
      hn = param['Parameter3'][0].chr
ln = param['Parameter3'][1].chr
+
      ln = param['Parameter3'][1].chr
$x10byte1 = $X10HouseCodes[hn]
+
      $x10byte1 = $X10HouseCodes[hn]
$x10byte1 += $X10UnitCodes[ln]
+
      $x10byte1 += $X10UnitCodes[ln]
log('Translated X10 House/Unit Code:' + $x10byte1)
+
      log('Translated X10 House/Unit Code:' + $x10byte1)
else
+
    else
log('This byte is a House/Command Code')
+
      log('This byte is a House/Command Code')
hn = param['Parameter3'][0].chr
+
      hn = param['Parameter3'][0].chr
ln = param['Parameter3'][1].chr
+
      ln = param['Parameter3'][1].chr
#$x10byte2 = $X10HouseCodes[hn]
+
      $x10byte2 = $X10HouseCodes[hn]
$x10byte2 = $X10CommandCodes[ln]
+
      $x10byte2 += $X10CommandCodes[ln]
log('Translated X10 Command Code:' + $x10byte2)
+
      log('Translated X10 Command Code:' + $x10byte2)
log('X10 Command ready to send:' + $x10byte1 + ' ' + $x10byte2)
+
      log('X10 Command ready to send:' + $x10byte1 + ' ' + $x10byte2)
case $x10byte2
+
      case $X10CommandCodes[ln]
when 'On'
+
      when 'On'
#Send ON to lmnce
+
        #Send ON to lmnce
if $children[$x10byte1] == nil
+
        if $children[$x10byte1] == nil
log('I do not control this X10 device')
+
          log('I do not control this X10 device')
else
+
        else
cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 192)
+
          cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 192)
SendCommand(cmd)
+
          cmd.params_[120] = "1"
end
+
          SendCommand(cmd)
$x10byte1 = ''
+
        end
$x10byte2 = ''
+
      when 'Off'
when 'Off'
+
        #Send OFF to lmnce
#Send OFF to lmnce
+
        if $children[$x10byte1] == nil
if $children[$x10byte1] == nil
+
          log('I do not control this X10 device')
log('I do not control this X10 device')
+
        else
else
+
          cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 193)
cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 193)
+
          cmd.params_[120] = "1"
SendCommand(cmd)
+
          SendCommand(cmd)
end
+
        end
$x10byte1 = ''
+
      when 'Bright'
$x10byte2 = ''
+
        if $children[$x10byte1] == nil
when 'Bright'
+
          log('I do not control this X10 device')
when 'Dim'
+
        else
when 'All Lights Off'
+
          #send a command to set the state + 1
when 'All Lights On'
+
          @curstate = ($state[$x10byte1] / 100) * 32 #get equal 32 steps
when 'Status Request'
+
          $state[$x10byte1] = ((@curstate + 1) / 32) * 100
when 'Hail Ack'
+
          cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 184)
end
+
          cmd.params_[76] = $state[$x10byte1].to_s
+
          cmd.params_[120] = "1"
end
+
          SendCommand(cmd)
 +
          #$state[$x10byte1] = ($state[$x10byte1] / 100) * 32
 +
        end
 +
      when 'Dim'
 +
        @curstate = ($state[$x10byte1] / 100) * 32 #get equal 32 steps
 +
        $state[$x10byte1] = ((@curstate - 1) / 32) * 100
 +
        cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 184)
 +
        cmd.params_[76] = $state[$x10byte1].to_s
 +
        cmd.params_[120] = "1"
 +
        SendCommand(cmd)
 +
      when 'All Lights Off'
 +
        log('ALL Lights OFF Command not implemented')
 +
      when 'All Lights On'
 +
        log('All Lights ON Command not implemented')
 +
      when 'Status Request'
 +
        log('Status Request Command not implemented')
 +
      when 'Hail Ack'
 +
        log('Hail Ack Command not implemented')
 +
      end
 +
 
 +
    end
 
   when 'InsLnkSts'
 
   when 'InsLnkSts'
 
     log('InsLnkSts Received')
 
     log('InsLnkSts Received')
Line 579: Line 611:
 
     SndIns()
 
     SndIns()
 
   else
 
   else
     log('-----XXXXXXX UNKNOWN Response Received:' + param['Response'])
+
     log('-----XXXXXXX UNKNOWN Response Received')
 
   end
 
   end
  
Line 588: Line 620:
 
   #Caught a LnkData Response
 
   #Caught a LnkData Response
 
   log('LnkData Message Received')
 
   log('LnkData Message Received')
   insteonID = padhex(param['Parameter5']) + '.' + padhex(param['Parameter6']) + '.' + padhex(param['Parameter7'])
+
   log(param.inspect)
 +
  if param['Parameter6'] == '00' and param['Parameter7'] == '00'
 +
    log('FOUND X10 DEVICE!!!')
 +
    insteonID = padhex(param['Parameter5'])
 +
  else
 +
    insteonID = padhex(param['Parameter5']) + '.' + padhex(param['Parameter6']) + '.' + padhex(param['Parameter7'])
 +
  end
 
   group = param['Parameter4']
 
   group = param['Parameter4']
 
   recflags = param['Parameter3']
 
   recflags = param['Parameter3']
Line 601: Line 639:
 
   #Add to plmdatabase
 
   #Add to plmdatabase
 
   $plmdatabase << @currentrecord
 
   $plmdatabase << @currentrecord
   log('PLM database=' +$plmdatabase.inspect)
+
   log('record Flags:' + recflags)
   if (recflags[0] & 0x80) == 0x80 # Record is in use if true  
+
  #log('PLM database=' +$plmdatabase.inspect)
 +
   if (recflags[0] & 0x80) == 0x80 # Record is in use if true
 
   end
 
   end
 
   if (recflags[0] & 0x40) == 0x40 # Controller if true
 
   if (recflags[0] & 0x40) == 0x40 # Controller if true
Line 613: Line 652:
  
 
   cmdComplete
 
   cmdComplete
   sendGetNext()
+
   sendGetNext()
  
 
end
 
end
 
### Support Routine for EZToDCE
 
### Support Routine for EZToDCE
 
def processExternalCommand(param)
 
def processExternalCommand(param)
   #there is no current command  
+
   #there is no current command
 
   # THIS IS COMING FROM AN OUTSIDE SOURCE
 
   # THIS IS COMING FROM AN OUTSIDE SOURCE
 
   #EG: Manually turning Light Switch On/Off
 
   #EG: Manually turning Light Switch On/Off
Line 625: Line 664:
 
   ### have to check here if child is mine!
 
   ### have to check here if child is mine!
  
# This is where I have to check for a broadcast command..
+
  # This is where I have to check for a broadcast command..
#if so, search the child databases for responders,
+
  #if so, search the child databases for responders,
#and fire events for each responder.
+
  #and fire events for each responder.
#Message flag is in parameter9 Group command 0xCx (All-Link Broadcast Message Pg 42.)
+
  #Message flag is in parameter9 Group command 0xCx (All-Link Broadcast Message Pg 42.)
#Group is in parameter8
+
  #Group is in parameter8
#From InsteonID is parameters 3, 4, 5
+
  #From InsteonID is parameters 3, 4, 5
if (param['Parameter9'].hex & 0xC0) == 0xC0 # Message is Broadcast  
+
  if (param['Parameter9'].hex & 0xC0) == 0xC0 # Message is Broadcast
log('Rerouting to processBroadcastMessage')
+
    log('Rerouting to processBroadcastMessage')
processBroadcastMessage(param)
+
    processBroadcastMessage(param)
else
+
  else
log('Process External Command:')
+
    log('Process External Command:')
log('Param:' + param.inspect)
+
    log('Param:' + param.inspect)
  
  # there is no ack here. Simply Send COMMANDS back to DCE
+
    # there is no ack here. Simply Send COMMANDS back to DCE
  # and Complete the recv..
+
    # and Complete the recv..
  case param['Parameter10'].hex #this is the command
+
    case param['Parameter10'].hex #this is the command
  when 0x01 #Assign to Group
+
    when 0x01 #Assign to Group
    log('Caught EXTERNAL Assign to Group')
+
      log('Caught EXTERNAL Assign to Group')
    processDeviceInfo(param)
+
      processDeviceInfo(param)
    recvComplete
+
      recvComplete
  when 0x02 #Delete from Group
+
    when 0x02 #Delete from Group
    log('Caught EXTERNAL Delete from Group')
+
      log('Caught EXTERNAL Delete from Group')
    recvComplete
+
      recvComplete
  when 0x10 # PING
+
    when 0x10 # PING
    log('Caught EXTERNAL Insteon PING result')
+
      log('Caught EXTERNAL Insteon PING result')
    recvComplete
+
      recvComplete
  
  
  when 0x11 #ON
+
    when 0x11 #ON
    log('Caught EXTERNAL Insteon ON command result')
+
      log('Caught EXTERNAL Insteon ON command result')
    #on level is in cmd2
+
      #on level is in cmd2
    insHb = param['Parameter3'] # From
+
      insHb = param['Parameter3'] # From
    insMb = param['Parameter4']
+
      insMb = param['Parameter4']
    insLb = param['Parameter5']
+
      insLb = param['Parameter5']
    insID = insHb + "." + insMb + "." + insLb
+
      insID = insHb + "." + insMb + "." + insLb
    log('From:' +insID)
+
      log('From:' +insID)
    log('Device:' + $children[insID].to_s)
+
      log('Device:' + $children[insID].to_s)
    myDevFrom = $children[insID]
+
      myDevFrom = $children[insID]
    # check to see if I own child
+
      # check to see if I own child
    if myDevFrom == nil
+
      if myDevFrom == nil
      log('I do not control this device.')
+
        log('I do not control this device.')
    else
+
      else
reportStatus(myDevFrom, hextopercent(param['Parameter11']))
+
        reportStatus(myDevFrom, hextopercent(param['Parameter11']))
      $currentcmd = 0
+
        $currentcmd = 0
    end
+
      end
    recvComplete
+
      recvComplete
  
  
  
  when 0x13 #OFF
+
    when 0x13 #OFF
    log('Caught EXTERNAL Insteon OFF result')
+
      log('Caught EXTERNAL Insteon OFF result')
    #on level is in cmd2
+
      #on level is in cmd2
    insHb = param['Parameter3'] # From
+
      insHb = param['Parameter3'] # From
    insMb = param['Parameter4']
+
      insMb = param['Parameter4']
    insLb = param['Parameter5']
+
      insLb = param['Parameter5']
    insID = insHb + "." + insMb + "." + insLb
+
      insID = insHb + "." + insMb + "." + insLb
    myDevFrom = $children[insID]
+
      myDevFrom = $children[insID]
    if myDevFrom == nil
+
      if myDevFrom == nil
      log('I do not control this device.')
+
        log('I do not control this device.')
    else
+
      else
  
reportStatus(myDevFrom, 0)
+
        reportStatus(myDevFrom, 0)
  
      $currentcmd = 0
+
        $currentcmd = 0
      #log('EVENT and state SENT!!!.48:[10]=0')
+
        #log('EVENT and state SENT!!!.48:[10]=0')
 +
      end
 +
      recvComplete
 +
    when 0x15; log('Caught EXTERNAL Insteon Brighten Result')
 +
    when 0x16; log('Caught EXTERNAL Insteon DIM Result')
 +
    when 0x24; log('Caught EXTERNAL Insteon DO EE READ')
 +
    when 0x28; log('Caught EXTERNAL Insteon SET ADDRESS MSB')
 +
    when 0x29; log('Caught EXTERNAL Insteon POKE')
 +
    when 0x2A; log('Caught EXTERNAL Insteon POKE EXTENDED')
 +
    when 0x2B; log('Caught EXTERNAL Insteon PEEK')
 +
    when 0x2C; log('Caught EXTERNAL Insteon PEEK INTERNAL')
 +
    when 0x2D; log('Caught EXTERNAL Insteon POKE INTERNAL')
 +
    else
 +
      log('Unknown EXTERNAL Insteon Command.')
 
     end
 
     end
    recvComplete
 
  when 0x15; log('Caught EXTERNAL Insteon Brighten Result')
 
  when 0x16; log('Caught EXTERNAL Insteon DIM Result')
 
  when 0x24; log('Caught EXTERNAL Insteon DO EE READ')
 
  when 0x28; log('Caught EXTERNAL Insteon SET ADDRESS MSB')
 
  when 0x29; log('Caught EXTERNAL Insteon POKE')
 
  when 0x2A; log('Caught EXTERNAL Insteon POKE EXTENDED')
 
  when 0x2B; log('Caught EXTERNAL Insteon PEEK')
 
  when 0x2C; log('Caught EXTERNAL Insteon PEEK INTERNAL')
 
  when 0x2D; log('Caught EXTERNAL Insteon POKE INTERNAL')
 
  else
 
    log('Unknown EXTERNAL Insteon Command.')
 
 
   end
 
   end
end
 
 
end
 
end
 
### Support Routine for EZToDCE
 
### Support Routine for EZToDCE
Line 750: Line 789:
 
     $currentcmd = 0x28
 
     $currentcmd = 0x28
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
     
+
 
 
   when 0x29
 
   when 0x29
 
     log('Caught ACK for Insteon POKE')
 
     log('Caught ACK for Insteon POKE')
 
     $currentcmd = 0x29
 
     $currentcmd = 0x29
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
     
+
 
 
   when 0x2A
 
   when 0x2A
 
     log('Caught ACK for Insteon POKE EXTENDED')
 
     log('Caught ACK for Insteon POKE EXTENDED')
 
     $currentcmd = 0x2A
 
     $currentcmd = 0x2A
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
     
+
 
 
   when 0x2B
 
   when 0x2B
 
     #log('Caught ACK for Insteon PEEK')
 
     #log('Caught ACK for Insteon PEEK')
 
     $currentcmd = 0x2B
 
     $currentcmd = 0x2B
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
     
+
 
 
   when 0x2C
 
   when 0x2C
 
     log('Caught ACK for Insteon PEEK INTERNAL')
 
     log('Caught ACK for Insteon PEEK INTERNAL')
 
     $currentcmd = 0x2C
 
     $currentcmd = 0x2C
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
     
+
 
 
   when 0x2D
 
   when 0x2D
 
     log('Caught ACK for Insteon POKE INTERNAL')
 
     log('Caught ACK for Insteon POKE INTERNAL')
 
     $currentcmd = 0x2D
 
     $currentcmd = 0x2D
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
 
     $cmdqueue[0]['Command'] = 'InsStdMsg'
     
+
 
 
   else
 
   else
 
     log('Unknown Insteon Cmd1')
 
     log('Unknown Insteon Cmd1')
Line 785: Line 824:
  
 
   $remoteLinkRecord += param['Parameter11'].hex.chr
 
   $remoteLinkRecord += param['Parameter11'].hex.chr
log('CURRENT REMOTE RECORD IS:')
+
  log('CURRENT REMOTE RECORD IS:')
debug($remoteLinkRecord)
+
  debug($remoteLinkRecord)
 
   if $remoteLinkRecord.length == 8
 
   if $remoteLinkRecord.length == 8
 
     log('REMOTE RECORD COMPLETE!')
 
     log('REMOTE RECORD COMPLETE!')
Line 822: Line 861:
 
     @insteonID += padhex("%X" %$remoteLinkRecord[3]) + '.'
 
     @insteonID += padhex("%X" %$remoteLinkRecord[3]) + '.'
 
     @insteonID += padhex("%X" %$remoteLinkRecord[4])
 
     @insteonID += padhex("%X" %$remoteLinkRecord[4])
+
 
 
     @group = "%X" %$remoteLinkRecord[1]
 
     @group = "%X" %$remoteLinkRecord[1]
 
     @flags += @insteonID + " Group:" + @group
 
     @flags += @insteonID + " Group:" + @group
Line 836: Line 875:
 
     log('Value:' + @work)
 
     log('Value:' + @work)
 
     $childdatabases[insID] << @work #add it to the database
 
     $childdatabases[insID] << @work #add it to the database
     log('Current Database:' + $childdatabases.inspect)
+
     # log('Current Database:' + $childdatabases.inspect)
 
     #now to save the database to configuration.
 
     #now to save the database to configuration.
 
     savechilddatabases(insID)
 
     savechilddatabases(insID)
Line 847: Line 886:
 
       sendPing(@insteonID)
 
       sendPing(@insteonID)
 
     else
 
     else
log('InsteonID:' + @insteonID.to_s + 'seems to exist in child databases')
+
      log('InsteonID:' + @insteonID.to_s + 'seems to exist in child databases')
log('CDB:' + $childdatabases.inspect)
+
      log('CDB:' + $childdatabases.inspect)
  
 
     end
 
     end
Line 855: Line 894:
 
   end
 
   end
 
   log($aqua + @flags + $grey)
 
   log($aqua + @flags + $grey)
log2(@flags)
+
  log2(@flags)
 
   if ($remoteLinkRecord[0] & 0x02) == 0x02
 
   if ($remoteLinkRecord[0] & 0x02) == 0x02
 
     sendRemoteGetNext(insID)
 
     sendRemoteGetNext(insID)
Line 888: Line 927:
 
end
 
end
  
def processDeviceInfo(param)
+
def getdevicetemplate(cat, subcat)
  ### temporary
+
  ### 12-24-07 Adding Device Template compatibility..
+
  #have to find MY address
+
  insHb = param['Parameter3'] # From
+
  insMb = param['Parameter4']
+
  insLb = param['Parameter5']
+
  
   insID = padhex(insHb) + "." + padhex(insMb) + "." + padhex(insLb)
+
   log('Entered getdevicetemplate, Cat=' + cat.to_s + ', subcat = ' + subcat.to_s)
  #set the devicecat and device subcat in the childdatabases
+
   @templid = 0
  # 0-1 Device Category
+
   case cat.hex
  # 2-3 Device SubCategory
+
  # 4-5 Device Firmware
+
  $childdatabases[insID][0][0..1] = param['Parameter6']
+
  $childdatabases[insID][0][2..3] = param['Parameter7']
+
  $childdatabases[insID][0][4..5] = param['Parameter8']
+
  savechilddatabases(insID)
+
  log('InsteonID: ' + insID)
+
  #log('Child Config AFTER update:' + $childdatabases[insID][0].to_s)
+
   log($yellow)
+
   case param['Parameter6'].hex
+
 
   when 0x0 # Generalized Controllers
 
   when 0x0 # Generalized Controllers
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x04; log('Found ControLinc [2430]')
 
     when 0x04; log('Found ControLinc [2430]')
 
     when 0x05; log('Found RemoteLinc [2440]')
 
     when 0x05; log('Found RemoteLinc [2440]')
Line 920: Line 943:
 
     end
 
     end
 
   when 0x01 # Dimmable Lighting Control
 
   when 0x01 # Dimmable Lighting Control
     case param['Parameter7'].hex
+
     # all these devices are associated with Template 38
      # all these devices are associated with Template 38
+
    # Light Switch (dimmable)
      # Light Switch (dimmable)
+
    @templid = 38
 +
    case subcat.hex
 
     when 0x00; log('Found LampLinc V2 [2456D3]')
 
     when 0x00; log('Found LampLinc V2 [2456D3]')
 
     when 0x01; log('Found SwitchLinc V2 Dimmer 600W [2476D]')
 
     when 0x01; log('Found SwitchLinc V2 Dimmer 600W [2476D]')
Line 937: Line 961:
 
     end
 
     end
 
   when 0x02 # Switched Lighting Control
 
   when 0x02 # Switched Lighting Control
     case param['Parameter7'].hex
+
     # all these devices are associated with Template 37
      # all these devices are associated with Template 37
+
    # Light Switch (ON/OFF)
      # Light Switch (ON/OFF)
+
    @templid = 37
+
    case subcat.hex
 +
 
 
     when 0x09; log('Found ApplianceLinc [2456S3]')
 
     when 0x09; log('Found ApplianceLinc [2456S3]')
 
     when 0x0A; log('Found SwitchLinc Relay [2476S]')
 
     when 0x0A; log('Found SwitchLinc Relay [2476S]')
Line 951: Line 976:
 
     end
 
     end
 
   when 0x03 # Network Bridges
 
   when 0x03 # Network Bridges
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x01; log('Found PowerLinc Serial [2414S]')
 
     when 0x01; log('Found PowerLinc Serial [2414S]')
 
     when 0x02; log('Found PowerLinc USB [2414U]')
 
     when 0x02; log('Found PowerLinc USB [2414U]')
Line 959: Line 984:
 
     end
 
     end
 
   when 0x04 # Irrigation Control
 
   when 0x04 # Irrigation Control
     case param['Parameter7'].hex
+
     # all these devices are associated with Template 1780
      # all these devices are associated with Template 1780
+
    # Standard Irrigation Sprinkler
      # Standard Irrigation Sprinkler
+
    @templid = 1780
 +
    case subcat.hex
  
 
     when 0x00; log('Found Simplehomenet EZRain1 Sprinkler Controller')
 
     when 0x00; log('Found Simplehomenet EZRain1 Sprinkler Controller')
 
     end
 
     end
 
   when 0x05 # Climate Control
 
   when 0x05 # Climate Control
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00; log('Found Broan SMSC080 Exhaust Fan')
 
     when 0x00; log('Found Broan SMSC080 Exhaust Fan')
 
     when 0x01; log('Found Simplehomenet EZTherm')
 
     when 0x01; log('Found Simplehomenet EZTherm')
Line 974: Line 1,000:
 
     end
 
     end
 
   when 0x06 # Pool and Spa Control
 
   when 0x06 # Pool and Spa Control
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00; log('Found Simplehomenet EZPool')
 
     when 0x00; log('Found Simplehomenet EZPool')
 
     end
 
     end
 
   when 0x07 # Sensors and Actuators
 
   when 0x07 # Sensors and Actuators
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
 
   when 0x08 # Home Entertainment
 
   when 0x08 # Home Entertainment
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
 
   when 0x09 # Energy Management
 
   when 0x09 # Energy Management
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
 
   when 0x0A # Built-In Appliance Control
 
   when 0x0A # Built-In Appliance Control
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
 
   when 0x0B # Plumbing
 
   when 0x0B # Plumbing
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
 
   when 0x0C # Communication
 
   when 0x0C # Communication
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
 
   when 0x0D # Computer Control
 
   when 0x0D # Computer Control
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
 
   when 0x0E # Window Coverings
 
   when 0x0E # Window Coverings
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
 
   when 0x0F # Access Control
 
   when 0x0F # Access Control
     case param['Parameter7'].hex
+
     case subcat.hex
 
     when 0x00
 
     when 0x00
 
     end
 
     end
Line 1,021: Line 1,047:
 
   when 0x16 # Holiday
 
   when 0x16 # Holiday
 
   end
 
   end
 +
  return @templid
 +
end
 +
 +
def processDeviceInfo(param)
 +
  ### temporary
 +
  ### 12-24-07 Adding Device Template compatibility..
 +
  #have to find MY address
 +
  insHb = param['Parameter3'] # From
 +
  insMb = param['Parameter4']
 +
  insLb = param['Parameter5']
 +
 +
  insID = padhex(insHb) + "." + padhex(insMb) + "." + padhex(insLb)
 +
  #set the devicecat and device subcat in the childdatabases
 +
  # 0-1 Device Category
 +
  # 2-3 Device SubCategory
 +
  # 4-5 Device Firmware
 +
  log('proccessDeviceInfo:Insteon ID' + insID)
 +
  $childdatabases[insID][0][0..1] = param['Parameter6']
 +
  $childdatabases[insID][0][2..3] = param['Parameter7']
 +
  $childdatabases[insID][0][4..5] = param['Parameter8']
 +
  savechilddatabases(insID)
 +
  log('InsteonID: ' + insID)
 +
  #log('Child Config AFTER update:' + $childdatabases[insID][0].to_s)
 +
  log($yellow)
 +
  @template = getdevicetemplate(param['Parameter6'], param['Parameter7'])
 +
  $devicetemplate[insID] = @template
 +
  log('Template ID:' + @template.to_s)
 
   ### eventually, open a XML configuration script?
 
   ### eventually, open a XML configuration script?
 
   ### or read saved data from mysql?
 
   ### or read saved data from mysql?
 
   ### most likely save this information to sql with device.
 
   ### most likely save this information to sql with device.
 
   ### eventually, IPKDB will be available to ping.
 
   ### eventually, IPKDB will be available to ping.
   log ('for Insteon ID:' + insID)
+
   log('for Insteon ID:' + insID)
 
   log($grey)
 
   log($grey)
 
end
 
end
Line 1,032: Line 1,085:
 
   # Clears the wait flag, but does not remove a command from the queue
 
   # Clears the wait flag, but does not remove a command from the queue
 
   $wAIT = false
 
   $wAIT = false
   log($green + "Receive Completed. Checking command queue" + $grey)
+
   log($green + "Receive Completed. Checking command queue" + $grey)
 
   if $cmdqueue.nitems > 0 then
 
   if $cmdqueue.nitems > 0 then
 
     log("Queue:" + $aqua + $cmdqueue.nitems.to_s + $grey + " : executing next command")
 
     log("Queue:" + $aqua + $cmdqueue.nitems.to_s + $grey + " : executing next command")
Line 1,043: Line 1,096:
 
       mainRestart()
 
       mainRestart()
 
     else
 
     else
       log('RERUN Not needed')
+
       log('RERUN Not needed. Checking if reported..')
#report Child devices here.
+
      #report Child devices here.
if $reported == false
+
      if $reported == false
cmd = Command.new(0, device_.devid_, 1, 1, 756)
+
        log('Reporting Child Devices')
$reported = true
+
        @work = ""
SendCommand(cmd)
+
        $childdatabases.each_key{
end
+
          |insteonID|
 +
          log('Child:' + insteonID)
 +
          log('Config:' + $childdatabases[insteonID].inspect)
 +
          @template = $devicetemplate[insteonID]
 +
          @work += insteonID + "\t\t\t" + @template.to_s + "\t\n"
 +
        }
 +
        log(@work)
 +
        cmd = Command.new(device_.devid_, -1001, 1, 2, 54)
 +
        cmd.params_[13] = @work
 +
        SendCommand(cmd)
 +
 
 +
        $reported = true
 +
      else
 +
        log('report not needed')
 +
      end
 
     end
 
     end
  
 
   end
 
   end
 +
end
 +
def removecurrentcommand
 +
  #get the current child
 +
  log('in RemoveCurrentCommand')
 +
  log('Current Command:' + $cmdqueue[0].inspect)
 +
  #id is in param123
 +
  @id = $cmdqueue[0]['Parameter1']
 +
  @id += '.' + $cmdqueue[0]['Parameter2']
 +
  @id += '.' + $cmdqueue[0]['Parameter3']
 +
  log('ID=' + @id)
 +
  #now to remove from child and PLM databases
 +
  removefromchild(@id)
 +
  removefromplm(@id)
 +
  cmdComplete
 
end
 
end
 
def cmdComplete
 
def cmdComplete
Line 1,085: Line 1,166:
 
   param = {}
 
   param = {}
 
   #here is a special case, the PLM seems to lock up.
 
   #here is a special case, the PLM seems to lock up.
   if value == 0x15.chr  
+
   if value == 0x15.chr
log('The PLM stopped responding')
+
    log('The PLM stopped responding')
log('Please unplug it, and plug it back in')
+
    log('Please unplug it, and plug it back in')
log('and do a quick reload router.')
+
    log('and do a quick reload router.')
  
 
   end
 
   end
Line 1,130: Line 1,211:
 
       log('ERROR IN PLMPARSE- Unknown Command')
 
       log('ERROR IN PLMPARSE- Unknown Command')
 
       debug(value)
 
       debug(value)
+
 
 
       return ''
 
       return ''
 
     end
 
     end
Line 1,185: Line 1,266:
 
       end
 
       end
 
       conn_.Reconnect()
 
       conn_.Reconnect()
       debug(work)
+
       debugout(work)
 
       conn_.Send(work)
 
       conn_.Send(work)
 
       #sleep 0.1
 
       #sleep 0.1
Line 1,197: Line 1,278:
 
       else
 
       else
 
         log('RERUN Not needed')
 
         log('RERUN Not needed')
 +
        if $reported == false
 +
          log('Reporting Child Devices')
 +
          @work = ""
 +
          $childdatabases.each_key{
 +
            |insteonID|
 +
            log('Child:' + insteonID)
 +
            log('Config:' + $childdatabases[insteonID].inspect)
 +
            @template = $devicetemplate[insteonID]
 +
            @work += insteonID + "\t\t\t" + @template.to_s + "\t\n"
 +
          }
 +
          log(@work)
 +
          cmd = Command.new(device_.devid_, -1001, 1, 2, 54)
 +
          cmd.params_[13] = @work
 +
          SendCommand(cmd)
 +
 +
          $reported = true
 +
        else
 +
          log('report not needed')
 +
        end
 
       end
 
       end
  
 
     end
 
     end
 
   else
 
   else
     log('X-----------SndIns: Waiting for response to:' + $cmdqueue[0]['Command'].to_s)
+
     log('X-----------SndIns: Waiting for response to:' + $cmdqueue[0]['Command'].to_s)
 
     log('X-----------SndIns: Current Queue Length:' + $cmdqueue.nitems.to_s)
 
     log('X-----------SndIns: Current Queue Length:' + $cmdqueue.nitems.to_s)
 
   end
 
   end
Line 1,218: Line 1,318:
 
   when 'StLnk'; return 0x64.chr
 
   when 'StLnk'; return 0x64.chr
 
   when 'CancelLnk'; return 0x65.chr
 
   when 'CancelLnk'; return 0x65.chr
   when 'MngLnk'; return 0x6F.chr  
+
   when 'MngLnk'; return 0x6F.chr
 
   when 'RstPLM'; return 0x67.chr
 
   when 'RstPLM'; return 0x67.chr
 
   when 'SetCfg'; return 0x6B.chr
 
   when 'SetCfg'; return 0x6B.chr
Line 1,232: Line 1,332:
  
 
def debug(text)
 
def debug(text)
   work = 'OUT:'
+
   work = 'DEBUG:'
  
 
   for c in 1..text.length
 
   for c in 1..text.length
 
     work += padhex("%X" %text[c-1]) + ' '
 
     work += padhex("%X" %text[c-1]) + ' '
 
   end
 
   end
   log($green + work + "Length:" + text.length.to_s + $grey)
+
   log($yellow + work + "Length:" + text.length.to_s + $grey)
 
end
 
end
 +
def debugout(text)
 +
  work = 'out:'
  
 +
  for c in 1..text.length
 +
    work += padhex("%X" %text[c-1]) + ' '
 +
  end
 +
  log($green + work + "Length:" + text.length.to_s + $grey)
 +
end
 
def debugin(text)
 
def debugin(text)
 
   work = 'IN:'
 
   work = 'IN:'
Line 1,271: Line 1,378:
 
end
 
end
 
def log2(line)
 
def log2(line)
#this will send a message out the the orbiters..
+
  #this will send a message out the the orbiters..
#/usr/pluto/bin/MessageSend localhost 0 20 1 809 9 "Text to Display" 70 "alert" 182 "30" 251 "??"
+
  #/usr/pluto/bin/MessageSend localhost 0 20 1 809 9 "Text to Display" 70 "alert" 182 "30" 251 "??"
cmd = Command.new(device_.devid_, -1000, 1, 1, 809)
+
  cmd = Command.new(device_.devid_, -1000, 1, 1, 809)
cmd.params_[9] = line #text to display
+
  cmd.params_[9] = line #text to display
cmd.params_[70] = 'PLMMessage' #Token
+
  cmd.params_[70] = 'PLMMessage' #Token
cmd.params_[182] = '10' #Timeout in seconds
+
  cmd.params_[182] = '10' #Timeout in seconds
cmd.params_[251] = '??'
+
  cmd.params_[251] = '??'
SendCommand(cmd)
+
  SendCommand(cmd)
 
end
 
end
 
def checkChildRecordsinPLM()
 
def checkChildRecordsinPLM()
   # log('In CheckChildRecordsinPLM')
+
  log('Entered CheckChildRecordsinPLM')
 +
   # log('In CheckChildRecordsinPLM')
 
   # time to verify all children are in the PLM
 
   # time to verify all children are in the PLM
 
   #
 
   #
   # log('Total PLM Records:' + $plmdatabase.nitems.to_s)
+
   # log('Total PLM Records:' + $plmdatabase.nitems.to_s)
   # $plmdatabase.each{|record|
+
   $plmdatabase.each{|record|
  # log('Record: = '+ getIIDfromRecord(record) + ' Group:' + getGroupfromRecord(record))
+
    log('Record: = '+ getIIDfromRecord(record) + ' Group:' + getGroupfromRecord(record))
   # }
+
    log('checking to see if it needs to be added as a child...')
 +
    if existsinchild(getIIDfromRecord(record)) == false
 +
       
 +
      log(getIIDfromRecord(record) + ' needs to be added to the child database')
 +
      addtochild(getIIDfromRecord(record))
 +
    end
 +
   }
  
 
   $childdatabases.each_key {|child|
 
   $childdatabases.each_key {|child|
 
     if existsinplm(child) == false
 
     if existsinplm(child) == false
       #log(child + ' needs to be added to PLM')
+
       log(child + ' needs to be added to PLM')
 
       sendAddtoPLM(child)
 
       sendAddtoPLM(child)
 
     else
 
     else
 
       log(child + ' exists in PLM')
 
       log(child + ' exists in PLM')
 
     end
 
     end
    @result = 'Child: ' + child + "\n"
+
 
 
     #now to scan the childs database
 
     #now to scan the childs database
 
     for record in 1..($childdatabases[child].nitems - 1)
 
     for record in 1..($childdatabases[child].nitems - 1)
Line 1,307: Line 1,421:
 
       end
 
       end
 
       #Also check to see if it needs to be added in the childdatabases
 
       #Also check to see if it needs to be added in the childdatabases
      if existsinchild(getIIDfromRecord(@test)) == false
 
        log(getIIDfromRecord(@test) + ' needs to be added to the child database')
 
        addtochild(getIIDfromRecord(@test))
 
      end
 
 
     end
 
     end
 
   }
 
   }
Line 1,320: Line 1,430:
 
     #log(insteonid + '==' + getIIDfromRecord(record))
 
     #log(insteonid + '==' + getIIDfromRecord(record))
 
     if insteonid == getIIDfromRecord(record)
 
     if insteonid == getIIDfromRecord(record)
      #log('TRUE')
 
 
       result = true
 
       result = true
 
     end
 
     end
Line 1,327: Line 1,436:
 
end
 
end
 
def existsinchild(insteonid)
 
def existsinchild(insteonid)
 +
  log('ExistsinChild:InsteonID:' + insteonid)
 
   result = false
 
   result = false
 
   $childdatabases.each_key{|record|
 
   $childdatabases.each_key{|record|
Line 1,333: Line 1,443:
 
     end
 
     end
 
   }
 
   }
 +
  log('ExistsinChild result:FALSE') if result == false
 +
  log('ExistsinChild result:TRUE') if result == true
 
   return result
 
   return result
 
end
 
end
Line 1,338: Line 1,450:
 
   log('addtochild Routne called')
 
   log('addtochild Routne called')
 
   log('Adding ' + insteonID + ' to the child database...')
 
   log('Adding ' + insteonID + ' to the child database...')
   $childdatabases[insteonID] = ['****************']
+
   if insteonID.length == 2 then
  sendPing(insteonID)
+
    log('Child is X10')
  $rerun = true
+
    $state[insteonID] = 0
 +
  else
 +
    log('Child is Insteon')
 +
    $childdatabases[insteonID] = ['****************']
 +
    sendPing(insteonID)
 +
    $rerun = true
 +
  end
 +
end
 +
def removefromchild(insteonID)
 +
  log('Removing ' + insteonID + ' from child database')
 +
  $childdatabases.delete(insteonID)
 +
  $state.delete(insteonID)
 +
end
 +
def removefromplm(insteonID)
 +
  log('Removing from plm')
 +
  $plmdatabase.each{|record|
 +
    #log(insteonid + '==' + getIIDfromRecord(record))
 +
    if insteonID == getIIDfromRecord(record)
 +
      debug(record)
 +
      log('Found Record, Deleting')
 +
      $plmdatabase.delete(record)
 +
     
 +
      #now, we have to remove it from the device.
 +
      param = {'Command' =>'MngLnk',
 +
        'Parameter1' => '80', #DELETE
 +
        'Parameter2' => record[0..1], #control byte
 +
        'Parameter3' => record[2..3], #group
 +
        'Parameter4' => record[4..5],#HB
 +
        'Parameter5' => record[6..7],#MB
 +
        'Parameter6' => record[8..9],#LB
 +
        'Parameter7' => record[10..11],#data1
 +
        'Parameter8' => record[12..13],#data2
 +
        'Parameter9' => record[14..15] #data3
 +
       
 +
      }
 +
      log(param.inspect)
 +
      $cmdqueue << param
 +
    end
 +
  }
 
end
 
end
 
def sendAddtoPLM(insteonID)
 
def sendAddtoPLM(insteonID)
Line 1,377: Line 1,527:
  
 
def processBroadcastMessage(param)
 
def processBroadcastMessage(param)
#search the child databases for responders,
+
  #search the child databases for responders,
#and fire COMMANDS for each responder. 06Feb08
+
  #and fire COMMANDS for each responder. 06Feb08
#and fire events for each responder.XXXXXXXXXXXXX
+
  #and fire events for each responder.XXXXXXXXXXXXX
#Message flag is in parameter9 Group command 0xCx (All-Link Broadcast Message Pg 42.)
+
  #Message flag is in parameter9 Group command 0xCx (All-Link Broadcast Message Pg 42.)
#Group is in parameter8
+
  #Group is in parameter8
#From InsteonID is parameters 3, 4, 5
+
  #From InsteonID is parameters 3, 4, 5
group = param['Parameter8']
+
  group = param['Parameter8']
from = padhex(param['Parameter3']) + '.'
+
  from = padhex(param['Parameter3']) + '.'
from += padhex(param['Parameter4']) + '.'
+
  from += padhex(param['Parameter4']) + '.'
from += padhex(param['Parameter5'])
+
  from += padhex(param['Parameter5'])
log('Looking for ' + from + ' Group:' + group)
+
  log('Looking for ' + from + ' Group:' + group)
#Ok, now have to search child databases for from AND group AND responder
+
  #Ok, now have to search child databases for from AND group AND responder
$childdatabases.each_key{|child|
+
  $childdatabases.each_key{|child|
  #log('Searching:' + child)
+
    #log('Searching:' + child)
  for rec in 1..($childdatabases[child].nitems - 1)
+
    for rec in 1..($childdatabases[child].nitems - 1)
record = $childdatabases[child][rec]
+
      record = $childdatabases[child][rec]
if getIIDfromRecord(record) == from # First, look for Insteon ID
+
      if getIIDfromRecord(record) == from # First, look for Insteon ID
#log('Found ID')
+
        #log('Found ID')
if getGroupfromRecord(record) == group #next, Group
+
        if getGroupfromRecord(record) == group #next, Group
#log('Found Group')
+
          #log('Found Group')
if isResponderRecord(record) # is a responder?
+
          if isResponderRecord(record) # is a responder?
#log('Found Responder')
+
            #log('Found Responder')
#figure out the child devicenum
+
            #figure out the child devicenum
from = $children[child]
+
            from = $children[child]
#figure out the command
+
            #figure out the command
case param['Parameter10'].hex
+
            case param['Parameter10'].hex
when 0x11 #on
+
            when 0x11 #on
reportStatus(from, 100)
+
              reportStatus(from, 100)
when 0x13 #off
+
            when 0x13 #off
reportStatus(from, 0)
+
              reportStatus(from, 0)
when 0x17 #dim/brighten -ignore
+
            when 0x17 #dim/brighten -ignore
level = 0
+
              level = 0
when 0x18 # STOP dim/brighten - sendgetstatus
+
            when 0x18 # STOP dim/brighten - sendgetstatus
level = 0
+
              level = 0
sendGetChildStatus(child)
+
              sendGetChildStatus(child)
else
+
            else
level = 0
+
              level = 0
log('Command is other than ON/OFF/Dim/Brighten')
+
              log('Command is other than ON/OFF/Dim/Brighten')
end
+
            end
end
+
          end
end
+
        end
end
+
      end
  end
+
    end
}
+
  }
 
end
 
end
  
 
def reportStatus(from, level)
 
def reportStatus(from, level)
 
+
  log('From:' + from.to_s)
log('current State:' + $state[from].to_s)  
+
  log('current State:' + $state[from].to_s)
log('Wanted State:' + level.to_s)
+
  log('Wanted State:' + level.to_s)
case $state[from]
+
  case $state[from]
when 0
+
  when 0
if level >=1  
+
    if level >=1
cmd = Command.new(from, from, 1, 1, 192) #on
+
      cmd = Command.new(from, from, 1, 1, 192) #on
cmd.params_[120] = "1"
+
      cmd.params_[120] = "1"
SendCommand(cmd)
+
      SendCommand(cmd)
cmd = Command.new(from, from, 1, 1, 184)
+
      cmd = Command.new(from, from, 1, 1, 184)
cmd.params_[76] = level.to_s
+
      cmd.params_[76] = level.to_s
SendCommand(cmd)
+
      cmd.params_[120] = "1"
end
+
      SendCommand(cmd)
when 100
+
    end
if level >= 1
+
  when 100
cmd = Command.new(from, from, 1, 1, 184)
+
    if level >= 1
cmd.params_[76] = level.to_s
+
      cmd = Command.new(from, from, 1, 1, 184)
SendCommand(cmd)
+
      cmd.params_[76] = level.to_s
else
+
      cmd.params_[120] = "1"
cmd = Command.new(from, from, 1, 1, 193) # off
+
      SendCommand(cmd)
cmd.params_[120] = "1"
+
    else
SendCommand(cmd)
+
      cmd = Command.new(from, from, 1, 1, 193) # off
end
+
      cmd.params_[120] = "1"
else
+
      SendCommand(cmd)
if level == 100
+
    end
cmd = Command.new(from, from, 1, 1, 193) #off
+
  else
cmd.params_[120] = "1"
+
    if level == 100
SendCommand(cmd)
+
      cmd = Command.new(from, from, 1, 1, 193) #off
cmd = Command.new(from, from, 1, 1, 192) # on
+
      cmd.params_[120] = "1"
cmd.params_[120] = "1"
+
      SendCommand(cmd)
SendCommand(cmd)
+
      cmd = Command.new(from, from, 1, 1, 192) # on
end
+
      cmd.params_[120] = "1"
cmd = Command.new(from, from, 1, 1, 184) #SetLevel
+
      SendCommand(cmd)
cmd.params_[76] = level.to_s
+
    end
cmd.params_[120] = "1"
+
    cmd = Command.new(from, from, 1, 1, 184) #SetLevel
SendCommand(cmd)
+
    cmd.params_[76] = level.to_s
end
+
    cmd.params_[120] = "1"
log('ReportStatus: device:' + from.to_s + ' Status:' + level.to_s)
+
    SendCommand(cmd)
$state[from] = level
+
  end
 +
  log('ReportStatus: device:' + from.to_s + ' Status:' + level.to_s)
 +
  $state[from] = level
  
 
end
 
end
  
 
def isResponderRecord(recordstring)
 
def isResponderRecord(recordstring)
work = recordstring[0..1].hex
+
  work = recordstring[0..1].hex
if (work & 0x40) == 0x40 #check bit 6
+
  if (work & 0x40) == 0x40 #check bit 6
result = false #signifies Controller record
+
    result = false #signifies Controller record
else
+
  else
result = true #signifies Responder record
+
    result = true #signifies Responder record
end
+
  end
return result  
+
  return result
 
end
 
end
  
Line 1,496: Line 1,648:
 
   #log('sendGetChildStatus Called')
 
   #log('sendGetChildStatus Called')
 
   if insteonID.length != 2 #X10 device
 
   if insteonID.length != 2 #X10 device
  @insID = insteonID.split('.')
+
    @insID = insteonID.split('.')
  param = {'Command' => 'SndIns',
+
    param = {'Command' => 'SndIns',
    'Parameter1' => @insID[0],  
+
      'Parameter1' => @insID[0],
    'Parameter2' => @insID[1],
+
      'Parameter2' => @insID[1],
    'Parameter3' => @insID[2],
+
      'Parameter3' => @insID[2],
    'Parameter4' => '0F', #flags
+
      'Parameter4' => '0F', #flags
    'Parameter5' => '19', #Status Request
+
      'Parameter5' => '19', #Status Request
    'Parameter6' => '00'} #not used.
+
      'Parameter6' => '00'} #not used.
  $cmdqueue << param
+
    $cmdqueue << param
  SndIns()
+
    SndIns()
  #Returned response will have cmd1 = DBDelta
+
    #Returned response will have cmd1 = DBDelta
  #Returned response will have cmd2 = ON-Level
+
    #Returned response will have cmd2 = ON-Level
 
   else
 
   else
log('X10 does not report status')
+
    log('X10 does not report status')
end
+
  end
 
end
 
end
  
Line 1,516: Line 1,668:
 
# time to define a structure to save the raw data in hex
 
# time to define a structure to save the raw data in hex
 
# starts at [0]
 
# starts at [0]
# Bytes Meaning
+
# Bytes Meaning
# 0-1 Device Category
+
# 0-1 Device Category
# 2-3 Device SubCategory
+
# 2-3 Device SubCategory
# 4-5 Device Firmware
+
# 4-5 Device Firmware
# 6-7 Database Delta
+
# 6-7 Database Delta
# 8-9 reserved
+
# 8-9 reserved
# 10-11 reserved
+
# 10-11 reserved
# 12-13 reserved
+
# 12-13 reserved
# 14-15 reserved
+
# 14-15 reserved
 
###### First database record below (in same format its read from the device)
 
###### First database record below (in same format its read from the device)
 
###### This is the same format as an ALL-Link Record Response from the PLM
 
###### This is the same format as an ALL-Link Record Response from the PLM
 
###### (0x57) bytes 3..10
 
###### (0x57) bytes 3..10
# 16-17 record control byte
+
# 16-17 record control byte
# 18-19 Group
+
# 18-19 Group
# 20-21 ID HB
+
# 20-21 ID HB
# 22-23 ID MB
+
# 22-23 ID MB
# 24-25 ID LB
+
# 24-25 ID LB
# 26-27 Link Specific Data1
+
# 26-27 Link Specific Data1
# 28-29 Link Specific Data2
+
# 28-29 Link Specific Data2
# 30-31 Link Specific Data3
+
# 30-31 Link Specific Data3
 
######
 
######
# 32-47 next database record...</pre>
+
# 32-47 next database record...
 +
 
 +
</pre>

Revision as of 00:23, 12 March 2008

#### Written by Dan Damron
#### #373 Private Method Listing ####

def mainStart() ## This is called FIRST, reruns cannot call this.
  #Register Message Interceptor
  @interceptor = Command.new(device_.devid_, -1000, 1, 5, 37)
  @interceptor.params_[2] = device_.devid_.to_s
  SendCommand(@interceptor)
  #Get the PLM Database
  sendGetLink
  #get Child devices
  log('Finding Children..')
  device_.childdevices_.each{|c| $children[device_.childdevices_[c.to_s.to_i].devdata_[12].chomp.lstrip.rstrip] = c.to_s.to_i}
  $children.keys.each{|c| log(c + ' = ' + $children[c].to_s)
  }
  log('reading stored Child configuration:')

  $children.keys.each{|c|
    #Get each Childs configuration
    $state[c] = 0
    getdeviceconfig(c) #

    #the above getdeviceconfig packs $configparams array
    log('Configuration for ' + c + ' = ' + $configparams.inspect.to_s)
  }

  log('********************************************************')
  #get childs actual configuation and status
  $children.keys.each{|c| sendGetChildStatus(c)}
  SndIns()

end
def mainRestart()
  #We have hashes already set up.
  $childdatabases.each_key{|@insteonID|
    $state[@insteonID] = 0
    sendGetChildStatus(@insteonID)}
  SndIns()
end

def setdeviceconfig(insteonid, configurestring)
  @deviceid = $children[insteonid]
  @cmdfrom = device_.devid_
  @cmdto = 4 #general info plugin
  @priority = 1
  @type=1 #command
  @cmdid = 246

  #set up command..
  @cmd = Command.new(@cmdfrom, @cmdto, @priority, @type, @cmdid)
  @cmd.params_[2] = @deviceid.to_s
  @cmd.params_[52] = '59' # Configuration
  @cmd.params_[5] = configurestring
  SendCommand(@cmd)
  #log('SetDeviceConfig:' + configurestring)
  #log('Configuration Saved - will be available on next reload')
end

def getdeviceconfig(insteonid)
  @deviceid = $children[insteonid]
  @configstring = ''
  begin
    @configstring = device_.childdevices_[@deviceid].devdata_[59].to_s
  rescue
    log('Device ID = ' + @deviceid.to_s)
    log($red + 'Error - Child has no configuration'+ $grey)
    log('Setting initial value of "****************"')
    setdeviceconfig(insteonid, ('*' * 16))
    @configstring = '*' * 16
    sendPing(insteonid)
  end
  if @configstring == ''
    $configparams = ['****************']
    log('CAUGHT BLANK RECORD')
    setdeviceconfig(insteonid, ('*' * 16))
    sendPing(insteonid)
  else
    $configparams = @configstring.unpack('a16' * (@configstring.length / 16))
    $devicetemplate[insteonid] = getdevicetemplate($configparams[0][0..1], $configparams[0][2..3])
  end
  #log($yellow + 'getdeviceconfig:' + $configparams.inspect + $grey)
  #add the configuration parameters to the child database
  $childdatabases[insteonid] = $configparams
  #get the device type

end

def sendGetLink()
  #lets just see exactly what is in the PLM database
  param = {'Command' => 'GetLnk'}
  $cmdqueue << param
  SndIns()
end

def sendGetNext()
  param = {'Command' => 'GetNext'}
  if $wAIT == true
    $cmdqueue.insert(1, param)
  else
    $cmdqueue.insert(0,param)
  end
  SndIns()
end

def sendRemoteGetLink(insteonID)
  # Read First ALDB Record
  # a few variables need to be set up here..
  $recordof = insteonID # save the insteon ID
  insID = insteonID.chomp.split('.') # get the seperate bytes
  $remoteDBOffsetMSB = 0x0F # initial offset
  $remoteDBOffsetLSB = 0xF8 # initial LSB offset
  param = {'Command' => 'SndIns',
    'Parameter1' => insID[0], #HB
    'Parameter2' => insID[1], #MB
    'Parameter3' => insID[2], #LB
    'Parameter4' => '0F', #Flags
    'Parameter5' => '28', #Cmd1
    'Parameter6' => "%X" %$remoteDBOffsetMSB #Cmd2 Set MSB Offset
  }
  $cmdqueue << param
  # repeat last param for each byte to read (F8..FF)=first record

  for x in 0..7
    param = {'Command' => 'SndIns',
      'Parameter1' => insID[0], #HB
      'Parameter2' => insID[1], #MB
      'Parameter3' => insID[2], #LB
      'Parameter4' => '0F', #Flags
      'Parameter5' => '2B', #Cmd1 Peek
      'Parameter6' => "%X" %($remoteDBOffsetLSB + x) #Cmd2
    }

    $cmdqueue << param
  end

end

def sendRemoteGetNext(insteonID)
  insID = insteonID.chomp.split('.') # get the seperate bytes
  ### Do NOT forget to check to see if we need to decrease the MSB

  if $remoteDBOffsetLSB == 0x00
    #OffsetMSB needs to be decreased, and LSB needs reset.
    $remoteDBOffsetMSB = $remoteDBOffsetMSB - 1
    $remoteDBOffsetLSN = 0xFF # the next line will decrease this by 8
  end
  # decrease DBOffsetLSB by 0x08
  $remoteDBOffsetLSB = $remoteDBOffsetLSB - 0x08

  for x in 0..7
    param = {'Command' => 'SndIns',
      'Parameter1' => insID[0], #HB
      'Parameter2' => insID[1], #MB
      'Parameter3' => insID[2], #LB
      'Parameter4' => '0F', #Flags
      'Parameter5' => '2B', #Cmd1 Peek
      'Parameter6' => "%X" %($remoteDBOffsetLSB + x) #Cmd2
    }
    #log('sendRemoteGetNet:added to queue:' + param.inspect)
    if $wAIT == true
      $cmdqueue.insert(x + 1, param)
    else
      $cmdqueue.insert(x,param)
    end


  end
end

### Main command parsing routine is EZToDCE
def EZToDCE(param)
  #param contains a hash of EZBridge command structure
  #log($blue + 'Queue:' + $cmdqueue[0].inspect + $grey)
  #log($blue + 'Param:' + param.inspect + $grey)
  #log($blue + 'currentcmd:' + $currentcmd.to_s + $grey)
  #checkWait(param)
  case param['Response']
    # Standard RESPONSES (to commands)
  when 'GetRevision' # Special Response
    log('-----|---------GetRevision:' + param['Parameter1'])

  when 'GetLatLong' # Special Response
    log('-----|---------GetLatLong: Lat=' + param['Lat'] + ', Long=' + param['Long'])

  when 'SetLatLong'
    if param['Parameter1'] == 'True' then
      log('-----|---------SetLatLong: Ok')
    else
      log('-----X---------SetLatLong: FAILED!')
    end
  when 'SetPasswd'

  when 'SetTimeZone'

  when 'GetClock' # Special Response

  when 'SetClock'

  when 'SetNTPServer'

  when 'Upgrade'

  when 'NetCfg'

  when 'Reset'
    #Reset Response

    cmdComplete
    SndIns()
  when 'LstTimers' # Special Response


  when 'ClrTimers'

  when 'AddTimer'

  when 'GetTimer' # Special Response

  when 'SetTimer'

  when 'DelTimer'

  when 'GetVersion' # Special Response

  when 'SndGrp'

  when 'SndIns' # response from SndIns
    ### BUG FOUND ### When the EZBridge receives a command from an EXTERNAL source
    ### ie not from this device, cmdqueue will be nil, and the code below
    ### fails. Have to check against that.
    if $cmdqueue.length > 0
      #First, check the response to make sure the command made it ok.
      if param['Parameter9'].to_i == 6 #Ack received
        #log('Sending to ProcessACK')
        processACK(param)
      else # NACK received - command failed.
        log('Command NACKED')
      end
    else
      #Response received for another device.
      log('Response detected for a command that was not sent by me')
    end
  when 'SndX10'
    log('Response detected for SndX10')
    if param['Parameter5'].to_i == 6 #ack
      log('X10 Command Successfull')

      cmdComplete
      SndIns()
    else
      log('X10 Command FAILED')
      cmdComplete
      SndIns()

    end
  when 'StLnk'

  when 'CancelLnk'

  when 'SetDev'

  when 'RstPLM'
    #Reset Response
    $timeout = 1
    cmdComplete
    SndIns()

  when 'GetLnk'
    if param['Parameter3'].to_i == 6 #ack
      log('GetLnk ACKED')
      #if we get this, we should get a AllLink Record Response next
    else
      log('GetLnk NACKED')
      # The PLM is BLANK
      #have to add records to the PLM here.
      cmdComplete
      ### FINISHED WITH GetLnk
      checkChildRecordsinPLM()
      SndIns()
    end
  when 'GetNext'
    if param['Parameter3'].to_i == 6 #ack
      log('sendGetNext ACKED')
      #if we get this, we should get a AllLink Record Response next
    else
      log('sendGetNext NACKED')
      #we get this when there are no more records
      cmdComplete
      #FINISHED with GetNext
      # if we are here, we are in config mode
      # so, next is to check to make sure the
      # childrens insteon ID is in the PLM
      checkChildRecordsinPLM()
      # now, to make sure that all the records in the PLM are sensed as children
      
      SndIns()
    end

  when 'SetCfg' # response from Setcfg command
    if param['Parameter4'].to_i == 6 #ack
      log('SetCfg Completed')
      cmdComplete
      SndIns()
    else
      log('SetCfg NACKED')
    end
  when 'GetLnkData'

  when 'LEDON'

  when 'LEDOFF'

  when 'MngLnk'
    if param['Parameter12'].to_i == 6
      log('MngLnk => ACK')
    else
      log('MngLnk => NACK')
    end
    cmdComplete
    SndIns()

  when 'GetCfg' # Special Response

  when 'LstMacros' # Special Response

  when 'ClrMacros'

  when 'AddMacro'

  when 'GetMacro' # Special Response

  when 'SetMacro'

  when 'DelMacro'

  when 'LstDevices' # Special Response

  when 'ClrDevices'

  when 'AddDevice'

  when 'GetDevice' # Special Response

  when 'SetDevice'

  when 'DelDevice'

  when 'LstZones'

  when 'ClrZones'

  when 'AddZone'

  when 'GetZone'

  when 'SetZone'

  when 'DelZone'

  when 'AddDevZone'

  when 'DelDevZone'

    # Response Messages
  when 'InsExtMsg'

  when 'InsStdMsg'
    case $currentcmd # if this msg is part of a response, the Insteon Cmd1 will be saved here.
    when 0x0
      #log('REROUTING to processExternalCommand(param)')
      processExternalCommand(param)
    when 0x1 #Assign to Group
      ### This is a broadcast message sent
      # from a PING command
      # or from a StartLink...
      log('Caught Assign to Group Message from Device')
      ### BUG HERE
      #have to check flags to see if this is a broadcast message
      log('Checking if this is a broadcast message')
      log('Flags:' + param['Parameter9'])
      if (param['Parameter9'].hex & 0x80) == 0x80
        log('Message IS BROADCAST')
        #recvComplete
        processDeviceInfo(param)

        # check to see if current cmd is for this broadcast..
        log('Current Command:' + $cmdqueue[0]['Parameter5'])
        if $cmdqueue[0]['Parameter5'] == '10'
          #log('Clearing PING Command')
          $currentcmd = 0
          cmdComplete
          SndIns()
        else
          log('CURRENT CMD IS NOT PING - NOT CLEARING')
        end

      else
        log('Message is NOT Broadcast')
      end
    when 0x2 #Delete from Group
    when 0x10 # PING
      #this is where I catch the InsStdMsg for ping.
      log('Caught PING Message from Device')
      $currentcmd = 1

    when 0x11 # ON
      log('Caught Insteon ON from INTERNAL source')
      insHb = param['Parameter3'] # From
      insMb = param['Parameter4']
      insLb = param['Parameter5']

      insID = insHb + "." + insMb + "." + insLb
      myDevFrom = $children[insID]
      log('Current DIM level:' + param['Parameter11'])

      reportStatus(myDevFrom, hextopercent(param['Parameter11']))

      $currentcmd = 0
      cmdComplete

      SndIns()
    when 0x13 # OFF
      insHb = param['Parameter3'] # From
      insMb = param['Parameter4']
      insLb = param['Parameter5']
      insID = insHb + "." + insMb + "." + insLb
      myDevFrom = $children[insID]
      reportStatus(myDevFrom, 0)

      $currentcmd = 0
      cmdComplete
      #log('EVENT and state SENT!!!.48:[10]=0')
      SndIns()
    when 0x19 # Status Report
      # now to clear the currentcmd and remove command from the queue
      $currentcmd = 0
      cmdComplete

      log('Processing 0x19 Status Report')
      #This is where I get the database delta (in cmd1)
      insHb = param['Parameter3'] # From
      insMb = param['Parameter4']
      insLb = param['Parameter5']
      insID = insHb + "." + insMb + "." + insLb
      #First, to compare the DB Delta with current config.
      #Database Delta...
      delta = param['Parameter10'].to_s
      log($blue + 'Database Delta=' + delta + $grey)
      log($blue + 'Configuration is:' + getdeltafromconfig(insID) + $grey)
      if delta == getdeltafromconfig(insID)
        if $children[insID] != nil
          myDevFrom = $children[insID]
          myDevTo = -1000 #DCE Router
          myPriority = 1
          myType = 2 #Event

          #Send an EVENT to report STATE ONLY if database has not changed
          # AND child exists in pluto
          reportStatus(myDevFrom, hextopercent(param['Parameter11']))
        end
      else
        log('Databse CHANGED -getting remote database')
        #here, I have to WIPE the databse
        # to prepare it for new data
        ### here is where the DAMN CONFIG was reset!!!
        oldconfigstring = $childdatabases[insID][0]
        $childdatabases[insID] = [oldconfigstring]
        log('Setting Database Config')
        $childdatabases[insID][0][6..7] = delta
        savechilddatabases(insID)
        sendRemoteGetLink(insID)
      end
      # finally, to check execute next command...
      SndIns()
    when 0x28 # Set Address MSB
      log('Received SET Address MSB from remote device')
      $currentcmd = 0
      $remoteLinkRecord = ''
      cmdComplete
      SndIns()
    when 0x2B # peek
      ### BUG HERE... have to verify response is a PEEK command
      #response command is stored in parameter10
      if param['Parameter10'].hex == 0x2B # this is the peek command
        cmdComplete
        log('Received PEEK from remote Device! DATA=' + param['Parameter11'])
        checkPeekData(param)
        $currentcmd = 0
        SndIns()
      else
        log('Waiting for remote PEEK response, but got :' + param['Parameter10'])
      end
    else
    end

  when 'X10Msg'
    log($purple + 'X10 Message Received' + $grey)
    if param['Parameter4'].hex == 0x00
      log('This byte is a House/Unit Code')
      hn = param['Parameter3'][0].chr
      ln = param['Parameter3'][1].chr
      $x10byte1 = $X10HouseCodes[hn]
      $x10byte1 += $X10UnitCodes[ln]
      log('Translated X10 House/Unit Code:' + $x10byte1)
    else
      log('This byte is a House/Command Code')
      hn = param['Parameter3'][0].chr
      ln = param['Parameter3'][1].chr
      $x10byte2 = $X10HouseCodes[hn]
      $x10byte2 += $X10CommandCodes[ln]
      log('Translated X10 Command Code:' + $x10byte2)
      log('X10 Command ready to send:' + $x10byte1 + ' ' + $x10byte2)
      case $X10CommandCodes[ln]
      when 'On'
        #Send ON to lmnce
        if $children[$x10byte1] == nil
          log('I do not control this X10 device')
        else
          cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 192)
          cmd.params_[120] = "1"
          SendCommand(cmd)
        end
      when 'Off'
        #Send OFF to lmnce
        if $children[$x10byte1] == nil
          log('I do not control this X10 device')
        else
          cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 193)
          cmd.params_[120] = "1"
          SendCommand(cmd)
        end
      when 'Bright'
        if $children[$x10byte1] == nil
          log('I do not control this X10 device')
        else
          #send a command to set the state + 1
          @curstate = ($state[$x10byte1] / 100) * 32 #get equal 32 steps
          $state[$x10byte1] = ((@curstate + 1) / 32) * 100
          cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 184)
          cmd.params_[76] = $state[$x10byte1].to_s
          cmd.params_[120] = "1"
          SendCommand(cmd)
          #$state[$x10byte1] = ($state[$x10byte1] / 100) * 32
        end
      when 'Dim'
        @curstate = ($state[$x10byte1] / 100) * 32 #get equal 32 steps
        $state[$x10byte1] = ((@curstate - 1) / 32) * 100
        cmd = Command.new($children[$x10byte1].to_i, -1000, 1, 1, 184)
        cmd.params_[76] = $state[$x10byte1].to_s
        cmd.params_[120] = "1"
        SendCommand(cmd)
      when 'All Lights Off'
        log('ALL Lights OFF Command not implemented')
      when 'All Lights On'
        log('All Lights ON Command not implemented')
      when 'Status Request'
        log('Status Request Command not implemented')
      when 'Hail Ack'
        log('Hail Ack Command not implemented')
      end

    end
  when 'InsLnkSts'
    log('InsLnkSts Received')

  when 'BtnRpt'
    log('Button Report Received')
  when 'UsrRst'
    log('User Reset Response Received')
  when 'GrpEvntRpt'
    log('Group Event Report Received')

  when 'LnkData'
    processLnkData(param)
    # Other messages
  when 'PLMTimeout'
    log('PLM Timeout detected.. resetting EZBridge')
    resetcmd = {'Command' => 'Reset'}
    if $wAIT == true
      $cmdqueue.insert(1, resetcmd)
    else
      $cmdqueue.insert(0,resetcmd)
    end
    sleep 15
    $wAIT = false
    SndIns()
  when 'PLMEchoError' # Have not seen this since a1.23
    # error sending command to PLM, reset command and try again
    log('-----XXXXXXX' + param['Response'])
    resetcmd = {'Command' => 'Reset'}
    if $wAIT == true
      $cmdqueue.insert(1, resetcmd)
    else
      $cmdqueue.insert(0,resetcmd)
    end

    sleep 15
    $wAIT = false
    SndIns()
  when 'LongAck'
    log('-----XXXXXXX' + param['Response'])
    # Error - seems to show up after PLMEchoError
    resetcmd = {'Command' => 'Reset'}
    if $wAIT == true
      $cmdqueue.insert(1, resetcmd)
    else
      $cmdqueue.insert(0,resetcmd)
    end
    sleep 15
    $wAIT = false
    SndIns()
  else
    log('-----XXXXXXX UNKNOWN Response Received')
  end

end

### Support routine for EZToDCE
def processLnkData(param)
  #Caught a LnkData Response
  log('LnkData Message Received')
  log(param.inspect)
  if param['Parameter6'] == '00' and param['Parameter7'] == '00'
    log('FOUND X10 DEVICE!!!')
    insteonID = padhex(param['Parameter5'])
  else
    insteonID = padhex(param['Parameter5']) + '.' + padhex(param['Parameter6']) + '.' + padhex(param['Parameter7'])
  end
  group = param['Parameter4']
  recflags = param['Parameter3']
  lnkdata1 = param['Parameter8']
  lnkdata2 = param['Parameter9']
  lnkdata3 = param['Parameter10']
  #pack string to store for PLM Database
  @currentrecord = recflags + group
  @currentrecord += param['Parameter5'] + param['Parameter6'] + param['Parameter7']
  @currentrecord += lnkdata1 + lnkdata2 + lnkdata3

  #Add to plmdatabase
  $plmdatabase << @currentrecord
  log('record Flags:' + recflags)
  #log('PLM database=' +$plmdatabase.inspect)
  if (recflags[0] & 0x80) == 0x80 # Record is in use if true
  end
  if (recflags[0] & 0x40) == 0x40 # Controller if true
    log('Controller')
  else
    log('Responder')
  end

  log('Insteon ID:' + insteonID + ', Group:' + group)

  cmdComplete
  sendGetNext()

end
### Support Routine for EZToDCE
def processExternalCommand(param)
  #there is no current command
  # THIS IS COMING FROM AN OUTSIDE SOURCE
  #EG: Manually turning Light Switch On/Off
  # process this command.
  # Note, this is a standard message
  ### have to check here if child is mine!

  # This is where I have to check for a broadcast command..
  #if so, search the child databases for responders,
  #and fire events for each responder.
  #Message flag is in parameter9 Group command 0xCx (All-Link Broadcast Message Pg 42.)
  #Group is in parameter8
  #From InsteonID is parameters 3, 4, 5
  if (param['Parameter9'].hex & 0xC0) == 0xC0 # Message is Broadcast
    log('Rerouting to processBroadcastMessage')
    processBroadcastMessage(param)
  else
    log('Process External Command:')
    log('Param:' + param.inspect)

    # there is no ack here. Simply Send COMMANDS back to DCE
    # and Complete the recv..
    case param['Parameter10'].hex #this is the command
    when 0x01 #Assign to Group
      log('Caught EXTERNAL Assign to Group')
      processDeviceInfo(param)
      recvComplete
    when 0x02 #Delete from Group
      log('Caught EXTERNAL Delete from Group')
      recvComplete
    when 0x10 # PING
      log('Caught EXTERNAL Insteon PING result')
      recvComplete


    when 0x11 #ON
      log('Caught EXTERNAL Insteon ON command result')
      #on level is in cmd2
      insHb = param['Parameter3'] # From
      insMb = param['Parameter4']
      insLb = param['Parameter5']
      insID = insHb + "." + insMb + "." + insLb
      log('From:' +insID)
      log('Device:' + $children[insID].to_s)
      myDevFrom = $children[insID]
      # check to see if I own child
      if myDevFrom == nil
        log('I do not control this device.')
      else
        reportStatus(myDevFrom, hextopercent(param['Parameter11']))
        $currentcmd = 0
      end
      recvComplete



    when 0x13 #OFF
      log('Caught EXTERNAL Insteon OFF result')
      #on level is in cmd2
      insHb = param['Parameter3'] # From
      insMb = param['Parameter4']
      insLb = param['Parameter5']
      insID = insHb + "." + insMb + "." + insLb
      myDevFrom = $children[insID]
      if myDevFrom == nil
        log('I do not control this device.')
      else

        reportStatus(myDevFrom, 0)

        $currentcmd = 0
        #log('EVENT and state SENT!!!.48:[10]=0')
      end
      recvComplete
    when 0x15; log('Caught EXTERNAL Insteon Brighten Result')
    when 0x16; log('Caught EXTERNAL Insteon DIM Result')
    when 0x24; log('Caught EXTERNAL Insteon DO EE READ')
    when 0x28; log('Caught EXTERNAL Insteon SET ADDRESS MSB')
    when 0x29; log('Caught EXTERNAL Insteon POKE')
    when 0x2A; log('Caught EXTERNAL Insteon POKE EXTENDED')
    when 0x2B; log('Caught EXTERNAL Insteon PEEK')
    when 0x2C; log('Caught EXTERNAL Insteon PEEK INTERNAL')
    when 0x2D; log('Caught EXTERNAL Insteon POKE INTERNAL')
    else
      log('Unknown EXTERNAL Insteon Command.')
    end
  end
end
### Support Routine for EZToDCE
def processACK(param)
  #log('In ProcessACK: Param7:' + param['Parameter7'])
  #log('CurrentCmd=' + $currentcmd.to_s)
  case param['Parameter7'].hex #Received an ack to THIS command
  when 0x1 #Assign to Group
    log('Got Assign to Group ACK')
    $currentcmd = 0x01
    $cmdqueue[0]['Command'] = 'InsStdMsg'
    #processDeviceInfo(param)
    #cmdComplete
  when 0x2 #Delete from Group
  when 0x10 # PING
    log('Got PING ACK')
    #cmdComplete
    $currentcmd = 0x1
    $cmdqueue[0]['Command'] = 'InsStdMsg'
  when 0x11 #ON
    $currentcmd = 0x11
    $cmdqueue[0]['Command'] = 'InsStdMsg'
  when 0x13 #OFF
    $currentcmd = 0x13
    $cmdqueue[0]['Command'] = 'InsStdMsg'
  when 0x15 #Bright
    $currentcmd = 0x15
    $cmdqueue[0]['Command'] = 'InsStdMsg'
  when 0x16 #DIM
    $currentcmd = 0x16
    $cmdqueue[0]['Command'] = 'InsStdMsg'
  when 0x17 #Start Manual Change
  when 0x18 #Stop Manual Change
  when 0x19 #Status Request
    # Status Request Acked - get ready for InsStdMsg
    $currentcmd = 0x19
    # change cmd to reflect InsStdMsg
    $cmdqueue[0]['Command'] = 'InsStdMsg'
  when 0x24
    log('Caught ACK for Insteon DO EE READ')
    $currentcmd = 0x24
    $cmdqueue[0]['Command'] = 'InsStdMsg'
  when 0x28
    log('Caught ACK for Insteon SET ADDRESS MSB')
    $currentcmd = 0x28
    $cmdqueue[0]['Command'] = 'InsStdMsg'

  when 0x29
    log('Caught ACK for Insteon POKE')
    $currentcmd = 0x29
    $cmdqueue[0]['Command'] = 'InsStdMsg'

  when 0x2A
    log('Caught ACK for Insteon POKE EXTENDED')
    $currentcmd = 0x2A
    $cmdqueue[0]['Command'] = 'InsStdMsg'

  when 0x2B
    #log('Caught ACK for Insteon PEEK')
    $currentcmd = 0x2B
    $cmdqueue[0]['Command'] = 'InsStdMsg'

  when 0x2C
    log('Caught ACK for Insteon PEEK INTERNAL')
    $currentcmd = 0x2C
    $cmdqueue[0]['Command'] = 'InsStdMsg'

  when 0x2D
    log('Caught ACK for Insteon POKE INTERNAL')
    $currentcmd = 0x2D
    $cmdqueue[0]['Command'] = 'InsStdMsg'

  else
    log('Unknown Insteon Cmd1')
  end
end


def checkPeekData(param)

  $remoteLinkRecord += param['Parameter11'].hex.chr
  log('CURRENT REMOTE RECORD IS:')
  debug($remoteLinkRecord)
  if $remoteLinkRecord.length == 8
    log('REMOTE RECORD COMPLETE!')
    processRemoteRecord(param)
    $remoteLinkRecord = ''
  end
end


def processRemoteRecord(param)
  #have to find MY address
  insHb = param['Parameter3'] # From
  insMb = param['Parameter4']
  insLb = param['Parameter5']
  insID = padhex(insHb) + "." + padhex(insMb) + "." + padhex(insLb)

  log('Processing remote Record below:')

  @flags = "\nFrom Device:" + insID + "\nFlags:\n"

  if ($remoteLinkRecord[0] & 0x02) == 0x02 # High water mark
    @flags += "Not the last record\n"
  else
    @flags += "This IS the last record\n"
  end

  if ($remoteLinkRecord[0] & 0x80) == 0x80 # Record is in use
    @flags += "Record In Use\n"
    if ($remoteLinkRecord[0] & 0x40) == 0x40 # Controller/Responder
      @flags += "I am a Controller of "
    else
      @flags += "I am a Responder of "
    end
    @insteonID = padhex("%X" %$remoteLinkRecord[2]) + '.'
    @insteonID += padhex("%X" %$remoteLinkRecord[3]) + '.'
    @insteonID += padhex("%X" %$remoteLinkRecord[4])

    @group = "%X" %$remoteLinkRecord[1]
    @flags += @insteonID + " Group:" + @group
    @work = padhex("%X" %$remoteLinkRecord[0]) #Control byte
    @work += padhex("%X" %$remoteLinkRecord[1]) # Group
    @work += padhex("%X" %$remoteLinkRecord[2]) # ID HB
    @work += padhex("%X" %$remoteLinkRecord[3]) # ID MB
    @work += padhex("%X" %$remoteLinkRecord[4]) # ID LB
    @work += padhex("%X" %$remoteLinkRecord[5]) # Data1
    @work += padhex("%X" %$remoteLinkRecord[6]) # Data2
    @work += padhex("%X" %$remoteLinkRecord[7]) # Data3
    log('adding to:' + insID)
    log('Value:' + @work)
    $childdatabases[insID] << @work #add it to the database
    # log('Current Database:' + $childdatabases.inspect)
    #now to save the database to configuration.
    savechilddatabases(insID)
    # Now to check to see if the child exists as a record
    if $childdatabases[@insteonID] == nil
      log('InsteonID is NEW, adding Child database entry')
      $childdatabases[@insteonID] = ['****************']
      $rerun = true
      sendAddtoPLM(@insteonID)
      sendPing(@insteonID)
    else
      log('InsteonID:' + @insteonID.to_s + 'seems to exist in child databases')
      log('CDB:' + $childdatabases.inspect)

    end
  else
    @flags += "Record NOT in use\n"
  end
  log($aqua + @flags + $grey)
  log2(@flags)
  if ($remoteLinkRecord[0] & 0x02) == 0x02
    sendRemoteGetNext(insID)
  end
end

def savechilddatabases(insteonID)
  #This takes the $childdatabase hash+array and encodes it to
  # save it as a string.
  @work = ''
  #log($yellow + 'SaveChildDatabases::nitems:' + $childdatabases[insteonID].nitems.to_s)
  #log($childdatabases[insteonID].inspect + $grey)
  $childdatabases[insteonID].each{|record|
    @work += record
  }

  #now to save the string...
  setdeviceconfig(insteonID, @work)

end
def sendPing(insteonID)
  insID = insteonID.split('.')
  param = {'Command' => 'SndIns',
    'Parameter1' => insID[0],
    'Parameter2' => insID[1],
    'Parameter3' => insID[2],
    'Parameter4' => '0F',
    'Parameter5' => '10', #ID Request
    'Parameter6' => '00'}
  $cmdqueue << param
  log('PING Sent!')
end

def getdevicetemplate(cat, subcat)

  log('Entered getdevicetemplate, Cat=' + cat.to_s + ', subcat = ' + subcat.to_s)
  @templid = 0
  case cat.hex
  when 0x0 # Generalized Controllers
    case subcat.hex
    when 0x04; log('Found ControLinc [2430]')
    when 0x05; log('Found RemoteLinc [2440]')
    when 0x06; log('Found Icon Tabletop Controller [2830]')
    when 0x09; log('Found SignaLinc RF Signal Enhancer [2442]')
    when 0x0A; log('Found Balboa Instruments Poolux LCD Controller')
    when 0x0B; log('Found Access Point [2443]')
    when 0x0C; log('Found IES Color Touchscreen')
    end
  when 0x01 # Dimmable Lighting Control
    # all these devices are associated with Template 38
    # Light Switch (dimmable)
    @templid = 38
    case subcat.hex
    when 0x00; log('Found LampLinc V2 [2456D3]')
    when 0x01; log('Found SwitchLinc V2 Dimmer 600W [2476D]')
    when 0x02; log('Found In-LineLinc Dimmer [2475D]')
    when 0x03; log('Found Icon Switch Dimmer [2876D]')
    when 0x04; log('Found SwitchLinc V2 Dimmer 1000W [2476DH]')
    when 0x06; log('Found LampLinc 2-pin [2456D2]')
    when 0x07; log('Found Icon LampLinc V2 2-pin [2456D2]')
    when 0x09; log('Found KeypadLinc Dimmer [2486D]')
    when 0x0A; log('Found Icon In-Wall Controller [2886D]')
    when 0x0D; log('Found SocketLinc [2454D]')
    when 0x13; log('Found Icon SwitchLinc Dimmer for Lixar/Bell Canada [2676D-B]')
    when 0x17; log('Found ToggleLinc Dimmer [2466D]')
    end
  when 0x02 # Switched Lighting Control
    # all these devices are associated with Template 37
    # Light Switch (ON/OFF)
    @templid = 37
    case subcat.hex

    when 0x09; log('Found ApplianceLinc [2456S3]')
    when 0x0A; log('Found SwitchLinc Relay [2476S]')
    when 0x0B; log('Found Icon On Off Switch [2876S]')
    when 0x0C; log('Found Icon Appliance Adapter [2856S3]')
    when 0x0D; log('Found ToggleLinc Relay [2466S]')
    when 0x0E; log('Found Switchlinc Relay Countdown Timer [2476ST]')
    when 0x10; log('Found In-LineLinc Relay [2475D]')
    when 0x13; log('Found Icon SwitchLinc Relay for Lixar/Bell Canada [2676R-B]')
    end
  when 0x03 # Network Bridges
    case subcat.hex
    when 0x01; log('Found PowerLinc Serial [2414S]')
    when 0x02; log('Found PowerLinc USB [2414U]')
    when 0x03; log('Found Icon PowerLinc Serial [2814S]')
    when 0x04; log('Found Icon PowerLinc USB [2814U]')
    when 0x05; log('Found Smartlabs Power Line Modem Serial [2412S]')
    end
  when 0x04 # Irrigation Control
    # all these devices are associated with Template 1780
    # Standard Irrigation Sprinkler
    @templid = 1780
    case subcat.hex

    when 0x00; log('Found Simplehomenet EZRain1 Sprinkler Controller')
    end
  when 0x05 # Climate Control
    case subcat.hex
    when 0x00; log('Found Broan SMSC080 Exhaust Fan')
    when 0x01; log('Found Simplehomenet EZTherm')
    when 0x02; log('Found Broan SMSC110 Exhaust Fan')
    when 0x03; log('Found Venstar RF Thermostat Module')
    when 0x04; log('Found Simplehomenet EZStat Thermostat')
    end
  when 0x06 # Pool and Spa Control
    case subcat.hex
    when 0x00; log('Found Simplehomenet EZPool')
    end
  when 0x07 # Sensors and Actuators
    case subcat.hex
    when 0x00
    end
  when 0x08 # Home Entertainment
    case subcat.hex
    when 0x00
    end
  when 0x09 # Energy Management
    case subcat.hex
    when 0x00
    end
  when 0x0A # Built-In Appliance Control
    case subcat.hex
    when 0x00
    end
  when 0x0B # Plumbing
    case subcat.hex
    when 0x00
    end
  when 0x0C # Communication
    case subcat.hex
    when 0x00
    end
  when 0x0D # Computer Control
    case subcat.hex
    when 0x00
    end
  when 0x0E # Window Coverings
    case subcat.hex
    when 0x00
    end
  when 0x0F # Access Control
    case subcat.hex
    when 0x00
    end
  when 0x10 # Security, Health, and Safety
  when 0x11 # Surveillance
  when 0x12 # Automotive
  when 0x13 # Pet care
  when 0x14 # Toys
  when 0x15 # Timekeeping
  when 0x16 # Holiday
  end
  return @templid
end

def processDeviceInfo(param)
  ### temporary
  ### 12-24-07 Adding Device Template compatibility..
  #have to find MY address
  insHb = param['Parameter3'] # From
  insMb = param['Parameter4']
  insLb = param['Parameter5']

  insID = padhex(insHb) + "." + padhex(insMb) + "." + padhex(insLb)
  #set the devicecat and device subcat in the childdatabases
  # 0-1 Device Category
  # 2-3 Device SubCategory
  # 4-5 Device Firmware
  log('proccessDeviceInfo:Insteon ID' + insID)
  $childdatabases[insID][0][0..1] = param['Parameter6']
  $childdatabases[insID][0][2..3] = param['Parameter7']
  $childdatabases[insID][0][4..5] = param['Parameter8']
  savechilddatabases(insID)
  log('InsteonID: ' + insID)
  #log('Child Config AFTER update:' + $childdatabases[insID][0].to_s)
  log($yellow)
  @template = getdevicetemplate(param['Parameter6'], param['Parameter7'])
  $devicetemplate[insID] = @template
  log('Template ID:' + @template.to_s)
  ### eventually, open a XML configuration script?
  ### or read saved data from mysql?
  ### most likely save this information to sql with device.
  ### eventually, IPKDB will be available to ping.
  log('for Insteon ID:' + insID)
  log($grey)
end

def recvComplete
  # Clears the wait flag, but does not remove a command from the queue
  $wAIT = false
  log($green + "Receive Completed. Checking command queue" + $grey)
  if $cmdqueue.nitems > 0 then
    log("Queue:" + $aqua + $cmdqueue.nitems.to_s + $grey + " : executing next command")
    SndIns()
  else
    log($yellow + 'Queue Empty.' + $grey)
    if $rerun == true
      log('RERUN=TRUE, RESTARTING')
      $rerun = false
      mainRestart()
    else
      log('RERUN Not needed. Checking if reported..')
      #report Child devices here.
      if $reported == false
        log('Reporting Child Devices')
        @work = ""
        $childdatabases.each_key{
          |insteonID|
          log('Child:' + insteonID)
          log('Config:' + $childdatabases[insteonID].inspect)
          @template = $devicetemplate[insteonID]
          @work += insteonID + "\t\t\t" + @template.to_s + "\t\n"
        }
        log(@work)
        cmd = Command.new(device_.devid_, -1001, 1, 2, 54)
        cmd.params_[13] = @work
        SendCommand(cmd)

        $reported = true
      else
        log('report not needed')
      end
    end

  end
end
def removecurrentcommand
  #get the current child
  log('in RemoveCurrentCommand')
  log('Current Command:' + $cmdqueue[0].inspect)
  #id is in param123
  @id = $cmdqueue[0]['Parameter1']
  @id += '.' + $cmdqueue[0]['Parameter2']
  @id += '.' + $cmdqueue[0]['Parameter3']
  log('ID=' + @id)
  #now to remove from child and PLM databases
  removefromchild(@id)
  removefromplm(@id)
  cmdComplete
end
def cmdComplete
  # Clears the wait flag, and removes the command from the queue.
  $wAIT = false
  $resetNext = 0
  $cmdqueue.delete_at(0)
  # now that THAT command is completed, check to see if there is
  # another command ready to transmit.
  log($green + "Command Completed." + $grey)
end
def checkWait(param)
  #Checks for response from current command.
  if $cmdqueue[0] != nil
    if $wAIT == true
      #log('CW:waiting for command to complete')
    else
      #log('CW:reports clear')
    end
  else
    log('------:)----checkWait: command queue is emtpy')
    if $wAIT == true #this should never happen
      log('------:(XXX-CheckWait: TRUE')
    end
  end
end

def plmparse(value)
  #THIS ROUTINE REPLACES parsestring()
  #this routine will PARSE the incoming stream into valid messages
  # value is the complete command
  param = {}
  #here is a special case, the PLM seems to lock up.
  if value == 0x15.chr
    log('The PLM stopped responding')
    log('Please unplug it, and plug it back in')
    log('and do a quick reload router.')

  end
  while value.length > 2
    case value[1]
    when 0x62 # Special case, need to look at flags
      if (value[5] & 0x10) == 0x10 # check for extended flag
        cmdlen = 23
      else
        cmdlen = 9
      end
      param['Response'] = 'SndIns'
    when 0x50; cmdlen = 11; param['Response'] = 'InsStdMsg'
    when 0x51; cmdlen = 25; param['Response'] = 'InsExtMsg'
    when 0x68; cmdlen = 4 #Set Insteon ACK Message Byte
    when 0x71; cmdlen = 5 #Set Insteon ACK Message Two Bytes
    when 0x70; cmdlen = 4 #Set Insteon NACK Message Byte
    when 0x63; cmdlen = 5; param['Response'] = 'SndX10'
    when 0x52; cmdlen = 4; param['Response'] = 'X10Msg'
    when 0x61; cmdlen = 6; param['Response'] = 'SndGrp'
    when 0x56; cmdlen = 7; param['Response'] = 'GrpEvntRpt'
    when 0x58; cmdlen = 3 #All-Link Cleanup Status Report
    when 0x64; cmdlen = 5; param['Response'] = 'StLnk'
    when 0x65; cmdlen = 3; param['Response'] = 'CancelLnk'
    when 0x53; cmdlen = 10; param['Response'] = 'InsLnkSts'
    when 0x69; cmdlen = 3; param['Response'] = 'GetLnk'
    when 0x6A; cmdlen = 3; param['Response'] = 'GetNext'
    when 0x6C; cmdlen = 3 #Get All-Link Record for Sender
    when 0x57; cmdlen = 10; param['Response'] = 'LnkData'
    when 0x6F; cmdlen = 12; param['Response'] = 'MngLnk'
    when 0x67; cmdlen = 3; param['Response'] = 'RstPLM'
    when 0x6B; cmdlen = 4; param['Response'] = 'SetCfg'
    when 0x60; cmdlen = 9; param['Response'] = 'GetVersion'
    when 0x66; cmdlen = 6 #Set Host Device Category
    when 0x72; cmdlen = 3 # RF Sleep
    when 0x54; cmdlen = 3; param['Response'] = 'BtnRpt'
    when 0x6D; cmdlen = 3; param['Response'] = 'LEDON'
    when 0x6E; cmdlen = 3; param['Response'] = 'LEDOFF'
    else

      log('ERROR IN PLMPARSE- Unknown Command')
      debug(value)

      return ''
    end

    #Now we know the length the command should be, see if we have it.
    #log('waiting for ' + cmdlen.to_s + ' characters...')
    #log('length of current input is ' + value.length.to_s)
    if value.length >= cmdlen
      #log('GOT whole response')
      #Yes, we have the whole command, Pack it in param
      for byt in 1..cmdlen
        param['Parameter' + byt.to_s] = padhex("%X" %value[byt - 1])
      end
      #now remove it from the string..
      value = value.slice(cmdlen, value.length - cmdlen)
      #Send it off for parsing
      #log('Sending to EZToDCE:' + param.inspect.to_s)
      EZToDCE(param)
    else
      #log('Still waiting...')
      #no, we have NOT received the whole command.

    end
  end
  return value
end

def rawX10(value)

  x10MSN = $X10HouseCodes.index[value[0..0]]
  x10LSN = $X10UnitCodes.index[value[1..1]]
  return x10MSN + x10LSN
end

def X10Flag(value)
  return + $X10CommandCodes.index[Value] + '0'
end

def SndIns
  # create a new PLM command for SndIns
  if $wAIT == false
    #log('SndIns:currentcmd=' + $currentcmd.to_s)

    if $cmdqueue.nitems > 0
      log("SndIns:Queue:" + $aqua + $cmdqueue.nitems.to_s + $grey)
      #log('SndIns:' + $cmdqueue.inspect)
      param = $cmdqueue[0]
      ### have to figure out the command byte 2 here
      work = '02'.hex.chr + plmcommand(param)
      ### PLM command compilation
      for loop in 2..param.keys.nitems
        @dummy = param['Parameter' + (loop - 1).to_s].to_s
        work+= @dummy.hex.chr
      end
      conn_.Reconnect()
      debugout(work)
      conn_.Send(work)
      #sleep 0.1
      $wAIT = TRUE
    else
      log($yellow + 'Queue Empty.' + $grey)
      if $rerun == true
        log('RERUN=TRUE, RESTARTING')
        $rerun = false
        mainRestart()
      else
        log('RERUN Not needed')
        if $reported == false
          log('Reporting Child Devices')
          @work = ""
          $childdatabases.each_key{
            |insteonID|
            log('Child:' + insteonID)
            log('Config:' + $childdatabases[insteonID].inspect)
            @template = $devicetemplate[insteonID]
            @work += insteonID + "\t\t\t" + @template.to_s + "\t\n"
          }
          log(@work)
          cmd = Command.new(device_.devid_, -1001, 1, 2, 54)
          cmd.params_[13] = @work
          SendCommand(cmd)

          $reported = true
        else
          log('report not needed')
        end
      end

    end
  else
    log('X-----------SndIns: Waiting for response to:' + $cmdqueue[0]['Command'].to_s)
    log('X-----------SndIns: Current Queue Length:' + $cmdqueue.nitems.to_s)
  end
end
def plmcommand(param)
  ### this returns the proper Byte2 for the command.
  case param['Command']
  when 'GetVersion'; return 0x60.chr
  when 'SndIns'; return 0x62.chr
  when 'SndGrp'; return 0x61.chr
  when 'SndX10'; return 0x63.chr
  when 'GetLnk'; return 0x69.chr
  when 'GetNext'; return 0x6A.chr
  when 'BtnRpt'; return 0x54.chr
  when 'GetCfg'; return 0x73.chr
  when 'StLnk'; return 0x64.chr
  when 'CancelLnk'; return 0x65.chr
  when 'MngLnk'; return 0x6F.chr
  when 'RstPLM'; return 0x67.chr
  when 'SetCfg'; return 0x6B.chr
  when 'LEDON'; return 0x6D.chr
  when 'LEDOFF'; return 0x6E.chr
    ## hack
  when 'InsStdMsg'
    log('ERROR:PLMCommand encountered a COMMAND of INSSTDMSG')
    break
    return 0x62.chr
  end
end

def debug(text)
  work = 'DEBUG:'

  for c in 1..text.length
    work += padhex("%X" %text[c-1]) + ' '
  end
  log($yellow + work + "Length:" + text.length.to_s + $grey)
end
def debugout(text)
  work = 'out:'

  for c in 1..text.length
    work += padhex("%X" %text[c-1]) + ' '
  end
  log($green + work + "Length:" + text.length.to_s + $grey)
end
def debugin(text)
  work = 'IN:'

  for c in 1..text.length
    work += padhex("%X" %text[c-1]) + ' '
  end
  log($red + work + "Length:" + text.length.to_s + $grey)
end

def padhex(hex)
  if hex.length==1
    hex = "0" + hex
  end
  return hex
end

def percenttohex(level)
  # convert from percent to byte
  return "%X" %((level.to_i * 2.55)).to_i
end

def hextopercent(level)
  return ((level.hex.to_i / 2.55)).to_i
end

def log(line)
  $log = File.open("/var/log/pluto/" + device_.devid_.to_s + "_Generic_Serial_Device.log", "a")
  $log.puts "(***):" + line.to_s
  $log.close
end
def log2(line)
  #this will send a message out the the orbiters..
  #/usr/pluto/bin/MessageSend localhost 0 20 1 809 9 "Text to Display" 70 "alert" 182 "30" 251 "??"
  cmd = Command.new(device_.devid_, -1000, 1, 1, 809)
  cmd.params_[9] = line #text to display
  cmd.params_[70] = 'PLMMessage' #Token
  cmd.params_[182] = '10' #Timeout in seconds
  cmd.params_[251] = '??'
  SendCommand(cmd)
end
def checkChildRecordsinPLM()
  log('Entered CheckChildRecordsinPLM')
  # log('In CheckChildRecordsinPLM')
  # time to verify all children are in the PLM
  #
  # log('Total PLM Records:' + $plmdatabase.nitems.to_s)
  $plmdatabase.each{|record|
    log('Record: = '+ getIIDfromRecord(record) + ' Group:' + getGroupfromRecord(record))
    log('checking to see if it needs to be added as a child...')
    if existsinchild(getIIDfromRecord(record)) == false
        
      log(getIIDfromRecord(record) + ' needs to be added to the child database')
      addtochild(getIIDfromRecord(record))
    end
  }

  $childdatabases.each_key {|child|
    if existsinplm(child) == false
      log(child + ' needs to be added to PLM')
      sendAddtoPLM(child)
    else
      log(child + ' exists in PLM')
    end

    #now to scan the childs database
    for record in 1..($childdatabases[child].nitems - 1)
      @test = $childdatabases[child][record]
      if existsinplm(getIIDfromRecord(@test)) == false
        log(getIIDfromRecord(@test) + ' needs to be added to PLM')
        sendAddtoPLM(getIIDfromRecord(@test))
      else
        log(getIIDfromRecord(@test) + ' exists in PLM')
      end
      #Also check to see if it needs to be added in the childdatabases
    end
  }

end
def existsinplm(insteonid)
  result = false
  $plmdatabase.each{|record|
    #log(insteonid + '==' + getIIDfromRecord(record))
    if insteonid == getIIDfromRecord(record)
      result = true
    end
  }
  return result
end
def existsinchild(insteonid)
  log('ExistsinChild:InsteonID:' + insteonid)
  result = false
  $childdatabases.each_key{|record|
    if insteonid == record
      result = true
    end
  }
  log('ExistsinChild result:FALSE') if result == false
  log('ExistsinChild result:TRUE') if result == true
  return result
end
def addtochild(insteonID)
  log('addtochild Routne called')
  log('Adding ' + insteonID + ' to the child database...')
  if insteonID.length == 2 then
    log('Child is X10')
    $state[insteonID] = 0
  else
    log('Child is Insteon')
    $childdatabases[insteonID] = ['****************']
    sendPing(insteonID)
    $rerun = true
  end
end
def removefromchild(insteonID)
  log('Removing ' + insteonID + ' from child database')
  $childdatabases.delete(insteonID)
  $state.delete(insteonID)
end
def removefromplm(insteonID)
  log('Removing from plm')
  $plmdatabase.each{|record|
    #log(insteonid + '==' + getIIDfromRecord(record))
    if insteonID == getIIDfromRecord(record)
      debug(record)
      log('Found Record, Deleting')
      $plmdatabase.delete(record)
      
      #now, we have to remove it from the device.
      param = {'Command' =>'MngLnk',
        'Parameter1' => '80', #DELETE
        'Parameter2' => record[0..1], #control byte
        'Parameter3' => record[2..3], #group
        'Parameter4' => record[4..5],#HB
        'Parameter5' => record[6..7],#MB
        'Parameter6' => record[8..9],#LB
        'Parameter7' => record[10..11],#data1
        'Parameter8' => record[12..13],#data2
        'Parameter9' => record[14..15] #data3
        
      }
      log(param.inspect)
      $cmdqueue << param
    end
  }
end
def sendAddtoPLM(insteonID)
  log('Adding ' + insteonID + ' to the PLM database...')
  #This adds a record into the PLM
  @insID = insteonID.split('.')
  param = {'Command' => 'MngLnk',
    'Parameter1' => '40', #control code -- add new record as Controller
    'Parameter2' => 'C2', #All Link Record Flags AKA Record Control Byte
    'Parameter3' => '01', #All Link Group
    'Parameter4' => @insID[0], #HB
    'Parameter5' => @insID[1], #MB
    'Parameter6' => @insID[2], #LB
    'Parameter7' => '01', #Link Data 1 ON-Level
    'Parameter8' => '01', #Link Data 2 Ramp Rate
    'Parameter9' => 'FF'} #Link Data 3 not used
  if $wAIT == true
    $cmdqueue.insert(1, param)
  else
    $cmdqueue.insert(0, param)
  end

  SndIns()
end

def getIIDfromRecord(recordstring)
  #this extracts the insteonID string from the record.
  #log('getIIDfromRecord::recordstring:' + recordstring)
  @idhb = recordstring[4..5]
  @idmb = recordstring[6..7]
  @idlb = recordstring[8..9]
  @result = @idhb + '.' + @idmb + '.' +@idlb
  #log('GetIIDfromRecord: Found ID:' + @result)
  return @result
end

def processBroadcastMessage(param)
  #search the child databases for responders,
  #and fire COMMANDS for each responder. 06Feb08
  #and fire events for each responder.XXXXXXXXXXXXX
  #Message flag is in parameter9 Group command 0xCx (All-Link Broadcast Message Pg 42.)
  #Group is in parameter8
  #From InsteonID is parameters 3, 4, 5
  group = param['Parameter8']
  from = padhex(param['Parameter3']) + '.'
  from += padhex(param['Parameter4']) + '.'
  from += padhex(param['Parameter5'])
  log('Looking for ' + from + ' Group:' + group)
  #Ok, now have to search child databases for from AND group AND responder
  $childdatabases.each_key{|child|
    #log('Searching:' + child)
    for rec in 1..($childdatabases[child].nitems - 1)
      record = $childdatabases[child][rec]
      if getIIDfromRecord(record) == from # First, look for Insteon ID
        #log('Found ID')
        if getGroupfromRecord(record) == group #next, Group
          #log('Found Group')
          if isResponderRecord(record) # is a responder?
            #log('Found Responder')
            #figure out the child devicenum
            from = $children[child]
            #figure out the command
            case param['Parameter10'].hex
            when 0x11 #on
              reportStatus(from, 100)
            when 0x13 #off
              reportStatus(from, 0)
            when 0x17 #dim/brighten -ignore
              level = 0
            when 0x18 # STOP dim/brighten - sendgetstatus
              level = 0
              sendGetChildStatus(child)
            else
              level = 0
              log('Command is other than ON/OFF/Dim/Brighten')
            end
          end
        end
      end
    end
  }
end

def reportStatus(from, level)
  log('From:' + from.to_s)
  log('current State:' + $state[from].to_s)
  log('Wanted State:' + level.to_s)
  case $state[from]
  when 0
    if level >=1
      cmd = Command.new(from, from, 1, 1, 192) #on
      cmd.params_[120] = "1"
      SendCommand(cmd)
      cmd = Command.new(from, from, 1, 1, 184)
      cmd.params_[76] = level.to_s
      cmd.params_[120] = "1"
      SendCommand(cmd)
    end
  when 100
    if level >= 1
      cmd = Command.new(from, from, 1, 1, 184)
      cmd.params_[76] = level.to_s
      cmd.params_[120] = "1"
      SendCommand(cmd)
    else
      cmd = Command.new(from, from, 1, 1, 193) # off
      cmd.params_[120] = "1"
      SendCommand(cmd)
    end
  else
    if level == 100
      cmd = Command.new(from, from, 1, 1, 193) #off
      cmd.params_[120] = "1"
      SendCommand(cmd)
      cmd = Command.new(from, from, 1, 1, 192) # on
      cmd.params_[120] = "1"
      SendCommand(cmd)
    end
    cmd = Command.new(from, from, 1, 1, 184) #SetLevel
    cmd.params_[76] = level.to_s
    cmd.params_[120] = "1"
    SendCommand(cmd)
  end
  log('ReportStatus: device:' + from.to_s + ' Status:' + level.to_s)
  $state[from] = level

end

def isResponderRecord(recordstring)
  work = recordstring[0..1].hex
  if (work & 0x40) == 0x40 #check bit 6
    result = false #signifies Controller record
  else
    result = true #signifies Responder record
  end
  return result
end

def getGroupfromRecord(recordstring)
  #this extracts the GROUP from the record.
  if recordstring == nil
    return '00'
  else
    return recordstring[2..3]
  end
end
def getdeltafromconfig(insteonID)
  #This returns the delta from the child.
  @work = $childdatabases[insteonID][0] # the settings stored in [0]
  if @work == nil
    return '00'
  else
    return @work[6..7]
  end
end
def sendGetChildStatus(insteonID)
  #log('sendGetChildStatus Called')
  if insteonID.length != 2 #X10 device
    @insID = insteonID.split('.')
    param = {'Command' => 'SndIns',
      'Parameter1' => @insID[0],
      'Parameter2' => @insID[1],
      'Parameter3' => @insID[2],
      'Parameter4' => '0F', #flags
      'Parameter5' => '19', #Status Request
      'Parameter6' => '00'} #not used.
    $cmdqueue << param
    SndIns()
    #Returned response will have cmd1 = DBDelta
    #Returned response will have cmd2 = ON-Level
  else
    log('X10 does not report status')
  end
end


# time to define a structure to save the raw data in hex
# starts at [0]
# Bytes Meaning
# 0-1 Device Category
# 2-3 Device SubCategory
# 4-5 Device Firmware
# 6-7 Database Delta
# 8-9 reserved
# 10-11 reserved
# 12-13 reserved
# 14-15 reserved
###### First database record below (in same format its read from the device)
###### This is the same format as an ALL-Link Record Response from the PLM
###### (0x57) bytes 3..10
# 16-17 record control byte
# 18-19 Group
# 20-21 ID HB
# 22-23 ID MB
# 24-25 ID LB
# 26-27 Link Specific Data1
# 28-29 Link Specific Data2
# 30-31 Link Specific Data3
######
# 32-47 next database record...