Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 11 Next »

Goal

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

System architecture:

The automate model

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

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

To append at the end of spinal-model-button/model.js

function automate() {
  automate.super(this);
  this.add_attr({
    name: "",
    equipments: []
  });
}
spinalCore.extend(automate, Model);
module.exports = automate;
The createEquipment organ

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

The createEquipment organ will create 10 equipments in a new list stored as "automate".

createEquipment/index.js

// 1: Requirements and connection
var spinalCore = require('spinal-core-connectorjs');
require('../spinal-model-button/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";

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

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

// 3: 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.

~/button-system/createEquipment$ node index.js 

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

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

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

Simulate sensors with automates

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


Automate 1

Create a new organ named "automate1".

~/button-system$ mkdir automate1
~/button-system$ cd automate1
~/button-system/automate1$ touch index.js

automate1/index.js

// 1: Requirements and connection
var spinalCore = require('spinal-core-connectorjs');
require('../spinal-model-button/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";

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

// 2: 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
});

// 3: 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);
}

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

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

// 5: 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.

~/button-system/automate1$ cd ..
~/button-system$ cp -r automate1 automate2
~/button-system$ cd automate2

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

var spinalCore = require('spinal-core-connectorjs');
require('../spinal-model-button/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";

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

spinalCore.load(conn, "Automate", function (list) {
// 1: An automate is created if there are less than 2 (instead of 1)
  if (list.automates.length < 2)
    addAutomate(list);
// 2: The list.automates[1] is pressed (instead of list.automates[0])
  press(list.automates[1]);
}, function () {
});

function addAutomate(list) {
// 3: The variable is named automate2 in this function (instead of automate1)
  var automate2 = new automate();

// 4: The name of the automate is automate1 (instead of automate0)
  automate2.name.set("automate1");
// 5: 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 selectEquipement = Math.floor(Math.random() * 5);
  const equipment = automate.equipments[selectEquipement];
  let hydro = Math.floor(Math.random() * 100);
  let degrees = Math.floor(Math.random() * 30);

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

  setTimeout(function () {
// 6: This log message changes
    console.log("automate2: has been pressed");
    press(automate);
  }, 1000);
}
Test your system

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

.apps.json

{
  "apps": [
    {
      "name": "spinal-core-hub",
      "script": "spinalhub.js",
      "cwd": "./nerve-center/"
    },
    {
      "name": "createEquipement",
      "script": "index.js",
      "cwd": "./createEquipement/"
    },
    {
      "name": "automate1",
      "script": "index.js",
      "cwd": "./automate1/"
    },
    {
      "name": "automate2",
      "script": "index.js",
      "cwd": "./automate2/"
    }
  ]
}

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

Create warnings

We now have 2 automates that change the data of equipments. 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

function press(automate) {
  let selectEquipement = Math.floor(Math.random() * 5);
  const equipment = automate.equipments[selectEquipement];
  let hydro = Math.floor(Math.random() * 100);
  let degrees = Math.floor(Math.random() * 30);

  equipment.hydrometry.set(hydro);
  equipment.temperature.set(degrees);
// 1: 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
// 2: Else we release the equipment
    pressed.set(false);

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

automate2/index.js

function press(automate) {
  let selectEquipement = Math.floor(Math.random() * 5);
  const equipment = automate.equipments[selectEquipement];
  let hydro = Math.floor(Math.random() * 100);
  let 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.

~/button-system$ pm2 restart launch.config.js
~/button-system$ pm2 log

You should see something like this.

Conclusion

In this tutorial you:

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


This tutorial will be continued in Getting Started Extended to Viewer 1.

  • No labels