Getting Started : Press Button
We will create a very simple system composed of a virtual button pressed periodically and a monitor which will display the state of the button in the Spinalcore admin interface and in the terminal.
System architecture:
The best way to use this tutorial is to follow each step as it happens, no code or step needed to make this example application has been left out, so you can literally follow along step by step. A the end of each section, we show the current system architecture.
For this tutorial, you just need the basic requirements
The first step is to create the project's directory. We will call it button-system. Then, install inside the “spinal-system-basic” template. We suggest that before running the following command you initialize an npm project (with npm init):
Install spinal-system-basic
~/$ mkdir button-system ~/$ cd button-system ~/button-system$ npm init -y ~/button-system$ npm i https://github.com/spinalcom/spinal-browser-admin.git
Launch spinal-system
That’s it. You have everything you need. You can check that everything is working by running the PM2 process file automatically generated:
~/button-system$ pm2 start launch.config.js
PM2 will automatically start the Spinal Hub and the organs.
After this installation, only SpinalHub is running on port 7777. SpinalHub contains a web server that provide his own Admin interface (spinal-browser-admin organ). Here is the architecture of the system you have after this first install:
Connect to Admin UI
The admin interface is a browser application. You need to access it via a browser. We suggest you use google chrome. (you may change the host/port and the password corresponding to your .config.json file):
http://127.0.0.1:7777/html/admin
The default admin account is :
Username | client ID | Password |
---|---|---|
admin | 168 | SPINAL_PASSWORD |
SPINAL_PASSWORD : you will find it in th file .config.json (spinalcom connection configuration file).
Admin interface views:
If you access the previous interface, then your system is running ! and you have access to the first organ (service) of your brand new spinal-system: its administration interface.
Now let’s create our first synchronized data model and our first organ.
Button-system Folder organization
Your button-system folder has been initialized with many folders and files that respect a spinal-system organization (see Framework & Best practices for more information). Apart from the node_modules folder which contains Node.js dependencies and the pm2 process file launch.config.js, a directory called nerve-center is generated which contains the database that will be stored and synchronized by using the Spinal System.
Spinalcom-system architecture:
- .browser_organs : This is your web browser folder
- .config_env : Your env configuration
- nerve-center : The Spinalcom nerve center
- node_modules : npm (node package manager) & spinal-package
- .apps.json : installed package of your spinal system
- .config.json : spinalcom connection configuration file
- launch.config.js : Start your hub using pm2
- package.json : config of your package
In the development of a Spinal System, one of the mains steps is to define the structure of the data (model) that will be synchronized. We are going to define this model in a specific library. In this quick start, we will create the model of a virtual button with a state attribute. The “virtualButton” organ will then modify the state of the model and we will monitor this state in the admin interface.
Create a folder named spinal-model-button at the root of your project and, inside it, create a file called model.js.
~/button-system$ mkdir spinal-model-button
spinal-model-button/model.js
class ButtonModel extends Model { // 1 constructor() { super(); // 2 this.add_attr({ // 3 pressed: false }); } } module.exports.ButtonModel = ButtonModel;
When creating a model, there are 2 things to take into account:
- Our ButtonModel class that inherits from the Model class in the SpinalCore library.
- The first instruction of the constructor is to call the super() method. As this function will inherit from a Model class inside the SpinalCore library, we need to call the parent constructor.
- Every argument that needs to be synchronized should be created using the add_attr() method like in the example above.
The model of the virtual button is now defined and contains its state (on/off) in an boolean attribute called pressed.
Now that we have our button model, we need to control its state by modifying its attribute “pressed”. To do this, we create an organ that interacts with the model.
Make a new folder called virtualButtonOrgan where we are going to define our process.
~/button-system$ mkdir virtualButtonOrgan
An organ has to be linked with the Spinalhub via a connector. For this tutorial, we use the Node.js connector, which has already been installed at the first step.
Inside the organ folder, create the file called index.js with the code below.
virtualButtonOrgan/index.js
// 1 const spinalCore = require('spinal-core-connectorjs'); const models = require('../spinal-model-button/model.js'); // 2 process.env.SPINALHUB_PORT = 7777; process.env.SPINALHUB_IP = "127.0.0.1"; process.env.SPINAL_USER_ID = 168; process.env.SPINAL_PASSWORD = "SPINAL_PASSWORD"; // you will find it in th file .config.json (spinalcom connection configuration file) const conn = spinalCore.connect(`http://${process.env.SPINAL_USER_ID}:${process.env.SPINAL_PASSWORD}@${process.env.SPINALHUB_IP}:${process.env.SPINALHUB_PORT}/`); // 3: Create and store button spinalCore.load(conn, "myButton", function (myButton) { //success callback console.log('load & sync existing model if it exists'); press(myButton); }, function (myButton) { //error callback myButton = new models.ButtonModel(); spinalCore.store(conn, myButton, "myButton", function () { console.log('store & sync new model, first connection'); press(myButton); }); } ); // 4: Simulate that a button is being pressed function press(button) { // Toggle pressed button.pressed.set(!button.pressed.get()); // Call the function every second setTimeout(function () { console.log("button has been pressed"); press(button); }, 1000); }
These are the steps that the code is following:
- Requires connector and model.
- Establishes a connection with the hub, with write/read rights, using a user, password and environment variables. To understand more about configuration, please head to the configuration docs.
- Creates and synchronizes an instance of our button model and stores it in the hub. We first try to load and sync an existing instance from the hub, if no instance is found we create a new one
- Changes the data periodically through the press() function.
The current system folder organization so far is:
Run your organ
Run your organ with node:
~/button-system$ node virtualButtonOrgan/index.js
We should have the following system running by now:
Results: Monitor the value in the admin UI
Now we will check if everything is fine. Let’s open the admin dashboard and see modification in real time.
We see the file “mybutton”, to access to the real time value, check db inspector.
Now that our virtual button works, we are going to create a monitoring organ that subscribe to the virtualButton data and display its state in real time in the terminal.
Make a new folder called virtualButtonMonitorOrgan where we are going to define our process.
~/button-system$ mkdir virtualButtonMonitorOrgan
We will use the Node.js connector in the same way then we did before in the file index.js
virtualButtonMonitorOrgan/index.js
// 1 const spinalCore = require('spinal-core-connectorjs'); // 2 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 = "SPINAL_PASSWORD"; // you will find it in th file .config.json (spinalcom connection configuration file) const conn = spinalCore.connect(`http://${process.env.SPINAL_USER_ID}:${process.env.SPINAL_PASSWORD}@${process.env.SPINALHUB_IP}:${process.env.SPINALHUB_PORT}/`); // 3: Create and store button spinalCore.load(conn, "myButton", function (myButton) { //success callback printState(myButton); } ); // 4: print the state when pressed function printState(button) { button.bind(function () { if (button.pressed.get() === true ) console.log("Button has been pressed!"); }); }
These are the steps that the code is following:
- Requires connector and model.
- Establishes a connection with the hub, with write/read rights, using a user, password and environment variables. To understand more about configuration, please head to the configuration docs.
- Load and sync the existing instance of the button from the hub.
- bind the display function that print the data periodically through the printState() function.
The current system folder organization so far is:
Run your organ
We assume that all your precedent organs are still running.
Run your monitoring organ with node:
~/button-system$ node virtualButtonMonitorOrgan/index.js
We should have the following system running by now:
Results
Conclusion
This first tutorial showed you three things :
- how to install & launch a basic spinal system
- how to create and store your own synchronized data model
- how to store subscribe, monitor and assign events to modification of one data
This tutorial will be continued in Basic Equipment Tutorial.