Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


Quick navigation

Child pages (Children Display)
alltrue
pageSimple Iot Tutorial


Panel
titleGoal

Anchor
1
1

In the previous tutorial we created a list of 2 sensors. In this tutorial we're going to create an organ which will make senors for us and 2 two automates to handle this new list.

System architecture:


Panel
titleRequirements

To follow this tutorial you must have done the Basic Equipment Tutorial.


Panel
titleThe automate model

Anchor
2
2

In this part we will create a new model that will be in charge of a group of sensors. This model needs 2 attributes:

  • name: so we can create multiple automates without losing track of them
  • sensors: an array of the sensors the automate is in charge

We're going to add an empty array named automates as property of the SensorList model and create a model Automate which has a name and an array of sensors as attributes.

spinal-models/model.js

Code Block
languagejs
themeDJango
linenumberstrue
class SensorModel extends Model {
  constructor() {
    super();
    this.add_attr({
      id: 0,
      name: "",
      hydrometry: 0,
      temperature: 0,
      pressed: false
    });
  }
}
module.exports.SensorModel = SensorModel;

class SensorListModel extends Model {
  constructor() {
    super();
    this.add_attr({
      sensors: [],
      automates: []
    });
  }
}
module.exports.SensorListModel = SensorListModel;

// Automate model
class AutomateModel extends Model {
  constructor() {
    super();
    this.add_attr({
      name: "",
      sensors: []
    });
  }
}
module.exports.AutomateModel = AutomateModel;



Panel
titleThe createSensor organ

Anchor
3
3

Before we can use our new model we're going to need sensors for them to handle.

The createSensor organ will create 10 sensors in a new list stored as "Automate".

createSensor/index.js

Code Block
languagejs
themeDJango
linenumberstrue
// Requirements and connection
const spinalCore = require('spinal-core-connectorjs');
require('../spinal-model/model.js');

console.log("Configuration Environment not found, using default config");
process.env.SPINALHUB_PORT = 7777;
process.env.SPINALHUB_IP = "127.0.0.1";
process.env.SPINAL_USER_ID = 168;
process.env.SPINAL_PASSWORD = "JHGgcz45JKilmzknzelf65ddDadggftIO98P";

const conn = spinalCore.connect(`http://${process.env.SPINAL_USER_ID}:${process.env.SPINAL_PASSWORD}@${process.env.SPINALHUB_IP}:${process.env.SPINALHUB_PORT}/`);

//  We load our automate
spinalCore.load(conn, "Automate", function (automate) {
  // callback success
}, function () {
  // callback error: We create a new list
  const list = new equipmentList();
  spinalCore.store(conn, list, "Automate", function () {
    addItem(list);
  });
}
);

//  We add 10 new equipments to the list
function addItem(list) {
  for (let i = 0; i < 10; i++) {
    let item = new equipment();

    item.id.set(i);
    item.name.set("equipment" + i);
    item.hydrometry.set(Math.floor(Math.random() * 30));
    item.temperature.set(Math.floor(Math.random() * 100));
    list.equipments.push(item);
  }
}

You can test it to see if it is working fine.

A new list named "Automate" should have appeared in the admin UI, put it in the inspector.

You can see that that the sensor array contains 10 sensors whereas the automate array is empty.


At this point in this tutorial our spinal system looks like this:


Panel
titleSimulate sensors with automates

Anchor
4
4

We are now going to create 2 automates. Each one will be in charge of 5 sensors from the list. Both will periodically choose one of their sensors and change its hydrometry and temperature.


Automate 1

automate1/index.js

Code Block
languagejs
themeDJango
linenumberstrue
// Requirements and connection
const spinalCore = require('spinal-core-connectorjs');
require('../spinal-model/model.js');

console.log("Configuration Environment not found, using default config");
process.env.SPINALHUB_PORT = 7777;
process.env.SPINALHUB_IP = "127.0.0.1";
process.env.SPINAL_USER_ID = 168;
process.env.SPINAL_PASSWORD = "JHGgcz45JKilmzknzelf65ddDadggftIO98P";

const conn = spinalCore.connect(`http://${process.env.SPINAL_USER_ID}:${process.env.SPINAL_PASSWORD}@${process.env.SPINALHUB_IP}:${process.env.SPINALHUB_PORT}/`);

// Loading the list
spinalCore.load(conn, "Automate", function (list) {
// callback success: if the array of automates is empty we create a first automate, else we press the first automate
  if (list.automates.length < 1)
    addAutomate(list);
  press(list.automates[0]);
}, function () {
// callback error
});

// Adds an automate to the list and attributes him the first 5 equipments
function addAutomate(list) {
  var automate1 = new automate();

  automate1.name.set("automate0");
  for (let i = 0; i < 5; i++) {
    automate1.equipments.push(list.equipments[i]);
  }
  list.automates.push(automate1);
}

// Randomly selects a sensor in the list and changes its hydrometry and temperature
function press(automate) {
  let selectedEquipment = Math.floor(Math.random() * 5);
  const equipment = automate.equipments[selectedEquipment];
  let hydro = Math.floor(Math.random() * 100);
  let degrees = Math.floor(Math.random() * 30);

  equipment.hydrometry.set(hydro);
  equipment.temperature.set(degrees);

// Repeats every second
  setTimeout(function () {
    console.log("automate1: has been pressed");
    press(automate);
  }, 1000);
}


Automate 2

Automate2 will be almost identical to automate1 so I suggest you start by copying automate1.

Code Block
languagejs
themeDJango
linenumberstrue
// Requirements and connection
const spinalCore = require('spinal-core-connectorjs');
const models = require('../spinal-models/models.js');

console.log("Configuration Environment not found, using default config");
process.env.SPINALHUB_PORT = 7777;
process.env.SPINALHUB_IP = "127.0.0.1";
process.env.SPINAL_USER_ID = 168;
process.env.SPINAL_PASSWORD = "JHGgcz45JKilmzknzelf65ddDadggftIO98P";

const conn = spinalCore.connect(`http://${process.env.SPINAL_USER_ID}:${process.env.SPINAL_PASSWORD}@${process.env.SPINALHUB_IP}:${process.env.SPINALHUB_PORT}/`);

// Loading the list
spinalCore.load(conn, "Automate", function (list) {
  // callback success: if the array of automates is empty we create a first automate, else we press the first automate
  if (list.automates.length < 2)
    addAutomate(list);
  press(list.automates[1]);
}, function () {
  // callback error
});

// Adds an automate to the list and attributes him the first 5 sensors
function addAutomate(list) {
  var automate = new models.AutomateModel();

  automate.name.set("automate1");
  for (let i = 5; i < 10; i++) {
    automate.sensors.push(list.sensors[i]);
  }
  list.automates.push(automate);
}

// Randomly selects a sensor in the list and changes its hydrometry and temperature
function press(automate) {
  let selectedSensor = Math.floor(Math.random() * 5);
  const sensor = automate.sensors[selectedSensor];
  let hydro = Math.floor(Math.random() * 100);
  let degrees = Math.floor(Math.random() * 30);

  sensor.hydrometry.set(hydro);
  sensor.temperature.set(degrees);

  // Repeats every second
  setTimeout(function () {
    console.log("automate2: has been pressed");
    press(automate);
  }, 1000);
}



Panel
titleTest your system

Anchor
5
5

Don't forget to add all this new organs to your .apps.json if it isn't already done.

.apps.json

Code Block
languagejs
themeDJango
linenumberstrue
{
  "apps": [
    {
      "name": "spinal-core-hub",
      "script": "spinalhub.js",
      "cwd": "./nerve-center/"
    },
    {
      "name": "createSensor"
      "script": "index.js",
      "cwd": "./createSensor/"
    },
    {
      "name": "automate1",
      "script": "index.js",
      "cwd": "./automate1/"
    },
    {
      "name": "automate2",
      "script": "index.js",
      "cwd": "./automate2/"
    }
  ]
}


2 new automates with 5 sensors each should have appeared in your list. You can compare the sensors in the array and those in the automates to verify that they correspond.


Panel
titleCreate warnings

Anchor
6
6

We now have 2 automates that change the data of sensors. Let's add analytic to the press function to catch those modifications.

We will change the press function in both so that when the hydrometry exceeds 70% or the temperature

automate1/index.js

Code Block
languagejs
themeDJango
linenumberstrue
function press(automate) {
  const selectedSensor = Math.floor(Math.random() * 5);
  const sensor = automate.sensors[selectedSensor];
  const hydro = Math.floor(Math.random() * 100);
  const degrees = Math.floor(Math.random() * 30);

  sensor.hydrometry.set(hydro);
  sensor.temperature.set(degrees);
  //  If the sensor's hydrometry or temperature are above certain value we send a message and press the sensor
  if (hydro > 70 || degrees > 20) {
    sensor.pressed.set(true);
    console.log("Alert: " + sensor.name.get() + " warning");
  } else
    // Else we release the sensor
    pressed.set(false);

  setTimeout(function () {
    console.log("automate1: has been pressed");
    press(automate);
  }, 1000);

automate2/index.js

Code Block
languagejs
themeDJango
linenumberstrue
function press(automate) {
    const selectedEquipment = Math.floor(Math.random() * 5);
    const equipment = automate.equipments[selectedEquipment];
    const hydro = Math.floor(Math.random() * 100);
    const degrees = Math.floor(Math.random() * 30);

    equipment.hydrometry.set(hydro);
    equipment.temperature.set(degrees);
    if (hydro > 70 || degrees > 20) {
        equipment.pressed.set(true);
        console.log("Alert: " + equipment.name.get() + " warning");
    } else
        equipment.pressed.set(false);

    setTimeout(function () {
        console.log("automate2: has been pressed");
        press(automate);
    }, 1000);
}

Now use pm2 restart and pm2 log to see when an equipment is in danger.

Code Block
languagebash
themeDJango
~/button-system$ pm2 restart launch.config.js
~/button-system$ pm2 log



Conclusion

In this tutorial you learned how to:

  • Automatically create sensors using an organ
  • Created 2 automates to handle sensors
  • Made those automates display warnings if a problem occurs


This tutorial will be continued in Get your Automate in the viewer.

...