I recently constructed a mini cluster consisting of 3 Raspberry Pi 3s.  I am planning on using these machines for various little projects.  I’ve installed some services on one of the nodes.  Currently that node hosts Redis and RabbitMQ instances.  I’m sure that I’ll have other services to install in the near future.  I may even use it to tinker with clustering those services.  Below are some pictures of the cluster as I was putting it together and a parts list.

Materials:

I was tinkering around with replacing the print statement with the print function in a Python 2 script when I ran across this peculiar oddity.

Notice that sequence is just importing the future print function as different names in each iteration.  The oddity is that the first import fails but the third (which is exactly the same) succeeds after performing the second.

** Note: I don’t know if replacing print with the print from the futures module is a wise thing to do.  I was simply using it while trying out some code. **

Versions tested: Python 2.7.10 (OSX), Python 2.7.6 (Ubuntu 14.04).

Have you ever encountered a situation where it would be beneficial to save whatever is written to the console across browser sessions?  If you have, you know there are not many solutions.  I recently decided that localStorage would be a good candidate to implement a solution to this problem with.

logsaver.js

logsaver.js is a lightweight, simple log preservation script.  It utilizes the flexibility of JavaScript to replace the default console.log function with a new, customized one.  Along with writing messages to the original console.log, this custom console.log  also writes messages to the specified localStorage key.

  • To start saving console.log messages, call startSavingLog().
  • To stop saving console.log messages, call stopSavingLog().
  • To clear saved console.log messages, call clearSavedLog().
  • To completely remove the localStorage key used by logsaver, call removeSavedLog().

For more information on options and how to use them, checkout the readme.

While you can copy the source below, I strongly recommend grabbing the latest from github here: logsaver.js.

Notes:

  • It doesn’t handle objects well.  Results in [Object object] appearing in the localStorage key value.  This is because localStorage is limited to strings.
  • It is possible to exceed the maximum space allocated to you in localStorage.  For desktop browsers, Chrome and Firefox have a 10 MB limit, while Safari and IE both have a 5 MB limit.  These number differs for mobile browsers.  More details.  In this event, logsaver.js will stop trying to save the log and display additional error messages in the console.

v0.1.0 Source

Raspbian GUI up and running.

This week I ordered and received the official Raspberry 7″ touchscreen ($60).  I’ve been tinkering with some ideas for it (some car based projects) and wanted it on hand to try out.

Opening the Box

The screen is packaged and presented really well.  It comes with all that you need to connect and power it from the Pi itself.  It comes with 4 screws to mount the Pi, the ribbon cable to connect it to the Pi’s DSI port, and 4 jumper wires, 2 of which are for powering the display on the Raspberry Pi 2 B+.  The other 2 are used when attaching the display to an older model A or B.

The Screen Itself

The screen itself seems really well made, I’m really impressed by it.  The LCD side seems pretty sturdy and the backside seems better than I would have expected.  Mine has a little give around the are the ribbons from the control board enter the LCD itself, but its nothing to complain about.

Connecting It All

In this case with the Raspberry Pi 2 B+, the screen connects easily via DSI ribbon and 2 jumpers to 5V and ground.  Once wired its an easy job to mount the Pi onto the screen.  In these pics you also see my cheap wifi and old keyboard dongle.  I think I will want to buy a good Bluetooth adapter and keyboard shortly.  I found a really need looking one here: http://www.amazon.com/gp/product/B00BX0YKX4.

Up and Running

Once all connected, the Pi boots right up to the console.  At this point you need the external keyboard to actually login and run startx, unless you’ve already configured Raspbian to do so.  You will also need to install a virtual keyboard like Florence or Matchbox.

Using It

The biggest shortcoming is the need for a physical keyboard, like I mentioned in the preceding section, and it is probably the biggest drawback.  The out of the box touch features seems only to augment physical keyboard functionality.  That’s because unlike Android or iOS, the virtual keyboard isn’t dynamic, it is either always there or not.  I suppose that a custom interface would be more touch oriented.  The one oddity I have found is that counter to other touch screens, the hotspot for a touch seems off and to me it seems more exaggerated near the edges of the screen.  It’s not a show stopper, but takes some getting used to.

Overall Opinion

After getting it all hooked up, I found that it seems a bit clunky.  It left me wondering if a better solution isn’t just a raspberry pi running as a server and using a Android or iOS device as a head.  However, assuming you stick with the Raspberry driving its own display, a longer cable might be desirable, depending on your project.  In that case a regular HDMI touchscreen with usb connections might be the better fit.

The lack of good cases is also a problem.  Nothing I have found yet, fully encloses the pi and the display.  Coincidentally, I had an old project box laying around that seems to fit almost perfectly.  At 7.5″ x 4.3″, the Hammond 1591ESBK‘s dimensions are only a little shy of the actual dimensions of the displays bezel (less than 0.25″).  I’ll post new photos if / when I do that.

Other Resources:

With the exploration of space and the eventual colonization of Mars humanity needs to establish a method for improving internet connectivity for people on the surface.

One method of achieving this is to place one or more satellites in high orbit around the planet.  These would use interplanetary internet(delay tolerant) technology and protocols to service requests as well as actively mirror content for primary sites located on Earth.  The goal of this strategy is to reduce the latency of user requests from 8-48 minutes down to at most a few seconds for popular content.

What is needed for a single node:

  • High bandwidth communications equipment similar to what would have been on the Mars Telecommunications Orbiter.
  • A cluster of servers in an a spacecraft the the size of a supply module.  Something similar to Microsoft’s Project Natick would be about right for a first generation.  There would be a redundant capacity built in to cover eventual server failure.
  • A heat management system.
  • A nuclear power generation system.

Now we just need NASA, Microsoft, SpaceX, Amazon (w/Blue Origin) AWS – Mars, or Google to make it happen!

Have you encountered the following scenario?

You are trying to solve a problem (or helping solve a problem) and know or at least think you know the solution.  You are in the middle of implementing it when someone else looks at it and says, “why don’t you do it this way, isn’t this way easier/better?”  Taking a step back, you realize that the question not only has merit but is a better and much more obvious solution; you can’t believe you missed it.

What happened?

I think its because you were too close to the problem and had developed a very narrow focus.  That narrow focus prevented you from seeing the better solution.  Perhaps this is even a variation of functional fixedness in that we’ve latched onto an idea of how to solve a problem and our mind’s may not see alternatives easily.

What can we do?

  • Think about the broad (or product) level goals regularly.
  • Entertain questions and/or suggestions from others.
  • Ask: “Is this the best way?”
  • Ask: “Is this the practical way?”
  • Don’t overthink the problem.
  • Get it working then evaluate the solution and/or do a code review!

The python logging module offers a wide variety of logging options and handlers.  One thing missing from the documentation is when to use each level.

A quick foreword

You really should familiarize yourself with the logging package.  How to create new loggers (I find creating them by module very useful).  There are many ways to configure logging, I tend to like dictConfig from logging.config (but start off with basicConfig form logging).

A Word on Optimal Setups

I prefer to setup my logging with each module having its own logger.  This allows me to configure logging levels at a package and/or module level.  I typically do the following in each module to create a logger.

Assuming my package structure consists of the following:

– foo (package)
—– core (module)
—– bar (module)

We can configure varying levels of logging for each element, as seen in the following snippet from a dictConfig.

In this example, the root ( ” ) logger (those not configured by any other settings) reports INFO level and up messages.  With the exception of the bar module, the foo package only reports WARNING level and up messages.  The bar module is set to a more verbose DEBUG level, to show information needed for debugging.

Selecting A Log Message Level

Out of the box, there are six default logging levels recognized by the logging module, most are self-explanatory.  I’ll just make some notes about usage.  (From here on out, I’ll refer to my logging instance as logger.)

For general status messages, you should use logger.info (INFO).  For errors, use either logger.critical (CRITICAL) or logger.error (ERROR).  For all exceptions, use logger.exception (ERROR).  logger.exception will automatically include stack trace information about the exception for you in the log. When you want verbose debugging information, use logging.debug (DEBUG)

In Closing

  • Use the logging module instead of print statements.
  • Always use logger.exception for logging exceptions.
  • Favor logger.debug for verbose log statements.
  • Favor logger.info for most other log statements (with the exception of errors).
  • Don’t forget that each of the logging functions uses C-style formatting.