Author Topic: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)  (Read 6562 times)

ddamron

  • Alumni
  • wants to work for LinuxMCE
  • *
  • Posts: 962
    • View Profile
    • My LinuxMCE User Page
Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« on: January 27, 2008, 07:01:31 am »
I think I'm pretty much ready to release this into the wild.
I've completely rewritten this code to be FULLY threaded and bidirectional.

This Beta version has a PLCBUS class which is being tested now. (all thumbs up so far!)

The PLCBUS class contains all the specific protocol conversions.  It can be re-coded for support of another protocol while still maintaining threading and bidirectional support.

The bulk of the code is in #373 Private Method Listing and can be Copy/Pasted in from here: http://rafb.net/p/f80h1p14.html

The rest of the code is so small, I'm posting it here.
#351 Process IDLE
Code: [Select]
errorHandler()
#350 Process Incoming Data
Code: [Select]
### #350

while(true)
  @buff = conn_.RecvDelimited(0x02.chr,100) #stx
  if(@buff.length() == 0)
    break
  end
  @buff2 = conn_.Recv(1,10) #Length of message
  @buff +=@buff2
  @length = @buff2[0]
  @buff += conn_.Recv(@length + 1, 100)
  debugin(@buff)
  dataIn(@buff)
end


# this routine needs to be handled better.
# possibly with regular expressions.

#355 Process Initialize
Code: [Select]
#########################
# Written by Dan Damron #
#########################

initDevices()

#384 Process Receive Command for Child
Code: [Select]
### #484 Process Receive Command for Child
log('DCE Command Received')

dataIn(cmd)

Some of you sharper characters out there MAY notice that I treat
Process Receive Command for Child AND Process Incoming Data the same.
They BOTH call datain()

Maybe that might pique your interest a bit.. Maybe not..

For all the guts and glory, (and about 200 hours hard work) look at #373 http://rafb.net/p/f80h1p14.html

P.S.

The PLCBUS class has a TON of instructions on how to use it.

Regards,

Dan
The only intuitive interface is the nipple.  After that it's all learned.
My other computer is your windows box.
I'm out of my mind.  Back in 5 minutes.
Q:  What's Red and smells like blue paint?

A:  Red Paint.

colinjones

  • Alumni
  • LinuxMCE God
  • *
  • Posts: 3003
    • View Profile
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #1 on: January 27, 2008, 11:47:40 am »
Well done, mate!!!

royw

  • Guru
  • ****
  • Posts: 261
    • View Profile
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #2 on: January 27, 2008, 12:29:34 pm »
Howdy,

I took a look at your code more as a curiosity of how ruby is being used in LinuxMCE than in actually using the feature.  I thought I'd give you a few comments in a friendly code review style.

* you might consider using rdoc style comments.  That will make publishing the API easier.

* naming choices are good, long names

* mixed constant naming, sometimes all uppercase, sometimes mixed (camel) case (ex: NotReady = 1).  Convention is constant object references should be all uppercase with underscores.  Camelcase is used for class and module names.

* a few methods are a little high on the line count, but mostly because of all the good logging calls.

* Your log() methods have me a little confused.  Why all the putc calls?  Wouldn't something like the following accomplish the same?

Code: [Select]
def log(line)
  File.open("/var/log/pluto/" + device_.devid_.to_s + "_Generic_Serial_Device.log", "a") do |logfile|
  logfile.puts '(***)' + line.to_s.gsub('<',' ')
  end
end

* in several debug methods you use this construct:

Code: [Select]
  work = label + ":"
  for c in 1..text.length
    work += padhex("%X" %text[c-1]) + ' '
  end

string concatenations are usually costly.  It might be better to append to an array then join to a string:

Code: [Select]
  array = []
  for c in 1..text.length
    array << padhex("%X" %text[c-1])
  end
  work = label + ':' + array.join(' ')

but then again, these are in debug methods so performance is probably not an issue.  :-)

* in gsdcommand() I'm not sure what the return value will be when the case statement hit's one of the when statements that don't have a block.  For example, what will be returned when @gsdcommand is 'REPORT ONLY ON PULSE'?  You might need an extra return statement at the bottom of the method.

* Sometimes the really long cases can be replaced with a hash lookup.  For example, in gsdcommand, you may want to play with something like:

Code: [Select]
FUNCTIONS = {'ALL UNIT OFF' => Proc.new {@gsdparams[10] = '0';return 48},
               'ALL LTS ON' => Proc.new {@gsdparams[10] = '1';return 48},
               #...
              }

def gsdcommand #returns DCE EVENT!! and compiles params
  p = FUNCTIONS[CommandFunctions[@gsdcommand]]
  p.call unless p.nil?
  return 0
end

But then again, the big case statement is probably more readable.  :-)

Overall, very nice looking code.  :-)

Have fun,
Roy

ddamron

  • Alumni
  • wants to work for LinuxMCE
  • *
  • Posts: 962
    • View Profile
    • My LinuxMCE User Page
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #3 on: January 27, 2008, 03:44:47 pm »
Howdy,

I took a look at your code more as a curiosity of how ruby is being used in LinuxMCE than in actually using the feature.  I thought I'd give you a few comments in a friendly code review style.

* you might consider using rdoc style comments.  That will make publishing the API easier.

* naming choices are good, long names

* mixed constant naming, sometimes all uppercase, sometimes mixed (camel) case (ex: NotReady = 1).  Convention is constant object references should be all uppercase with underscores.  Camelcase is used for class and module names.

* a few methods are a little high on the line count, but mostly because of all the good logging calls.

* Your log() methods have me a little confused.  Why all the putc calls?  Wouldn't something like the following accomplish the same?

Code: [Select]
def log(line)
  File.open("/var/log/pluto/" + device_.devid_.to_s + "_Generic_Serial_Device.log", "a") do |logfile|
  logfile.puts '(***)' + line.to_s.gsub('<',' ')
  end
end

* in several debug methods you use this construct:

Code: [Select]
  work = label + ":"
  for c in 1..text.length
    work += padhex("%X" %text[c-1]) + ' '
  end

string concatenations are usually costly.  It might be better to append to an array then join to a string:

Code: [Select]
  array = []
  for c in 1..text.length
    array << padhex("%X" %text[c-1])
  end
  work = label + ':' + array.join(' ')

but then again, these are in debug methods so performance is probably not an issue.  :-)

* in gsdcommand() I'm not sure what the return value will be when the case statement hit's one of the when statements that don't have a block.  For example, what will be returned when @gsdcommand is 'REPORT ONLY ON PULSE'?  You might need an extra return statement at the bottom of the method.

* Sometimes the really long cases can be replaced with a hash lookup.  For example, in gsdcommand, you may want to play with something like:

Code: [Select]
FUNCTIONS = {'ALL UNIT OFF' => Proc.new {@gsdparams[10] = '0';return 48},
               'ALL LTS ON' => Proc.new {@gsdparams[10] = '1';return 48},
               #...
              }

def gsdcommand #returns DCE EVENT!! and compiles params
  p = FUNCTIONS[CommandFunctions[@gsdcommand]]
  p.call unless p.nil?
  return 0
end

But then again, the big case statement is probably more readable.  :-)

Overall, very nice looking code.  :-)

Have fun,
Roy


Roy,

Hello and Thanks for the review!
This is my SECOND attempt in ERb and I'm still learning the language..

RDOC style Comments: Don't know that yet. will look into it
(I have a book on it, but haven't read that chapter yet)
Naming Conventions:
I wasn't aware of that:  Ruby's naming conventions are based on the first character..
Yes, I know a few methods are a bit high on the line count ;)
half of those lines are logging and comments. (which can be taken out)
regarding my log():
ok, I originally wrote the log() routine when I started ruby..
I ran into problems displaying XML in the log.
Then, later, I ran into problems displaying Object.inspect in the log..
out of much frustration, that is what I ended up with, and as long as it worked (ie displayed what I needed it to) I left it.
ERb (at least in linuxmce) doesn't like displaying <object>. I tries to parse it.
Even in the code window, when you want to make a String='<?xml version="1.0"?>', when you save it, you get String=''
The debug calls are just them.  debug.  they can be removed.

That's an interesting way to use a hash!  I like that!
As far as that long case statement.. Yeah, I should add a return at the end.
Most of those functions aren't needed.. but I copied them in from the specs, so they won't hurt.

I've been using Ruby for about 2-3 months now..
Nice to see some feedback!

Regards,

Dan

The only intuitive interface is the nipple.  After that it's all learned.
My other computer is your windows box.
I'm out of my mind.  Back in 5 minutes.
Q:  What's Red and smells like blue paint?

A:  Red Paint.

ddamron

  • Alumni
  • wants to work for LinuxMCE
  • *
  • Posts: 962
    • View Profile
    • My LinuxMCE User Page
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #4 on: January 27, 2008, 08:56:35 pm »
Ok, after a few hours of testing, with Hari (in Germany) and myself (in Canada)..

Added a $delayBetweenTransmit in the initDevices() to allow for a processing delay(of the interface)

Then, after even more testing, we realised a key problem:

PLCBUS (or at least this interface) isn't threaded! ie, I HAVE to wait for a response to a command.

AAAAAAAAAAAAAAAAAAAAAAARRRRRRRRRRRRRRRRGGGGGGGGGGGGGGHHHHHHHHHHHHHH!!!!

Ah well.. So, instead of throwing it all away, I've added a threaded flag to the command object.
If this flag is NOT set, it will force the routines to wait for a response to that command.

Interestingly enough, it wasn't that hard to do.. and as a side benifit, commands going the other way are not impeded.. ie, switching on a light switch will make it to DCE (and hence the floorplan) whether threading is suspended or not.

In other words, the Threading Suspension is only 1 way: DCE to GSD.

Still have a few things to iron out, but I will post new code soon.

Best Regards,

Dan
The only intuitive interface is the nipple.  After that it's all learned.
My other computer is your windows box.
I'm out of my mind.  Back in 5 minutes.
Q:  What's Red and smells like blue paint?

A:  Red Paint.

royw

  • Guru
  • ****
  • Posts: 261
    • View Profile
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #5 on: January 27, 2008, 11:03:47 pm »
regarding my log():
ok, I originally wrote the log() routine when I started ruby..
I ran into problems displaying XML in the log.
Then, later, I ran into problems displaying Object.inspect in the log..
out of much frustration, that is what I ended up with, and as long as it worked (ie displayed what I needed it to) I left it.
ERb (at least in linuxmce) doesn't like displaying <object>. I tries to parse it.
Even in the code window, when you want to make a String='<?xml version="1.0"?>', when you save it, you get String=''
The debug calls are just them.  debug.  they can be removed.

You might want to try something like:

require 'cgi'

puts CGI.escapeHTML(line)

that will escape html characters ('<' => '&lt;', '&' => '&amp;',...)

Have fun,
Roy

bulek

  • Administrator
  • wants to work for LinuxMCE
  • *****
  • Posts: 909
  • Living with LMCE
    • View Profile
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #6 on: January 28, 2008, 10:42:35 am »
Hi,

first great thanks for great work. I'm really interested in this one. I have something similar, but done as external driver in Perl, so I'm thinking about moving it to Ruby - but my Ruby knowledge is nearly nonexistent, so don't know if this migration would be easy.

- does anyone know of any source how to learn Ruby and your code efficiently ?

- do you have an option to respond to events also - since you use threads, does this mean you can start something that is continuosly running (I'm interested in this, cause I also try to implement other things for my home automation system - integration of scenes, speech announcements, etc..) ?

- under what licence do you plan to release the code ?

- what steps are needed to customize code to some other protocols (I need UDP connection to my system) ?

- this is really interesting idea - to have common skeleton on LMCE's side and just change modules for each separate protocol on top of that...

Thanks in advance for any opinions ,

regards,

Bulek.
Thanks in advance,

regards,

Bulek.

ddamron

  • Alumni
  • wants to work for LinuxMCE
  • *
  • Posts: 962
    • View Profile
    • My LinuxMCE User Page
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #7 on: January 28, 2008, 08:09:56 pm »
Hi,

first great thanks for great work. I'm really interested in this one. I have something similar, but done as external driver in Perl, so I'm thinking about moving it to Ruby - but my Ruby knowledge is nearly nonexistent, so don't know if this migration would be easy.

- does anyone know of any source how to learn Ruby and your code efficiently ?

- do you have an option to respond to events also - since you use threads, does this mean you can start something that is continuosly running (I'm interested in this, cause I also try to implement other things for my home automation system - integration of scenes, speech announcements, etc..) ?

- under what licence do you plan to release the code ?

- what steps are needed to customize code to some other protocols (I need UDP connection to my system) ?

- this is really interesting idea - to have common skeleton on LMCE's side and just change modules for each separate protocol on top of that...

Thanks in advance for any opinions ,

regards,

Bulek.


Bulek,
Thanks for the response! (I love hearing feedback)

Regarding your questions: (I'll try to answer them)

I just googled Ruby... learned by trial and error.. Because Ruby is an interpreted language, you can always test in irb.

I'm not sure I know what you mean by responding to events...
My code does NOT use threads (as they exist..) I basically created a 'kernel' that allows each 'command' object to be handled seperately from other 'command' objects.

That said,  if you want to respond to a DCE Event, not a problem.  an Event is a message, just like a command, just like gsd data coming in, just like gsd data going out..

I pass ALL data IN/OUT (to and from DCE and GSD) to my 'protocolObject' class..
It's up the that class to either ACCEPT the data or REJECT the data..

Take a closer look at the remarks in the PLCBUS class... you'll see what I mean.

Under what license do I plan to release the code!?? I firmly believe in GPL.

What steps are needed to customize the code:  Create a new protocol object class, and implement the required methods.  That's it.

It is designed to be DROP IN replaceable.

HTH,

Dan
The only intuitive interface is the nipple.  After that it's all learned.
My other computer is your windows box.
I'm out of my mind.  Back in 5 minutes.
Q:  What's Red and smells like blue paint?

A:  Red Paint.

royw

  • Guru
  • ****
  • Posts: 261
    • View Profile
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #8 on: January 28, 2008, 09:42:50 pm »
- does anyone know of any source how to learn Ruby and your code efficiently ?

The definitive and very readable book is "Programming Ruby, The Pragmatic Programmers' Guide" by Dave Thomas.  The older release of the book is available online at http://www.ruby-doc.org/docs/ProgrammingRuby/

The ruby language site is http://www.ruby-lang.org/en/

A nice quick reference (once you learn the language) is: http://www.zenspider.com/Languages/Ruby/QuickRef.html

And finally the API docs are at: http://www.ruby-doc.org/

If you decide to look into Rails, then start with Dave Thomas' "Agile Web Development with Rails".  Rails itself is an excellent example on how to use Ruby.

Have fun,
Roy

nite_man

  • NEEDS to work for LinuxMCE
  • ***
  • Posts: 1019
  • Want to work with LinuxMCE
    • View Profile
    • Smart Home Blog
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #9 on: January 30, 2008, 11:11:37 am »
I develop on Perl more than 6 years. Recently I created a GSD interface with Ruby. So, I can say that Ruby is very close to Perl. Except Ruby is typified language. IMHO the porting application from Perl to Ruby shouldn't be a big deal. Except you use a lot of Perl modules :)
Michael Stepanov,
My setup: http://wiki.linuxmce.org/index.php/User:Nite_man#New_setup
Russian LinuxMCE community: http://linuxmce.ru

ddamron

  • Alumni
  • wants to work for LinuxMCE
  • *
  • Posts: 962
    • View Profile
    • My LinuxMCE User Page
Re: Threaded GSDRuby Beta Ready! (c/w PLCBUS bidi support)
« Reply #10 on: January 30, 2008, 09:02:09 pm »
I've started a wiki for Threaded Ruby.
http://wiki.linuxmce.org/index.php/Category:ThreadedRuby
Anyone, please feel free to format it better...

Regards,

Dan
The only intuitive interface is the nipple.  After that it's all learned.
My other computer is your windows box.
I'm out of my mind.  Back in 5 minutes.
Q:  What's Red and smells like blue paint?

A:  Red Paint.