ThreadedRubyProtocolObject
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.
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