diff --git a/README.md b/README.md index 4b13f424b..cdda94879 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Smart Mirror -[![Join the chat at https://gitter.im/evancohen/smart-mirror](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/evancohen/smart-mirror?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Stories in Progress](https://img.shields.io/waffle/label/evancohen/smart-mirror/in%20progress.svg)] (https://waffle.io/evancohen/smart-mirror) [![Suggestions](https://img.shields.io/waffle/label/evancohen/smart-mirror/suggestion.svg?label=suggestions)] (https://github.com/evancohen/smart-mirror/issues?q=is%3Aissue+is%3Aopen+label%3Asuggestion) [![devDependency Status](https://david-dm.org/evancohen/smart-mirror/dev-status.svg)](https://david-dm.org/evancohen/smart-mirror#info=devDependencies) +[![Join the chat at https://gitter.im/evancohen/smart-mirror](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/evancohen/smart-mirror?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Stories in Progress](https://img.shields.io/waffle/label/evancohen/smart-mirror/in%20progress.svg)] (https://waffle.io/evancohen/smart-mirror) [![Suggestions](https://img.shields.io/waffle/label/evancohen/smart-mirror/suggestion.svg?label=suggestions)] (https://github.com/evancohen/smart-mirror/issues?q=is%3Aissue+is%3Aopen+label%3Asuggestion) [![Dependency Status](https://dependencyci.com/github/evancohen/smart-mirror/badge)](https://dependencyci.com/github/evancohen/smart-mirror) -Check out the [smart mirror documentation](http://docs.smart-mirror.io) for installation instructions and troubleshooting. +Check out the [smart mirror documentation](http://docs.smart-mirror.io) for more information, installation instructions, and troubleshooting. #### Gitter: A live chat to get help and discuss mirror related issues: https://gitter.im/evancohen/smart-mirror. Usually there are a few folks hanging around in the lobby, but if there arent you are probubly better off [filing an issue](https://github.com/evancohen/smart-mirror/issues/new). diff --git a/config.example.js b/config.example.js index 1164d72bc..6c7eda239 100644 --- a/config.example.js +++ b/config.example.js @@ -25,37 +25,56 @@ var config = { //use this only if you want to hardcode your geoposition (used for weather) /* - geo_position: { + geoPosition: { latitude: 78.23423423, longitude: 13.123124142 }, */ - - // forcast.io + + // forecast.io forecast : { - key : "", // Your forcast.io api key - units : "auto" // See forcast.io documentation if you are getting the wrong units + key : "", // Your forecast.io api key + units : "auto", // See forecast.io documentation if you are getting the wrong units + refreshInterval : 2, // Number of minutes the information is refreshed. Forecast.io limits requests to 1000/day: a 2min interval = 720 calls/day }, - // Philips Hue - hue : { - ip : "", // The IP address of your hue base - uername : "", // The username used to control your hue - groups : [{ - id : 0, // The group id 0 will change all the lights on the network - name : "all" - }, { - id : 1, - name : "bedroom" - }, { - id : 2, - name : "kitchen" - }] + // lights + light : { + settings : { + hueIp : "", // The IP address of your hue base + hueUsername : "" // The username used to control your hue + }, + setup : [ + { + name : "parlor", // Single word room name for speech recognition + targets : [ + { + type : "hyperion", + ip : "", // The IP address of your hyperion + port : "19444" // The port of your hyperion + }, + { + type : "hue", // Philips Hue + id : 1 // The group id (0 will change all the lights on the network) + } + ] + }, + { + name : "bath", + targets : [ + { + type : "hue", + id : 2 + } + ] + } + ] }, // Calendar (An array of iCals) calendar: { icals : [], // Be sure to wrap your URLs in quotes maxResults: 9, // Number of calender events to display (Defaults is 9) - maxDays: 365 // Number of days to display (Default is one year) + maxDays: 365, // Number of days to display (Default is one year) + showCalendarNames: false // Show calendar names above events }, // Giphy giphy: { @@ -71,12 +90,12 @@ var config = { }, traffic: { key : "", // Bing Maps API Key - - reload_interval : 5, // Number of minutes the information is refreshed + refreshInterval : 5, // Number of minutes the information is refreshed // An array of tips that you would like to display travel time for trips : [{ mode : "Driving", // Possibilities: Driving / Transit / Walking origin : "", // Start of your trip. Human readable address. + via : "", // [Optional] Set an intermediate goal for getting an alternate route for example destination : "", // Destination of your trip. Human readable address. name : "work", // Name of your destination ex: "work" /*startTime: "", @@ -86,6 +105,20 @@ var config = { rss: { feeds : [], // RSS feeds list - e.g. ["rss1.com", "rss2.com"] refreshInterval : 120 // Number of minutes the information is refreshed + }, + stock: { + names: [] // The names of the stock quotes you with to show in the official format. (e.g.: 'YHOO','AAPL','GOOG') + }, + autoTimer: { + autoSleep: 2400000, // How long the screen will stay awake before going to sleep (40 Mins) + autoWake: '07:00:00', // When to automatically wake the screen up (7:00AM) + 'wake_cmd': '/opt/vc/bin/tvservice -p', // The binary and arguments used on your system to wake the screen + 'sleep_cmd': '/opt/vc/bin/tvservice -o', // The binary and arguments used on your system to sleep the screen + }, + lastfm: { + key: "", // Your last.fm api key + user: "", // Your last.fm username + refreshInterval : 0.6 // Number of minutes between checks for playing track } }; diff --git a/css/icesnow.css b/css/icesnow.css index 2a212d483..73a1cae43 100644 --- a/css/icesnow.css +++ b/css/icesnow.css @@ -115,7 +115,7 @@ ul.calendar { text-align: right; width: 230px; } -.weather-today .tempreture { +.weather-today .temperature { font-size: 60px; } .weather-week-descriptor { @@ -132,7 +132,7 @@ ul.calendar { display: inline-block; margin-right: 10px; width: 40px; } - .weather-week .tempreture { + .weather-week .temperature { display: inline-block; width: 60px; } @@ -284,7 +284,7 @@ body { Weather */ -.weather-today .tempreture { +.weather-today .temperature { font-size: 80px; } .weather-week-descriptor span.ng-binding { diff --git a/css/icesnow.css.map b/css/icesnow.css.map deleted file mode 100644 index 7fa9c801a..000000000 --- a/css/icesnow.css.map +++ /dev/null @@ -1,7 +0,0 @@ -{ -"version": 3, -"mappings": "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", -"sources": ["../sass/icesnow.scss","../sass/main.scss"], -"names": [], -"file": "icesnow.css" -} diff --git a/css/main.css b/css/main.css index e7c86dabc..9fedeb5e8 100644 --- a/css/main.css +++ b/css/main.css @@ -1,158 +1,231 @@ @font-face { - font-family: "HelveticaNeue-UltraLight"; - src: url("../fonts/HelveticaNeue-UltraLight.ttf"); - /* EOT file for IE */ } + font-family: "HelveticaNeue-UltraLight"; + src: url("../fonts/HelveticaNeue-UltraLight.ttf"); + /* EOT file for IE */ +} + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { + display: none !important; +} + body { - background-color: black; - color: #fff; - font-family: 'HelveticaNeue-UltraLight', 'Open Sans', sans-serif; - font-weight: 300; - position: relative; } + background-color: black; + color: #fff; + font-family: 'HelveticaNeue-UltraLight', 'Open Sans', sans-serif; + font-weight: 300; + position: relative; +} -h1, h2, h3, h4, h5 { - font-weight: 300; } +h1, +h2, +h3, +h4, +h5 { + font-weight: 300; +} h1 { - font-size: 120px; } + font-size: 120px; +} dt { - font-weight: 600; } + font-weight: 600; +} /* Colors */ .light-grey { - color: #ccc; } + color: #ccc; +} .grey { - color: #999; } + color: #999; +} /* Displays */ .sleep-cover { - background-color: black; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 999; } + background-color: black; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999; +} .container { - z-index: -1; - /* so things are still selectable */ - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; - transition: all 0.3s ease;} + z-index: -1; + /* so things are still selectable */ + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + transition: all 0.3s ease; +} .listening { - box-shadow: inset 0px -40px 40px -40px #fff -} + box-shadow: inset 0px -40px 40px -40px #fff +} .not-listening { - box-shadow: inset 0px 0px 0px 0px #fff -} + box-shadow: inset 0px 0px 0px 0px #fff +} .interim-result { - font-family: 'Open Sans', sans-serif; } + font-family: 'Open Sans', sans-serif; +} .top-left { - float: left; } + float: left; +} .date { - font-size: 42px; } + font-size: 42px; +} .time { - font-size: 110px; } + font-size: 110px; +} .top-right { - float: right; } + float: right; +} .middle-center { - display: flex; - flex: 1; - align-items: stretch; - align-self: flex-start; - flex-direction: column; - width: 100%; - text-align: center; - justify-content: center; } + display: flex; + flex: 1; + align-items: stretch; + align-self: flex-start; + flex-direction: column; + width: 100%; + text-align: center; + justify-content: center; +} .bottom-center { - font-family: 'Open Sans', sans-serif; - width: 100%; - text-align: center; - margin-bottom: 20px; } + font-family: 'Open Sans', sans-serif; + width: 100%; + text-align: center; + margin-bottom: 20px; +} -.bottom-left { +.bottom-left, .bottom-right { font-family: 'Open Sans', sans-serif; position: absolute; - bottom: 20px; + bottom: 50px; + width: 50%; +} + +.bottom-left { left: 20px; } +.bottom-right { + right: 20px; +} + .commands { - width: 450px; - text-align: left; - margin-left: auto; - margin-right: auto; } + width: 450px; + text-align: left; + margin-left: auto; + margin-right: auto; +} ul.calendar { - list-style: none; - font-size: 22px; - margin-left: 10px; - padding: 0; } + list-style: none; + font-size: 22px; + margin-left: 10px; + padding: 0; +} .calendar .event { - margin-bottom: 10px; } + margin-bottom: 10px; +} + .calendar span { - display: inline-block; } - .calendar span.day { + display: inline-block; +} + +.calendar .day { + display: none; font-weight: bold; - width: 128px; - vertical-align: top; } - .calendar span.summary { - max-width: 400px; } + vertical-align: top; +} + +.calendar span.summary { + font-size: 25px; + max-width: 400px; +} + .calendar .event-details .details { - font-size: 12px; - padding-left: 135px; - font-family: 'Open Sans', sans-serif; - font-weight: lighter; } + font-size: 12px; + font-family: 'Open Sans', sans-serif; + font-weight: lighter; +} + +.calendar-name { + display: none; +} + +.show-calendar-names .calendar-name { + display: block; +} + +.day-marker { + margin-top: 30px; +} + +.day-marker .day { + display: block; + font-size: 15px; + letter-spacing: 2px; + margin-bottom: 10px; +} .weather { - margin-left: auto; - display: inline-block; - text-align: right; - width: 230px; } + margin-left: auto; + display: inline-block; + text-align: right; + width: 230px; +} -.weather-today .tempreture { - font-size: 60px; } +.weather-today .temperature { + font-size: 60px; +} .weather-week-descriptor { - font-family: 'Open Sans', sans-serif; - font-size: 12px; - margin-left: auto; - margin-bottom: 10px; - text-align: justify; } + font-family: 'Open Sans', sans-serif; + font-size: 12px; + margin-left: auto; + margin-bottom: 10px; + text-align: justify; +} .weather-week { - margin-right: 10px; - font-size: 22px; } - .weather-week .day { + margin-right: 10px; + font-size: 22px; +} + +.weather-week .day { display: inline-block; margin-right: 10px; - width: 40px; } - .weather-week .tempreture { + width: 40px; +} + +.weather-week .temperature { display: inline-block; - width: 50px; } + width: 50px; +} -.weather .weather-today canvas, .weather .weather-week-day canvas { - display: none; } +.weather .weather-today canvas, +.weather .weather-week-day canvas { + display: none; +} .fitbit { height: 100%; @@ -185,78 +258,108 @@ ul.calendar { width: 450px; } -.traffic-information { - text-align: right; - margin-top: 10px; - margin-right: 10px; } +.playing-track img { + float: left; + margin-right: 5px; +} + +.traffic-information, .stock-information { + text-align: right; + margin-top: 10px; + margin-right: 10px; +} .time-to { - font-weight: bold; } + font-weight: bold; +} @keyframes reduce-dashoffset { - to { - stroke-dashoffset: 0; } } + to { + stroke-dashoffset: 0; + } + +} + @keyframes increase-dashoffset { - from { - stroke-dashoffset: 0; } } + from { + stroke-dashoffset: 0; + } + +} + .timer { - font-size: 120px; - position: relative; } + font-size: 120px; + position: relative; +} .timer-circle { - width: 3.25em; - height: 3.25em; - transform: rotate(-90deg) scaleY(-1); - margin: 20px auto; - display: block; } - .timer-circle .background, - .timer-circle .progress { + width: 3.25em; + height: 3.25em; + transform: rotate(-90deg) scaleY(-1); + margin: 20px auto; + display: block; +} + +.timer-circle .background, +.timer-circle .progress { r: 1.525em; cx: 1.625em; cy: 1.625em; stroke-width: 0.1em; fill: none; - stroke: #222; } - .timer-circle .progress { + stroke: #222; +} + +.timer-circle .progress { stroke-dasharray: 10.2101761239em; stroke-dashoffset: 10.2101761239em; stroke-linecap: round; animation-name: increase-dashoffset; animation-timing-function: linear; animation-fill-mode: forwards; - stroke: white; } + stroke: white; +} -.timer-countdown, .timer-duration { - position: absolute; - top: 50%; - left: 50%; - transform: translateY(-50%) translateX(-50%); } +.timer-countdown, +.timer-duration { + position: absolute; + top: 50%; + left: 50%; + transform: translateY(-50%) translateX(-50%); +} .timer-duration { - top: 75%; - font-size: 25%; } + top: 75%; + font-size: 25%; +} .contents { - max-width: 100%; } + max-width: 100%; +} .gif { - height: 100%; } + height: 100%; +} .map { - height: 1080px; } + height: 1080px; +} .reminders-container { - width: 250px; - text-align: left; - margin-left: auto; - margin-right: auto; } + width: 250px; + text-align: left; + margin-left: auto; + margin-right: auto; +} .contents-box { - text-align: center; - width: 100%; - position: relative; - overflow: hidden; } - .contents-box:after { + text-align: center; + width: 100%; + position: relative; + overflow: hidden; +} + +.contents-box:after { content: ''; position: absolute; top: 0; @@ -266,7 +369,8 @@ ul.calendar { -webkit-box-shadow: inset 0 0 10px 10px #000; -moz-box-shadow: inset 0 0 10px 10px #000; box-shadow: inset 0 0 10px 10px #000; - overflow: hidden; } + overflow: hidden; +} .video { width: 100%; @@ -275,88 +379,115 @@ ul.calendar { /* If you want to make the video black and white -webkit-filter: grayscale(100%); filter: grayscale(100%); - */ -} + */} .sc-container { - margin:auto; - -webkit-filter: grayscale(70%); - filter: grayscale(70%); - font-family: bold; + margin: auto; + -webkit-filter: grayscale(70%); + filter: grayscale(70%); + font-family: bold; } + .scWaveform { - background-color: #000000; - width: 500px; - -webkit-filter: invert(100%); - filter: invert(100%); + background-color: #000000; + width: 500px; + -webkit-filter: invert(100%); + filter: invert(100%); } .color-block { - height: 200px; - width: 200px; - display: inline-block; - margin: 10px; - margin-bottom: 20px; } + height: 200px; + width: 200px; + display: inline-block; + margin: 10px; + margin-bottom: 20px; +} .debug-info { - width: 500px; } + width: 500px; +} /* Animations */ .fade.ng-hide { - opacity: 0; } -.fade.ng-hide-remove, .fade.ng-hide-add { - display: block !important; } + opacity: 0; +} + +.fade.ng-hide-remove, +.fade.ng-hide-add { + display: block !important; +} + .fade.ng-hide-remove { - transition: all ease 1500ms; } + transition: all ease 1500ms; +} + .fade.ng-hide-add { - transition: all ease 500ms; } + transition: all ease 500ms; +} .animate-grow { - max-height: 1280px !important; } - .animate-grow.ng-hide-add, .animate-grow.ng-hide-remove { - transition: all linear 500ms; } - .animate-grow.ng-hide { - max-height: 0 !important; } + max-height: 1280px !important; +} + +.animate-grow.ng-hide-add, +.animate-grow.ng-hide-remove { + transition: all linear 500ms; +} + +.animate-grow.ng-hide { + max-height: 0 !important; +} .dimmed { - color: #aaa; } + color: #aaa; +} -.xxsmall, .xsmall, .small { - font-family: "HelveticaNeue-Medium", sans-serif; - letter-spacing: 0; } +.xxsmall, +.xsmall, +.small { + font-family: "HelveticaNeue-Medium", sans-serif; + letter-spacing: 0; +} .xxsmall { - font-size: 15px; } - .xxsmall .wi { - line-height: 15px; } + font-size: 15px; +} + +.xxsmall .wi { + line-height: 15px; +} .xsmall { - font-size: 20px; } + font-size: 20px; +} .small { - font-size: 25px; } + font-size: 25px; +} .icon { - position: relative; - top: -10px; - display: inline-block; - font-size: 45px; - padding-right: 5px; - font-weight: 100; - margin-right: 10px; } + position: relative; + top: -10px; + display: inline-block; + font-size: 45px; + padding-right: 5px; + font-weight: 100; + margin-right: 10px; +} .icon-small { - position: relative; - display: inline-block; - font-size: 20px; - padding-left: 0px; - padding-right: -10px; - font-weight: 100; - width: 20px; } + position: relative; + display: inline-block; + font-size: 20px; + padding-left: 0px; + padding-right: -10px; + font-weight: 100; + width: 20px; +} .xkcd { - -webkit-filter: invert(100%); - max-width: 100%; + -webkit-filter: invert(100%); + max-width: 100%; } .news { diff --git a/css/main.css.map b/css/main.css.map deleted file mode 100644 index 19c7a95da..000000000 --- a/css/main.css.map +++ /dev/null @@ -1,7 +0,0 @@ -{ -"version": 3, -"mappings": "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", -"sources": ["../sass/main.scss"], -"names": [], -"file": "main.css" -} diff --git a/index.html b/index.html index 6e1cdf3f2..e2b63d911 100644 --- a/index.html +++ b/index.html @@ -22,6 +22,7 @@ + @@ -29,7 +30,7 @@ - + @@ -38,28 +39,39 @@ + + + - + -
+' + JSON.stringify(profile, null, 2) + ''); + res.redirect('/fb-profile'); }); - else - res.send('
' + JSON.stringify(profile, null, 2) + ''); + }); + }); + + // Call an API. fitbit.request() mimics nodejs request() library, automatically + // adding the required oauth2 headers. The callback is a bit different, called + // with ( err, body, token ). If token is non-null, this means a refresh has happened + // and you should persist the new token. + // + app.get( '/fb-profile', function(req, res, next) { + fitbit.request({ + uri: "https://api.fitbit.com/1/user/-/profile.json", + method: 'GET', + }, function(err, body, token) { + if (err) return next(err); + var profile = JSON.parse(body); + // if token is not null, a refesh has happened and we need to persist the new token + if (token) + persist.write(tfile, token, function(err) { + if (err) return next(err); + res.send('
' + JSON.stringify(profile, null, 2) + ''); + }); + else + res.send('
' + JSON.stringify(profile, null, 2) + ''); + }); }); - }); + } // Only start up express and enable the fitbit service to start making API calls if the fitbit config is present in config.js. if (typeof config.fitbit != 'undefined') { @@ -146,21 +164,7 @@ return null; } - var today = new Date(); - var dd = today.getDate(); - var mm = today.getMonth()+1; //January is 0! - var yyyy = today.getFullYear(); - - // Add padding for the date, (we want 0x where x is the day or month number if its less than 10) - if(dd<10) { - dd='0'+dd - } - - if(mm<10) { - mm='0'+mm - } - - today = yyyy+'-'+mm+'-'+dd; + today = service.getToday(); // Make an API call to get the users activities for today fitbit.request({ @@ -171,7 +175,37 @@ console.log(err); } var result = JSON.parse(body); + console.log(result); + // If the token arg is not null, then a refresh has occured and + // we must persist the new token. + if (token) { + persist.write(tfile, token, function(err) { + if (err) console.log(err); + }); + } + return callback(result); + }); + + + } + + service.sleepSummary = function(callback) { + if(service.today === null){ + return null; + } + + today = service.getToday(); + // Make an API call to get the users sleep summary for today + fitbit.request({ + uri: "https://api.fitbit.com/1/user/-/sleep/date/" + today + ".json", + method: 'GET', + }, function(err, body, token) { + if (err) { + console.log(err); + } + var result = JSON.parse(body); + console.log(result); // If the token arg is not null, then a refresh has occured and // we must persist the new token. if (token) { @@ -181,8 +215,38 @@ } return callback(result); }); + + } + service.deviceSummary = function(callback) { + if(service.today === null){ + return null; + } + + // Make an API call to get the users device status + fitbit.request({ + uri: "https://api.fitbit.com/1/user/-/devices.json", + method: 'GET', + }, function(err, body, token) { + if (err) { + console.log(err); + } + var result = JSON.parse(body); + console.log(result); + // If the token arg is not null, then a refresh has occured and + // we must persist the new token. + if (token) { + persist.write(tfile, token, function(err) { + if (err) console.log(err); + }); + } + return callback(result); + }); + + + } + return service; } diff --git a/js/services/geolocation.js b/js/services/geolocation.js index bdae63aba..60572f7bd 100644 --- a/js/services/geolocation.js +++ b/js/services/geolocation.js @@ -23,14 +23,14 @@ var deferred = $q.defer(); // Use geo postion from config file if it is defined - if(typeof config.geo_position != 'undefined' - && typeof config.geo_position.latitude != 'undefined' - && typeof config.geo_position.longitude != 'undefined'){ + if(typeof config.geoPosition != 'undefined' + && typeof config.geoPosition.latitude != 'undefined' + && typeof config.geoPosition.longitude != 'undefined'){ deferred.resolve({ coords: { - latitude: config.geo_position.latitude, - longitude: config.geo_position.longitude, + latitude: config.geoPosition.latitude, + longitude: config.geoPosition.longitude, }, }); diff --git a/js/services/hue.js b/js/services/hue.js deleted file mode 100644 index 96ab095a9..000000000 --- a/js/services/hue.js +++ /dev/null @@ -1,125 +0,0 @@ -(function() { - 'use strict'; - - function HueService($http, $translate) { - var service = {}; - //Updates a group of Hue lights (Assumes that one group is configured) - //You can change the group to 0 to perform the updates to all lights - service.performUpdate = function(spokenWords) { - var spokenWordsArray = spokenWords.toLowerCase().split(" "); - //deturmine the updates that we need to perform to the lights - var update = deturmineUpdates(spokenWordsArray); - // Deturmine which light to swith on/off - var light = deturmineLight(spokenWordsArray); - //Parse the update string and see what actions we need to perform - console.log("Updating hue group [" + light + "]:", update); - - $http.put('http://' + config.hue.ip + '/api/' + config.hue.uername + "/groups/" + light + "/action", update) - .success(function (data, status, headers) { - console.log(data); - }) - } - - //Detect any kind of target color - function deturmineUpdates(spokenWords){ - var update = {}; - - update["transitiontime"] = 10; - - for(var i = 0; i < spokenWords.length; i++){ - - //Check for color updates - if($translate.instant('lights.colors.red') == spokenWords[i]){ - update["xy"] = [0.674,0.322]; - } else if($translate.instant('lights.colors.dark_green') == spokenWords[i]){ - update["xy"] = [0.408,0.517]; - } else if($translate.instant('lights.colors.green') == spokenWords[i]){ - update["xy"] = [0.408,0.517]; - } else if($translate.instant('lights.colors.blue') == spokenWords[i]){ - update["xy"] = [0.168,0.041]; - } else if($translate.instant('lights.colors.yellow') == spokenWords[i]){ - update["xy"] = [0.4317,0.4996]; - } else if($translate.instant('lights.colors.orange') == spokenWords[i]){ - update["xy"] = [0.5562,0.4084]; - } else if($translate.instant('lights.colors.pink') == spokenWords[i]){ - update["xy"] = [0.3824,0.1601]; - } else if($translate.instant('lights.colors.purple') == spokenWords[i]){ - update["xy"] = [0.2725,0.1096]; - } else if($translate.instant('lights.colors.white') == spokenWords[i]){ - update["xy"] = [0.3227,0.329]; - } else if($translate.instant('lights.colors.movie') == spokenWords[i]){ - update["xy"] = [0.3227,0.329]; - update["sat"] = 0; - update["bri"] = 15; - } else if($translate.instant('lights.colors.colorloop') == spokenWords[i]){ - update["effect"] = "colorloop"; - } else if($translate.instant('lights.colors.stop') == spokenWords[i]){ - update["effect"] = "none"; - update["xy"] = [0.3227,0.329]; - update["sat"] = 0; - update["bri"] = 255; - } - - //check for a brightness adjustment - if(spokenWords[i] == '10'){ - update["bri"] = 26; - } else if(spokenWords[i] == '20'){ - update["bri"] = 51; - } else if(spokenWords[i] == '25'){ - update["bri"] = 64; - } else if(spokenWords[i] == '30'){ - update["bri"] = 77; - } else if(spokenWords[i] == '40'){ - update["bri"] = 102; - } else if(spokenWords[i] == '50'){ - update["bri"] = 128; - } else if(spokenWords[i] == '60'){ - update["bri"] = 153; - } else if(spokenWords[i] == '70'){ - update["bri"] = 179; - } else if(spokenWords[i] == '75'){ - update["bri"] = 191; - } else if(spokenWords[i] == '80'){ - update["bri"] = 204; - } else if(spokenWords[i] == '90'){ - update["bri"] = 230; - } else if(spokenWords[i] == '100'){ - update["bri"] = 255; - } else if($translate.instant('lights.intensity.increase') == spokenWords[i]){ - update["bri_inc"] = 51; // 20% - } else if($translate.instant('lights.intensity.decrease') == spokenWords[i]){ - update["bri_inc"] = -51; // 20% - } else if($translate.instant('lights.intensity.max') == spokenWords[i]){ - update["bri"] = 254; - } - - //are we turning the lights on or off? - if($translate.instant('lights.action.on') == spokenWords[i]){ - update["on"] = true; - update["bri"] = 250; - } else if($translate.instant('lights.action.off') == spokenWords[i]){ - update["on"] = false; - } - } - return update; - } - - // Detect light - // TODO make this return an array of groups to update - function deturmineLight(spokenWords){ - for(var i = 0; i < spokenWords.length; i++){ - for (var j = 0; j < config.hue.groups.length; j++){ - if (spokenWords[i] == config.hue.groups[j].name){ - return j; - } - } - } - return 0; - } - return service; - } - - angular.module('SmartMirror') - .factory('HueService', HueService); - -}()); diff --git a/js/services/light.js b/js/services/light.js new file mode 100644 index 000000000..860c88559 --- /dev/null +++ b/js/services/light.js @@ -0,0 +1,202 @@ +(function() { + 'use strict'; + + var Hyperion = require('hyperion-client'); + + function LightService($http, $translate) { + var service = {}; + + // update lights + service.performUpdate = function(spokenWords){ + // split string into separate words and remove empty ones + var spokenWords = spokenWords.toLowerCase().split(" ").filter(Boolean); + + // what locations are defined in the config + var definedLocations = []; + for(var i = 0; i < config.light.setup.length; i++){ + definedLocations.push(config.light.setup[i].name.toLowerCase()); + } + + var SaidParameter = {}; + SaidParameter['locations'] = []; + SaidParameter['on'] = true; + + // what has been said + for(var i = 0; i < spokenWords.length; i++){ + var index = definedLocations.indexOf(spokenWords[i]); + if(index > -1){ + SaidParameter['locations'].push(index); + } + + // turn lights on or off? + if($translate.instant('lights.action.off') == spokenWords[i]){ + SaidParameter['on'] = false; + } + + // Choose Color + if($translate.instant('lights.colors.red') == spokenWords[i]){ + SaidParameter['colorRGB'] = [255, 0, 0]; + SaidParameter['colorHSV'] = [0, 255, 254]; + } else if($translate.instant('lights.colors.green') == spokenWords[i]){ + SaidParameter['colorRGB'] = [0, 255, 0]; + SaidParameter['colorHSV'] = [25500, 255, 254]; + } else if($translate.instant('lights.colors.blue') == spokenWords[i]){ + SaidParameter['colorRGB'] = [0, 0, 255]; + SaidParameter['colorHSV'] = [46920, 255, 254]; + } else if($translate.instant('lights.colors.yellow') == spokenWords[i]){ + SaidParameter['colorRGB'] = [255, 255, 0]; + SaidParameter['colorHSV'] = [10920, 255, 254]; + } else if($translate.instant('lights.colors.orange') == spokenWords[i]){ + SaidParameter['colorRGB'] = [255, 127, 0]; + SaidParameter['colorHSV'] = [5460, 255, 254]; + } else if($translate.instant('lights.colors.pink') == spokenWords[i]){ + SaidParameter['colorRGB'] = [255, 0, 255]; + SaidParameter['colorHSV'] = [54610, 255, 254]; + } else if($translate.instant('lights.colors.purple') == spokenWords[i]){ + SaidParameter['colorRGB'] = [127, 0, 127]; + SaidParameter['colorHSV'] = [54610, 255, 127]; + } else if($translate.instant('lights.colors.white') == spokenWords[i]){ + SaidParameter['colorRGB'] = [255, 255, 255]; + SaidParameter['colorHSV'] = [0, 0, 254]; + } + + // Adjust brightness + if(spokenWords[i] == '100%' || $translate.instant('lights.intensity.max').includes(spokenWords[i])){ + SaidParameter['brightness'] = 1.0; + } else if(spokenWords[i] == '10%'){ + SaidParameter['brightness'] = 0.1; + } else if(spokenWords[i] == '20%'){ + SaidParameter['brightness'] = 0.2; + } else if(spokenWords[i] == '25%' || $translate.instant('lights.intensity.quarter').includes(spokenWords[i])){ + SaidParameter['brightness'] = 0.25; + } else if(spokenWords[i] == '30%'){ + SaidParameter['brightness'] = 0.3; + } else if(spokenWords[i] == '40%'){ + SaidParameter['brightness'] = 0.3; + } else if(spokenWords[i] == '50%' || $translate.instant('lights.intensity.half').includes(spokenWords[i])){ + SaidParameter['brightness'] = 0.5; + } else if(spokenWords[i] == '60%'){ + SaidParameter['brightness'] = 0.6; + } else if(spokenWords[i] == '70%'){ + SaidParameter['brightness'] = 0.7; + } else if(spokenWords[i] == '75%' || $translate.instant('lights.intensity.threequarter').includes(spokenWords[i])){ + SaidParameter['brightness'] = 0.75; + } else if(spokenWords[i] == '80%'){ + SaidParameter['brightness'] = 0.8; + } else if(spokenWords[i] == '90%'){ + SaidParameter['brightness'] = 0.9; + } + + // special mode + if($translate.instant('lights.action.nightmode').includes(spokenWords[i])){ + SaidParameter['colorRGB'] = [255, 0, 0]; + SaidParameter['colorHSV'] = [0, 255, 254]; + SaidParameter['brightness'] = 0.1 + } + + // reset all LED + if($translate.instant('lights.action.reset').includes(spokenWords[i])){ + localStorage.clear() + } + + } + + // if spoken words contain no location, use all defined locations + if(SaidParameter['locations'].length == 0){ + for(var i = 0; i < definedLocations.length; i++){ + SaidParameter['locations'].push(i); + } + } + + var SavedSettings = []; + + // get remaining info from local storage + for(var j = 0 ; j < SaidParameter['locations'].length; j++){ + var i = SaidParameter['locations'][j]; + var SavedSetting = {}; + // read settings from storage or use default + if(localStorage.getItem('Light_Setup_' + i) == null){ + SavedSetting['colorRGB'] = [255, 255, 255]; + SavedSetting['colorHSV'] = [0, 0, 254]; + SavedSetting['brightness'] = 0.4 + } + else{ + SavedSetting = JSON.parse(localStorage.getItem('Light_Setup_' + i)); + } + + // overwrite settings with spoken info + for(var key in SaidParameter){ + if(SaidParameter.hasOwnProperty(key)) { + SavedSetting[key] = SaidParameter[key]; + } + } + + // save new values in local storage + localStorage.setItem('Light_Setup_' + i, JSON.stringify(SavedSetting)); + + SavedSetting['location'] = i; + + SavedSettings.push(SavedSetting); + } + + SavedSettings.map(updateLights); + } + + function updateLights(setting){ + var index = setting['location']; + for(var i = 0; i < config.light.setup[index].targets.length; i++){ + if(config.light.setup[index].targets[i].type == "hyperion"){ + updateHyperion(i, index, setting); + } + else if(config.light.setup[index].targets[i].type == "hue"){ + updateHue(i, index, setting); + } + } + } + + function updateHyperion(i, index, setting){ + // Convert color and brightness + for(var j = 0; j < setting['colorRGB'].length; j++){ + setting['colorRGB'][j] = Math.round(setting['colorRGB'][j] * setting['brightness']); + } + // Connect to the configured Hyperion client + var hyperion = new Hyperion(config.light.setup[index].targets[i].ip, config.light.setup[index].targets[i].port); + + hyperion.on('connect', function(){ + if(setting['on']){ + hyperion.setColor(setting['colorRGB']); + } + else{ + hyperion.clearall(); + } + }); + + hyperion.on('error', function(error){ + console.error('error:', error); + }); + } + + function updateHue(i, index, setting){ + var update = {}; + update["transitiontime"] = 10; + + update['on'] = setting['on']; + if(setting['on']){ + update['hue'] = setting['colorHSV'][0]; + update['sat'] = setting['colorHSV'][1]; + update['bri'] = Math.round(setting['colorHSV'][2] * setting['brightness']); + } + + $http.put('http://' + config.light.settings.hueIp + '/api/' + config.light.settings.hueUsername + "/groups/" + config.light.setup[index].targets[i].id + "/action", update) + .success(function (data, status, headers) { + console.log(data); + }) + } + + return service; + } + + angular.module('SmartMirror') + .factory('LightService', LightService); + +}()); diff --git a/js/services/rss.js b/js/services/rss.js index bb2e9d9b6..3e140c976 100644 --- a/js/services/rss.js +++ b/js/services/rss.js @@ -1,7 +1,7 @@ (function(annyang) { 'use strict'; - function RssService($http) { + function RssService($http, $q) { var service = {}; service.feed = []; service.currentFeed = 0; @@ -11,24 +11,29 @@ service.currentFeed = 0; var currentTime = new moment(); - angular.forEach(config.rss.feeds, function(url) { - $http.jsonp('http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=50&callback=JSON_CALLBACK&q=' + encodeURIComponent(url)).then(function(response) { - for (var i=0; i < response.data.responseData.feed.entries.length; i++){ - var feedEntry = { - title : response.data.responseData.feed.title, - content: response.data.responseData.feed.entries[i].title, - lastUpdated : currentTime, - }; - //console.log(feedEntry); - service.feed.push(feedEntry); - } + if (typeof config.rss != 'undefined'){ + var promises = []; + angular.forEach(config.rss.feeds, function(url) { + promises.push($http.jsonp('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%20%3D%20\'' + encodeURIComponent(url) + '\'&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=JSON_CALLBACK')); }); - }); - return service.feed; + + return $q.all(promises).then(function(response) { + for (var i=0; i < response['0'].data.query.results.rss.channel.item.length; i++){ + var feedEntry = { + title : response['0'].data.query.results.rss.channel.title, + content: response['0'].data.query.results.rss.channel.item[i].title, + lastUpdated : currentTime, + }; + service.feed.push(feedEntry); + } + }); + } }; service.refreshRssList = function() { - return service.init(); + return service.init().then(function(entries) { + return entries; + }); }; service.getNews = function() { diff --git a/js/services/scrobbler.js b/js/services/scrobbler.js new file mode 100644 index 000000000..8d4a7a39f --- /dev/null +++ b/js/services/scrobbler.js @@ -0,0 +1,40 @@ +(function(annyang) { + 'use strict'; + + function ScrobblerService($http, $q) { + var service = {}; + + service.getCurrentTrack = function () { + var deferred = $q.defer(); + if (config.lastfm.user && config.lastfm.key) { + var url = "http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user="+config.lastfm.user+"&api_key="+config.lastfm.key+"&limit=1&format=json"; + + $http.get(url).then(function(response) { + if (response.data.error){ + // If there is an error with the request (excluding network errors) + console.log("Scrobbler Error: ", response.data.message); + deferred.reject(response); + } else if (typeof response.data.recenttracks.track[0]["@attr"] == "object"){ + // If there is a track currently playing + var track = response.data.recenttracks.track[0]; + deferred.resolve({ + title: track.name, + artist: track.artist["#text"] || "Unknown", + album: track.album["#text"] || "", + cover: track.image[1]["#text"], + }); + } else { + // Either there was a network error or there is no song currently playing + deferred.reject(response); + } + }); + } + return deferred.promise; + } + + return service; + } + + angular.module('SmartMirror') + .factory('ScrobblerService', ScrobblerService); +}(window.annyang)); diff --git a/js/services/soundcloud.js b/js/services/soundcloud.js index 73067094b..e313029e7 100644 --- a/js/services/soundcloud.js +++ b/js/services/soundcloud.js @@ -76,7 +76,7 @@ var canvas = document.getElementById('visualizer'); var canvasCtx = canvas.getContext("2d"); - var WIDTH = 150; + var WIDTH = 300; var HEIGHT = 150; canvasCtx.fillStyle = 'rgb(0, 0, 0)'; diff --git a/js/services/stock.js b/js/services/stock.js new file mode 100644 index 000000000..7eb4cf2e3 --- /dev/null +++ b/js/services/stock.js @@ -0,0 +1,27 @@ +(function(annyang) { + 'use strict'; + + function StockService($window, $http, $q) { + var service = {}; + + service.getStockQuotes = function() { + var deferred = $q.defer(); + if (config.stock.names.length) { + var url = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quote%20where%20symbol%20in%20('+"'" + config.stock.names.join("','") + "'"+')&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&format=json'; + + $http.get(url).then(function(response) { + deferred.resolve(response.data); + }, function(error) { + deferred.reject('Unknown error'); + }); + } + + return deferred.promise; + } + + return service; + } + + angular.module('SmartMirror') + .factory('StockService', StockService); +}(window.annyang)); diff --git a/js/services/traffic.js b/js/services/traffic.js index 6420ef87e..f601d0f1c 100644 --- a/js/services/traffic.js +++ b/js/services/traffic.js @@ -37,6 +37,7 @@ } else { trip.duration = moment.duration(response.data.resourceSets[0].resources[0].travelDurationTraffic, 'seconds') } + deferred.resolve(trip); }, function(error) { // Most of the time this is because an address can't be found @@ -54,7 +55,13 @@ // Depending on the mode of transport different paramaters are required. function getEndpoint(trip){ - var endpoint = BING_MAPS + trip.mode + "?wp.0=" + trip.origin + "&wp.1="+trip.destination; + var waypoints = 1; + var intermediateGoal = ""; + if (typeof trip.via !== 'undefined' && trip.via != "") { + waypoints = 2; + intermediateGoal = "&wp.1=" + trip.via; + } + var endpoint = BING_MAPS + trip.mode + "?wp.0=" + trip.origin + intermediateGoal + "&wp."+ waypoints + "="+trip.destination; if(trip.mode == "Driving"){ endpoint += "&avoid=minimizeTolls"; } else if(trip.mode == "Transit"){ diff --git a/js/services/weather.js b/js/services/weather.js index ee37f4a1e..35b2ba737 100644 --- a/js/services/weather.js +++ b/js/services/weather.js @@ -8,15 +8,23 @@ service.init = function(geoposition) { geoloc = geoposition; + var language = (typeof config.language !== 'undefined')?config.language.substr(0, 2) : "en" return $http.jsonp('https://api.forecast.io/forecast/'+config.forecast.key+'/'+ geoposition.coords.latitude+','+geoposition.coords.longitude+'?units=' + - config.forecast.units + "&lang="+ config.language.substr(0, 2) + "&callback=JSON_CALLBACK") + config.forecast.units + "&lang=" + language + "&callback=JSON_CALLBACK") .then(function(response) { return service.forecast = response; }); }; - //Returns the current forecast along with high and low tempratures for the current day + service.minutelyForecast = function(){ + if(service.forecast === null){ + return null; + } + return service.forecast.data.minutely; + } + + //Returns the current forecast along with high and low tempratures for the current day service.currentForecast = function() { if(service.forecast === null){ return null; diff --git a/locales/de.json b/locales/de.json index 4d7f7ff17..45d5c3d5f 100644 --- a/locales/de.json +++ b/locales/de.json @@ -6,7 +6,7 @@ "time_to" : "Zeit bis {{name}}: " }, "reminders": { - "empty": "Keine Erinnerungen" + "empty": "Keine Erinnerungen." }, "timer": { "one": "Eine", @@ -31,11 +31,16 @@ "intensity": { "increase": "heller", "decrease": "dunkler", - "max": "maximal" + "max": "maximal", + "half": "halber", + "quarter": "viertel", + "threequarter": "dreiviertel" }, "action": { "on": "an", - "off": "aus" + "off": "aus", + "nightmode": "nachtmodus", + "reset": "zurücksetzen" } }, "commands": { @@ -83,7 +88,7 @@ "map_zoom_out": { "text": "verkleinern", "voice": "(Karte) verkleinern", - "description": "Verkleinert die aktulle Karte" + "description": "Verkleinert die aktuelle Karte." }, "map_zoom_point": { "text": "vergrößere ________", @@ -93,7 +98,7 @@ "map_zoom_reset": { "text": "Normalansicht", "voice": "(Karte) Normalansicht", - "description": "Setzt die Ansicht zurück" + "description": "Setzt die Ansicht zurück." }, "video_search": { "text": "Zeige mir ________", @@ -103,12 +108,12 @@ "video_stop": { "text": "Stop video", "voice": "stop (the) video", - "description": "Stops the playback of video content." + "description": "Stopt die Video Wiedergabe." }, "image_giphy": { "text": "Bild von ________", "voice": "Bild von *img", - "description": "Zeigt ein Giphy Bild" + "description": "Zeigt ein Giphy Bild." }, "image_comic": { "text": "Zeige Comic", @@ -118,7 +123,7 @@ "image_comic_dilbert": { "text": "Dilbert Comic", "voice": "Dilbert", - "description": "Dilbert Comic" + "description": "Zeigt den aktuellsten Dilbert Comic." }, "reminder_insert": { "text": "Erinnere mich an ________", @@ -163,27 +168,27 @@ "sc_play": { "text": "SoundCloud play ________", "voice": "SoundCloud play *query", - "description": "Play a song on SoundCloud" + "description": "Spielt einen Song auf SoundCloud." }, "sc_pause": { "text": "SoundCloud pause/stop", "voice": "SoundCloud (pause)(post)(stop)(stock)", - "description": "Stop/pause SoundCoud playback" + "description": "Stoppt/Pausiert die SoundCoud Wiedergabe." }, "sc_resume": { "text": "SoundCloud play", "voice": "SoundCloud (play)(resume)", - "description": "Resumes playback" + "description": "Setzt die Soundcloud Wiedergabe fort." }, "sc_replay": { "text": "SoundCloud replay", "voice": "SoundCloud replay", - "description": "Replays the current song on SoundCloud" + "description": "Spielt den aktuellen Song erneut auf Soundcloud." }, "light_action": { - "text": "Schalte das (state) Licht (action)", - "voice": "(Schalte) (das) :state (die) Licht(er) *action", - "description": "(Schalte) (das) :state (die) Licht(er) *action" + "text": "Schalte (das|die) Licht(er) (action)", + "voice": "(Schalte) (das) (die) Licht(er) *action", + "description": "Steuert Farbe und Helligkeit von Lichtern." } } } diff --git a/locales/en.json b/locales/en.json index dbb1a84e8..42f2842f5 100644 --- a/locales/en.json +++ b/locales/en.json @@ -6,7 +6,7 @@ "time_to" : "Time to {{name}}: " }, "reminders": { - "empty": "Empty list" + "empty": "Empty list." }, "timer": { "one": "One", @@ -31,11 +31,16 @@ "intensity": { "increase": "increase", "decrease": "decrease", - "max": "max" + "max": "max", + "half": "half", + "quarter": "quarter", + "threequarter": ["three-quarter", "three-fourth"] }, "action": { "on": "on", - "off": "off" + "off": "off", + "nightmode": "nightmode", + "reset": "reset" } }, "commands": { @@ -48,22 +53,22 @@ "home": { "text": "Go home", "voice": "Go home", - "description": "Takes you back to the home screen" + "description": "Takes you back to the home screen." }, "sleep": { "text": "Go to sleep", "voice": "Go to sleep", - "description": "Go to sleep" + "description": "Go to sleep." }, "wake_up": { "text": "Wake up", "voice": "Wake up", - "description": "Wake up" + "description": "Wake up." }, "debug": { "text": "Show debug information", "voice": "Show debug information", - "description": "Show debug information" + "description": "Show debug information." }, "map_show": { "text": "Show map", @@ -78,22 +83,22 @@ "map_zoom_in": { "text": "Zoom in", "voice": "(map) zoom in", - "description": "Zooms in the current map" + "description": "Zooms in the current map." }, "map_zoom_out": { "text": "Zoom out", "voice": "(map) zoom out", - "description": "Zooms out the current map" + "description": "Zooms out the current map." }, "map_zoom_point": { "text": "Zoom to ________", "voice": "(map) zoom (to) *value", - "description": "Zooms to indicated point" + "description": "Zooms to indicated point." }, "map_zoom_reset": { "text": "Reset zoom", "voice": "(map) reset zoom", - "description": "Resets zoom" + "description": "Resets zoom." }, "video_search": { "text": "Show me ________", @@ -108,7 +113,7 @@ "image_giphy": { "text": "Giphy ________", "voice": "giphy *img", - "description": "Shows a giphy image" + "description": "Shows a Giphy image." }, "image_comic": { "text": "Show xkcd", @@ -118,7 +123,7 @@ "image_comic_dilbert": { "text": "Show Dilbert comic", "voice": "Show Dilbert (comic)", - "description": "Show Dilbert comic." + "description": "Show the most recent Dilbert comic." }, "reminder_insert": { "text": "Remind me to ________", @@ -133,12 +138,12 @@ "reminder_show": { "text": "Show me reminders", "voice": "Show me reminders", - "description": "Display the reminders list" + "description": "Display the reminders list." }, "time_show": { "text": "what time is it", "voice": "what time is it", - "description": "what time is it" + "description": "Shows the current time." }, "timer_start": { "text": "Timer for ________", @@ -158,32 +163,32 @@ "timer_resume": { "text": "Resume timer", "voice": "resume (the) timer", - "description": "Resume timer" + "description": "Resume timer." }, "sc_play": { "text": "SoundCloud play ________", "voice": "SoundCloud play *query", - "description": "Play a song on SoundCloud" + "description": "Play a song on SoundCloud." }, "sc_pause": { "text": "SoundCloud pause/stop", "voice": "SoundCloud (pause)(post)(stop)(stock)", - "description": "Stop/pause SoundCoud playback" + "description": "Stop/pause SoundCoud playback." }, "sc_resume": { "text": "SoundCloud play", "voice": "SoundCloud (play)(resume)", - "description": "Resumes playback" + "description": "Resumes playback." }, "sc_replay": { "text": "SoundCloud replay", "voice": "SoundCloud replay", - "description": "Replays the current song on SoundCloud" + "description": "Replays the current song on SoundCloud." }, "light_action": { - "text": "Turn the (state) light (action)", + "text": "Turn (state) light(s) (action)", "voice": "(turn) (the) :state (the) light(s) *action", - "description": "(turn) (the) :state (the) light(s) *action" + "description": "Control color and brightness of lights." } } } diff --git a/locales/es.json b/locales/es.json index 7c30ee8b8..48530d259 100644 --- a/locales/es.json +++ b/locales/es.json @@ -6,7 +6,7 @@ "time_to" : "Tiempo al {{name}}: " }, "reminders": { - "empty": "No recuerdo" + "empty": "No recuerdo." }, "timer": { "one": "Uno", @@ -43,62 +43,62 @@ "list": { "text": "¿Qué digo?", "voice": "Que digo", - "description": "Lista de los comandos de voz" + "description": "Lista de los comandos de voz." }, "home": { "text": "Vuelve", "voice": "Vuelve", - "description": "Vuelve al menú principal" + "description": "Vuelve al menú principal." }, "sleep": { "text": "Duerme", "voice": "Duerme", - "description": "Duerme el sistema" + "description": "Duerme el sistema." }, "wake_up": { "text": "Despierta", "voice": "Despierta", - "description": "Despierta el sistema" + "description": "Despierta el sistema." }, "debug": { "text": "Opciones", "voice": "Opciones", - "description": "Muestra información de depuración" + "description": "Muestra información de depuración." }, "map_show": { "text": "Muestra el mapa", "voice": "Muestra el mapa", - "description": "Muestra el mapa de tu posición actual" + "description": "Muestra el mapa de tu posición actual." }, "map_location": { "text": "Muestra el mapa", "voice": "Muestra el mapa de *location", - "description": "Muestra el mapa de la posición indicada" + "description": "Muestra el mapa de la posición indicada." }, "map_zoom_in": { "text": "Centra el mapa", "voice": "Centra (el mapa)", - "description": "Centra el mapa" + "description": "Centra el mapa." }, "map_zoom_out": { "text": "Amplia el mapa", "voice": "Amplia (el mapa)", - "description": "Amplia el mapa" + "description": "Amplia el mapa." }, "map_zoom_point": { "text": "Apunta el mapa a _______", "voice": "Apunta (el mapa) a *value", - "description": "Apunta el mapa a un punto en concreto" + "description": "Apunta el mapa a un punto en concreto." }, "map_zoom_reset": { "text": "Resetea el mapa", "voice": "Resetea (el) (mapa)", - "description": "Resetea (el) (mapa)" + "description": "Resetea (el) (mapa)." }, "video_search": { "text": "Busca imagen de _______", "voice": "Busca imagen de *term", - "description": "Busca una imagen" + "description": "Busca una imagen." }, "video_stop": { "text": "Stop video", @@ -108,12 +108,12 @@ "image_giphy": { "text": "Busca animacion de _______", "voice": "Busca animacion de *img", - "description": "Busca animacion de algún tema" + "description": "Busca animacion de algún tema." }, "image_comic": { "text": "Comic", "voice": "Comic (del dia)", - "description": "Muestra el comic del día" + "description": "Muestra el comic del día." }, "image_comic_dilbert": { "text": "Comic Dilbert", @@ -123,22 +123,22 @@ "reminder_insert": { "text": "Recuerdame hacer _______", "voice": "Recuerdame hacer *task", - "description": "Recuerdame hacer una tarea" + "description": "Recuerdame hacer una tarea." }, "reminder_clear": { "text": "Limpia la tareas pendientes", "voice": "Limpia la tareas pendientes", - "description": "Limpia la tareas pendientes" + "description": "Limpia la tareas pendientes." }, "reminder_show": { "text": "Muéstrame la lista de retiro", "voice": "Muéstrame la lista de retiro", - "description": "Muestra la lista de retiro" + "description": "Muestra la lista de retiro." }, "time_show": { "text": "¿Qué hora es?", "voice": "que hora es", - "description": "Muestra la hora actual" + "description": "Muestra la hora actual." }, "timer_start": { "text": "Temporizador a _______", @@ -163,27 +163,27 @@ "sc_play": { "text": "SoundCloud play ________", "voice": "SoundCloud play *query", - "description": "Play a song on SoundCloud" + "description": "Play a song on SoundCloud." }, "sc_pause": { "text": "SoundCloud pause/stop", "voice": "SoundCloud (pause)(post)(stop)(stock)", - "description": "Stop/pause SoundCoud playback" + "description": "Stop/pause SoundCoud playback." }, "sc_resume": { "text": "SoundCloud play", "voice": "SoundCloud (play)(resume)", - "description": "Resumes playback" + "description": "Resumes playback." }, "sc_replay": { "text": "SoundCloud replay", "voice": "SoundCloud replay", - "description": "Replays the current song on SoundCloud" + "description": "Replays the current song on SoundCloud." }, "light_action": { "text": "[estado] las luces a [acción]", "voice": ":state las luces a *action", - "description": "Cambia el estado de las luces" + "description": "Cambia el estado de las luces." } } } diff --git a/locales/fr.json b/locales/fr.json index df5d85162..92036d799 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -6,7 +6,7 @@ "time_to" : "Temps de {{name}}: " }, "reminders": { - "empty": "Aucun rappel" + "empty": "Aucun rappel." }, "timer": { "one": "Une", @@ -48,22 +48,22 @@ "home": { "text": "Accueil", "voice": "Accueil", - "description": "Vous ramène à l'écran d'accueil" + "description": "Vous ramène à l'écran d'accueil." }, "sleep": { "text": "Bonne nuit", "voice": "Bonne nuit", - "description": "Va te coucher" + "description": "Va te coucher." }, "wake_up": { "text": "Réveille toi", "voice": "Réveille toi", - "description": "Réveille Toi" + "description": "Réveille Toi." }, "debug": { "text": "Débogage", "voice": "Débogage", - "description": "Afficher les informations de débogage" + "description": "Afficher les informations de débogage." }, "map_show": { "text": "Affiche carte", @@ -78,22 +78,22 @@ "map_zoom_in": { "text": "Zoom avant", "voice": "Zoom (avant) (sur la carte)", - "description": "Zoom avant sur la carte actuelle" + "description": "Zoom avant sur la carte actuelle." }, "map_zoom_out": { "text": "Zoom arrière", "voice": "Zoom arrière (sur la carte)", - "description": "Zoom arrière sur la carte actuelle" + "description": "Zoom arrière sur la carte actuelle." }, "map_zoom_point": { "text": "Zoom vers ________", "voice": "Zoom (vers) *value", - "description": "Zoom vers le point indiqué" + "description": "Zoom vers le point indiqué." }, "map_zoom_reset": { "text": "Réinitialise zoom", "voice": "Réinitialise le zoom", - "description": "Réinitilalise la fonction zoom" + "description": "Réinitilalise la fonction zoom." }, "video_search": { "text": "(Re)cherche une image de ________", @@ -108,7 +108,7 @@ "image_giphy": { "text": "(Re)cherche une image animée de ________", "voice": "(Re)cherche une image animée de *img", - "description": "Affiche une image de giphy" + "description": "Affiche une image de giphy." }, "image_comic": { "text": "Montre(-moi) le dernier xkcd ", @@ -163,27 +163,27 @@ "sc_play": { "text": "SoundCloud play ________", "voice": "SoundCloud play *query", - "description": "Play a song on SoundCloud" + "description": "Play a song on SoundCloud." }, "sc_pause": { "text": "SoundCloud pause/stop", "voice": "SoundCloud (pause)(post)(stop)(stock)", - "description": "Stop/pause SoundCoud playback" + "description": "Stop/pause SoundCoud playback." }, "sc_resume": { "text": "SoundCloud play", "voice": "SoundCloud (play)(resume)", - "description": "Resumes playback" + "description": "Resumes playback." }, "sc_replay": { "text": "SoundCloud replay", "voice": "SoundCloud replay", - "description": "Replays the current song on SoundCloud" + "description": "Replays the current song on SoundCloud." }, "light_action": { "text": "(Allume|Éteins) (la|les) lumières (action)", "voice": ":state (les) (la) lumière(s) (*action)", - "description": ":state (les) (la) lumière(s) (*action)" + "description": ":state (les) (la) lumière(s) (*action)." } } } diff --git a/locales/ko.json b/locales/ko.json index b0b01ec0b..3bbb30817 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -6,7 +6,7 @@ "time_to" : "{{name}} 에 시간: " }, "reminders": { - "empty": "더 리콜 없습니다" + "empty": "더 리콜 없습니다." }, "timer": { "one": "일", @@ -53,12 +53,12 @@ "sleep": { "text": "잠자러가", "voice": "잠자러가", - "description": "잠자러가" + "description": "잠자러가." }, "wake_up": { "text": "일어나", "voice": "일어나", - "description": "일어나" + "description": "일어나." }, "debug": { "text": "디버그 정보 보여 줘", @@ -133,57 +133,57 @@ "reminder_show": { "text": "나에게 리콜 목록을 표시", "voice": "나에게 리콜 목록을 표시", - "description": "리콜 목록을 표시합니다" + "description": "리콜 목록을 표시합니다." }, "time_show": { "text": "지금 몇 시", "voice": "지금 몇 시", - "description": "지금 몇 시" + "description": "지금 몇 시." }, "timer_start": { "text": "______ 타이머 (설정)", "voice": "*duration 타이머 (설정)", - "description": "*duration 타이머 (설정)" + "description": "*duration 타이머 (설정)." }, "timer_show": { "text": "타이머 보여줄래", "voice": "타이머 보여줄래", - "description": "타이머 보여줄래" + "description": "타이머 보여줄래." }, "timer_stop": { "text": "타이머 정지", "voice": "타이머 정지", - "description": "타이머 정지" + "description": "타이머 정지." }, "timer_resume": { "text": "타이머 재시작", "voice": "타이머 재시작", - "description": "타이머 재시작" + "description": "타이머 재시작." }, "sc_play": { "text": "SoundCloud play ________", "voice": "SoundCloud play *query", - "description": "Play a song on SoundCloud" + "description": "Play a song on SoundCloud." }, "sc_pause": { "text": "SoundCloud pause/stop", "voice": "SoundCloud (pause)(post)(stop)(stock)", - "description": "Stop/pause SoundCoud playback" + "description": "Stop/pause SoundCoud playback." }, "sc_resume": { "text": "SoundCloud play", "voice": "SoundCloud (play)(resume)", - "description": "Resumes playback" + "description": "Resumes playback." }, "sc_replay": { "text": "SoundCloud replay", "voice": "SoundCloud replay", - "description": "Replays the current song on SoundCloud" + "description": "Replays the current song on SoundCloud." }, "light_action": { "text": "불 (흰/빨간/파란)색으로 (켜/꺼)줘", "voice": "불 :state *action (해)줘", - "description": "불 :state *action (해)줘" + "description": "불 :state *action (해)줘." } } } diff --git a/main.js b/main.js index b429846a2..c79e3e659 100644 --- a/main.js +++ b/main.js @@ -11,6 +11,9 @@ const BrowserWindow = electron.BrowserWindow const powerSaveBlocker = electron.powerSaveBlocker powerSaveBlocker.start('prevent-display-sleep') +// Launching the mirror in dev mode +const DevelopmentMode = process.argv[2] == "dev"; + // Load the smart mirror config var config; try{ @@ -59,7 +62,7 @@ function createWindow () { mainWindow.loadURL('file://' + __dirname + '/index.html') // Open the DevTools if run with "npm start dev" - if(process.argv[2] == "dev"){ + if(DevelopmentMode){ mainWindow.webContents.openDevTools(); } @@ -108,4 +111,4 @@ app.on('window-all-closed', function () { // No matter how the app is quit, we should clean up after ourselvs app.on('will-quit', function () { kwsProcess.kill() -}) \ No newline at end of file +}) diff --git a/package.json b/package.json index 0fbe3712a..cac0865f1 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "smart-mirror", - "version": "0.0.2", + "version": "0.0.3", "description": "The fairest of them all", "main": "main.js", "scripts": { "install": "bower install", "start": "electron main.js ", "microphone-debug" : "electron scripts/microphone-debug/main.js", + "train-model" : "electron scripts/train-model.js", "wiredep": "wiredep -s index.html" }, "repository": { @@ -37,6 +38,7 @@ "express": "^4.13.4", "fitbit-oauth2": "0.0.1", "fs": "0.0.2", + "hyperion-client": "1.0.3", "electron-json-storage": "2.0.0" } } diff --git a/sass/icesnow.scss b/sass/icesnow.scss deleted file mode 100644 index a53db7242..000000000 --- a/sass/icesnow.scss +++ /dev/null @@ -1,114 +0,0 @@ -@import "main"; - -@import url(https://fonts.googleapis.com/css?family=Work+Sans:300,400,500); - -body { - font-family: 'Work Sans', sans-serif; - font-weight: 300; -} - -.top-left { - float: right; - text-align: right; - display: -webkit-flex; - -webkit-flex-direction: column; - flex-direction: column; - float: right; - width: 420px; - .date { - -webkit-flex: 2; - flex: 2; - -webkit-order: 2; - order: 2; - width: 220px; - position: relative; - left: 200px; - } - ul.calendar { - -webkit-flex: 3; - flex: 3; - -webkit-order: 3; - order: 3; - } - .time { - -webkit-flex: 1; - flex: 1; - -webkit-order: 1; - order: 1; - } -} - -.top-right { - float: left; - text-align: left; - width: 265px; - .weather { - text-align: left; - width: 100%; - } -} - -/* - -Weather - -*/ - -.weather-today .tempreture { - font-size: 80px; -} - -.weather-week-descriptor span.ng-binding { - &:first-child { - font-size: 21px; - } - text-align: left; - word-spacing: normal; - display: inline-block; -} - -.weather-week-day { - margin-bottom: 5px; -} - -.weather { - .weather-today .icon, .weather-week-day .icon-small { - display: none; - } - .weather-today canvas, .weather-week-day canvas { - display: inline-block; - } - .weather-week-descriptor span { - padding-bottom: 7px; - margin-bottom: 7px; - display: block; - border-bottom: 2px solid #aaa; - &:last-child { - border-bottom: 0; - } - } -} - -/* -Calc -*/ - -.top-left ul.calendar { - font-size: 17px; - margin-top: 80px; - .day { - display: none; - } - .event-details .details { - color: #999; - } -} - -/* middle */ - -.middle-center { - justify-content: flex-end; - h1 { - font-size: 90px; - } -} \ No newline at end of file diff --git a/sass/main.scss b/sass/main.scss deleted file mode 100644 index f9a82b62a..000000000 --- a/sass/main.scss +++ /dev/null @@ -1,370 +0,0 @@ -@font-face { - font-family: "HelveticaNeue-UltraLight"; - src: url("../fonts/HelveticaNeue-UltraLight.ttf"); - /* EOT file for IE */ -} - -body { - background-color: black; - color: #fff; - font-family: 'HelveticaNeue-UltraLight', 'Open Sans', sans-serif; - font-weight: 300; - position: relative; -} - -h1, h2, h3, h4, h5 { - font-weight: 300; -} - -h1 { - font-size: 120px; -} - -dt { - font-weight: 600; -} - -/* Colors */ - -.light-grey { - color: #ccc; -} - -.grey { - color: #999; -} - -/* Displays */ - -.sleep-cover { - background-color: black; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 999; -} - -.container { - z-index: -1; - /* so things are still selectable */ - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; -} - -.listening, .interim-result { - font-family: 'Open Sans', sans-serif; -} - -.top-left { - float: left; -} - -.date { - font-size: 42px; -} - -.time { - font-size: 110px; -} - -.top-right { - float: right; -} - -.middle-center { - display: flex; - flex: 1; - align-items: stretch; - align-self: flex-start; - flex-direction: column; - width: 100%; - text-align: center; - justify-content: center; -} - -.bottom-center { - font-family: 'Open Sans', sans-serif; - width: 100%; - text-align: center; - margin-bottom: 20px; -} - -.commands { - width: 450px; - text-align: left; - margin-left: auto; - margin-right: auto; -} - -ul.calendar { - list-style: none; - font-size: 22px; - margin-left: 10px; - padding: 0; -} - -.calendar { - .event { - margin-bottom: 10px; - } - span { - display: inline-block; - &.day { - font-weight: bold; - width: 128px; - vertical-align: top; - } - &.summary { - max-width: 400px; - } - } - .event-details .details { - font-size: 12px; - padding-left: 135px; - font-family: 'Open Sans', sans-serif; - font-weight: lighter; - } -} - -.weather { - margin-left: auto; - display: inline-block; - text-align: right; - width: 230px; -} - -.weather-today .tempreture { - font-size: 60px; -} - -.weather-week-descriptor { - font-family: 'Open Sans', sans-serif; - font-size: 12px; - margin-left: auto; - margin-bottom: 10px; - text-align: justify; -} - -.weather-week { - margin-right: 10px; - font-size: 22px; - .day { - display: inline-block; - margin-right: 10px; - width: 40px; - } - .tempreture { - display: inline-block; - width: 60px; - } -} - -.weather { - .weather-today canvas, .weather-week-day canvas { - display: none; - } -} - -.traffic-information { - text-align: right; - margin-top: 10px; - margin-right: 10px; -} - -.time-to { - font-weight: bold; -} - -@keyframes reduce-dashoffset { - to { stroke-dashoffset: 0; } -} - -@keyframes increase-dashoffset { - from { stroke-dashoffset: 0; } -} - -.timer { - font-size: 120px; - position: relative; -} - -.timer-circle { - $size: 3.25em; - $stroke: 0.1em; - $pi: 3.1415926535; - - width: $size; - height: $size; - transform: rotate(-90deg) scaleY(-1); - margin: 20px auto; - display: block; - - .background, - .progress { - r: $size / 2 - $stroke; - cx: $size / 2; - cy: $size / 2; - fill: none; - stroke: #222; - stroke-width: $stroke; - } - - .progress { - stroke-dasharray: $pi * $size; - stroke-dashoffset: $pi * $size; - - stroke: white; - stroke-linecap: round; - animation-name: increase-dashoffset; - animation-timing-function: linear; - animation-fill-mode: forwards; - } - - &.finish .progress { - // animation-name: reduce-dashoffset; - // animation-duration: 1500ms; - // animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.335); - } -} - -.timer-countdown { - position: absolute; - top: 50%; - left: 50%; - transform: translateY(-50%) translateX(-50%); -} - -.timer-duration { - @extend .timer-countdown; - top: 75%; - font-size: 25%; -} - -.contents { - max-width: 100%; -} - -.gif { - height: 100%; -} - -.map { - height: 1080px; -} - -.contents-box { - text-align: center; - width: 100%; - position: relative; - overflow: hidden; - &:after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - -webkit-box-shadow: inset 0 0 10px 10px #000; - -moz-box-shadow: inset 0 0 10px 10px #000; - box-shadow: inset 0 0 10px 10px #000; - overflow: hidden; - } -} - -.color-block { - height: 200px; - width: 200px; - display: inline-block; - margin: 10px; - margin-bottom: 20px; -} - -.debug-info { - width: 500px; -} - -/* Animations */ - -.fade { - &.ng-hide { - opacity: 0; - } - &.ng-hide-remove, &.ng-hide-add { - display: block !important; - } - &.ng-hide-remove { - transition: all ease 1500ms; - } - &.ng-hide-add { - transition: all ease 500ms; - } -} - -.animate-grow { - max-height: 1280px !important; - &.ng-hide-add, &.ng-hide-remove { - transition: all linear 500ms; - } - &.ng-hide { - max-height: 0 !important; - } -} - -.dimmed { - color: #aaa; -} - -.xxsmall, .xsmall, .small { - font-family: "HelveticaNeue-Medium", sans-serif; - letter-spacing: 0; -} - -.xxsmall { - font-size: 15px; - .wi { - line-height: 15px; - } -} - -.xsmall { - font-size: 20px; -} - -.small { - font-size: 25px; -} - -.icon { - position: relative; - top: -10px; - display: inline-block; - font-size: 45px; - padding-right: 5px; - font-weight: 100; - margin-right: 10px; -} - -.icon-small { - position: relative; - display: inline-block; - font-size: 20px; - padding-left: 0px; - padding-right: -10px; - font-weight: 100; - width: 20px; -} - -.xkcd { - -webkit-filter: invert(100%); - max-width: 100%; -} diff --git a/scripts/bash-start.sh b/scripts/bash-start.sh new file mode 100755 index 000000000..b4c53b1c6 --- /dev/null +++ b/scripts/bash-start.sh @@ -0,0 +1,4 @@ +#!/bin/bash +export DISPLAY=:0 +export XAUTHORITY=/home/pi/.Xauthority +cd /home/pi/smart-mirror && npm start diff --git a/scripts/install.sh b/scripts/install.sh deleted file mode 100644 index 6bb428076..000000000 --- a/scripts/install.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/bash - -# Any subsequent(*) commands which fail will cause the shell script to exit immediately -set -e - -# Supported versions of node: v4.x, v5.x -NODE_VERSION="v4.*\|v5.*" - -# Terminal Colors -red=$'\e[1;31m' -grn=$'\e[1;32m' -yel=$'\e[1;33m' -blu=$'\e[1;34m' -mag=$'\e[1;35m' -cyn=$'\e[1;36m' -end=$'\e[0m' - -# Ensure we are using sudo -if [ "$(whoami)" != "root" ]; -then - echo "This script requires root permissions, try: sudo ./${0##*/} " - exit 0 -fi - -cat << "EOF" - ________ _____ ______ ________ ________ _________ -|\ ____\|\ _ \ _ \|\ __ \|\ __ \|\___ ___\ -\ \ \___|\ \ \\\__\ \ \ \ \|\ \ \ \|\ \|___ \ \_| - \ \_____ \ \ \\|__| \ \ \ __ \ \ _ _\ \ \ \ - \|____|\ \ \ \ \ \ \ \ \ \ \ \ \\ \| \ \ \ - ____\_\ \ \__\ \ \__\ \__\ \__\ \__\\ _\ \ \__\ - |\_________\|__| \|__|\|__|\|__|\|__|\|__| \|__| - \|_________| - - _____ ______ ___ ________ ________ ________ ________ -|\ _ \ _ \|\ \|\ __ \|\ __ \|\ __ \|\ __ \ -\ \ \\\__\ \ \ \ \ \ \|\ \ \ \|\ \ \ \|\ \ \ \|\ \ - \ \ \\|__| \ \ \ \ \ _ _\ \ _ _\ \ \\\ \ \ _ _\ - \ \ \ \ \ \ \ \ \ \\ \\ \ \\ \\ \ \\\ \ \ \\ \ - \ \__\ \ \__\ \__\ \__\\ _\\ \__\\ _\\ \_______\ \__\\ _\ - \|__| \|__|\|__|\|__|\|__|\|__|\|__|\|_______|\|__|\|__| - -EOF - -printf "%sThis script will install the smart-mirror and it's dependencies.\n" - -# Ensure the use would like to start the install -read -r -p "Would you like to continue? [y/N] " response -if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]] -then - printf "%sExcellent! ${red}Please do not exit this script until it is complete.${end}\n" -else - exit 1 -fi - -printf "%s\n" -read -r -p "[Requires Reboot] Would you like to automoticlly rotate your monitor? [y/N]" rotateResponse -if [[ $rotateResponse =~ ^([yY][eE][sS]|[yY])$ ]] -then - # Rotate Display (replace the display_rotate line with display_rotate=1) - sed -i -e '$a\ -\ -#Rotate the display (smart-mirror)\ -display_rotate=1' /boot/config.txt -fi - -printf "%s\nChecking for node...\n" -node --version | grep ${NODE_VERSION} -if [[ $? != 0 ]] ; -then - # Install Node - printf "%s{blu}Downloading node${end}\n" - wget https://nodejs.org/dist/v4.0.0/node-v4.0.0-linux-armv7l.tar.gz - tar -xvf node-v4.0.0-linux-armv7l.tar.gz - cd node-v4.0.0-linux-armv7l - - # Copy to /usr/local - printf "%s{blu}Installing node${end}\n" - sudo cp -R * /usr/local/ - - # Clean up after ourselvs - cd .. - rm node-v4.0.0-linux-armv7l.tar.gz - rm -R node-v4.0.0-linux-armv7l - printf "%s$(tput setaf 10)node is now installed!${end}\n" -else - printf "%s$(tput setaf 10)node is already installed, great job!${end}\n" -fi - -# Getting the code -printf "%s\n{blu}Cloning Git Repo${end}\n" -cd /home/$SUDO_USER -sudo -u $SUDO_USER git clone https://github.com/evancohen/smart-mirror.git -printf "%s\n$(tput setaf 10)smart-mirror code is now downloaded${end}\n" - -cd smart-mirror - -printf "%s{blu}generating config template${end}\n" -sudo -u $SUDO_USER cp config.example.js config.js - -# Install package to hide the mouse when inactive -printf "%s\n{blu}Installing unclutter${end}\n" -sudo apt-get install unclutter - -# Apply LXDE unclutter autostart -sed -i -e '$a\ -\ -#Hide the mouse when inactive (smart-mirror)\ -unclutter -idle 0.1 -root' /etc/xdg/lxsession/LXDE-pi/autostart - -printf "%s\n{blu}Installing smart-mirror dependencies...${end}\n" -printf "%s${yel}This may take a while. Go grab a beer :)${end}\n" -sudo -u $SUDO_USER npm install - -# The mirror is now installed, yay! -cat << "EOF" - - | The smart-mirror is now installed! - / \ - / _ \ Once you fill out your config you can start the mirror with: - |.o '.| npm start - |'._.'| - | | To lean more, check out the documentation at: - ,'| | |`. docs.smart-mirror.io - / | | | \ - |,-'--|--'-.| - -EOF -# ASCII art found on http://textart.io/ - -exit 0 \ No newline at end of file diff --git a/scripts/pi-install.sh b/scripts/pi-install.sh new file mode 100755 index 000000000..a9bd19f68 --- /dev/null +++ b/scripts/pi-install.sh @@ -0,0 +1,181 @@ +#!/bin/bash + +# Any subsequent(*) commands which fail will cause the shell script to exit immediately +set -e + +# Supported versions of node: v4.x, v5.x +NODE_MINIMUM_VERSION="v4.0.0" +NODE_STABLE_VERSION="6.x" + +# Compare node versions. +function check_version() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; } +# Check to see if a command exists (if something is installed) +function command_exists () { type "$1" &> /dev/null ;} + +# Terminal Colors +red=$'\e[1;31m' +grn=$'\e[1;32m' +yel=$'\e[1;33m' +blu=$'\e[1;34m' +mag=$'\e[1;35m' +cyn=$'\e[1;36m' +end=$'\e[0m' + +# Ensure we are using sudo +if [ "$(whoami)" != "root" ]; +then + echo "This script requires root permissions, try: sudo ./${0##*/} " + exit 0 +fi + +cat << "EOF" + ________ _____ ______ ________ ________ _________ +|\ ____\|\ _ \ _ \|\ __ \|\ __ \|\___ ___\ +\ \ \___|\ \ \\\__\ \ \ \ \|\ \ \ \|\ \|___ \ \_| + \ \_____ \ \ \\|__| \ \ \ __ \ \ _ _\ \ \ \ + \|____|\ \ \ \ \ \ \ \ \ \ \ \ \\ \| \ \ \ + ____\_\ \ \__\ \ \__\ \__\ \__\ \__\\ _\ \ \__\ + |\_________\|__| \|__|\|__|\|__|\|__|\|__| \|__| + \|_________| + + _____ ______ ___ ________ ________ ________ ________ +|\ _ \ _ \|\ \|\ __ \|\ __ \|\ __ \|\ __ \ +\ \ \\\__\ \ \ \ \ \ \|\ \ \ \|\ \ \ \|\ \ \ \|\ \ + \ \ \\|__| \ \ \ \ \ _ _\ \ _ _\ \ \\\ \ \ _ _\ + \ \ \ \ \ \ \ \ \ \\ \\ \ \\ \\ \ \\\ \ \ \\ \ + \ \__\ \ \__\ \__\ \__\\ _\\ \__\\ _\\ \_______\ \__\\ _\ + \|__| \|__|\|__|\|__|\|__|\|__|\|__|\|_______|\|__|\|__| + +EOF + +ARCH=$(uname -m) +# Check processor archetecture. +if [$ARCH != "armv7l" ]; then + printf "%s${red} Unupported device!${end} The smart-mirror only works on the Pi 2 and 3" + exit; +fi + +printf "%sThis script will install the smart-mirror and it's dependencies.\n" + +# Ensure the use would like to start the install +read -r -p "Would you like to continue? [y/N] " response +if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then + printf "%sExcellent! ${red}Please do not exit this script until it is complete.${end}\n" +else + exit 1 +fi + +# # Rotate the monitor +# printf "%s\n" +# read -r -p "Would you like to rotate your monitor? [y/N]" rotateResponse +# if [[ $rotateResponse =~ ^([yY][eE][sS]|[yY])$ ]]; then +# # Rotate Display (replace the display_rotate line with display_rotate=1) +# sed -i -e '$a\ +# \ +# #Rotate the display (smart-mirror)\ +# display_rotate=1' /boot/config.txt +# fi + +# Install native dependencies +printf "%s\n${blu}Installing native dependencies${end}\n" +sudo apt-get install curl wget git python-pyaudio python3-pyaudio sox unclutter + +# Check if we need to install or upgrade Node.js. +printf "%s\n${blu}Checking current Node installation${end}\n" +NODE_INSTALL=false +if command_exists node; then + NODE_CURRENT=$(node -v) + printf "%sMinimum Node version: $NODE_MINIMUM_VERSION\n" + printf "%sInstalled Node version: $NODE_CURRENT\n" + if check_version $NODE_MINIMUM_VERSION $NODE_CURRENT; then + NODE_INSTALL=true + # If Node is already running then abort + if pgrep "node" > /dev/null; then + printf "%s${red}A node process is currently running. Unable to upgrade for you.${end}\n" + printf "Exit all Node processes and then restart this installer." + exit; + fi + printf "%sLooks like you need an upgrade. Taking care of that for you.\n" + fi +else + printf "%sNo Node installation found. Installing it for you.\n"; + NODE_INSTALL=true +fi +# Upgrade node if it is out of date +if $NODE_INSTALL; then + printf "%sInstalling Node...\n" + curl -sL https://deb.nodesource.com/setup_$NODE_STABLE_VERSION | sudo -E bash - + sudo apt-get install -y nodejs + printf "%sNode installation complete.\n" +fi + +#Install magic mirror +cd /home/"$SUDO_USER" +if [ -d "$HOME/smart-mirror" ]; then + printf "%s${red}Looks like the smart mirror is already installed.${end}\n" + printf "%sPlease rename or remove the ${mag}smart-mirror${end} folder and re-run the installer.\n" + printf "%sIf you want to upgrade your smart mirror run ${cyn}git pull${end} from the ~/smart-mirror directory.\n" + exit; +fi + +# Getting the code +printf "%s\n${blu}Cloning smart-mirror Git Repo${end}\n" +if sudo -u "$SUDO_USER" git clone https://github.com/evancohen/smart-mirror.git; then + printf "%s${grn}smart-mirror code is now downloaded${end}\n" +else + printf "%s${red}Unable to clone smart-mirror :( ${end}\n" + exit; +fi + +# Generate config and install dependencies +cd smart-mirror || exit +printf "%s\n${blu}generating config template...${end}\n" +sudo -u "$SUDO_USER" cp config.example.js config.js + +# Install smart-mirror dependencies +printf "%s\n${blu}Installing smart-mirror dependencies...${end}\n" +printf "%s${yel}This may take a while. Go grab a beer :)${end}\n" +if sudo -u "$SUDO_USER" npm install; then + printf "%s${grn}Dependency installation complete!${end}\n" +else + printf "%s${red}Unable to install dependencies :( ${end}\n" + exit; +fi + +# Apply LXDE unclutter autostart (if we haven't already) +if ! grep -q '(smart-mirror)' /etc/xdg/lxsession/LXDE/autostart; then + sed -i -e '$a\ +\ +#Hide the mouse when inactive (smart-mirror)\ +unclutter -idle 0.1 -root' /etc/xdg/lxsession/LXDE/autostart +fi + +# Disable the screensaver (if we haven't already) +if ! grep -q '(smart-mirror)' /home/"$SUDO_USER"/.config/lxsession/LXDE-pi/autostart; then + sed -i -e '$a\ +\ +#Disable screen saver (smart-mirror)\ +@xset s 0 0\ +@xset s noblank\ +@xset s noexpose\ +@xset dpms 0 0 0' /home/"$SUDO_USER"/.config/lxsession/LXDE-pi/autostart +fi + + +# The mirror is now installed, yay! +cat << "EOF" + + | The smart-mirror is now installed! + / \ + / _ \ Once you fill out your config you can start the mirror with: + |.o '.| > npm start + |'._.'| Or if you are running over SSH: + | | > DISPLAY=:0 npm start + ,'| | |`. + / | | | \ To lean more, check out the documentation at: + |,-'--|--'-.| http://docs.smart-mirror.io + +EOF +# ASCII art found on http://textart.io/ + +exit 0 diff --git a/scripts/train-model.js b/scripts/train-model.js new file mode 100644 index 000000000..c16646d32 --- /dev/null +++ b/scripts/train-model.js @@ -0,0 +1,51 @@ +'use strict'; + +const electron = require('electron'); +// Module to control application life. +const app = electron.app; +// Module to create native browser window. +const BrowserWindow = electron.BrowserWindow; + +// Keep a global reference of the window object, if you don't, the window will +// be closed automatically when the JavaScript object is garbage collected. +let mainWindow; + +function createWindow () { + // Create the browser window. + mainWindow = new BrowserWindow({width: 1000, height: 800, webPreferences : {nodeIntegration: false}}); + + // and load the index.html of the app. + mainWindow.loadURL('https://snowboy.kitt.ai/hotword/47'); + + // Open the DevTools. + //mainWindow.webContents.openDevTools(); + + // Emitted when the window is closed. + mainWindow.on('closed', function() { + // Dereference the window object, usually you would store windows + // in an array if your app supports multi windows, this is the time + // when you should delete the corresponding element. + mainWindow = null; + }); +} + +// This method will be called when Electron has finished +// initialization and is ready to create browser windows. +app.on('ready', createWindow); + +// Quit when all windows are closed. +app.on('window-all-closed', function () { + // On OS X it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +app.on('activate', function () { + // On OS X it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (mainWindow === null) { + createWindow(); + } +});