Pages about my work at the Electronic Visualization Laboratory (EVL) at the University of Illinois at Chicago (UIC).

sabi.js

sabi.js

sabi.js: control your devices through a HTML5/Node/Javascript framework

Sabi.js

  • Run commands locally
  • Run scripts locally
  • Run scripts on a remote server
  • Send OSC messages to a network device
  • Send serial port commands to a device

Software dependencies

  • node.js
    • package: http-auth
    • package: mime
    • package: socket.io
    • package: sprint
    • package: serialport
    • package: forever
  • Web packages
    • socket.io.js
    • jquery.mobile.js
    • jquery.js
    • socket.io.js
    • underscore.js
    • backbone.js

Download

Initial release:

  • sabi.js - fix http digest authentification - Version: 1.2 Size: 2.11 MB Release date: 2015-04-24
  • sabi.js for Windows - Version for Windows and nodejs v0.12.2 - Version: 1.2 Size: 17.38 MB Release date: 2015-04-24 version for Windows and Nodejs 0.12.2 (no installation required). Just run GO.bat

Installation

  • Install Node.js and its package manager
  • Check the installation
    • node.js: type node -v You should get something like v0.10.xx
    • npm: type npm -v You should get something like v1.xx
  • Install dependencies
    • In the sabi.js folder: npm install
  • Settings
    • On Linux: the user running the serial port commands should be in the ‘dial out’ group
  • Open the sabi.js folder
    • Edit the file text config/sabi.json (JSON file format). Syntax is defined in the section below. Watch out: the JSON syntax is very strict, all names are surrounded by quotes (“bla”), opening and closing brackets must match, and, very important, a comma is needed is there’s a following item in the list, but no comma in the last item.
      • In the “global” section: server_port specifies the port the web server is listening to (port 9000 by default). Check your firewall, as needed.
      • In the “global” section: security set to true will require an account name and password to access the pages. Set to false, anyone can access the site.
    • Generate user passwords: if “security” is set to “true” in sabi.json, you need to generate a password file (called users.htpasswd) containing one or more accounts (in the realm ‘sabi’): users will need to enter a username and password to access the commands
      • Syntax: htdigest [-c] passwordfile realm username
      • Create a new file with a new user: ./node_modules/htdigest/lib/htdigest-bin.js -c users.htpasswd sabi user1
      • Add a new user: ./node_modules/htdigest/lib/htdigest-bin.js users.htpasswd sabi user2
  • Run
    • While editing your sabi.json file, it is convenient to check the messages from the server. For this, just run node server.js from the prompt,
    • Open any web browser to the http://server:port address. Fill out the password if needed and start controlling your devices,
    • Once your configuration if finalized, your can use the forever command or the provided GO script:
      • ./node_modules/forever/bin/forever start server.js starts the server in the background, and will monitor its execution (and restart if it crashes)
      • ./node_modules/forever/bin/forever stopall stops all the instances of the server
      • in production mode, the GO script should be placed in the startup script of the machine or the user.

To do

  • Bi-directorional communication (web-socket) to build collaborative interfaces (needed to maintain a shared state on the server, for instance a volume value).
  • Expose more jquery-mobile UI elements

Screenshots of example pages

mainpage admin
omegalib sound

Action shots

cybercommons ipad-cave2-vert
ipad-cave2 iphone-1
iphone-3 nexus-cave2

Sample file (sabi.json)

{
    "global": {
	"security" : "true",
	"server_port" : "10000"
    },
    "main": {
        "header" : "<h1 > Cybercommons - EVL / UIC < /h1 >",
        "footer" : "<h4> > abi.js control interface < /h4 >",
        "image" : "images/sabi_coffee_400.jpg",
        "image_style" : "width=\"90%\" style=\"max-width:420px;align:center;margin: 0 auto;\"",
        "pages" : [ "Setup", "SAGE", "Audio" ]
    },
    "actions": {
        "displays-on":    {  "serial": "op A1 display.power = 1\r", "baud":"19200", "port":"/dev/ttyUSB1" },
        "displays-off":   {  "serial": "op A1 display.power = 0\r", "baud":"19200", "port":"/dev/ttyUSB1" },
        "displays-orion": {  "serial": "op A1 slot.recall (8) \r", "baud":"19200", "port":"/dev/ttyUSB1" },
        "displays-sage":  {  "serial": "op A1 slot.recall (0) \r", "baud":"19200", "port":"/dev/ttyUSB1" },
        "displays-center":{  "serial": "op A1 slot.recall (1) \r", "baud":"19200", "port":"/dev/ttyUSB1" },
        "displays-split": {  "serial": "op A1 slot.recall (2) \r", "baud":"19200", "port":"/dev/ttyUSB1" },
        "xinerama-on":    {  "command": "ssh bigdaddy sudo /usr/local/bin/goXinerama" },
        "xinerama-off":   {  "command": "ssh bigdaddy sudo /usr/local/bin/noXinerama" },

        "sage-on":      {  "command": "xterm -e ssh bigdaddy ./GO-sage" },
        "sage-off":     {  "command": "ssh bigdaddy ./KILL_ALL" },
        "sage-ui":      {  "script": "/home/sage/UI" },
        "touch-on":     {  "command": "xterm -e ssh wasp.evl.uic.edu ./Dev/pqlabs/GO" },
        "touch-off":    {  "command": "ssh wasp.evl.uic.edu ./Dev/pqlabs/GO" },

        "capture-laptop1":    {  "script": "/home/sage/HD-720p-SDI"},
        "capture-laptop2":    {  "script": "/home/sage/HD-720p-SDI2"},
        "capture-laptop3":    {  "script": "/home/sage/HD-1080p-SDI"},
        "capture-stop":    {  "script": "/home/sage/STOP"},

        "audio-reset":         { "oscmessage" : "/as/cues", "parameters" : "1",      "server": "lynch.evl.uic.edu:16003" },
        "audio-main-mute-on":  { "oscmessage" : "/as/vGroups/1/mute", "parameters" : "1",      "server": "lynch.evl.uic.edu:16003" },
        "audio-main-mute-off": { "oscmessage" : "/as/vGroups/1/mute", "parameters" : "0",      "server": "lynch.evl.uic.edu:16003" },
        "audio-main-volume":   { "oscmessage" : "/as/vGroups/1/level",  "server": "lynch.evl.uic.edu:16003" },

        "audio-wall-on":        { "oscmessage" : "/as/cues", "parameters" : "33",      "server": "lynch.evl.uic.edu:16003" },
        "audio-wall-off":       { "oscmessage" : "/as/cues", "parameters" : "-1",      "server": "lynch.evl.uic.edu:16003" },
        "audio-wall-mute-on":  { "oscmessage" : "/as/vGroups/9/mute", "parameters" : "1",      "server": "lynch.evl.uic.edu:16003" },
        "audio-wall-mute-off": { "oscmessage" : "/as/vGroups/9/mute", "parameters" : "0",      "server": "lynch.evl.uic.edu:16003" },
        "audio-wall-volume":    { "oscmessage" : "/as/vGroups/9/level",  "server": "lynch.evl.uic.edu:16003" },

        "audio-laptop-on":        { "oscmessage" : "/as/cues", "parameters" : "29",      "server": "lynch.evl.uic.edu:16003" },
        "audio-laptop-off":       { "oscmessage" : "/as/cues", "parameters" : "-1",      "server": "lynch.evl.uic.edu:16003" },
        "audio-laptop-mute-on":  { "oscmessage" : "/as/vGroups/10/mute", "parameters" : "1",      "server": "lynch.evl.uic.edu:16003" },
        "audio-laptop-mute-off": { "oscmessage" : "/as/vGroups/10/mute", "parameters" : "0",      "server": "lynch.evl.uic.edu:16003" },
        "audio-laptop-volume":    { "oscmessage" : "/as/vGroups/10/level",  "server": "lynch.evl.uic.edu:16003" }
    },


    "Setup" : {
        "title" : "Wall setup",
        "groups" : [ "displays", "x11server"],
        "displays" : { 
            "title": "Displays",
            "image": "images/planar_small.jpg",
            "actions": [
                {"title": "Displays ON", "action": "displays-on"},
                {"title": "Displays OFF", "action": "displays-off"},
                {"title": "SAGE mode", "action": "displays-sage", "theme":"b"},
                {"title": "Cluster mode", "action": "displays-orion", "theme":"e"},
                {"title": "Laptop mode", "action": "displays-center", "theme":"c"}
            ]
        },
        "x11server" : {
            "title": "X11 server",
            "image": "images/x11_small.png",
            "actions": [
                {"title": "With Xinerama mode (large desktop)", "action": "xinerama-on"},
                {"title": "No Xinerama mode (many servers)", "action": "xinerama-off"}
            ]
        }
    },
    "SAGE" : {
        "title" : "SAGE",
        "groups" : [ "usesage", "capture" ],
        "usesage" : { 
            "title": "Use SAGE",
            "image": "images/sage_small.jpg",
            "actions": [
                {"title": "Setup X11 server", "action": "xinerama-off"},
                {"title": "Show SAGE", "action": "displays-sage"},
                {"title": "Start SAGE", "action": "sage-on", "theme": "b"},
                {"title": "Stop SAGE", "action": "sage-off", "theme": "b"},
                {"title": "Start Touch", "action": "touch-on", "theme": "c"},
                {"title": "Stop Touch", "action": "touch-off", "theme": "c"},
                {"title": "SAGE UI", "action": "sage-ui", "theme": "e"}
            ]
        },
        "capture" : { 
            "title": "Use the capture card",
            "image": "images/capture_small.png",
            "actions": [
                {"title": "Laptop-1 720p 60Hz", "action": "capture-laptop1"},
                {"title": "Laptop-2 720p 60Hz", "action": "capture-laptop2"},
                {"title": "Laptop-1 1080p 30Hz", "action": "capture-laptop3"},
                {"title": "Capture Stop", "action": "capture-stop", "theme":"e"}
            ]
        }
    },
    "Audio" : {
        "title" : "Audio system",
        "groups" : [ "volume", "wall", "laptop" ],
        "volume" : { 
            "title": "Volume",
            "image": "images/volume_small.png",
            "description": "Main controls",
            "actions": [
                {"title": "Volume",  "action": "audio-main-volume",  "role": "range", "minvalue": "-40", "maxvalue": "0" },
                {"title": "Mute",    "action": "audio-main-mute-on" , "theme": "b"},
                {"title": "unMute",  "action": "audio-main-mute-off" , "theme": "b"},
                {"title": "Reset audio server",  "action": "audio-reset"}
            ]
        },
        "wall" : { 
            "title": "Wall audio",
            "image": "images/sage_small.jpg",
            "description": "Manage the audio from the wall (SAGE)",
            "actions": [
                {"title": "Volume",  "action": "audio-wall-volume",  "role": "range", "minvalue": "-40", "maxvalue": "0" },
                {"title": "Activate","action": "audio-wall-on"},
                {"title": "Mute",    "action": "audio-wall-mute-on" , "theme": "b"},
                {"title": "unMute",  "action": "audio-wall-mute-off" , "theme": "b"}
            ]
        },
        "laptop" : { 
            "title": "Laptop audio",
            "image": "images/volume_small.png",
            "description": "Manage the audio from laptop",
            "actions": [
                {"title": "Volume",  "action": "audio-laptop-volume",  "role": "range", "minvalue": "-40", "maxvalue": "0" },
                {"title": "Activate","action": "audio-laptop-on"},
                {"title": "Mute",    "action": "audio-laptop-mute-on" , "theme": "b"},
                {"title": "unMute",  "action": "audio-laptop-mute-off" , "theme": "b"}
            ]
        }
    }
}

Licence

Software License Agreement (BSD License)

Copyright © 2012 Luc Renambot. University of Illinois at Chicago

All rights reserved.
Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of Luc Renambot, UIC nor the names of sabi.js’s contributors may be used to endorse or promote products derived from this software without specific prior written permission of Luc Renambot.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Sources of Intellectual Property Included in sabi.js

sabi.js is issued by Luc Renambot under the BSD license above. Below is a list of certain publicly available software that is the source of intellectual property in sabi.js, along with the licensing terms that pertain to those sources of IP. This list is for informational purposes only and is not intended to represent an exhaustive list of third party contributions to sabi.js.

        node.js
        NPM
                node package: http-auth
                node package: mime
                node package: socket.io
                node package: sprint
                node package: serialport
                node package: forever
        Web packages
                socket.io.js
                jquery.mobile.js
                jquery.js
                socket.io.js
                underscore.js
                backbone.js

Name

How do you pronounce ‘sabi.js’:
I personally say ‘sabi’ dot J S

What does sabi mean?
it’s half of wabi-sabi, that’s the short answer. One longer answer, in english, is in the book ‘Wabi-Sabi: for Artists, Designers, Poets & Philosophers’, ISBN: 0981484603

wabi-sabi

life

(‘cat’ art work by a little girl near Hilo, Hawaii)