├── .gitignore ├── LICENSE ├── README.md ├── apps ├── dashboard │ ├── app.js │ ├── client │ │ ├── css │ │ │ ├── app.css │ │ │ ├── bootstrap.min.css │ │ │ ├── dashboard.css │ │ │ └── font-awesome.css │ │ ├── favicon.ico │ │ ├── fonts │ │ │ ├── NeoSansIntel │ │ │ │ ├── NeoSansIntel-Italic.ttf │ │ │ │ ├── NeoSansIntel-Light.ttf │ │ │ │ ├── NeoSansIntel-LightItalic.ttf │ │ │ │ ├── NeoSansIntel-Medium.ttf │ │ │ │ ├── NeoSansIntel-MediumItalic.ttf │ │ │ │ └── NeoSansIntel.ttf │ │ │ ├── droid-sans │ │ │ │ ├── DroidSans-Bold.ttf │ │ │ │ ├── DroidSans.ttf │ │ │ │ └── LICENSE.txt │ │ │ ├── font-awesome │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ └── fontawesome-webfont.woff │ │ │ └── glyphicons-halflings-regular.ttf │ │ ├── index.html │ │ └── js │ │ │ ├── app.js │ │ │ ├── jquery.min.js │ │ │ └── underscore-min.js │ └── dashboard_controller.js ├── hello_world │ ├── README.md │ ├── app.js │ └── client │ │ └── index.html └── maker_cat │ ├── client │ ├── favicon.ico │ ├── favicon.png │ ├── index.html │ ├── sass │ │ └── app.scss │ ├── static │ │ ├── css │ │ │ ├── app.css │ │ │ ├── bootstrap.min.css │ │ │ └── play_mode.css │ │ ├── fonts │ │ │ ├── NeoSansIntel │ │ │ │ ├── NeoSansIntel-Italic.ttf │ │ │ │ ├── NeoSansIntel-Light.ttf │ │ │ │ ├── NeoSansIntel-LightItalic.ttf │ │ │ │ ├── NeoSansIntel-Medium.ttf │ │ │ │ ├── NeoSansIntel-MediumItalic.ttf │ │ │ │ └── NeoSansIntel.ttf │ │ │ ├── droid-sans │ │ │ │ ├── DroidSans-Bold.ttf │ │ │ │ ├── DroidSans.ttf │ │ │ │ └── LICENSE.txt │ │ │ └── glyphicons-halflings-regular.ttf │ │ ├── img │ │ │ ├── loading.gif │ │ │ ├── loading_inverted.gif │ │ │ └── loading_old.gif │ │ └── js │ │ │ ├── angular-route.min.js │ │ │ ├── angular.min.js │ │ │ ├── app.js │ │ │ ├── d3.min.js │ │ │ ├── jquery.min.js │ │ │ └── underscore-min.js │ └── templates │ │ ├── add_remove_pins.html │ │ ├── app_settings.html │ │ ├── connect.html │ │ ├── pin.html │ │ ├── pin_button.html │ │ ├── pin_settings.html │ │ ├── pin_settings_directive.html │ │ ├── pin_slider.html │ │ ├── pin_stub.html │ │ ├── play.html │ │ ├── remove_pin_dialog.html │ │ ├── reset_dialog.html │ │ ├── ssid_changed.html │ │ └── ssid_dialog.html │ ├── default_boardstate.conf │ ├── index.js │ ├── lib │ ├── app.js │ ├── conf.js │ ├── gpio.js │ ├── http.js │ └── socket.js │ ├── package.json │ └── test-server.js ├── client ├── app.less ├── favicon.ico ├── index.html ├── static │ ├── css │ │ ├── app.css │ │ ├── bootstrap.min.css │ │ ├── font-awesome.css │ │ └── jquery.scombobox.min.css │ ├── fonts │ │ ├── NeoSansIntel │ │ │ ├── NeoSansIntel-Italic.ttf │ │ │ ├── NeoSansIntel-Light.ttf │ │ │ ├── NeoSansIntel-LightItalic.ttf │ │ │ ├── NeoSansIntel-Medium.ttf │ │ │ ├── NeoSansIntel-MediumItalic.ttf │ │ │ └── NeoSansIntel.ttf │ │ ├── droid-sans │ │ │ ├── DroidSans-Bold.ttf │ │ │ ├── DroidSans.ttf │ │ │ └── LICENSE.txt │ │ ├── font-awesome │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ └── fontawesome-webfont.woff │ │ └── glyphicons-halflings-regular.ttf │ ├── img │ │ ├── galileo_pin13_led_off.png │ │ ├── galileo_pin13_led_on.png │ │ ├── intel_logo.jpg │ │ ├── loading.gif │ │ ├── step_1_active.png │ │ ├── step_1_inactive.png │ │ ├── step_2_active.png │ │ ├── step_2_inactive.png │ │ ├── step_3_active.png │ │ ├── step_3_inactive.png │ │ ├── wifi_select_android.png │ │ ├── wifi_select_ios.png │ │ ├── wifi_select_mac.png │ │ └── wifi_select_pc.png │ └── js │ │ ├── angular-route.min.js │ │ ├── angular.min.js │ │ ├── app.js │ │ ├── jquery.easing.min.js │ │ ├── jquery.min.js │ │ ├── jquery.scombobox.min.js │ │ ├── missed.js │ │ └── underscore-min.js └── templates │ ├── connecting_to_router.html │ ├── controller.html │ ├── dashboard.html │ ├── empty.html │ ├── pin_button.html │ ├── pin_slider.html │ ├── set_hostname.html │ ├── set_root_password.html │ ├── steps_pics.html │ ├── test_pin.html │ └── wifi_setup.html ├── conf ├── README.md ├── default_appstate.conf ├── default_boardstate.conf ├── dnsd.conf ├── dynamic_wlan.conf ├── hostapd.conf ├── maker-node.service ├── reset-ap.service ├── static_wlan.conf ├── udhcpd.conf └── wifi.config ├── index.js ├── install_iot_libs.sh ├── iotkd_libs ├── busybox-i586 ├── hostapd ├── hostapd_cli ├── libnl.so.1 ├── rsync └── vim ├── lib ├── app.js ├── board_controller.js ├── conf.js ├── dashboard_controller.js ├── setup_controller.js └── utils │ ├── README.md │ ├── command_queue.js │ ├── galileo.js │ └── log.js ├── package.json ├── set_hostname.sh ├── sh ├── install_updates.sh ├── maker-node.sh ├── reset_AP_service.sh ├── reset_button_monitor.sh ├── restore_factory_settings.sh └── set_hostname.sh ├── startAP.sh ├── test ├── README.md ├── board_controller_test.js ├── conf_test.js ├── manual │ ├── cpu_test.js │ ├── cylon_test.js │ ├── gpio_test.js │ └── testCommandQueue.js ├── setup_controller_test.js └── test_boardstate.conf └── tools ├── README.md ├── plugin └── Prefixr │ ├── Default (OSX).sublime-keymap │ ├── Main.sublime-menu │ ├── Prefixr.py │ └── Prefixr.pyc ├── project_skeleton ├── README.md ├── app.js ├── client │ ├── index.html │ └── main.js └── package.json └── sh ├── mn_create.sh ├── mn_deploy.sh └── mn_run.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | todo.md 3 | test/coverage 4 | client/.sass-cache/* 5 | node_modules 6 | conf/boardstate.conf 7 | conf/appstate.conf 8 | client/docs 9 | coverage 10 | client/coverage 11 | npm-debug.log 12 | *.log 13 | **/reset.pid 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 IntelOpenDesign 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # README # 2 | 3 | A set of tools to wirelessly configure, develop, deploy and debug projects on Galileo Gen2 and Edison using standard text editors and web browsers. Makernode is designed for the Intel IOTDK to make it easy to get started with Javascript or Python development by suppriting developers who want to customize their existing toolsets - and want to have a completely wireless workflow. 4 | 5 | The files here contain a work-in-progress POC of wireless configuration with a dashboard manager. The binaries required to quickly convert the IOTDevkit build into a wirelessly configured build are provided in the repo. 6 | 7 | So far have tested primarily on OSX and Linux which have bonjour services preinstalled. For Windows please install [Bonjour for Windows](http://support.apple.com/kb/dl999). This enables zero config so you don't have to type in the IP address into your browser. 8 | 9 | We are planning to provide a build with the code from this repo included because the whole point of it is to simplify setup, but for now if you want to try it, download the IOTDK, please [see the wiki](https://github.com/IntelOpenDesign/MakerNode/wiki) for instructions of how to setup your Galileo, get the linux build, and connect to the web. The login and password defaults for the boards are "root" and "root". 10 | 11 | Once your galileo is connected to the web, go to the home directory on the console and: 12 | 13 | git config --global http.sslVerify false 14 | cd 15 | git clone https://github.com/IntelOpenDesign/MakerNode MakerNode 16 | cd MakerNode 17 | npm install 18 | 19 | This script will install the tools and configs you need: 20 | 21 | ./install_iot_libs.sh 22 | 23 | To put the board back into startup mode, call the following script inside the `sh/` folder. 24 | 25 | ./restore_factory_settings.sh 26 | 27 | The board will then restart in AP mode - at which point you can try our wifi configuration. To do this, select the wifi network Makernode-5char (5char will be replaced by the last 5 char of your Mac address, printed on a sticker on the top of your Ethernet port on the board). This is to distiguish it from other boards at hackathons. 28 | 29 | Then open a browser and type in any address. The dns should route you to a configuration page hosted on the device. If you don't see the webpage, try typing: `192.168.0.10` 30 | 31 | In the future you can simply press the "reset" button on the galileo board for 5 seconds. There is a service that will reset the board to factory settings and reboot back into access point mode. This takes about 1 minute. 32 | 33 | [Here is a video demo](https://vimeo.com/107971075) of the configuration from Oct 4 on vimeo. 34 | 35 | ### Issues: ### 36 | 37 | -Access point mode works well in most cases, during hackathons we have found that there are two many overlapping channels in the 2.4 ghz range. We are looking into using the 5 ghz bandwidth on the centrino cards. 38 | 39 | -The makernode utilitiy has not been optimized to lower CPU on the Galileo. We are working to reduce this and let you toggle it on and off. 40 | 41 | 42 | ### Who do I talk to? ### 43 | 44 | * seth.e.hunter@intel.com - developer and project manager 45 | * carlos.montesinos@intel.com - developer and project manager 46 | * adampasz@gmail.com - nodejs lead programmer 47 | * noura.howell@gmail.com - front end developer 48 | -------------------------------------------------------------------------------- /apps/dashboard/app.js: -------------------------------------------------------------------------------- 1 | doc = function() { 2 | /*! 3 | Usage: 4 | dashboard.js [--port=] 5 | */ 6 | } 7 | var docopt = require ('docopt-js-shim'); 8 | var args = docopt.fromComment(doc); 9 | var port = args['--port']; 10 | 11 | var utils = require('../../lib/utils/galileo')(); 12 | var path = require('path'); 13 | 14 | var servers = utils.create_servers(port ? port : 80, path.join(__dirname, 'client')); 15 | servers.socketio_server.on('connect', function(conn) { 16 | require('./dashboard_controller')(conn); 17 | }); 18 | 19 | -------------------------------------------------------------------------------- /apps/dashboard/client/css/dashboard.css: -------------------------------------------------------------------------------- 1 | .btn-group span { 2 | font-size: 24px; 3 | margin: 0 12px; 4 | float: right; 5 | } 6 | .btn-success:not(:first-child) { 7 | background-color: red; 8 | } 9 | .btn-off { 10 | margin-right: 10px; 11 | } 12 | .block { 13 | border: 1px solid #ccc; 14 | margin-bottom: 5px; 15 | border-radius: 5px; 16 | font-size: 80%; 17 | } 18 | .block .fa { 19 | color: #0860a8; 20 | /*Intel Blue*/ 21 | } 22 | .fa-info-circle { 23 | font-size: 78%; 24 | } 25 | .btn { 26 | margin-bottom: 5px; 27 | } 28 | -------------------------------------------------------------------------------- /apps/dashboard/client/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/favicon.ico -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-Italic.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-Light.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-LightItalic.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-Medium.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel-MediumItalic.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/NeoSansIntel/NeoSansIntel.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/droid-sans/DroidSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/droid-sans/DroidSans-Bold.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/droid-sans/DroidSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/droid-sans/DroidSans.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/font-awesome/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/font-awesome/FontAwesome.otf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/font-awesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/font-awesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/font-awesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/font-awesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/font-awesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/font-awesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /apps/dashboard/client/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/dashboard/client/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /apps/dashboard/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MakerNode 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |
21 |
22 |

MakerNode Dashboard

23 |
24 |
25 |
26 |
27 |

ACTIONS

28 |

29 |  PIN MONITOR 30 |  SET HOSTNAME 31 |  WIFI SETUP 32 |  CHANGE ROOT PASSWORD 33 | 34 | 35 | 36 | 37 | 38 |

39 |
40 |
41 |
42 |
43 | 44 |
45 |
46 |
47 |
48 |

SERVICES

49 |
50 |
51 |
52 |
53 |

SYSTEM STATUS

54 |

Online: 55 |

56 |

IP Address: 57 |

58 |

hostname: 59 |

60 |

mac address: 61 |

62 |

NodeJS version: 63 |

64 |

MRAA version: 65 |

66 |
67 |
68 |
69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /apps/dashboard/client/js/app.js: -------------------------------------------------------------------------------- 1 | var gDashboardTooltips = { 2 | 'avahi-daemon': "Networking system that allows discovery of your board via [hostname].local address. A.K.A. Bonjour", 3 | 'bluetooth': "Blutooth wireless services.", 4 | 'connman': "Network manager. Warning: stopping Connman may make your device inaccessible over the network.", 5 | 'lighttpd': "Web server used by IoT Dev Kit", 6 | 'maker-node': "Node JS server for setting up and managing your device.", 7 | 'redis': "Key-value store used by IoT Dev Kit", 8 | 'xdk-daemon': "Server used by IoT Dev Kit" 9 | }; 10 | 11 | var send_server_update; 12 | 13 | $(function() { 14 | var ws; 15 | ws = io(); 16 | ws.on('connect', function() { 17 | console.log('connected to websocket'); 18 | }); 19 | 20 | ws.on('dashboard-service', function(data) { 21 | if (data.action == 'list') { 22 | function getServiceClick(name, action) { 23 | return function() { 24 | send_server_update('dashboard-service', { 25 | name: name, 26 | action: action 27 | }); 28 | } 29 | } 30 | _.each(data.services, function(value, key) { 31 | var id = '#service-' + key; 32 | if ($('#services-block ' + id).length == 0) { 33 | var html = '

'; 34 | $('#services-block').append(html); 35 | html = '

'; 36 | html += '
' 37 | html += ''; 38 | // html += ''; //TODO: Implement fancier tooltips via plugin, and add on-click here..? 39 | html += key + '
'; 40 | html += '
'; 41 | html += '
'; 42 | html += ''; 43 | html += '
'; 44 | html += ''; 45 | html += '
'; 46 | $('#services-block ' + id).append(html); 47 | $(id + ' .btn-restart').click(getServiceClick(key, 'restart')); 48 | $(id + ' .btn-on').click(getServiceClick(key, 'start')); 49 | $(id + ' .btn-off').click(getServiceClick(key, 'stop')); 50 | 51 | } 52 | $(id + ' .btn-on').toggleClass('btn-success', value); 53 | $(id + ' .btn-off').toggleClass('btn-success', !value); 54 | }); 55 | } else { 56 | var element = '#service-' + data.id; 57 | $(element + ' button').prop('disabled', (data.status == 'begin')); 58 | $(element + ' .btn-on').toggleClass('btn-success', data.action == 'start'); 59 | $(element + ' .btn-off').toggleClass('btn-success', data.action == 'stop'); 60 | } 61 | }); 62 | 63 | //TODO: Modify this so we are not looking for hard-coded fields, and can display any dynamic status data from server. 64 | ws.on('dashboard-info', function(data) { 65 | console.log('got dashboard-info'); 66 | console.log(data); 67 | $('#node_version').text(data.node_version); 68 | $('#mraa_version').text(data.mraa_version); 69 | $('#ip_address').text(data.ip); 70 | $('#host_name').text(data.hostname); 71 | $('#mac_address').text(data.mac); 72 | $('#online').text(data.online ? 'yes' : 'no'); 73 | }); 74 | 75 | send_server_update = function(msg_type, d) { 76 | console.log('sending ' + msg_type); 77 | console.log(d); 78 | ws.emit(msg_type, d); 79 | }; 80 | 81 | function send_service_list_request() { 82 | var options = { 83 | action: 'list' 84 | }; 85 | console.log('sending service request:'); 86 | console.log(options); 87 | send_server_update('dashboard-service', options); 88 | setTimeout(send_service_list_request, 3000); 89 | } 90 | send_service_list_request(); 91 | send_server_update('dashboard-info'); 92 | 93 | $('.btn-toggle').click(function() { 94 | $(this).find('.btn').toggleClass('active'); 95 | 96 | if ($(this).find('.btn-primary').size() > 0) { 97 | $(this).find('.btn').toggleClass('btn-primary'); 98 | } 99 | if ($(this).find('.btn-danger').size() > 0) { 100 | $(this).find('.btn').toggleClass('btn-danger'); 101 | } 102 | if ($(this).find('.btn-success').size() > 0) { 103 | $(this).find('.btn').toggleClass('btn-success'); 104 | } 105 | if ($(this).find('.btn-info').size() > 0) { 106 | $(this).find('.btn').toggleClass('btn-info'); 107 | } 108 | $(this).find('.btn').toggleClass('btn-default'); 109 | }); 110 | 111 | }); 112 | -------------------------------------------------------------------------------- /apps/dashboard/dashboard_controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module dashboard_controller 3 | **/ 4 | 5 | "use strict"; 6 | var log = require('../../lib/utils/log')('dashboard_controller'); 7 | var utils = require('../../lib/utils/galileo')(); 8 | var mraa_version = 'unknown'; 9 | try { 10 | mraa_version = require("mraa").getVersion().substr(1); 11 | } catch (e) {}; 12 | 13 | var SERVICES = ['avahi-daemon', 'bluetooth', 'connman', 'lighttpd', 'maker-node', 'redis', 'xdk-daemon']; 14 | 15 | module.exports = function(conn) { 16 | function checkService(index, result) { 17 | if (!result) { 18 | result = { 19 | action: 'list', 20 | services: {} 21 | }; 22 | } 23 | if (index < SERVICES.length) { 24 | utils.is_service_active(SERVICES[index], function(b) { 25 | result.services[SERVICES[index]] = b; 26 | checkService(index + 1, result); 27 | }); 28 | } else { 29 | conn.emit('dashboard-service', result); 30 | } 31 | } 32 | 33 | function toggleService(name, action, callback) { 34 | 35 | conn.emit('dashboard-service', { 36 | id: name, 37 | action: action, 38 | status: 'begin' 39 | }); 40 | var f = (action == 'stop' ? utils.stop_service : utils.start_service); 41 | f(name, function() { 42 | conn.emit('dashboard-service', { 43 | id: name, 44 | action: action, 45 | status: 'end' 46 | }); 47 | callback ? callback() : null; 48 | }); 49 | 50 | } 51 | 52 | conn.on('dashboard-command', function(d) { 53 | log.debug('dashboard-command: ', d); 54 | switch (d.action) { 55 | case 'reboot': 56 | utils.reboot(); 57 | break; 58 | case 'install_updates': 59 | utils.install_updates(); 60 | break; 61 | case 'setup': 62 | utils.stop_supplicant(); 63 | break; 64 | } 65 | }); 66 | 67 | conn.on('dashboard-info', function(d) { 68 | var result = { 69 | node_version: process.versions.node, 70 | mraa_version: mraa_version 71 | }; 72 | utils.get_hostname(function(error, hostname) { 73 | result.hostname = hostname; 74 | utils.get_mac_address(function(mac) { 75 | result.mac = mac; 76 | utils.is_online(function(b) { 77 | result.online = b; 78 | utils.get_ip_address('wlp1s0', function(ip) { 79 | if (ip) { 80 | result.ip = ip + ' (wifi wlp1s0)'; 81 | conn.emit('dashboard-info', result); 82 | } else { 83 | utils.get_ip_address('enp0s20f6', function(ip2) { 84 | if (ip2) { 85 | result.ip = ip2 + ' (wired enp0s20f6)'; 86 | } 87 | conn.emit('dashboard-info', result); 88 | }); 89 | } 90 | }); 91 | }); 92 | }); 93 | }); 94 | }); 95 | 96 | conn.on('dashboard-service', function(d) { 97 | switch (d.action) { 98 | case 'list': 99 | checkService(0); 100 | break; 101 | case 'stop': 102 | case 'start': 103 | toggleService(d.name, d.action); 104 | break; 105 | case 'restart': 106 | toggleService(d.name, 'stop', function() { 107 | toggleService(d.name, 'start'); 108 | }); 109 | break; 110 | default: 111 | break; 112 | } 113 | }); 114 | return {}; 115 | } 116 | -------------------------------------------------------------------------------- /apps/hello_world/README.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | This is a simple "hello world" app. that demonstrates the major components of a MakerNode project (client, server and hardware). The app. allows you to toggle an LED on your board by sending commands from any web browser. 3 | 4 | # Running the App 5 | You should be connected to your board via serial cable or SSH. To start the server for your project, on your board, `cd` into this directory. Then, type: 6 | ```` 7 | node app.js 8 | ```` 9 | Open a web browser, and navigate to 10 | ```` 11 | http://[the_name_of_your_board].local:3000 12 | ```` 13 | (You may also use the IP address.) 14 | 15 | If everything is working correctly, you should see a simple web page, with 2 buttons for turning the 'pin 13' LED on and off on your board. 16 | 17 | Note that the app. is configured to run on HTTP port 3000, so need to add ':3000' to the URL. You may change the port in app.js: 18 | ```` 19 | var HTTP_PORT = 3000; 20 | ```` 21 | 22 | # Explanation of the Code 23 | ## Server 24 | The server code in 'app.js' is responsible for the following: 25 | 1. Create an Express HTTP server that will display the web page. 26 | 1. Create a Socket-IO server that listens for button click events emitted by the client. 27 | 1. Initialize the connection to the board, and write a 1 or 0 to the pin to toggle the LED. 28 | 29 | ## Client 30 | In 'client/index.html', you will see the HTML for a simple web page. There is also some inline JavaScript that initializes the socket on the client side, and emits messages to the server when the buttons are pressed. 31 | One key detail is the client-side Socket-IO library is generated "on-the-fly" when the Socket-IO server is running. Hence, you will not see a file in the file system at this location in the 'client/' directory: 32 | ```` 33 | 34 | ```` 35 | 36 | # Dependencies 37 | This app. has dependencies on 3 NPM modules -- [galielo-io](https://www.npmjs.org/package/galileo-io), [express](https://www.npmjs.org/package/express), and [socket-io](https://www.npmjs.org/package/socket.io). These should already have been installed for initial setup of your board. You might also choose to install them globally on your board since you will probably want them for future projects. 38 | ```` 39 | npm install -g galileo-io 40 | npm install -g socket-io 41 | npm install -g express 42 | ```` 43 | 44 | In 'app.js', there is also a relative path to include the utilities library for MakerNode: 45 | ```` 46 | var utils = require('../../lib/utils/galileo')(); 47 | ```` 48 | This library includes a number of useful commands to simplify setting up the server, and interacting with your board. You are encouraged to copy the files in 'lib/utils/' and use them for your own projects. 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /apps/hello_world/app.js: -------------------------------------------------------------------------------- 1 | //Import libraries 2 | var utils = require('../../lib/utils/galileo')(); 3 | var path = require('path'); 4 | var Galileo = require("galileo-io"); 5 | 6 | //Initialize gpio communication with board 7 | var board = new Galileo(); 8 | 9 | //The pin ID of the LED that will toggle 10 | var pin = 13; 11 | 12 | //The port for the server that will host the web page 13 | //Port number should appear in the URL, e.g.: http://clanton.local:3000 14 | var HTTP_PORT = 3000; 15 | 16 | //Create HTTP and SOCKET servers 17 | var servers = utils.create_servers(HTTP_PORT, path.join(__dirname, '/client')); 18 | console.log('HTTP and WS servers listening on port', HTTP_PORT); 19 | 20 | //Add event listener when a client connects to the socket server 21 | servers.socketio_server.on('connect', handleConnect); 22 | 23 | function handleConnect(conn) { 24 | console.log('client connected'); 25 | //Add event listeners for pin_on and pin_off messages from the client. 26 | conn.on('pin_on', handlePinOn); 27 | conn.on('pin_off', handlePinOff); 28 | } 29 | 30 | function handlePinOn() { 31 | console.log('toggle_13 on'); 32 | //turn the LED on 33 | board.digitalWrite(pin, 1); 34 | } 35 | 36 | function handlePinOff() { 37 | console.log('toggle_13 off'); 38 | //turn the LED off 39 | board.digitalWrite(pin, 0); 40 | } 41 | -------------------------------------------------------------------------------- /apps/hello_world/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MakerNode - Hello World 6 | 7 | 30 | 31 | 32 | 33 |

MakerNode - Hello World

34 |

Click a button to turn the test pin on or off.

35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /apps/maker_cat/client/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/favicon.ico -------------------------------------------------------------------------------- /apps/maker_cat/client/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/favicon.png -------------------------------------------------------------------------------- /apps/maker_cat/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Connect Anything 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 63 | 64 |
66 |
67 | waiting for connection 68 |
69 |
70 | 71 |
72 | 73 | 74 | -------------------------------------------------------------------------------- /apps/maker_cat/client/sass/app.scss: -------------------------------------------------------------------------------- 1 | $yellow: rgb(247, 193, 40); 2 | $bright_yellow: rgb(255, 238, 40); 3 | $dark_yellow: rgb(159, 122, 35); 4 | $green: rgb(45, 104, 84); 5 | $black: rgb(44, 38, 33); 6 | $gray: rgb(157, 160, 173); 7 | $chatbox_color: rgb(198, 188, 175); 8 | $intel_blue: rgb(30, 96, 181); 9 | $bright_blue: rgb(58, 158, 233); 10 | 11 | @mixin tap_feedback($color) { 12 | background-color: $color; 13 | box-shadow: 4px 4px 4px $gray; 14 | 15 | &:active { 16 | @if lightness($color) > 16 { 17 | background-color: darken($color, 10%); 18 | } @else { 19 | background-color: lighten($color, 10%); 20 | } 21 | box-shadow: 2px 2px 2px $gray; 22 | position: relative; 23 | top: 2px; 24 | left: 2px; 25 | } 26 | } 27 | 28 | @font-face { 29 | font-family: 'Neo Sans Intel'; 30 | font-weight: normal; 31 | font-style: normal; 32 | src: url('../fonts/NeoSansIntel/NeoSansIntel.ttf'); 33 | } 34 | 35 | @font-face { 36 | font-family: 'Droid Sans'; 37 | font-weight: normal; 38 | font-style: normal; 39 | src: url('../fonts/droid-sans/DroidSans.ttf'); 40 | } 41 | .intel-font { 42 | font-family: 'Neo Sans Intel'; 43 | } 44 | .droid-font { 45 | font-family: 'Droid Sans'; 46 | } 47 | .pin-name { 48 | font-family: 'Neo Sans Intel'; 49 | } 50 | .pin-label { 51 | font-family: 'Droid Sans'; 52 | } 53 | 54 | 55 | html, body { 56 | height: 100%; 57 | margin: 0; 58 | padding: 0; 59 | font-size: 42px; 60 | font-family: 'Droid Sans'; 61 | } 62 | 63 | h1 { 64 | font-size: 150%; 65 | line-height: 1.5em; 66 | } 67 | 68 | p { 69 | font-size: 95%; 70 | line-height: 1.2em; 71 | } 72 | 73 | .navbar { 74 | background: $intel_blue; 75 | color: white; 76 | } 77 | 78 | .hide { 79 | display: none; 80 | } 81 | 82 | .row.padded { 83 | padding-bottom: .5em; 84 | } 85 | 86 | #loading { 87 | background: rgb(255, 255, 255) url('../img/loading.gif') center center no-repeat; 88 | position: fixed; 89 | top: 0; 90 | left: 0; 91 | width: 100%; 92 | height: 100%; 93 | z-index: 50; 94 | } 95 | 96 | /* APP CONTAINER AND HEADER */ 97 | #app-container { 98 | position: relative; 99 | padding-bottom: 50px; 100 | } 101 | #header .navbar-header { 102 | width: 100%; 103 | } 104 | #header table { 105 | width: 100%; 106 | } 107 | 108 | /* SETUP FORM */ 109 | .setup-form h1 { 110 | color: $intel_blue; 111 | text-align: center; 112 | } 113 | .setup-form input { 114 | display: block; 115 | margin-left: auto; 116 | margin-right: auto; 117 | text-align: center; 118 | } 119 | .setup-form .button.submit { 120 | display: block; 121 | margin-left: auto; 122 | margin-right: auto; 123 | max-width: 375px; 124 | } 125 | @mixin step_inactive($n) { 126 | background-image: url('/static/img/step_' + $n + '_inactive.jpg'); 127 | background-position-x: center; 128 | background-position-y: center; 129 | background-repeat: no-repeat; 130 | background-size: cover; 131 | height: 375px; 132 | } 133 | @mixin step_active($n) { 134 | background-image: url('/static/img/step_' + $n + '_active.jpg'); 135 | box-shadow: 15px 15px 5px rgb(230, 230, 230); 136 | } 137 | div[steps-pics] .step-pic[data-step="1"] { 138 | @include step_inactive(1); 139 | } 140 | div[steps-pics] .step-pic[data-step="2"] { 141 | @include step_inactive(2); 142 | } 143 | div[steps-pics] .step-pic[data-step="3"] { 144 | @include step_inactive(3); 145 | } 146 | div[steps-pics][step="1"] .step-pic[data-step="1"] { 147 | @include step_active(1); 148 | } 149 | div[steps-pics][step="2"] .step-pic[data-step="2"] { 150 | @include step_active(2); 151 | } 152 | div[steps-pics][step="3"] .step-pic[data-step="3"] { 153 | @include step_active(3); 154 | } 155 | 156 | 157 | .pin-label { 158 | white-space: nowrap; 159 | text-overflow: ellipsis; 160 | overflow-x: hidden; 161 | cursor: default; 162 | } 163 | 164 | /* BUTTONS */ 165 | 166 | .button { 167 | min-height: 60px; 168 | margin: 20px; 169 | padding: 0; 170 | color: white; 171 | text-align: center; 172 | line-height: 60px; 173 | cursor: default; 174 | position: relative; 175 | @include tap_feedback($intel_blue); 176 | } 177 | .button.square { 178 | max-width: 60px; 179 | width: 100%; 180 | } 181 | .button.wide { 182 | max-width: 300px; 183 | width: 100%; 184 | } 185 | .button.danger { 186 | @include tap_feedback(rgb(189, 42, 42)); 187 | } 188 | .button.secondary { 189 | @include tap_feedback($gray); 190 | } 191 | 192 | /* CONTROL MODE */ 193 | 194 | // TODO colors 195 | // TODO real tap feedback for digital pin buttons 196 | 197 | $pin_button_h: 70px; 198 | $pin_slider_h: 70px; 199 | $pin_border_w: 15px; 200 | 201 | #control-mode div[pin-button], 202 | #control-mode div[pin-slider] { 203 | margin: 30px 5% 60px; 204 | height: $pin_button_h; 205 | box-sizing: border-box; 206 | } 207 | #control-mode div[pin-button] .pin-name, 208 | #control-mode div[pin-button] .pin-label { 209 | height: 100%; 210 | line-height: $pin_button_h; 211 | text-align: center; 212 | } 213 | #control-mode .pin.digital.sensor div[pin-button] .pin-name, 214 | #control-mode .pin.digital.sensor div[pin-button] .pin-label { 215 | line-height: $pin_button_h - (2 * $pin_border_w); 216 | } 217 | #control-mode div[pin-slider] .pin-name, 218 | #control-mode div[pin-slider] .pin-label { 219 | position: absolute; 220 | top: 0; 221 | left: 0; 222 | width: 100%; 223 | height: 100%; 224 | z-index: 5; 225 | text-align: center; 226 | } 227 | #control-mode .pin.analog.sensor div[pin-slider] .pin-name, 228 | #control-mode .pin.analog.sensor div[pin-slider] .pin-label { 229 | line-height: $pin_slider_h - (2 * $pin_border_w); 230 | } 231 | #control-mode .pin.analog.actuator div[pin-slider] .pin-name, 232 | #control-mode .pin.analog.actuator div[pin-slider] .pin-label { 233 | line-height: $pin_slider_h; 234 | } 235 | 236 | // digital sensors 237 | #control-mode .pin.sensor.digital .pin-box { 238 | border-width: $pin_border_w; 239 | border-color: $gray; 240 | border-style: solid; 241 | height: 100%; 242 | background-color: white; 243 | box-sizing: border-box; 244 | } 245 | #control-mode .pin.sensor.digital.pressed .pin-box { 246 | background-color: $bright_yellow; 247 | } 248 | 249 | // analog sensors 250 | #control-mode .pin.sensor.analog .pin-box { 251 | border-width: $pin_border_w; 252 | border-style: solid; 253 | border-color: $gray; 254 | height: $pin_slider_h; 255 | box-sizing: border-box; 256 | position: relative; 257 | } 258 | 259 | // digital actuators 260 | #control-mode .pin.digital.actuator .pin-box { 261 | height: 100%; 262 | @include tap_feedback($bright_blue); 263 | } 264 | #control-mode .pin.digital.actuator.pressed .pin-box { 265 | @include tap_feedback($bright_yellow); 266 | } 267 | 268 | // analog actuators 269 | #control-mode .pin.analog.actuator div[pin-slider] { 270 | position: relative; 271 | } 272 | #control-mode .pin.analog.actuator .pin-box { 273 | position: relative; 274 | top: 0; 275 | height: $pin_slider_h; 276 | background-color: $bright_blue; 277 | } 278 | 279 | 280 | 281 | 282 | #control-mode .pin-value-container { 283 | width: 100%; 284 | height: 100%; 285 | top: 0; 286 | left: 0; 287 | background: transparent; 288 | position: absolute; 289 | z-index: 0; 290 | } 291 | #control-mode .pin-value { 292 | position: absolute; 293 | left: 0; 294 | bottom: 0; 295 | background: $bright_yellow; 296 | z-index: 0; 297 | border-width: 0; 298 | height: 100%; 299 | } 300 | 301 | $pin_slider_thumb_w: 35px; 302 | #control-mode .pin-slider-container { 303 | width: 100%; 304 | height: 100%; 305 | position: absolute; 306 | top: 0; 307 | left: -$pin_slider_thumb_w; 308 | padding: 0 $pin_slider_thumb_w; 309 | box-sizing: content-box; 310 | } 311 | #control-mode .pin-slider-container input[type=range] { 312 | z-index: 4; 313 | position: absolute; 314 | top: 0; 315 | left: 0; 316 | -webkit-appearance: none; 317 | background: transparent; 318 | height: 100%; 319 | width: 100%; 320 | } 321 | #control-mode .pin-slider-container input[type=range]:focus { 322 | box-shadow: 0 0 0 transparent; 323 | outline: 0 none; 324 | } 325 | #control-mode .pin-slider-container input[type=range]::-webkit-slider-thumb { 326 | -webkit-appearance: none; 327 | display: block; 328 | background: transparent; 329 | width: 0; 330 | height: 0; 331 | border-left: 35px solid transparent; 332 | border-right: 35px solid transparent; 333 | border-bottom: 56px solid white; 334 | -webkit-background-clip: content-box; 335 | position: relative; 336 | top: 50px; 337 | } 338 | #control-mode .pin-slider-container input[type=range]::-webkit-slider-thumb:before { 339 | width: 0; 340 | height: 0; 341 | display: block; 342 | content: "\A"; 343 | border-left: 30px solid transparent; 344 | border-right: 30px solid transparent; 345 | border-bottom: 50px solid $bright_blue; 346 | position: absolute; 347 | top: 3px; 348 | left: -30px; 349 | box-shadow: 0 8px 4px -4px $gray; 350 | } 351 | 352 | /* SMALL DEVICES */ 353 | @media (max-device-width: 4in) { 354 | 355 | } 356 | 357 | @media (max-device-width: 4in) and (min-resolution: 100dpi) { 358 | 359 | html, body { 360 | font-size: 60px; 361 | } 362 | .button { 363 | min-height: 100px; 364 | margin: 10px; 365 | line-height: 100px; 366 | } 367 | .button.square { 368 | max-width: 100px; 369 | width: 100%; 370 | } 371 | .button.wide { 372 | max-width: 500px; 373 | } 374 | 375 | } 376 | -------------------------------------------------------------------------------- /apps/maker_cat/client/static/css/play_mode.css: -------------------------------------------------------------------------------- 1 | /* clean up CSS. now that I am using different templates for pins in the add pins menu and pins in the play mode, I don't think I need this separate CSS file at all. */ 2 | 3 | #play-pins { 4 | padding-top: 50px; 5 | padding-bottom: 100px; 6 | } 7 | #play-pins .pin { 8 | display: inline-block; 9 | width: 94%; 10 | border-width: 15px; 11 | border-color: transparent; 12 | margin-left: 3% !important; 13 | margin-right: 3% !important; 14 | margin-top: 25px; 15 | margin-bottom: 0; 16 | box-sizing: border-box; 17 | height: inherit; 18 | } 19 | #play-pins .pin-box { 20 | height: 145px; 21 | width: 100%; 22 | display: inline-block; 23 | background-color: rgb(135, 135, 135); 24 | } 25 | 26 | #play-pins .pin.pressed { 27 | border-color: rgb(180, 206, 184); 28 | } 29 | #play-pins .pin.pressed .pin-box { 30 | background-color: rgb(45, 104, 84); 31 | } 32 | #play-pins .pin.pressed .pin-box:before { 33 | display: none; 34 | } 35 | #play-pins .pin .pin-box:active { 36 | background-color: rgb(83, 83, 83); 37 | border-color: transparent; 38 | } 39 | #play-pins .pin.pressed .pin-box:active { 40 | background-color: rgb(45, 84, 64); 41 | } 42 | 43 | #play-pins .pin-label, 44 | #play-pins .pin-name { 45 | color: white; 46 | 47 | font-size: 100%; 48 | font-weight: normal; 49 | height: 140px; 50 | line-height: 140px; 51 | top: 0; 52 | left: 0; 53 | width: 100%; 54 | text-align: center; 55 | } 56 | -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-Italic.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-Light.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-LightItalic.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-Medium.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel-MediumItalic.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/NeoSansIntel/NeoSansIntel.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/droid-sans/DroidSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/droid-sans/DroidSans-Bold.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/droid-sans/DroidSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/droid-sans/DroidSans.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /apps/maker_cat/client/static/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/img/loading.gif -------------------------------------------------------------------------------- /apps/maker_cat/client/static/img/loading_inverted.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/img/loading_inverted.gif -------------------------------------------------------------------------------- /apps/maker_cat/client/static/img/loading_old.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/apps/maker_cat/client/static/img/loading_old.gif -------------------------------------------------------------------------------- /apps/maker_cat/client/static/js/angular-route.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.9 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(h,e,A){'use strict';function u(w,q,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,n){function y(){l&&(l.$destroy(),l=null);g&&(k.leave(g),g=null)}function v(){var b=w.current&&w.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),f=w.current;g=n(b,function(d){k.enter(d,null,g||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||q()});y()});l=f.scope=b;l.$emit("$viewContentLoaded");l.$eval(h)}else y()}var l,g,t=b.autoscroll,h=b.onload||""; 7 | a.$on("$routeChangeSuccess",v);v()}}}function z(e,h,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var n=e(c.contents());b.controller&&(f.$scope=a,f=h(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));n(a)}}}h=e.module("ngRoute",["ng"]).provider("$route",function(){function h(a,c){return e.extend(new (e.extend(function(){},{prototype:a})),c)}function q(a, 8 | e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},h=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;h.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&q(a,c));if(a){var b="/"==a[a.length-1]?a.substr(0, 9 | a.length-1):a+"/";k[b]=e.extend({redirectTo:a},q(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,n,q,v,l){function g(){var d=t(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!x)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)x=!1,a.$broadcast("$routeChangeStart",d,m), 10 | (r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(u(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?n.get(d):n.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=l.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl= 11 | b,c=q.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function t(){var a,b;e.forEach(k,function(f,k){var p;if(p=!b){var s=c.path();p=f.keys;var l={};if(f.regexp)if(s=f.regexp.exec(s)){for(var g=1,q=s.length;g 2 |
3 |
4 |
5 |
6 | 7 | add/remove sensors 8 | 9 | 10 | add/remove actuators 11 | 12 |
13 | 14 |
15 |
17 | × 18 |
19 |
20 |
21 | 22 |
23 |
27 |
28 |
32 |
33 |
34 | 35 |
36 |
37 | 38 |
39 | 40 |
41 |
42 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/app_settings.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
6 | 7 |
8 |
9 |
10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 | App Settings 18 |
19 |
20 |
21 |
23 | × 24 |
25 |
26 |
27 |
28 |
29 |
31 | Reset 32 |
33 |
34 |
35 |

Remove all pins and connections, restore all pin settings to defaults.

36 |
37 |
38 |
39 |
40 |
42 | Change Network Name 43 |
44 |
45 |
46 |

Change the name of the wifi network ConnectAnything uses.

47 |

48 |
49 |
50 |
51 |
53 | OK 54 |
55 |
56 |
57 |
58 |
59 | 60 |
61 | 62 |
63 |
64 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/connect.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
8 | 9 |
10 |
11 |
12 | 13 |
15 |
16 | 17 |
18 |
20 | sensors 21 |
22 |
23 |
24 | 25 |
26 |
28 | actuators 29 |
30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
44 | 45 | 46 | 47 | 48 | 49 |
50 |
51 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/pin.html: -------------------------------------------------------------------------------- 1 |
19 |
20 |
21 | {{pin.label}} 22 |
23 |
24 | {{pin.name}} 25 |
26 |
27 |
31 |
32 |
33 |
35 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/pin_button.html: -------------------------------------------------------------------------------- 1 |
5 |
7 |
9 | {{pin.label}} 10 |
11 |
13 | {{pin.name}} 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/pin_settings.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/pin_settings_directive.html: -------------------------------------------------------------------------------- 1 |
10 |
11 |
12 | 13 |
14 |
15 | {{pin.name}} 16 |
17 |
18 | 19 |
20 |
21 | Name: 22 |
23 |
24 |
25 |
26 | 33 |
34 |
35 |
36 |
37 | 38 | ({{label_limit_length}} char max) 39 | 40 |
41 |
42 |
43 |
44 | 45 |
46 |
47 | Type: 48 |
49 |
50 | {{pin.type}} 51 |
52 |
53 | 54 |
55 |
56 | 57 | 58 |
61 |
63 | 71 |
72 |
73 |
76 |
77 |
80 |
81 |
84 |
85 |
89 |
90 |
94 |
95 |
98 |
99 |
102 |
103 | 104 | 105 |
107 | 110 | 111 |
112 |
113 |
115 | 123 |
124 |
125 |
126 |
127 |
128 |
129 | 130 | 131 | Value:  132 | 133 | {{scaled_value()}}% 134 |
135 |
136 |
137 | 140 | 141 |
142 | 143 | 151 | 155 |
156 |
157 | 160 | 161 |
162 |
163 |
164 | 165 |
166 |
167 |
169 | Remove 170 |
171 |
172 |
173 |
175 | OK 176 |
177 |
178 |
179 | 180 |
181 |
182 |
183 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/pin_slider.html: -------------------------------------------------------------------------------- 1 |
5 |
6 |
7 |
9 | {{pin.label}} 10 |
11 |
13 | {{pin.name}} 14 |
15 | 16 |
18 |
19 |
20 |
21 | 22 |
23 | 30 |
31 |
32 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/pin_stub.html: -------------------------------------------------------------------------------- 1 |
11 |
13 |
14 | {{pin.label}} 15 |
16 |
17 | {{pin.name}} 18 |
19 |
20 |
23 |
24 |
25 |
26 |
27 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/play.html: -------------------------------------------------------------------------------- 1 |
3 |
5 |
6 | actuators with no connections 7 |
8 |
9 |
10 |
13 | 14 |
17 |
18 |
20 |
21 |
22 |
23 |
24 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/remove_pin_dialog.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

Are you sure you want to remove pin {{pin.name}} and all its connections?

7 |
8 |
9 |
10 |
11 |
13 | No 14 |
15 |
16 |
17 |
19 | Yes 20 |
21 |
22 |
23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/reset_dialog.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 |

Are you sure you want to reset all pins and connections?

8 |
9 |
10 |
11 |
12 |
14 | No 15 |
16 |
17 |
18 |
20 | Yes 21 |
22 |
23 |
24 |
25 |
26 |
27 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/ssid_changed.html: -------------------------------------------------------------------------------- 1 |
3 |
4 |
5 |
6 |

The name of the wifi network is being changed to

7 | {{s.ssid}} 8 |

For the changes to go into effect, please unplug the Galileo, plug it back in, and wait a few minutes. When you see the new wifi network {{s.ssid}}, please connect to it and hit this button:

9 |

11 | Home 12 |
13 |
14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /apps/maker_cat/client/templates/ssid_dialog.html: -------------------------------------------------------------------------------- 1 |
2 |
4 |
5 |
6 |
7 |

Enter a new wifi network name, press submit, wait a few minutes, then connect to new network.

8 |
9 |
10 |
11 |
12 | 15 |
16 |
17 |
18 |
19 |
21 | Cancel 22 |
23 |
24 |
25 |
27 | Submit 28 |
29 |
30 |
31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /apps/maker_cat/default_boardstate.conf: -------------------------------------------------------------------------------- 1 | {"pins":{"0":{"label":"","is_analog":false,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":false,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"1":{"label":"","is_analog":false,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":false,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"2":{"label":"ADAM111","is_analog":false,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"3":{"label":"TREE RED","is_analog":true,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"4":{"label":"","is_analog":false,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":false,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"5":{"label":"TREE GREEN","is_analog":true,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"6":{"label":"TREE BLUE","is_analog":true,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"7":{"label":"","is_analog":false,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":false,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"8":{"label":"","is_analog":false,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":false,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"9":{"label":"THEREMIN","is_analog":true,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"10":{"label":"","is_analog":true,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":false,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"11":{"label":"","is_analog":true,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":false,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"12":{"label":"BUBBLES","is_analog":false,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"13":{"label":"","is_analog":false,"is_input":false,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":false,"value":0,"is_timer_on":false,"timer_value":0,"damping":0},"14":{"label":"1 BRIGHT","is_analog":true,"is_input":true,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0.29931173264048994,"is_timer_on":false,"timer_value":0,"damping":0},"15":{"label":"2 RED","is_analog":true,"is_input":true,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0.1345119304023683,"is_timer_on":false,"timer_value":0,"damping":0},"16":{"label":"2 GREEN","is_analog":true,"is_input":true,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0.870145900407806,"is_timer_on":false,"timer_value":0,"damping":0},"17":{"label":"2 BLUE","is_analog":true,"is_input":true,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0.7994520112406462,"is_timer_on":false,"timer_value":0,"damping":0},"18":{"label":"3 BRIGHT","is_analog":true,"is_input":true,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0.4925047110300511,"is_timer_on":false,"timer_value":0,"damping":0},"19":{"label":"4 BRIGHT","is_analog":true,"is_input":true,"input_min":0,"input_max":1,"is_inverted":false,"is_visible":true,"value":0.803674541413784,"is_timer_on":false,"timer_value":0,"damping":0}},"connections":[{"source":"17","target":"6","connect":true},{"source":"18","target":"9","connect":true},{"source":"19","target":"12","connect":true}],"count":31,"message_ids_processed":["7-1402021914295-1402022077282"]} -------------------------------------------------------------------------------- /apps/maker_cat/index.js: -------------------------------------------------------------------------------- 1 | doc = function() { 2 | /*! 3 | Usage: 4 | index.js [--port=] 5 | */ 6 | } 7 | var docopt = require ('docopt-js-shim'); 8 | var args = docopt.fromComment(doc); 9 | var port = args['--port']; 10 | 11 | var app = require('./lib/app')(); 12 | app.start(port ? port : 80); 13 | 14 | -------------------------------------------------------------------------------- /apps/maker_cat/lib/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function App() {} 4 | var log = require('../../../lib/utils/log')('App'); 5 | var conf = require('./conf'); 6 | var boardConf = conf.create(); 7 | var gpio = require('./gpio')(); 8 | var http = require('./http')(); 9 | var socket = require('./socket').create(); 10 | var sh = require('../../../lib/utils/command_queue')().enqueue; 11 | 12 | var BOARD_CONF_FILE = 'boardstate.conf'; 13 | var APP_CONF_FILE = 'appstate.conf'; 14 | var HTTP_PORT; 15 | 16 | App.prototype.start = start; 17 | module.exports = function() { 18 | return new App(); 19 | } 20 | 21 | function start(port) { 22 | HTTP_PORT = port; 23 | log.info('Starting MakerCAT...'); 24 | 25 | gpio.init(onInput).then( 26 | onBoardReady, 27 | function(reason) { 28 | log.error('could not init gpio: ' + reason); 29 | } 30 | ); 31 | 32 | function onBoardReady(board) { 33 | boardConf.read(BOARD_CONF_FILE) 34 | .then( 35 | function(pinState) { 36 | log.debug('Pin state loaded.', pinState); 37 | socket.create(function() { 38 | var model = socket.getMessage(); 39 | gpio.refreshOutputs(model); 40 | boardConf.write(BOARD_CONF_FILE, JSON.stringify(model)); //TODO: throttle writes 41 | }); 42 | if (typeof pinState === 'undefined') { 43 | //TODO: initiate setup flow? 44 | } else { 45 | socket.setMessage(pinState); 46 | } 47 | http.listen(HTTP_PORT); 48 | log.info('CAT is ready.'); 49 | 50 | }, 51 | function(reason) { 52 | log.error('read error: ' + reason); 53 | } 54 | ); 55 | } 56 | 57 | function onInput(pinIndex, value) { 58 | var boardState = socket.getMessage(); 59 | boardState.pins[pinIndex].value = value / 1024; 60 | gpio.refreshOutputs(boardState); 61 | } 62 | } 63 | 64 | function stop() { 65 | http.close(); 66 | } 67 | -------------------------------------------------------------------------------- /apps/maker_cat/lib/conf.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var fs = require('q-io/fs'); 3 | var log = require('../../../lib/utils/log')('Conf'); 4 | 5 | function Conf() { 6 | log.info('New Conf'); 7 | } 8 | 9 | function create() { 10 | return new Conf(); 11 | } 12 | 13 | function read(path) { 14 | log.info('Reading: ' + path); 15 | return fs.read(path).then(JSON.parse, 16 | function(reason) { 17 | log.error('Could not read file. ' + reason); 18 | } 19 | ); 20 | } 21 | 22 | function write(path, content) { 23 | log.info('Writing to: ' + path); 24 | 25 | return fs.write(path, content) 26 | .then( 27 | function() { 28 | log.info('Write successful.'); 29 | }, 30 | function(reason) { 31 | log.error('Write failed: ' + reason); 32 | } 33 | ); 34 | } 35 | 36 | Conf.prototype.read = read; 37 | Conf.prototype.write = write; 38 | module.exports = Conf; 39 | module.exports.create = create; 40 | -------------------------------------------------------------------------------- /apps/maker_cat/lib/gpio.js: -------------------------------------------------------------------------------- 1 | var log = require('../../../lib/utils/log')('GPIO'); 2 | var Galileo = require("galileo-io"); 3 | var Q = require('q'); 4 | var _ = require('underscore'); 5 | var board; 6 | var OUTPUT_SCALE = 255; 7 | 8 | function GPIO() {} 9 | 10 | GPIO.prototype.init = init; 11 | GPIO.prototype.refreshOutputs = refreshOutputs; 12 | 13 | module.exports = function(){ 14 | return new GPIO(); 15 | } 16 | 17 | function init(onInput) { 18 | log.debug('init gpio'); 19 | var deferred = Q.defer(); 20 | board = new Galileo(); 21 | board.on("ready", function() { 22 | log.info("BOARD READY"); 23 | var byte = 0; 24 | this.pinMode(9, this.MODES.OUTPUT); 25 | board.analogRead('A0', function(data) { 26 | onInput(14, data); 27 | }); 28 | board.analogRead('A1', function(data) { 29 | onInput(15, data); 30 | }); 31 | board.analogRead('A2', function(data) { 32 | onInput(16, data); 33 | }); 34 | board.analogRead('A3', function(data) { 35 | onInput(17, data); 36 | }); 37 | board.analogRead('A4', function(data) { 38 | onInput(18, data); 39 | }); 40 | board.analogRead('A5', function(data) { 41 | onInput(19, data); 42 | }); 43 | //TODO: Figure out why bind wasn't working here. :/ 44 | deferred.resolve(board); 45 | }); 46 | board.on('error', function(reason) { 47 | deferred.reject(reason); 48 | }); 49 | return deferred.promise; 50 | } 51 | 52 | var cachedPinValues = []; 53 | 54 | function refreshOutputs(model) { 55 | _.each(model.connections, 56 | function(connection) { 57 | var source = connection.source; 58 | var target = connection.target; 59 | //console.log(source + "->" + target + " value=" + model.pins[target].value ); 60 | model.pins[target].value = model.pins[source].value; 61 | } 62 | //TODO: AND values for multiple inputs 63 | ); 64 | 65 | var i = 0; 66 | _.each(model.pins, 67 | function(pin) { 68 | var scaledValue; 69 | if (pin.is_analog) { 70 | scaledValue = Math.round(pin.value * OUTPUT_SCALE) 71 | } else { 72 | //TODO: No, need to read min/max from input pin 73 | var threshold = pin.input_min + (pin.input_max - pin.input_min) / 2; 74 | scaledValue = pin.value < threshold ? 0 : OUTPUT_SCALE; 75 | } 76 | if (pin.is_inverted) { 77 | scaledValue = 255 - scaledValue; 78 | } 79 | if (!pin.is_input && cachedPinValues[i] != scaledValue) { 80 | log.debug("Changed pin=" + i + " oldValue=" + cachedPinValues[i] + " newValue=" + scaledValue); 81 | write(pin, i, scaledValue); 82 | } 83 | cachedPinValues[i] = scaledValue; 84 | i++; 85 | } 86 | ); 87 | } 88 | 89 | function write(pin, pinIndex, scaledValue) { 90 | pin.is_analog ? board.analogWrite(pinIndex, scaledValue) : board.digitalWrite(pinIndex, scaledValue); 91 | 92 | } 93 | -------------------------------------------------------------------------------- /apps/maker_cat/lib/http.js: -------------------------------------------------------------------------------- 1 | var log = require('../../../lib/utils/log')('HTTP'); 2 | var httpServer = require("http-server"); 3 | var server; 4 | 5 | function http() { 6 | server = httpServer.createServer({ 7 | root: 'client', 8 | cache: -1, 9 | showDir: true, 10 | }); 11 | }; 12 | 13 | module.exports = function() { 14 | return new http; 15 | } 16 | 17 | http.prototype.listen = function(port) { 18 | log.info('HTTP Server listening on port ' + port); 19 | server.listen(port); 20 | } 21 | 22 | http.prototype.close = function() { 23 | server.close(); 24 | } 25 | 26 | //TODO: I don't like that http-server is synchronous, so we should swap it out with the connect or express modules. 27 | -------------------------------------------------------------------------------- /apps/maker_cat/lib/socket.js: -------------------------------------------------------------------------------- 1 | var _ = require('underscore'); 2 | var log = require('../../../lib/utils/log')('Socket'); 3 | var WebSocketServer = require('ws').Server; 4 | var exec = require('child_process').exec; 5 | 6 | var onUpdate; 7 | var msg; 8 | 9 | function Socket(){ 10 | //TODO: Move initialization here... 11 | msg = { 12 | status: 'OK', // TODO test client side with "error" status 13 | pins: {}, 14 | connections: [], 15 | count: 0, // TODO remove when done debugging 16 | message_ids_processed: [], 17 | ssid: 'ConnectAnything', 18 | }; 19 | _.each(digital_outs, pin_setter(false, false)); 20 | _.each(digital_ins, pin_setter(false, true)); 21 | _.each(analog_outs, pin_setter(true, false)); 22 | _.each(analog_ins, pin_setter(true, true)); 23 | } 24 | 25 | Socket.prototype.create = create; 26 | Socket.prototype.getMessage = getMessage; 27 | Socket.prototype.setMessage = setMessage; 28 | 29 | module.exports = Socket; 30 | module.exports.create = function(){ 31 | return new Socket(); 32 | } 33 | 34 | // pin defaults 35 | var digital_outs = ['1', '2', '3', '4', '7', '8', '12', '13']; 36 | var digital_ins = ['0']; 37 | var analog_outs = ['3', '5', '6', '9', '10', '11']; 38 | var analog_ins = ['14', '15', '16', '17', '18', '19']; // A0 - A5 39 | 40 | var all_pins = [].concat(digital_outs).concat(digital_ins).concat(analog_outs).concat(analog_ins); 41 | 42 | function setMessage(state) { 43 | msg = state; 44 | } 45 | 46 | function getMessage() { 47 | return msg; 48 | } 49 | 50 | var messages_dict = {}; 51 | 52 | var N_CLIENTS = 0; 53 | 54 | var change_ssid_message_id = null; 55 | 56 | function pin_setter(is_analog, is_input) { 57 | return function(id) { 58 | msg.pins[id] = { 59 | label: '', 60 | value: 0, 61 | is_visible: Math.random() > 0.5 ? true : false, 62 | //is_visible: true, 63 | is_analog: is_analog, 64 | is_input: is_input, 65 | input_min: 0.0, 66 | input_max: 1.0, 67 | damping: 0, 68 | is_inverted: false, 69 | is_timer_on: false, 70 | timer_value: 0, 71 | }; 72 | } 73 | } 74 | 75 | var broadcast_interval_id = 0; 76 | 77 | var onConnect = function(conn) { 78 | 79 | N_CLIENTS += 1; 80 | log.info('new connection, N_CLIENTS', N_CLIENTS); 81 | if (!broadcast_interval_id) { 82 | broadcast_interval_id = setInterval(function() { 83 | msg.count += 1; 84 | msg.message_ids_processed = _.keys(messages_dict); 85 | try { 86 | conn.send(JSON.stringify(msg)); 87 | } catch (error) { 88 | log.info(error); 89 | //TODO: do we need to recover here? 90 | } 91 | //log.info('sent message: ' + JSON.stringify(msg)); 92 | _.each(_.keys(messages_dict), function(id) { 93 | messages_dict[id] += 1; 94 | }); 95 | var message_ids_to_delete = _.filter(_.keys(messages_dict), 96 | function(id) { 97 | return messages_dict[id] >= N_CLIENTS * 2; 98 | }); 99 | _.each(message_ids_to_delete, function(id) { 100 | delete messages_dict[id]; 101 | if (id === change_ssid_message_id) { 102 | clearInterval(broadcast_interval_id); 103 | log.info('clearing broadcast interval'); 104 | } 105 | }); 106 | }, 33); //TODO: Figure out the optimal value here 107 | } 108 | 109 | conn.on('message', function(str) { 110 | log.info('received ' + str); 111 | setTimeout(function() { 112 | //log.info('processing ' + str); 113 | var d = JSON.parse(str); 114 | _.each(d.connections, function(dc) { 115 | var index = -1; 116 | _.each(msg.connections, function(mc, i) { 117 | if (mc.source === dc.source && mc.target === dc.target) { 118 | index = i; 119 | } 120 | }); 121 | // if client wants to add connection && we don't already have it 122 | if (dc.connect && index < 0) { 123 | msg.connections.push({ 124 | source: dc.source, 125 | target: dc.target 126 | }); 127 | // if client wants to remove connection && we have it 128 | } else if (!dc.connect && index >= 0) { 129 | msg.connections.splice(index, 1); 130 | } 131 | }); 132 | _.each(d.pins, function(pin, id) { 133 | msg.pins[id].value = pin.value; 134 | msg.pins[id].label = pin.label; 135 | msg.pins[id].is_visible = pin.is_visible; 136 | msg.pins[id].is_analog = pin.is_analog; 137 | msg.pins[id].is_input = pin.is_input; 138 | msg.pins[id].is_inverted = pin.is_inverted; 139 | msg.pins[id].input_min = pin.input_min; 140 | msg.pins[id].input_max = pin.input_max; 141 | msg.pins[id].damping = pin.damping; 142 | msg.pins[id].is_timer_on = pin.is_timer_on; 143 | msg.pins[id].timer_value = pin.timer_value; 144 | }); 145 | log.info('processing message ID', d.message_id); 146 | messages_dict[d.message_id] = 0; 147 | if (_.has(d, 'ssid') && d.ssid !== msg.ssid) { 148 | // a user has changed the SSID. we should notify all other 149 | // users and then stop broadcasting, to mimic the users having 150 | // to reconnect to another wifi hotspot 151 | msg.ssid = d.ssid; 152 | var change_ssid_message_id = d.message_id; 153 | } 154 | onUpdate(); 155 | }, 0); 156 | }); 157 | 158 | conn.on('close', function(code, reason) { 159 | clearInterval(broadcast_interval_id); 160 | broadcast_interval_id = 0; 161 | try { 162 | log.info('close - try'); 163 | } catch (e) { 164 | log.info('close - catch'); 165 | } finally { 166 | log.info('close - finally'); 167 | } 168 | }); 169 | conn.on('end', function() { 170 | try { 171 | log.info('end - try'); 172 | } catch (e) { 173 | log.info('end - catch'); 174 | } finally { 175 | log.info('end - finally'); 176 | } 177 | }); 178 | conn.on('error', function() { 179 | log.info('error'); 180 | }); 181 | } 182 | 183 | function create(callback) { 184 | onUpdate = callback; 185 | 186 | var port = 8001; 187 | log.info('WebSockets Serving listening on port ' + port); 188 | wss = new WebSocketServer({ 189 | port: port, 190 | }); 191 | wss.on('connection', onConnect); 192 | //for testing random data 193 | //setInterval(update, 6000); 194 | } 195 | 196 | -------------------------------------------------------------------------------- /apps/maker_cat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cat.js", 3 | "preferGlobal": false, 4 | "version": "0.0.1", 5 | "author": "adampasz ", 6 | "description": "NodeJS backend for Intel Connect Anything", 7 | "contributors": [ 8 | {} 9 | ], 10 | "main": "./index", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/IntelOpenDesign/ConnectAnyThing.git" 14 | }, 15 | "keywords": [ 16 | "intel", 17 | "galileo", 18 | "arduino" 19 | ], 20 | "dependencies": { 21 | "cli-color": "0.3.2", 22 | "galileo-io": "^0.4.0", 23 | "http-server": "0.6.1", 24 | "q": "1.0.1", 25 | "q-io": "1.11.1", 26 | "underscore": "1.6.0", 27 | "ws": "0.4.31", 28 | "nodejs-websocket": "~1.0.0", 29 | "docopt-js-shim": "git+https://github.com/adampasz/docopt-js-shim.git" 30 | }, 31 | "licenses": { 32 | "type": "UNLICENSE", 33 | "url": "https://github.com/IntelOpenDesign/ConnectAnyThing/blob/master/LICENSE" 34 | }, 35 | "engines": { 36 | "node": ">=0.8.18" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /apps/maker_cat/test-server.js: -------------------------------------------------------------------------------- 1 | 2 | var _und = require('underscore'); 3 | var ws = require('nodejs-websocket'); 4 | 5 | // initialize msg with pin defaults 6 | var digital_outs = ['1', '2', '3', '4', '7', '8', '12', '13']; 7 | var digital_ins = ['0']; 8 | var analog_outs = ['3', '5', '6', '9', '10', '11']; 9 | var analog_ins = ['14', '15', '16', '17', '18', '19']; // A0 - A5 10 | 11 | var all_pins = [].concat(digital_outs).concat(digital_ins).concat(analog_outs).concat(analog_ins); 12 | 13 | var msg = { 14 | status: 'OK', // TODO test client side with "error" status 15 | pins: {}, 16 | connections: [], 17 | count: 0, // TODO remove when done debugging 18 | message_ids_processed: [], 19 | ssid: 'ConnectAnything', 20 | }; 21 | 22 | var messages_dict = {}; 23 | 24 | var N_CLIENTS = 0; 25 | 26 | var change_ssid_message_id = null; 27 | 28 | function pin_setter(is_analog, is_input) { 29 | return function(id) { 30 | msg.pins[id] = { 31 | label: '', 32 | value: 0, 33 | is_visible: Math.random() > 0.5 ? true : false, 34 | //is_visible: true, 35 | is_analog: is_analog, 36 | is_input: is_input, 37 | is_servo: false, 38 | input_min: 0.0, 39 | input_max: 1.0, 40 | damping: 0, 41 | is_inverted: false, 42 | is_timer_on: false, 43 | timer_value: 0, 44 | }; 45 | } 46 | } 47 | 48 | _und.each(digital_outs, pin_setter(false, false)); 49 | _und.each(digital_ins, pin_setter(false, true)); 50 | _und.each(analog_outs, pin_setter(true, false)); 51 | _und.each(analog_ins, pin_setter(true, true)); 52 | 53 | // initialize a few random connections between visible pins 54 | function get_pin_ids_if(f) { 55 | var oids = _und.map(msg.pins, function(pin, id) { 56 | return _und.extend({id: id}, pin); 57 | }); 58 | var pins = _und.filter(oids, function(pin) { 59 | return f(pin); 60 | }); 61 | return _und.pluck(pins, 'id'); 62 | } 63 | var visible_sensors = get_pin_ids_if(function(pin) { 64 | return pin.is_input && pin.is_visible; 65 | }); 66 | var visible_actuators = get_pin_ids_if(function(pin) { 67 | return !pin.is_input && pin.is_visible; 68 | }); 69 | visible_actuators = _und.shuffle(visible_actuators); 70 | var n_connections = 3; 71 | n_connections = Math.min(n_connections, visible_sensors.length); 72 | n_connections = Math.min(n_connections, visible_actuators.length); 73 | for (var i = 0; i < n_connections; i++) { 74 | msg.connections.push({source: visible_sensors[i], target: visible_actuators[i]}); 75 | } 76 | 77 | // change state randomly to simulate other users and hardware 78 | function update() { 79 | _und.each(all_pins, function(id) { 80 | if (!msg.pins[id].is_input) 81 | return; 82 | if (msg.pins[id].is_analog) { 83 | msg.pins[id].value = Math.random(); 84 | } else { 85 | msg.pins[id].value = Math.random() < 0.5 ? 0 : 1; 86 | } 87 | }); 88 | } 89 | 90 | setInterval(update, 6000); 91 | 92 | var server = ws.createServer(function(conn){ 93 | 94 | N_CLIENTS += 1; 95 | console.log('new connection, N_CLIENTS', N_CLIENTS); 96 | 97 | var broadcast_interval_id = setInterval(function() { 98 | msg.count += 1; 99 | msg.message_ids_processed = _und.keys(messages_dict); 100 | conn.sendText(JSON.stringify(msg)); 101 | 102 | _und.each(_und.keys(messages_dict), function(id) { 103 | messages_dict[id] += 1; 104 | }); 105 | var message_ids_to_delete = _und.filter(_und.keys(messages_dict), 106 | function(id) { return messages_dict[id] >= N_CLIENTS * 2; }); 107 | _und.each(message_ids_to_delete, function(id) { 108 | delete messages_dict[id]; 109 | if (id === change_ssid_message_id) { 110 | clearInterval(broadcast_interval_id); 111 | console.log('clearing broadcast interval'); 112 | } 113 | }); 114 | }, 500); 115 | 116 | conn.on('text', function(str) { 117 | console.log('received ' + str); 118 | setTimeout(function() { 119 | //console.log('processing ' + str); 120 | var d = JSON.parse(str); 121 | _und.each(d.connections, function(dc) { 122 | var index = -1; 123 | _und.each(msg.connections, function(mc, i) { 124 | if (mc.source === dc.source && mc.target === dc.target) { 125 | index = i; 126 | } 127 | }); 128 | // if client wants to add connection && we don't already have it 129 | if (dc.connect && index < 0) { 130 | msg.connections.push({ 131 | source: dc.source, 132 | target: dc.target 133 | }); 134 | // if client wants to remove connection && we have it 135 | } else if (!dc.connect && index >= 0) { 136 | msg.connections.splice(index, 1); 137 | } 138 | }); 139 | // TODO do this dynamically for all attributes? (make sure not to 140 | // send over "type" attribute that client side makes up) 141 | _und.each(d.pins, function(pin, id) { 142 | msg.pins[id].value = pin.value; 143 | msg.pins[id].label = pin.label; 144 | msg.pins[id].is_visible = pin.is_visible; 145 | msg.pins[id].is_analog = pin.is_analog; 146 | msg.pins[id].is_input = pin.is_input; 147 | msg.pins[id].is_servo = pin.is_servo; 148 | msg.pins[id].is_inverted = pin.is_inverted; 149 | msg.pins[id].input_min = pin.input_min; 150 | msg.pins[id].input_max = pin.input_max; 151 | msg.pins[id].damping = pin.damping; 152 | msg.pins[id].is_timer_on = pin.is_timer_on; 153 | msg.pins[id].timer_value = pin.timer_value; 154 | }); 155 | console.log('processing message ID', d.message_id); 156 | messages_dict[d.message_id] = 0; 157 | if (_und.has(d, 'ssid') && d.ssid !== msg.ssid) { 158 | // a user has changed the SSID. we should notify all other 159 | // users and then stop broadcasting, to mimic the users having 160 | // to reconnect to another wifi hotspot 161 | msg.ssid = d.ssid; 162 | var change_ssid_message_id = d.message_id; 163 | } 164 | }, 0); 165 | }); 166 | 167 | conn.on('close', function(code, reason) { 168 | try { 169 | console.log('close - try'); 170 | } catch(e) { 171 | console.log('close - catch'); 172 | } finally { 173 | console.log('close - finally'); 174 | } 175 | }); 176 | conn.on('end', function() { 177 | try { 178 | console.log('end - try'); 179 | } catch(e) { 180 | console.log('end - catch'); 181 | } finally { 182 | console.log('end - finally'); 183 | } 184 | }); 185 | conn.on('error', function(e) { 186 | console.log(e); 187 | }); 188 | }).listen(8001); 189 | 190 | // https://www.npmjs.org/package/nodejs-websocket 191 | -------------------------------------------------------------------------------- /client/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/favicon.ico -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MakerNode 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 44 | 45 | 52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /client/static/css/jquery.scombobox.min.css: -------------------------------------------------------------------------------- 1 | .scombobox{margin:5px;position:relative}.scombobox-display{-moz-box-sizing:border-box;border:1px solid #CCC;border-radius:4px;box-sizing:border-box;height:100%;padding:2px 4px;width:100%}.scombobox-display:focus{box-shadow:0 0 3px #CCC;outline:none}.scombobox-display:disabled{background:#F0F0F0}.scombobox-display.scombobox-invalid{background:#FFCCD4}.scombobox-display-div{border:1px solid #CCC;border-radius:4px;cursor:pointer}.scombobox-display-div-holder{padding:2px}.scombobox-display-div-item{background:#F8F8F8;border:1px solid #CCC;border-radius:4px;cursor:default;display:none;float:left;height:100%;margin:2px;max-width:150px;overflow:hidden;padding:4px 18px 4px 8px;position:relative;vertical-align:middle;white-space:nowrap}.scombobox-display-div-item-text{max-width:140px;overflow:hidden}.scombobox-display-div-item-remove{background:#A0A0A0;border-radius:100px;color:#FFF;cursor:pointer;line-height:90%;padding:1px 3px 0;position:absolute;right:2px;top:2px}.scombobox-display-div-item-remove:hover{background:#408CBE}.scombobox-display-div-item-remove:active{background:#3075A3}.scombobox-list{-moz-box-sizing:border-box;background:#FFF;border:1px solid #CCC;border-radius:4px;border-top:none;box-shadow:0 0 3px #CCC;box-sizing:border-box;display:none;max-height:400px;max-width:300%;min-width:100%;overflow-y:auto;position:absolute;white-space:nowrap;z-index:10}.scombobox-list p{cursor:pointer;margin:0;padding:5px}.scombobox-list p input[type=checkbox]{margin-right:8px;vertical-align: middle;}.scombobox-list p:hover,.scombobox-list p.scombobox-hovered{background-color:#E9EFFC}.scombobox-list p.scombobox-separator{background:#EEE;cursor:default;height:2px;padding:0}.scombobox-list p.scombobox-header{background:#EEE;cursor:default}.scombobox-dropdown-arrow{background:url(data:image/png;base64,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) center no-repeat;cursor:pointer;filter:alpha(opacity=85);height:100%;opacity:0.85;position:absolute;right:0;top:0;width:20px;z-index:1}.scombobox-dropdown-arrow:hover{filter:alpha(opacity=100);opacity:1}.scombobox-dropdown-arrow-up{background:url(data:image/png;base64,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) center no-repeat}.scombobox-dropdown-background{-moz-box-sizing:border-box;background:#FFF;border:1px solid #CCC;border-left:none;border-radius:0 4px 4px 0;box-sizing:border-box;height:100%;position:absolute;right:0;top:0;width:20px}.scombobox-dropdown-background-invalid{border-left:1px solid #CCC}.scombobox-marker{background:#958FFF;border-radius:2px;color:#FFF;margin:0 2px;padding:0 2px}.scombobox input[type=checkbox]{cursor:pointer}.scombobox-disabled .scombobox-display-div{background:#F8F8F8;cursor:default}.scombobox select,.scombobox-disabled .scombobox-dropdown-background,.scombobox-disabled .scombobox-dropdown-arrow{display:none} -------------------------------------------------------------------------------- /client/static/fonts/NeoSansIntel/NeoSansIntel-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/NeoSansIntel/NeoSansIntel-Italic.ttf -------------------------------------------------------------------------------- /client/static/fonts/NeoSansIntel/NeoSansIntel-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/NeoSansIntel/NeoSansIntel-Light.ttf -------------------------------------------------------------------------------- /client/static/fonts/NeoSansIntel/NeoSansIntel-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/NeoSansIntel/NeoSansIntel-LightItalic.ttf -------------------------------------------------------------------------------- /client/static/fonts/NeoSansIntel/NeoSansIntel-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/NeoSansIntel/NeoSansIntel-Medium.ttf -------------------------------------------------------------------------------- /client/static/fonts/NeoSansIntel/NeoSansIntel-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/NeoSansIntel/NeoSansIntel-MediumItalic.ttf -------------------------------------------------------------------------------- /client/static/fonts/NeoSansIntel/NeoSansIntel.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/NeoSansIntel/NeoSansIntel.ttf -------------------------------------------------------------------------------- /client/static/fonts/droid-sans/DroidSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/droid-sans/DroidSans-Bold.ttf -------------------------------------------------------------------------------- /client/static/fonts/droid-sans/DroidSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/droid-sans/DroidSans.ttf -------------------------------------------------------------------------------- /client/static/fonts/font-awesome/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/font-awesome/FontAwesome.otf -------------------------------------------------------------------------------- /client/static/fonts/font-awesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/font-awesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /client/static/fonts/font-awesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/font-awesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /client/static/fonts/font-awesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/font-awesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /client/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /client/static/img/galileo_pin13_led_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/galileo_pin13_led_off.png -------------------------------------------------------------------------------- /client/static/img/galileo_pin13_led_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/galileo_pin13_led_on.png -------------------------------------------------------------------------------- /client/static/img/intel_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/intel_logo.jpg -------------------------------------------------------------------------------- /client/static/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/loading.gif -------------------------------------------------------------------------------- /client/static/img/step_1_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/step_1_active.png -------------------------------------------------------------------------------- /client/static/img/step_1_inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/step_1_inactive.png -------------------------------------------------------------------------------- /client/static/img/step_2_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/step_2_active.png -------------------------------------------------------------------------------- /client/static/img/step_2_inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/step_2_inactive.png -------------------------------------------------------------------------------- /client/static/img/step_3_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/step_3_active.png -------------------------------------------------------------------------------- /client/static/img/step_3_inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/step_3_inactive.png -------------------------------------------------------------------------------- /client/static/img/wifi_select_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/wifi_select_android.png -------------------------------------------------------------------------------- /client/static/img/wifi_select_ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/wifi_select_ios.png -------------------------------------------------------------------------------- /client/static/img/wifi_select_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/wifi_select_mac.png -------------------------------------------------------------------------------- /client/static/img/wifi_select_pc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/client/static/img/wifi_select_pc.png -------------------------------------------------------------------------------- /client/static/js/angular-route.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.9 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(h,e,A){'use strict';function u(w,q,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,n){function y(){l&&(l.$destroy(),l=null);g&&(k.leave(g),g=null)}function v(){var b=w.current&&w.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),f=w.current;g=n(b,function(d){k.enter(d,null,g||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||q()});y()});l=f.scope=b;l.$emit("$viewContentLoaded");l.$eval(h)}else y()}var l,g,t=b.autoscroll,h=b.onload||""; 7 | a.$on("$routeChangeSuccess",v);v()}}}function z(e,h,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var n=e(c.contents());b.controller&&(f.$scope=a,f=h(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));n(a)}}}h=e.module("ngRoute",["ng"]).provider("$route",function(){function h(a,c){return e.extend(new (e.extend(function(){},{prototype:a})),c)}function q(a, 8 | e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},h=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;h.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&q(a,c));if(a){var b="/"==a[a.length-1]?a.substr(0, 9 | a.length-1):a+"/";k[b]=e.extend({redirectTo:a},q(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,n,q,v,l){function g(){var d=t(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!x)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)x=!1,a.$broadcast("$routeChangeStart",d,m), 10 | (r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(u(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?n.get(d):n.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=l.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl= 11 | b,c=q.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function t(){var a,b;e.forEach(k,function(f,k){var p;if(p=!b){var s=c.path();p=f.keys;var l={};if(f.regexp)if(s=f.regexp.exec(s)){for(var g=1,q=s.length;g>> 0; 24 | 25 | if (len === 0) { 26 | return -1; 27 | } 28 | var n = 0; 29 | if (arguments.length > 1) { 30 | n = Number(arguments[1]); 31 | if (n != n) { // shortcut for verifying if it's NaN 32 | n = 0; 33 | } else if (n != 0 && n != Infinity && n != -Infinity) { 34 | n = (n > 0 || -1) * Math.floor(Math.abs(n)); 35 | } 36 | } 37 | if (n >= len) { 38 | return -1; 39 | } 40 | var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); 41 | for (; k < len; k++) { 42 | if (k in t && t[k] === searchElement) { 43 | return k; 44 | } 45 | } 46 | return -1; 47 | } 48 | } 49 | if (!Object.keys) { 50 | Object.keys = (function () { 51 | 'use strict'; 52 | var hasOwnProperty = Object.prototype.hasOwnProperty, 53 | hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), 54 | dontEnums = [ 55 | 'toString', 56 | 'toLocaleString', 57 | 'valueOf', 58 | 'hasOwnProperty', 59 | 'isPrototypeOf', 60 | 'propertyIsEnumerable', 61 | 'constructor' 62 | ], 63 | dontEnumsLength = dontEnums.length; 64 | 65 | return function (obj) { 66 | if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { 67 | throw new TypeError('Object.keys called on non-object'); 68 | } 69 | 70 | var result = [], prop, i; 71 | 72 | for (prop in obj) { 73 | if (hasOwnProperty.call(obj, prop)) { 74 | result.push(prop); 75 | } 76 | } 77 | 78 | if (hasDontEnumBug) { 79 | for (i = 0; i < dontEnumsLength; i++) { 80 | if (hasOwnProperty.call(obj, dontEnums[i])) { 81 | result.push(dontEnums[i]); 82 | } 83 | } 84 | } 85 | return result; 86 | }; 87 | }()); 88 | } -------------------------------------------------------------------------------- /client/templates/connecting_to_router.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |

Please rejoin the network now!

10 |
11 |
12 | 13 |
14 |
15 |

Your Galileo is rebooting and attempting to join your wifi network. This will take approximately 1 minute.

16 |
17 |
18 | 19 |
20 |
21 |

This page will redirect you when everything is ready.

22 |
23 |
24 |
25 |
26 |

If you have trouble connecting, you may need to install Bonjour Network Services on this computer.

27 |
28 |
29 | 30 | 31 |
32 | -------------------------------------------------------------------------------- /client/templates/controller.html: -------------------------------------------------------------------------------- 1 |
3 | 4 |
5 |
6 |

Galileo Controller

7 |
8 |
9 | 10 |
11 |
12 |

Monitor input pins and control output pins

13 |
14 |
15 | 16 | 17 |
18 |
19 |

Inputs

20 |
21 |
22 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | 38 |
39 |
40 |

Outputs

41 |
42 |
44 |
52 |
54 |
55 |
57 |
58 |
59 |
60 |
61 | 62 |
63 | -------------------------------------------------------------------------------- /client/templates/dashboard.html: -------------------------------------------------------------------------------- 1 | 37 | 63 |
64 | 65 |
66 |
67 |

MakerNode Dashboard

68 |
69 |
70 | 71 | 72 | 73 |
74 |
75 |

ACTIONS

76 |

77 |  PIN MONITOR 78 |  SET HOSTNAME 79 |  WIFI SETUP 80 |  CHANGE ROOT PASSWORD 81 | 82 | 83 | 84 | 85 | 86 |

87 |
88 |
89 |
90 |
91 | 92 |
93 |
94 |
95 |
96 |

SERVICES

97 |
98 |
99 |
100 |
101 |

SYSTEM STATUS

102 |

Online: 103 |

104 |

IP Address: 105 |

106 |

hostname: 107 |

108 |

mac address: 109 |

110 |

NodeJS version: 111 |

112 |

MRAA version: 113 |

114 |
115 |
116 |
117 | -------------------------------------------------------------------------------- /client/templates/empty.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | -------------------------------------------------------------------------------- /client/templates/pin_button.html: -------------------------------------------------------------------------------- 1 |
2 | {{pin.name}} 3 |
4 |
5 |
7 |
8 |
ON
9 |
10 |
11 |
OFF
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /client/templates/pin_slider.html: -------------------------------------------------------------------------------- 1 |
2 | {{pin.name}} 3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
14 | 21 |
22 |
23 | -------------------------------------------------------------------------------- /client/templates/set_hostname.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 |

Name Your Galileo

8 |
9 |
10 | 11 |
12 |
13 |

This is the "hostname" that you will use to connect to Galileo on your wifi network later, so remember this name.

14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 |
22 | 23 |
24 | 25 |
26 |
27 | -------------------------------------------------------------------------------- /client/templates/set_root_password.html: -------------------------------------------------------------------------------- 1 | 6 |
7 |
8 |
9 |

Set Password

10 |
11 |
12 |
13 |
14 |

This is the password for the root user on your Galileo. You probably will not need this until you move on to more advanced usage of your Galileo, so choose something you can remember for a long time.

15 |
16 |
17 | 18 |
19 |
20 | 21 | 22 | 23 |
24 |

Fields do not match!

25 | 26 |
27 | 28 |
29 | 30 |
31 |
32 | -------------------------------------------------------------------------------- /client/templates/steps_pics.html: -------------------------------------------------------------------------------- 1 |
2 |
 
3 |
5 | 9 |
10 |
11 | -------------------------------------------------------------------------------- /client/templates/test_pin.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 |

Connected to Your Network!

7 |
8 |
9 |
10 |
11 | Next Steps   >> 12 |
13 |
14 |
15 |
16 |

17 | Your Galileo is connected via a nodejs websocket to the button below. Use 18 | it to confirm the device is properly configured. 19 |

20 |
21 |
22 |
23 |
24 |
25 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 47 |
48 |
49 | 50 |
51 |
52 | 53 |
54 | -------------------------------------------------------------------------------- /client/templates/wifi_setup.html: -------------------------------------------------------------------------------- 1 | 31 |
32 | 33 |
34 | 35 |
36 |
37 |

Connect Galileo to Wifi

38 |
39 |
40 | 41 |
42 |
43 |

This will let Galileo connect to your home wifi network. Then you can connect with Galileo and use the internet simultaneously.

44 |
45 |
46 |
47 |  SCANNING WIFI NETWORKS... 48 |
49 |
50 |
51 |
52 | 53 |
54 |
55 |
56 |
57 | 58 | 59 |
60 |

Fields do not match!

61 |

Leave blank if you have an unsecured network. 62 |

63 |
64 |
65 | 66 |
67 |
68 |
69 | -------------------------------------------------------------------------------- /conf/README.md: -------------------------------------------------------------------------------- 1 | ## wifi.config 2 | Wifi configurations for Galileo2, IoT image. 3 | Copy this file to: 4 | /var/lib/connman/wifi.config 5 | -------------------------------------------------------------------------------- /conf/default_appstate.conf: -------------------------------------------------------------------------------- 1 | { 2 | "mode":"setup", 3 | "setup_state": { 4 | "set_hostname":false, 5 | "set_root_password":false, 6 | "ssid":"", 7 | "pwd":"", 8 | "router_gateway_ip":"", 9 | "galileo_static_ip":"" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /conf/default_boardstate.conf: -------------------------------------------------------------------------------- 1 | { 2 | "pins": { 3 | "2": { 4 | "is_analog": false, 5 | "is_input": false, 6 | "value": 0 7 | }, 8 | "3": { 9 | "is_analog": true, 10 | "is_input": false, 11 | "value": 0 12 | }, 13 | "4": { 14 | "is_analog": false, 15 | "is_input": false, 16 | "value": 0 17 | }, 18 | "5": { 19 | "is_analog": true, 20 | "is_input": false, 21 | "value": 0 22 | }, 23 | "6": { 24 | "is_analog": true, 25 | "is_input": false, 26 | "value": 0 27 | }, 28 | "7": { 29 | "is_analog": false, 30 | "is_input": false, 31 | "value": 0 32 | }, 33 | "8": { 34 | "is_analog": false, 35 | "is_input": false, 36 | "value": 0 37 | }, 38 | "9": { 39 | "is_analog": true, 40 | "is_input": false, 41 | "value": 0 42 | }, 43 | "10": { 44 | "is_analog": true, 45 | "is_input": false, 46 | "value": 0 47 | }, 48 | "11": { 49 | "is_analog": true, 50 | "is_input": false, 51 | "value": 0 52 | }, 53 | "12": { 54 | "is_analog": false, 55 | "is_input": false, 56 | "value": 0 57 | }, 58 | "13": { 59 | "is_analog": false, 60 | "is_input": false, 61 | "value": 0 62 | }, 63 | "14": { 64 | "is_analog": true, 65 | "is_input": true, 66 | "value": 0.29931173264048994 67 | }, 68 | "15": { 69 | "is_analog": true, 70 | "is_input": true, 71 | "value": 0.1345119304023683 72 | }, 73 | "16": { 74 | "is_analog": true, 75 | "is_input": true, 76 | "value": 0.870145900407806 77 | }, 78 | "17": { 79 | "is_analog": true, 80 | "is_input": true, 81 | "value": 0.7994520112406462 82 | }, 83 | "18": { 84 | "is_analog": true, 85 | "is_input": true, 86 | "value": 0.4925047110300511 87 | }, 88 | "19": { 89 | "is_analog": true, 90 | "is_input": true, 91 | "value": 0.803674541413784 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /conf/dnsd.conf: -------------------------------------------------------------------------------- 1 | cat 192.168.0.10 2 | cat.com 192.168.0.10 3 | google.com 192.168.0.10 4 | bing.com 192.168.0.10 5 | * 192.168.0.10 6 | 7 | -------------------------------------------------------------------------------- /conf/dynamic_wlan.conf: -------------------------------------------------------------------------------- 1 | # /etc/network/interfaces -- configuration file for ifup(8), ifdown(8) 2 | 3 | # The loopback interface 4 | auto lo 5 | iface lo inet loopback 6 | 7 | # Wireless interfaces 8 | auto wlan0 9 | iface wlan0 inet dhcp 10 | wireless_mode managed 11 | wireless_essid any 12 | wpa-driver wext 13 | wpa-conf /etc/wpa_supplicant.conf 14 | 15 | iface atml0 inet dhcp 16 | 17 | # Wired or wireless interfaces 18 | auto eth0 19 | iface eth0 inet dhcp 20 | iface eth1 inet dhcp 21 | 22 | # Ethernet/RNDIS gadget (g_ether) 23 | # ... or on host side, usbnet and random hwaddr 24 | iface usb0 inet static 25 | address 192.168.7.2 26 | netmask 255.255.255.0 27 | network 192.168.7.0 28 | gateway 192.168.7.1 29 | 30 | # Bluetooth networking 31 | iface bnep0 inet dhcp 32 | -------------------------------------------------------------------------------- /conf/hostapd.conf: -------------------------------------------------------------------------------- 1 | interface=wlp1s0 2 | driver=nl80211 3 | ssid=MakerNode 4 | 5 | channel=1 6 | hw_mode=g 7 | 8 | wmm_enabled=0 9 | 10 | -------------------------------------------------------------------------------- /conf/maker-node.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Maker-Node setup and control server 3 | After=connman.service 4 | 5 | [Service] 6 | Type=simple 7 | WorkingDirectory=/home/root/MakerNode/ 8 | ExecStart=/bin/sh sh/maker-node.sh start 9 | ExecStop=/bin/sh sh/maker-node.sh stop 10 | ExecReload=/bin/sh sh/maker-node.sh restart 11 | StandardOutput=tty 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | 16 | -------------------------------------------------------------------------------- /conf/reset-ap.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Button-Monitor-for-AP-Reset 3 | After=maker-node.service 4 | 5 | [Service] 6 | Type=simple 7 | WorkingDirectory=/home/root/MakerNode/ 8 | ExecStart=/bin/sh sh/reset_AP_service.sh start 9 | ExecStop=/bin/sh sh/reset_AP_service.sh stop 10 | ExecReload=/bin/sh sh/reset_AP_service.sh restart 11 | StandardOutput=tty 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /conf/static_wlan.conf: -------------------------------------------------------------------------------- 1 | # /etc/network/interfaces -- configuration file for ifup(8), ifdown(8) 2 | 3 | # The loopback interface 4 | auto lo 5 | iface lo inet loopback 6 | 7 | # Wireless interfaces 8 | auto wlan0 9 | iface wlan0 inet static 10 | wpa-driver wext 11 | wpa-conf /etc/wpa_supplicant.conf 12 | # REPLACE FOLLOWING LINES WITH YOUR ROUTERS INFO... 13 | # address 10.0.1.49 14 | # gateway 10.0.1.1 15 | netmask 255.255.255.0 16 | 17 | iface atml0 inet dhcp 18 | 19 | # Wired or wireless interfaces 20 | auto eth0 21 | iface eth0 inet dhcp 22 | iface eth1 inet dhcp 23 | 24 | # Ethernet/RNDIS gadget (g_ether) 25 | # ... or on host side, usbnet and random hwaddr 26 | iface usb0 inet static 27 | address 192.168.7.2 28 | netmask 255.255.255.0 29 | network 192.168.7.0 30 | gateway 192.168.7.1 31 | 32 | # Bluetooth networking 33 | iface bnep0 inet dhcp 34 | -------------------------------------------------------------------------------- /conf/udhcpd.conf: -------------------------------------------------------------------------------- 1 | start 192.168.0.10 2 | end 192.168.0.255 3 | static_lease 0C:D2:92:58:E5:A3 192.168.0.10 # LYT 4 | static_lease 0C:D2:92:59:24:AA 192.168.0.11 # board 1 5 | static_lease 0C:D2:92:59:0D:9E 192.168.0.12 # board 2 6 | static_lease 0C:D2:92:59:17:53 192.168.0.13 # board 3 7 | static_lease 84:A6:C8:D2:B3:BF 192.168.0.14 # Debug computer 8 | 9 | 10 | interface wlp1s0 11 | 12 | opt dns 192.168.0.10 13 | option dns 192.168.0.10 14 | 15 | #option domain-name-server 192.168.0.19 16 | 17 | #option broadcast-address 192.168.0.255 18 | 19 | opt router 192.168.0.10 20 | option subnet 255.255.255.0 21 | 22 | -------------------------------------------------------------------------------- /conf/wifi.config: -------------------------------------------------------------------------------- 1 | [service_****] 2 | Type = wifi 3 | Security = wpa2 4 | Name = ***** 5 | Passphrase = ****** 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | doc = function() { 2 | /*! 3 | Usage: 4 | index.js [--port=] 5 | */ 6 | } 7 | var docopt = require ('docopt-js-shim'); 8 | var args = docopt.fromComment(doc); 9 | var port = args['--port']; 10 | 11 | var app = require('./lib/app')(); 12 | app.start(port ? port : 80); 13 | -------------------------------------------------------------------------------- /install_iot_libs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Tools 4 | echo "installing hostapd, libnl 1.1, rsync, vim, and busybox-i586 binaries" 5 | pushd iotkd_libs/ 6 | cp libnl.so.1 /usr/lib 7 | cp hostapd /usr/bin 8 | cp hostapd_cli /usr/bin 9 | cp busybox-i586 /usr/bin 10 | cp rsync /usr/bin 11 | cp vim /usr/local/bin 12 | popd 13 | 14 | # Access point configuration 15 | echo "Configuring device to act as wifi access point." 16 | cp conf/hostapd.conf /etc 17 | cp conf/udhcpd.conf /etc 18 | cp conf/dnsd.conf /etc 19 | cp conf/maker-node.service /etc/systemd/system/multi-user.target.wants 20 | cp conf/reset-ap.service /etc/systemd/system/multi-user.target.wants 21 | 22 | #Ensure shell scripts can be run 23 | chmod u+x sh/* 24 | -------------------------------------------------------------------------------- /iotkd_libs/busybox-i586: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/iotkd_libs/busybox-i586 -------------------------------------------------------------------------------- /iotkd_libs/hostapd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/iotkd_libs/hostapd -------------------------------------------------------------------------------- /iotkd_libs/hostapd_cli: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/iotkd_libs/hostapd_cli -------------------------------------------------------------------------------- /iotkd_libs/libnl.so.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/iotkd_libs/libnl.so.1 -------------------------------------------------------------------------------- /iotkd_libs/rsync: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/iotkd_libs/rsync -------------------------------------------------------------------------------- /iotkd_libs/vim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/iotkd_libs/vim -------------------------------------------------------------------------------- /lib/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module app 3 | **/ 4 | "use strict"; 5 | 6 | function app() { 7 | var APP_CONF_FILE = 'conf/appstate.conf'; 8 | var BOARD_CONF_FILE = 'conf/boardstate.conf'; 9 | var server_port; 10 | var PING_PORT = 8000; // for the hacky http server that just responds with 'Hello...' 11 | 12 | var path = require('path'); 13 | var http = require('http'); 14 | var sh = require('./utils/command_queue')(); 15 | var log = require('./utils/log')('app') 16 | var conf = require('./conf')(); 17 | var setupCtrlF = require('./setup_controller'); 18 | var boardCtrlF = require('./board_controller'); 19 | var DashboardController = require('./dashboard_controller'); 20 | var utils = require('./utils/galileo')(); 21 | 22 | var servers; 23 | var app_state; 24 | var setupCtrl; 25 | var boardCtrl; 26 | 27 | /** 28 | * Start the application 29 | * @method start 30 | * @param {} port for the static file server and the websocket server 31 | * @return void 32 | */ 33 | var start = function(port) { 34 | server_port = port; 35 | log.info('Starting MakerNode...'); 36 | conf.read(APP_CONF_FILE).then(function(o) { 37 | app_state = o; 38 | utils.get_ip_address('enp0s20f6', function(wired_ip) { 39 | if (wired_ip) { 40 | app_state.mode = 'control'; 41 | } 42 | utils.get_ip_address('enp0s20f6', function(wired_ip) { 43 | if (wired_ip) { 44 | app_state.mode = 'control'; 45 | } 46 | utils.stop_service('lighttpd', function() { 47 | servers = utils.create_servers(server_port, path.join(__dirname, '../client')); 48 | log.info('HTTP and WS servers listening on port', server_port); 49 | if (app_state.mode === 'setup') { 50 | utils.list_wifi_networks(function() { //we need to run this to cache the list before connman goes down 51 | utils.start_access_point(launch_setup_ctrl); 52 | }); 53 | } else { 54 | launch_board_ctrl(function() { // callback for when board controller is ready 55 | // TODO only call this when needed 56 | // only host this http server for when the client side is 57 | // trying to ping the server side to see if it can redirect 58 | // so we only need to do this when we boot up immediately after 59 | // finishing setup, not every time we launch board controller 60 | log.debug('Setting up ping HTTP server'); 61 | http.createServer(function(req, res) { 62 | res.writeHead(200, { 63 | 'Content-Type': 'text/plain', 64 | 'Access-Control-Allow-Origin': '*', 65 | }); 66 | res.end('Hello from your friendly hacky Galileo webserver'); 67 | }).listen(PING_PORT); 68 | log.info('Ping HTTP server is listening on port', PING_PORT); 69 | }); 70 | } 71 | 72 | servers.socketio_server.on('connect', function(conn) { 73 | log.debug('client connected'); 74 | DashboardController(conn); //TODO: figure out what to do about abandoned connections 75 | conn.on('mode', function() { 76 | log.debug('client is asking what mode we are in:', app_state.mode); 77 | conn.emit('mode', app_state.mode); 78 | }); 79 | conn.on('networks', function() { 80 | utils.list_wifi_networks(function(available_wifi_networks) { 81 | if (!available_wifi_networks || !available_wifi_networks.length) { 82 | log.error("No networks were found!"); 83 | } 84 | conn.emit('networks', available_wifi_networks); 85 | }); 86 | }); 87 | conn.on('reset', function() { 88 | log.info('client has requested a server reset'); 89 | sh('./restore_factory_settings.sh'); 90 | sh('reboot'); 91 | }); 92 | 93 | conn.on('set_root_password', function(d) { 94 | log.debug('got set_root_password info', JSON.stringify(d)); 95 | utils.set_root_password(d.root_password, function() { 96 | app_state.set_root_password = true; 97 | }); 98 | }); 99 | }); 100 | }); 101 | }); 102 | }); 103 | }); 104 | }; 105 | 106 | /** 107 | * Stop the application 108 | * @method stop 109 | * @return void 110 | */ 111 | var stop = function() { 112 | conf.write(app_state); 113 | express_server.close(); 114 | // TODO close websocket 115 | if (app_state.mode === 'setup') { 116 | // TODO do we need to kill the access point here 117 | setupCtrl.stop(); 118 | } else { 119 | // TODO close ping http server if it is running 120 | boardCtrl.stop(); 121 | } 122 | conf.write(app_state); 123 | // TODO make sure we are actually closing the websocket server 124 | //socketio_server.close(); 125 | servers.express_server.close(); 126 | // TODO stop http ping server 127 | }; 128 | 129 | var launch_setup_ctrl = function() { 130 | log.info('launch_setup_ctrl'); 131 | setupCtrl = setupCtrlF(app_state.setup_state, servers.socketio_server, 132 | function on_finished(setup_state) { 133 | log.debug('finished with setup'); 134 | app_state.mode = 'control'; 135 | app_state.setup_state = setup_state; 136 | log.debug('app_state', JSON.stringify(app_state, null, 2)); 137 | conf.write(APP_CONF_FILE, app_state).then(function() { 138 | log.debug('getting hostname for redirect...'); 139 | utils.get_hostname(function(error, stdout, stderr) { 140 | // take newline off the end of stdout 141 | var hostname = stdout.slice(0, -1); 142 | // make sure hostname ends in .local 143 | var suffix = ".local"; 144 | var suffix_len = suffix.length; 145 | if (hostname.slice(-suffix_len) !== suffix) { 146 | hostname = hostname + suffix; 147 | } 148 | log.debug('about to ask the client to redirect with hostname', hostname); 149 | // ask the client to redirect 150 | servers.socketio_server.emit('redirect', { 151 | url: hostname, 152 | ping_port: PING_PORT, 153 | port: server_port, 154 | }); 155 | }); 156 | }); 157 | }, 158 | // when the client says it is ready to redirect 159 | function on_redirect() { 160 | log.debug('on_redirect, about to stop access point'); 161 | utils.stop_access_point(function() { 162 | log.debug('finished stopping access point'); 163 | setupCtrl.stop(); 164 | //sh('reboot'); 165 | sh('systemctl restart avahi-daemon', function() { 166 | require('child_process').spawn('systemctl', ['restart', 'maker-node']); 167 | }); 168 | }); 169 | }); 170 | // TODO error callback 171 | // TODO have setup_controller _.extend({}, setup_state) to clone 172 | // setup_state instead of modify it. then we copy it back onto the 173 | // app_state here 174 | setupCtrl.start(); 175 | }; 176 | 177 | var launch_board_ctrl = function(cb) { 178 | utils.start_supplicant({ 179 | ssid: app_state.setup_state.ssid, 180 | pwd: app_state.setup_state.pwd, 181 | }, function() { // callback 182 | sh('ifdown wlan0'); 183 | sh('ifup wlan0'); 184 | boardCtrl = boardCtrlF(BOARD_CONF_FILE, servers.socketio_server); 185 | boardCtrl.start(cb); 186 | log.info('Done with start_supplicant'); 187 | }); 188 | }; 189 | 190 | return { 191 | start: start, 192 | stop: stop, 193 | }; 194 | }; 195 | 196 | module.exports = app; 197 | -------------------------------------------------------------------------------- /lib/board_controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module board_controller 3 | **/ 4 | var log = require('./utils/log')('board_conroller'); 5 | var conf = require('./conf')(); 6 | var _ = require('underscore'); 7 | var GalileoF = require('galileo-io'); 8 | 9 | function board_controller(conf_filename, ws) { 10 | 11 | var state; // board state JSON object, recorded in conf file 12 | var galileo; // communication with the actual Galileo using GPIO 13 | 14 | /** 15 | * Init gpio, and start running the board controller server 16 | * @method start 17 | * @param {} cb callback that extecutes when server is done starting. 18 | * @return void 19 | */ 20 | var start = function(cb) { 21 | log.info('Start Board Controller'); 22 | // first read the conf file 23 | conf.read(conf_filename).then(function(o) { 24 | state = o; 25 | log.debug('done reading board state conf file'); 26 | 27 | // second initialize Galileo IO 28 | galileo = new GalileoF(); 29 | galileo.on('ready', function() { 30 | _.each(state.pins, function(pin, idstr) { 31 | var id = parseInt(id); 32 | var mode = pin.is_input ? 'INPUT': 'OUTPUT'; 33 | this.pinMode(id, this.modes[mode]); 34 | if (pin.is_input) { 35 | var method = pin.is_analog ? 'analog': 'digital'; 36 | galileo[method+'Read'](id, pin_listener(id)); 37 | } 38 | }); 39 | log.debug('set up Galileo-IO'); 40 | }); 41 | 42 | // TODO put this in the galileo on ready callback so it happens 43 | // after we are able to update the galileo board based on client 44 | // updates (right now galileo io is broken so that callback never 45 | // happens, it seems) 46 | // third start handling websocket stuff that might require 47 | // updating pins 48 | ws.on('connection', function(conn) { 49 | // send client all the pin info 50 | conn.emit('pins', {pins: state.pins}); 51 | 52 | // client is sending us a pin update 53 | conn.on('pins', update_pins); 54 | 55 | conn.on('disconnect', function() { 56 | log.debug('client disconnected'); 57 | }); 58 | }); 59 | log.debug('set up board controller websocket stuff'); 60 | 61 | // fourth do the callback from app.js 62 | log.debug('about to do the on-done-starting callback'); 63 | cb(); 64 | 65 | }); // end of conf read then 66 | }; // end of start 67 | 68 | var broadcast_pin_updates = function(pin_idstrs, msg_id) { 69 | ws.emit('pins', { 70 | pins: _.pick(state.pins, pin_idstrs), 71 | msg_id_processed: msg_id, 72 | }); 73 | }; 74 | 75 | var pin_listener = function(id) { 76 | return _.throttle(function(id, val) { 77 | log.debug('Update pins from Galileo IO info id', id, 'val', val); 78 | var idstr = id.toString(); 79 | if (state.pins[idstr].value === val) { 80 | return; 81 | } 82 | state.pins[idstr].value = val; 83 | conf.write(conf_filename, state); 84 | broadcast_pin_updates([idstr], null); 85 | }, 100); 86 | }; 87 | 88 | // update output pins when client has changed their values 89 | var update_pins = function(d) { 90 | log.debug('update pins from client info', JSON.stringify(d, null, 2)); 91 | _.each(d.pins, function(pin, idstr) { 92 | var id = parseInt(idstr); 93 | if ( state.pins[idstr].value !== pin.value 94 | && !pin.is_input ) { 95 | var method = pin.is_analog ? 'analog' : 'digital'; 96 | galileo[method+'Write'](id, pin.value); 97 | } 98 | _.extend(state.pins[idstr], pin); 99 | }); 100 | conf.write(conf_filename, state); 101 | broadcast_pin_updates(_.keys(d.pins), d.msg_id); 102 | }; 103 | 104 | /** 105 | * Stop the board controller server. 106 | * @method stop 107 | * @return void CallExpression 108 | */ 109 | var stop = function() { 110 | // TODO do we need to stop Galileo IO? 111 | log.info('Stopping Board Controller'); 112 | return conf.write(conf_filename, state); 113 | }; 114 | 115 | return { 116 | start: start, 117 | stop: stop, 118 | }; 119 | }; 120 | 121 | module.exports = board_controller; 122 | -------------------------------------------------------------------------------- /lib/conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module conf 3 | **/ 4 | 5 | "use strict"; 6 | var fs = require('q-io/fs'); 7 | var log = require('./utils/log')('Conf'); 8 | 9 | module.exports = function() { 10 | /** 11 | * Load and parse a JSON configuration file. 12 | * @method read 13 | * @param {} path 14 | * @return CallExpression 15 | */ 16 | var read = function(path) { 17 | log.info('Reading:', path); 18 | return fs.read(path).then( 19 | JSON.parse, 20 | function(reason) { 21 | log.error('Could not read file', path, 'for reason', reason); 22 | } 23 | ); 24 | }; 25 | 26 | /** 27 | * Save date in a JSON configuration file. 28 | * @method write 29 | * @param {} path 30 | * @param {} content 31 | * @return CallExpression 32 | */ 33 | var write = function(path, content) { 34 | log.info('Writing:', path); 35 | return fs.write(path, JSON.stringify(content, null, 2)).then( 36 | function() { 37 | log.info('Write to', path, 'successful.'); 38 | }, 39 | function() { 40 | log.error('Could not write file', path, 'for reason', reason); 41 | } 42 | ); 43 | }; 44 | 45 | return { 46 | read: read, 47 | write: write, 48 | }; 49 | }; 50 | 51 | -------------------------------------------------------------------------------- /lib/dashboard_controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module dashboard_controller 3 | **/ 4 | 5 | "use strict"; 6 | var log = require('./utils/log')('dashboard_controller'); 7 | var utils = require('./utils/galileo')(); 8 | var mraa_version = 'unknown'; 9 | try { 10 | mraa_version = require("mraa").getVersion().substr(1); 11 | } catch (e) {}; 12 | 13 | var SERVICES = ['avahi-daemon', 'bluetooth', 'connman', 'lighttpd', 'maker-node', 'redis', 'xdk-daemon']; 14 | 15 | module.exports = function(conn) { 16 | function checkService(index, result) { 17 | if (!result) { 18 | result = { 19 | action: 'list', 20 | services: {} 21 | }; 22 | } 23 | if (index < SERVICES.length) { 24 | utils.is_service_active(SERVICES[index], function(b) { 25 | result.services[SERVICES[index]] = b; 26 | checkService(index + 1, result); 27 | }); 28 | } else { 29 | conn.emit('dashboard-service', result); 30 | } 31 | } 32 | 33 | function toggleService(name, action, callback) { 34 | 35 | conn.emit('dashboard-service', { 36 | id: name, 37 | action: action, 38 | status: 'begin' 39 | }); 40 | var f = (action == 'stop' ? utils.stop_service : utils.start_service); 41 | f(name, function() { 42 | conn.emit('dashboard-service', { 43 | id: name, 44 | action: action, 45 | status: 'end' 46 | }); 47 | callback ? callback() : null; 48 | }); 49 | 50 | } 51 | 52 | conn.on('dashboard-command', function(d) { 53 | log.debug('dashboard-command: ', d); 54 | switch (d.action) { 55 | case 'reboot': 56 | utils.reboot(); 57 | break; 58 | case 'install_updates': 59 | utils.install_updates(); 60 | break; 61 | case 'setup': 62 | utils.stop_supplicant(); 63 | break; 64 | } 65 | }); 66 | 67 | conn.on('dashboard-info', function(d) { 68 | var result = { 69 | node_version: process.versions.node, 70 | mraa_version: mraa_version 71 | }; 72 | utils.get_hostname(function(error, hostname) { 73 | result.hostname = hostname; 74 | utils.get_mac_address(function(mac) { 75 | result.mac = mac; 76 | utils.is_online(function(b) { 77 | result.online = b; 78 | utils.get_ip_address('wlp1s0', function(ip) { 79 | if (ip) { 80 | result.ip = ip + ' (wifi wlp1s0)'; 81 | conn.emit('dashboard-info', result); 82 | } else { 83 | utils.get_ip_address('enp0s20f6', function(ip2) { 84 | if (ip2) { 85 | result.ip = ip2 + ' (wired enp0s20f6)'; 86 | } 87 | conn.emit('dashboard-info', result); 88 | }); 89 | } 90 | }); 91 | }); 92 | }); 93 | }); 94 | }); 95 | 96 | conn.on('dashboard-service', function(d) { 97 | switch (d.action) { 98 | case 'list': 99 | checkService(0); 100 | break; 101 | case 'stop': 102 | case 'start': 103 | toggleService(d.name, d.action); 104 | break; 105 | case 'restart': 106 | toggleService(d.name, 'stop', function() { 107 | toggleService(d.name, 'start'); 108 | }); 109 | break; 110 | default: 111 | break; 112 | } 113 | }); 114 | return {}; 115 | } 116 | -------------------------------------------------------------------------------- /lib/setup_controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module setup_controller 3 | **/ 4 | 5 | "use strict"; 6 | var io = require('socket.io'); 7 | var _ = require('underscore'); 8 | var log = require('./utils/log')('setup_controller'); 9 | var utils = require('./utils/galileo')(); 10 | 11 | module.exports = function(state, wss, on_finished, on_redirect) { 12 | var onUpdate; 13 | 14 | /** 15 | * Call to start setup flow. 16 | * @method start 17 | * @return void 18 | */ 19 | function start() { 20 | log.info('Start'); 21 | 22 | wss.on('connect', function(conn) { 23 | conn.on('set_hostname', function(d) { // STEP 1 24 | log.debug('got set_hostname info', JSON.stringify(d)); 25 | utils.set_hostname(d.hostname, function() { 26 | state.set_hostname = true; 27 | }); 28 | }); 29 | 30 | conn.on('router_setup', function(d) { // STEP 2 31 | log.debug('got router info', JSON.stringify(d)); 32 | if (_.has(d, 'ssid')) { 33 | state.ssid = d.ssid; 34 | } 35 | if (_.has(d, 'pwd')){ 36 | state.pwd = d.pwd; 37 | } 38 | on_finished(state); 39 | }); 40 | 41 | // TODO I think it would be better to assign to this event in lib/app.js, 42 | // but I am not sure if I can do that without blocking the other events 43 | // that setup_controller.js needs to listen to 44 | conn.on('redirect', function(d) { 45 | log.debug('client says it is ready to redirect'); 46 | on_redirect(); 47 | }); 48 | 49 | conn.on('disconnect', function(d) { 50 | log.debug('client disconnected'); 51 | }); 52 | }); 53 | 54 | } 55 | 56 | /** 57 | * Call when setup flow is completed. 58 | * @method stop 59 | * @return void 60 | */ 61 | function stop() { 62 | log.info('STOPPED', state); 63 | }; 64 | 65 | return { 66 | start: start, 67 | stop: stop, 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /lib/utils/README.md: -------------------------------------------------------------------------------- 1 | MakerNodeUtils 2 | ============== 3 | 4 | Utilities for developing javascript apps. on the Intel Galileo 5 | -------------------------------------------------------------------------------- /lib/utils/command_queue.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var sys = require('sys'); 3 | var exec = require('child_process').exec; 4 | var log = require('./log')('Command Queue', 'command_queue.log'); 5 | 6 | /** 7 | * This module provides a mechanism to synchronously execute shell commands via a queue. 8 | * @constructor command_queue 9 | **/ 10 | module.exports = function() { 11 | var queue = []; 12 | 13 | /** 14 | * Execute the next shell command in the queue. 15 | * @memberOf command_queue 16 | * @method dequeue 17 | * @return void 18 | */ 19 | var dequeue = function() { 20 | if (queue.length > 0) { 21 | //log.info(queue[0].cmd); 22 | var cp = exec(queue[0].cmd, function(error, stdout, stderr) { 23 | //log.debug('[out] ' + stdout); 24 | if (error) { 25 | log.info(queue[0].cmd); 26 | log.error('exec error:', error); 27 | } 28 | if (queue[0].cb) { 29 | setTimeout(queue[0].cb, 1, error, stdout, stderr); 30 | } 31 | queue.shift(); 32 | dequeue(); 33 | }); 34 | }; 35 | }; 36 | 37 | /** 38 | * Add a shell command to the queue 39 | * @memberOf command_queue 40 | * @method enqueue 41 | * @param string command 42 | * @param {} callback An optional callback to exectue when the command is done. 43 | * Use the form void->(error, stdout, stderr) 44 | * @return void 45 | */ 46 | var enqueue = function(command, callback) { 47 | queue.push({cmd: command, cb: callback}); 48 | if (queue.length == 1) { 49 | dequeue(); 50 | } 51 | }; 52 | 53 | return enqueue; 54 | }; 55 | -------------------------------------------------------------------------------- /lib/utils/galileo.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var sh = require('./command_queue')(); 3 | var log = require('./log')('galileo'); 4 | var express = require('express'); 5 | var socketio = require('socket.io'); 6 | var fs = require('fs'); 7 | 8 | 9 | /** 10 | * @constructor galileo 11 | **/ 12 | module.exports = function() { 13 | 14 | function start_service(name, callback) { 15 | sh('systemctl start ' + name, callback); 16 | } 17 | 18 | function stop_service(name, callback) { 19 | sh('systemctl stop ' + name, callback); 20 | } 21 | 22 | function is_service_active(name, callback) { 23 | sh('systemctl is-active ' + name, function(error, stdout, stderr) { 24 | callback(stdout.indexOf('inactive') === -1); 25 | }); 26 | } 27 | 28 | function get_mac_address(callback) { 29 | sh("ifconfig | grep -o -m 1 'HWaddr[^\n]*'", function(error, stdout, stderr) { 30 | 31 | var result = null; 32 | if (stdout) { 33 | result = stdout.split(' '); 34 | result = result[1].split(':').join(''); 35 | 36 | } 37 | callback(result); 38 | }); 39 | 40 | } 41 | 42 | function get_ip_address(network_interface, callback) { 43 | sh("ifconfig " + network_interface + " | grep 'inet addr:' | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1", function(error, stdout, stderr) { 44 | callback(stdout); 45 | }); 46 | } 47 | 48 | function is_online(callback) { 49 | sh('curl www.intel.com', function(error, stdout, stderr) { 50 | callback(error ? false : true) 51 | }); 52 | } 53 | 54 | function set_ap_host_name(callback) { 55 | get_mac_address(function(address) { 56 | if (address) { 57 | sh("sed -i 's/ssid=.*/ssid=MakerNode-" + address.substring(address.length - 5) + "/' /etc/hostapd.conf", callback); 58 | } else { 59 | log.error('Could not get mac address. Maybe networking is disabled..?'); 60 | callback(); 61 | } 62 | }); 63 | } 64 | 65 | var cached_wifi_network_list = null; 66 | 67 | function list_wifi_networks(callback) { 68 | log.debug('client is asking what wifi networks are available'); 69 | sh("iwlist wlp1s0 scan | grep 'ESSID'", 70 | function(error, stdout, stderr) { 71 | if (!error) { 72 | stdout = remove_extra_spaces(stdout); 73 | stdout = stdout.replace(/ESSID:/g, ''); 74 | stdout = stdout.replace(/\"/g, ''); 75 | cached_wifi_network_list = stdout.split(' '); 76 | } 77 | callback(cached_wifi_network_list); 78 | } 79 | ); 80 | } 81 | 82 | function get_wifi_key(ssid, callback) { 83 | sh("connmanctl services", 84 | function(error, stdout, stderr) { 85 | console.log('Match ' + ssid + ' in ' + stdout); 86 | stdout = remove_extra_spaces(stdout); 87 | var a = stdout.split(' '); 88 | for (var i = 0; i < a.length; i++) { 89 | if (a[i] == ssid) { 90 | callback(a[i + 1]); 91 | } 92 | } 93 | callback(null); 94 | }); 95 | 96 | } 97 | 98 | function remove_extra_spaces(string) { 99 | return string.replace(/\s+/g, ' ').trim(); 100 | } 101 | /** 102 | * Description 103 | * @memberOf galileo 104 | * @method start_access_point 105 | * @param {} callback 106 | * @return void 107 | */ 108 | 109 | function start_access_point(callback) { 110 | set_ap_host_name(function() { 111 | stop_service('connman', function() { 112 | require('child_process').exec('./startAP.sh'); //Not sure why this sometimes fails to call back 113 | //TODO: Consider breaking up startAP.sh into discrete sh() calls... 114 | callback(); 115 | // sh('./startAP.sh', callback); 116 | }); 117 | }); 118 | } 119 | 120 | /** 121 | * Description 122 | * @memberOf galileo 123 | * @method stop_access_point 124 | * @param {} callback 125 | * @return void 126 | */ 127 | function stop_access_point(callback) { 128 | sh('killall hostapd', callback); 129 | } 130 | 131 | /** 132 | * Description 133 | * @method start_supplicant 134 | * @memberOf galileo 135 | * @param {} options 136 | * @param {} callback 137 | * @return void 138 | */ 139 | function start_supplicant(options, callback) { 140 | log.debug('start_supplicant was called', options); 141 | var data = ''; 142 | data += '[service_null123]\n'; 143 | data += 'Type = wifi\n'; 144 | //data += 'Security = none\n'; 145 | data += 'Name = ' + options.ssid + '\n'; 146 | if (options.hasOwnProperty('pwd') && options.pwd) { 147 | data += 'Passphrase = ' + options.pwd + '\n'; 148 | } 149 | log.debug('data=', data); 150 | fs.writeFile('/var/lib/connman/wifi.config', data, function(err) { 151 | if (err) { 152 | console.log(err); 153 | } else { 154 | log.debug('starting connman'); 155 | start_service('connman', callback); 156 | }; 157 | }); 158 | } 159 | 160 | // TODO stop_supplicant does more than just stop the wifi connection. 161 | // it also resets us to setup mode! this is not a well named function 162 | /** 163 | * Description 164 | * @memberOf galileo 165 | * @method stop_supplicant 166 | * @param {} callback 167 | * @return void 168 | */ 169 | function stop_supplicant(callback) { 170 | sh('sh/restore_factory_settings.sh', callback); 171 | } 172 | 173 | function install_updates(callback) { 174 | sh('sh/install_updates.sh', callback); 175 | } 176 | 177 | function reboot() { 178 | sh('reboot'); 179 | } 180 | 181 | /** 182 | * Description 183 | * @memberOf galileo 184 | * @method get_hostname 185 | * @param {} callback 186 | * @return void 187 | */ 188 | function get_hostname(callback) { 189 | sh('hostname', callback); 190 | } 191 | 192 | /** 193 | * Description 194 | * @method set_hostname 195 | * @memberOf galileo 196 | * @param {} name 197 | * @param {} callback 198 | * @return void 199 | */ 200 | function set_hostname(name, callback) { 201 | sh('sh/set_hostname.sh ' + name, callback); 202 | } 203 | 204 | /** 205 | * Description 206 | * @memberOf galileo 207 | * @method set_root_password 208 | * @param {} pwd 209 | * @param {} callback 210 | * @return void 211 | */ 212 | function set_root_password(pwd, callback) { 213 | // Steve's configure_edison.py commands for changing the password 214 | // def changePassword(newPass): 215 | // os.popen('echo "root":"%s" | chpasswd' % newPass) 216 | // os.popen("sed -i 's/^wpa_passphrase=.*/wpa_passphrase=%s/' /etc/hostapd/hostapd.conf" % (newPass)) 217 | sh('echo root:' + pwd + ' | chpasswd', callback); 218 | } 219 | 220 | /** 221 | * Description 222 | * @memberOf galileo 223 | * @method create_servers 224 | * @param {} port 225 | * @param {} client_path 226 | * @return ObjectExpression 227 | */ 228 | function create_servers(port, client_path) { //TODO: refactor so this takes callback; need to stop connman here 229 | var express_app = express(); 230 | if (client_path) { 231 | express_app.use(express.static(client_path)); 232 | } 233 | var express_server = express_app.listen(port); 234 | var socketio_server = socketio.listen(express_server); 235 | express_app.get('/test_connection', function(req, res) { 236 | res.setHeader('Access-Control-Allow-Origin', '*'); 237 | res.send({ 238 | success: true 239 | }); 240 | }); 241 | 242 | return { 243 | express_app: express_app, 244 | express_server: express_server, 245 | socketio_server: socketio_server 246 | } 247 | } 248 | 249 | return { 250 | get_wifi_key: get_wifi_key, 251 | list_wifi_networks: list_wifi_networks, 252 | start_service: start_service, 253 | stop_service: stop_service, 254 | is_service_active: is_service_active, 255 | start_access_point: start_access_point, 256 | stop_access_point: stop_access_point, 257 | start_supplicant: start_supplicant, 258 | stop_supplicant: stop_supplicant, 259 | get_hostname: get_hostname, 260 | set_hostname: set_hostname, 261 | set_root_password: set_root_password, 262 | create_servers: create_servers, 263 | get_mac_address: get_mac_address, 264 | get_ip_address: get_ip_address, 265 | reboot: reboot, 266 | install_updates: install_updates, 267 | is_online: is_online 268 | }; 269 | } 270 | -------------------------------------------------------------------------------- /lib/utils/log.js: -------------------------------------------------------------------------------- 1 | "use strict;" 2 | var clc = require('cli-color'); 3 | var fs = require('fs'); 4 | 5 | var log_types = { 6 | info: { 7 | color: 'blue', 8 | console: 'log', 9 | prefix: 'INFO', 10 | }, 11 | error: { 12 | color: 'red', 13 | console: 'error', 14 | prefix: 'ERROR', 15 | }, 16 | debug: { 17 | color: 'blackBright', 18 | console: 'log', 19 | prefix: 'DEBUG', 20 | }, 21 | }; 22 | 23 | /** 24 | * @constructor log 25 | * @param {String} name An identifier for this logger; usually the class or module name. 26 | * @param {String} [dest] The name of a file to write this log to. If not specified, the logger will write to console. 27 | * @return {Object} the logger instance 28 | * @example 29 | * var log = require('log')('my_module_name', 'log_file.txt'); 30 | * log.debug('Something happened!'); 31 | */ 32 | function log(name, dest) { 33 | var have_written_prefix = false; 34 | 35 | var write_msg = function(t, msg) { 36 | if (msg !== '') { 37 | var timestamp = new Date().toTimeString(); 38 | 39 | var prefix = '[' + timestamp.substring(0, timestamp.indexOf(' ')) + " " + name + ':' + t.prefix + ']'; 40 | if (dest) { 41 | write_to_file(prefix + msg); 42 | } else { 43 | console[t.console](clc[t.color].bold(prefix) + clc[t.color](msg)); 44 | } 45 | have_written_prefix = true; 46 | } 47 | }; 48 | 49 | var write_obj = function(t, obj) { 50 | if (!have_written_prefix) { 51 | write_msg(t, ' '); 52 | } 53 | if (dest) { 54 | write_to_file(JSON.stringify(obj)); 55 | } else { 56 | console[t.console](obj); 57 | } 58 | }; 59 | 60 | var write_to_file = function(line) { 61 | fs.appendFile(dest, line + '\n', function(err) { 62 | if (err) { 63 | throw err; 64 | } 65 | }); 66 | } 67 | 68 | var logger = function(type) { 69 | // TODO make sure this prints JSON nicely 70 | var t = log_types[type]; 71 | return function() { 72 | have_written_prefix = false; 73 | var msg = ''; 74 | for (var i = 0; i < arguments.length; i++) { 75 | var data_type = typeof(arguments[i]); 76 | if (data_type === "string" || 77 | data_type === "number" || 78 | data_type === "undefined" || 79 | arguments[i] === null) { 80 | msg += ' ' + arguments[i]; 81 | } else { 82 | write_msg(t, msg); 83 | write_obj(t, arguments[i]); 84 | msg = ''; 85 | } 86 | } 87 | write_msg(t, msg); 88 | }; 89 | }; 90 | 91 | return { 92 | /** 93 | * @memberOf log 94 | * @method 95 | * @param {String} message 96 | **/ 97 | info: logger('info'), 98 | /** 99 | * @memberOf log 100 | * @method 101 | * @param {String} message 102 | **/ 103 | debug: logger('debug'), 104 | /** 105 | * @memberOf log 106 | * @method 107 | * @param {String} message 108 | **/ 109 | error: logger('error'), 110 | }; 111 | }; 112 | 113 | module.exports = log; 114 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MakerNode", 3 | "preferGlobal": false, 4 | "version": "0.0.1", 5 | "author": "adampasz ", 6 | "description": "Write NodeJS for the Intel Galileo", 7 | "contributors": [ 8 | { 9 | "name": "Noura Howell", 10 | "email": "noura.howell@gmail.com", 11 | "url": "http://nourahowell.com" 12 | } 13 | ], 14 | "main": "./index", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/IntelOpenDesign/MakerNode" 18 | }, 19 | "keywords": [ 20 | "intel", 21 | "galileo", 22 | "arduino" 23 | ], 24 | "dependencies": { 25 | "galileo-io": "git+https://github.com/rwaldron/galileo-io.git", 26 | "q": "1.0.1", 27 | "q-io": "1.11.1", 28 | "underscore": "1.6.0", 29 | "docopt-js-shim": "git+https://github.com/adampasz/docopt-js-shim.git" 30 | }, 31 | "licenses": { 32 | "type": "MIT" 33 | }, 34 | "engines": { 35 | "node": ">=0.8.18" 36 | }, 37 | "devDependencies": { 38 | "chai": "~1.9.1", 39 | "istanbul": "~0.3.0", 40 | "mocha": "~1.20.1", 41 | "mocha-better-spec-reporter": "0.0.2", 42 | "mocha-unfunk-reporter": "~0.4.0", 43 | "socket.io": "^1.0.6", 44 | "socket.io-client": "~1.0.6", 45 | "jsdoc": "~3.3.0-alpha9", 46 | "less": "~1.7.5", 47 | "cli-color": "~0.3.2", 48 | "express": "~4.9.6" 49 | }, 50 | "scripts": { 51 | "test": "./node_modules/mocha/bin/mocha --timeout 5000 --reporter mocha-unfunk-reporter", 52 | "coverage": "./node_modules/istanbul/lib/cli.js cover node_modules/mocha/bin/_mocha -- --timeout 5000 -R mocha-unfunk-reporter && mv coverage/lcov-report/ client/coverage/", 53 | "doc": "./node_modules/jsdoc/jsdoc.js -d client/docs/server -r lib", 54 | "css": "./node_modules/less/bin/lessc client/app.less > client/static/css/app.css" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /set_hostname.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Deprecated. Use sh/set_hostname 3 | # Steve's configure_edison.py commands for setting hostname 4 | # def changeName(newName): 5 | # #mDNS later 6 | # os.popen("hostname %s" % (newName)) 7 | # os.popen("sed -i 's/^hostname.*/hostname %s/' /etc/init.d/run-startup" % (newName)) 8 | # os.popen("sed -i 's/^ssid=.*/ssid=%s/' /etc/hostapd/hostapd.conf" % (newName+"_ap")) 9 | 10 | hostname $1 11 | echo $1 > /etc/hostname 12 | #sed -i 's/^hostname.*/hostname $1/' /etc/init.d/run-startup 13 | 14 | -------------------------------------------------------------------------------- /sh/install_updates.sh: -------------------------------------------------------------------------------- 1 | # update system time over the internet 2 | rdate -s rdate.cpanel.net 3 | 4 | # get the latest from git and npm 5 | git pull origin master 6 | npm install 7 | -------------------------------------------------------------------------------- /sh/maker-node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | start() { 3 | echo "Starting MakerNode Server..." 4 | pushd /home/root/MakerNode 5 | node ./index.js 6 | popd 7 | } 8 | 9 | stop() { 10 | echo "Stopping MakerNode Server..." 11 | #TODO: need more graceful implementation. :) 12 | killall hostapd 13 | killall node 14 | } 15 | 16 | restart() { 17 | echo "Restarting MakerNode Server..." 18 | stop 19 | start 20 | } 21 | 22 | status() { 23 | echo "Do something here..." 24 | } 25 | 26 | help() { 27 | echo $"Usage: $0 {start|stop|restart|status|help}" 28 | } 29 | 30 | if [ "$#" -ne 1 ] 31 | then 32 | help 33 | exit 1 34 | fi 35 | 36 | # call arguments verbatim: 37 | $@ 38 | -------------------------------------------------------------------------------- /sh/reset_AP_service.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | start() { 3 | echo "Starting Button Monitor..." 4 | pushd /home/root/MakerNode/ 5 | sh/reset_button_monitor.sh 6 | popd 7 | } 8 | 9 | stop() { 10 | echo "Stopping Button Monitor..." 11 | #TODO: need more graceful implementation. :) 12 | kill $(echo -n > /home/root/MakerNode/sh/reset.pid) 13 | } 14 | 15 | restart() { 16 | echo "Restarting Button Monitor..." 17 | stop 18 | start 19 | } 20 | 21 | status() { 22 | echo "Still monitoring..." 23 | } 24 | 25 | help() { 26 | echo $"Usage: $0 {start|stop|restart|status|help}" 27 | } 28 | 29 | if [ "$#" -ne 1 ] 30 | then 31 | help 32 | exit 1 33 | fi 34 | 35 | # call arguments verbatim: 36 | $@ 37 | -------------------------------------------------------------------------------- /sh/reset_button_monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Reset button mapped to reset Wifi to AP mode after a 5 second long press..." 4 | 5 | declare -i count=0 6 | declare -i max=4 7 | declare -i waitL=20 8 | declare -i waitCount=0 9 | 10 | inWaitMode=false 11 | gpioPressed="0" 12 | input_reset_gpio= 13 | output_reset_gpio= 14 | board= 15 | 16 | #get the distribution of Linux 17 | issue=$(cat /etc/issue | awk '{print $1;}' | tr -d "\n") 18 | echo "linux distribution is: $issue" 19 | 20 | if [ "$issue" == "iot-devkit" ]; then 21 | #method for iotdk dist. by SSG (full gcc) 22 | board=$(cat /sys/devices/virtual/dmi/id/board_name) 23 | echo "board name is: $board" 24 | else 25 | #method for standard version of linux dist. by NDG 26 | type dmidecode > /dev/null 2>&1 || die "dmidecode not installed" 27 | board=$(dmidecode -s baseboard-product-name) 28 | echo "board name is: $board" 29 | fi 30 | 31 | #get the GPIO pins for the button 32 | case "$board" in 33 | "Galileo") 34 | input_reset_gpio=52 35 | output_reset_gpio=53 36 | ;; 37 | "GalileoGen2") 38 | input_reset_gpio=63 39 | output_reset_gpio=47 40 | ;; 41 | esac 42 | 43 | 44 | startAPMode() 45 | { 46 | echo "USER pressed reset for 5 seconds....." 47 | ~/MakerNode/sh/restore_factory_settings.sh 48 | echo "Board returned to original setting and is now in AP mode" 49 | } 50 | 51 | #output the pid of this process to file (no longer needed) 52 | echo $$ > reset.pid 53 | 54 | #make sure the GPIO is exported, on the iotdk only R3 pins are exported 55 | echo -n $output_reset_gpio > /sys/class/gpio/export 56 | echo -n $input_reset_gpio > /sys/class/gpio/export 57 | 58 | #check button press of buttons 59 | keepgoing=true 60 | while $keepgoing 61 | 62 | do 63 | if [ "$inWaitMode" == false ]; then 64 | 65 | 66 | gpioIn=`cat /sys/class/gpio/gpio${output_reset_gpio}/value` 67 | gpioOut=`cat /sys/class/gpio/gpio${input_reset_gpio}/value` 68 | 69 | if [[ "$gpioIn" = "$gpioPressed" ]] && [[ "$gpioOut" = "$gpioPressed" ]]; then 70 | echo "Reset Button press" 71 | count=$((count+1)) 72 | else 73 | count=$((0)) 74 | fi 75 | 76 | if [ "$count" -ge "$max" ]; then 77 | startAPMode 78 | count=$((0)) 79 | inWaitMode=true 80 | fi 81 | 82 | else 83 | waitCount=$((waitCount+1)) 84 | if [ "$waitCount" -ge "$waitL" ]; then 85 | waitCount=$((0)) 86 | inWaitMode=false 87 | fi 88 | 89 | fi 90 | 91 | sleep 1 92 | 93 | done 94 | -------------------------------------------------------------------------------- /sh/restore_factory_settings.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | pushd ~/MakerNode 3 | sh/set_hostname.sh clanton 4 | echo root:root | chpasswd 5 | rm /var/lib/connman/wifi.config 6 | cp conf/default_appstate.conf conf/appstate.conf 7 | cp conf/default_boardstate.conf conf/boardstate.conf 8 | popd 9 | reboot 10 | -------------------------------------------------------------------------------- /sh/set_hostname.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Steve's configure_edison.py commands for setting hostname 4 | # def changeName(newName): 5 | # #mDNS later 6 | # os.popen("hostname %s" % (newName)) 7 | # os.popen("sed -i 's/^hostname.*/hostname %s/' /etc/init.d/run-startup" % (newName)) 8 | # os.popen("sed -i 's/^ssid=.*/ssid=%s/' /etc/hostapd/hostapd.conf" % (newName+"_ap")) 9 | 10 | hostname $1 11 | echo $1 > /etc/hostname 12 | #sed -i 's/^hostname.*/hostname $1/' /etc/init.d/run-startup 13 | 14 | -------------------------------------------------------------------------------- /startAP.sh: -------------------------------------------------------------------------------- 1 | ifconfig wlp1s0 up 2 | wpa_cli -iwlp1s0 "terminate" & 3 | hostapd -B /etc/hostapd.conf & 4 | ifconfig wlp1s0 192.168.0.10 & 5 | busybox-i586 dnsd -i 192.168.0.10 -p 53 -c /etc/dnsd.conf & 6 | busybox-i586 udhcpd /etc/udhcpd.conf & 7 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | ```` 2 | cd maker/app 3 | ```` 4 | 5 | To run unit tests: 6 | 7 | ```` 8 | npm test 9 | ```` 10 | 11 | To run tests with code coverage: 12 | ```` 13 | npm run coverage 14 | ```` 15 | 16 | A pretty coverage report gets written to test/coverage/lcov-report/index.html 17 | 18 | Text execution commands can be found in the "scripts" block of package.json. 19 | Note that the async. test timeout was increased to 5 seconds to ensure tests would pass when running on slower hardware. 20 | 21 | -------------------------------------------------------------------------------- /test/board_controller_test.js: -------------------------------------------------------------------------------- 1 | var io = require('socket.io-client'); 2 | var exec = require('child_process').exec; 3 | var should = require('chai').should(); 4 | 5 | var network_utils = require('../lib/utils/galileo')(); 6 | 7 | var client; 8 | var HOST = 'localhost'; 9 | var PORT = 8002; 10 | var NETSTAT = "netstat -a -n | egrep '" + PORT + ".* LISTEN'"; //TODO: Make this a util method 11 | var FILE = 'test/test_boardstate.conf'; 12 | 13 | var servers = network_utils.create_servers(PORT); 14 | var board_controller = require('../lib/board_controller')(FILE, servers.socketio_server); 15 | 16 | describe('board_controller.start()', function() { 17 | 18 | board_controller.start(function() { 19 | it('* Should listen on port ' + PORT, function(done) { 20 | exec(NETSTAT, function(error, stdout, stderr) { 21 | stdout.should.not.have.length(0); 22 | done(); 23 | }); 24 | }); 25 | }); 26 | 27 | it('* Client should open and.emit messages', function(done) { 28 | var message_count = 0; 29 | client = io('http://' + HOST + ':' + PORT); 30 | client.on('connect', function() { 31 | setTimeout(function() { 32 | done(); 33 | client.close(); 34 | }, 1200); 35 | }); 36 | 37 | client.on('disconnect', function() { 38 | describe('board_controller.stop()', function() { 39 | it('* Socket should close', function(done) { 40 | 41 | var result = board_controller.stop(); 42 | console.log(result); 43 | servers.express_server.close(); 44 | exec(NETSTAT, function(error, stdout, stderr) { 45 | stdout.should.have.length(0); 46 | done(); 47 | }); 48 | }); 49 | }); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/conf_test.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var conf = require('../lib/conf')(); 3 | var chai = require('chai'), 4 | should = chai.should(); 5 | var FILE = 'foo.temp'; 6 | 7 | //First, delete file. 8 | function deleteFile() { 9 | fs.unlink(FILE, function(err) { 10 | if (err) throw err; 11 | }); 12 | } 13 | 14 | describe('Conf.write()', function() { 15 | deleteFile(); 16 | it('* Writes ' + FILE, function(done) { 17 | conf.write(FILE, { 18 | test: 'pass' 19 | }) 20 | .then( 21 | function(state) { 22 | done(); 23 | 24 | describe('Conf.read()', function() { 25 | it('* Reads valid JSON from ' + FILE, function(done) { 26 | conf.read(FILE) 27 | .then( 28 | function(state) { 29 | state.should.have.property('test', 'pass'); 30 | done(); 31 | deleteFile(); 32 | }, 33 | function(reason) { 34 | throw ('read error: ' + reason); 35 | } 36 | ) 37 | }); 38 | }); 39 | }, 40 | function(reason) { 41 | throw ('write error: ' + reason); 42 | } 43 | ) 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /test/manual/cpu_test.js: -------------------------------------------------------------------------------- 1 | // var Galileo = require('galileo-io'); 2 | function test() { 3 | console.log('test'); 4 | setTimeout(test, 3000); 5 | } 6 | test(); 7 | -------------------------------------------------------------------------------- /test/manual/cylon_test.js: -------------------------------------------------------------------------------- 1 | var Cylon = require('cylon'); 2 | 3 | Cylon.robot({ 4 | connection: { name: 'galileo', adaptor: 'intel-iot' }, 5 | device: {name: 'led', driver: 'led', pin: 13 }, 6 | 7 | work: function(my) { 8 | every((1).second(), function() { 9 | my.led.toggle(); 10 | }); 11 | } 12 | }).start(); 13 | 14 | -------------------------------------------------------------------------------- /test/manual/gpio_test.js: -------------------------------------------------------------------------------- 1 | var Galileo = require("galileo-io"); 2 | var board = new Galileo(); 3 | var pin = 13; 4 | if (process.argv.length > 2) { 5 | pin = process.argv[2]; 6 | } 7 | 8 | board.on("ready", function() { 9 | var byte = 0; 10 | this.pinMode(pin, this.MODES.OUTPUT); 11 | 12 | setInterval(function() { 13 | board.digitalWrite(pin, (byte ^= 1)); 14 | }, 500); 15 | }); 16 | -------------------------------------------------------------------------------- /test/manual/testCommandQueue.js: -------------------------------------------------------------------------------- 1 | var utils = require('../lib/utils/galileo')(); 2 | var sh = require('../lib/utils/command_queue')(); 3 | utils.stop_service('connman', function() { 4 | console.log('stopped connman'); 5 | utils.start_access_point(function() { 6 | console.log('set up ap'); 7 | utils.set_hostname('rrr', function() { 8 | // utils.get_hostname(function(err, stdout, stderr) { 9 | // console.log(err + ' ' + stdout + ' '); 10 | console.log('ok'); 11 | // }); 12 | }); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/setup_controller_test.js: -------------------------------------------------------------------------------- 1 | var io = require('socket.io-client'); 2 | var exec = require('child_process').exec; 3 | var should = require('chai').should(); 4 | 5 | var utils = require('../lib/utils/galileo')(); 6 | 7 | var state = { 8 | "setup_state": { 9 | "network_confirmed": false, 10 | "user_password_set": false, 11 | "ssid": "", 12 | "pwd": "", 13 | "router_gateway_ip": "", 14 | "galileo_static_ip": "" 15 | } 16 | }; 17 | 18 | var client; 19 | var HOST = 'localhost'; 20 | var PORT = 8001; 21 | var NETSTAT = "netstat -a -n | egrep '" + PORT + ".* LISTEN'"; //TODO: Make this a util method 22 | 23 | var servers = utils.create_servers(PORT); 24 | var setup_controller = require('../lib/setup_controller')(state, servers.socketio_server, on_finished, on_redirect); 25 | 26 | describe('setup_controller.start()', function() { 27 | 28 | setup_controller.start(); 29 | it('* Should listen on port ' + PORT, function(done) { 30 | exec(NETSTAT, function(error, stdout, stderr) { 31 | stdout.should.not.have.length(0); 32 | done(); 33 | }); 34 | }); 35 | 36 | it('* Client should open and.emit messages', function(done) { 37 | var message_count = 0; 38 | client = io('http://' + HOST + ':' + PORT); 39 | client.on('connect', function() { 40 | utils.get_hostname(function(err, name){ 41 | client.emit('set_hostname', {hostname: name}); 42 | setTimeout(function() { 43 | client.emit('router_setup', {ssid:'cat', pwd:'meow'}); 44 | }, 500); 45 | setTimeout(done, 1000); //HACK 46 | }); 47 | }); 48 | 49 | client.on('disconnect', function() { 50 | describe('setup_controller.stop()', function() { 51 | it('* Socket should close', function(done) { 52 | 53 | setup_controller.stop(); 54 | servers.express_server.close(); 55 | exec(NETSTAT, function(error, stdout, stderr) { 56 | stdout.should.have.length(0); 57 | done(); 58 | }); 59 | }); 60 | }); 61 | }); 62 | }); 63 | }); 64 | 65 | function on_finished(state) { 66 | describe('setup_controller.on_finished()', function() { 67 | it('* Messages should update state correctly', function(done) { 68 | console.log(state.set_hostname + "=state.set_hostname"); 69 | state.set_hostname.should.equal(true); 70 | client.close(); 71 | done(); 72 | }); 73 | }); 74 | } 75 | 76 | function on_redirect() {} 77 | -------------------------------------------------------------------------------- /test/test_boardstate.conf: -------------------------------------------------------------------------------- 1 | { 2 | "pins": { 3 | "2": { 4 | "is_analog": false, 5 | "is_input": false, 6 | "value": 0 7 | }, 8 | "3": { 9 | "is_analog": true, 10 | "is_input": false, 11 | "value": 0 12 | }, 13 | "4": { 14 | "is_analog": false, 15 | "is_input": false, 16 | "value": 0 17 | }, 18 | "5": { 19 | "is_analog": true, 20 | "is_input": false, 21 | "value": 0 22 | }, 23 | "6": { 24 | "is_analog": true, 25 | "is_input": false, 26 | "value": 0 27 | }, 28 | "7": { 29 | "is_analog": false, 30 | "is_input": false, 31 | "value": 0 32 | }, 33 | "8": { 34 | "is_analog": false, 35 | "is_input": false, 36 | "value": 0 37 | }, 38 | "9": { 39 | "is_analog": true, 40 | "is_input": false, 41 | "value": 0 42 | }, 43 | "10": { 44 | "is_analog": true, 45 | "is_input": false, 46 | "value": 0 47 | }, 48 | "11": { 49 | "is_analog": true, 50 | "is_input": false, 51 | "value": 0 52 | }, 53 | "12": { 54 | "is_analog": false, 55 | "is_input": false, 56 | "value": 0 57 | }, 58 | "13": { 59 | "is_analog": false, 60 | "is_input": false, 61 | "value": 0 62 | }, 63 | "14": { 64 | "is_analog": true, 65 | "is_input": true, 66 | "value": 0.29931173264048994 67 | }, 68 | "15": { 69 | "is_analog": true, 70 | "is_input": true, 71 | "value": 0.1345119304023683 72 | }, 73 | "16": { 74 | "is_analog": true, 75 | "is_input": true, 76 | "value": 0.870145900407806 77 | }, 78 | "17": { 79 | "is_analog": true, 80 | "is_input": true, 81 | "value": 0.7994520112406462 82 | }, 83 | "18": { 84 | "is_analog": true, 85 | "is_input": true, 86 | "value": 0.4925047110300511 87 | }, 88 | "19": { 89 | "is_analog": true, 90 | "is_input": true, 91 | "value": 0.803674541413784 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | The Sublime 2 Plugin that makes it easy to deploy nodejs projects to the Intel Galileo with MakerNode. Work in progress. 2 | -------------------------------------------------------------------------------- /tools/plugin/Prefixr/Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [{ "keys": ["super+shift+e"], "command": "example" }] 2 | -------------------------------------------------------------------------------- /tools/plugin/Prefixr/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "project", 4 | "children": 5 | [ 6 | {"id": "end"}, 7 | { "command": "example" } 8 | ] 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /tools/plugin/Prefixr/Prefixr.py: -------------------------------------------------------------------------------- 1 | import sublime, sublime_plugin, subprocess, thread, os, functools 2 | 3 | class ExampleCommand(sublime_plugin.WindowCommand): 4 | def run(self): 5 | self.window.run_command("exec", {"cmd": ["pwd"]}) -------------------------------------------------------------------------------- /tools/plugin/Prefixr/Prefixr.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/tools/plugin/Prefixr/Prefixr.pyc -------------------------------------------------------------------------------- /tools/project_skeleton/README.md: -------------------------------------------------------------------------------- 1 | # Setting Up a Project on the Galileo 2 | The recommended location for your project folders is in /home/root/projects. (Use mkdir to create a projects folder if it does not already exist.) 3 | 4 | ```` 5 | cd /home/root/ 6 | mkdir projects 7 | cd projects/ 8 | git clone https://github.com/adampasz/MakerNodeProjectSkeleton.git your_project_name 9 | cd your_project_name 10 | npm install 11 | chmod u+x app.js 12 | ```` 13 | 14 | # Running Your Project 15 | To start the server for your project: 16 | ```` 17 | cd /home/root/projects/your_project_name 18 | killall node 19 | node app.js 20 | ```` 21 | 22 | # Troubleshooting 23 | **If you get a weird error about SSL or a CAfile, do this** 24 | ```` 25 | git config --global http.sslVerify false 26 | ```` 27 | **Avoid having to re-enter your github credentials all the time** 28 | ```` 29 | git config --global credential.helper cache 30 | git config --global credential.helper 'cache --timeout=3600' 31 | ```` 32 | -------------------------------------------------------------------------------- /tools/project_skeleton/app.js: -------------------------------------------------------------------------------- 1 | var utils = require('maker-node-utils/galileo')(); 2 | var log = require('maker-node-utils/log')('app') 3 | var path = require('path'); 4 | var HOST = 'localhost'; 5 | var PORT = 3000; 6 | 7 | var servers = utils.create_servers(PORT, path.join(__dirname, '/client')); 8 | log.info('HTTP and WS servers listening on port', PORT); 9 | -------------------------------------------------------------------------------- /tools/project_skeleton/client/index.html: -------------------------------------------------------------------------------- 1 | HELLO WORLD, FROM THE GALILEO! 2 | -------------------------------------------------------------------------------- /tools/project_skeleton/client/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntelOpenDesign/MakerNode/6d50c5552823595dfa84afb86c16125839942389/tools/project_skeleton/client/main.js -------------------------------------------------------------------------------- /tools/project_skeleton/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mnskeleton", 3 | "version": "0.0.0", 4 | "description": "Project template for apps. running on the Intel Galileo.", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/adampasz/MakerNodeProjectSkeleton.git" 12 | }, 13 | "keywords": [ 14 | "Intel", 15 | "Galileo", 16 | "Node" 17 | ], 18 | "dependencies": { 19 | "mnutils": "git+https://github.com/adampasz/MakerNodeUtils.git", 20 | "galileo-io": "~0.1.3" 21 | }, 22 | "author": "", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/adampasz/MakerNodeProjectSkeleton/issues" 26 | }, 27 | "homepage": "https://github.com/adampasz/MakerNodeProjectSkeleton" 28 | } 29 | -------------------------------------------------------------------------------- /tools/sh/mn_create.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | repo=https://github.com/IntelOpenDesign/MakerNodeProjectSkeleton.git 3 | start_time=`date +%s` 4 | project_name=${1:-my_project} 5 | echo creating project $project_name 6 | git clone -v --progress $repo ./$project_name 7 | pushd $project_name 8 | rm -rf .git* 9 | # npm install 10 | popd 11 | # The next lines clones directly on the device, but I don't think we need this... 12 | #project_path=/home/root/projects 13 | # target="root@${2:-clanton.local}" 14 | # ssh $target git clone -v --progress $repo $project_path/$project_name 15 | echo Completed in $(expr `date +%s` - $start_time) seconds. 16 | exit 0 17 | -------------------------------------------------------------------------------- /tools/sh/mn_deploy.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | start_time=`date +%s` 3 | payload=${1:-.} 4 | target="root@${2:-clanton.local}:${3:-/home/root/projects/}" 5 | echo deploying $payload to $target 6 | scp -prC $payload $target 7 | echo Completed in $(expr `date +%s` - $start_time) seconds. 8 | exit 0 9 | 10 | -------------------------------------------------------------------------------- /tools/sh/mn_run.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | start_time=`date +%s` 3 | project_name=${1:-my_project} 4 | # The next lines clones directly on the device, but I don't think we need this... 5 | project_path=/home/root/projects 6 | target="root@${2:-clanton.local}" 7 | echo running node $project_path/$project_name/app.js 8 | ssh $target bash -c "' 9 | killall node 10 | node $project_path/$project_name/app.js 11 | '" 12 | echo Completed in $(expr `date +%s` - $start_time) seconds. 13 | exit 0 14 | --------------------------------------------------------------------------------