ThreadedRubyProtocolObject: Difference between revisions
| Line 23: | Line 23: | ||
=Command Object= | =Command Object= | ||
This is the PARENT class to your protocol Object. | |||
This class is responsible for determining the DIRECTION of the conversation: | |||
either DCEtoGSD (from DCERouter to your GSD Device) | |||
or GSDtoDCE (from your GSD Device to DCERouter) | |||
The actual data is irrelevant in this object. The data is simply passed to your protocol Object. | |||
=$Commands Array= | =$Commands Array= | ||
This is an Array of the Command Objects. | This is an Array of the Command Objects. | ||
Revision as of 19:48, 30 January 2008
Here is my ThreadedRuby code. I'm trying to add notes and a bit of an explanation as to what each piece of code does. If you just want to get going, create a class Object for your protocol as per in section 5.
Device Object
This class is simply a holder for a Child Device with onoff and level added:
class Device
attr_accessor :devdata, :deviceid, :template, :parent, :onoff, :level
def initialize()
@onoff = 'OFF' #State
@level = 0 #Level
@devdata = Hash.new #to hold devdata
@deviceid = @template = @parent = 0
end
end
$devices hash
This hash contains all the Device Objects (child objects with state info)
This is initialized in initDevices()
Command Object
This is the PARENT class to your protocol Object. This class is responsible for determining the DIRECTION of the conversation: either DCEtoGSD (from DCERouter to your GSD Device) or GSDtoDCE (from your GSD Device to DCERouter)
The actual data is irrelevant in this object. The data is simply passed to your protocol Object.
$Commands Array
This is an Array of the Command Objects. This serves as the queue for the threading.
Once a command has been completed, it is removed from this array.
PLCBUS OBJECT
This is a generic replaceable object This object needs the following methods:
Methods
Initialize()
- What it does:
- any Object initialization you may need.
- When is this called:
- Upon Object creation.
- What you will get:
- nothing.
- What you will return:
- nothing.
dceCommandIn(cmd)
- What is does:
- sends you a command object to allow you to create gsdOut().
- What you will get:
- cmd (Command Object)
- What you need to return:
- nothing (ignored)
- When you will get this:
- executed when a new DCE command is sent to you.
dceResponseIn(cmd)
- What it does:
- Sends you a DCE object to compare with the command.
- What you will get:
- cmd (Command Object)
- What you need to return:
- TRUE if you accept this response.
- FALSE if you do NOT accept this response.
- When you will get this:
- executed when a new DCE response is ready.
gsdCommandIn(value)
- What it does:
sends you a String to allow you to create a dceOut().
- What you will get:
value (String Object)
- What you need to return:
nothing (ignored)
- When you will get this:
executed when a new GSD command is sent to you.
gsdResponseIn(value)
- What it does:
Sends you a GSD Response to compare with the command.
- What you will get:
cmd (Command Object)
- What you need to return:
- TRUE if you accept this response.
- FALSE if you do NOT accept this response.
- When you will get this:
executed when a new GSD response is ready.
dceout()
- What it does:
Creates a Command Object to send to DCE.
- What you will get:
nothing.
- What you need to return:
a Command Object representing the previous gsdCommandIn.
- When is this called:
After a gsdCommandIn has been sent.
gsdout()
- What it does:
creates a String Object to send to GSD.
- What you will get:
nothing.
- What you will return:
a String Object representing the previous dceCommandIn.
- When is this called:
After a dceCommandIn has been sent.
Properties:
@responseAccepted
- What it does:
- signals that the current response is accepted as valid.
- When you should set this:
- Set this to TRUE if you accept the response as a valid response for this command.
- Set this to FALSE if you do NOT accept this response
@responseNeeded
What it does:
signals when you need a response.
@commandHolder
- What it does:
- If you need to create a new command, this is the holder for it.
ProtocolObject Class Template
class PLCBUS
attr_reader :responseAccepted, :responseNeeded, :commandHolder, :threaded
#Constants: Set up any constants here...
STX=0x02.chr
ETX=0x03.chr
def initialize()
@responseAccepted = false
@responseNeeded = false
@commandHolder = nil
@threaded = true
#set up any variable initialization here.
end
def dceCommandIn(cmd)
#This is fired when a new DCE command is created.
#cmd is a Command object ie Command.new
#eg:
@dcehomeunit = $devices[cmd.devidto_].devdata[12][0..1]
@dcehome = HomeCodes[$devices[cmd.devidto_].devdata[12][0].chr].to_s
@dceunit = UnitCodes[$devices[cmd.devidto_].devdata[12][1].chr].to_s
@dcefrom = cmd.devidfrom_
@dceto = cmd.devidto_
@dcepriority = cmd.priority_
@dcecmdtype = cmd.type_
@dcecmdid = cmd.id_
@dceparams = cmd.params_
end
def dceResponseIn(cmd)
# Returns TRUE if response is accepted.
#This is a RESPONSE from DCE. Normally, we do not get DCE responses
#as the DCE commands we send do not need a Reply.
#but if you need it, here is where you get it.
return true #or false
end
def gsdCommandIn(value)
@gsdusercode = value[2]
@gsdhomeunit = ("%X" %value[3])
@gsdhome = @gsdhomeunit[0].chr
@gsdunit = @gsdhomeunit[1].chr
@gsdcommand = value[4]
@gsdcmdAckPulse = true if (value[4] & 0x20) == 0x20
@gsdcmdReprq = true if (value[4] & 0x40) == 0x40
@gsdcmdLink = true if (value[4] & 0x80) == 0x80
@gsddata1 = value[5]
@gsddata2 = value[6]
if value[1] == 6
rxtxSwitchRegister(value[7]) #set switches if they exist
end
end
def gsdResponseIn(value)
#returns TRUE if response is accepted.
#no need to store response.. just compare.
@result = true
#value is a string from GSD.
#validate if you accept this response here....
return @result
end
def dceout
# Returns the GSD values as a DCE command.
@myfrom = gsdhomeunit
if @myfrom == 0
log('I DONT KNOW THIS DEVICE ID')
else
@mycommandout = gsdcommand
@cmdout = Command.new(@myfrom, -1001, 1, 2, @mycommandout)
@gsdparams.each_pair{|k,v| @cmdout.params_[k]=v}
return @cmdout
end
end
def gsdout
# Returns the DCE values as a gsd string
@threaded = false #PLCBUS does not support threading
#compile the output string from the values set in dceCommandIn(cmd)
@gsdout = @usercode.chr
@gsdout += dcehomeunit + dcecommand(@dcecmdid) + @data1.chr + @data2.chr
@gsdout = @gsdout.length.chr + @gsdout
@gsdout = STX + @gsdout + ETX
return @gsdout
end
def checkResponse(cmd) #old?? fired when a response was accepted.
@responseAccepted = true
end
### Below you can add any kind of support routines you may need for your protocol.
#I've deleted most of the code for brevity of a template.
#Support Routines for PLCBUS
def dcecommand(value) #DCE value is DCE Command.
#user code is in devdata[59] Configuration
#devdata[250] 3phase (boolean)
case value
when 192 #ON
when 193 #OFF
when 184 # SETLEVEL
end
return @command.chr
end
def gsdcommand
#returns DCE EVENT!! and compiles params
case CommandFunctions[@gsdcommand]
when 'ALL UNIT OFF'
@gsdparams[10] = '0'
return 48
when 'ALL LTS ON'
@gsdparams[10] = '1'
return 48
when 'ON'
@gsdparams[10] = '1'
return 48
when 'OFF'
@gsdparams[10] = '0'
return 48
when 'DIM'
@gsdparams[10] = @gsddata1 # set Brightness
return 48
when 'BRIGHT'
@gsdparams[10] = @gsddata1 # set Brightness
return 48
when 'ALL LIGHT OFF'
@gsdparams[10] = '0'
return 48
when 'ALL USER LTS ON'
@gsdparams[10] = '1'
return 48
when 'ALL USER UNIT OFF'
@gsdparams[10] = '0'
return 48
when 'ALL USER LIGHT OFF'
@gsdparams[10] = '0'
return 48
when 'PRESETDIM'
@gsdparams[10] = @gsddata1
return 48
else
return 0
end
return 0
end
def rxtxSwitchRegister(value)
#log('setting RX_TX_SWITCH')
if (value & 0x40) == 0x40
#log('r_id_sw is set')
@r_id_sw = true
else
#log('r_id_sw is reset')
@r_id_sw = false
end
if (value & 0x20) == 0x20
#log('r_ack_sw is set')
@r_ack_sw = true
@responseNeeded = false
else
#log('ResponseNeeded set to TRUE')
@responseNeeded = true
#log('r_ack_sw is reset')
@r_ack_sw = false
end
if (value & 0x10) == 0x10
#log('r_itself is set')
@r_itself = true
log('I heard myself Transmit this command on the PLCBUS.')
else
#log('r_itself is reset')
@r_itself = false
log('This Command is transmitted from an OUTSIDE SOURCE!')
end
if (value & 0x8) == 0x8
#log('r_risc is set')
@r_risc = true
else
#log('r_risc is reset')
@r_risc = false
end
if (value & 0x4) == 0x4
#log('r_sw is set')
@r_sw = true
else
#log('r_sw is reset')
@r_sw = false
end
end
#Generic Support Routines
def log(line)
@log = File.open("/var/log/pluto/" + $me.deviceid.to_s + "_Generic_Serial_Device.log", "a")
@log.putc '('[0]
@log.putc 'P'[0]
@log.putc 'L'[0]
@log.putc 'C'[0]
@log.putc ')'[0]
@l = line.to_s
@l.each_byte{|ch|
@log.putc ch
if ch == 60
@log.putc 32
end
}
@log.puts
@log.close
@log = nil
end
def debug(label, text)
work = label + ":"
for c in 1..text.length
work += padhex("%X" %text[c-1]) + ' '
end
log(BLUE + work + "Length:" + text.length.to_s + GREY)
end
def padhex(hex)
if hex.length==1
hex = "0" + hex
end
return hex
end
end