Sunday, September 27, 2009

Great Website for Printing Patents

It's been a busy day and I'm finishing it with some patent work. I wanted to share a really great discovery. PAT2PDF is a free site that seems to be somewhat supported by donations (I made one!). The site accepts a search phrase for the following types of items:
  • US Utility Patent
  • US Pre-Grant Publication
  • US Design Patent
  • US Plant Patent
  • US Reissue
  • US Statutory Invention Reg.
You can even issue multiple requests by separating terms with semicolons.

The site looks up your item, pulls it from the US Patent Office's website and assembles it into a single PDF for download. Sweet.

What I Learned About Garage Door Openers

A friend's garage door opener wasn't opening the door although the motor was running. I offered to try and repair it. After all, it already wasn't working; what was the harm?

After opening the cover the problem was obvious. The nylon gear which drove the shaft that drove the sprocket (which is a gear that is driven by or drives a chain), was split in half. I looked up the manufacturer on the 'Net, then the model number and ordered a replacement kit. I was so relieved that it came with a detailed instruction book!

Here's what I learned about this garage door opener:

Limit Switches

The limit switches are very simple. As the drive shaft turns, it drives a screw upon which is mounted a moving contact. As the screw turns, it moves the contact to one end or the other. One screw on each side of the moving contact has the other end of the contact. As soon as the moving contact meets the end contacts -- the door stops. Simple!

Rate Sensor
There is a rate sensor that measures the rate at which the motor is spinning. This was also simple. A cap on the motor shaft had a series of four slots and openings, which passed through a sensor with a tiny emitter and sensor. If the door gets blocked, the motor can't turn. If the motor can't turn and the unit has not hit one of the limit switches, and the door is moving down, the controller reverses direction. If the door is moving up, it stops. Simple!

Retaining Pins
There isn't any other way to get a retaining pin out other than with a hammer. The sprocket drive shaft holds the drive gear in place with two retaining pins. These fit tightly into place. I had to drive the lower pin out in order to slide the new drive gear into place and the only way to do that was with a hammer. As soon as the pin was flush with the shaft, I used a punch to continue driving the pin through the shaft. After the new drive gear was in place, it was hammering once again to get the pin back into position.

Disassembly & Reassembly

Check the orientation of things as you disassemble them. I made two good choice and missed one opportunity. Before unplugging drive motor power connectors, I confirmed that the diagram in the instruction booklet was accurate and took a picture of the setup with my phone. When re-assembling the unit, I had all the documentation that I needed. However, I didn't notice the tabs in the top plate that holds the drive shaft in position and ended up re-installing that plate rotated 1/3 around. I didn't notice the mistake until nearly the very last step of re-installing the protective plastic cap over the sprocket and drive chain. It didn't make sense to disassemble the entire unit at that point, so we're living with my error. Had I taken a picture of that unit before disassembling it, I would have had the necessary reference.

Clean Grease

Clean grease isn't so bad. Dirty grease is wicked icky, but the new clean grease was easy to put on and I didn't mind cleaning up afterwards.

End of the story: the garage door works perfectly now. And I had a lot of fun taking the durn thing apart and putting it together!

Configuring Drupal for McNiff Plumbing & Heating

As mentioned in my last post on Selecting Drupal for McNiff Plumbing & Heating, I wanted to talk about configuring Drupal for a mostly static site.

The requirements are:
  • Anonymous Users can view all content
  • The site is Page oriented; Home, Services, Comments, Contact Us
  • No navigation menu
  • No login options visible to anonymous users
  • No content titles, author information or posting dates on pages
  • No user comment links
To start with, I went to Administer >> Site Building >> Blocks and disabled nearly all the blocks. I changed the Navigation block to be visible only to Authenticated Users.

I then created the following pages: Home, Services & Comments and copied some of the content from the current site as a place holder. I also set the Menu Title Links in each of these pages to their base name, so that it could be referenced from a menu.

I used Administer >> Site Building >> Menus >> Primary Links to add a menu item for each page.

Next up was creating the Contact Us form. I enabled the Contact module in the Core - optional section, wen to "Administer By Module" and configured the permissions for the Contact Form and enabled "access site-wide contact form" for all users.

Back to the Menus to add a new Primary Link menu option for Contact by specifying the "contact" page as the target. After saving this new menu item, it was showing up as a new tab with the other menu pages. Great!

Let's check for an anonymous users. I opened up a different browser (I just hate logging out and in and out and in) and checked the development site. No joy in Mudville -- and no tab either.

Somewhere along the line, I was missing permissions. I checked and double checked that the menu was enabled and that anonymous users could access the contact form. I even typed the path into the other browser and the form displayed. Hmmm; not a permission problem because the anonymous user could see the form. The navigation link was simply not being displayed.

Back to Administer >> Site Building >> Contact Form >> Edit. There is a "Selected" option, which was set to "No". Changing that to "Yes" turned on the tab in the Anonymous User's view.

Yea!

Next up; clean up the pages to show only the pieces of information we want. This might require a custom View.

Selecting Drupal for McNiff Plumbing & Heating

I've been helping a local service provide, James McNiff of McNiff Plumbing & Heating improve his website. When we started, his site was a single page, over 60 keywords, and practically no inbound links. Website Grader gave it a 7 out of 100

My first work was to try and touch as little as possible and clean up the HTML so that the site was more search engine friendly. It was actually less time to re-implement the site in clean HTML with CSS, but it was still one page and still was lacking on the SEM side. Website grader raised it to an 8 out of 100.

Version 2 broke the single page into three pages, Home, Services, Comments and to add a rudimentary Contact form. I like working in Ruby on Rails, but his hosting provide charged extra for that application, so I used ROR to generate the web pages, captured them statically and uploaded the static content to his provider. Website grader raised it to a 12 out of 100.

Adding listings to his services and website to some business directories has helped, raising his score to 15.

However, Mr. McNiff didn't really like to content, which had been carried over from the original site and he wanted to be able to add pictures to his site. Given my interest in Drupal, I thought this was a perfect application for trying Drupal.

The hosting provide had a control panel installer for installing Drupal, which set up the MySQL database and installed Drupal 6.14. Here is a list of the modules that I added to begin configuring the site:
  • Admin Menu
  • Advanced Help
  • CCK
  • Devel
  • FCKEditor
  • Google Analytics
  • IMCE (for image upload)
  • INT Meta
  • Webform (although the Contact module looks sufficient)
Please note, that as of this posting, the Drupal site is hidden. As soon as it's ready, I'll swap Drupal to the HTML root and archive the current site.

Next up, a bit about configuring Drupal for a site with essentially static content.

Friday, September 18, 2009

Drupal 6 with GD on OS/X

In my last post on Apache, PHP & Postgres on OS/X, I left off with the step where I was installing Drupal. Heck, that was easy. I downloaded and unzipped Drupal, placed it into my Sites directory, set up a symbolic link and hit it with http://localhost/drupal. I had to adjust some permissions with a chmod -R a+w *, but the installer ran fine, found Postgres and finished nicely.

But Drupal's administrative page reported that I had problems because I was missing GD, which is necessary for image handling. This required a recompile of PHP. The documentation indicated that by adding the --with-gd, that PHP would compile with the built in GD distribution. Unfortunately, I needed other libraries, JPEG, PNG & ZLIB in particular. This is with PHP 5.2.10, please recall. Older versions used TIFF also, so it seems.

I ended up intalling FINK to make life easy. I ran the following commands:

sudo fink install libjpeg
sudo fink install libpng3

(use fink list libpng to find out which version you need to install fink reports that the package can't be found)

I then modified my PHP config command to be:

./configure --prefix=/usr/local/php5 --mandir=/usr/share/man --infodir=/usr/share/info --sysconfdir=/etc --with-zlib --with-zlib-dir=/usr --with-openssl --without-iconv --enable-exif --enable-ftp --enable-mbstring --enable-mbregex --enable-sockets --with-pgsql --with-apxs2=/usr/sbin/apxs --with-jpeg-dir=/sw --with-png-dir=/sw --with-gd --with-zlib-dir=/usr/local

Note that when using the --with-jpeg-dir=DIR commands, the DIR needs to be the directory in which the /lib directory that contains the .a or .so exists. That's why I used --with-jpeg-dir=/sw and not --with-jpeg-dir=/sw/lib.

Next is make and sudo make install. Then recycle the Web Sharing service and Drupal is reporting GD installed. Whoot!

Thursday, September 17, 2009

Apache, PHP & Postgres on OS/X 10.5 (Leopard)

The goal is to have Drupal running on OS/X using Postgres as the database.

I started looking at the MAMP install, but I don't want MySQL as part of the stack, so I didn't think it would work. However, I found Lullabot's post on Beginning with Drupal 6 and PostgreSQL on OS X 10.5 Leopard and John VanDyk claimed that the MAMP + plain vanilla install gave him the option of choosing which database to use. That didn't work for me -- the Drupal install gave me no such option.

So I tried testing the apache - php - postgres stack to make sure I could hit my long- working postgres database. Running a little php test showed that I wasn't able to connect to my postgres database and the documentation from the PHP site indicates that I needed to recompile php with the postgres option. So I got the latest PHP -- 2.5.10.

However downloading, configuring, makeing & installing, httpd was still using the original PHP 2.5.8 and not the new PHP 2.5.10. So said the phpinfo script after recycling httpd. Httpd uses the php5 shared object library in /usr/libexec/apache2. The libphp5.so had not been updated. Why? Is the problem with Apache?

DIYMacServer.com has an excellent series of articles on installing Apache on OS/X. I'm installing Apache in 32 bits mode on Leopard and chose to use the Darwin layout. So it was configure with the Darwin layout and all the options, make and sudo make install.

The next step was to edit /etc/apache2/httpd.conf and enable index.php, the user under which Apache will run to "_www", and allow the use of the .htaccess file. Next was enabling the use of the users directory in /etc/apache2 (I copied the original users directory into the new /etc/apache2 directory). To do this, I uncommented the Include /etc/apache2/extra/httpd-userdir.conf line in httpd.conf. I chose to not enable Virtual Hosts. I also changed the DocumentRoot to my Sites directory. Because this is a development environment, I also commented out the Deny from all directive in the block

With all that done, I fired up the "Web Sharing" from the control panel and hit http://localhost (which is how I configured the ServerName in my users .conf file). The default site came up, so I tried the phpinfo.php script. Nada. Not processing php. Well, there is no LoadModule directive for php5_module in the httpd.conf, so I added it. However, the reference libphp5.so was still from the older PHP installation, the one that was not compiled with support for Postgres.

Here's what worked:
  • Moved old /etc/apache2 out of the way
  • Made sure all httpd processes were shut down
  • Deleted old /usr/libexec/apache2/libphp5.so
  • Configured httpd-2.2.13 with the following. The Darwin layout preserved the ability to use the System Preferences to control httpd.
./configure -enable-layout=Darwin -enable-mods-shared=all
  • Did the make and sudo make install.
  • Edited the new httpd.conf with the changes described above & copied the user directory from the original apache2 directory to the new directory
  • Configured PHP with the following. Note the "--with-pgsql" and "--with-apxs2" commands (From the DIYMacServer site)
./configure --prefix=/usr/local/php5 --mandir=/usr/share/man --infodir=/usr/share/info --sysconfdir=/etc --with-zlib --with-zlib-dir=/usr --with-openssl --without-iconv --enable-exif --enable-ftp --enable-mbstring --enable-mbregex --enable-sockets --with-pgsql --with-apxs2=/usr/sbin/apxs
  • Finished with the make & sudo make install. This time I saw the libphp5.so being copied to the correct directory -- yea!
  • Fired up the web service from the System Preference panel and checked my phpinfo file. SUCCESS! We are now looking at PHP 5.2.10.
  • Wrote a small postgres test (below), created the table and added two names to it. SUCCESS! Whoot! We are in.
Next up: Drupal.

Sunday, September 06, 2009

Installing Spree eCommerce

I'm looking to update a website that was written in a decent, but not great website creator application. I want to write it in Rails (yea!) because I had such great fun creating the Zepatter.com website. I mean, that took less than 12 hours from sitting down with the GIMP to getting the application installed on the hosting environment. And a huge chunk of that 12 hours was figuring out how to get the hosting environment configured correctly. hehe.

So, I'm looking for an eCommerce engine for Rails. Yes, I could create the whole shopping cart and payment gateway on my own because there are tons of tutorials and general advice. However, I suspect that if I could find a full-featured engine, then someone else will have thought of -- and solved -- problems that will take me time to recognize and address.

So I came across Spree eCommerce.

However, I haven't updated Rails on my system in a while and Spree requires Rails 2.3.2. So I start by doing a

sudo gem update rails


which gets me to Rails 2.3.4. However, Spree wants 2.3.2 ONLY. So I remove Rails 2.3.4 and install 2.3.2. Then I install Spree according to the instructions. Then I try to create my first Spree application with:
spree mystore
Unfortunately, I got this error:
/usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:578:in `report_activate_error': RubyGem version error: hoe(1.5.3 not >= 1.8.0) (Gem::LoadError)

OK. No problem. Need to update hoe
~/src:sudo gem update hoe
Updating installed gems
Updating hoe
ERROR: While executing gem ... (Gem::InstallError)
hoe requires RubyGems version >= 1.3.1

OK. No problem. Need to update gem. After all,
~/src:gem --version
1.2.0
So I do the following:
~/src:sudo gem update --system
Updating RubyGems
Nothing to update
OK, this may be a problem. Referring to the rubygems documentation, one needs to do the following:
gem install rubygems-update
update_rubygems
However, this failed with:
~/src:sudo update_rubygems
/usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:578:in `report_activate_error': Could not find RubyGem session (>= 0) (Gem::LoadError)
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:134:in `activate'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:158:in `activate'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:157:in `each'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:157:in `activate'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:49:in `gem'
from /usr/local/bin/update_rubygems:18
Mark Howe has a helpful blog on the matter.

In the end, the trick was to uninstall the partly installed rubygems 1.3.5, install rubygems 1.3.4, then do the
update_rubygems
And all was well. I was able to update hoe and then successfully run
spree mystore

Friday, August 14, 2009

Fixing the Kenmore washing machine

My beloved wife said that the washer wasn't working.

"Typical", I thought, "the extended warranty expired about a month ago."

The washer wasn't draining water during the spin cycle. But, hey, my friends had this problem with their front loader a year or so ago. The repair man said that they were using way too much soap; that the front loader needs about half the volume of soap the top loader needs. Detergent bottles and measure are still assuming a top-loading washer (I haven't seen any detergent boxes that talk about the volume needed for your front-loader -- post a comment if you have). The extra soap clogs the outlet valve and prevents the water from getting out. So, armed with this completely inadequate knowledge, I grab a screw driver and start looking for screws.

We have a Kenmore 3.1 Cubic Foot Front Loader. There is a lower front panel with two screws holding it in place; so that's where I started. The outlet from the drum as visible on the right side of the machine when facing it. A rubber tube that connected to two drain points from the drum ran to a small impeller pump and then to the outlet line. Everything was held in place with pinch-clamps. So I pull it all apart. Some soap, hair, coins, pebbles and a few tiny toys, but it really didn't look like enough to stop the machine from draining. Put everything back together and test it. Water in; start the spin cycle, water drains, no spin. Damn; I have to pull off the back panel.

That's about 40,000 screws that don't want to come out. Most of them need some Liquid Wrench and a Vise Grip to get them started. Last thing I want are 30,000 stripped screws. Um; you do know that I'm exaggerating here, right? There were only 4,o00 screws.

The drum looks fine. The belt looks fine, but I pull it off to double check. The drum spins without any catching, grinding or stiffness. The belt has no wear at all. I pull off the motor. That spins with a purr. Back-tracking the wires from the motor, I get to the control unit. That's held in with two screws and has two power and control connectors.

I pull out the control unit and, well, damn. The plastic protective sheet that covers the circuit board has a brown spot in the center. Off come two more screws, so I can lift the sheet and sure enough, something burned out some transistors.

Off to Sears.com to look up the model & buy a new control board for $150 + $20 in enhanced shipping.

Slapped that puppy in and we have clean clothes!

You know what? There is no need for that extended warranty. There is nothing in that machine that I can't fix. Darn that feels good.

Monday, June 15, 2009

Replacing a 1st Gen iPod Nano headphone jack

A few years back, I was lucky enough to win an iPod Nano from the Clock Tower Law Group (because I returned a data sheet at the right time). It was pretty cutting-edge at the time and I really enjoyed listening to podcasts on a variety of subjects during morning runs. For about three months. At that point, it was "borrowed" by kit and kin and I've barely used it since. C'est la vie.

My wife, who is studying voice, relied upon the iPod heavily. She listened to music she was studying, new songs, recordings of her voice lessons, and warm-up routines. She would use the iPod to get her voice work in where ever possible; no small challenge while raising five children. So, when the iPod stopped working reliably, she was at a loss.

The symptoms were that the sound was not coming reliably through both headphone ear buds. I tried swapping headphones, listening to different music and as many other diagnostic comparisons as I could manage. I wish I knew how to put the iPod into diagnostic mode then. (Press and hold the center Activate button + the Menu button until the phone reboots. Then move your finger from the Menu button to the Left Arrow button and press and hold the Activate and Left Arrow button until the diagnostic menu appears. Press Activate + Menu to reboot when done).

Nonetheless, I determined that the headphone jack was defective. I despaired at the thought of trying to pry open the iPod and replace the headphone jack, but since the darn thing didn't work anyway, what did I have to loose?

I googled around for a 1st Generation iPod Nano headphone jack and purchased one for $6 from Binh An at bureenz@gmail.com through eBay. He was very helpful even when I initially purchased the wrong generation headphone jack. I also picked up a replacement battery since I knew I would have the unit open. Mr. Binh included an iPod tool for opening the unit at no cost.

I followed the directions at www.ifixit.com to open the unit and remove the motherboard. The headphone jack is held to the motherboard by a screw and there is a small nipple under the motherboard that fits into a hole in the headphone jack unit. I used a pencil tip on my soldering iron and removed the old headphone jack. I then stripped off as much old solder as possible with some solder braid and cleaned up the entire area by scraping away the solder paste that appeared.

Finally, I put the new headphone jack in place and carefully soldered the four leads to the motherboard. Keep your soldering iron hot and touch the tip to the leads one at a time. Wait a moment before moving to the next lead to let the board cool down.

Then I replaced the battery -- very straight forward compared to soldering the leads of the headphone jack. I used a tiny drop of cryanoacrylate to re-attach the grounding strap before closing up the unit. Make sure the ground strap runs from the headphone jack screw to the back plate.

Check that the little tabs on the metal back plate are all in the proper position before closing up the unit. They're easy to bend when opening the unit.

I charged up the battery and ran the unit through the diagnostics. Everything works perfectly and my wife has her iPod back for less than $20 in materials.

Tuesday, June 09, 2009

Supressing Object#id deprecation warnings

I picked up some Ruby on Rails code up which I was working a few months ago to complete the project. While adding and running my rspec tests, I started getting the following warning during test execution:

"Object#id will be deprecated; use Object#object_id"

The warning was coming from the super_inplace_controls plug in that I was using. I really like these controls, and wanted to clean up the warning.

So, I popped open vendor/plugins/super_inplace_controls/lib/super_inplace_controls.rb and checked out line 234, from which one of the warning was eminating.

Sure enough, there was, in the method id_string_for, the line:

"#{object_name}_#{method_name}_#{object.id}"

No problems, I'll just change "object.id" to "object.object_id". I did this here and on line 260 in the form_for_inplace_display method.

Of course, this broke the code and the in-place object no longer received its updates after changing a value. The ID part was necessary to retrieve the updated record and display the correct value after update. So I backed out my changes.

Some more searching and I came across a way to suppress warnings around a small block of code, which is exactly what I wanted. I didn't want to suppress all warnings, but I knew that the object.id had to be there (truth be told, I should have tried using just "object"); I just didn't want to hear about it.

To suppress the warning, I wrapped the offending line in Kernel::silence_warnings() {}. So the id_string_for method become:

def id_string_for(object_name, method_name, object)
     Kernel::silence_warnings {
        "#{object_name}_#{method_name}_#{object.id}"
    {
end

I tried the same thing for the form_for_inplace_display method and ended up putting the whole method into the silence_warnings block due to the scoping problems the block introduced.

The danger to this whole method is that, should this code base advance into a new version of Ruby or Rails where the object.id call causes an error, code that seems to work will suddenly break. On the plus side, this won't be a complex logic bomb to solve, but should come up right away in a standard testing cycle.