visit
This can be used to collect the temperature data of a large number of Raspberry Pi devices.
npm init adonis-ts-app@latest raspberry-pi-adonisjs-app
Once you run that, you will be asked to select a project structure. You will be able to choose between an API, Web App, and a minimal possible AdonisJS app:
CUSTOMIZE PROJECT
❯ Select the project structure … Press <ENTER> to select
❯ api (Tailored for creating a REST API server)
web (Traditional web application with server-rendered templates)
slim (A smallest possible AdonisJS application)
For this tutorial let's go with the API option! Using your arrow keys select web and hit enter.
After that you will be asked to choose a name for the project, I will leave this as raspberry-pi-adonisjs-app
but feel free to choose a different name.
❯ Enter the project name · raspberry-pi-adonisjs-app
❯ Setup eslint? (y/N) · y
❯ Configure webpack encore for compiling front-end assets? (y/N) › y
Once that is done, you can switch to the new project directory:
cd raspberry-pi-adonisjs-app
And once in there, start the webserver:
node ace serve --watch
The ace
command is very similar to the artisan
command in Laravel. It is a command-line interface for running AdonisJS commands. The node ace serve
command will start the webserver and watch for changes to your code.
To check all of the ace commands, you can run: node ace
.
npm i @adonisjs/lucid
Once done, you would need to do a quick configuration.
node ace configure @adonisjs/lucid
You will be asked to select the database driver that you want to use. Here, make sure to select PostgreSQL!
Next, you will be asked to select where you want to display the configuration instructions. I chose In the terminal
, which prints out the necessary environment variables that you have to add to your .env
file.
Make sure to update the DB_DATABASE
and DB_USERNAME
and DB_PASSWORD
variables in your .env
file accordingly so that you can connect to your database.
node ace make:model Sensor -m
This will create a new model and a migration:
CREATE: database/migrations/90_sensors.ts
CREATE: app/Models/Sensor.ts
Open the migration file and update the file so that it looks like this:
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
export default class Sensors extends BaseSchema {
protected tableName = 'sensors'
public async up () {
this.schema.createTable(this.tableName, (table) => {
table.increments('id')
table.string('device')
table.string('temperature')
table.string('timestamp')
/**
* Uses timestamptz for PostgreSQL and DATETIME2 for MSSQL
*/
table.timestamp('created_at', { useTz: true })
table.timestamp('updated_at', { useTz: true })
})
}
public async down () {
this.schema.dropTable(this.tableName)
}
}
We basically added 3 extra columns that will store the name of the device, the temperature, and the timestamp when the data was recorded.
To run the migration, run the following command:
node ace migration:run
This will create the sensors table in your database with the columns we specified.
Again we will be using the ace
command to create a new controller:
node ace make:controller SensorsController
This will create a controller file at:
app/Controllers/Http/SensorsController.ts
Next, let's create the routes that we would need!
With your favorite text editor, open the SensorsController.ts
file and add the following method:
import Route from '@ioc:Adonis/Core/Route'
import Database from '@ioc:Adonis/Lucid/Database'
// import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class SensorsController {
public async store ({ request }) {
let name = 'raspberry-1';
if (request.qs().name != null) {
name = request.qs().name;
}
let timestamp = '2021-11-21 19:52:49';
if (request.qs().timestamp != null) {
timestamp = request.qs().timestamp;
}
let temperature = '41.1';
if (request.qs().temperature != null) {
temperature = request.qs().temperature;
}
console.log(name, timestamp, temperature)
await Database
.insertQuery()
.table('sensors')
.insert({ device: name, timestamp: timestamp, temperature: temperature})
return {
message: 'Successfully added sensor data'
}
}
})
There are a few things to note here:
import
statement is importing the Route
and Database
from the @ioc:Adonis/Core/Route
and @ioc:Adonis/Lucid/Database
packages.await
keyword is used to wait for the database query to finish.request.qs()
method is used to get the query string parameters from the request. That way we will be able to get the name, timestamp, and temperature sent by the Raspberry Pi devices.Your routes file is stored at start/routes.ts
. In there we can specify our application URLs and map them to different controllers and methods!
GET /temperature
: This route will store the data sent by the Raspberry Pi devices.Open your routes file at start/routes.ts
and update it so that it has the following content:
import Route from '@ioc:Adonis/Core/Route'
Route.get('/temperature', 'SensorsController.store')
#!/bin/bash
# AdonisJS API URL - Make sure to change this to your API URL
api_url="//localhost:3333/temperature"
# Specify the name of the Raspberry Pi device:
name="raspberry-1"
if [[ -z ${NAME} ]] ; then
name="raspberry"
fi
# Get the temperature from the Raspberry Pi device:
function temperature(){
temperature=$(/opt/vc/bin/vcgencmd measure_temp | tr -d temp=\'C)
echo ${temperature}
}
# Get the current time
function timestamp(){
time=$(date +%s)
echo ${time}
}
echo ${name},$(timestamp),$(temperature)
curl -X GET "${api_url}?name=${name}-${i}×tamp=$(timestamp)&temperature=$(temperature)"
Make sure to change the URL to your AdonisJS API. If you are running this on the same Raspbery Pi, you can leave it as localhost
, if not you could use the IP of the device that you are running the API on.
Save the script as temperature.sh
and make it executable:
chmod +x temperature.sh
Then edit your crontab
:
sudo crontab -e
Add the following line to your crontab
:
* * * * * /home/pi/temperature.sh
This will run the script every minute and send the data to the API.