Database Schema, Mongoose and Node.js

This article is part of a series with the name IoT Remote Power Switch – Project Part 5.

It describes how I derive a database schema from the requirements and how I connect the Node.js based web server using Mongoose.

Requirements Review

I start with a review on the requirements. They state that the user shall have a means to switch the heater on or off via the browser, and that it shall be possible displaying the heater’s status (on, off) in the browser. A more formal summary of these requirements looks like this:
Switch heater

  • Off
  • On

These commands are written by the browser to the web server’s database, and read by the embedded computer from the server’s database. (Note: the database is transparent to the embedded computer; it has no notion of it. It’s just mentioned here because I’ll program it shortly.)
Heater states

  • Offline
  • Online
    • Off
    • On

This status information is written by the embedded computer to the web server’s database, and read by the browser from the server’s database.
The above list can be simplified to these three heater states:

  • Off
  • On
  • Unknown/Offline

The tricky one is the state Unknown/Offline. How does the server know if the embedded computer is offline or online? In the solution I propose here it is the embedded computer that periodically sends a status information to the server. If that information fails to arrive for a certain period of time, the server will conclude that the embedded computer has gone offline.

Database Schema and Mongoose

Since I have a database in place, I will use it to not only store the states of the heater or the switch, but with it the date and time when states have changed. Every state change will create an entry in the database.
It is absolutely possible to use MongoDB directly from Node.js. However, I’ll add a layer in between, and that’s Mongoose. Mongoose offers the possibility to use database schemas, which make in my opinion the database code more readable for humans. Thus let me define the schemas we are going to use. Note that in MongoDB a collection is what in a relational database a table is, and that in Mongoose a schema maps to a collection. Here comes the schema model in Mongoose schema notation:
File: model.js

var mongoose = require('mongoose');

// Create schema for switch (written to by user)
var switchSchema = mongoose.Schema({
  date: Date,
  state: Boolean
});
// Compile schema into model
// Note: the name 'switch' can't be used since it is a keyword;
// thus the name 'switchOffOn' is being used instead
exports.switchOffOn = mongoose.model('switchOffOn', switchSchema);

// Create schema for status (written to by embedded computer)
var statusSchema = mongoose.Schema({
  date: Date,
  state: String
});
// Compile schema into model
exports.status = mongoose.model('status', switchSchema);

Before I can use Mongoose inside Node.js JavaScript code, I have to install it in the project’s directory.

npm install mongoose --save

This will create a node_modules directory and update the dependency list inside package.json.

Summary and Outlook

For the database connection I’ve added some files. The connection handling is stored in db.js, The connection settings are stored in settings.js; this file existed already. In addition, I’ve prepared two more files, switchOffOn.js and status.js. They’ll process the requests coming from the web server and act on the database.

You can find the source code here. Note that the node_modules folder isn’t part of the repository. After downloading the repo or its zip file you’ll have to change directory to the top-level folder of the project and run $> npm install.

A note on the folder structure: I’ve intentionally kept the structure flat until now. In production environments, the structure looks quite different, and I may at a later stage change it a little for more clarity.

That’s it for this time. Next time I’ll add code to the web server that implements the REST API. After that, I’ll only have to extend the browser’s JavaScript code such that it issues AJAX calls and I am done with the client side!