Monday, March 4, 2019

Talking MQTT

This post will be about using MQTT from the command line. Don't be afraid, next post will be instructions on how to do the same thing through the GUI. This post will allow someone to do some troubleshooting if the GUI isn't working, as well as some familiarity with some of the concepts of MQTT.

Before getting started, ensure Mosquitto is installed and running on an agent. For now, it doesn't need to be on the final server, it can be on any supported platform. There is no need even for another node. If running on a Linux system including Raspberry PI be sure to install both the server/agent as well as the clients:

sudo apt-get install mosquitto
sudo apt-get install mosquitto-clients

Once mosquitto is running, then it will be necessary to have two windows connected to the server, where commands can be entered. In one window, enter the command "mosquitto_sub" to subscribe to a topic using the local agent:

pi@raspberrypi:~ $ mosquitto_sub -h localhost -t test

In the other window, enter "mosquitto_pub" to publish a message to that topic:

pi@raspberrypi:~ $ mosquitto_pub -h localhost -t test -m "hello world"

The "-t" option to both "mosquitto_sub" and "mosquitto_pub" indicates the topic the message will be published to. The "-h" option to both is the agent that will handle the messages for the topic, and can be the host name, or the ip address. The mosquitto_pub has a "-m" option for setting the payload of the message that will be published. The mosquitto_sub will just output the payload to stdout. The two windows look something like:


Multiple windows can be opened to be subscribers. When the pub message is sent, they all will receive identical copies of the payload:


If there are nodes, payloads can be sent to them as well. The server/agent host (-h option) must be the same server/agent that the node is attached to. An example, the alarm sounder from the last post can be turned on using the mostuitto_pub application. The topics it is subscribed to are "alarm/light" for the LED, and "home/alarm" for the tone generator.

 pi@raspberrypi:~ $ mosquitto_pub -h localhost -t alarm/light -m "on"

or 

pi@raspberrypi:~ $ mosquitto_pub -h localhost -t home/alarm -m "off"

Using a simple topic/payload combination many items can be controlled. The next post will be the beginning of using Node-Red, a GUI for these commands. 


Stay tuned...

Friday, March 1, 2019

ESP8266 and MQTT

The ESP8266 is a wonderful kludge. It found exposure as a module (ESP-01) that could be added to a micro controller giving it WiFi connectivity. People eventually figured out it was a processor that was more powerful than the typical micro controller it was being added to. The ESP8266 is a 32bit RISC processor running at 80MHz. Eventually there were various development kits put together for it, including the Arduino IDE.

Looking at the Wikipedia page, you can see the device is available in multiple form factors, from small boards to full blown DevKits. The bare boards are designed to be added to various other projects. The Devkits are standalone systems that will typically have a USB port provided for programming, powering and dataIO.

For most of the work I have been doing in my home automation systems, I have been using the NodeMCU or WeMos clones. These are available from many vendors, including Sparkfun, Banggood and others. I have programmed them using the Arduino IDE. I have built little boxes for them using 3D printed boxes from designs that are already on Thingiverse.



Because these modules are so inexpensive, I am able to limit the complexity of the individual node. I have one node that is in my bedroom that only has a NodeMcu and audio oscillator. This will alert me when something is out of the ordinary in the house. If I go to bed and the garage door was left open, or if someone breaks into the house.

The most complex node is the thermostat I have in the sunroom. This node has a touch screen display for displaying the current temperature in the room, and allows setting the thermostat. It also has a temperature and humidity sensor for measuring the conditions in the room.  There is a separate node that will turn on the heater if the temperature is too cold.

Coding for a node


Most nodes have a similar pattern. All the sensors in the node will send a payload on an MQTT topic. All the outputs in the node will listen for specific MQTT topics to take action on. Most of the nodes will only be action nodes (relays, lights, sound, etc), or sensor nodes (door open, temperature, switches, etc). Keeping the node simple will allow the system to be more reliable. Typically, nodes that do both input and output will not have input actions do output actions.

The node must know the MQTT agent to connect to. For my house, I am using a RaspberryPI that is acting as it's own WiFi hotspot. This will allow me to move the RaspberryPI and all the nodes on that network without affecting the home WiFi. The RaspberryPi doesn't need to be connected to the internet for this to work. I'll show in future posts how connecting it to the internet can be useful and safe. A spare Windows, Mac or Linux computer can be used as well, I just like the portability of the RaspberryPi.



A simple output node

/**
 * Simple action node. makes noise when receives alert
 * 
 * home/alert
 * 
 * They are separate devices, but using Node Red can be connected.
 * 
 * TGB 9/30/18
 */

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <PubSubClientTools.h>


const char* ssid = "raspi-webgui";
const char* password = "XXXXXXXX";
const char* MQTT_SERVER = "10.3.141.1";


WiFiClient espClient;
PubSubClient client(MQTT_SERVER, 1883, espClient);
PubSubClientTools mqtt(client);

String s = "";

void setup() {
  Serial.begin(115200);

  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  pinMode(D5, OUTPUT);
  
  // Connect to WiFi
  Serial.print(s+"Connecting to WiFi: "+ssid+" ");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(s+" connected with IP: "+WiFi.localIP());

  // Connect to MQTT
  Serial.print(s+"Connecting to MQTT: "+MQTT_SERVER+" ... ");
  if (client.connect("HomeAlert")) {
    Serial.println("connected");
    digitalWrite(BUILTIN_LED, HIGH); // turn LED off

    mqtt.subscribe("home/alarm", topic1_subscriber);
    mqtt.subscribe("alarm/light", topic2_subscriber);
  } else {
    Serial.println(s+"failed, rc="+client.state());
  }

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("HomeAlert")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic","garageControl Reconnect");
      mqtt.subscribe("home/alarm", topic1_subscriber);
      mqtt.subscribe("alarm/light", topic2_subscriber);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" Resetting");
      // Wait 5 seconds before retrying
    }
  }
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }

  client.loop();
}


void topic1_subscriber(String topic, String message) {
  Serial.println(s+"Message arrived in function 1 ["+topic+"] "+message);
  if (message.equals("on"))
  {
    tone(D5, 1000, 0);
  } else {
    noTone(D5);
  }
}

void topic2_subscriber(String topic, String message) {
  Serial.println(s+"Message arrived in function 1 ["+topic+"] "+message);
  if (message.equals("on"))
  {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
  }
  else
  {
    digitalWrite(BUILTIN_LED, HIGH);
  }
}



For Arduino programmers, this should look familiar. There are some definitions at the top, including the SSID, password for the WiFi network. The IP address of the MQTT server is also there. The global defines are next, where the wifiClient is defined, along with pubsub client definitions:


PubSubClient client(MQTT_SERVER, 1883, espClient);
PubSubClientTools mqtt(client);

The client is defined to use the MQTT_SERVER ip address, on port 1883 (normal MQTT server port). and will use the espClient WiFi client. The mqtt tools will use this client definition. I define a String s, but it is only used for debugging, and could be removed. 

Then the normal Arduino Setup function is defined. This function completes the setup. 
It defines the debugging serial port baud rate, and sets the pinModes to "output" for the built in LED and the in that the tone generator is connected to. Looking at the NodeMCU pinout, D5 is next to a ground so it makes a very easy interface, requiring only a 2 pin header (see picture above). The NodeMCU has constants for the labeled pins, so it isn't necessary to translate Arduino GPIOs to NodeMCU pins in your code. 

The WiFi connection is attempted until a connection is made, with a half second between tries. Lots of debug print when successful. The build in LED will be turned on when the NodeMCU is powered up, I turn the LED off once the WiFi connection is established. This helps when the node is away from a debug terminal. 

The MQTT client is used to connect next. Many examples aren't clear, but each node MUST have a unique name. If two nodes have the same name, the MQTT server will be confused and not know where to send messages to. Once the connection to the MQTT agent is established, subscriptions can be made. The topics are subscribed to along with the callback methods that should be invoked with a message on that topic is made available. This node will allow the LED to be controlled and the tone will be sounded. 

There is a reconnect method that will be nearly identical to the connect bits in the setup() function. The reconnect will connect if the client looses the connection, like with the MQTT server is rebooted. The main loop() method will check for a connection, and if not there, will call reconnect(). After the connection is restored, then the client.loop() function is called to see if any messages have arrived on subscribed topics. 

If a message arrives on any of the subscribed topics, one of the two callback methods is called. The topic1 messages will turn the sound on or off. The topic 2 messages will turn the LED on. The message that the callbacks check is the payload of the message. This node has simple payloads, only "on" or "off". Other nodes could have more sophisticated payloads. Even this node could have different frequencies for the tone as the payload to make a simple alert more useful (low tone for window open, higher tone for the garage open). 




This will build in the Arduino IDE using the "LOLIN(WEMOS) D1 R2 & mini" board setting in the Arduino IDE.  

It may not be the most efficient, but to run this node, I have a simple wall wart, and USB cable connected to the microUSB port on the board. It runs no trouble from a 500ma USB wall wart. Larger nodes may need more current. 

Next post, I'll start talking about using the MQTT server and how to control and hear from the nodes. 

Friday, February 22, 2019

Intro to MQTT

In the previous post, I talked about how MQTT came about. In this post I will talk a little about what it is but mostly how to use it.



As a publish/subscribe (pub/sub) architecture, the nodes collect data or do actions, using a network connection. In the middle is a server or agent that will allow the nodes to only have a single connection. All the nodes connect to the server, and send or receive data with that one server. The server contains the smarts about who will receive any messages sent to it. Nodes are clients in the TCP/IP nomenclature. The MQTT agent is the server.

There is a normal TCP/IP connection protocol, where a server is listening for clients to connect. The Server will accept connections, and handle multiple clients communication. The details I won't go into, but you can read about it.

As a node connects, it may register certain topics that it will listen to. When the node connects, it must inform the server what message topics it will subscribe to. The server will make a list of these devices that are subscribed to the various topics.

Nodes may send messages on any topic, but only to the server. The server will repeat the message to each node subscribed to the topic. An example would be if a node was to send a message on the topic "outside/temperature" with a payload of 52 to the server, and there were 3 nodes subscribed to this topic, then the server would send a unique message with the topic "outside/temperature" and a payload of 52 to each of the three nodes subscribed.

A single node may subscribe to any number of topics, and send to multiple other topics. The payload of the messages sent is 65535 bytes. MQTT payloads are mostly free format, and can be single values or json formatted. Messages can be commands to set, or status of a node.

 The free format nature of the MQTT Nodes, message and topics can be a challenge for interoperability. All my nodes work the way they do for me, but your nodes may work differently. If you have a node that says it is a temperature sensor, how do I know what it is measuring the temperature of? There is a proposed standard called "Homie" to address most of the confusion.

Typically an MQTT setup will have a machine dedicated to be the MQTT agent. This machine must be running all the time, and ready to act on MQTT messages. There is no connection necessary to the cloud or any outside systems. Connecting to the cloud may be something you want to do for a particular application, or to relay some information out to a remote monitoring and control system.

Dedicating a whole Windows system is probably overkill, unless there is a great deal of processing needed on the received messages. Normally the MQTT server will just pass the messages along to the required recipients. For my home control system I am using a RaspberryPi 3B running Raspian, and I am using the mosquito MQTT server. Using apt-get, from the normal Raspian repository, MQTT can be installed.



For most of the nodes, I am using ESP8266 or ESP32 boards. These boards can be purchased locally for about $15 or mail order for $3-10. I typically need to add sensors and output to these boards so I do a little customization before deploying them. The MQTT libraries are in the normal Arduino library UI. I do all the programming in the Arduino IDE, I am not pushing the limits of anything, and just trying to make a simple reliable system.

The ESP32 and ESP8266 come in various formats. The various formats make adding peripherals convenient and mounting the devices as easy or complex as the box I put it in. I have a 3D printer, so I am able to package up the nodes in pleasant looking boxes.

In future posts, I start building nodes.


Saturday, February 16, 2019

Starting Home Automation

What does this have to do with an engine monitor?

Sensors!

Somewhere along about Nick O’Leary and Dave Conway-Jones of IBM’s Emerging Technology Services group had a side project where they came up with what we now call Node-Red. Before that (1999) there were two other engineers Andy Stanford-Clark (IBM) and Arlen Nipper (Eurotech) who wanted a way to monitor oil pipelines and came up with MQTT.

MQTT is a lightweight protocol for delivering messages from sensors to a server. The protocol is direction agnostic, allowing the server to send messages to the sensors as well. The messages provide multiple levels of Quality of Service (QoS) such that the messages can be reliable or unreliable depending on the application.

You've heard of IOT, and that is pretty boring, or not, and seems that people are excited about it or not. I was for a long time too, but then I started playing with things. I've been using ESP8266 systems for a couple years now. They are all that an Arduino can be, plus they support WiFi and other protocols. The ESP8266's can be programmed using the Arduino IDE, so that makes the very friendly to hobbiests and others. It is easy to come up with a quick project, and knock something out very quickly.

I'd been working on a bunch of sensors and control panels around the house just standalone, when I had a job where I was introduced to Node-Red, and saw the potential. I moved one of my projects from standalone to Node-Red and demonstrated that standalone was not the best way. Using Node-Red I can integrate sensors and control panels in varying ways, allowing easier updates, and more capabilities.

MQTT basics

The heart of the system is MQTT. Generally MQTT has "clients" around the edges, and a central "agent" or server. For open source projects, the easiest agent to work with is Mosquito since it runs on Windows or Linux systems equally easy. There are utilities included with Mosquito allowing monitoring and control without any other GUIs or anything.

MQTT is a publish/subscribe (pub/sub) protocol. Anyone can publish a message on any topic, but only the subscribers to that topic will receive the message. Mosquito is the arbiter of the messages. Mosquito will receive all the messages, but only send them on the the appropriate receivers.

A simple sensor can send a message, and the MQTT agent receive the message and make the message available to anyone registered on that topic. If a temperature sensor broadcasts a new reading, the door monitoring devices don't need to know about it. Likewise if the door open message is sent, the water sensing system doesn't need to know about it. Or maybe they do need some additional information, it all can be programmed later.

Node-Red teaser

Node-Red allows programming flows. A flow connects several inputs on various topics to any outputs based on a need to know.

The green "connected" boxes on the left are input MQTT nodes connected to an MQTT agent. The output of those boxes go into various other boxes. The green "msg.payload" boxes are there for debugging. The blue boxes are outputs to a User Interface (UI) and the The green "connected" boxes below are MQTT outputs nodes connected to an MQTT agent. 

This flow is looking at the sensors on the garage doors to know the current state (open/closed). They both feed the message into a door open alarm node. This node has some programming associated with it (something for a future post). If the doors are open during the night, an MQTT output node that has an ESP8266 and a sounder is in my bedroom that should wake me up. It isn't physically connected, it only is a WiFi device. 

I did something, else on the input ESP8266, not just the magnetic reed sensors. I also added a DS18b20 sensor that was to let me keep track of the outside temperature. The 18B20 works in Celsius, but I only think in Fahrenheit so I have a node here that converts the temperature from C to F. 


This code is fairly straight forward, and as you see, uses JavaScript as the language. The message came with a payload that contained a number. That number was multiplied by 9 divided by 5 and added to 32. The results was made to be the payload of the resultant message. The result message goes both to the debug output (msg.payload) and a new MQTT message on a new topic. 

I'll detail more of this in future blog posts. Come back soon. 






Wednesday, February 6, 2019

Floor Temperature


The building that I work in is extremely cold in the winter time. Many Mondays, especially, the area where I work is below 60 degrees. I bought a simple indoor outdoor thermometer, and put the outdoor sensor on the floor, and left the main unit on top of my desk. There is often a 15 degree difference from the floor to the top of the desk.



The building has a unique architectural feature. The first two floors are indented slightly over the third floor, where I sit. I actually have a window seat which, in this case, is a distinct disadvantage. The floor under my desk actually is a slab of concrete exposed to the outside air with little to no insulation. There is a layer of carpet, that is glued to the to the concrete that may be providing some insulation.

I decided to further instrument the situation. I build a matrix of temperature sensors connected to an Arduino. I decided to use the DS18B20 sensors since there are inexpensive, and provide a direct temperature readout with out using the A/D converters. There is a library for using these sensors, and several options for connecting them.

I modified the example to only read the sensors I was interested, and output CSV format to the USB interface. I collected this file, and was able to graph the output. I didn't use a RTC module, so the time output is relative to the start time.

I set up a grid of 6 sensors using yardsticks both for support and to give consistent distance:

The sensors closest to the wall of course gave the lowest readings, but even 3 feet in from the wall showed temperatures about 5 degrees warmer. The ones that were 5 feet from the wall were another 5 degrees warmer. The second set verified the results. 


// Include the libraries we need
#include <TimeLib.h>


#include <OneWire.h>
#include <DallasTemperature.h>


// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
DeviceAddress  device[8];
int            numSensors=0;

void setup(void)
{
  // start serial port
  Serial.begin(115200);
  Serial.println("Dallas Temperature IC Control Library Demo");

  // Start up the library
  sensors.begin();

  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  numSensors = sensors.getDeviceCount();
  Serial.print(numSensors, DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: "); 
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");


  // Search for devices on the bus and assign based on an index. Ideally,
  // you would do this to initially discover addresses on the bus and then 
  // use those addresses and manually assign them (see above) once you know 
  // the devices on your bus (and assuming they don't change).
  // 
  // method 1: by index
  for(int i=0; i<numSensors; i++)
  {
      if (!sensors.getAddress(device[i], i)) Serial.println("Unable to find address for Device 0"); 
  }

  // show the addresses we found on the bus
  for(int i=0; i < numSensors; i++)
  {
      Serial.print("Device ");
      Serial.print(i);
      Serial.print(" Address: ");
      printAddress(device[i]);
      Serial.println();
  }

  // set the resolution to 9 bit per device
  for(int i=0; i< numSensors; i++)
      sensors.setResolution(device[i], TEMPERATURE_PRECISION);

}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < numSensors; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  //Serial.print("Temp C: ");
  //Serial.print(tempC);
  Serial.print((int)DallasTemperature::toFahrenheit(tempC));
}

// function to print a device's resolution
void printResolution(DeviceAddress deviceAddress)
{
  Serial.print("Resolution: ");
  Serial.print(sensors.getResolution(deviceAddress));
  Serial.println();    
}

// main function to print information about a device
void printData(DeviceAddress deviceAddress)
{
  printAddress(deviceAddress);
  Serial.print(", ");
  printTemperature(deviceAddress);
  //Serial.println();
}

/*
 * Main function, calls the temperatures in a loop.
 */
void loop(void)
{ 
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  //Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();
  //Serial.println("DONE");

  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(", ");
  // print the device information
  for(int i=0; i<numSensors; i++)
  {
      printData(device[i]);
      if (i<numSensors-1)
         Serial.print(", ");
  }
  Serial.println();
  delay(10000);
}

void printDigits(byte digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits,DEC);
}


So the output looks similar to:
0:11:12, 28FFD2890117, 70, 28FFF2F10117, 70, 28FF1A040217, 71, 28FFC1F70117, 72, 28FF59070217, 71, 28FFED8D0117, 70
0:11:23, 28FFD2890117, 70, 28FFF2F10117, 70, 28FF1A040217, 71, 28FFC1F70117, 72, 28FF59070217, 71, 28FFED8D0117, 70
0:11:33, 28FFD2890117, 70, 28FFF2F10117, 70, 28FF1A040217, 71, 28FFC1F70117, 72, 28FF59070217, 71, 28FFED8D0117, 70
0:11:43, 28FFD2890117, 70, 28FFF2F10117, 70, 28FF1A040217, 71, 28FFC1F70117, 72, 28FF59070217, 71, 28FFED8D0117, 70
0:11:53, 28FFD2890117, 70, 28FFF2F10117, 70, 28FF1A040217, 71, 28FFC1F70117, 72, 28FF59070217, 71, 28FFED8D0117, 70
0:12:03, 28FFD2890117, 70, 28FFF2F10117, 70, 28FF1A040217, 71, 28FFC1F70117, 72, 28FF59070217, 71, 28FFED8D0117, 70
0:12:13, 28FFD2890117, 70, 28FFF2F10117, 70, 28FF1A040217, 71, 28FFC1F70117, 72, 28FF59070217, 71, 28FFED8D0117, 70
 
CSV files are easier it ingest, and graph using whatever spreadsheet program one might like.

The night I took a sample, the temperature was down around 10-15 degrees below zero. The graph of the output looks like:

At the lowest, the temperature hit 49 degrees against the wall.

 

Monday, August 21, 2017

Finally, ADS-B for under $1000.

I am sure everyone has heard of uavionix by now, but wow! This company has it together. They found a potential market for more than the GA market. They figured if they built it, they would come. The UAS market is starting to be a potential market for ADS-B out units. UAS may be a multi-million unit market for avionics, including ADS-B. (or there may be some dopey proprietary solution, that will be expensive, and less compatible).



Using the technology they have developed and mass manufacturing allowed the development costs to be amortized over many, many units. The basic unit, echoUAT is available today for $999 and can be installed on most aircraft. This will output WiFi to a tablet or phone, as well as integrate with existing in panel EFIS systems. It does require an external WAAS enabled GPS though.

I promised before that there were under $1000 solutions. NavWorx ran into a little trouble with their internal GPS, and it may have been outputting incorrect position accuracy information. This has been resolved, but now their cost is about $1500. The store seems to not have anything available right now, so I don't know what the costs are.

There is another version of the uAvionix echo, that looks like a wingtip light. The Skybeacon will replace a wingtip light, and be a full UAT ADS-B out system that can be added to any aircraft, even certified. It can be configured using WiFi, and listens to the transponder in the aircraft for squawk codes. There is an option to feed tablets in the cockpit with traffic information.



As you can see there are finally options for the rest of us. Items we can afford that deliver high performance.

Are you going to get one?

Saturday, October 29, 2016

What Might Have Been part 2.

I was never a good reader. In high school and college I would go to the library to read Aviation Week, or look at books on flying (not many) and electronics. There were always little project books. About 1978, I went into the very back of a B. Dalton Book Store, and found a section on computers. I suddenly was someone who would buy books, and actually read them. B Dalton and Barnes and Noble merged in the early 80's so I would seek out book stores where ever I was.



Through the 90s I relied on Barnes and Noble (B&N) to have the books I needed for the various jobs I was pursuing. As technology changed, so did the book shelves. I think for a while my local B&N store had 2 or 3 rows with multiple shelves full of computer books. The variety was very good from end users, to developers.

In the late 90s Amazon was born, and my book buying shifted. I went from perusing the book shelves at B&N to shopping on line, and ordering whatever I needed. It didn't matter that it might take 3 days to get the book, it was probably available, and I was going to get it. Eventually Amazon gamed the system with their multiply rejected one-click patent, and I vowed never to buy anything there again.

It didn't matter, there were other book sellers on line. I mostly use Half.com, but there were others including A1 (now out of business). These book sellers would sell new and used books at a fraction of the price others were.

As technology started moving faster, some of the books were out of date by the time they hit the shelves. Online forums replaced the tech books. Open source software begat open source documentation, and eventually tech books seemed obsolete. I mostly stopped shopping in book stores, since everything I was looking for was on line.

A funny thing happened though. The magazine stores went out of business, so I would go to B&N about once a month to browse magazines for some of the fringe subjects I am interested in (Model Railroading, Wooden Boats). These are subjects I am interested in, not always for the actual heart of the subject, but they are craftsmen and hackers on a whole nuther level.

This month, I had an article published in Kitplanes Magazine and I wanted to get a couple copies. While wandering the aisles in B&N to see what else is going on, I noticed several kits that might be useful. The store carries Little Bits and Arduino kits, along with some other robots and RasberryPi kits.

The kits sold at B&N are not the cheapest, but are probably suitable to the retail space where clerks may not be able to provide much after the sales support. But maybe their staff knows a thing or two. On top of kit display, there was a sign:



Yes a mini maker faire at all the stores. I am hoping the staff is helping and participating. It sounds like they are moving in the right direction. Engaging the community. Go if you can, tell 'em it is a great idea.

If you go, please give me some feedback.