See END OF THREAD for most current code.
Here is my beta code for EZBridge. This code works fairly well. It's a far cry from my previous attempt(Gimme a break, I was learning Ruby at the same time, and still am).
I have implemented a cmdqueue to queue commands so I can receive the responses in a timely manner.
I still have ONE SMALL question, I hope someone here can answer..
I process the Receive command for Child: all Ok.
I want to tell linuxmce the command was successful.
What device do I send the 'Successful' command? Or, do I have to send an event?!?
Here's a snippet from my DCERouter log showing the two commands:
Received Message from 41 (Windows XP PC/tablet (Horiz) / Office) to 40 (Office Light / Office), type 1 id 184 Command:Set Level, retry none,
parameters: <0x877ccb90>
08 12/04/07 19:08:53.346 Parameter 76(Level): 100 <0x877ccb90>
08 12/04/07 19:08:56.534 Received Message from 40 (Office Light / Office) to 1 (CORE / Office), type 1 id 184 Command:Set Level, retry none,
parameters: <0x82fc3b90>
08 12/04/07 19:08:56.534 Parameter 76(Level): 100 <0x82fc3b90>
I've tried sending the command to:
1 (CORE/Office),
2 (DCERouter), and
41 (Windows XP PC/tablet (Horiz) / Office)
The commands get sent, but status doesn't get updated...
I'm really fighting with this issue because:
when I click <Light ON> from an orbiter, all is well, (from my log:)
05 12/04/07 18:50:41.630 GSDMessageTranslator isCmdImplemented = false <0xb6010b90>
05 12/04/07 18:50:41.631 #### Pre-Process Queue = 1 <0xb6010b90>
05 12/04/07 18:50:41.651 _QueueProc Pre - 184 : 0 <0xb7813b90>
05 12/04/07 18:50:41.651 GSD-Sleep Pre 184 : 0 <0xb7813b90>
05 12/04/07 18:50:41.651 Process Queue = 1 <0xb7813b90>
when, I click <Light OFF> from said orbiter, I get (in my log):
05 12/04/07 18:50:59.099 GSDMessageTranslator isCmdImplemented = false <0xb6010b90>
05 12/04/07 18:50:59.100 #### Pre-Process Queue = 1 <0xb6010b90>
05 12/04/07 18:50:59.154 _QueueProc Pre - 193 : 0 <0xb7813b90>
05 12/04/07 18:50:59.155 GSD-DispatchMessage - ignoring 193 because is useless. <0xb7813b90>
05 12/04/07 18:50:59.155 _QueueProc Post - 193 : 0 <0xb7813b90>
Now, Here's the problem: I don't want to send an 'ack' until I've verified the command has sent successfully. This includes 'process incoming data' routines...
Am I going about this in the wrong way?? do I HAVE to return the 'ack' from within the Process Command for Child (or private methods as needed) ?
Anywho, here's the code snippets..
(There is useless code here, that's beta for you!)
Private Method Listing:#### Written by Dan Damron
#### #373 Private Method Listing ####
#
# Commands send back to DCE
# 184 - SetLevel value 0-100 (% on) or +-1 for steps
# 193 - Turn Light OFF
# 192 - Turn Light ON
#
#
#
#
require "rexml/document"
require "rexml/streamlistener"
include REXML
def EZToDCE(param)
#param contains a hash of EZBridge command structure
log('--|---------EZtoDCE')
checkWait(param)
log('-----:)-----EZtoDCE ' + param['Response'] + ' Received.')
case param['Response']
# Standard Commands (responses to command)
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'
sleep 0.5
log('----X-------' + param['Parameter1']) # RestartEZBridge
when 'LstTimers' # Special Response
when 'ClrTimers'
when 'AddTimer'
when 'GetTimer' # Special Response
when 'SetTimer'
when 'DelTimer'
when 'GetVersion' # Special Response
when 'SndGrp'
when 'SndIns'
when 'SndX10'
when 'StLnk'
when 'CancelLnk'
when 'SetDev'
when 'RstPLM'
when 'GetLnk'
when 'GetNext'
when 'SetCfg'
when 'GetLnkData'
when 'LEDON'
when 'LEDOFF'
when 'MngLnk'
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 'InsStdMsg'
when 'InsExtMsg'
when 'X10Msg'
when 'InsLnkSts'
when 'BtnRpt'
when 'UsrRst'
when 'GrpEvntRpt'
when 'LnkData'
# Other messages
when 'PLMEchoError' # I know theres a PLM comm error...
# error sending command to PLM, reset command and try again
log('-----X------' + param['Response'])
resetcmd = {'Command' => 'Reset'}
$cmdqueue.insert(0, resetcmd)
sleep 0.1
$wAIT = false
SndIns()
when 'LongAck'
log('-----X------' + param['Response'])
# Error - seems to show up after PLMEchoError
resetcmd = {'Command' => 'Reset'}
$cmdqueue.insert(0, resetcmd)
sleep 0.1
$wAIT = false
SndIns()
else
log('-----XXXXXXX UNKNOWN Response Received:' + param['Response'])
end
end
def checkWait(param)
#Checks for response from current command.
if $cmdqueue[0] != nil
log('---|--------CheckWait:')
log('---|--------Current Command:' + $cmdqueue[0]['Command'])
log('---|--------param:' + param['Response'])
log('---|--------Flag:'+ $wAIT.to_s)
if $cmdqueue[0]['Command'] == param['Response']
$wAIT = false
log('---|--------Current Command Queue Length Before Delete:' + $cmdqueue.nitems.to_s)
$cmdqueue.delete_at(0)
log('---|--------Flag & currentCmd cleared')
log('---|--------Current Command Queue Length:' + $cmdqueue.nitems.to_s)
if $cmdqueue.nitems > 0 then
SndIns()
end
end
else
log('------:)----checkWait: command queue is emtpy')
if $wAIT == true
log('------:(----CheckWait: TRUE')
else
log('------:)----CheckWait: TRUE')
end
end
end
def parseMessage(param)
param.keys.each{|p| log("PM Param:" + p.to_s + "=" + param[p].to_s)}
case param['Response']
when 'SndIns' # response message
$wAIT = false
insHb = param['Parameter3'] # From
insMb = param['Parameter4']
insLb = param['Parameter5']
insID = insHb + "." + insMb + "." + insLb
myDevFrom = $children[insID]
myDevTo = 2 #DCE Router
myPriority = 1
myType = 1 # Command
#####log('Parent:' + parent_) -- this crashes the code
case param['Parameter7']
when '11' # dim/Brighten
myID = 184
log('From:' + myDevFrom.to_s)
log('To:' + myDevTo.to_s)
log('Pri:' + myPriority.to_s)
log('Type:' + myType.to_s)
log('ID:' + myID.to_s)
cmd = Command.new(myDevFrom, myDevTo, myPriority, myType, 184)
cmd.params_[184] = hextopercent(param['Parameter8']).to_s
SendCommand(cmd)
log('SENT!!!..............')
when '13' # off
cmd = Command.new(myDevFrom, myDevTo, myPriority, myType, 193)
SendCommand(cmd)
when '12' # on
cmd = Command.new(myDevFrom, myDevTo, myPriority, myType, 192)
SendCommand(cmd)
end
when 'InsStdMsg'
insHb = param['Parameter3']
insMb = param['Parameter4']
insLb = param['Parameter5']
insID = insHb + "." + insMb + "." + insLb
myDevFrom = $children[insID]
myDevTo = 2 #DCE Router
myPriority = 1
myType = 1 # Command
myID = InsCmdtoID(param['Parameter10'])
$wAIT = false
when 'InsExtMsg'
$wAIT = false
when 'X10Msg'
$wAIT = false
when 'InsLnkSts'
$wAIT = false
when 'BtnRpt'
$wAIT = false
when 'UsrRst'
$wAIT = false
when 'GrpEvntRpt'
$wAIT = false
when 'LnkData'
$wAIT = false
when 'GetVersion'
$wAIT = false
when 'GetCfg'
$wAIT = false
when 'LstTimers'
$wAIT = false
when 'GetTimer'
$wAIT = false
when 'GetRevision'
$wAIT = false
when 'GetLatLong'
$wAIT = false
when 'GetClock'
$wAIT = false
when 'LstMacros'
$wAIT = false
when 'GetMacro'
$wAIT = false
when 'LstDevices'
$wAIT = false
when 'GetDevice'
$wAIT = false
else
log('*#*#*#*#*#*#*#UNKNOWN COMMAND*#*#*#*#*#*#')
log(param['Response'])
$wAIT = false
end
end
def InsCmdtoID(value)
case value
when '01' # Assign to (Insteon) Group
return 0
when '02' # Delete from (Insteon) Group
return 0
when '10' # Ping
return 0
when '11' # ON
return 192
when '13' # OFF
return 193
when '15' # Brighten 1 step
return 0
when '16' # Dim 1 step
return 0
when '17' # Start Manual Change
return 0
when '18' # Stop Manual Change
return 0
when '19' # Status Request
return 0
when '24' # Do EE READ
return 0
when '28' # Set Address MSB
return 0
when '29' # POKE
return 0
when '2A' # POKE Extended
return 0
when '2B' # PEEK
return 0
when '2C' # PEEK Internal
return 0
when '2D' # POKE internal
return 0
else
return 0
end
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 XML command for SndIns
log('|-----------SndIns:WAIT FLAG = ' + $wAIT.to_s)
if $wAIT == false
param = $cmdqueue[0]
log('|-----------SndIns: Items in queue:' + $cmdqueue.nitems.to_s)
doc = Document.new
doc << XMLDecl.new
el = doc.add_element 'command'
el.text = param['Command']
param.keys.each {|k|
#log('|-----------SndIns:param[' + k.to_s + ']=' + param[k].to_s)
if k != 'Command' then
el1 = el.add_element k
el1.text = param[k]
end
}
conn_.Reconnect()
conn_.Send(doc.to_s)
log('Out---------SndIns:CmdSent:' + doc.to_s)
$wAIT = TRUE
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 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.56) -1).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/39_Generic_Serial_Device.log", "a")
$log.puts "(***):" + line.to_s
$log.close
end
Process Incoming Data:
#### Written by Dan Damron
#### #350 Process Incoming Data ####
#$recvBuff = ''
#while (true)
# buff = conn_.RecvDelimited($responseString, 100)
# if (buff.length() == 0)
# break
# end
# $recvbuff = $recvbuff + buff
#end
log('In----------Processing Incoming Data')
while(true)
buff=conn_.Recv(128,100)
if(buff.length() == 0)
break
end
$recvbuff = $recvbuff + buff
end
$recvbuff = parsestring($recvbuff)
Process Initialize:
#### Written by Dan Damron
#### #355 Process Initialize ####
$log = ''
$cmdTo = ''
$cmdFrom = ''
$cmdPriority = ''
$cmdType = ''
$cmdID = ''
$cmdParams = {}
$children = {}
$recvbuff = ''
$wAIT = false
$currentCmd = {}
$flagsBroadcastMessage = 128
$flagsDirectMessage = 0
$flagsAckDirectMessage = 32
$flagsNackDirectMessage = 160
$flagsGroupBroadcaseMessage = 192
$flagsGroupCleanupDirectMessage = 64
$flagsGroupAckDirectMessage =96
$flagsGroupNackDirectMessage = 224
$cmdqueue = []
$dcequeue = []
$X10HouseCodes = {
'6', 'A',
'E', 'B',
'2', 'C',
'A', 'D',
'1', 'E',
'9', 'F',
'5', 'G',
'D', 'H',
'7', 'I',
'F', 'J',
'3', 'K',
'B', 'L',
'0', 'M',
'8', 'N',
'4', 'O',
'C', 'P'}
$X10UnitCodes = {'6', '1', 'E', '2', '2', '3', 'A', '4',
'1', '5', '9', '6', '5', '7', 'D', '8',
'7', '9', 'F', '10', '3', '11', 'B', '12',
'0', '13', '8', '14', '4', '15', 'C', '16'}
$X10CommandCodes = {'6', 'All Lights Off', 'E', 'Status = off',
'2', 'On', 'A', 'Pre-Set Dim',
'1', 'All Lights On', '9', 'Hail Ack',
'5', 'Bright', 'D', 'Status=on',
'7', 'Extended Code','F', 'Status Request',
'3', 'Off', 'B', 'Pre-set Dim',
'0', 'All Units Off', '8', 'Hail Request',
'4', 'Dim', 'C', 'Extended Data(analog)'}
$responseString = '<' + '/' + 'Response>'
log('Finding Children..')
device_.childdevices_.each{|c|
log(c.to_s.to_i)
log(device_.childdevices_[c.to_s.to_i].devdata_[12])
$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)}
Process Command for Child:
#### Written by Dan Damron
#### #384 Process Receive Command for Child ####
log('------dce--- PRCFC:$wAIT=' + $wAIT.to_s)
#add DCE command to DCE queue
insteonID = device_.childdevices_[cmd.devidto_].devdata_[12].chomp.split('.')
$cmdID = cmd.id_
$cmdTo = cmd.devidto_
childType = device_.childdevices_[cmd.devidto_].devtemplid_
$cmdFrom = cmd.devidfrom_
$cmdPriority = cmd.priority_
$cmdType = cmd.type_
$cmdParams = cmd.params_
log('------dce--- cmdID:' + $cmdID.to_s + ', cmdFrom:' + $cmdFrom.to_s + ', cmdTo:' + $cmdTo.to_s + ', cmdType:' + $cmdType.to_s + ', Priority:' + $cmdPriority.to_s)
$cmdParams.keys.each {|p| log('------dce--- Param_[' + p.to_s + ']=' + $cmdParams[p])}
case cmd.id_
when 192 # ON
if insteonID.length > 2 then
param = {'Command' => 'SndIns',
'Parameter1' => insteonID[0],
'Parameter2' => insteonID[1],
'Parameter3' => insteonID[2],
'Parameter4' => '0F',
'Parameter5' => '11',
'Parameter6' => 'FF'}
$cmdqueue << param
SndIns()
else
log "------dce--- X10 DEVICE!!!"
param = {'Command' => 'SndX10',
'Parameter1' => rawX10(device_.childdevices_[cmd.devidto_].devdata_[12]),
'Parameter2' => X10Flag('On')}
$cmdqueue << param
SndIns()
end
resp = Command.new($cmdTo, 1, $cmdPriority, $cmdType, $cmdID)
resp.params_ = $cmdParams
SendCommand(resp)
when 193 #OFF
if insteonID.length > 2 then
param = {'Command' => 'SndIns',
'Parameter1' => insteonID[0],
'Parameter2' => insteonID[1],
'Parameter3' => insteonID[2],
'Parameter4' => '0F',
'Parameter5' => '13',
'Parameter6' => '00'}
$cmdqueue << param
SndIns()
else
log "------dce--- X10 DEVICE!!!"
param = {'Command' => 'SndX10',
'Parameter1' => rawX10(device_.childdevices_[cmd.devidto_].devdata_[12]),
'Parameter2' => X10Flag('Off')}
$cmdqueue << param
SndIns()
end
resp = Command.new($cmdTo, 1, $cmdPriority, $cmdType, $cmdID)
resp.params_ = $cmdParams
SendCommand(resp)
when 184 #SetLevel
# convert from percent to hex
dim_level = percenttohex(cmd.params_[76])
log("------dce--- Dim Level:" + dim_level.to_s)
if insteonID.length > 2 then
param = {'Command' => 'SndIns',
'Parameter1' => insteonID[0],
'Parameter2' => insteonID[1],
'Parameter3' => insteonID[2],
'Parameter4' => '0F',
'Parameter5' => '11',
'Parameter6' => dim_level}
$cmdqueue << param
SndIns()
else
log "X10 DEVICE!!! relative Dimming command"
# have to send 2 commands
#param = {'Command' => 'SndX10',
#'Parameter1' => rawX10(device_.childdevices_[cmd.devidto_].devdata_[12]),
#'Parameter2' => $X10CommandCodes.index['Bright'] + $X10UnitCodes.index[dim_level]
#$cmdqueue << param
#param = {'Command' => 'SndX10',
#dim_level = ((cmd.params_[76] * 16 + 1)/100).to_i.to_s
#'Parameter1' => rawX10(device_.Childdevices_[cmd.devidto_].devdata_[12]),
#'Parameter2' => $X10CommandCodes.index['Dim'] + $X10UnitCodes.index[dim_level]}
SndIns()
end
resp = Command.new($cmdTo, 1, $cmdPriority, $cmdType, $cmdID)
resp.params_ = $cmdParams
SendCommand(resp)
end