Versions Compared

Key

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

Image Removed

Table of contents

  1. Goal
  2. Creating a new spinal System
  3. Create your wine cellar digital twin
  4. Create the virtualTemperatureSensor organ
  5. Launch the system and monitor the results

Quick navigation

Child pages (Children Display)
alltrue
pageTutorials

Panel
titleGoal
Anchor11

We will create a simple IoT system that will alert us through a nice web interface whenever the temperature at our wine cellar is not between 10°C and 16°C. We will call this system FineWine.

System architecture:

Image Removed

This system, based on our understanding of intelligent micro-system, is composed of the following organs:

  • Nerve center: where the hub and its data are located.
  • Admin dashboard: the administration interface of your hub.
  • VirtualTemperatureSensor organ: simulate the temperature sensor of the wine cellar continuously and synchronize the samples with the hub.
  • Analytics organ: analyzes the temperature and alerts if the temperature is ok or not.
  • Monitoring interface organ: a web interface, displaying the current status of our wine cellar.
Panel
titleCreating a new Spinal System
Anchor22

Install spinal-system-basic

The first step is to create the directory where the project will be stored. We will call it fine-wine-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):

Code Block
languagebash
themeDJango
~/$  mkdir fine-wine-system
~/$ cd fine-wine-system
~/fine-wine-system$ npm init -y
~/fine-wine-system$ npm i https://github.com/spinalcom/spinal-browser-admin.git

Launch spinal-system

Code Block
languagebash
themeDJango
~/fine-wine-system$ pm2 start launch.config.js

PM2 will automatically start the Spinal Hub and the organs. Take care, if you have another hub running on port 7777, your new hub will not be launched ! (here is a command to see what port are used on ubuntu: sudo netstat -lp --inet)

After this installation, only SpinalHub is running on port 7777. SpinalHub containes a web server that provide his own Admin interface. Here is the architecture of the system you have after this first install:

Connect to Admin UI

As we have done in the getting started, connect to the admin dashboard to see if you hub is running :

http://127.0.0.1:7777/html/admin

The default admin account is :

Username

client ID

Passwordadmin168JHGgcz45JKilmzknzelf65ddDadggftIO98P

Image Removed

  • .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

    Image Added


    Panel
    titleGoal of the tutorial

    Anchor
    1
    1

    The objective of this tutorial is to create a simple IoT system that will alert us through a nice web interface whenever the temperature of our wine cellar is not between 10°C and 15°C. We will call this system FineWine.


    System architecture


    Image Added


    This system, based on our understanding of intelligent micro-system, is composed of the following organs:

    • Nerve Center : where the hub and its data are located.
    • Admin Dashboard : the administration interface of your hub.
    • VirtualTemperatureSensor organ : simulate the temperature sensor of the wine cellar continuously and synchronize the samples with the hub.
    • Analytics organ : analyzes the temperature and alerts if the temperature is ok or not.
    • Monitoring interface organ : a web interface, displaying the current status of our wine cellar.


    Panel
    titleRequirements

    For this tutorial, you just need the basic requirements.


    The digital twin will be defined in the libraries.

    The model is very simple, since we will not manage a lot of data. It is just a JavaScript function, which we will assume it's a class, from where we can create instances and store and load data.

    The three important points to follow in the creation of a model are:

    • The first instruction of the function must call the super() method passing its context as an argument. 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 passed using the add_attr() method like in the example below.
    • To inherit from the Model class, we call the extend() method from the SpinalCore library.

    Create a folder called spinal-model-wine-cellar at the root of your project and, inside it, create a file called model.js:

    Panel
    titleCreating a new Spinal System

    Anchor
    2
    2

    Install spinal-system-basic


    The first step is to create the directory where the project will be stored. We will call it fine-wine-system. Then, install inside the “spinal-system-basic” template. We suggest that before running the following command you initialize an npm project.

    Code Block
    languagebash
    themeDJango
    ~/$ mkdir fine-wine-system
    ~/$ cd fine-wine-system
    ~/fine-wine-system$ npm init -y
    ~/fine-wine-system$ npm i https://github.com/spinalcom/spinal-browser-admin.git

    Configuration files and passwords
    Anchor
    passwords
    passwords


    The installation of the basic system will generate 2 configuration files :

    • .apps.json : installed organ package of your spinal system
    • .config.json : spinalcom Spinalcom connection / environment configuration filelaunch

    In the .config.

    js : Start your hub using pm2
  • package.json : config of your package
  • Panel
    titleCreate your wine cellar digital twin
    Anchor
    33
    Code Block
    languagebash
    ~/fine-wine-system$  mkdir spinal-model-wine-cellar

    spinal-model-wine-cellar/model.js

    Code Block
    languagejs
    themeDJango
    linenumberstrue
    // wineCave-model.js function WineCellarModel() { WineCellarModel.super(this); this.add_attr({

    json file you will also find the password of the 3 basic users:

    • SPINAL_PASSWORD: password for the admin user, 
    • SPINAL_PASSWORD_ROOT : password for the root user,
    • SPINAL_PASSWORD_USER: password for the user user.


    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system$ cat .config.json


    Exemple of the .config.json

    .config.json

    Code Block
    languagejs
    themeDJango
    linenumberstrue
    {
      "spinal-core-hub": {
        "env": {
          "SPINAL_USER_ID": "168",
          "SPINALHUB_PORT": 7777,
           temperature: 0,"SPINALHUB_IP": "127.0.0.1",
          "SPINAL_PASSWORD": "RggdgJ7LUGT7", //this danger:is falsenot a default password. 
    }); }  spinalCore.extend(WineCellarModel, Model); module.exports = WineCellarModel;
    Panel
    titleCreate the virtualTemperatureSensor organ
    Anchor44

    Now that we have our model, we need to monitor its state. for this we are going to simulate a temperature sensor that modify its attribute “temperature”. Later we will be able to connect with a real IoT sensor.

    Make a new folder called virtualTempSensorOrgan where we are going to define our process.

    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system$  mkdir virtualTempSensorOrgan

    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.

    virtualTempSensorOrgan/index.js

    Code Block
    languagejs
    themeDJango
    linenumberstrue
    // 1
    var spinalCore = require("spinal-core-connectorjs");
    require("../spinal-model-wine-cellar/model.js");
    
    // 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 = "JHGgcz45JKilmzknzelf65ddDadggftIO98P";
    
    var 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 the wineCave model or load it if it exists
    spinalCore.load(
      conn,
      "myCellar",
      function(myCellar) {
        //success callback
        console.log("load & sync existing model if it exists");
        setSensorData(myCellar.temperature);
      },
      function(myCellar) {
        //error callback
        myCellar = new WineCellarModel();
        spinalCore.store(conn, myCellar, "myCellar", function() {
          console.log("store & sync new model, first connection");
          setSensorData(myCellar.temperature);
        });
      }
    );
    
    i = 0;
    sampleRate = 2;
    
    function setSensorData(currentTemperature) {
      var simTemp;
      console.log("Sending sensored temperature");
      simTemp = 15 + 5 * Math.sin(i);
      i += 0.5;
      currentTemperature.set(simTemp);
      setTimeout(function() {
        setSensorData(currentTemperature);
      }, sampleRate * 1000);
    }

    These are the steps that the code is following:

    1. Requires connector and model.
    2. 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.
    3. Creates and synchronize 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 exist, than we create a new one
    4. Changes the data periodically through the setSensorData() function.

    The current system folder organization so far is:

    Image Removed

    Panel
    titleCreate the analyticsTemp Organ
    Anchor55

    Now that we have our temperature Sensor organ, we need to monitor its danger zone. For this we are going to simulate a analytics organ that modify its attribute “danger”. Later we will be able to connect with a real IoT sensor.

    Make a new folder called TempSensor where we are going to define our danger zone.

    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system$  mkdir analyticsTempOrgan

    Inside the organ folder, create the file called index.js with the code below.

    analyticsTempOrgan/index.js

    Code Block
    languagejs
    themeDJango
    linenumberstrue
    // 1
    var spinalCore = require("spinal-core-connectorjs");
    require("../ "SPINAL_PASSWORD_ROOT": "cvXqdkRFqUHF", //this is not a default password. 
          "SPINAL_PASSWORD_USER": "I5h8bqkvPxjN"  //this is not a default password. 
        },
        "env_test": {
          "SPINAL_USER_ID": "168",
          "SPINALHUB_PORT": 7777,
          "SPINALHUB_IP": "127.0.0.1",
          "SPINAL_PASSWORD": "RggdgJ7LUGT7", //this is not a default password. 
          "SPINAL_PASSWORD_ROOT": "cvXqdkRFqUHF", //this is not a default password. 
          "SPINAL_PASSWORD_USER": "I5h8bqkvPxjN" //this is not a default password. 
        },
        "env_production": {
          "SPINAL_USER_ID": "168",
          "SPINALHUB_PORT": 7777,
          "SPINALHUB_IP": "127.0.0.1",
          "SPINAL_PASSWORD": "RggdgJ7LUGT7", //this is not a default password. 
          "SPINAL_PASSWORD_ROOT": "cvXqdkRFqUHF", //this is not a default password. 
          "SPINAL_PASSWORD_USER": "I5h8bqkvPxjN" //this is not a default password. 
        }
      }
    }
    
    

    Launch spinal-system


    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system$ pm2 start launch.config.js

    PM2 will automatically start the SpinalHub. Take care, if you have another hub running on port 7777, your new hub will not be launched ! ( here is a command to see what port are used on Ubuntu: sudo netstat -lp --inet ). If you want to launch two hubs at the same time, you will need to modify the port number in the configuration file (.config.json).

    After this installation, your SpinalHub is running on port 7777. SpinalHub containes a web server that provide his own Admin interface. Here is the architecture of the system you have after this first install:

    Image Added

    Connect to Spinalcom Admin interface


    As we have done in the getting started, connect to the admin dashboard to see if you hub is running :

    http://127.0.0.1:7777/html/admin


    Your folder organization should look like this after this first step:

    Image Added

    • .browser_organs : web browser folder
    • .config_env : the environment configuration
    • nerve-center : Spinalcom nerve center
    • node_modules : npm (Node package manager) & All the spinal-packages
    • .apps.json : installed packages of your spinal system
    • .config.json : Spinalcom connection configuration file
    • launch.config.js : launch pm2 file
    • package.json : configuration file


    For this step, we create a browser organ. This type of organ will create for you an new web page with the visualisation of your data. We will be able to create what we want to see. Actually we will do this for our fine wine cellar to know when temperature is in danger zone.

    These are the steps that the code is following:

    1. Create your spinal browser folder
    2. Creates and synchronize an instance with Javascript
    3. browserify the code
    4. Launch the browser organ.

    Inside .browser_organs, make a new folder called finewine inside, create a file named index.html. we define our web page.

    Panel
    titleCreate your wine cellar digital twin

    Anchor
    3
    3

    The digital twin will be defined in a specific libraries: spinal-model-wine-cellar.

    The model is very simple, since we will not manage a lot of data. It is just a JavaScript function, which we will assume it's a class, from where we can create instances, store and load data.

    Create a folder called spinal-model-wine-cellar at the root of your project and, inside it, create a file called model.js:


    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system$ mkdir spinal-model-wine-cellar

    spinal-model-wine-cellar/model.js

    ");

    Code Block
    languagejs
    themeDJango
    linenumberstrue
    class WineCellarModel extends Model { // 1
    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 = "JHGgcz45JKilmzknzelf65ddDadggftIO98P";
    
    var conn = spinalCore.connect(
      `http://${process.env.SPINAL_USER_ID}:${process.env.SPINAL_PASSWORD}@${
        process.env.SPINALHUB_IP
      }:${process.env.SPINALHUB_PORT}/`
    );
    
    // 3: load the wineCave model if it exists
    spinalCore.load(conn, "myCellar", function(myCellar) {
      //success callback
      console.log("load & sync existing model if it exists");
      // analyzeData(myCellar.temperature);
      analyzeData(myCellar);
    });
    
    // 4
    function analyzeData(myCellar) {
      myCellar.bind(function() {
        if (myCellar.temperature.get() < 10 || myCellar.temperature.get() > 16) {
          myCellar.danger.set(true);
          console.log("Danger");
        } else {
          myCellar.danger.set(false);
          console.log("Fine Wine");
        }
      });
    }

    These are the steps that the code is following:

    1. Requires connector and model.
    2. 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.
    3. Creates and synchronize an instance of our wineCellar model and stores it in the hub. We first try to load and sync an existing instance of the wine cellar from the hub.
    4. Changes the danger data everytime temperature value change. We used bind function from spinalConnector to synchronized the data. Function inside bind will be called everytime the data change.

    The current system folder organization so far is:

    Image Removed

    Panel
    titleCreate a browser organ
    Anchor
    66
    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system/.browser_organ$ mkdir analyticsTempOrgan
    ~/fine-wine-system/.browser_organ$ cd analyticsTempOrgan
    ~/fine-wine-system/.browser_organ$ touch index.html

    Index.html

    Code Block
    languagexml
    themeDJango
    linenumberstrue
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8">
      <title>FineWine: SpinalCore Quickstart</title>
      <link rel="stylesheetconstructor() {
        super(); // 2
        this.add_attr({ // 3
          temperature: 0,
          danger: false
        });
      }
    }
    module.exports.WineCellarModel = WineCellarModel;


    The three important points to follow in the creation of a model are:

    1. Our WineCellarModel will be a class that inherits from the Model class from the SpinalCore library.
    2. 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.
    3. Every argument that needs to be synchronized should be passed using the add_attr() method like in the example above.


    Panel
    titleCreate the virtualTemperatureSensor organ

    Anchor
    4
    4

    Now that we have our model (simple digital twin of the wine cellar), we need to monitor its state. For this we are going to simulate a temperature sensor that modify its attribute “temperature”. Later we will be able to connect with a real IoT sensor.

    Make a new folder called virtualTempSensorOrgan where we are going to define our process.

    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system$ mkdir virtualTempSensorOrgan

    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 (in the node_modules folder).

    Inside the organ folder, create the file called index.js with the code below.

    ( don't forget to replace "YOUR PASSWORD FOR THE 'ADMIN' USER" with the appropriate password that you can find in the .config.json file 

    SPINAL_PASSWORD: password for the admin user, generated automatically )

    Inside the folder virtualTempSensorOrgan, install spinal-core-connectorjs from GitHub.


    virtualTempSensorOrgan/index.js

    Code Block
    languagejs
    themeDJango
    linenumberstrue
    const spinalCore = require("spinal-core-connectorjs");
    const model = require("../spinal-model-wine-cellar/model.js");
    
    console.log("Configuration environnement 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.SPINALH_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.SPINALH_PASSWORD}@${process.env.SPINALHUB_IP}:${process.env.SPINALHUB_PORT}/`);
    
    spinalCore.load(conn, "myCellar", function (myCellar) {
      console.log("load & sync new model, first connection");
      setSensorData(myCellar.temperature);
    }, function (myCellar) {
      myCellar = new model.WineCellarModel();
      spinalCore.store(conn, myCellar, "myCellar", function () {
        console.log("load & sync new model, first connection");
        setSensorData(myCellar.temperature);
      })
    })
    
    i = 0;
    sampleRate = 2;
    
    function setSensorData(currentTemperature) {
      var simTemp;
    
      console.log("Sending sensor temperature");
      simTemp = 15 + 5 * Math.sin(i);
      i += 0.5;
      currentTemperature.set(simTemp);
      setTimeout(function () {
        setSensorData(currentTemperature);
      }, sampleRate * 1000);
    }


    These are the steps that the code is following:

    1. Requires connector and model.
    2. 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.
    3. Creates and synchronize 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 exist, then we create a new one.
    4. Changes the data periodically through the setSensorData() function.

    The current system folder organization so far is:

    Image Added


    Instead of running your organ with node, you can add your organ to the pm2 process.

    Just add it into the file .apps.json


    .apps.json

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


    Here is the architecture of the system you have after this step:

    Image Added



    Panel
    titleCreate the analyticsTemp Organ

    Anchor
    5
    5

    Now that we have our temperature Sensor organ, we need to monitor its danger zone. For this we are going to simulate a analytics organ that modify its attribute “danger”. Later we will be able to connect with a real IoT sensor.

    Make a new folder called TempSensor where we are going to define our danger zone.

    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system$ mkdir analyticsTempOrgan

    Inside the organ folder, create the file called index.js with the code below, install spinal-core-connectorjs, and replace SPINAL_PASSWORD": "YOUR PASSWORD FOR THE 'ADMIN' USERSPINAL_PASSWORD": "YOUR PASSWORD FOR THE 'ADMIN' USER with the appropriate password.

    analyticsTempOrgan/index.js

    Code Block
    languagejs
    themeDJango
    linenumberstrue
    // 1
    const spinalCore = require("spinal-core-connectorjs");
    
    // 2
    console.log("Configuration environnement 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.SPINALH_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.SPINALH_PASSWORD}@${process.env.SPINALHUB_IP}:${process.env.SPINALHUB_PORT}/`);
    // 3
    spinalCore.load(conn, "myCellar", function (myCellar) {
      console.log("load & sync new model if it exists");
      analyseSensorData(myCellar);
    });
    
    i = 0;
    sampleRate = 2;
    // 4
    function analyseSensorData(cellar) {
      cellar.bind(function () {
        if (cellar.temperature.get() < 10 || cellar.temperature.get() > 16) {
          cellar.danger.set(true);
          console.log("Danger");
        } else {
          cellar.danger.set(false);
          console.log("Fine Wine");
        }
      });
    }

    These are the steps that the code is following:

    1. Requires connector.
    2. Establishes a connection with the hub, with write/read rights, using user, password and environment variables. To learn more about configuration, please head to the configuration docs.
    3. We first try to load and sync an existing instance of the wine cellar from the hub. If this fails, creates and synchronizes an instance of our WineCellar model and stores it in the hub.
    4. Changes the danger data every time temperature value change. We use the bind function from spinalConnector to synchronize the data. The function given to bind will be called every time the data changes.

    The current system folder organization so far is:

    Image Added


    Instead of running your organ with node, you can add your organ to the hub process, just add it into .apps.json


    .apps.json

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


    Here is the architecture of the system you have after this step:

    Image Added


    7
    Panel
    titleCreate a browser organ

    Anchor
    6
    6

    For this step, we create a browser organ. This type of organ will create a new web page with the visualization of your data. Now we will do this for our fine wine cellar to know when temperature is in danger zone.

    These are the steps that the code is following:

    1. Create your spinal browser folder
    2. Creates and synchronize an instance with Javascript
    3. Browserify the code
    4. Launch the browser organ.

    At the end of this part your system's folder organization will be:


    Image Added


           1. Create your spinal browser folder


    Inside .browser_organs, make a new folder called finewine inside, create a file named index.html. we define our web page.

    Code Block
    languagebash
    themeDJango
    ~/fine-wine-system/.browser_organ$ mkdir finewine
    ~/fine-wine-system/.browser_organ$ cd finewine
    ~/fine-wine-system/.browser_organ/finewine$ touch index.html
    ~/fine-wine-system/.browser_organ/finewine$ mkdir src
    ~/fine-wine-system/.browser_organ/finewine$ touch src/inspectFineWine.js


    fine-wine-system/.browser_organ/finewine/index.html

    Code Block
    languagexml
    themeDJango
    linenumberstrue
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8">
      <title>FineWine: SpinalCore Quickstart</title>
      <link rel="stylesheet"
            href="https://bootswatch.com/_vendor/bootstrap/dist/css/bootstrap.min.css">
    </head>
    
    <body>
      <div style="margin-top: 100px; margin-left: auto; margin-right: auto; width: 300px">
        <div class="row"
             style="text-align: center;">
          <div class="col-lg-offset-4">
            <h1>FineWine</h1>
            <p>This simple IoT system will let you know whenever the temperature at your
              wine cave is not between 10°C and 16°C. Cheers!</p>
          </div>
        </div>
        <div class="row">
          <div class="col-lg-offset-4">
            <hr />
          </div>
        </div>
        <div class="row">
          <div class="col-lg-offset-4"
               style="width: 100%">
            <div class="bs-component">
              <div class="alert alert-success"
                   id="wine_temp_container">
                <div style="font-size: 100px; text-align: center;">
                  <strong id="wine_temp">0</strong>°C</div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- SpinalCore SDK -->
    
      <script type="text/javascript"
            href  src="https://bootswatch.com/_vendor/bootstrap/dist/css/bootstrap.min.cssfinewine/bundle.js">
      </head>script>
      <script>
     <body>   <divFileSystem.CONNECTOR_TYPE style="margin-top: 100px; margin-left: auto; margin-right: auto; width: 300px">
        <div class="row"
             style="text-align: center;">
          <div class="col-lg-offset-4">
            <h1>FineWine</h1>
            <p>This simple IoT system will let you know whenever the temperature at your
              wine cave is not between 10°C and 16°C. Cheers!</p1>
          </div>
        </div>
        <div class="row">
          <div class="col-lg-offset-4">
            <hr />
          </div>
        </div>
        <div class="row">
          <div class="col-lg-offset-4"
               style="width: 100%">
            <div class="bs-component">
              <div class="alert alert-success"
           "Browser";
      </script>
    </body>
    
    </html>

    2. Creates and synchronize an instance with Javascript

    src/inspectFineWine.js

    Code Block
    languagejs
    themeDJango
    linenumberstrue
    // 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}/`
    );
    
    // Load avatar
    spinalCore.load(conn, "myCellar", function(myCellar) {
      console.log("Model loaded!");
      updateView(myCellar);
    });
    
    // Listen to changes in the avatar and update view
    function updateView(myCellar) {
      myCellar.bind(function() {
        if (myCellar.temperature.has_been_modified()) {
          var new_temp = parseFloat(myCellar.temperature.get()).toFixed(1);
          document.getElementById("wine_temp").innerHTML = new_temp;
        }
        if (myCellar.danger.has_been_modified()) {
          var danger = myCellar.danger.get();
          if (danger)
            id=document.getElementById("wine_temp_container">).className =
              "alert alert-danger";
          else
     <div style="font-size: 100px; text-align: center;">   document.getElementById("wine_temp_container").className =
              <strong id="wine_temp">0</strong>°C</div>"alert alert-success";
        }
      });
      </div>
            </div>
          </div>
        </div>
      </div>
      <!-- SpinalCore API -->
    
      <script type="text/javascript"
              src="finewine/bundle.js">
      </script>
      <script>
        FileSystem.CONNECTOR_TYPE = "Browser";
      </script>
    </body>
    
    </html>
    </html>

    The current system folder organization so far is:

    Panel
    titleCreate our second organ : virtualButtonMonitor
    Anchor
    7
    }
    

    3. Browserify the code


    You need to install browserify package through npm, if is not installed yet.

    Code Block
    languagebash
    themeDJango
    linenumberstrue
    npm install browserify

    And browserify the code with this command :

    Code Block
    languagebash
    ~/fine-wine-system/.browser_organ/finewine$ ../../node_modules/.bin/browserify src/inspectFineWine.js -o bundle.js
    

    4. Launch the browser organ.


    You have everything you need. You can check that everything is working by running the PM2 process file automatically generated:

    Code Block
    languagebash
    ~/fine-wine-system$ pm2 start launch.config.js


    PM2 will automatically start the Spinal Hub and the organs.

    Image Added

    Browser organ are little different than other organ, they provide a web page with his own route. Name of the folder in .browser_organs correspond to the route in your browser.

    Base URL:

    http://localhost:7777/html/

    Your browser organ runs on this page:

    http://localhost:7777/html/finewine


    Image AddedImage Added
    After this installation, only SpinalHub is running on port 7777. SpinalHub containes a web server that provides your browser organ. Here is the architecture of the system you have after this first install:

    Image Added


    Conclusion