Difference between revisions of "PLCBUS"

From LinuxMCE
Jump to: navigation, search
m (GSD/Ruby Code: added actual template)
 
(21 intermediate revisions by 8 users not shown)
Line 1: Line 1:
[[Category: Hardware]]
+
{{versioninfo|810Status=Working|810UpdatedDate=1st May 2010|810UpdatedBy=BongoWongo}}
 
[[Category: Automation]]
 
[[Category: Automation]]
 +
[[Category: Power Line Control]]
 +
[[Category: PLCBUS]]
 
  {| align="right"
 
  {| align="right"
 
   | __TOC__
 
   | __TOC__
Line 6: Line 8:
 
[[Image:Plcbus-logo.jpg|right]]
 
[[Image:Plcbus-logo.jpg|right]]
 
= Status =
 
= Status =
ddamron wrote a GSD for PLCBUS with ruby. Hari will try to get a c++ dce client running.
+
We've implemented a new C++ driver for 0810b2. More information here: http://forum.linuxmce.org/index.php?topic=11170.0
  
 
= About =
 
= About =
Line 29: Line 31:
 
* http://x10-hk.com/store/manual/plcbus/plcbus-1141.pdf
 
* http://x10-hk.com/store/manual/plcbus/plcbus-1141.pdf
  
= GSD/Ruby Code =
 
* [[ThreadedRuby]]
 
  
<pre>
 
RCODE:
 
  0:require 'Ruby_Generic_Serial_Device'
 
  1:class Command < Ruby_Generic_Serial_Device::RubyCommandWrapper
 
  2:end
 
  3:class Device_110 < Ruby_Generic_Serial_Device::RubySerialIOWrapper
 
  4:#### 350 ####################################################################
 
  5:def cmd_350(cmd=nil)
 
  6:@returnParamArray.clear
 
  7:### #350
 
  8:
 
  9:while(true)
 
  10:  @buff = conn_.RecvDelimited(0x02.chr,100) #stx
 
  11:  if(@buff.length() == 0)
 
  12:    break
 
  13:  end
 
  14:  @buff2 = conn_.Recv(1,10) #Length of message
 
  15:  @buff +=@buff2
 
  16:  @length = @buff2[0]
 
  17:  @buff += conn_.Recv(@length + 1, 100)
 
  18:  debugin(@buff)
 
  19:  dataIn(@buff)
 
  20:end
 
  21:
 
  22:
 
  23:# this routine needs to be handled better.
 
  24:# possibly with regular expressions.
 
  25:return @returnParamArray
 
  26:end
 
  27:#### 351 ####################################################################
 
  28:def cmd_351(cmd=nil)
 
  29:@returnParamArray.clear
 
  30:errorHandler()
 
  31:return @returnParamArray
 
  32:end
 
  33:#### 355 ####################################################################
 
  34:def cmd_355(cmd=nil)
 
  35:@returnParamArray.clear
 
  36:#########################
 
  37:# Written by Dan Damron #
 
  38:#########################
 
  39:
 
  40:initDevices()
 
  41:return @returnParamArray
 
  42:end
 
  43:#### PRIVATE METHODS ####################################################################
 
  44:#######################################
 
  45:# Threaded RubyCommand
 
  46:# Written by Dan Damron
 
  47:#######################################
 
  48:
 
  49:class Device                                                      #Child Device Holder
 
  50:  attr_accessor  :devdata, :deviceid, :template, :parent, :onoff, :level
 
  51:  def initialize()                                             
 
  52:    @onoff = 'OFF'                                                #State
 
  53:    @level = 0                                                    #Level
 
  54:    @devdata = Hash.new                                          #to hold devdata
 
  55:    @deviceid = @template = @parent = 0
 
  56:  end
 
  57:end
 
  58:
 
  59:class Devices                                                    #holder for Child Devices
 
  60:  def initialize
 
  61:    @devices = Hash.new
 
  62:  end
 
  63:  def append(device)                                              #Device Object
 
  64:    @devices[device.deviceid] = device
 
  65:  end
 
  66:  def find(value)                                                #this method finds the devdata[12] and returns the child ID
 
  67:    @result = 0
 
  68:    log('Looking up:' + value.to_s)
 
  69:    @devices.each_key{|d|
 
  70:      if @devices[d].devdata[12] == value
 
  71:        @result = @devices[d].deviceid
 
  72:      end}
 
  73:    log('In Devices:find() result:' + @result.to_s)
 
  74:    return @result
 
  75:  end
 
  76:  def [](value)                                                  #return the device.
 
  77:    return @devices[value]
 
  78:  end
 
  79:  def log(line)                                                  #logger
 
  80:    @log = File.open("/var/log/pluto/" + $me.deviceid.to_s + "_Generic_Serial_Device.log", "a")
 
  81:    @log.putc '('[0]
 
  82:    @log.putc 'D'[0]
 
  83:    @log.putc 'E'[0]
 
  84:    @log.putc 'V'[0]
 
  85:    @log.putc 'I'[0]
 
  86:    @log.putc 'C'[0]
 
  87:    @log.putc 'E'[0]
 
  88:    @log.putc 'S'[0]
 
  89:    @log.putc ')'[0]
 
  90:    @l = line.to_s
 
  91:    @l.each_byte{|ch|
 
  92:      @log.putc ch
 
  93:      if ch == 60
 
  94:        @log.putc 32
 
  95:      end
 
  96:    }
 
  97:    @log.puts
 
  98:    @log.close
 
  99:    @log = nil
 
100:  end
 
101:end
 
102:
 
103:
 
104:RED = 0x1b.chr + '[31m'
 
105:GREEN = 0x1b.chr + '[32m'
 
106:YELLOW = 0x1b.chr + '[33m'
 
107:BLUE = 0x1b.chr + '[34m'
 
108:PURPLE = 0x1b.chr + '[35m'
 
109:AQUA = 0x1b.chr + '[36m'
 
110:GREY = 0x1b.chr + '[37m'
 
111:REDBACK = 0x1b.chr + '[41m'
 
112:GREENBACK = 0x1b.chr + '[42m'
 
113:YELLOWBACK = 0x1b.chr + '[43m'
 
114:BLUEBACK = 0x1b.chr + '[44m'
 
115:PURPLEBACK = 0x1b.chr + '[45m'
 
116:AQUABACK = 0x1b.chr + '[46m'
 
117:GREYBACK = 0x1b.chr + '[47m'
 
118:BLACKBACK = 0x1b.chr + '[48m'
 
119:DCEtoGSD = 10
 
120:GSDtoDCE = 20
 
121:NotReady = 1
 
122:SendReady = 2
 
123:ReceiveReady = 3
 
124:Complete = 4
 
125:Failed = 5
 
126:
 
127:
 
128:
 
129:
 
130:##############################
 
131:# Methods for $commands[] queue
 
132:##############################
 
133:def dataIn(value)
 
134:  #log('DataIn Entered:')
 
135:  $commands.each{|cmd|
 
136:    if cmd.state == ReceiveReady                                    #only ReceiveReady cmds.
 
137:      if cmd.dataIn(value) == true                                  #this data was accepted if TRUE
 
138:        @newcmd = cmd.commandHolder                                #check for new command
 
139:        if @newcmd != nil
 
140:          log(YELLOW + 'This command is spawning!!!' + GREY)
 
141:          $commands.push @newcmd                                    #if so, push it onto the queue
 
142:        end
 
143:        if cmd.state == SendReady
 
144:          log('DataIn: Ready to Send.')
 
145:          dataOutSingleCmd(cmd)
 
146:        end
 
147:        if cmd.state == Complete
 
148:          if cmd.threaded == false
 
149:            log(YELLOW + 'Threading RESUMED' + GREY)
 
150:            $threadingSuspended = false                                #allow other commands to now transmit.
 
151:          end
 
152:          log(PURPLE + 'DataIn:Command Complete!' + GREY)
 
153:          $commands.delete(cmd)                                    #remove command if complete
 
154:        end
 
155:        if cmd.state == Failed
 
156:          log(RED + 'DataIn:This Command FAILED:' + GREY)
 
157:          log(YELLOW + cmd.inspect + GREY)                          #inspect the failed command
 
158:          log('Command Deleted.')
 
159:          $commands.delete(cmd)                                    #remove command if failed
 
160:        end
 
161:        return
 
162:      end
 
163:    end
 
164:  }
 
165:  #if we hit here, the data has been rejected by all current commands.
 
166:  log('dataIn: New Command:')
 
167:  c = RubyCommand.new
 
168:  c.dataIn(value) # sets up the command.
 
169:  dataOutSingleCmd(c) if c.state == SendReady #check to see if it's ready to send
 
170:  $commands.push c.clone                      #push a copy of it onto the queue.
 
171:  c = nil
 
172: 
 
173:  #dataOut()                                                        #safer to call it in turn.
 
174:  #log('DataIn Exited:')
 
175:end
 
176:def dataOut()                                                      #replaces send()
 
177:  log('dataOut Entered:')
 
178:  #Send out all the commands...
 
179:  $commands.each{|cmd|
 
180:    dataOutSingleCmd(cmd)
 
181:    if cmd.state == Complete
 
182:      log(PURPLE + 'DataOut:Command Complete!' + GREY)
 
183:      $commands.delete(cmd)
 
184:    end
 
185:    if cmd.state == Failed
 
186:      log(RED + 'DataOut:This Command FAILED:' + GREY)
 
187:      log(YELLOW + cmd.inspect + GREY)                          #inspect the failed command
 
188:      log('Command Deleted.')
 
189:      $commands.delete(cmd)                                    #remove command if failed
 
190:    end
 
191:
 
192:  }
 
193:  #log('dataOut Exited:')
 
194:end
 
195:def dataOutSingleCmd(cmd)
 
196:  log('dataOutSingleCmd Entered:')
 
197:  if cmd.state == SendReady                                        #send out only if ready.
 
198:    @out = cmd.dataOut
 
199:    log('got past cmd.dataOut')
 
200:    log('@out is type:' + @out.class.to_s)
 
201:    case @out.class.to_s
 
202:    when 'String'
 
203:      log('Threading Suspended = FALSE') if $threadingSuspended == false
 
204:      log('Threading Suspended = TRUE') if $threadingSuspended == true
 
205:     
 
206:      if $threadingSuspended == false
 
207:      conn_.Reconnect()
 
208:      log('Sending to GSD...')
 
209:      debugout(@out)
 
210:      conn_.Send(@out)
 
211:      debugout(@out)
 
212:      conn_.Send(@out)
 
213:      sleep $delayBetweenTransmits
 
214:      if cmd.threaded == false
 
215:        log(YELLOW + 'THREADING SUSPENDED!!!' + GREY)
 
216:        $threadingSuspended == true
 
217:      end
 
218:      else
 
219:        #cannot send data out while waiting for a NON threaded response.
 
220:      end
 
221:    when 'Command'
 
222:      log('Sending to DCE...')
 
223:      SendCommand(@out)
 
224:    when 'NilClass'                                                #safety first!
 
225:      log('This command not ready to send.')
 
226:    end
 
227:  end
 
228:  #log('dataOutSingleCmd Exited:')
 
229:end
 
230:def log(line)
 
231:  $log = File.open("/var/log/pluto/" + device_.devid_.to_s + "_Generic_Serial_Device.log", "a")
 
232:  $log.putc '('[0]
 
233:  $log.putc '*'[0]
 
234:  $log.putc '*'[0]
 
235:  $log.putc '*'[0]
 
236:  $log.putc ')'[0]
 
237:  @l = line.to_s
 
238:  @l.each_byte{|ch|
 
239:    $log.putc ch
 
240:    if ch == 60
 
241:      $log.putc 32
 
242:    end
 
243:  }
 
244:  $log.puts
 
245:  $log.close
 
246:end
 
247:def debugout(text)
 
248:  work = 'OUT:'
 
249:
 
250:  for c in 1..text.length
 
251:    work += padhex("%X" %text[c-1]) + ' '
 
252:  end
 
253:  log(GREEN + work + "Length:" + text.length.to_s + GREY)
 
254:end
 
255:def debug(label, text)
 
256:  work = label + ":"
 
257:  for c in 1..text.length
 
258:    work += padhex("%X" %text[c-1]) + ' '
 
259:  end
 
260:  log(BLUE + work + "Length:" + text.length.to_s + GREY)
 
261:end
 
262:def debugin(text)
 
263:  work = 'IN:'
 
264:
 
265:  for c in 1..text.length
 
266:    work += padhex("%X" %text[c-1]) + ' '
 
267:  end
 
268:  log(RED + work + "Length:" + text.length.to_s + GREY)
 
269:end
 
270:def padhex(hex)
 
271:  if hex.length==1
 
272:    hex = "0" + hex
 
273:  end
 
274:  return hex
 
275:end
 
276:
 
277:##############################
 
278:#Initialization Routine
 
279:##############################
 
280:def initDevices()                                                  #Loads Child Devices into Devices
 
281:  $threadingSuspended = false
 
282:  $timeout = 1                                                  #Global timeout
 
283:  $retryAttempts = 10                                          #Global Retry Attempts
 
284:  $delayBetweenTransmits = 0.4
 
285:  log(YELLOW + 'Loading Child Devices...' + GREY)
 
286:  $devices = Devices.new
 
287:  device_.childdevices_.keys.each{|c|                          #Populate children
 
288:    d = Device.new()                                            #create a new device
 
289:    d.deviceid = c                                             
 
290:    d.template = device_.childdevices_[c].devtemplid_
 
291:    d.parent = device_.childdevices_[c].parent_
 
292:    d.devdata = device_.childdevices_[c].devdata_
 
293:    $devices.append(d)                                          #add d to $devices
 
294:    log('Device:' + d.deviceid.to_s)}
 
295:  $me = Device.new()                                            #get MY info
 
296:  $me.deviceid = device_.devid_
 
297:  $me.parent = device_.parent_
 
298:  $me.devdata = []
 
299:  $me.devdata = device_.devdata_
 
300:  $me.onoff = "ON"
 
301:  $me.level = 100
 
302:  myusercode = "My Usercode: %X" %$me.devdata[59].to_i          #show in hex form
 
303:  log(myusercode)
 
304:
 
305:  log(YELLOW + 'Done.' + GREY)                                  #devdata[59] = usercode
 
306:  log(YELLOW + 'Setting up Command Queue' + GREY)            #dedata[249] =  3phase (boolean)
 
307:  $commands = Array.new
 
308:  log(YELLOW + 'Done.' + GREY)
 
309:  #TODO:  read all the PLC devices to get initial status.
 
310:  #TODO:  and report status back to lmce.
 
311:end
 
312:def errorHandler                                                    # threaded errorhandler
 
313:  #Error handling is now handled at the RubyCommand Level.
 
314:  if $commands.nitems != 0                                          #log out the commands waiting to be processed, if any.
 
315:    @work = YELLOW + 'Command Queue:' + $commands.nitems.to_s
 
316:    $commands.each{|cm| @work += ', State:'
 
317:      @work += 'NEW' if cm.state == 1
 
318:      @work += 'SendReady' if cm.state == 2
 
319:      @work += 'ReceiveReady' if cm.state == 3
 
320:      @work += 'Complete' if cm.state == 4
 
321:      @work += 'Failed' if cm.state == 5
 
322:      @work += GREY + '  '}
 
323:    log(@work)
 
324:  end
 
325:  $commands.each{|cmd|
 
326:    case cmd.state                                                  #possible to clear out commands here..
 
327:    when Complete
 
328:      $commands.delete(cmd)
 
329:      #    when SendReady
 
330:      #      dataOutSingleCmd(cmd)
 
331:    when ReceiveReady
 
332:      if cmd.timeout == true                                        #call the timeout and get back error.
 
333:        log(RED + 'This Command Timed Out!:' + GREY)
 
334:        log(RED + cmd.inspect + GREY)
 
335:        $commands.delete(cmd)
 
336:      else
 
337:        dataOutSingleCmd(cmd)
 
338:      end
 
339:    end
 
340:  }
 
341:end
 
342:
 
343:##############################
 
344:#Class RubyCommand
 
345:##############################
 
346:class RubyCommand
 
347:  # This class is a container for a protocolObject Instance.
 
348:  # This class is responsible for the DIRECTION of communication of a specific command.
 
349:  #
 
350:  # Error Handling is also handled in the timeout method.
 
351:  #
 
352:  # If this command creates a NEW command, this object will allow only ONE creation.
 
353:  # This class also controls the state information.
 
354:  # Constants:
 
355:  DCEtoGSD = 10
 
356:  GSDtoDCE = 20
 
357:  #Object States:
 
358:  NEW = 1
 
359:  SendReady = 2
 
360:  ReceiveReady = 3
 
361:  Complete = 4
 
362:  Failed = 5
 
363:
 
364:
 
365:  def initialize
 
366:    #log('Initialize Entered:')
 
367:    @protocolObject = PLCBUS.new()
 
368:    @direction = nil
 
369:    @timeoutCounter = 0
 
370:    @timeoutRetries = 0
 
371:    @state = NEW
 
372:    @serialNumber = rand(10000).to_s                #for DCE object
 
373:    @newCommandSent = false
 
374:    #log('Initialize Exited:')
 
375:  end
 
376:  def dataIn(cmd)                                                  #Returns TRUE if accepted, FALSE if not.
 
377:    #log('dataIn Entered:')
 
378:    case @state
 
379:    when NEW
 
380:      log('dataIn: creating NEW command')
 
381:      @savedCommand = cmd
 
382:     
 
383:      case cmd.class.to_s
 
384:      when 'String'                                  # new Command from GSD
 
385:        @direction = GSDtoDCE
 
386:        @protocolObject.gsdCommandIn(cmd)
 
387:        @state = SendReady                          #This command is ready to send.
 
388:      when 'Command'                                  # new Command from DCE
 
389:        @direction = DCEtoGSD
 
390:        @protocolObject.dceCommandIn(cmd)
 
391:        @state = SendReady                          #This command is ready to send.
 
392:      else
 
393:        log('FAILURE IN dataIn - cmd.class not recognized!')
 
394:        log('Direction: nil')
 
395:        log('class is:' + cmd.class.to_s)
 
396:        @state = Failed                            #fail this command. (remove it)
 
397:      end
 
398:      @result = true                                #returns datain Accepted.
 
399:    when ReceiveReady                              #Possible Response
 
400:      log('dataIn: Possible Response')
 
401:      @result = false
 
402:      @class = cmd.class.to_s                      #get this only once.
 
403:      case @direction
 
404:      when DCEtoGSD
 
405:        case @class
 
406:        when 'String'                              # from GSD
 
407:          #log('dataIn: class is STRING')
 
408:          #pass the data to the protocol Object and check for accepted.
 
409:          #log('dataIn: executing gsdResponseIn')
 
410:          if @protocolObject.gsdResponseIn(cmd) == true
 
411:            log('response Accepted.')
 
412:            @result = true
 
413:            if @protocolObject.responseNeeded == true
 
414:              log('Command not yet complete.')
 
415:              @state = ReceiveReady                  # ProtocolObject needs another response.
 
416:            else
 
417:              log('Command Complete.')
 
418:              @state = Complete                      # ProtocolObject is complete.
 
419:            end
 
420:
 
421:          else
 
422:            log('response Rejected!')
 
423:          end
 
424:        when 'Command'                                # from DCE
 
425:          #log('dataIn: class is COMMAND')
 
426:          @result = false                          # cmd is NOT for me.
 
427:        else
 
428:          log('FAILURE IN dataIn - cmd.class not recognised!')
 
429:          log('Direction: DCEtoGSD')
 
430:          log('class is:' + @class.to_s)
 
431:
 
432:          @result = false
 
433:        end
 
434:
 
435:      when GSDtoDCE
 
436:        case @class
 
437:        when 'String'                                # from GSD
 
438:          @result = false                          # not for me.
 
439:        when 'Command'                                # POSSIBLE when sending commands to self.
 
440:          if cmd.params_[999] == @serialNumber
 
441:            @result = true                          #I sent this command!
 
442:            log('Caught Command Sent to Self!')
 
443:          end
 
444:        else
 
445:          log('FAILURE IN dataIn - cmd.class not recognised!')
 
446:          log('Direction: GSDtoDCE')
 
447:          log('class is:' + @class.to_s)
 
448:
 
449:        end
 
450:      end
 
451:      #log('dataIn: returning TRUE (exited)') if @result == true
 
452:      #log('dataIn: returning FALSE (exited)') if @result == false
 
453:      return @result
 
454:    end
 
455:  end
 
456:  def dataOut
 
457:    log('dataOut Entered:')
 
458:    if @state == SendReady
 
459:      case @direction
 
460:      when DCEtoGSD                                  #Send GSD String
 
461:        @work = @protocolObject.gsdout
 
462:        log('dataOut:  Setting @state to Receive Ready')
 
463:        @state = ReceiveReady
 
464:      when GSDtoDCE
 
465:        @work = @protocolObject.dceout
 
466:        if @work.class.to_s == 'Command'              #check for valid Object (returns nil if not ready)
 
467:          if @work.devidto_ == @work.devidfrom_      #check for command to self
 
468:            log('Detected attempting to send to self')
 
469:            @work.devdata_[999] = @serialNumber      #this command is to self.  Serialize it.
 
470:          end
 
471:        end
 
472:        log('dataOut:  Setting @state to Complete')
 
473:        @state = Complete                            #DCE does not send responses. (yet)
 
474:      else
 
475:        log('Attempted DataOut with uninitialized Object')
 
476:        @state = Failed
 
477:        @work = nil
 
478:      end
 
479:      log('dataOut: Returning @work')
 
480:      return @work
 
481:    else
 
482:      log('This command is not ready to send.')
 
483:    end
 
484:    log('DataOut Exited:')
 
485:  end
 
486:  def timeout                                                      #called ONLY when @state == ReceiveReady
 
487:    @result = false                                #returns TRUE if command times out.
 
488:    @timeoutCounter +=1                            #ticker += 1
 
489:    if @timeoutCounter == $timeout                  #global variable defined in init.
 
490:      @timeoutCounter = 0                          #reset ticker
 
491:      @timeoutRetries += 1                          #increment Retries..
 
492:      if @timeoutRetries == $retryAttempts          #global variable defined in init.
 
493:        @state = Failed
 
494:        @result = true
 
495:      else
 
496:        log('Attempt:' + (@timeoutRetries + 1).to_s)
 
497:        if @state == ReceiveReady
 
498:          @state = SendReady
 
499:        end
 
500:      end
 
501:     
 
502:    end
 
503:    log('Tick...')
 
504:    return @result
 
505:  end
 
506:  def state
 
507:    return @state
 
508:  end
 
509:  def direction()
 
510:    return @direction
 
511:  end
 
512:  def responseNeeded()
 
513:    return @protocolObject.responseNeeded
 
514:  end
 
515:  def commandHolder()                                              #This is a holder of self.  Used when inserting another command.
 
516:    #allow only ONE command to be returned.
 
517:    @holder = @protocolObject.commandHolder
 
518:    if @holder != nil
 
519:      if @newCommandSent == false
 
520:        #we can send the command here.
 
521:        @newCommandSent = true 
 
522:        return @holder
 
523:      end
 
524:    end
 
525:    return nil
 
526:  end
 
527:  def threaded
 
528:    return @protocolObject.threaded
 
529:  end
 
530:  #  def packCommand(value)  # this is used by protocolObject to pack a command.
 
531:  #    if value.class.to_s == 'Command'
 
532:  #      #packing a DCE Object..
 
533:  #      self.dcein(value)
 
534:  #      #override the direction...
 
535:  #      @direction = GSDtoDCE
 
536:  #      #flag the command ready to be sent.
 
537:  #      @sendReady = true
 
538:  #    end
 
539:  #    if value.class.to_s == 'String'
 
540:  #      #packing a GSD object
 
541:  #      self.gsdin(value)
 
542:  #      #override the direction...
 
543:  #      @direction = DCEtoGSD
 
544:  #      #flag the command ready to be sent.
 
545:  #      @sendReady = true
 
546:  #    end
 
547:  #  end
 
548:  #  def hasNewCommand()
 
549:  #    return @hasNewCommand
 
550:  #  end
 
551:  def log(line)                                                    #support method.
 
552:    @log = File.open("/var/log/pluto/" + $me.deviceid.to_s + "_Generic_Serial_Device.log", "a")
 
553:    @log.putc '('[0]
 
554:    @log.putc 'C'[0]
 
555:    @log.putc 'o'[0]
 
556:    @log.putc 'm'[0]
 
557:    @log.putc 'm'[0]
 
558:    @log.putc 'a'[0]
 
559:    @log.putc 'n'[0]
 
560:    @log.putc 'd'[0]
 
561:
 
562:    @log.putc ')'[0]
 
563:    @l = line.to_s
 
564:    @l.each_byte{|ch|
 
565:      @log.putc ch
 
566:      if ch == 60
 
567:        @log.putc 32
 
568:      end
 
569:    }
 
570:    @log.puts
 
571:    @log.close
 
572:    @log = nil
 
573:  end
 
574:end
 
575:
 
576:
 
577:
 
578:#####################
 
579:### PLCBUS OBJECT ###
 
580:#####################
 
581:# This is a generic replaceable object
 
582:# This object needs the following methods:
 
583:#
 
584:# Initialize()
 
585:#
 
586:#  What it does:
 
587:#    any Object initialization you may need.
 
588:#   
 
589:#  When is this called:
 
590:#    Upon Object creation.
 
591:#   
 
592:#  What you will get:
 
593:#    nothing.
 
594:#   
 
595:#  What you will return:
 
596:#    nothing.
 
597:#   
 
598:#
 
599:# dceCommandIn(cmd)
 
600:# 
 
601:#  What is does:
 
602:#    sends you a command object to allow you to create gsdOut().
 
603:#   
 
604:#  What you will get:
 
605:#    cmd (Command Object)
 
606:# 
 
607:#  What you need to return:
 
608:#    nothing (ignored)
 
609:#   
 
610:#  When you will get this:
 
611:#    executed when a new DCE command is sent to you.
 
612:#
 
613:#   
 
614:# dceResponseIn(cmd)
 
615:# 
 
616:#  What it does:
 
617:#    Sends you a DCE object to compare with the command.
 
618:#   
 
619:#  What you will get:
 
620:#    cmd (Command Object)
 
621:# 
 
622:#  What you need to return:
 
623:#    TRUE if you accept this response.
 
624:#    FALSE if you do NOT accept this response.
 
625:#   
 
626:#  When you will get this:
 
627:#    executed when a new DCE response is ready.
 
628:#
 
629:#
 
630:# gsdCommandIn(value)
 
631:# 
 
632:#  What it does:
 
633:#    sends you a String to allow you to create a dceOut().
 
634:#   
 
635:#  What you will get:
 
636:#    value (String Object)
 
637:# 
 
638:#  What you need to return:
 
639:#    nothing (ignored)
 
640:#   
 
641:#  When you will get this:
 
642:#    executed when a new GSD command is sent to you.
 
643:#
 
644:#   
 
645:# gsdResponseIn(value)
 
646:#
 
647:#  What it does:
 
648:#    Sends you a GSD Response to compare with the command. 
 
649:#  What you will get:
 
650:#    cmd (Command Object)
 
651:# 
 
652:#  What you need to return:
 
653:#    TRUE if you accept this response.
 
654:#    FALSE if you do NOT accept this response.
 
655:#   
 
656:#  When you will get this:
 
657:#    executed when a new GSD response is ready.
 
658:#
 
659:# dceout()
 
660:# 
 
661:#  What it does:
 
662:#    Creates a Command Object to send to DCE.
 
663:#
 
664:#  What you will get:
 
665:#    nothing.
 
666:#   
 
667:#  What you need to return:
 
668:#    a Command Object representing the previous gsdCommandIn.
 
669:#
 
670:#  When is this called:
 
671:#    After a gsdCommandIn has been sent.
 
672:# gsdout()
 
673:#
 
674:#  What it does:
 
675:#    creates a String Object to send to GSD.
 
676:#   
 
677:#  What you will get:
 
678:#    nothing.
 
679:#   
 
680:#  What you will return:
 
681:#    a String Object representing the previous dceCommandIn.
 
682:#
 
683:#  When is this called:
 
684:#    After a dceCommandIn has been sent.
 
685:#
 
686:#
 
687:# Properties:
 
688:#
 
689:# @responseAccepted
 
690:# 
 
691:#  What it does:
 
692:#    signals that the current response is accepted as valid.
 
693:# 
 
694:#  When you should set this:
 
695:#
 
696:# @responseNeeded
 
697:#
 
698:#  What it does:
 
699:#    signals when you need a response.       
 
700:# 
 
701:# @commandHolder
 
702:#
 
703:#  What it does:
 
704:#    If you need to create a new command, this is the holder for it.
 
705:#
 
706:
 
707:class PLCBUS
 
708:  attr_reader :responseAccepted, :responseNeeded, :commandHolder, :threaded
 
709:  #Conatants:
 
710:  STX=0x02.chr
 
711:  ETX=0x03.chr
 
712:  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}
 
713:  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}
 
714:  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',
 
715:    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'}
 
716:
 
717: 
 
718:  def initialize()
 
719:    # declare gsd variables
 
720:    @home = 0 #these two varianles determine the TO or FROM address
 
721:    @unit = 0 #these two variables determine the TO or FROM address
 
722:    @command = 0
 
723:    @usercode = $me.devdata[59].to_i
 
724:    #@cmdReprq = $me.devdata[260]      #3Phase on Dan's system
 
725:    @cmdReprq = $me.devdata[249]      #3Phase on Hari's system
 
726:    @data1 = 0
 
727:    @data2 = 0
 
728:    @cmdAckPulse = false
 
729:    @cmdLink = false
 
730:    #declare DCE variables
 
731:    @dceto = 0
 
732:    @dcefrom = 0
 
733:    @dcepriority = 0
 
734:    @dcecmdtype = 0
 
735:    @dcecmdid = 0
 
736:    @dceparams = {}
 
737:    @responseNeeded = false
 
738:    @responseAccepted = false
 
739:    @gsdparams = {}
 
740:    #@gsdparams[120] = '1' # hack to force command is useless...
 
741:    @commandHolder = nil
 
742:    #log('Leaving Initialize')
 
743:    @threaded = true
 
744:  end
 
745:  def dceCommandIn(cmd)
 
746:    log('dceCommandIn Entered:')
 
747:    @dcehomeunit = $devices[cmd.devidto_].devdata[12][0..1]
 
748:    @dcehome = HomeCodes[$devices[cmd.devidto_].devdata[12][0].chr].to_s
 
749:    @dceunit = UnitCodes[$devices[cmd.devidto_].devdata[12][1].chr].to_s
 
750:    @dcefrom = cmd.devidfrom_
 
751:    @dceto = cmd.devidto_
 
752:    @dcepriority = cmd.priority_
 
753:    @dcecmdtype = cmd.type_
 
754:    @dcecmdid = cmd.id_
 
755:    @dceparams = cmd.params_
 
756:
 
757:  end
 
758:  def dceResponseIn(cmd)                                        # Returns TRUE if response is accepted.
 
759:    log('dceResponseIn Entered:')
 
760:    log(cmd.inspect)
 
761:    return true                          #ignored in PLCBUS
 
762:  end
 
763:  def gsdCommandIn(value)
 
764:    log('gsdCommandIn Entered:')
 
765:    debug('Value:', value)
 
766:    @gsdusercode = value[2]
 
767:    @gsdhomeunit = ("%X" %value[3])
 
768:    @gsdhome = @gsdhomeunit[0].chr
 
769:    @gsdunit = @gsdhomeunit[1].chr
 
770:    @gsdcommand = value[4]
 
771:    @gsdcmdAckPulse = true if (value[4] & 0x20) == 0x20
 
772:    @gsdcmdReprq = true if (value[4] & 0x40) == 0x40
 
773:    @gsdcmdLink = true if (value[4] & 0x80) == 0x80
 
774:    @gsddata1 = value[5]
 
775:    @gsddata2 = value[6]
 
776:    if value[1] == 6
 
777:      rxtxSwitchRegister(value[7])  #set switches if they exist
 
778:    end
 
779:  end
 
780:  def gsdResponseIn(value)                                      #returns TRUE if response is accepted.
 
781:    #no need to store response.. just compare.
 
782:    #negative logic here
 
783:    @result = true
 
784:    #log('gsdResponseIn Entered:')
 
785:    #debug('Value:', value)
 
786:    if @usercode == value[2]
 
787:      #log('Usercode Check!')
 
788:    else
 
789:      log('Usercode compare failed')
 
790:      @result = false
 
791:    end
 
792:    if dcehomeunit[0] == value[3]
 
793:      #log('Home and Unit CHECK!')
 
794:    else
 
795:      log('Home and Unit compare failed')
 
796:      @result = false
 
797:    end
 
798:    if dcecommand(@dcecmdid)[0] == value[4]
 
799:      #log('PLCBus Command CHECK!')
 
800:    else
 
801:      log('PLCBus Command compare failed')
 
802:      @result = false
 
803:    end
 
804:    if value[1] == 6
 
805:      #log('Setting rxtxRegister')
 
806:      rxtxSwitchRegister(value[7])
 
807:    else
 
808:      log('no rxtxRegister')
 
809:      @result = false
 
810:    end
 
811:    #log('gsdResponseIn returning TRUE') if @result == true
 
812:    #log('gsdResponseIn returning FALSE') if @result == false
 
813:    return @result
 
814:  end
 
815:  def dceout                                                    # Returns the GSD values as a DCE command.
 
816:    @myfrom = gsdhomeunit
 
817:    if @myfrom == 0
 
818:      log('I DONT KNOW THIS DEVICE ID')
 
819:    else
 
820:      @mycommandout = gsdcommand
 
821:      log('IN PLCBUS:DCEOUT')
 
822:      log('        From: ' + @myfrom.to_s)
 
823:      log('          To: -1001')
 
824:      log('    Priority: 1')
 
825:      log('      CmdType: 2')
 
826:      log('        CmdId: ' + @mycommandout.to_s)
 
827:      log('Devdata Below:')
 
828:      @gsdparams.each_pair{|k,v|
 
829:        log('    devdata_[' + k.to_s + '] = ' + v)
 
830:      }
 
831:      @cmdout = Command.new(@myfrom, -1001, 1, 2, @mycommandout)
 
832:      @gsdparams.each_pair{|k,v| @cmdout.params_[k]=v}
 
833:      #      @responseNeeded = false
 
834:      #      @responseAccepted = true
 
835:      return @cmdout
 
836:    end
 
837:  end
 
838:  def gsdout                                                    # Returns the DCE values as a gsd string
 
839:    #log('IN PLCBUS:GSDOUT')
 
840:    log('SETTING THREADING to FALSE in PLCBUS:GSDOUT:')
 
841:    @threaded = false
 
842:    @gsdout = @usercode.chr
 
843:    @gsdout += dcehomeunit + dcecommand(@dcecmdid) + @data1.chr + @data2.chr
 
844:    @gsdout = @gsdout.length.chr + @gsdout
 
845:    @gsdout = STX + @gsdout + ETX
 
846:    #debug('Data Out', @gsdout)
 
847:    return @gsdout
 
848:  end
 
849:  def checkResponse(cmd)  #old?? fired when a response was accepted.
 
850:    log('WARNING: CheckResponse was CALLED')
 
851:    #    #this routine needs to set ONE flag:
 
852:    #    #responseNeeded (true/false) if we need more data
 
853:    #    if cmd.class.to_s == 'String'
 
854:    #      #we are checking a GSD command.
 
855:    #
 
856:    #    end
 
857:    #    if cmd.class == Command
 
858:    #      #we are checking a DCE command.
 
859:    #      if @r_ack_sw == true
 
860:    #        #here is a good place to check the data1 and data2 values
 
861:    #        #to make sure the proper device responded.
 
862:    #        #
 
863:    #        #PLCBUS command complete
 
864:    #        log('Received Ack from PLCBUS device.')
 
865:    #        @responseNeeded = false
 
866:    #        # attempt to set device info here.
 
867:    #        case @dcecmdid
 
868:    #        when 192 # ON
 
869:    #          $devices[@dceto].onoff = "ON"
 
870:    #          if $devices[@dceto].level != 100
 
871:    #            $devices[@dceto].level = 100
 
872:    #            log('HAVE TO SEND A SETLEVEL=100')
 
873:    #          end
 
874:    #        when 193 # OFF
 
875:    #          $devices[@dceto].onoff = "OFF"
 
876:    #          if $devices[@dceto].level != 0
 
877:    #            $devices[@dceto].level = 0
 
878:    #            log('HAVE TO SEND A SETLEVEL = 0')
 
879:    #            log('**************************')
 
880:    #            log('**************************')
 
881:    #            log('**************************')
 
882:    #            log('**************************')
 
883:    #            @commandHolder = RubyCommand.new()
 
884:    #            #pack a new DCE command with the Event..
 
885:    #            @mycmd = Command.new(@dceto, @dceto, 1, 1, 184)
 
886:    #            @mycmd.params_[76] = '0'
 
887:    #            @commandHolder.packCommand(@mycmd)
 
888:    #
 
889:    #          end
 
890:    #        when 184 # SetLevel
 
891:    #          if @dceparams[76].to_i == 0
 
892:    #            #dimming to OFF
 
893:    #            if $devices[@dceto].onoff == 'ON'
 
894:    #              log('HAVE TO SEND AN OFF to DCE')
 
895:    #              log('**************************')
 
896:    #              log('**************************')
 
897:    #              log('**************************')
 
898:    #              log('**************************')
 
899:    #              @commandHolder = RubyCommand.new()
 
900:    #              #pack a new DCE command with the Event..
 
901:    #              @mycmd = Command.new(@dceto, -1001, 1, 2, 40)
 
902:    #              @mycmd.params_[10] = '0'
 
903:    #              @commandHolder.packCommand(@mycmd)
 
904:    #              #
 
905:    #             
 
906:    #              #@commandHolder = Command.new(@dcefrom, -1001, 1, 2, 40)
 
907:    #              #@commandHolder.params_[10] = '0'
 
908:    #              $devices[@dceto].onoff = 'OFF'
 
909:    #             
 
910:    #            end
 
911:    #             
 
912:    #          else
 
913:    #            #dimming to ON
 
914:    #            if $devices[@dceto].onoff == 'OFF'
 
915:    #              log('HAVE TO SEND AN ON to DCE')
 
916:    #              log('**************************')
 
917:    #              log('**************************')
 
918:    #              log('**************************')
 
919:    #              log('**************************')
 
920:    #              @commandHolder = RubyCommand.new()
 
921:    #              @mycmd = Command.new(@dceto, -1001, 1, 2, 40)
 
922:    #              @mycmd.params_[10] = '1'
 
923:    #              @commandHolder.packCommand(@mycmd)
 
924:    #              #@commandHolder = Command.new(@dcefrom, -1001, 1, 2, 40)
 
925:    #              #@commandHolder.params_[10] = '1'
 
926:    #
 
927:    #              $devices[@dceto].onoff = 'ON'
 
928:    #            end
 
929:    #          end
 
930:    #          $devices[@dceto].level = @dceparams[76].to_i
 
931:    #        end
 
932:    #        log('Device:' + @dceto.to_s)
 
933:    #        log('on/off:' + $devices[@dceto].onoff)
 
934:    #        log(' level:' + $devices[@dceto].level.to_s)
 
935:    #      end
 
936:    #      if @r_itself == true
 
937:    #        #heard myself send the response.
 
938:    #        log('I heard myself send the command properly.')
 
939:    #        @responseNeeded = true
 
940:    #      end
 
941:    #
 
942:    #    end
 
943:    @responseAccepted = true
 
944:  end
 
945:  #Support Routines for PLCBUX
 
946:  def dcecommand(value) #DCE value is DCE Command.
 
947:    #user code is in devdata[59] Configuration
 
948:    #devdata[250] 3phase (boolean)
 
949:    @work = 0
 
950:    #log('DCE Command is' + value.to_s)
 
951:    case value
 
952:    when 192 #ON
 
953:
 
954:      @cmdLink = false
 
955:      @cmdReprq = false
 
956:      @cmdAckPulse = true
 
957:      @data1 = 0 #Fade Rate
 
958:      @work = 0x80 if @cmdling == true
 
959:      @work += 0x40 if @cmdReprq == true
 
960:      @work += 0x20 if @cmdAckPulse == true
 
961:      @command =@work + CommandFunctions.index("ON")
 
962:    when 193 #OFF
 
963:      @cmdLink = false
 
964:      @cmdReprq = false
 
965:      @cmdAckPulse = true
 
966:      @data1 = 0 #Fade Rate
 
967:      @work = 0x80 if @cmdling == true
 
968:      @work += 0x40 if @cmdReprq == true
 
969:      @work += 0x20 if @cmdAckPulse == true
 
970:      @command =@work + CommandFunctions.index("OFF")
 
971:    when 184 # SETLEVEL
 
972:      @cmdLink = false
 
973:      @cmdReprq = false
 
974:      @cmdAckPulse = true
 
975:      @data1 = @dceparams[76].to_i #dim level
 
976:      @data2 = 2 #Fade Rate
 
977:      @work = 0x80 if @cmdling == true
 
978:      @work += 0x40 if @cmdReprq == true
 
979:      @work += 0x20 if @cmdAckPulse == true
 
980:      @data2 = 2#Fade Rate
 
981:      @command =@work + CommandFunctions.index("PRESETDIM")
 
982:    end
 
983:    #how convert it into a integer - currently it a HEX string.
 
984:    #log('PLC Command is:' + @command.to_s + 'DECIMAL')
 
985:    return @command.chr
 
986:  end
 
987:  def gsdcommand #returns DCE EVENT!! and compiles params
 
988:
 
989:    #log('IN DCECommand')
 
990:   
 
991:    case CommandFunctions[@gsdcommand]
 
992:    when 'ALL UNIT OFF'
 
993:      @gsdparams[10] = '0'
 
994:      return 48
 
995:    when 'ALL LTS ON'
 
996:      @gsdparams[10] = '1'
 
997:      return 48
 
998:    when 'ON'
 
999:      @gsdparams[10] = '1'
 
1000:      return 48
 
1001:    when 'OFF'
 
1002:      @gsdparams[10] = '0'
 
1003:      return 48
 
1004:    when 'DIM'
 
1005:      @gsdparams[10] = @gsddata1 # set Brightness
 
1006:      return 48
 
1007:
 
1008:    when 'BRIGHT'
 
1009:      @gsdparams[10] = @gsddata1 # set Brightness
 
1010:      return 48
 
1011:
 
1012:    when 'ALL LIGHT OFF'
 
1013:      @gsdparams[10] = '0'
 
1014:      return 48
 
1015:    when 'ALL USER LTS ON'
 
1016:      @gsdparams[10] = '1'
 
1017:      return 48
 
1018:    when 'ALL USER UNIT OFF'
 
1019:      @gsdparams[10] = '0'
 
1020:      return 48
 
1021:    when 'ALL USER LIGHT OFF'
 
1022:      @gsdparams[10] = '0'
 
1023:      return 48
 
1024:    when 'BLINK'
 
1025:    when 'FADE STOP'
 
1026:    when 'PRESETDIM'
 
1027:      @gsdparams[10] = @gsddata1
 
1028:      return 48
 
1029:    when 'STATUS ON'
 
1030:    when 'STATUS OFF'
 
1031:    when 'STATUS REQ'
 
1032:    when '(R)MASTER ADDRS SETUP'
 
1033:    when '(T)MASTER ADDRS SETUP'
 
1034:    when 'SCENES ADDRS SETUP'
 
1035:    when 'SCENES ADDRS ERASE'
 
1036:    when 'ALL SCENES ADDRS ERASE'
 
1037:    when 'FOR FUTURE'
 
1038:    when 'GET SIGNAL STRENGTH'
 
1039:    when 'GET NOISE STRENGTH'
 
1040:    when 'REPORT SIGNAL STRENGTH'
 
1041:    when 'REPORT NOISE STRENGTH'
 
1042:    when 'GET ALL ID PULSE'
 
1043:    when 'GET ONLY ON ID PULSE'
 
1044:    when 'REPORT ALL ID PULSE'
 
1045:    when 'REPORT ONLY ON PULSE'
 
1046:    else
 
1047:      log('UNKNOWN COMMAND RESPONSE in PLCBUS OBJECT')
 
1048:      return 0
 
1049:    end
 
1050:
 
1051:  end
 
1052:  def dcehomeunit() # returns GSD homeunit byte from DCE homeunit
 
1053:    @work = @dcehome + @dceunit
 
1054:    return (@work.hex.chr)
 
1055:  end
 
1056:  def gsdhomeunit() #returns DCE Child ID from gsd homeunit
 
1057:    #@gsdhomeunit holds the data
 
1058:    @work = HomeCodes.index(@gsdhomeunit[0].chr.to_i)
 
1059:    @work += UnitCodes.index(@gsdhomeunit[1].chr.to_i)
 
1060:    return $devices.find(@work)
 
1061:  end
 
1062:  def rxtxSwitchRegister(value)
 
1063:    #log('setting RX_TX_SWITCH')
 
1064:    if (value & 0x40) == 0x40
 
1065:      #log('r_id_sw is set')
 
1066:      @r_id_sw = true
 
1067:    else
 
1068:      #log('r_id_sw is reset')
 
1069:      @r_id_sw = false
 
1070:    end
 
1071:    if (value & 0x20) == 0x20
 
1072:      #log('r_ack_sw is set')
 
1073:      @r_ack_sw = true
 
1074:      @responseNeeded = false
 
1075:    else
 
1076:      #log('ResponseNeeded set to TRUE')
 
1077:      @responseNeeded = true
 
1078:      #log('r_ack_sw is reset')
 
1079:      @r_ack_sw = false
 
1080:    end
 
1081:    if (value & 0x10) == 0x10
 
1082:      #log('r_itself is set')
 
1083:      @r_itself = true
 
1084:      log('I heard myself Transmit this command on the PLCBUS.')
 
1085:    else
 
1086:      #log('r_itself is reset')
 
1087:      @r_itself = false
 
1088:      log('This Command is transmitted from an OUTSIDE SOURCE!')
 
1089:    end
 
1090:    if (value & 0x8) == 0x8
 
1091:      #log('r_risc is set')
 
1092:      @r_risc = true
 
1093:    else
 
1094:      #log('r_risc is reset')
 
1095:      @r_risc = false
 
1096:    end
 
1097:    if (value & 0x4) == 0x4
 
1098:      #log('r_sw is set')
 
1099:      @r_sw = true
 
1100:    else
 
1101:      #log('r_sw is reset')
 
1102:      @r_sw = false
 
1103:    end
 
1104:   
 
1105:  end
 
1106:  #Generic Support Routines
 
1107:  def log(line)
 
1108:    @log = File.open("/var/log/pluto/" + $me.deviceid.to_s + "_Generic_Serial_Device.log", "a")
 
1109:    @log.putc '('[0]
 
1110:    @log.putc 'P'[0]
 
1111:    @log.putc 'L'[0]
 
1112:    @log.putc 'C'[0]
 
1113:    @log.putc ')'[0]
 
1114:    @l = line.to_s
 
1115:    @l.each_byte{|ch|
 
1116:      @log.putc ch
 
1117:      if ch == 60
 
1118:        @log.putc 32
 
1119:      end
 
1120:    }
 
1121:    @log.puts
 
1122:    @log.close
 
1123:    @log = nil
 
1124:  end
 
1125:  def debug(label, text)
 
1126:    work = label + ":"
 
1127:    for c in 1..text.length
 
1128:      work += padhex("%X" %text[c-1]) + ' '
 
1129:    end
 
1130:    log(BLUE + work + "Length:" + text.length.to_s + GREY)
 
1131:  end
 
1132:  def padhex(hex)
 
1133:    if hex.length==1
 
1134:      hex = "0" + hex
 
1135:    end
 
1136:    return hex
 
1137:  end
 
1138:end
 
1139:def cmd_ReceiveCommandForChild(cmd)
 
1140:### #484 Process Receive Command for Child
 
1141:log('DCE Command Received')
 
1142:
 
1143:dataIn(cmd)
 
1144:end
 
1145:#### 760 ####################################################################
 
1146:def cmd_760(id, pk_command, parameters, cmd=nil)
 
1147:@returnParamArray.clear
 
1148:log('DCE Send Command to Child 760 Received')
 
1149:
 
1150:dcein760(cmd)
 
1151:return @returnParamArray
 
1152:end
 
1153:#### 776 ####################################################################
 
1154:def cmd_776(arguments, cmd=nil)
 
1155:@returnParamArray.clear
 
1156:#Simulate a gsdin command...
 
1157:#[31mIN:02 06 22 30 02 64 00 0C 03 Length:9
 
1158:@simulation = 0x02.chr + 0x06.chr + 0x22.chr + 0x30.chr + 0x02.chr
 
1159:@simulation += 0x64.chr + 0x00.chr + 0x0C.chr + 0x03.chr
 
1160:log(AQUA + 'sending Simulated PLCBUS Command' + GREY)
 
1161:debugin(@simulation)
 
1162:dataIn(@simulation)
 
1163:return @returnParamArray
 
1164:end
 
1165:#### START SETTERS ####################################################################
 
1166:def initialize()
 
1167:super
 
1168:@returnParamArray=Array.new
 
1169:end
 
1170:####  END  SETTERS ####################################################################
 
1171:end
 
</pre>
 
  
 
= Links =
 
= Links =
 
* http://www.plcbus.com.cn/
 
* http://www.plcbus.com.cn/
 
* http://www.futurehomes.com.sg/PLCBUSinfo.htm
 
* http://www.futurehomes.com.sg/PLCBUSinfo.htm

Latest revision as of 02:20, 28 September 2015

Version Status Date Updated Updated By
710 Unknown N/A N/A
810 Working 1st May 2010 BongoWongo
1004 Unknown N/A N/A
1204 Unknown N/A N/A
1404 Unknown N/A N/A
Usage Information
Plcbus-logo.jpg

Status

We've implemented a new C++ driver for 0810b2. More information here: http://forum.linuxmce.org/index.php?topic=11170.0

About

PLCBUS Technology provides you the most perfect Home Automation solutions. Control one lamp minimally to the whole house, all the PLCBUS products range is including Lamp control, Appliance control, Remote telephone control, Computer control and Security System control. Based on the features: “High Reliability”, “Two-Way Communications”, “No rewiring necessary”, etc, PLCBUS Technology will be new Home Automation standard in the following 10-15 years.

Demo video:

Features

  • Reliability
  • 2-way communication
  • Powerline, no rewiring
  • ~200bps
  • 230V/50hz

Interfaces

Command specification


Links