Difference between revisions of "ThreadedRubyProtocolObject"

From LinuxMCE
Jump to: navigation, search
(@responseAccepted)
m
 
(23 intermediate revisions by 4 users not shown)
Line 1: Line 1:
=PLCBUS OBJECT=
+
{{Versioninfo}}
**This is a generic replaceable object
+
{| align="right"
**This object needs the following methods:
+
  | __TOC__
 +
  |}
 +
[[Category:Tutorials]]
 +
[[Category:GSD]]
 +
[[Category:ThreadedRuby]]
 +
 
 +
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 below.
 +
 
 +
=ProtocolObject Class=
 +
This is a generic replaceable class.
 +
This object needs the following methods:
 
==Methods==
 
==Methods==
 
===Initialize()===
 
===Initialize()===
*What it does:
+
*'''What it does:'''
 
::any Object initialization you may need.
 
::any Object initialization you may need.
*When is this called:
+
*'''When is this called:'''
 
::Upon Object creation.
 
::Upon Object creation.
*What you will get:
+
*'''What you will get:'''
 
::nothing.
 
::nothing.
*What you will return:
+
*'''What you will return:'''
 
::nothing.
 
::nothing.
 
===dceCommandIn(cmd)===
 
===dceCommandIn(cmd)===
*What is does:
+
*'''What is does:'''
 
::sends you a command object to allow you to create gsdOut().
 
::sends you a command object to allow you to create gsdOut().
*What you will get:
+
*'''What you will get:'''
 
::cmd (Command Object)
 
::cmd (Command Object)
*What you need to return:
+
*'''What you need to return:'''
 
::nothing (ignored)
 
::nothing (ignored)
*When you will get this:
+
*'''When you will get this:'''
 
::executed when a new DCE command is sent to you.
 
::executed when a new DCE command is sent to you.
 
===dceResponseIn(cmd)===
 
===dceResponseIn(cmd)===
*What it does:
+
*'''What it does:'''
 
::Sends you a DCE object to compare with the command.
 
::Sends you a DCE object to compare with the command.
*What you will get:
+
*'''What you will get:'''
 
::cmd (Command Object)
 
::cmd (Command Object)
*What you need to return:
+
*'''What you need to return:'''
 
::TRUE if you accept this response.
 
::TRUE if you accept this response.
 
::FALSE if you do NOT accept this response.
 
::FALSE if you do NOT accept this response.
*When you will get this:
+
*'''When you will get this:'''
 
::executed when a new DCE response is ready.
 
::executed when a new DCE response is ready.
 
===gsdCommandIn(value)===
 
===gsdCommandIn(value)===
*What it does:
+
*'''What it does:'''
sends you a String to allow you to create a dceOut().
+
::sends you a String to allow you to create a dceOut().
*What you will get:
+
*'''What you will get:'''
value (String Object)
+
::value (String Object)
*What you need to return:
+
*'''What you need to return:'''
nothing (ignored)
+
::nothing (ignored)
*When you will get this:
+
*'''When you will get this:'''
executed when a new GSD command is sent to you.
+
::executed when a new GSD command is sent to you.
 
===gsdResponseIn(value)===
 
===gsdResponseIn(value)===
*What it does:
+
*'''What it does:'''
Sends you a GSD Response to compare with the command.   
+
::Sends you a GSD Response to compare with the command.   
*What you will get:
+
*'''What you will get:'''
cmd (Command Object)
+
::cmd (Command Object)
*What you need to return:
+
*'''What you need to return:'''
:TRUE if you accept this response.
+
::TRUE if you accept this response.
:FALSE if you do NOT accept this response.
+
::FALSE if you do NOT accept this response.
*When you will get this:
+
*'''When you will get this:'''
executed when a new GSD response is ready.
+
::executed when a new GSD response is ready.
 
===dceout()===
 
===dceout()===
*What it does:
+
*'''What it does:'''
Creates a Command Object to send to DCE.
+
::Creates a Command Object to send to DCE.
*What you will get:
+
*'''What you will get:'''
nothing.
+
::nothing.
*What you need to return:
+
*'''What you need to return:'''
a Command Object representing the previous gsdCommandIn.
+
::a Command Object representing the previous gsdCommandIn.
*When is this called:
+
*'''When is this called:'''
After a gsdCommandIn has been sent.
+
::After a gsdCommandIn has been sent.
 
===gsdout()===
 
===gsdout()===
*What it does:
+
*'''What it does:'''
creates a String Object to send to GSD.
+
::creates a String Object to send to GSD.
*What you will get:
+
*'''What you will get:'''
nothing.
+
::nothing.
*What you will return:
+
*'''What you will return:'''
a String Object representing the previous dceCommandIn.
+
::a String Object representing the previous dceCommandIn.
*When is this called:
+
*'''When is this called:'''
After a dceCommandIn has been sent.
+
::After a dceCommandIn has been sent.
 
==Properties:==
 
==Properties:==
===@responseAccepted===
+
===responseAccepted===
*What it does:
+
*'''What it does:'''
:signals that the current response is accepted as valid.
+
::signals that the current response is accepted as valid.
*When you should set this:
+
*'''When you should set this:
:Set this to TRUE if you accept the response as a valid response for this command.
+
::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
 
:Set this to FALSE if you do NOT accept this response
  
===@responseNeeded===
+
===responseNeeded===
 
   
 
   
  What it does:
+
*'''What it does:'''
    signals when you need a response.         
+
::signals when you need a response.         
 
    
 
    
===@commandHolder===
+
===commandHolder===
 +
*'''What it does:'''
 +
::If you need to create a new command, this is the holder for it.
  
  What it does:
+
===threaded===
    If you need to create a new command, this is the holder for it.
+
*'''What it does:'''
 +
::determines if this command is threadable
 +
*'''When you should set this:'''
 +
::This should be set to TRUE to enable threading.
 +
::if this is set to FALSE, all threading will be suspended UNTIL this command is complete. (or times out)
  
 +
==ProtocolObject Class Template==
 
<pre>
 
<pre>
 
class PLCBUS
 
class PLCBUS
 
   attr_reader :responseAccepted, :responseNeeded, :commandHolder, :threaded
 
   attr_reader :responseAccepted, :responseNeeded, :commandHolder, :threaded
   #Conatants:
+
 
 +
   #Constants: Set up any constants here...
 
   STX=0x02.chr
 
   STX=0x02.chr
 
   ETX=0x03.chr
 
   ETX=0x03.chr
  HomeCodes = {'A'=>0b0000,'B'=>0b0001,'C'=>0b0010,'D'=>0b0011,'E'=>0b0100,'F'=>0b0101,'G'=>0b0110,'H'=>0b0111,'I'=>0b1000,'J'=>0b1001,'K'=>0b1010,'L'=>0b1011,'M'=>0b1100,'N'=>0b1101,'O'=>0b1110,'P'=>0b1111}
 
  UnitCodes = {'1'=>0b0000,'2'=>0b0001,'3'=>0b0010,'4'=>0b0011,'5'=>0b0100,'6'=>0b0101,'7'=>0b0110,'8'=>0b0111,'9'=>0b1000,'10'=>0b1001,'11'=>0b1010,'12'=>0b1011,'13'=>0b1100,'14'=>0b1101,'15'=>0b1110,'16'=>0b1111}
 
  CommandFunctions = {0x00=>'ALL UNIT OFF',0x01=>'ALL LTS ON',0x02=>'ON',0x03=>'OFF',0x04=>'DIM',0x05=>'BRIGHT',0x06=>'ALL LIGHT OFF',0x07=>'ALL USER LTS ON',0x08=>'ALL USER UNIT OFF',0x09=>'ALL USER LIGHT OFF',0x0A=>'BLINK',0x0B=>'FADE STOP',0x0C=>'PRESETDIM',0x0D=>'STATUS ON',0x0E=>'STATUS OFF',0x0F=>'STATUS REQ',0x10=>'(R)MASTER ADDRS SETUP',0x11=>'(T)MASTER ADDRS SETUP',
 
    0x12=>'SCENES ADDRS SETUP',0x13=>'SCENES ADDRS ERASE',0x14=>'ALL SCENES ADDRS ERASE',0x15=>'FOR FUTURE',0x16=>'FOR FUTURE',0x17=>'FOR FUTURE',0x18=>'GET SIGNAL STRENGTH',0x19=>'GET NOISE STRENGTH',0x1A=>'REPORT SIGNAL STRENGTH',0x1B=>'REPORT NOISE STRENGTH',0x1C=>'GET ALL ID PULSE',0x1D=>'GET ONLY ON ID PULSE',0x1E=>'REPORT ALL ID PULSE',0x1F=>'REPORT ONLY ON PULSE'}
 
 
 
    
 
    
 
   def initialize()
 
   def initialize()
    # declare gsd variables
 
    @home = 0 #these two varianles determine the TO or FROM address
 
    @unit = 0 #these two variables determine the TO or FROM address
 
    @command = 0
 
    @usercode = $me.devdata[59].to_i
 
    #@cmdReprq = $me.devdata[260]      #3Phase on Dan's system
 
    @cmdReprq = $me.devdata[249]      #3Phase on Hari's system
 
    @data1 = 0
 
    @data2 = 0
 
    @cmdAckPulse = false
 
    @cmdLink = false
 
    #declare DCE variables
 
    @dceto = 0
 
    @dcefrom = 0
 
    @dcepriority = 0
 
    @dcecmdtype = 0
 
    @dcecmdid = 0
 
    @dceparams = {}
 
    @responseNeeded = false
 
 
     @responseAccepted = false
 
     @responseAccepted = false
     @gsdparams = {}
+
     @responseNeeded = false
    #@gsdparams[120] = '1' # hack to force command is useless...
+
 
     @commandHolder = nil
 
     @commandHolder = nil
    #log('Leaving Initialize')
 
 
     @threaded = true
 
     @threaded = true
 +
 +
    #set up any variable initialization here.
 +
 
   end
 
   end
 +
 
   def dceCommandIn(cmd)
 
   def dceCommandIn(cmd)
     log('dceCommandIn Entered:')
+
 
 +
     #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]
 
     @dcehomeunit = $devices[cmd.devidto_].devdata[12][0..1]
 
     @dcehome = HomeCodes[$devices[cmd.devidto_].devdata[12][0].chr].to_s
 
     @dcehome = HomeCodes[$devices[cmd.devidto_].devdata[12][0].chr].to_s
Line 138: Line 139:
  
 
   end
 
   end
   def dceResponseIn(cmd)                                       # Returns TRUE if response is accepted.
+
 
    log('dceResponseIn Entered:')
+
   def dceResponseIn(cmd)
    log(cmd.inspect)
+
    # Returns TRUE if response is accepted.
     return true                           #ignored in PLCBUS
+
    #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
 
   end
 +
 
   def gsdCommandIn(value)
 
   def gsdCommandIn(value)
    log('gsdCommandIn Entered:')
+
 
    debug('Value:', value)
+
 
     @gsdusercode = value[2]
 
     @gsdusercode = value[2]
 
     @gsdhomeunit = ("%X" %value[3])
 
     @gsdhomeunit = ("%X" %value[3])
Line 159: Line 164:
 
       rxtxSwitchRegister(value[7])  #set switches if they exist
 
       rxtxSwitchRegister(value[7])  #set switches if they exist
 
     end
 
     end
 +
 
   end
 
   end
   def gsdResponseIn(value)                                     #returns TRUE if response is accepted.
+
   def gsdResponseIn(value)
 +
    #returns TRUE if response is accepted.
 
     #no need to store response.. just compare.
 
     #no need to store response.. just compare.
    #negative logic here
 
 
     @result = true
 
     @result = true
     #log('gsdResponseIn Entered:')
+
     #value is a string from GSD.
    #debug('Value:', value)
+
     #validate if you accept this response here....
     if @usercode == value[2]
+
 
      #log('Usercode Check!')
+
    else
+
      log('Usercode compare failed')
+
      @result = false
+
    end
+
    if dcehomeunit[0] == value[3]
+
      #log('Home and Unit CHECK!')
+
    else
+
      log('Home and Unit compare failed')
+
      @result = false
+
    end
+
    if dcecommand(@dcecmdid)[0] == value[4]
+
      #log('PLCBus Command CHECK!')
+
    else
+
      log('PLCBus Command compare failed')
+
      @result = false
+
    end
+
    if value[1] == 6
+
      #log('Setting rxtxRegister')
+
      rxtxSwitchRegister(value[7])
+
    else
+
      log('no rxtxRegister')
+
      @result = false
+
    end
+
    #log('gsdResponseIn returning TRUE') if @result == true
+
    #log('gsdResponseIn returning FALSE') if @result == false
+
 
     return @result
 
     return @result
 
   end
 
   end
   def dceout                                                   # Returns the GSD values as a DCE command.
+
   def dceout
 +
    # Returns the GSD values as a DCE command.
 
     @myfrom = gsdhomeunit
 
     @myfrom = gsdhomeunit
 
     if @myfrom == 0
 
     if @myfrom == 0
Line 201: Line 182:
 
     else
 
     else
 
       @mycommandout = gsdcommand
 
       @mycommandout = gsdcommand
      log('IN PLCBUS:DCEOUT')
 
      log('        From: ' + @myfrom.to_s)
 
      log('          To: -1001')
 
      log('    Priority: 1')
 
      log('      CmdType: 2')
 
      log('        CmdId: ' + @mycommandout.to_s)
 
      log('Devdata Below:')
 
      @gsdparams.each_pair{|k,v|
 
        log('    devdata_[' + k.to_s + '] = ' + v)
 
      }
 
 
       @cmdout = Command.new(@myfrom, -1001, 1, 2, @mycommandout)
 
       @cmdout = Command.new(@myfrom, -1001, 1, 2, @mycommandout)
 
       @gsdparams.each_pair{|k,v| @cmdout.params_[k]=v}
 
       @gsdparams.each_pair{|k,v| @cmdout.params_[k]=v}
      #      @responseNeeded = false
 
      #      @responseAccepted = true
 
 
       return @cmdout
 
       return @cmdout
 
     end
 
     end
 
   end
 
   end
   def gsdout                                                   # Returns the DCE values as a gsd string
+
   def gsdout
     #log('IN PLCBUS:GSDOUT')
+
    # Returns the DCE values as a gsd string
     log('SETTING THREADING to FALSE in PLCBUS:GSDOUT:')
+
     @threaded = false #PLCBUS does not support threading
    @threaded = false
+
     #compile the output string from the values set in dceCommandIn(cmd)
 +
 
 
     @gsdout = @usercode.chr
 
     @gsdout = @usercode.chr
 
     @gsdout += dcehomeunit + dcecommand(@dcecmdid) + @data1.chr + @data2.chr
 
     @gsdout += dcehomeunit + dcecommand(@dcecmdid) + @data1.chr + @data2.chr
 
     @gsdout = @gsdout.length.chr + @gsdout
 
     @gsdout = @gsdout.length.chr + @gsdout
 
     @gsdout = STX + @gsdout + ETX
 
     @gsdout = STX + @gsdout + ETX
    #debug('Data Out', @gsdout)
 
 
     return @gsdout
 
     return @gsdout
 
   end
 
   end
 +
 
   def checkResponse(cmd)  #old?? fired when a response was accepted.
 
   def checkResponse(cmd)  #old?? fired when a response was accepted.
    log('WARNING: CheckResponse was CALLED')
 
    #    #this routine needs to set ONE flag:
 
    #    #responseNeeded (true/false) if we need more data
 
    #    if cmd.class.to_s == 'String'
 
    #      #we are checking a GSD command.
 
    #
 
    #    end
 
    #    if cmd.class == Command
 
    #      #we are checking a DCE command.
 
    #      if @r_ack_sw == true
 
    #        #here is a good place to check the data1 and data2 values
 
    #        #to make sure the proper device responded.
 
    #        #
 
    #        #PLCBUS command complete
 
    #        log('Received Ack from PLCBUS device.')
 
    #        @responseNeeded = false
 
    #        # attempt to set device info here.
 
    #        case @dcecmdid
 
    #        when 192 # ON
 
    #          $devices[@dceto].onoff = "ON"
 
    #          if $devices[@dceto].level != 100
 
    #            $devices[@dceto].level = 100
 
    #            log('HAVE TO SEND A SETLEVEL=100')
 
    #          end
 
    #        when 193 # OFF
 
    #          $devices[@dceto].onoff = "OFF"
 
    #          if $devices[@dceto].level != 0
 
    #            $devices[@dceto].level = 0
 
    #            log('HAVE TO SEND A SETLEVEL = 0')
 
    #            log('**************************')
 
    #            log('**************************')
 
    #            log('**************************')
 
    #            log('**************************')
 
    #            @commandHolder = RubyCommand.new()
 
    #            #pack a new DCE command with the Event..
 
    #            @mycmd = Command.new(@dceto, @dceto, 1, 1, 184)
 
    #            @mycmd.params_[76] = '0'
 
    #            @commandHolder.packCommand(@mycmd)
 
    #
 
    #          end
 
    #        when 184 # SetLevel
 
    #          if @dceparams[76].to_i == 0
 
    #            #dimming to OFF
 
    #            if $devices[@dceto].onoff == 'ON'
 
    #              log('HAVE TO SEND AN OFF to DCE')
 
    #              log('**************************')
 
    #              log('**************************')
 
    #              log('**************************')
 
    #              log('**************************')
 
    #              @commandHolder = RubyCommand.new()
 
    #              #pack a new DCE command with the Event..
 
    #              @mycmd = Command.new(@dceto, -1001, 1, 2, 40)
 
    #              @mycmd.params_[10] = '0'
 
    #              @commandHolder.packCommand(@mycmd)
 
    #              #
 
    #             
 
    #              #@commandHolder = Command.new(@dcefrom, -1001, 1, 2, 40)
 
    #              #@commandHolder.params_[10] = '0'
 
    #              $devices[@dceto].onoff = 'OFF'
 
    #             
 
    #            end
 
    #             
 
    #          else
 
    #            #dimming to ON
 
    #            if $devices[@dceto].onoff == 'OFF'
 
    #              log('HAVE TO SEND AN ON to DCE')
 
    #              log('**************************')
 
    #              log('**************************')
 
    #              log('**************************')
 
    #              log('**************************')
 
    #              @commandHolder = RubyCommand.new()
 
    #              @mycmd = Command.new(@dceto, -1001, 1, 2, 40)
 
    #              @mycmd.params_[10] = '1'
 
    #              @commandHolder.packCommand(@mycmd)
 
    #              #@commandHolder = Command.new(@dcefrom, -1001, 1, 2, 40)
 
    #              #@commandHolder.params_[10] = '1'
 
    #
 
    #              $devices[@dceto].onoff = 'ON'
 
    #            end
 
    #          end
 
    #          $devices[@dceto].level = @dceparams[76].to_i
 
    #        end
 
    #        log('Device:' + @dceto.to_s)
 
    #        log('on/off:' + $devices[@dceto].onoff)
 
    #        log(' level:' + $devices[@dceto].level.to_s)
 
    #      end
 
    #      if @r_itself == true
 
    #        #heard myself send the response.
 
    #        log('I heard myself send the command properly.')
 
    #        @responseNeeded = true
 
    #      end
 
    #
 
    #    end
 
 
     @responseAccepted = true
 
     @responseAccepted = true
 
   end
 
   end
   #Support Routines for PLCBUX
+
 
 +
 
 +
 
 +
### 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.
 
   def dcecommand(value) #DCE value is DCE Command.
 
     #user code is in devdata[59] Configuration
 
     #user code is in devdata[59] Configuration
 
     #devdata[250] 3phase (boolean)
 
     #devdata[250] 3phase (boolean)
    @work = 0
 
    #log('DCE Command is' + value.to_s)
 
 
     case value
 
     case value
 
     when 192 #ON
 
     when 192 #ON
  
      @cmdLink = false
 
      @cmdReprq = false
 
      @cmdAckPulse = true
 
      @data1 = 0 #Fade Rate
 
      @work = 0x80 if @cmdling == true
 
      @work += 0x40 if @cmdReprq == true
 
      @work += 0x20 if @cmdAckPulse == true
 
      @command =@work + CommandFunctions.index("ON")
 
 
     when 193 #OFF
 
     when 193 #OFF
      @cmdLink = false
+
 
      @cmdReprq = false
+
      @cmdAckPulse = true
+
      @data1 = 0 #Fade Rate
+
      @work = 0x80 if @cmdling == true
+
      @work += 0x40 if @cmdReprq == true
+
      @work += 0x20 if @cmdAckPulse == true
+
      @command =@work + CommandFunctions.index("OFF")
+
 
     when 184 # SETLEVEL
 
     when 184 # SETLEVEL
      @cmdLink = false
 
      @cmdReprq = false
 
      @cmdAckPulse = true
 
      @data1 = @dceparams[76].to_i #dim level
 
      @data2 = 2 #Fade Rate
 
      @work = 0x80 if @cmdling == true
 
      @work += 0x40 if @cmdReprq == true
 
      @work += 0x20 if @cmdAckPulse == true
 
      @data2 = 2#Fade Rate
 
      @command =@work + CommandFunctions.index("PRESETDIM")
 
 
     end
 
     end
    #how convert it into a integer - currently it a HEX string.
+
 
    #log('PLC Command is:' + @command.to_s + 'DECIMAL')
+
 
     return @command.chr
 
     return @command.chr
 
   end
 
   end
   def gsdcommand #returns DCE EVENT!! and compiles params
+
   def gsdcommand  
 +
  #returns DCE EVENT!! and compiles params
  
    #log('IN DCECommand')
 
   
 
 
     case CommandFunctions[@gsdcommand]
 
     case CommandFunctions[@gsdcommand]
 
     when 'ALL UNIT OFF'
 
     when 'ALL UNIT OFF'
Line 404: Line 258:
 
       @gsdparams[10] = '0'
 
       @gsdparams[10] = '0'
 
       return 48
 
       return 48
    when 'BLINK'
 
    when 'FADE STOP'
 
 
     when 'PRESETDIM'
 
     when 'PRESETDIM'
 
       @gsdparams[10] = @gsddata1
 
       @gsdparams[10] = @gsddata1
 
       return 48
 
       return 48
    when 'STATUS ON'
 
    when 'STATUS OFF'
 
    when 'STATUS REQ'
 
    when '(R)MASTER ADDRS SETUP'
 
    when '(T)MASTER ADDRS SETUP'
 
    when 'SCENES ADDRS SETUP'
 
    when 'SCENES ADDRS ERASE'
 
    when 'ALL SCENES ADDRS ERASE'
 
    when 'FOR FUTURE'
 
    when 'GET SIGNAL STRENGTH'
 
    when 'GET NOISE STRENGTH'
 
    when 'REPORT SIGNAL STRENGTH'
 
    when 'REPORT NOISE STRENGTH'
 
    when 'GET ALL ID PULSE'
 
    when 'GET ONLY ON ID PULSE'
 
    when 'REPORT ALL ID PULSE'
 
    when 'REPORT ONLY ON PULSE'
 
 
     else
 
     else
      log('UNKNOWN COMMAND RESPONSE in PLCBUS OBJECT')
 
 
       return 0
 
       return 0
 
     end
 
     end
 +
  return 0
 +
  end
  
  end
 
  def dcehomeunit() # returns GSD homeunit byte from DCE homeunit
 
    @work = @dcehome + @dceunit
 
    return (@work.hex.chr)
 
  end
 
  def gsdhomeunit() #returns DCE Child ID from gsd homeunit
 
    #@gsdhomeunit holds the data
 
    @work = HomeCodes.index(@gsdhomeunit[0].chr.to_i)
 
    @work += UnitCodes.index(@gsdhomeunit[1].chr.to_i)
 
    return $devices.find(@work)
 
  end
 
 
   def rxtxSwitchRegister(value)
 
   def rxtxSwitchRegister(value)
 
     #log('setting RX_TX_SWITCH')
 
     #log('setting RX_TX_SWITCH')
Line 486: Line 311:
 
      
 
      
 
   end
 
   end
 +
 
   #Generic Support Routines
 
   #Generic Support Routines
 
   def log(line)
 
   def log(line)

Latest revision as of 08:33, 3 May 2010

Version Status Date Updated Updated By
710 Unknown N/A N/A
810 Unknown N/A N/A
1004 Unknown N/A N/A
1204 Unknown N/A N/A
1404 Unknown N/A N/A
Usage Information

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

ProtocolObject Class

This is a generic replaceable class. 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.

threaded

  • What it does:
determines if this command is threadable
  • When you should set this:
This should be set to TRUE to enable threading.
if this is set to FALSE, all threading will be suspended UNTIL this command is complete. (or times out)

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