Versions Compared

Key

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

Table of contents

  1. Goal
  2. The equipment and equipementList Create the models
  3. Create a list of 2 equipmentsSensor
  4. How to launch you organs effectivelyefficiently

Quick navigation

Child pages (Children Display)
alltrue
pageSimple Iot TutorialTutorials


Panel
titleGoal

Anchor
1
1

After the Getting Started tutorial, you should have a Spinal-system with one model and one organ. We will use it to create an intelligent system with more synchronized information.
System architecture:

Image Removed

In this tutorial you will learn how to make a list of items and how to launch your organs with more efficacy.:

  1. Create a model or a Digital twin of your sensors equipment.
  2. Create organs that simulate your sensors behavior.
  3. Launch your organs with efficiently
System architecture:

Image Added


Panel
titleRequirements

For this tutorial, you just need the basic requirements


Panel
titleThe equipment and equipementList modelsCreate the models / Digital twins

Anchor
2
2

In this part we will create 2 new you’re going to create two sensor models:

  • equipmentSensor, a complex model with 5 4 attributes:
    • id
    , name, hydrometry, temperature and pressed (boolean)
  • equipmentList, a model that contains an array of equipments
spinal-model-button/model
    • : unique integer
    • name : string 
    • hygrometry : integer
    • temperature : integer
  • SensorList, a model with 1 attribute:
    • sensors : array of sensors

Create your spinal system and digital twin by following these steps:

  1. Create a new spinal-system from the browser-admin template (explained in the section "Creating a new Spinal System" in the Getting Started tutorial).
  2. Create a folder called spinal-models to store the different models you are going to create. Within this folder create a file named model.js.
  3. Complete model.js:
    1. Create the sensor model.
    2. Extend the sensor model with the Model class from spinalCore.
    3. Export the sensor model.
    4. Create the sensor list.
    5. Extend the sensor list with the Model of spinalCore.
    6. Export the sensor list.

Your model file should look like this:

spinal-models/models.js

Code Block
languagejs
themeDJango
titlemodels.js
linenumberstrue
const// spinalCoreSensorModel = require("spinal-core-connectorjs");
// 1: Previously used buttonModel
function buttonModel() {
    buttonModel.super(this);
    this.add_attr({
        pressed: false
    });
}
spinalCore.extend(buttonModel, Model);
module.exports = buttonModel;inherits from Model
class SensorModel extends Model {
  constructor() {
    super();
    // 2:add Equipmentattributes modelto functionthe equipment()model
{     equipment.super(this); // 3: Creating attributes
    this.add_attr({
          id: 0,
          name: "",
         hydrometryhygrometry: 0,
         temperature: 0,
    });
  }
pressed: false
    });
}}
module.exports.SensorModel = SensorModel;

// 4:SensorListModel Registeringinherits thefrom equipmentModel
modelclass in the Spinal system
spinalCore.extend(equipment, Model);
module.exports = equipment;

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



Panel
titleCreate Instantiate a list of 2 equipmentsSensors

Anchor
3
3

With our new models we will now create In this part your are going to instantiate a list of 2 equipments. We will create an organ for each equipment. Each one will have an automate which changes its hydrometry virtual sensors in the database and create two "organs" of the system that will simulate the sensor behavior.

Each organ will simulate changes of hygrometry and temperature.

Equipment 1

Make
  1. Create a
folder named equipment1 and the file
  1. new folder spinal-organ-sensor1 and within it a file named index.js
in it.
Code Block
languagebash
themeDJango
~/button-system$ mkdir equipment1
~/button-system$ cd equipment1
~/button-system/equipment1$ touch index.js
​This organ will create the first equipment and will revover data from a simulated sensor.
equipment1/index.js
  1. .
  2. in the index.js file:
    1. Require spinal-core.
    2. Get the connection parameter from the config.js file in the main folder
    3. Create a function addItem. This function create, set and add an item to the list given in argument.
    4. Create a function simulate. This function simulate the value of the sensor.
    5. Create a function onSuccess. This function will be executed if the loading of ‘List’ is successful. 
    6. Create a function onFaill. This function will be executed if the loading of ‘List’ fail.
    7. Load list from spinal-core.
  3. Create a new folder spinal-organ-sensor2 
  4. Copy paste the index.js into sensor2 folder and do the appropriate modifications.
  5.  Don't forget to install spinal-core-connectorjs from GitHub in the two folders


Panel
titleNote
  • If you have and API to retrieve the real data of your sensor use it to send real data to the graph.
  • You can run every sensor independently by running the corresponding index.js (node index.js)


Your file spinal-organ-sensor1/index.js should look like this.

Code Block
languagejs
themeDJango
titlespinal-organ-sensor1/index.js
linenumberstrue
// 
1: Requirement
Requirements and connection
const spinalCore = require('spinal-core-connectorjs');
const models = require('../spinal-
model-button
models/
model
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}/`);

// 
2: Tries
Gives random values to
load 'List' spinalCore.load(conn, "List",
 the hygrometry and temperature of a sensor
function simulate(
list
sensor) {
//
  
3:
const 
If
hydro 
the list exists but is empty a first equipment is added if (list.equipments.length < 1) addItem(list); // 4: Else the first equipment is pressed else press(list.equipments[0]); }, function () { // 5: If 'List'
= Math.floor(Math.random() * 100);
  const degrees = Math.floor(Math.random() * 30);
  sensor.hygrometry.set(hydro);
  sensor.temperature.set(degrees);
  // Repeats every second
  setTimeout(() => {
    console.log(sensor.name.get() + ": data has changed");
    simulate(sensor);
  }, 1000);
};

// Finds a Sensor in the SensorList, if it doesn't exist, 
an
creates it
empty
function getSensorById(list, 
is
id) 
created
{
and
 
its
 
first
let 
equipment
item;
is

pressed
  for 
var
(let 
list
i = 
new equipmentList(); spinalCore.store(conn, list, "List", function () { addItem(list); }); }); // 6: Creates a new equipement and adds it to the list function addItem(list
0; i < list.sensors.length; i++) {
    if (list.sensors[i].id.get() === id) {
      item = list.sensors[i];
      break;
    }
  }
  if (typeof item === "undefined") {
  
const
  item = new 
equipment
models.SensorModel();
    item.id.set(
0
id);
    item.name.set("
equipment0
sensor" + id);
    list.
equipments
sensors.push(item);
  }
  return 
press(
item
)
;
}

// This 
7:
function 
Gives
will 
random
be 
values
called 
to
if the 
hydrometry and temperature of an equipment function press(equipment) { const hydro = Math.floor(Math.random() * 100); const degrees = Math.floor(Math.random() * 30); equipment.hydrometry.set(hydro); equipment.temperature.set(degrees); // 8: Repeats every second setTimeout(function ()
list is successfully loaded
function onSuccess(list) {
  simulate(getSensorById(list, 0));
};

// This function will be called if the list cannot be loaded
function onFailure() {
  const list = new models.SensorListModel();
  const item = getSensorById(list, 0);

  spinalCore.store(conn, list, "List", () => {
    
console.log("equipment 1: has been pressed"
simulate(item);
  });
};

press(equipment); }, 1000
spinalCore.load(conn, "List", onSuccess, onFailure);
}

You can launch your new organ with node.

Code Block
languagebash
themeDJango
~/button-system/equipment1$ node index.js
Go


Run spinal-organ-sensor1/index.js and go to the admin UI and put 'List' into the inspector and you should see the hydrometry hygrometry and temperature of equipment0 sensor0 change every second.

Image Removed

Equipment2

Equipment2 will be almost identical to equipment1 so I suggest you start by copying equipment1

Image Added


Your file spinal-organ-sensor2/index.js should look like this.

Code Block
languagebashjs
themeDJango
~/button-system/equipement1$ cd ..
~/button-system$ cp -r equipment1 equipment2
~/button-system$ cd equipment2

There are very few changes to make to index.js.

equipment2/index.js

Code Block
DJango
languagejs
themetitlespinal-organ-sensor2/index.js
linenumberstrue
var// Requirements and connection
const spinalCore = require('spinal-core-connectorjs');
const models = require('../spinal-model-buttonmodels/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}/`);

// Gives random values to the hygrometry and temperature of a 
var list = new equipmentList();
spinalCore.load(conn, "List", function (list) {
// 1: An item is created if there are less than 2 equipments in the list
  if (list.equipments.length < 2)
    addItem(list);
// 2: The second item is pressed (instead of the first)
  press(list.equipments[1]);
}, function () {
  spinalCore.store(conn, list, "List", function () {
    addItem(list);
  });
});

function addItem(list) {
  let item = new equipmentsensor
function simulate(sensor) {
  const hydro = Math.floor(Math.random() * 100);
  const degrees = Math.floor(Math.random() * 30);
  sensor.hygrometry.set(hydro);
  sensor.temperature.set(degrees);
  // Repeats every second
  setTimeout(() => {
    console.log(sensor.name.get() + ": data has changed");
    simulate(sensor);
  }, 1000);
};

// Finds a Sensor in the SensorList, if it doesn't exist, creates it
function getSensorById(list, id) {
  let item;

  for (let i = 0; i < list.sensors.length; i++) {
    if (list.sensors[i].id.get() === id) {
      item = list.sensors[i];
      break;
    }
  }
  if (typeof item === "undefined") {
    item = new models.SensorModel();
    item.id.set(0id);
// 3:
The new item is named equipment1 (instead of equipment0)
  item.name.set("equipment1sensor" + id);
    list.equipmentssensors.push(item);
  }
  press(return item);
}

// This function press(equipment) {
  let hydro = Math.floor(Math.random() * 100);
  let degrees = Math.floor(Math.random() * 30);

  equipment.hydrometry.set(hydro);
  equipment.temperature.set(degrees);
  setTimeout(function () {
// 4: This message changes
    console.log("equipment 2: has been pressed");
    press(equipment will be called if the list is successfully loaded
function onSuccess(list) {
  simulate(getSensorById(list, 1));
};

// This function will be called if the list cannot be loaded
function onFailure() {
  const list = new models.SensorListModel();
  const item = getSensorById(list, 1);

  spinalCore.store(conn, list, "List", () => {
    simulate(item);
  }, 1000);
}

Now launch equipment2 with node.

Code Block
languagebash
themeDJango
~/button-system/equipment2$ node index.js

If you go back to the inspector you will notice that a new equipment has appeared in the List.

Image Removed
;

spinalCore.load(conn, "List", onSuccess, onFailure); 


Image Added


Panel
titleHow to launch you organs effectivelyLaunch efficiently your organs

Anchor
4
4

After the last part you You might have noticed that the way we have been launching our organs isn't very effective, you have to launch and stop organs one by one.

This is because this is not the right way to do it. In this part you will learn how to launch  your organs effectively.

To do that we need to look at .apps.json. When you open it for the first time it should look like this:

Code Block
languagejs
themeDJango
linenumberstrue
{
  "apps": [
    {
      "name": "spinal-core-hub",
      "script": "spinalhub.js",
      "cwd": "./nerve-center/"
    }
  ]
}
.apps.json contains the organs that should be launched. They are identified by:

you are running every organ independently.

In a system where all the organs run on the same server, you can simplify this process and monitor your organs using pm2.

  1. Take a look at .app.json.
  2. add dependency to your organs.
    1. name: The name they will be identified by pm2
    2. script: The name of the script to be executed to launch the organ
    3. cwd: The location of the script (relative to the root of the project)
With all that in mind let's add equipment 1 and 2 to the list.
  1. run the commande pm2 restart launch.config.json.

Your .app.json should look like this:

Code Block
languagejs
themeDJango
linenumberstrue
{
  "apps": [
    {
      "name": "spinal-core-hub",
      "script": "spinalhub.js",
      "cwd": "./nerve-center/"
    },
    {
      "name": "equipment1sensor1",
      "script": "index.js",
      "cwd": "./equipment1spinal-organ-sensor1/"
    },
    {
      "name": "equipment2sensor2",
      "script": "index.js",
      "cwd": "./equipment2spinal-organ-sensor2/"
    }
  ]
}

Now all we have to do is let pm2 do the work.

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

pm2 will now show you equipment sensor 1 and 2 along with spinal-core-hub.

Image RemovedImage Added


Conclusion


In this second tutorial you learned:

  • how to create more complicated complex models
  • how to organize your data coming from multiple organs
  • how to launch you your organs effectivelyefficiently


This tutorial will be continued in Getting Started Extended 2 Basic Automate Tutorial.