In this tutorial you learn how to :
- Create model or a Digital twin of your equipments sensors.
- Create organs that simulate your sensors behaviour.
- Launch your organs with efficiency.
System architecture:
For this tutorial, you just need the basic requirements
In this part you’re going to create two sensor models:
- Sensor, a object with 4 attributes:
- id : unique int
- name : string
- hygrometry : int
- temperature : int
- sensorList, an object with 1 list:
- sensors : []
Sensor and sensorList model
- Create a new spinal-system with the browser-admin template like it’s explained in the in the section Creating a new Spinal System in the Getting Started tutorial.
- Create a folder spinal-model to store the differents models. Within this folder create a file models.js.
- Complete the file model.js
- Create the sensor model.
- Extend the sensor model with the Model of spinal-core.
- Export the sensor model
- Create the sensor list.
- Extend the sensor list with the Model of spinal-core.
- Export the sensor list.
Your model file should look like this:
spinal-model/model.js
const spinalCore = require("spinal-core-connectorjs"); // Sensor model function Sensor() { Sensor.super(this); // add attributes to the model this.add_attr({ id: 0, name: "", hydrometry: 0, temperature: 0, }); } // Sensor inherit of model spinalCore.extend(Sensor, Model); module.exports.Sensor = Sensor; // SensorList model function SensorList() { SensorList.super(this); // Array of equipments this.add_attr({ sensors: [] }); } // SensorList inherit of model spinalCore.extend(SensorList, Model); module.exports.SensorList = SensorList;
In this part your are going to create a list of 2 sensors.
Every sensor will have its own organ.
Each one of those will have an automate which will change its hydrometry and temperature.
create a list of two sensor:
- Create a new folder sensor1 and within a file named index.js.
- Require spinal-core.
- Get the connection string from config.js.
- Create a function addItem. This function create, set and add an item to the list given in argument.
- Create a function simulate. This function simulate the value of the sensor.
- Create a function onSuccess. this function will be executed if the loading of ‘List’ is successful. For this part you to add an element to the list if the list is empty and simulate the data of this element this element.
- Create a function onFaill. this function will be executed if the loading of ‘List’ fail. For this part if the loading fail you want to create a new list and store it into spinal-core.
- Load list from spinal-core.
- Copy paste this folder into sensor2 and do the appropriate modification in index.js .
- 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 sensor1/index.js should look like this.
// Requirement and connection const spinalCore = require('spinal-core-connectorjs'); require('../spinal-model/models.js'); const connection_string = require("../config"); const conn = spinalCore.connect(connection_string); // Creates a new sensor and add it to the list addItem = (list) => { const item = new Sensor(); item.id.set(0); item.name.set("sensor0"); list.sensors.push(item); simulate(item); }; // Gives random values to the hydrometry and temperature of a sensor simulate = (sensor) => { const hydro = Math.floor(Math.random() * 100); const degrees = Math.floor(Math.random() * 30); sensor.hydrometry.set(hydro); sensor.temperature.set(degrees); // Repeats every second setTimeout(() => { console.log("sensor 1: data has changed"); simulate(sensor); }, 1000); }; findIndexById = (id, list) => { if (list.sensors.length <= 0) return -1; let i; for (i = 0; i < i < list.sensors.length && list.sensors[i].id !== id; i++); if (i < list.sensors.length) return i; else return -1; }; //this function will be called if the list is successfully load onSuccess = (list) => { const index = findIndexById(0, list); console.log("success 2 : index:", index); if (index !== -1) simulate(list.sensors[index]); else addItem(list); }; //this function will be called if the list is failed to load onFail = () => { const list = new SensorList(); spinalCore.store(conn, list, "List", () => { addItem(list); }); }; spinalCore.load(conn, "List", onSuccess, onFail);
Run sensor1 and go to the admin UI and put 'List' into the inspector and you should see the hydrometry and temperature of sensor0 change every second.
Your file sensor2/index.js should look like this.
// Requirement and connection const spinalCore = require('spinal-core-connectorjs'); require('../spinal-model/models.js'); const connection_string = require("../config"); const conn = spinalCore.connect(connection_string); // Creates a new sensor and add it to the list addItem = (list) => { const item = new Sensor(); item.id.set(1); item.name.set("sensor1"); list.sensors.push(item); simulate(item); }; // Gives random values to the hydrometry and temperature of a sensor simulate = (sensor) => { const hydro = Math.floor(Math.random() * 100); const degrees = Math.floor(Math.random() * 30); sensor.hydrometry.set(hydro); sensor.temperature.set(degrees); // Repeats every second setTimeout(() => { console.log("sensor 2: data has changed"); simulate(sensor); }, 1000); }; findIndexById = (id, list) => { if (list.sensors.length <= 0) return -1; let i; for (i = 0; i < i < list.sensors.length && list.sensors[i].id !== id; i++); if (i < list.sensors.length) return i; else return -1; }; //this function will be called if the list is successfully load onSuccess = (list) => { const index = findIndexById(1, list); console.log("success 2 : index:", index); if (index !== -1) simulate(list.sensors[index]); else addItem(list); }; //this function will be called if the list is failed to load onFail = () => { const list = new SensorList(); spinalCore.store(conn, list, "List", () => { addItem(list); }); }; spinalCore.load(conn, "List", onSuccess, onFail);
You might have noticed that running every organ independently is painful.
If you wonder why it’s so painful it’s because you are not supposed to do that :p.
In this part you will learn a to run you organs efficiently.
- Take a look at .app.json
- add dependency to your organs.
- name: The name they will be identified by pm2
- script: The name of the script to be executed to launch the organ
- cwd: The location of the script (relative to the root of the project)
- run the commande pm2 start launch.config.json.
.apps.json contains the organs that should be launched. They are identified by:
- name: The name they will be identified by pm2
- script: The name of the script to be executed to launch the organ
- cwd: The location of the script (relative to the root of the project)
Your .app.json should look like this:
{ "apps": [ { "name": "spinal-core-hub", "script": "spinalhub.js", "cwd": "./nerve-center/" }, { "name": "sensor1", "script": "index.js", "cwd": "./sensor1/" }, { "name": "sensor2", "script": "index.js", "cwd": "./sensor2/" } ] }
pm2 will now show you sensor 1 and 2 along with spinal-core-hub.
Conclusion
In this tutorial you learned:
- how to create complex models
- how to organize your data coming from multiple organs
- how to launch you your organs effectively
This tutorial will be continued in Basic Automate Tutorial.