I’ve had a Raspberry Pi for a couple years. When I first bought one, I had some ambitious dreams. Using Android Things, I was going to build a parking helper for our garage. Currently, Android Things is a dead platform and my parking helper never made it past being an interesting demo.

I still have ambitious project ideas for my lone Raspberry Pi. I’m going to start with a prototype I could use here at my home. My home has a walkin crawlspace that is sealed and contains a de-humidifier. It feels great in there. I’ve always been curious to measure how cool and how dry the air is at all times of the day, so I thought I’d put my Raspberry Pi to use.

HumiJS: A Raspberry Pi-Powered Humidistat and Thermometer

You can get all of the source code on GitHub. Here is what you need for this project:

  • JavaScript & Nodejs knowledge
  • Raspberry Pi (I’m using a 3b+)
    • Configured for wired or wireless network access and SSH, with Nodejs installed
    • See this guide for more info w3schools.com
  • DHT22 temperature & humidity sensor

Setting up the Hardware

Setting up your Raspberry Pi and DHT22 sensor is relatively straightforward. There are three pins on the DHT22 for power and data.

DHT22 Wiring Setup - from GitHub

The connection configuration I used (and diagramed above):

Raspberry Pi 3b+ Pinout
  • Pin 2 - 5V power
  • Pin 39 - Ground
  • Pin 4 - GPIO 4 (data)

That’s it! They’ll be more work to do if you need to place your humidistat in a hard to reach location, but it should work once we get the software setup and running.

Getting the Software Running

The software that will run on our Raspberry Pi is powered by Nodejs and Express. It’s a very simple REST API with a couple endpoints for retrieving the humidity and temperature.

Suppose we had our Raspberry Pi setup and wanted to retrieve the humidity.

Using HTTPie, the request:

http http://localhost:3000/humidity

Or Curl, the request:

curl http://localhost:3000/humidity

The response:

{
    "humidity": 47.29999923706055
}

The code itself is straightforward. We interact with the DHT22 humidity and temperature sensor with a library called node-dht-sensor.

Here is a basic Nodejs script for reading data from the sensor and printing it to the console. I’m going to use Promises/Async/Await in this example.

const sensor = require("node-dht-sensor").promises
const SENSOR_TYPE = 22;
const PIN = 4;

(async () => {
  let data = await sensor.read(SENSOR_TYPE, PIN);
  console.log(data);
})();

The output is:

{ temperature: 18.600000381469727, humidity: 47.20000076293945 }

That’s it!

One point to note. I wrote this class on my development computer, which doesn’t have access to the sensor connected to my Raspberry Pi. To test my implementation I needed some mock data. The library node-dht-sensor has an API where you can have it return mock data. I accomplish this by looking for a command line argument test. If the command line argument is present, I instruct the sensor to return the mocked data.

if (process.argv.length > 2 && process.argv[2] == 'test') {
  sensor.initialize({
    test: {
      fake: {
        temperature: 21,
        humidity: 60
      }
    }
  });
}

For example, running the server with:

node .  test

Initializes the sensor in test mode. Excluding test will read the data from the sensor.

Once the code is completed, the only remaining item is getting the code to your Raspberry Pi, either with SCP or cloning the GitHub repository directly on to your Raspberry Pi.

Everything after this point is just the work to wrap a decent REST API around this data. Here is the source code for the complete API server.

const sensor = require("node-dht-sensor").promises;
const express = require("express");

const PORT = 3000;
const SENSOR_TYPE = 22;
const PIN = 4;

const app = express();

if (process.argv.length > 2 && process.argv[2] == 'test') {
  sensor.initialize({
    test: {
      fake: {
        temperature: 21,
        humidity: 60
      }
    }
  });
}

app.get('/temperature', async (req, res) => {
	let data = await readSensor();
  
  if (data) {
    let temperature = data.temperature;
    let unit = 'c';

    if (req.query.unit) {
      unit = req.query.unit.toLowerCase();
    }

    if (unit == 'f') {
      temperature = convertToFahrenheit(temperature);
    }
    res.status(200).json({ temperature: temperature });
  } else {
    res.status(500).send();
  }
});

app.get('/humidity', async (req, res) => {
  let data = await readSensor();
  
  if (data) {
    res.status(200).json({ humidity: data.humidity });
  } else {
    res.status(500).send();
  }
});

async function readSensor() {
  let data = null;

  try {
    data = await sensor.read(SENSOR_TYPE, PIN);
	} catch (err) {
		console.log('Error reading sensor', err);
  }
  return data;
}

function convertToFahrenheit(temperatureInCelsius) {
  return (temperatureInCelsius * 9/5) + 32;
}

app.listen(PORT, () => {
  	console.log(`HumiJS is online @ http://localhost:${PORT}`)
});

Check out the project on GitHub.

🧇