Versions Compared

Key

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


Quick navigation

Child pages (Children Display)
alltrue
pageSimple Iot TutorialTutorials


Panel
titleGoal

Anchor
1
1

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

System architecture:

Image RemovedImage Added


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 another model a new model, named an "automate", that will be in charge of a group of equipmentsensors. This model needs 2 attributes:

  • name: so we can create multiple automates without losing track of and identify them
  • equipmentssensors: an  an array of the equipments the automate has in chargesensors that are managed by this automate

We're going to add an empty array named automates as property of the equipementList model SensorListModel and create a model automate which has a name and a array of equipement as Automate with the two previously described attributes. spinal-model/model

Take care of SensorListModel, an automate as been added to the model.

spinal-models/models.js

Code Block
languagejs
themeDJango
linenumberstrue
constclass spinalCoreSensorModel = require("spinal-core-connectorjs");

// Equipment model
function equipmentextends Model {
  constructor() {
    equipment.super(this);
// Creating attributes
    this.add_attr({
 
      id: 0,
 
      name: "",
 
      hydrometry: 0,
 
      temperature: 0,
 
      pressed: false
    });
} // Registering the equipment model in the Spinal system
spinalCore.extend(equipment, Model);
}
}
module.exports.SensorModel = equipmentSensorModel;

// equipmentList model
function equipmentListclass SensorListModel extends Model {
  constructor() {
    equipmentList.super(this);
// Array of equipments
    this.add_attr({
        equipmentssensors: [],
 
      automates: []
    });
}  // Registering the equipmentList model in the Spinal system
spinalCore.extend(equipmentList, Model);
}
}
module.exports.SensorListModel = equipmentListSensorListModel;

// automateAutomate model
function automateclass AutomateModel extends Model {
  constructor() {
    automate.super(this);
    this.add_attr({
 
      name: "",
        equipmentssensors: []
    });
  }
}
spinalCore.extend(automate, Model);
module.exportsmodule.exports.AutomateModel = automateAutomateModel;



~/equipment-system/createEquipment$ node index

.

js

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

Image RemovedImage Added

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


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

Image RemovedImage Added

Panel
titleThe createEquipment createSensor organ

Anchor
3
3

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

The createEquipment createSensor organ will create 10 equipments virtual sensors in a new list stored as in the file "automateAutomate".

createEquipmentCreate a folder called createSensor and add a file called index.js inside.

createSensor/index.js

Code Block
languagejs
themeDJango
linenumberstrue
// Requirements and connection
const spinalCore = require('spinal-core-connectorjs');
const models = require('../spinal-modelmodels/modelmodels.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 equipmentListmodels.SensorListModel();
  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 equipmentmodels.SensorModel();

    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.equipmentssensors.push(item);
  }
}

Install spinal-core-connectorjs from GitHub.


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

Code Block
languagebash
themeDJango


Panel
titleSimulate sensors with automates

Anchor
4
4

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

Automate 1

Create a new organ named "automate1".

Create two folders, called automate1 and automate2 and inside, create a file index.js.

Don't forget to install spinal-core-connectorjs from GitHub, inside the two folders.

Automate 1

automate1/index.js

Code Block
languagebashjs
themeDJango
linenumberstrue
~//equipment-system$ mkdirRequirements automate1
~/equipment-system$ cd automate1
~/equipment-system/automate1$ touch index.js

automate1/index.js

Code Block
languagejs
themeDJango
linenumberstrue
// Requirements and connection
const and connection
const spinalCore = require('spinal-core-connectorjs');
const models = require('../spinal-modelmodels/modelmodels.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 automatemodels.AutomateModel();

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

// Randomly selects ana equipmentsensor in the list and changes its hydrometryhygrometry and temperature
function press(automate) {
  let selectedEquipment = Math.floor(Math.random() * 5);
  const equipmentsensor = automate.equipmentssensors[selectedEquipment];
  let hydro = Math.floor(Math.random() * 100);
  let degrees = Math.floor(Math.random() * 30);

  equipmentsensor.hydrometry.set(hydro);
  equipmentsensor.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 and modify the file as follow.

var spinalCore = require('spinal-core-connectorjs'); require('
Code Block
Code Block
languagejs
themeDJango
linenumberstrue
languagebashjs
themeDJango
~/equipment-system/automate1$ cd ..
~/equipment-system$ cp -r automate1 automate2
~/equipment-system$ cd automate2

There are very few changes to make to index.js so I will point them out instead of explaining everything again.

linenumberstrue
// Requirements and connection
const spinalCore = require('spinal-core-connectorjs');
const models = require('../spinal-modelmodels/modelmodels.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";

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


spinalCore.// Loading the list
spinalCore.load(conn, "Automate", function (list) {
  // callback success: if the Anarray of automateautomates is empty createdwe create ifa therefirst areautomate, lesselse thanwe 2press (insteadthe offirst 1)automate
  if (list.automates.length < 2)
    addAutomate(list);
//  The press(list.automates[1]);
is}, pressedfunction (instead of list.automates[0])
  press(list.automates[1]);
}, function () {
});
) {
  // callback error
});

// Adds an automate to the list and attributes him the first 5 sensors
function addAutomate(list) {
// The variablevar isautomate named= automate2 in this function (instead of automate1)
  var automate2 = new automate();

// The name of the automate is automate1 (instead of automate0)
  automate2.name.set("automate1");
// The loop goes from 5 to 10 (instead of from 0 to 5)
  for (let i = 5; i < 10; i++) {
    automate2.equipments.push(list.equipments[i]);
  }
  list.automates.push(automate2);
}

function press(automate) {
  let selectEquipementnew 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 hygrometry 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() * 530);

 const equipment = automate.equipments[selectEquipement] sensor.hydrometry.set(hydro);
  let hydro = Math.floor(Math.random() * 100);
  let degrees = Math.floor(Math.random() * 30);

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

  setTimeout(function () {
// This log message changes
    console.log(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 isnyou wan't already doneto use pm2 to launch them.

.apps.json

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


2 new automates with 5 equipment sensors each should have appeared in your list. You can compare the equipments sensors in the equipments 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 equipmentstheir 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 hygrometry exceeds 70% or the temperaturetemperature exceeds 20°, it will create a alert log. 

automate1/index.js

Code Block
languagejs
themeDJango
firstline29
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 the equipment's hydrometry or temperature are above certain value we send a message and press the equipment
    if (hydro > 70 || degrees > 20) {
        equipment.pressed.set(true);
        console.log("Alert: " + equipment.name.get() + " warning");
    } else
// Else we release the equipment
        pressed.set(false);

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

automate2/index.js

Code Block
languagejs
themeDJango
firstline29
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 < 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 models.AutomateModel();

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

// Warning fonction alert log for hygrometry and temperature
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 hygrometry 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
    sensor.pressed.set(false);

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

automate2/index.js

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);
}

// Warning fonction alert log for hygrometry and temperature
function press(automate) {
    const selectedEquipment = Math.floor(Math.random() * 5);
    const equipmentsensor = automate.equipmentssensors[selectedEquipment];
    const hydro = Math.floor(Math.random() * 100);
    const degrees = Math.floor(Math.random() * 30);

    equipmentsensor.hydrometry.set(hydro);
    equipmentsensor.temperature.set(degrees);
    if (hydro > 70 || degrees > 20) {
        equipmentsensor.pressed.set(true);
        console.log("Alert: " + equipmentsensor.name.get() + " warning");
    } else
        equipmentsensor.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 dangerunder alarm.

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

You should see something like this.

Image Removed



Conclusion

In this tutorial you learned how to:

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


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

...