├── .gitignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── EventedDatastore.js ├── LICENSE.md ├── README.md ├── components ├── api.js ├── arguments-handler.js ├── ascii_logo.js ├── dbFunctions.js ├── debug.js ├── demo_cards.json ├── notification.js ├── platform.js ├── server.js └── socketFunctions.js ├── config.json ├── hardware-layer ├── README.md ├── rc-switch-2.52.zip ├── receiver │ ├── helperfunctions.ino │ ├── output.ino │ └── receiver.ino ├── sender │ └── sender.ino └── single-arduino-tx-rx │ └── single-arduino-tx-rx.ino ├── index.js ├── other ├── IoT-433Mhz.json.postman_collection ├── backend_urls.json ├── pics │ ├── 433mhz-contact-door-sensor.png │ ├── 433mhz-pir-sensor.jpg │ ├── 433mhz-rf.jpg │ ├── RXB6-super-heterodyne.JPG │ ├── added-to-homescreen.JPG │ ├── iot-433mhz-cli-options.PNG │ ├── iot-433mhz-telegram-settings.PNG │ ├── logo.png │ ├── logo128x128.png │ ├── mosquito.psd │ ├── rc-433mhz-outplug-dip.png │ ├── rc-controller-433mhz-dip.png │ ├── start-iot-433mhz.PNG │ └── web-ui.gif └── schemes │ ├── arduino-transmitter-and-receiver.jpg │ ├── raspberry-pi-rxb6-kxd10036-on-3.3v.jpg │ ├── rpi-llc-receiver.jpg │ └── voltage-divider.jpg ├── package.json ├── test └── test.js ├── www ├── .jshintrc ├── 404.html ├── assets │ ├── demo_img │ │ ├── bedroom1.jpg │ │ ├── kitchen1.jpg │ │ ├── livingroom1.jpg │ │ └── raspberry-pi-2.png │ ├── img │ │ ├── 404-img.png │ │ ├── background-repeat-pattern.png │ │ ├── backgrounds │ │ │ ├── blur-bg1.jpg │ │ │ ├── blurred-water-surface.jpg │ │ │ ├── desk-blurred.png │ │ │ └── street-car-vehicle-blur.jpg │ │ ├── favicon.ico │ │ ├── heartbeat.gif │ │ ├── icon_128.png │ │ ├── icon_48.png │ │ ├── logo.png │ │ ├── logo.psd │ │ ├── menu_icon │ │ │ ├── about.png │ │ │ ├── add-card.png │ │ │ ├── code.png │ │ │ ├── house.svg │ │ │ ├── paper-plane.png │ │ │ ├── photo.svg │ │ │ ├── pin.svg │ │ │ ├── search.svg │ │ │ ├── simple-trigger.png │ │ │ ├── timer.png │ │ │ └── tools.svg │ │ ├── siren-sprite.png │ │ └── siren-sprite.psd │ └── sounds │ │ ├── button_tiny.aac │ │ ├── button_tiny.mp3 │ │ ├── button_tiny.ogg │ │ ├── door_bell.aac │ │ ├── door_bell.mp3 │ │ ├── door_bell.ogg │ │ ├── glass.aac │ │ ├── glass.mp3 │ │ ├── glass.ogg │ │ ├── navigate_stab_2.aac │ │ ├── navigate_stab_2.mp3 │ │ ├── navigate_stab_2.ogg │ │ ├── notification1.aac │ │ ├── notification1.mp3 │ │ ├── notification1.ogg │ │ ├── siren-sound.aac │ │ ├── siren-sound.mp3 │ │ ├── siren-sound.ogg │ │ ├── switch-toggle.aac │ │ ├── switch-toggle.mp3 │ │ ├── switch-toggle.ogg │ │ ├── water_droplet.aac │ │ ├── water_droplet.mp3 │ │ ├── water_droplet.ogg │ │ ├── water_droplet_2.aac │ │ ├── water_droplet_2.mp3 │ │ ├── water_droplet_2.ogg │ │ ├── water_droplet_3.aac │ │ ├── water_droplet_3.mp3 │ │ └── water_droplet_3.ogg ├── console.html ├── css │ └── dashboard-style.css ├── dist │ ├── css │ │ ├── add-to-homescreen │ │ │ └── addtohomescreen.css │ │ ├── bootstrap-material-design │ │ │ ├── bootstrap-material-design.css │ │ │ ├── ripples.min.css │ │ │ └── roboto.min.css │ │ ├── bootstrap │ │ │ └── bootstrap.css │ │ ├── css-circle-menu │ │ │ └── circle-menu.min.css │ │ ├── font-awesome.min.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── RobotoDraftBold.woff │ │ │ ├── RobotoDraftBold.woff2 │ │ │ ├── RobotoDraftItalic.woff │ │ │ ├── RobotoDraftItalic.woff2 │ │ │ ├── RobotoDraftMedium.woff │ │ │ ├── RobotoDraftMedium.woff2 │ │ │ ├── RobotoDraftRegular.woff │ │ │ ├── RobotoDraftRegular.woff2 │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── hover.css │ │ └── snackbar.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── RobotoDraftBold.woff │ │ ├── RobotoDraftBold.woff2 │ │ ├── RobotoDraftItalic.woff │ │ ├── RobotoDraftItalic.woff2 │ │ ├── RobotoDraftMedium.woff │ │ ├── RobotoDraftMedium.woff2 │ │ ├── RobotoDraftRegular.woff │ │ ├── RobotoDraftRegular.woff2 │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ └── js │ │ ├── EventEmitter.js │ │ ├── add-to-homescreen │ │ └── addtohomescreen.js │ │ ├── arrive.min.js │ │ ├── bootstrap-material-design │ │ ├── material.min.js │ │ └── ripples.min.js │ │ ├── bootstrap.min.js │ │ ├── browser.console.mirror.js │ │ ├── css-circle-menu │ │ └── circleMenu.js │ │ ├── favico-0.3.10.min.js │ │ ├── form-validator │ │ ├── brazil.dev.js │ │ ├── brazil.js │ │ ├── date.dev.js │ │ ├── date.js │ │ ├── file.dev.js │ │ ├── file.js │ │ ├── html5.dev.js │ │ ├── html5.js │ │ ├── jquery.form-validator.js │ │ ├── jquery.form-validator.min.js │ │ ├── jsconf.dev.js │ │ ├── jsconf.js │ │ ├── lang │ │ │ ├── cz.dev.js │ │ │ ├── cz.js │ │ │ ├── de.dev.js │ │ │ ├── de.js │ │ │ ├── es.dev.js │ │ │ ├── es.js │ │ │ ├── fr.dev.js │ │ │ ├── fr.js │ │ │ ├── it.dev.js │ │ │ └── it.js │ │ ├── location.dev.js │ │ ├── location.js │ │ ├── sanitize.dev.js │ │ ├── sanitize.js │ │ ├── security.dev.js │ │ ├── security.js │ │ ├── sweden.dev.js │ │ ├── sweden.js │ │ ├── theme-default.css │ │ ├── theme-default.min.css │ │ ├── toggleDisabled.dev.js │ │ ├── toggleDisabled.js │ │ ├── uk.dev.js │ │ └── uk.js │ │ ├── ion.sound.min.js │ │ ├── jquery.min.js │ │ ├── jquery.mixitup.min.js │ │ ├── moment.min.js │ │ ├── mustache.min.js │ │ ├── notie.js │ │ ├── shake.js │ │ └── snackbar.js ├── js │ ├── RFcodes.js │ ├── bg-handler.js │ ├── client.socketing.js │ ├── eventing.js │ ├── main.js │ └── templating.js ├── manifest.json ├── templates │ ├── about.mustache │ ├── assignCode.mustache │ ├── cards.mustache │ ├── ignoredCodes.mustache │ ├── newCardForm.mustache │ └── settings.mustache └── views │ └── index.html └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | DB/ 3 | www/uploads/ 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // The plugin looks for a .jshintrc file in the same directory as the source 3 | // file you're prettifying (or any directory above if it doesn't exist, or in 4 | // your home folder if everything else fails) and uses those options along 5 | // the default ones. 6 | 7 | // Details: https://github.com/victorporof/Sublime-JSHint#using-your-own-jshintrc-options 8 | // Example: https://github.com/jshint/jshint/blob/master/examples/.jshintrc 9 | // Documentation: http://www.jshint.com/docs/options/ 10 | "esnext": true, 11 | "globals": {}, 12 | "globalstrict": false, 13 | "quotmark": true, 14 | "undef": true, 15 | "unused": true, 16 | "devel": true, 17 | "node": true 18 | } 19 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | other/ 2 | DB/ 3 | www/uploads/ 4 | /webHooksDB.json -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | sudo: required 4 | 5 | node_js: 6 | - "0.10" 7 | - "0.12" 8 | - "4.4.7" 9 | - "6.2.1" 10 | 11 | cache: 12 | directories: 13 | - node_modules 14 | -------------------------------------------------------------------------------- /EventedDatastore.js: -------------------------------------------------------------------------------- 1 | var util = require('util') 2 | var EventEmitter = require('events').EventEmitter 3 | var Datastore = require('nedb') 4 | 5 | function EventedDatastore (options) { 6 | var self = this 7 | 8 | // Add EventEmitter capabilities 9 | self.__events = new EventEmitter() 10 | 11 | options = options || {} 12 | 13 | var autoLoadOption = options.autoload || false 14 | options.autoload = false 15 | 16 | Datastore.call(self, options) 17 | options.autoload = autoLoadOption 18 | self.autoload = autoLoadOption 19 | 20 | // Temporary properties used to collect data for event emissions 21 | self.__removedDocs = null 22 | self.__modifications = null 23 | 24 | if (self.autoload) { 25 | // Wait till the next tick to allow time for event listeners to be attached 26 | process.nextTick(function () { 27 | self.loadDatabase(options.onload || function (err) { 28 | if (err) { 29 | throw err 30 | } 31 | }) 32 | }) 33 | } 34 | } 35 | 36 | util.inherits(EventedDatastore, Datastore) 37 | 38 | EventedDatastore.prototype.on = function (eventType, listener) { 39 | return this.__events.on(eventType, listener) 40 | } 41 | 42 | EventedDatastore.prototype.once = function (eventType, listener) { 43 | return this.__events.once(eventType, listener) 44 | } 45 | 46 | EventedDatastore.prototype.listeners = function (eventType) { 47 | return this.__events.listeners(eventType) 48 | } 49 | 50 | EventedDatastore.prototype.off = function (eventType, listener) { 51 | return this.__events.removeListener(eventType, listener) 52 | } 53 | 54 | EventedDatastore.prototype._insert = function (newDoc, cb) { 55 | var callback = cb || function () {} 56 | 57 | var self = this 58 | 59 | var eventedCallback = function (err, newDocs) { 60 | if (err) { 61 | return callback(err, newDocs) 62 | } 63 | 64 | var newDocsArr = util.isArray(newDocs) ? newDocs : [newDocs] 65 | 66 | // Ensure there are listeners registered before making a bunch of unnecessary function calls to `emit` 67 | if (self.listeners('inserted').length > 0) { 68 | newDocsArr.forEach(function (newDoc) { 69 | self.__events.emit('inserted', newDoc) 70 | }) 71 | } 72 | 73 | return callback(null, newDocs) 74 | } 75 | 76 | return Datastore.prototype._insert.call(self, newDoc, eventedCallback) 77 | } 78 | 79 | EventedDatastore.prototype._update = function (query, updateQuery, options, cb) { 80 | var self = this 81 | 82 | if (typeof options === 'function') { 83 | cb = options 84 | options = {} 85 | } 86 | var callback = cb || function () {} 87 | 88 | var eventedCallback = function (err, numReplaced) { 89 | if (err) { 90 | return callback(err) 91 | } 92 | 93 | if (self.__modifications && self.__modifications.length > 0) { 94 | var modifications = self.__modifications 95 | 96 | // Remove the temporary property 97 | self.__modifications = null 98 | 99 | // Ensure there are listeners registered before making a bunch of unnecessary function calls to `emit` 100 | if (self.listeners('updated').length > 0) { 101 | modifications.forEach(function (mod) { 102 | self.__events.emit('updated', mod.newDoc, mod.oldDoc) 103 | }) 104 | } 105 | } 106 | 107 | return callback(null, numReplaced) 108 | } 109 | 110 | return Datastore.prototype._update.call(self, query, updateQuery, options, eventedCallback) 111 | } 112 | 113 | EventedDatastore.prototype.updateIndexes = function (modifications) { 114 | // Add a new temporary property 115 | this.__modifications = modifications 116 | 117 | return Datastore.prototype.updateIndexes.apply(this, arguments) 118 | } 119 | 120 | EventedDatastore.prototype._remove = function (query, options, cb) { 121 | var self = this 122 | 123 | if (typeof options === 'function') { 124 | cb = options 125 | options = {} 126 | } 127 | var callback = cb || function () {} 128 | 129 | // Add a new temporary property 130 | if (!self.__removedDocs) { 131 | self.__removedDocs = [] 132 | } 133 | 134 | var eventedCallback = function (err, numRemoved) { 135 | if (err) { 136 | return callback(err) 137 | } 138 | 139 | if (self.__removedDocs && self.__removedDocs.length > 0) { 140 | var removedDocs = self.__removedDocs 141 | 142 | // Remove the temporary property 143 | self.__removedDocs = null 144 | 145 | // Ensure there are listeners registered before making a bunch of unnecessary function calls to `emit` 146 | if (self.listeners('removed').length > 0) { 147 | removedDocs.forEach(function (oldDoc) { 148 | self.__events.emit('removed', oldDoc) 149 | }) 150 | } 151 | } 152 | 153 | return callback(null, numRemoved) 154 | } 155 | 156 | return Datastore.prototype._remove.call(self, query, options, eventedCallback) 157 | } 158 | 159 | if (typeof Datastore.prototype._removedExpiredDocuments === 'function') { 160 | EventedDatastore.prototype._removeExpiredDocuments = function (docs, cb) { 161 | var self = this 162 | 163 | var callback = cb || function () {} 164 | 165 | // Add a new temporary property 166 | if (!self.__removedDocs) { 167 | self.__removedDocs = [] 168 | } 169 | 170 | var eventedCallback = function (err, numExpired) { 171 | if (err) { 172 | return callback(err) 173 | } 174 | 175 | if (self.__removedDocs && self.__removedDocs.length > 0) { 176 | var removedDocs = self.__removedDocs 177 | 178 | // Remove the temporary property 179 | self.__removedDocs = null 180 | 181 | // Ensure there are listeners registered before making a bunch of unnecessary function calls to `emit` 182 | if (self.listeners('removed').length > 0) { 183 | removedDocs.forEach(function (oldDoc) { 184 | self.__events.emit('removed', oldDoc) 185 | }) 186 | } 187 | } 188 | 189 | return callback(null, numExpired) 190 | } 191 | 192 | return Datastore.prototype._removeExpiredDocuments.call(self, docs, eventedCallback) 193 | } 194 | } 195 | 196 | EventedDatastore.prototype.removeFromIndexes = function (doc, cb) { 197 | if (this.__removedDocs) { 198 | if (util.isArray(doc)) { 199 | this.__removedDocs.push.apply(this.__removedDocs, doc) 200 | } else { 201 | this.__removedDocs.push(doc) 202 | } 203 | } 204 | 205 | return Datastore.prototype.removeFromIndexes.apply(this, arguments) 206 | } 207 | 208 | module.exports = EventedDatastore 209 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License (MIT) 2 | 3 | Copyright (c) 2016 Rocco Musolino, hackerstribe.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /components/arguments-handler.js: -------------------------------------------------------------------------------- 1 | var argv = require('yargs') 2 | .usage('Usage: iot-433mhz -s [serialPort] -d [debug] -p [serverPort] -u [username] -P [password]') 3 | .help('help') 4 | .alias('help', 'h') 5 | .option('debug', { 6 | alias: 'd', 7 | demand: false, 8 | describe: 'Debug Mode (aka Verbose mode).', 9 | type: 'boolean' 10 | }) 11 | .default('debug', undefined) 12 | .option('serialport', { 13 | alias: 's', 14 | demand: false, 15 | describe: 'Arduino Serial Port.', 16 | type: 'string' 17 | }) 18 | .option('username', { 19 | alias: 'u', 20 | demand: false, 21 | describe: 'Username for Web Interface and API', 22 | type: 'string' 23 | }) 24 | .option('password', { 25 | alias: 'P', 26 | demand: false, 27 | describe: 'Password for Web Interface and API', 28 | type: 'string' 29 | }) 30 | .implies('username', 'password') 31 | .implies('password', 'username') 32 | .option('port', { 33 | alias: 'p', 34 | demand: false, 35 | describe: 'HTTP Server Port.', 36 | type: 'number' 37 | }) 38 | .example('iot-433mhz -d false', 'Choose to enable or not Debug Mode') 39 | .example('iot-433mhz -s COM4', 'Start the system using arduino on the specified serial port') 40 | .example('iot-433mhz -u username -P password', 'Start the system setting custom username and password') 41 | .example('iot-433mhz -p 8080', 'Start the system server on the specified port') 42 | .epilogue('@Author: Rocco Musolino - github.com/roccomuso/iot-433mhz - @Copyright 2016') 43 | .argv 44 | 45 | // console.log(argv); 46 | 47 | module.exports = argv 48 | -------------------------------------------------------------------------------- /components/ascii_logo.js: -------------------------------------------------------------------------------- 1 | var figlet = require('figlet') 2 | var config = require('../config.json') 3 | 4 | module.exports = function (module_callback) { 5 | figlet(config.app_title, function (err, data) { 6 | if (err) { 7 | console.log('Something went wrong...') 8 | console.dir(err) 9 | return 10 | } 11 | module_callback(data) // then print logo con console 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /components/debug.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config.json') 3 | var chalk = require('chalk') 4 | 5 | function noop () {} 6 | var firstCall = false 7 | 8 | var PROJECT_NAME = config.debug_namespace // debug environment 9 | 10 | module.exports = function (customName) { 11 | if (!module.parent) throw Error('module.parent not defined') 12 | 13 | if (process.env.DEBUG === undefined && config.debug === true) { process.env.DEBUG = PROJECT_NAME + ':*' } 14 | 15 | if (process.env.DEBUG && !(process.env.DEBUG).match(new RegExp(config.namespace)) && !firstCall) { console.log(chalk.bgBlue.bold('DEBUG not enabled on the ' + config.namespace + ' namespace!')) } 16 | 17 | if (!firstCall) { 18 | console.log(chalk.bgCyan.bold('Debug:', (!!process.env.DEBUG))) 19 | firstCall = true 20 | } 21 | 22 | if (process.env.DEBUG) { 23 | var sector = PROJECT_NAME + ':' + (customName || path.basename(module.parent.filename)) 24 | return require('debug')(sector) 25 | } else { return noop } 26 | } 27 | -------------------------------------------------------------------------------- /components/demo_cards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "active": true, 4 | "date": 1453057691, 5 | "headline": "Welcome!", 6 | "shortname": "welcome", 7 | "card_body": "Welcome to the Iot-433mhz Dashboard. We've made for you a clear design.
From here you can interact with almost every 433-mhz based device! Just keep in mind that every single card in this page represents a device. A device can be one of three different types: switch, alarm, info.", 8 | "background_color": "#ffd180", 9 | "img": "/assets/demo_img/kitchen1.jpg", 10 | "room": "kitchen", 11 | "type": "info", 12 | "device": {} 13 | }, 14 | { 15 | "active": true, 16 | "date": 1452989005, 17 | "headline": "I'm an info card!", 18 | "shortname": "welcome-info-card-1", 19 | "card_body": "This is an example of info card!
You can add new card from the beautiful circular menu on the bottom right of the screen! and for every card you can choose the color you like the most and upload whatever header image you want.", 20 | "background_color": "#FFFF8D", 21 | "img": false, 22 | "room": "bathroom", 23 | "type": "info", 24 | "device": {} 25 | }, 26 | { 27 | "active": true, 28 | "date": 1452989005, 29 | "headline": "Alarm in Bedroom", 30 | "shortname": "welcome-alarm-1", 31 | "card_body": "An alarm device is like a switch one, with the exception that you can't trigger it! The Alarm is triggered when the associated radio code is received.", 32 | "background_color": "#ccff90", 33 | "img": "/assets/demo_img/bedroom1.jpg", 34 | "room": "bedroom", 35 | "type": "alarm", 36 | "device": { 37 | "last_alert": false, 38 | "notification_sound": true, 39 | "armed": true, 40 | "trigger_code": 3333 41 | } 42 | }, 43 | { 44 | "active": true, 45 | "date": 1452989005, 46 | "headline": "Ignore Noisy codes", 47 | "shortname": "welcome-info-card-2", 48 | "card_body": "If you get flooded by a code, you can hit the 'Ignore' button once it pop out...
Tip: Usually a single RF button can generates multiple radio codes according to several reasons (pressure or waves noise), make sure to select the most common one for your switch/alarm card.", 49 | "background_color": "#80d8ff", 50 | "img": "/assets/demo_img/raspberry-pi-2.png", 51 | "room": "living-room", 52 | "type": "info", 53 | "device": {} 54 | }, 55 | { 56 | "active": true, 57 | "date": 1452989005, 58 | "headline": "Switch Card", 59 | "shortname": "welcome-switch-card", 60 | "card_body": "This is a switch card example! You can easily use a 433mhz-based remote controller and catch the button codes directly in this dashboard! Once you got some codes, you're ready to associate them to the ON and OFF buttons, it's easy as programming your TV!", 61 | "background_color": "#fafafa", 62 | "img": "/assets/demo_img/livingroom1.jpg", 63 | "room": "living-room", 64 | "type": "switch", 65 | "device": { 66 | "on_code": 1111, 67 | "off_code": 2222, 68 | "notification_sound": true, 69 | "is_on": false 70 | } 71 | } 72 | ] -------------------------------------------------------------------------------- /components/notification.js: -------------------------------------------------------------------------------- 1 | var request = require('request') 2 | var config = require('../config.json') 3 | var debug = require('./debug.js')() 4 | 5 | function _getRemoteUrl (url_name) { 6 | return new Promise(function (resolve, reject) { 7 | request(config.backend_urls, function (error, response, body) { 8 | if (!error && response.statusCode == 200) { 9 | try { 10 | var data = JSON.parse(body) 11 | if (url_name in data) resolve(data[url_name]) 12 | else reject('Can\'t get the remote URL') 13 | } catch (err) { 14 | reject(err) 15 | } 16 | } else reject(error.toString() + ' ' + response.statusCode) 17 | }) 18 | }) 19 | } 20 | 21 | function _postRequestJSON (url, json_data, uid, callback) { 22 | request({ 23 | method: 'POST', 24 | uri: url + '/' + uid, // always attach the uid as entrypoint. 25 | strictSSL: false, // because we're using a self-signed certificate 26 | headers: {'cache-control': 'no-cache', 'Content-Type': 'application/json'}, 27 | body: JSON.stringify(json_data) 28 | }, 29 | callback 30 | ) 31 | } 32 | 33 | module.exports = function (dbFunctions, webHooks) { 34 | var t = +new Date() 35 | 36 | var methods = { 37 | adviceTelegram: function (card) { 38 | return new Promise(function (resolve, reject) { 39 | // advice user through telegram 40 | dbFunctions.isTelegramEnabled().then(function (outcome) { 41 | if (outcome) { 42 | _getRemoteUrl('telegram_backend').then(function (url) { 43 | dbFunctions.getIotUID().then(function (uid) { 44 | // card.iot_uid = uid; // si può eliminare. passato in URL 45 | _postRequestJSON(url, card, uid, function (error, response, body) { 46 | if (error || response.statusCode !== 200) return reject('HTTP failed: ' + error) 47 | debug('Telegram Notification sent! - Server responded with:', body) 48 | resolve(card) 49 | }) 50 | }) 51 | }).catch(function (err) { reject(err) }) 52 | } else { 53 | debug('Telegram Notification disabled. Menu > Settings.') 54 | resolve(card) 55 | } 56 | }).catch(function (err) { reject(err) }) 57 | }) 58 | }, 59 | adviceEmail: function (card) { 60 | return new Promise(function (resolve, reject) { 61 | // TODO 62 | resolve(card) 63 | }) 64 | }, 65 | adviceWebHook: function (card) { 66 | return new Promise(function (resolve, reject) { 67 | // WebHook call (alarm triggered) 68 | webHooks.trigger('alarmTriggered', card) 69 | resolve(card) 70 | }) 71 | }, 72 | alarmAdviseAll: function (card) { 73 | // advice telegram, email, webhooks 74 | var now = +new Date() 75 | var elapsed = now - t 76 | if (elapsed > config.notificationDelay * 1000) { 77 | methods.adviceEmail(card) 78 | .then(methods.adviceTelegram) 79 | .then(methods.adviceWebHook) 80 | .catch(function (err) { 81 | console.error(err) 82 | }) 83 | t = now 84 | } else debug('Notification delayed') // 1 notification every 5 sec 85 | }, 86 | webHookCodeDetected: function (codeData) { 87 | // webHook call (code detected) 88 | webHooks.trigger('newCode', codeData) 89 | } 90 | } 91 | 92 | // expose methods 93 | return methods 94 | } 95 | -------------------------------------------------------------------------------- /components/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express') // Get the module 2 | var app = express() 3 | var bodyParser = require('body-parser') 4 | var server = require('http').Server(app) 5 | var io = require('socket.io')(server) 6 | var config = require('../config.json') // config file 7 | var basicAuth = require('basic-auth') 8 | var cons = require('consolidate') 9 | var cors = require('cors') 10 | 11 | var corsOptions = { 12 | origin: function(origin, cb) { 13 | cb(null, true) 14 | }, 15 | optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204 16 | credentials: true 17 | } 18 | 19 | module.exports = function (argv, _cb) { 20 | // Setting up parameters passed by CLI 21 | if (argv.username && argv.password) { config.username = argv.username.trim(); config.password = argv.password.trim() } 22 | config.server_port = argv.port || process.env.PORT || config.server_port 23 | 24 | // Starting Server 25 | server.listen(config.server_port) 26 | console.info('Server started on', getLocalIPAddress(), '- Port', config.server_port) 27 | 28 | // enable cors 29 | app.use(cors(corsOptions)) 30 | 31 | // Auth function 32 | var auth = function (req, res, next) { 33 | function unauthorized (res) { 34 | res.set('WWW-Authenticate', 'Basic realm=Authorization Required') 35 | return res.status(401).send('Unauthorized') 36 | } 37 | 38 | var user = basicAuth(req) 39 | 40 | if (!user || !user.name || !user.pass) { 41 | return unauthorized(res) 42 | } 43 | 44 | if (user.name === config.username && user.pass === config.password) { 45 | return next() 46 | } else { 47 | return unauthorized(res) 48 | } 49 | } 50 | 51 | // set authentication middleware 52 | app.use(auth) 53 | 54 | // set middleware 55 | app.use(bodyParser.json()) 56 | 57 | // assign the mustache engine to .html files 58 | app.engine('html', cons.mustache) 59 | 60 | // set .html as the default extension 61 | app.set('view engine', 'html') 62 | app.set('views', __dirname + '/../www/views') 63 | 64 | // API and Web Server + Socket part 65 | _cb({http: app, io: io}) 66 | } 67 | 68 | // utility function 69 | function getLocalIPAddress () { 70 | // synchronous method 71 | var interfaces = require('os').networkInterfaces() 72 | var IPs = [] 73 | for (var devName in interfaces) { 74 | var iface = interfaces[devName] 75 | 76 | for (var i = 0; i < iface.length; i++) { 77 | var alias = iface[i] 78 | if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) { IPs.push(alias.address) } 79 | } 80 | } 81 | 82 | if (IPs.length === 1) return IPs[0] 83 | else if (IPs.length > 1) return IPs.toString() 84 | else return '0.0.0.0' 85 | } 86 | -------------------------------------------------------------------------------- /components/socketFunctions.js: -------------------------------------------------------------------------------- 1 | var debug = require('./debug.js')() 2 | 3 | // For socket sending methods see http://stackoverflow.com/questions/10058226/send-response-to-all-clients-except-sender-socket-io 4 | 5 | module.exports = function (io, rf433mhz, dbFunctions) { 6 | var clients = [] // Store sockets 7 | 8 | // private methods 9 | var _methods = { 10 | 11 | onGetInitCards: function (socket_id) { 12 | clients.forEach(function (sock) { 13 | if (sock.id === socket_id) { 14 | // Sending the cards stored in db.CARDS 15 | methods.asyncEmitInitCards(sock) 16 | } 17 | }) 18 | }, 19 | onIgnoreCode: function (code) { 20 | // ignore the specified code, isIgnored = true in DB 21 | dbFunctions.ignoreCode(code, true).then(function (ok) { 22 | debug('code ignored: ', code) 23 | }).catch(function (err) { 24 | console.error(err) 25 | }) 26 | }, 27 | onRemoveIgnoreCode: function (code) { 28 | // make the code no more ignored (putting isIgnored = false) 29 | dbFunctions.ignoreCode(code, false).then(function (ok) { 30 | debug('code no more ignored: ', code) 31 | }).catch(function (err) { 32 | console.error(err) 33 | }) 34 | }, 35 | onSwitchCommuted: function (data) { 36 | // send the RF code | data = {card_id: '...', set: 'on/off'} 37 | dbFunctions.getSwitchCodes(data.card_id).then(function (switch_codes) { 38 | var codeToSend = (data.set === 'on') ? switch_codes.on_code : switch_codes.off_code 39 | var is_on = (data.set === 'on') 40 | rf433mhz.send(codeToSend, function (err, out) { 41 | if (err) return console.log('Error:', err) 42 | debug('Code ' + codeToSend + ' sent!') 43 | // let's commute the switch on UI 44 | io.emit('uiSwitchToggle', {card_id: data.card_id, set: is_on, sound: switch_codes.sound}) 45 | // save it on DB 46 | dbFunctions.setSwitchStatus(data.card_id, is_on).then(function (numDocs) { 47 | debug('DB records updated:', numDocs) 48 | }, function (err) { console.error(err) }) 49 | }) 50 | }).catch(function (err) { 51 | console.error(err) 52 | }) 53 | }, 54 | onDeviceShake: function () { 55 | debug('Randomizing Cards on the UI') 56 | io.emit('randomizeCards') 57 | }, 58 | onDeleteCard: function (_id) { 59 | // delete the card with the given _id 60 | dbFunctions.deleteCard({_id: _id}).then(function () { 61 | // UI refreshed by db.CARDS on Remove listener in index.js 62 | }).catch(function (err) { 63 | if (err) console.error(err) 64 | }) 65 | }, 66 | onMuteCard: function (_id) { 67 | // mute/unmute card 68 | dbFunctions.muteCard(_id).then(function (result) { 69 | // update every UI 70 | io.emit('uiMuteStatus', {card_id: _id, notification_sound: result}) 71 | }).catch(function (err) { 72 | if (err) console.error(err) 73 | }) 74 | }, 75 | onArmDisarm: function (_id) { 76 | // arm/disarm card 77 | dbFunctions.armCard({_id: _id}).then(function (result) { 78 | // update every UI 79 | io.emit('uiArmStatus', {card_id: _id, is_armed: result.is_armed}) 80 | }).catch(function (err) { 81 | if (err) console.error(err) 82 | }) 83 | } 84 | } 85 | 86 | // exposed methods 87 | var methods = { 88 | 89 | onConnection: function (client_socket) { // single user socket 90 | debug('Client connected via socket.io:', client_socket.id) 91 | 92 | // Save the user: 93 | clients.push(client_socket) 94 | client_socket.on('disconnect', function () { 95 | clients.splice(clients.indexOf(client_socket), 1) 96 | debug('Client disconnected:', client_socket.id) 97 | // remaining clients 98 | // clients.forEach(function(sckt){ console.log(sckt.id);} ); 99 | }) 100 | 101 | // Sending the cards stored in db.CARDS 102 | methods.asyncEmitInitCards(client_socket) 103 | 104 | // Listen for socket events 105 | client_socket.on('shakeOccurred', _methods.onDeviceShake) 106 | client_socket.on('getInitCards', _methods.onGetInitCards) 107 | client_socket.on('ignoreCode', _methods.onIgnoreCode) 108 | client_socket.on('removeIgnoreCode', _methods.onRemoveIgnoreCode) 109 | client_socket.on('switchCommuted', _methods.onSwitchCommuted) 110 | client_socket.on('deleteCard', _methods.onDeleteCard) 111 | client_socket.on('muteCard', _methods.onMuteCard) 112 | client_socket.on('arm_disarm', _methods.onArmDisarm) 113 | }, 114 | asyncEmitInitCards: function (socket) { 115 | dbFunctions.getAllCards().then(function (cards) { 116 | if (socket) { socket.emit('initCards', cards) } else { io.emit('initCards', cards) } 117 | }).catch(function (err) { 118 | console.error(err) 119 | }) 120 | } 121 | 122 | } 123 | 124 | return methods 125 | } 126 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_title": "IoT-433Mhz", 3 | "debug_namespace": "iot-433mhz", 4 | "debug": true, 5 | "username": "root", 6 | "password": "root", 7 | "arduino_baudrate": 9600, 8 | "server_port": 8080, 9 | "db_compact_interval": 12, 10 | "backend_urls": "https://raw.githubusercontent.com/roccomuso/iot-433mhz/master/other/backend_urls.json", 11 | "notificationDelay": 5, 12 | "platforms":{ 13 | "rpi": { 14 | "sniff-pin": 2, 15 | "transmitter-pin": 0, 16 | "debounce-delay": 500, 17 | "use-external-arduino": true 18 | }, 19 | "windows": { 20 | 21 | }, 22 | "linux": { 23 | 24 | }, 25 | "mac":{ 26 | 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /hardware-layer/README.md: -------------------------------------------------------------------------------- 1 | The Hardware-layer sketches are built for **Arduino** and only if running on platform different from RPi (or on RPI but with the use-external-arduino option setted on true in the config.json file). 2 | 3 | In this directory you'll find sender, receiver and a single-arduino-tx-rx that's a single sketch both for sending and receiving with only one arduino board. 4 | 5 | Use the latter in production environment. 6 | 7 | # RC-Switch 8 | 9 | Every sketch is based on the library ([RC-Switch](https://github.com/sui77/rc-switch)) used to receive and send radio signal through the Arduino. This will most likely work with all popular low cost power outlet sockets, Gas sensor, PIR/Door sensors. 10 | Supported devices should have one of the following chipset: *SC5262 / SC5272, HX2262 / HX2272, PT2262 / PT2272, EV1527, RT1527, FP1527 or HS1527*. 11 | 12 | # Recommended TX/RX Hardware 13 | 14 | Personally my advice is to use an Arduino nano with a common 433mhz radio transmitter and a 433mhz receiver. Both this modules can be bought with few euros on Ebay or Aliexpress. 15 | 16 | ![cheap tx rx modules 433mhz](https://github.com/roccomuso/iot-433mhz/blob/master/other/pics/433mhz-rf.jpg "cheap tx rx modules 433mhz") 17 | 18 | better and recommended modules are this **'Super-heterodyne' RXB6**: 19 | 20 | ![RXB6 super heterodyne](https://github.com/roccomuso/iot-433mhz/blob/master/other/pics/RXB6-super-heterodyne.JPG "RXB6 super heterodyne") 21 | 22 | ## Antenna length 23 | 24 | Actually, many 433MHz circuit boards have a coil with a few windings between the circuitry and the solder pad marked ANT. The XD-RF-5V commonly available on the market has a three winding coil with a 5mm diameter. *5mm x 3 x PI accounts* for almost 5cm, so the external part of the antenna should be around 12cm to come to a total length of quarter lambda. 25 | 26 | I always find antenna's to be black magic, but for me 12cm seemed to work! Around the internet the most common antenna's length seems to be 17.3 cm. 27 | 28 | You can even do some more spires if you want or ... if you don't want to make the antenna by yourself, just buy it somewhere. 29 | 30 | ### Outlet sockets 31 | 32 | Referring to RCSwitch library, there are generally few common kinds of outlet switches (working on a Frequency 433.92Mhz). From a 10 pole DIP switch to the one with two rotary (or sliding) switches with four setting possibilities each. 33 | 34 | These are the recommended kind with the 10 pole DIP: 35 | 36 | ![Outlet Sockets 433mhz](https://github.com/roccomuso/iot-433mhz/blob/master/other/pics/rc-433mhz-outplug-dip.png "outlet sockets 433mhz") 37 | 38 | ![433mhz Remote Controller](https://github.com/roccomuso/iot-433mhz/blob/master/other/pics/rc-controller-433mhz-dip.png "Remote controller") 39 | 40 | ### Other devices 41 | 42 | Gas Sensor, Pir Sensor, Door/contact sensor. 43 | 44 | ![433mhz PIR Sensor](https://github.com/roccomuso/iot-433mhz/blob/master/other/pics/433mhz-pir-sensor.jpg "PIR Sensor") 45 | 46 | ![433mhz Door sensor](https://github.com/roccomuso/iot-433mhz/blob/master/other/pics/433mhz-contact-door-sensor.png "Door Sensor") 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /hardware-layer/rc-switch-2.52.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/hardware-layer/rc-switch-2.52.zip -------------------------------------------------------------------------------- /hardware-layer/receiver/helperfunctions.ino: -------------------------------------------------------------------------------- 1 | static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength){ 2 | static char bin[64]; 3 | unsigned int i=0; 4 | 5 | while (Dec > 0) { 6 | bin[32+i++] = (Dec & 1 > 0) ? '1' : '0'; 7 | Dec = Dec >> 1; 8 | } 9 | 10 | for (unsigned int j = 0; j< bitLength; j++) { 11 | if (j >= bitLength - i) { 12 | bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; 13 | }else { 14 | bin[j] = '0'; 15 | } 16 | } 17 | bin[bitLength] = '\0'; 18 | 19 | return bin; 20 | } 21 | -------------------------------------------------------------------------------- /hardware-layer/receiver/output.ino: -------------------------------------------------------------------------------- 1 | void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) { 2 | 3 | if (decimal == 0) { 4 | Serial.print("Unknown encoding."); 5 | } else { 6 | char* b = dec2binWzerofill(decimal, length); 7 | Serial.print("Decimal: "); 8 | Serial.print(decimal); 9 | Serial.print(" ("); 10 | Serial.print( length ); 11 | Serial.print("Bit) Binary: "); 12 | Serial.print( b ); 13 | Serial.print(" Tri-State: "); 14 | Serial.print( bin2tristate( b) ); 15 | Serial.print(" PulseLength: "); 16 | Serial.print(delay); 17 | Serial.print(" microseconds"); 18 | Serial.print(" Protocol: "); 19 | Serial.println(protocol); 20 | } 21 | 22 | Serial.print("Raw data: "); 23 | for (int i=0; i<= length*2; i++) { 24 | Serial.print(raw[i]); 25 | Serial.print(","); 26 | } 27 | Serial.println(); 28 | Serial.println(); 29 | } 30 | 31 | 32 | static char* bin2tristate(char* bin) { 33 | char returnValue[50]; 34 | int pos = 0; 35 | int pos2 = 0; 36 | while (bin[pos]!='\0' && bin[pos+1]!='\0') { 37 | if (bin[pos]=='0' && bin[pos+1]=='0') { 38 | returnValue[pos2] = '0'; 39 | } else if (bin[pos]=='1' && bin[pos+1]=='1') { 40 | returnValue[pos2] = '1'; 41 | } else if (bin[pos]=='0' && bin[pos+1]=='1') { 42 | returnValue[pos2] = 'F'; 43 | } else { 44 | return "not applicable"; 45 | } 46 | pos = pos+2; 47 | pos2++; 48 | } 49 | returnValue[pos2] = '\0'; 50 | return returnValue; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /hardware-layer/receiver/receiver.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Example for receiving 3 | 4 | https://github.com/sui77/rc-switch 5 | 6 | How to connect the 433mhz receiver to arduino: GND - 5V - pin D2 7 | 8 | */ 9 | 10 | #include 11 | 12 | RCSwitch mySwitch = RCSwitch(); 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | mySwitch.enableReceive(0); // Receiver on inerrupt 0 => that is pin #2 17 | } 18 | 19 | void loop() { 20 | if (mySwitch.available()) { 21 | output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol()); 22 | mySwitch.resetAvailable(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hardware-layer/sender/sender.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Simple example for sender 3 | 4 | https://github.com/sui77/rc-switch 5 | 6 | How to connect the 433mhz transmitter to Arduino: GND - 5V - pin D10 7 | 8 | */ 9 | 10 | #include 11 | 12 | RCSwitch mySwitch = RCSwitch(); 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | 17 | // Transmitter is connected to Arduino Pin #10 18 | mySwitch.enableTransmit(10); 19 | } 20 | 21 | 22 | void invia(){ 23 | 24 | if (Serial.available() > 0){ 25 | 26 | String val = Serial.readStringUntil('\n'); 27 | 28 | Serial.println(val); 29 | if (val) 30 | { 31 | 32 | mySwitch.send(val.toInt(), 24); 33 | Serial.println(val+" inviato!"); 34 | /* MODI DISPONIBILI D'INVIO */ 35 | /* See Example: TypeA_WithDIPSwitches */ 36 | //mySwitch.switchOn("11111", "00100"); 37 | //delay(5000); 38 | //mySwitch.switchOff("11111", "00100"); 39 | //delay(1000); 40 | 41 | /* Same switch as above, but using decimal code */ 42 | //mySwitch.send(5201, 24); // on 43 | //delay(5000); 44 | //mySwitch.send(5204, 24); // off 45 | //delay(1000); 46 | 47 | /* Same switch as above, but using binary code */ 48 | //mySwitch.send("000000000001010001010001"); // on 49 | //delay(5000); 50 | //mySwitch.send("000000000001010001010100"); // off 51 | //delay(1000); 52 | 53 | 54 | 55 | } 56 | 57 | } 58 | 59 | 60 | } 61 | 62 | 63 | 64 | void loop() { 65 | 66 | invia(); 67 | 68 | 69 | /* 70 | String content = ""; 71 | char character; 72 | 73 | while(Serial.available()) { 74 | character = Serial.read(); 75 | content.concat(character); 76 | delay(15); 77 | } 78 | 79 | if (content != "") { 80 | Serial.println(content); 81 | } 82 | */ 83 | 84 | } 85 | 86 | -------------------------------------------------------------------------------- /hardware-layer/single-arduino-tx-rx/single-arduino-tx-rx.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Simple example for both sender and receiver 3 | 4 | - Dependencies: 5 | https://github.com/sui77/rc-switch/releases/latest (RC 433mhz library) 6 | https://github.com/bblanchon/ArduinoJson (Arduino JSON Library) 7 | 8 | How to connect the 433mhz receiver to arduino: GND - 5V - pin D2 9 | How to connect the 433mhz transmitter to Arduino: GND - 5V - pin D10 10 | 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | RCSwitch mySwitch = RCSwitch(); 17 | 18 | void setup() { 19 | Serial.begin(9600); 20 | 21 | // Transmitter is connected to Arduino Pin #10 22 | mySwitch.enableTransmit(10); 23 | // Receiver connected on inerrupt 0 => that is pin #2 24 | mySwitch.enableReceive(0); 25 | 26 | } 27 | 28 | 29 | void invia(){ 30 | 31 | 32 | if (Serial.available() > 0){ 33 | 34 | String val = Serial.readStringUntil('\n'); 35 | 36 | Serial.println(val); 37 | if (val) 38 | { 39 | 40 | mySwitch.send(val.toInt(), 24); 41 | 42 | // Serial response 43 | StaticJsonBuffer<100> jsonBuffer; 44 | 45 | JsonObject& root = jsonBuffer.createObject(); 46 | root["type"] = "signal"; 47 | root["status"] = "sent"; 48 | root["code"] = val; 49 | 50 | 51 | root.printTo(Serial); 52 | Serial.println(); // send a \n 53 | 54 | //Serial.println("@ "+val+" sent!"); 55 | 56 | 57 | /* ALTRI MODI DISPONIBILI D'INVIO */ 58 | /* See Example: TypeA_WithDIPSwitches */ 59 | //mySwitch.switchOn("11111", "00100"); 60 | //delay(5000); 61 | //mySwitch.switchOff("11111", "00100"); 62 | //delay(1000); 63 | 64 | /* Same switch as above, but using decimal code */ 65 | //mySwitch.send(5201, 24); // on 66 | //delay(5000); 67 | //mySwitch.send(5204, 24); // off 68 | //delay(1000); 69 | 70 | /* Same switch as above, but using binary code */ 71 | //mySwitch.send("000000000001010001010001"); // on 72 | //delay(5000); 73 | //mySwitch.send("000000000001010001010100"); // off 74 | //delay(1000); 75 | 76 | 77 | } 78 | 79 | } 80 | 81 | 82 | } 83 | 84 | void ricevi(){ 85 | 86 | if (mySwitch.available()) { 87 | 88 | int value = mySwitch.getReceivedValue(); 89 | 90 | StaticJsonBuffer<200> jsonBuffer; 91 | JsonObject& root = jsonBuffer.createObject(); 92 | 93 | if (value == 0) { 94 | Serial.print("Unknown encoding"); 95 | root["type"] = "signal"; 96 | root["status"] = "unknown"; 97 | root["code"] = value; 98 | root["bitlength"] = mySwitch.getReceivedBitlength(); 99 | root["protocol"] = mySwitch.getReceivedProtocol(); 100 | 101 | root.printTo(Serial); 102 | Serial.println(); // send a \n 103 | 104 | } else { 105 | 106 | // Serial response 107 | 108 | root["type"] = "signal"; 109 | root["status"] = "received"; 110 | root["code"] = mySwitch.getReceivedValue(); 111 | root["bitlength"] = mySwitch.getReceivedBitlength(); 112 | root["protocol"] = mySwitch.getReceivedProtocol(); 113 | 114 | root.printTo(Serial); 115 | Serial.println(); // send a \n 116 | 117 | } 118 | 119 | mySwitch.resetAvailable(); 120 | } 121 | 122 | /* // Advanced debug 123 | if (mySwitch.available()) { 124 | output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol()); 125 | mySwitch.resetAvailable(); 126 | } 127 | */ 128 | } 129 | 130 | void loop() { 131 | 132 | invia(); 133 | 134 | ricevi(); 135 | 136 | } 137 | 138 | -------------------------------------------------------------------------------- /other/backend_urls.json: -------------------------------------------------------------------------------- 1 | { 2 | "telegram_backend": "https://hackerstribe.com:2096/telegram/advise" 3 | } 4 | -------------------------------------------------------------------------------- /other/pics/433mhz-contact-door-sensor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/433mhz-contact-door-sensor.png -------------------------------------------------------------------------------- /other/pics/433mhz-pir-sensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/433mhz-pir-sensor.jpg -------------------------------------------------------------------------------- /other/pics/433mhz-rf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/433mhz-rf.jpg -------------------------------------------------------------------------------- /other/pics/RXB6-super-heterodyne.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/RXB6-super-heterodyne.JPG -------------------------------------------------------------------------------- /other/pics/added-to-homescreen.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/added-to-homescreen.JPG -------------------------------------------------------------------------------- /other/pics/iot-433mhz-cli-options.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/iot-433mhz-cli-options.PNG -------------------------------------------------------------------------------- /other/pics/iot-433mhz-telegram-settings.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/iot-433mhz-telegram-settings.PNG -------------------------------------------------------------------------------- /other/pics/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/logo.png -------------------------------------------------------------------------------- /other/pics/logo128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/logo128x128.png -------------------------------------------------------------------------------- /other/pics/mosquito.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/mosquito.psd -------------------------------------------------------------------------------- /other/pics/rc-433mhz-outplug-dip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/rc-433mhz-outplug-dip.png -------------------------------------------------------------------------------- /other/pics/rc-controller-433mhz-dip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/rc-controller-433mhz-dip.png -------------------------------------------------------------------------------- /other/pics/start-iot-433mhz.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/start-iot-433mhz.PNG -------------------------------------------------------------------------------- /other/pics/web-ui.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/pics/web-ui.gif -------------------------------------------------------------------------------- /other/schemes/arduino-transmitter-and-receiver.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/schemes/arduino-transmitter-and-receiver.jpg -------------------------------------------------------------------------------- /other/schemes/raspberry-pi-rxb6-kxd10036-on-3.3v.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/schemes/raspberry-pi-rxb6-kxd10036-on-3.3v.jpg -------------------------------------------------------------------------------- /other/schemes/rpi-llc-receiver.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/schemes/rpi-llc-receiver.jpg -------------------------------------------------------------------------------- /other/schemes/voltage-divider.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/other/schemes/voltage-divider.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iot-433mhz", 3 | "version": "1.0.6", 4 | "description": "Node server to handle 433mhz outlets and sensors.", 5 | "main": "index.js", 6 | "preferGlobal": true, 7 | "bin": { 8 | "iot-433mhz": "./index.js" 9 | }, 10 | "scripts": { 11 | "start": "node index.js", 12 | "test": "npm run integration_test && npm run security_check", 13 | "integration_test": "NODE_ENV=development mocha --timeout=5000 test/**/*.js", 14 | "security_check": "nsp check" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/roccomuso/iot-433mhz" 19 | }, 20 | "bugs": { 21 | "url": "https://github.com/roccomuso/iot-433mhz/issues" 22 | }, 23 | "keywords": [ 24 | "iot", 25 | "433mhz", 26 | "domotic", 27 | "arduino", 28 | "raspberry", 29 | "433", 30 | "rc-switch", 31 | "pir" 32 | ], 33 | "author": "Rocco Musolino", 34 | "license": "MIT", 35 | "dependencies": { 36 | "async": "^2.6.0", 37 | "basic-auth": "1.1.0", 38 | "body-parser": "^1.18.2", 39 | "chalk": "^2.4.0", 40 | "console-mirroring": "^1.0.3", 41 | "consolidate": "0.14.5", 42 | "cors": "^2.8.4", 43 | "debug": "^3.1.0", 44 | "dotlocal": "^1.1.0", 45 | "express": "^4.16.3", 46 | "figlet": "^1.2.0", 47 | "multer": "^1.3.0", 48 | "mustache": "2.2.1", 49 | "nedb": "1.8.0", 50 | "node-webhooks": "1.2.4", 51 | "prompt": "1.0.0", 52 | "request": "^2.85.0", 53 | "semver": "^5.3.0", 54 | "serialport": "4.0.6", 55 | "socket.io": "2.0.4", 56 | "validator": "4.5.0", 57 | "virtual-serialport": "^4.0.1", 58 | "yargs": "4.8.1" 59 | }, 60 | "devDependencies": { 61 | "chai": "^3.5.0", 62 | "mocha": "^3.2.0", 63 | "nsp": "^3.2.1" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var expect = chai.expect; 3 | var should = chai.should(); 4 | var debug = require('debug')('test-suite'); 5 | var http = require('http'); 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | var iot; 9 | var emitter; 10 | 11 | // IMPLEMENTED TESTS: 12 | 13 | /* 14 | 15 | # Start 16 | - Should start iot-433mhz. 17 | 18 | # Auth 19 | - Should not authenticate with wrong login credentials 20 | - Should authenticate with right login credentials 21 | 22 | # Serial Port 23 | - Should open the virtual serial port. 24 | - Should send a command over serial and get a response. 25 | 26 | # Socket 27 | - Should enstablish a socket.io connection 28 | 29 | # API 30 | /api/settings/get - get 31 | /api/system/get/uid - get 32 | /api/system/new/uid - get 33 | /api/system/telegram/enable - get 34 | /api/system/telegram/disable - get 35 | /api/system/email/enable - get 36 | /api/system/email/disable - get 37 | /api/code/send/:code - get 38 | /api/codes/ignored - get 39 | /api/codes/all - get 40 | /api/codes/available - get 41 | /api/cards/all - get 42 | /api/cards/get/:shortname - get 43 | /api/cards/delete/:shortname - get 44 | /api/cards/arm-all - post 45 | /api/cards/disarm-all - post 46 | /api/alarm/:shortname/arm - get 47 | /api/alarm/:shortname/disarm - get 48 | /api/switch/:shortname/on - get 49 | /api/switch/:shortname/off - get 50 | /api/switch/:shortname/toggle - get 51 | /api/webhook/get - get 52 | /api/webhook/get/:webHookShortname - get 53 | /api/webhook/add/:webHookShortname - post 54 | /api/webhook/delete/:webHookShortname - get 55 | /api/webhook/delete/:webHookShortname - post 56 | /api/webhook/trigger/:webHookShortname - post 57 | 58 | # UI (API & Socket.io conn.) 59 | - Should send a random code (and have socket.io getting it) 60 | - Should ... 61 | 62 | 63 | */ 64 | 65 | 66 | describe('Auth >', function() { 67 | 68 | before(function(done) { 69 | // TODO 70 | iot = require('../index'); 71 | done(); 72 | 73 | }); 74 | 75 | it('...', function(done) { 76 | // TODO 77 | done(); 78 | }); 79 | 80 | }); 81 | 82 | describe('Serial Port >', function(){ 83 | 84 | after(function(done) { 85 | // TODO 86 | done(); 87 | }); 88 | 89 | }); 90 | -------------------------------------------------------------------------------- /www/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // The plugin looks for a .jshintrc file in the same directory as the source 3 | // file you're prettifying (or any directory above if it doesn't exist, or in 4 | // your home folder if everything else fails) and uses those options along 5 | // the default ones. 6 | 7 | // Details: https://github.com/victorporof/Sublime-JSHint#using-your-own-jshintrc-options 8 | // Example: https://github.com/jshint/jshint/blob/master/examples/.jshintrc 9 | // Documentation: http://www.jshint.com/docs/options/ 10 | "browser": true, 11 | "esnext": true, 12 | "globals": {}, 13 | "globalstrict": false, 14 | "quotmark": true, 15 | "undef": true, 16 | "unused": true, 17 | "devel": true, 18 | "jquery": true 19 | } 20 | -------------------------------------------------------------------------------- /www/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | IoT 433Mhz (404) 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 | 41 |

Page not Found!

42 |

Get Back in HomePage.

43 | 44 | 45 |
46 | 47 | 48 | 49 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /www/assets/demo_img/bedroom1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/demo_img/bedroom1.jpg -------------------------------------------------------------------------------- /www/assets/demo_img/kitchen1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/demo_img/kitchen1.jpg -------------------------------------------------------------------------------- /www/assets/demo_img/livingroom1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/demo_img/livingroom1.jpg -------------------------------------------------------------------------------- /www/assets/demo_img/raspberry-pi-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/demo_img/raspberry-pi-2.png -------------------------------------------------------------------------------- /www/assets/img/404-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/404-img.png -------------------------------------------------------------------------------- /www/assets/img/background-repeat-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/background-repeat-pattern.png -------------------------------------------------------------------------------- /www/assets/img/backgrounds/blur-bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/backgrounds/blur-bg1.jpg -------------------------------------------------------------------------------- /www/assets/img/backgrounds/blurred-water-surface.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/backgrounds/blurred-water-surface.jpg -------------------------------------------------------------------------------- /www/assets/img/backgrounds/desk-blurred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/backgrounds/desk-blurred.png -------------------------------------------------------------------------------- /www/assets/img/backgrounds/street-car-vehicle-blur.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/backgrounds/street-car-vehicle-blur.jpg -------------------------------------------------------------------------------- /www/assets/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/favicon.ico -------------------------------------------------------------------------------- /www/assets/img/heartbeat.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/heartbeat.gif -------------------------------------------------------------------------------- /www/assets/img/icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/icon_128.png -------------------------------------------------------------------------------- /www/assets/img/icon_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/icon_48.png -------------------------------------------------------------------------------- /www/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/logo.png -------------------------------------------------------------------------------- /www/assets/img/logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/logo.psd -------------------------------------------------------------------------------- /www/assets/img/menu_icon/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/menu_icon/about.png -------------------------------------------------------------------------------- /www/assets/img/menu_icon/add-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/menu_icon/add-card.png -------------------------------------------------------------------------------- /www/assets/img/menu_icon/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/menu_icon/code.png -------------------------------------------------------------------------------- /www/assets/img/menu_icon/house.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/assets/img/menu_icon/paper-plane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/menu_icon/paper-plane.png -------------------------------------------------------------------------------- /www/assets/img/menu_icon/photo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/assets/img/menu_icon/pin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/assets/img/menu_icon/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/assets/img/menu_icon/simple-trigger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/menu_icon/simple-trigger.png -------------------------------------------------------------------------------- /www/assets/img/menu_icon/timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/menu_icon/timer.png -------------------------------------------------------------------------------- /www/assets/img/menu_icon/tools.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/assets/img/siren-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/siren-sprite.png -------------------------------------------------------------------------------- /www/assets/img/siren-sprite.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/img/siren-sprite.psd -------------------------------------------------------------------------------- /www/assets/sounds/button_tiny.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/button_tiny.aac -------------------------------------------------------------------------------- /www/assets/sounds/button_tiny.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/button_tiny.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/button_tiny.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/button_tiny.ogg -------------------------------------------------------------------------------- /www/assets/sounds/door_bell.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/door_bell.aac -------------------------------------------------------------------------------- /www/assets/sounds/door_bell.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/door_bell.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/door_bell.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/door_bell.ogg -------------------------------------------------------------------------------- /www/assets/sounds/glass.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/glass.aac -------------------------------------------------------------------------------- /www/assets/sounds/glass.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/glass.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/glass.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/glass.ogg -------------------------------------------------------------------------------- /www/assets/sounds/navigate_stab_2.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/navigate_stab_2.aac -------------------------------------------------------------------------------- /www/assets/sounds/navigate_stab_2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/navigate_stab_2.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/navigate_stab_2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/navigate_stab_2.ogg -------------------------------------------------------------------------------- /www/assets/sounds/notification1.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/notification1.aac -------------------------------------------------------------------------------- /www/assets/sounds/notification1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/notification1.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/notification1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/notification1.ogg -------------------------------------------------------------------------------- /www/assets/sounds/siren-sound.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/siren-sound.aac -------------------------------------------------------------------------------- /www/assets/sounds/siren-sound.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/siren-sound.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/siren-sound.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/siren-sound.ogg -------------------------------------------------------------------------------- /www/assets/sounds/switch-toggle.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/switch-toggle.aac -------------------------------------------------------------------------------- /www/assets/sounds/switch-toggle.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/switch-toggle.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/switch-toggle.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/switch-toggle.ogg -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet.aac -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet.ogg -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet_2.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet_2.aac -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet_2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet_2.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet_2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet_2.ogg -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet_3.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet_3.aac -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet_3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet_3.mp3 -------------------------------------------------------------------------------- /www/assets/sounds/water_droplet_3.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/assets/sounds/water_droplet_3.ogg -------------------------------------------------------------------------------- /www/console.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Console Mirroring 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /www/dist/css/bootstrap-material-design/ripples.min.css: -------------------------------------------------------------------------------- 1 | .withripple{position:relative}.ripple-container{position:absolute;top:0;left:0;z-index:1;width:100%;height:100%;overflow:hidden;border-radius:inherit;pointer-events:none}.ripple{position:absolute;width:20px;height:20px;margin-left:-10px;margin-top:-10px;border-radius:100%;background-color:#000;background-color:rgba(0,0,0,.05);-webkit-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1);-webkit-transform-origin:50%;-ms-transform-origin:50%;-o-transform-origin:50%;transform-origin:50%;opacity:0;pointer-events:none}.ripple.ripple-on{-webkit-transition:opacity .15s ease-in 0s,-webkit-transform .5s cubic-bezier(.4,0,.2,1) .1s;-o-transition:opacity .15s ease-in 0s,-o-transform .5s cubic-bezier(.4,0,.2,1) .1s;transition:opacity .15s ease-in 0s,transform .5s cubic-bezier(.4,0,.2,1) .1s;opacity:.1}.ripple.ripple-out{-webkit-transition:opacity .1s linear 0s!important;-o-transition:opacity .1s linear 0s!important;transition:opacity .1s linear 0s!important;opacity:0} 2 | /*# sourceMappingURL=ripples.min.css.map */ -------------------------------------------------------------------------------- /www/dist/css/bootstrap-material-design/roboto.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:RobotoDraft;src:local('RobotoDraft'),local('RobotoDraft-Regular'),local('Roboto-Regular'),url(../fonts/RobotoDraftRegular.woff2) format('woff2'),url(../fonts/RobotoDraftRegular.woff) format('woff')}@font-face{font-family:RobotoDraft;font-weight:500;src:local('RobotoDraft Medium'),local('RobotoDraft-Medium'),local('Roboto-Medium'),url(../fonts/RobotoDraftMedium.woff2) format('woff2'),url(../fonts/RobotoDraftMedium.woff) format('woff')}@font-face{font-family:RobotoDraft;font-weight:700;src:local('RobotoDraft Bold'),local('RobotoDraft-Bold'),local('Roboto-Bold'),url(../fonts/RobotoDraftBold.woff2) format('woff2'),url(../fonts/RobotoDraftBold.woff) format('woff')}@font-face{font-family:RobotoDraft;font-style:italic;src:local('RobotoDraft Italic'),local('RobotoDraft-Italic'),local('Roboto-Italic'),url(../fonts/RobotoDraftItalic.woff2) format('woff2'),url(../fonts/RobotoDraftItalic.woff) format('woff')} 2 | /*# sourceMappingURL=roboto.min.css.map */ -------------------------------------------------------------------------------- /www/dist/css/css-circle-menu/circle-menu.min.css: -------------------------------------------------------------------------------- 1 | .c-circle-nav__toggle,.c-circle-nav__toggle span{transition:background .3s;-webkit-transition:background .3s}.c-circle-nav{position:fixed;bottom:12px;right:12px;z-index:1000;width:48px;height:48px;border-radius:24px}@media (min-width:480px)and (min-height:480px){.c-circle-nav{width:96px;height:96px;border-radius:48px}}.c-circle-nav__items{display:block;list-style:none;position:absolute;z-index:90;margin:0;padding:0}.c-circle-nav__item{display:block;position:absolute;top:0;left:0;width:48px;height:48px;border-radius:24px;opacity:0;-webkit-transition-property:-webkit-transform,opacity;transition-property:transform,opacity;-webkit-transition-duration:.3s,.3s;transition-duration:.3s,.3s;-webkit-transition-timing-function:cubic-bezier(.35,-.59,.47,.97);transition-timing-function:cubic-bezier(.35,-.59,.47,.97)}.c-circle-nav__item:nth-child(1){-webkit-transition-delay:.4s;transition-delay:.4s}.c-circle-nav__item:nth-child(2){-webkit-transition-delay:.3s;transition-delay:.3s}.c-circle-nav__item:nth-child(3){-webkit-transition-delay:.2s;transition-delay:.2s}.c-circle-nav__item:nth-child(4){-webkit-transition-delay:.1s;transition-delay:.1s}.c-circle-nav__item:nth-child(5){-webkit-transition-delay:0s;transition-delay:0s}.c-circle-nav.is-active .c-circle-nav__item{-webkit-transition-timing-function:cubic-bezier(.35,.03,.47,1.59);transition-timing-function:cubic-bezier(.35,.03,.47,1.59);opacity:1}.c-circle-nav.is-active .c-circle-nav__item:nth-child(1){-webkit-transition-delay:0s;transition-delay:0s;-webkit-transform:translate(-144px,0);-ms-transform:translate(-144px,0);transform:translate(-144px,0)}@media (min-width:480px)and (min-height:480px){.c-circle-nav__item{width:96px;height:96px;border-radius:48px}.c-circle-nav.is-active .c-circle-nav__item:nth-child(1){-webkit-transform:translate(-288px,0);-ms-transform:translate(-288px,0);transform:translate(-288px,0)}}.c-circle-nav.is-active .c-circle-nav__item:nth-child(2){-webkit-transition-delay:.1s;transition-delay:.1s;-webkit-transform:translate(-134px,-56px);-ms-transform:translate(-134px,-56px);transform:translate(-134px,-56px)}@media (min-width:480px)and (min-height:480px){.c-circle-nav.is-active .c-circle-nav__item:nth-child(2){-webkit-transform:translate(-267px,-111px);-ms-transform:translate(-267px,-111px);transform:translate(-267px,-111px)}}.c-circle-nav.is-active .c-circle-nav__item:nth-child(3){-webkit-transition-delay:.2s;transition-delay:.2s;-webkit-transform:translate(-102px,-102px);-ms-transform:translate(-102px,-102px);transform:translate(-102px,-102px)}@media (min-width:480px)and (min-height:480px){.c-circle-nav.is-active .c-circle-nav__item:nth-child(3){-webkit-transform:translate(-204px,-204px);-ms-transform:translate(-204px,-204px);transform:translate(-204px,-204px)}}.c-circle-nav.is-active .c-circle-nav__item:nth-child(4){-webkit-transition-delay:.3s;transition-delay:.3s;-webkit-transform:translate(-56px,-134px);-ms-transform:translate(-56px,-134px);transform:translate(-56px,-134px)}@media (min-width:480px)and (min-height:480px){.c-circle-nav.is-active .c-circle-nav__item:nth-child(4){-webkit-transform:translate(-111px,-267px);-ms-transform:translate(-111px,-267px);transform:translate(-111px,-267px)}}.c-circle-nav.is-active .c-circle-nav__item:nth-child(5){-webkit-transition-delay:.4s;transition-delay:.4s;-webkit-transform:translate(0,-144px);-ms-transform:translate(0,-144px);transform:translate(0,-144px)}.c-circle-nav__link{display:block;width:100%;height:100%;border-radius:24px;box-shadow:inset 0 0 0 2px #fff}@media (min-width:480px)and (min-height:480px){.c-circle-nav.is-active .c-circle-nav__item:nth-child(5){-webkit-transform:translate(0,-288px);-ms-transform:translate(0,-288px);transform:translate(0,-288px)}.c-circle-nav__link{border-radius:48px}}.c-circle-nav__link img{display:block;max-width:100%;height:auto}.c-circle-nav__link:hover{box-shadow:inset 0 0 0 2px #ff283c}.c-circle-nav__toggle{display:block;position:absolute;z-index:100;margin:0;padding:0;width:48px;height:48px;background-color:#ff283c;font:inherit;font-size:0;text-indent:-9999px;border-radius:24px;cursor:pointer;border:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;box-shadow:none}@media (min-width:480px)and (min-height:480px){.c-circle-nav__toggle{width:96px;height:96px;border-radius:48px}}.c-circle-nav__toggle.is-active,.c-circle-nav__toggle:focus,.c-circle-nav__toggle:hover{outline:0;background-color:#c10012}.c-circle-nav__toggle span,.c-circle-nav__toggle span::after,.c-circle-nav__toggle span::before{display:block;position:absolute;height:4px;background:#fff;border-radius:1px}.c-circle-nav__toggle span{top:22px;left:10px;right:10px}@media (min-width:480px)and (min-height:480px){.c-circle-nav__toggle span,.c-circle-nav__toggle span::after,.c-circle-nav__toggle span::before{height:8px;border-radius:2px}.c-circle-nav__toggle span{top:44px;left:20px;right:20px}}.c-circle-nav__toggle span::after,.c-circle-nav__toggle span::before{left:0;width:100%;content:"";-webkit-transition-duration:.3s,.3s;transition-duration:.3s,.3s;-webkit-transition-delay:.3s,0s;transition-delay:.3s,0s}.c-circle-nav__toggle span::before{top:-8px;-webkit-transition-property:top,-webkit-transform;transition-property:top,transform}.c-circle-nav__toggle span::after{bottom:-8px;-webkit-transition-property:bottom,-webkit-transform;transition-property:bottom,transform}@media (min-width:480px)and (min-height:480px){.c-circle-nav__toggle span::before{top:-16px}.c-circle-nav__toggle span::after{bottom:-16px}}.c-circle-nav__toggle.is-active span{background:0 0}.c-circle-nav__toggle.is-active span::before{top:0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);-webkit-transition-delay:0s,.3s;transition-delay:0s,.3s}.c-circle-nav__toggle.is-active span::after{bottom:0;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transition-delay:0s,.3s;transition-delay:0s,.3s}.c-mask{position:fixed;top:0;left:0;z-index:900;visibility:hidden;opacity:0;width:100%;height:100%;background-color:rgba(0,0,0,.8);-webkit-transition:opacity .3s,visibility .3s;transition:opacity .3s,visibility .3s}.c-mask.is-active{opacity:1;visibility:visible} -------------------------------------------------------------------------------- /www/dist/css/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /www/dist/css/fonts/RobotoDraftBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/RobotoDraftBold.woff -------------------------------------------------------------------------------- /www/dist/css/fonts/RobotoDraftBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/RobotoDraftBold.woff2 -------------------------------------------------------------------------------- /www/dist/css/fonts/RobotoDraftItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/RobotoDraftItalic.woff -------------------------------------------------------------------------------- /www/dist/css/fonts/RobotoDraftItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/RobotoDraftItalic.woff2 -------------------------------------------------------------------------------- /www/dist/css/fonts/RobotoDraftMedium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/RobotoDraftMedium.woff -------------------------------------------------------------------------------- /www/dist/css/fonts/RobotoDraftMedium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/RobotoDraftMedium.woff2 -------------------------------------------------------------------------------- /www/dist/css/fonts/RobotoDraftRegular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/RobotoDraftRegular.woff -------------------------------------------------------------------------------- /www/dist/css/fonts/RobotoDraftRegular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/RobotoDraftRegular.woff2 -------------------------------------------------------------------------------- /www/dist/css/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /www/dist/css/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /www/dist/css/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /www/dist/css/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/css/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /www/dist/css/snackbar.css: -------------------------------------------------------------------------------- 1 | #snackbar-container { 2 | position: fixed; 3 | left: 20px; 4 | bottom: 0; 5 | z-index: 99999; 6 | } 7 | .snackbar { 8 | overflow: hidden; 9 | clear: both; 10 | min-width: 288px; 11 | max-width: 568px; 12 | cursor: pointer; 13 | opacity: 0; 14 | } 15 | .snackbar.snackbar-opened { 16 | height: auto; 17 | opacity: 1; 18 | } 19 | @media (max-width: 767px) { 20 | #snackbar-container { 21 | left: 0px !important; 22 | right: 0px; 23 | width: 100%; 24 | } 25 | #snackbar-container .snackbar { 26 | min-width: 100%; 27 | } 28 | #snackbar-container [class="snackbar snackbar-opened"] ~ .snackbar.toast { 29 | margin-top: 20px; 30 | } 31 | #snackbar-container [class="snackbar snackbar-opened"] { 32 | border-radius: 0; 33 | margin-bottom: 0; 34 | } 35 | } 36 | /*# sourceMappingURL=snackbar.css.map */ -------------------------------------------------------------------------------- /www/dist/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /www/dist/fonts/RobotoDraftBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/RobotoDraftBold.woff -------------------------------------------------------------------------------- /www/dist/fonts/RobotoDraftBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/RobotoDraftBold.woff2 -------------------------------------------------------------------------------- /www/dist/fonts/RobotoDraftItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/RobotoDraftItalic.woff -------------------------------------------------------------------------------- /www/dist/fonts/RobotoDraftItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/RobotoDraftItalic.woff2 -------------------------------------------------------------------------------- /www/dist/fonts/RobotoDraftMedium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/RobotoDraftMedium.woff -------------------------------------------------------------------------------- /www/dist/fonts/RobotoDraftMedium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/RobotoDraftMedium.woff2 -------------------------------------------------------------------------------- /www/dist/fonts/RobotoDraftRegular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/RobotoDraftRegular.woff -------------------------------------------------------------------------------- /www/dist/fonts/RobotoDraftRegular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/RobotoDraftRegular.woff2 -------------------------------------------------------------------------------- /www/dist/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /www/dist/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /www/dist/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /www/dist/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /www/dist/js/EventEmitter.js: -------------------------------------------------------------------------------- 1 | //events (publish subscribe) pattern [aka Event Emitter] 2 | var events = { 3 | events: {}, 4 | on: function (eventName, fn) { 5 | this.events[eventName] = this.events[eventName] || []; 6 | this.events[eventName].push(fn); 7 | }, 8 | off: function(eventName, fn) { 9 | if (this.events[eventName]) { 10 | for (var i = 0; i < this.events[eventName].length; i++) { 11 | if (this.events[eventName][i] === fn) { 12 | this.events[eventName].splice(i, 1); 13 | break; 14 | } 15 | } 16 | } 17 | }, 18 | emit: function (eventName, data) { 19 | if (this.events[eventName]) { 20 | this.events[eventName].forEach(function(fn) { 21 | fn(data); 22 | }); 23 | } 24 | } 25 | }; -------------------------------------------------------------------------------- /www/dist/js/arrive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * arrive.js 3 | * v2.3.0 4 | * https://github.com/uzairfarooq/arrive 5 | * MIT licensed 6 | * 7 | * Copyright (c) 2014-2015 Uzair Farooq 8 | */ 9 | 10 | var Arrive=function(r,n,q){function t(e,a,c){f.addMethod(a,c,e.unbindEvent);f.addMethod(a,c,e.unbindEventWithSelectorOrCallback);f.addMethod(a,c,e.unbindEventWithSelectorAndCallback)}function p(e){e.arrive=k.bindEvent;t(k,e,"unbindArrive");e.leave=h.bindEvent;t(h,e,"unbindLeave")}if(r.MutationObserver&&"undefined"!==typeof HTMLElement){var w=0,f=function(){var e=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector; 11 | return{matchesSelector:function(a,c){return a instanceof HTMLElement&&e.call(a,c)},addMethod:function(a,c,d){var b=a[c];a[c]=function(){if(d.length==arguments.length)return d.apply(this,arguments);if("function"==typeof b)return b.apply(this,arguments)}},callCallbacks:function(a){for(var c=0,d;d=a[c];c++)d.callback.call(d.elem)},checkChildNodesRecursively:function(a,c,d,b){for(var u=0,m;m=a[u];u++)d(m,c,b)&&b.push({callback:c.callback,elem:m}),00?!a.ctrlKey&&!a.metaKey&&!a.altKey&&8!=a.which&&9!=a.which&&13!=a.which&&16!=a.which&&17!=a.which&&20!=a.which&&27!=a.which:!1}function c(b){var c=a(b);c.prop("disabled")||c.closest(".form-group").addClass("is-focused")}function d(b){b.closest("label").hover(function(){var b=a(this).find("input");b.prop("disabled")||c(b)},function(){e(a(this).find("input"))})}function e(b){a(b).closest(".form-group").removeClass("is-focused")}a.expr[":"].notmdproc=function(b){return a(b).data("mdproc")?!1:!0},a.material={options:{validate:!0,input:!0,ripples:!0,checkbox:!0,togglebutton:!0,radio:!0,arrive:!0,autofill:!1,withRipples:[".btn:not(.btn-link)",".card-image",".navbar a:not(.withoutripple)",".dropdown-menu a",".nav-tabs a:not(.withoutripple)",".withripple",".pagination li:not(.active):not(.disabled) a:not(.withoutripple)"].join(","),inputElements:"input.form-control, textarea.form-control, select.form-control",checkboxElements:".checkbox > label > input[type=checkbox]",togglebuttonElements:".togglebutton > label > input[type=checkbox]",radioElements:".radio > label > input[type=radio]"},checkbox:function(b){var c=a(b?b:this.options.checkboxElements).filter(":notmdproc").data("mdproc",!0).after("");d(c)},togglebutton:function(b){var c=a(b?b:this.options.togglebuttonElements).filter(":notmdproc").data("mdproc",!0).after("");d(c)},radio:function(b){var c=a(b?b:this.options.radioElements).filter(":notmdproc").data("mdproc",!0).after("");d(c)},input:function(b){a(b?b:this.options.inputElements).filter(":notmdproc").data("mdproc",!0).each(function(){var b=a(this),c=b.closest(".form-group");0===c.length&&(b.wrap("
"),c=b.closest(".form-group")),b.attr("data-hint")&&(b.after("

"+b.attr("data-hint")+"

"),b.removeAttr("data-hint"));var d={"input-lg":"form-group-lg","input-sm":"form-group-sm"};if(a.each(d,function(a,d){b.hasClass(a)&&(b.removeClass(a),c.addClass(d))}),b.hasClass("floating-label")){var e=b.attr("placeholder");b.attr("placeholder",null).removeClass("floating-label");var f=b.attr("id"),g="";f&&(g="for='"+f+"'"),c.addClass("label-floating"),b.after("")}(null===b.val()||"undefined"==b.val()||""===b.val())&&c.addClass("is-empty"),c.append(""),c.find("input[type=file]").length>0&&c.addClass("is-fileinput")})},attachInputEventHandlers:function(){var d=this.options.validate;a(document).on("change",".checkbox input[type=checkbox]",function(){a(this).blur()}).on("keydown paste",".form-control",function(c){b(c)&&a(this).closest(".form-group").removeClass("is-empty")}).on("keyup change",".form-control",function(){var b=a(this),c=b.closest(".form-group"),e="undefined"==typeof b[0].checkValidity||b[0].checkValidity();""===b.val()?c.addClass("is-empty"):c.removeClass("is-empty"),d&&(e?c.removeClass("has-error"):c.addClass("has-error"))}).on("focus",".form-control, .form-group.is-fileinput",function(){c(this)}).on("blur",".form-control, .form-group.is-fileinput",function(){e(this)}).on("change",".form-group input",function(){var b=a(this);if("file"!=b.attr("type")){var c=b.closest(".form-group"),d=b.val();d?c.removeClass("is-empty"):c.addClass("is-empty")}}).on("change",".form-group.is-fileinput input[type='file']",function(){var b=a(this),c=b.closest(".form-group"),d="";a.each(this.files,function(a,b){d+=b.name+", "}),d=d.substring(0,d.length-2),d?c.removeClass("is-empty"):c.addClass("is-empty"),c.find("input.form-control[readonly]").val(d)})},ripples:function(b){a(b?b:this.options.withRipples).ripples()},autofill:function(){var b=setInterval(function(){a("input[type!=checkbox]").each(function(){var b=a(this);b.val()&&b.val()!==b.attr("value")&&b.trigger("change")})},100);setTimeout(function(){clearInterval(b)},1e4)},attachAutofillEventHandlers:function(){var b;a(document).on("focus","input",function(){var c=a(this).parents("form").find("input").not("[type=file]");b=setInterval(function(){c.each(function(){var b=a(this);b.val()!==b.attr("value")&&b.trigger("change")})},100)}).on("blur",".form-group input",function(){clearInterval(b)})},init:function(b){this.options=a.extend({},this.options,b);var c=a(document);a.fn.ripples&&this.options.ripples&&this.ripples(),this.options.input&&(this.input(),this.attachInputEventHandlers()),this.options.checkbox&&this.checkbox(),this.options.togglebutton&&this.togglebutton(),this.options.radio&&this.radio(),this.options.autofill&&(this.autofill(),this.attachAutofillEventHandlers()),document.arrive&&this.options.arrive&&(a.fn.ripples&&this.options.ripples&&c.arrive(this.options.withRipples,function(){a.material.ripples(a(this))}),this.options.input&&c.arrive(this.options.inputElements,function(){a.material.input(a(this))}),this.options.checkbox&&c.arrive(this.options.checkboxElements,function(){a.material.checkbox(a(this))}),this.options.radio&&c.arrive(this.options.radioElements,function(){a.material.radio(a(this))}),this.options.togglebutton&&c.arrive(this.options.togglebuttonElements,function(){a.material.togglebutton(a(this))}))}}}(jQuery); 2 | //# sourceMappingURL=material.min.js.map -------------------------------------------------------------------------------- /www/dist/js/bootstrap-material-design/ripples.min.js: -------------------------------------------------------------------------------- 1 | !function(a,b,c,d){"use strict";function e(b,c){g=this,this.element=a(b),this.options=a.extend({},h,c),this._defaults=h,this._name=f,this.init()}var f="ripples",g=null,h={};e.prototype.init=function(){var c=this.element;c.on("mousedown touchstart",function(d){if(!g.isTouch()||"mousedown"!==d.type){c.find(".ripple-container").length||c.append('
');var e=c.children(".ripple-container"),f=g.getRelY(e,d),h=g.getRelX(e,d);if(f||h){var i=g.getRipplesColor(c),j=a("
");j.addClass("ripple").css({left:h,top:f,"background-color":i}),e.append(j),function(){return b.getComputedStyle(j[0]).opacity}(),g.rippleOn(c,j),setTimeout(function(){g.rippleEnd(j)},500),c.on("mouseup mouseleave touchend",function(){j.data("mousedown","off"),"off"===j.data("animating")&&g.rippleOut(j)})}}})},e.prototype.getNewSize=function(a,b){return Math.max(a.outerWidth(),a.outerHeight())/b.outerWidth()*2.5},e.prototype.getRelX=function(a,b){var c=a.offset();return g.isTouch()?(b=b.originalEvent,1===b.touches.length?b.touches[0].pageX-c.left:!1):b.pageX-c.left},e.prototype.getRelY=function(a,b){var c=a.offset();return g.isTouch()?(b=b.originalEvent,1===b.touches.length?b.touches[0].pageY-c.top:!1):b.pageY-c.top},e.prototype.getRipplesColor=function(a){var c=a.data("ripple-color")?a.data("ripple-color"):b.getComputedStyle(a[0]).color;return c},e.prototype.hasTransitionSupport=function(){var a=c.body||c.documentElement,b=a.style,e=b.transition!==d||b.WebkitTransition!==d||b.MozTransition!==d||b.MsTransition!==d||b.OTransition!==d;return e},e.prototype.isTouch=function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},e.prototype.rippleEnd=function(a){a.data("animating","off"),"off"===a.data("mousedown")&&g.rippleOut(a)},e.prototype.rippleOut=function(a){a.off(),g.hasTransitionSupport()?a.addClass("ripple-out"):a.animate({opacity:0},100,function(){a.trigger("transitionend")}),a.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(){a.remove()})},e.prototype.rippleOn=function(a,b){var c=g.getNewSize(a,b);g.hasTransitionSupport()?b.css({"-ms-transform":"scale("+c+")","-moz-transform":"scale("+c+")","-webkit-transform":"scale("+c+")",transform:"scale("+c+")"}).addClass("ripple-on").data("animating","on").data("mousedown","on"):b.animate({width:2*Math.max(a.outerWidth(),a.outerHeight()),height:2*Math.max(a.outerWidth(),a.outerHeight()),"margin-left":-1*Math.max(a.outerWidth(),a.outerHeight()),"margin-top":-1*Math.max(a.outerWidth(),a.outerHeight()),opacity:.2},500,function(){b.trigger("transitionend")})},a.fn.ripples=function(b){return this.each(function(){a.data(this,"plugin_"+f)||a.data(this,"plugin_"+f,new e(this,b))})}}(jQuery,window,document); 2 | //# sourceMappingURL=ripples.min.js.map -------------------------------------------------------------------------------- /www/dist/js/browser.console.mirror.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Browser module for console mirroring. 3 | * Works with Socket.io 4 | */ 5 | 6 | var consoleMirroring = (function(document){ // Module Pattern Design 7 | 8 | var methods = {}; 9 | var domElem; 10 | 11 | function validateOptions(options){ 12 | return new Promise(function(resolve, reject){ 13 | if (typeof options === 'undefined') return reject('pass a valid option argument'); 14 | if (typeof options.socketLib === 'undefined') return reject('pass a valid socket.io instance'); 15 | if (typeof options.socketLib.io === 'undefined') return reject('Socket.io instance not valid'); 16 | if (typeof options.containerId === 'undefined') return reject('containerId required.'); 17 | if (document.getElementById(options.containerId) === null) return reject('containerId not found in the DOM'); 18 | // set default values 19 | if (typeof options.fullScreen === 'undefined') options.fullScreen = false; 20 | if (typeof options.border === 'undefined') options.border = true; 21 | 22 | resolve(); 23 | }); 24 | } 25 | 26 | function addStyling(elem, extra){ 27 | 28 | elem.style.background = '#000'; 29 | elem.style.border = (extra.border) ? '3px groove #ccc' : 'none'; 30 | elem.style.color = '#ccc'; 31 | elem.style.display = 'block'; 32 | elem.style.padding = '7px'; 33 | elem.style.width = (extra.fullScreen) ? '100%' : '70%'; 34 | elem.style.height = (extra.fullScreen) ? '100%' : '300px'; 35 | elem.style['overflow-y'] = 'scroll'; 36 | } 37 | 38 | methods.init = function(options){ 39 | 40 | validateOptions(options).then(function(){ 41 | domElem = document.getElementById(options.containerId); 42 | addStyling(domElem, options); 43 | var io = options.socketLib; 44 | io.on('logEvent', function(data){ 45 | // {text: '...', color: '#...'} received through socket 46 | var mex = ''+data.text+''+'
'; 47 | domElem.insertAdjacentHTML('beforeend', mex); 48 | }); 49 | }).catch(function(err){ 50 | console.error(err); 51 | }); 52 | 53 | }; 54 | 55 | 56 | return methods; 57 | 58 | })(document); 59 | -------------------------------------------------------------------------------- /www/dist/js/css-circle-menu/circleMenu.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | "use strict"; 4 | 5 | /** 6 | * Cache variables 7 | */ 8 | var menu = document.querySelector("#c-circle-nav"); 9 | var toggle = document.querySelector("#c-circle-nav__toggle"); 10 | var mask = document.createElement("div"); 11 | var activeClass = "is-active"; 12 | 13 | /** 14 | * Create mask 15 | */ 16 | mask.classList.add("c-mask"); 17 | document.body.appendChild(mask); 18 | 19 | /** 20 | * Listen for clicks on the toggle 21 | */ 22 | toggle.addEventListener("click", function(e) { 23 | e.preventDefault(); 24 | toggle.classList.contains(activeClass) ? deactivateMenu() : activateMenu(); 25 | }); 26 | 27 | /** 28 | * Listen for clicks on the mask, which should close the menu 29 | */ 30 | mask.addEventListener("click", function() { 31 | deactivateMenu(); 32 | console.log('click'); 33 | }); 34 | 35 | /** 36 | * Activate the menu 37 | */ 38 | function activateMenu() { 39 | menu.classList.add(activeClass); 40 | toggle.classList.add(activeClass); 41 | mask.classList.add(activeClass); 42 | } 43 | 44 | /** 45 | * Deactivate the menu 46 | */ 47 | function deactivateMenu() { 48 | menu.classList.remove(activeClass); 49 | toggle.classList.remove(activeClass); 50 | mask.classList.remove(activeClass); 51 | } 52 | 53 | })(); -------------------------------------------------------------------------------- /www/dist/js/form-validator/brazil.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator Module: Brazil 3 | * ------------------------------------------ 4 | * Created by Eduardo Cuducos 5 | * 6 | * This form validation module adds validators typically used on 7 | * websites in the Brazil. This module adds the following validators: 8 | * - cpf 9 | * - cep 10 | * - brphone 11 | * 12 | * @website http://formvalidator.net/#brazil-validators 13 | * @license MIT 14 | * @version 2.2.83 15 | */ 16 | 17 | $.formUtils.addValidator({ 18 | name : 'cpf', 19 | validatorFunction : function(string) { 20 | 21 | // Based on this post from DevMedia: 22 | // http://www.devmedia.com.br/validar-cpf-com-javascript/23916 23 | 24 | // clean up the input (digits only) and set some support vars 25 | var cpf = string.replace(/\D/g,''); 26 | var sum1 = 0; 27 | var sum2 = 0; 28 | var remainder1 = 0; 29 | var remainder2 = 0; 30 | 31 | // skip special cases 32 | if (cpf.length !== 11 || cpf === '00000000000') { 33 | return false; 34 | } 35 | 36 | // check 1st verification digit 37 | for (i = 1; i<= 9; i++) { 38 | sum1 += parseInt(cpf.substring(i - 1, i)) * (11 - i); 39 | } 40 | remainder1 = (sum1 * 10) % 11; 41 | if (remainder1 >= 10) { 42 | remainder1 = 0; 43 | } 44 | if (remainder1 !== parseInt(cpf.substring(9, 10))) { 45 | return false; 46 | } 47 | 48 | // check 2nd verification digit 49 | for (i = 1; i <= 10; i++) { 50 | sum2 += parseInt(cpf.substring(i - 1, i)) * (12 - i); 51 | } 52 | remainder2 = (sum2 * 10) % 11; 53 | if (remainder2 >= 10) { 54 | remainder2 = 0; 55 | } 56 | if (remainder2 !== parseInt(cpf.substring(10, 11))) { 57 | return false; 58 | } 59 | 60 | return true; 61 | 62 | }, 63 | errorMessage : '', 64 | errorMessageKey: 'badBrazilCPFAnswer' 65 | 66 | }); 67 | 68 | $.formUtils.addValidator({ 69 | name : 'brphone', 70 | validatorFunction : function(string) { 71 | 72 | // validates telefones such as (having X as numbers): 73 | // (XX) XXXX-XXXX 74 | // (XX) XXXXX-XXXX 75 | // XX XXXXXXXX 76 | // XX XXXXXXXXX 77 | // XXXXXXXXXX 78 | // XXXXXXXXXXX 79 | // +XX XX XXXXX-XXXX 80 | // +X XX XXXX-XXXX 81 | // And so on… 82 | 83 | if (string.match(/^(\+[\d]{1,3}[\s]{0,1}){0,1}(\(){0,1}(\d){2}(\)){0,1}(\s){0,1}(\d){4,5}([-. ]){0,1}(\d){4}$/g)) { 84 | return true; 85 | } 86 | 87 | return false; 88 | 89 | }, 90 | errorMessage : '', 91 | errorMessageKey: 'badBrazilTelephoneAnswer' 92 | 93 | }); 94 | 95 | $.formUtils.addValidator({ 96 | name : 'cep', 97 | validatorFunction : function(string) { 98 | 99 | // validates CEP such as (having X as numbers): 100 | // XXXXX-XXX 101 | // XXXXX.XXX 102 | // XXXXX XXX 103 | // XXXXXXXX 104 | 105 | if (string.match(/^(\d){5}([-. ]){0,1}(\d){3}$/g)) { 106 | return true; 107 | } 108 | 109 | return false; 110 | 111 | }, 112 | errorMessage : '', 113 | errorMessageKey: 'badBrazilCEPAnswer' 114 | 115 | }); 116 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/brazil.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | $.formUtils.addValidator({name:"cpf",validatorFunction:function(a){var b=a.replace(/\D/g,""),c=0,d=0,e=0,f=0;if(11!==b.length||"00000000000"===b)return!1;for(i=1;i<=9;i++)c+=parseInt(b.substring(i-1,i))*(11-i);if(e=10*c%11,e>=10&&(e=0),e!==parseInt(b.substring(9,10)))return!1;for(i=1;i<=10;i++)d+=parseInt(b.substring(i-1,i))*(12-i);return f=10*d%11,f>=10&&(f=0),f!==parseInt(b.substring(10,11))?!1:!0},errorMessage:"",errorMessageKey:"badBrazilCPFAnswer"}),$.formUtils.addValidator({name:"brphone",validatorFunction:function(a){return a.match(/^(\+[\d]{1,3}[\s]{0,1}){0,1}(\(){0,1}(\d){2}(\)){0,1}(\s){0,1}(\d){4,5}([-. ]){0,1}(\d){4}$/g)?!0:!1},errorMessage:"",errorMessageKey:"badBrazilTelephoneAnswer"}),$.formUtils.addValidator({name:"cep",validatorFunction:function(a){return a.match(/^(\d){5}([-. ]){0,1}(\d){3}$/g)?!0:!1},errorMessage:"",errorMessageKey:"badBrazilCEPAnswer"}); -------------------------------------------------------------------------------- /www/dist/js/form-validator/date.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator Module: Date 3 | * ------------------------------------------ 4 | * Created by Victor Jonsson 5 | * Documentation and issue tracking on Github 6 | * 7 | * The following validators will be added by this module: 8 | * - Time (HH:mmm) 9 | * - Birth date 10 | * 11 | * @website http://formvalidator.net/#location-validators 12 | * @license MIT 13 | * @version 2.2.83 14 | */ 15 | (function($) { 16 | 17 | /* 18 | * Validate time hh:mm 19 | */ 20 | $.formUtils.addValidator({ 21 | name : 'time', 22 | validatorFunction : function(time) { 23 | if (time.match(/^(\d{2}):(\d{2})$/) === null) { 24 | return false; 25 | } else { 26 | var hours = parseInt(time.split(':')[0],10); 27 | var minutes = parseInt(time.split(':')[1],10); 28 | if( hours > 23 || minutes > 59 ) { 29 | return false; 30 | } 31 | } 32 | return true; 33 | }, 34 | errorMessage : '', 35 | errorMessageKey: 'badTime' 36 | }); 37 | 38 | /* 39 | * Is this a valid birth date 40 | */ 41 | $.formUtils.addValidator({ 42 | name : 'birthdate', 43 | validatorFunction : function(val, $el, conf) { 44 | var dateFormat = 'yyyy-mm-dd'; 45 | if($el.valAttr('format')) { 46 | dateFormat = $el.valAttr('format'); 47 | } 48 | else if(typeof conf.dateFormat !== 'undefined') { 49 | dateFormat = conf.dateFormat; 50 | } 51 | 52 | var inputDate = $.formUtils.parseDate(val, dateFormat); 53 | if (!inputDate) { 54 | return false; 55 | } 56 | 57 | var d = new Date(); 58 | var currentYear = d.getFullYear(); 59 | var year = inputDate[0]; 60 | var month = inputDate[1]; 61 | var day = inputDate[2]; 62 | 63 | if (year === currentYear) { 64 | var currentMonth = d.getMonth() + 1; 65 | if (month === currentMonth) { 66 | var currentDay = d.getDate(); 67 | return day <= currentDay; 68 | } 69 | else { 70 | return month < currentMonth; 71 | } 72 | } 73 | else { 74 | return year < currentYear && year > (currentYear - 124); // we can not live for ever yet... 75 | } 76 | }, 77 | errorMessage : '', 78 | errorMessageKey: 'badDate' 79 | }); 80 | 81 | })(jQuery); 82 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/date.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a){a.formUtils.addValidator({name:"time",validatorFunction:function(a){if(null===a.match(/^(\d{2}):(\d{2})$/))return!1;var b=parseInt(a.split(":")[0],10),c=parseInt(a.split(":")[1],10);return b>23||c>59?!1:!0},errorMessage:"",errorMessageKey:"badTime"}),a.formUtils.addValidator({name:"birthdate",validatorFunction:function(b,c,d){var e="yyyy-mm-dd";c.valAttr("format")?e=c.valAttr("format"):"undefined"!=typeof d.dateFormat&&(e=d.dateFormat);var f=a.formUtils.parseDate(b,e);if(!f)return!1;var g=new Date,h=g.getFullYear(),i=f[0],j=f[1],k=f[2];if(i===h){var l=g.getMonth()+1;if(j===l){var m=g.getDate();return m>=k}return l>j}return h>i&&i>h-124},errorMessage:"",errorMessageKey:"badDate"})}(jQuery); -------------------------------------------------------------------------------- /www/dist/js/form-validator/file.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){"use strict";var c="undefined"!=typeof b.FileReader,d=function(b){var c=a.split((b.valAttr("allowing")||"").toLowerCase());return a.inArray("jpg",c)>-1&&-1===a.inArray("jpeg",c)?c.push("jpeg"):a.inArray("jpeg",c)>-1&&-1===a.inArray("jpg",c)&&c.push("jpg"),c},e=function(a,b,c,d){var e=d[b]||"";a.errorMessageKey="",a.errorMessage=e.replace("%s",c)},f=function(a){b.console&&b.console.log&&b.console.log(a)},g=function(c,d,e){var f=new FileReader,g=new Image;f.readAsDataURL(c),f.onload=function(c){g.onload=function(){a(b).trigger("imageValidation",[this]),d(this)},g.onerror=function(){e()},g.src=c.target.result}};a.formUtils.addValidator({name:"mime",validatorFunction:function(b,g,h,i){if(c){var j=!0,k=g.get(0).files||[],l="",m=d(g);return k.length&&(a.each(k,function(b,c){return j=!1,l=c.type||"",a.each(m,function(a,b){return j=l.indexOf(b)>-1,j?!1:void 0}),j}),j||(f("Trying to upload a file with mime type "+l+" which is not allowed"),e(this,"wrongFileType",m.join(", "),i))),j}return f("FileReader not supported by browser, will check file extension"),a.formUtils.validators.validate_extension.validatorFunction(b,g,h,i)},errorMessage:"",errorMessageKey:"wrongFileType"}),a.formUtils.addValidator({name:"extension",validatorFunction:function(b,c,f,g){var h=!0,i=this,j=d(c);return a.each(c.get(0).files||[b],function(b,c){var d="string"==typeof c?c:c.value||c.fileName||c.name,f=d.substr(d.lastIndexOf(".")+1);return-1===a.inArray(f.toLowerCase(),j)?(h=!1,e(i,"wrongFileType",j.join(", "),g),!1):void 0}),h},errorMessage:"",errorMessageKey:"wrongFileType"}),a.formUtils.addValidator({name:"size",validatorFunction:function(b,d,g,h){var i=d.valAttr("max-size");if(!i)return f('Input "'+d.attr("name")+'" is missing data-validation-max-size attribute'),!0;if(!c)return!0;var j=a.formUtils.convertSizeNameToBytes(i),k=!0;return a.each(d.get(0).files||[],function(a,b){return k=b.size<=j}),k||e(this,"wrongFileSize",i,h),k},errorMessage:"",errorMessageKey:"wrongFileSize"}),a.formUtils.convertSizeNameToBytes=function(a){return a=a.toUpperCase(),"M"===a.substr(a.length-1,1)?1024*parseInt(a.substr(0,a.length-1),10)*1024:"MB"===a.substr(a.length-2,2)?1024*parseInt(a.substr(0,a.length-2),10)*1024:"KB"===a.substr(a.length-2,2)?1024*parseInt(a.substr(0,a.length-2),10):"B"===a.substr(a.length-1,1)?parseInt(a.substr(0,a.length-1),10):parseInt(a,10)};var h=function(){return!1};a.formUtils.checkImageDimension=function(a,b,c){var d=!1,e={width:0,height:0},f=function(a){a=a.replace("min","").replace("max","");var b=a.split("x");e.width=b[0],e.height=b[1]?b[1]:b[0]},g=!1,h=!1,i=b.split("-");return 1===i.length?0===i[0].indexOf("min")?g=i[0]:h=i[0]:(g=i[0],h=i[1]),g&&(f(g),(a.widthe.width||a.height>e.height)&&(d=a.width>e.width?c.imageTooWide+" "+e.width+"px":c.imageTooTall+" "+e.height+"px",d+=" ("+c.max+" "+e.width+"x"+e.height+"px)")),d},a.formUtils.checkImageRatio=function(a,b,c){var d=a.width/a.height,e=function(a){var b=a.replace("max","").replace("min","").split(":");return b[0]/b[1]},f=b.split("-"),g=function(a,b,c){return a>=b&&c>=a};if(1===f.length){if(d!==e(f[0]))return c.imageRatioNotAccepted}else if(2===f.length&&!g(d,e(f[0]),e(f[1])))return c.imageRatioNotAccepted;return!1},a.formUtils.addValidator({name:"dimension",validatorFunction:function(b,d,e,f,i){var j=!1;if(c){var k=d.get(0).files||[];if(j=!0,-1===d.attr("data-validation").indexOf("mime"))return alert("You should validate file type being jpg, gif or png on input "+d[0].name),!1;if(k.length>1)return alert("Validating image dimensions does not support inputs allowing multiple files"),!1;if(0===k.length)return!0;if(d.valAttr("has-valid-dim"))return!0;if(d.valAttr("has-not-valid-dim"))return this.errorMessage=f.wrongFileDim+" "+d.valAttr("has-not-valid-dim"),!1;if("keyup"===a.formUtils.eventType)return null;var l=!1;return a.formUtils.isValidatingEntireForm&&(l=!0,a.formUtils.haltValidation=!0,i.bind("submit",h).addClass("on-blur")),g(k[0],function(b){var c=!1;d.valAttr("dimension")&&(c=a.formUtils.checkImageDimension(b,d.valAttr("dimension"),f)),!c&&d.valAttr("ratio")&&(c=a.formUtils.checkImageRatio(b,d.valAttr("ratio"),f)),c?d.valAttr("has-not-valid-dim",c):d.valAttr("has-valid-dim","true"),d.valAttr("has-keyup-event")||d.valAttr("has-keyup-event","1").bind("keyup change",function(b){9!==b.keyCode&&16!==b.keyCode&&a(this).valAttr("has-not-valid-dim",!1).valAttr("has-valid-dim",!1)}),l?(a.formUtils.haltValidation=!1,i.removeClass("on-blur").get(0).onsubmit=function(){},i.unbind("submit",h),i.trigger("submit")):d.trigger("blur")},function(a){throw a}),!0}return j},errorMessage:"",errorMessageKey:""}),a(b).one("validatorsLoaded formValidationSetup",function(b,c){var d;d=c?c.find('input[type="file"]'):a('input[type="file"]'),d.filter("*[data-validation]").bind("change",function(){a(this).removeClass("error").parent().find(".form-error").remove()})})}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/html5.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator Module: html5 3 | * ------------------------------------------ 4 | * Created by Victor Jonsson 5 | * 6 | * The following module will make this jQuery plugin serve as a 7 | * html5 fallback. It makes older browsers support the following 8 | * - validation when type="email" 9 | * - validation when type="url" 10 | * - validation when type="time" 11 | * - validation when type="date" 12 | * - validation when type="number" and max="" min="" 13 | * - validation when pattern="REGEXP" 14 | * - validation when using maxlength 15 | * - Using datalist element for creating suggestions 16 | * - placeholders 17 | * 18 | * @website http://formvalidator.net/ 19 | * @license MIT 20 | * @version 2.2.83 21 | */ 22 | (function($, window) { 23 | 24 | 'use strict'; 25 | 26 | var SUPPORTS_PLACEHOLDER = 'placeholder' in document.createElement('INPUT'), 27 | SUPPORTS_DATALIST = 'options' in document.createElement('DATALIST'), 28 | hasLoadedDateModule = false, 29 | setupValidationUsingHTML5Attr = function($form) { 30 | 31 | $form.each(function() { 32 | var $f = $(this), 33 | $formInputs = $f.find('input,textarea,select'), 34 | foundHtml5Rule = false; 35 | 36 | $formInputs.each(function() { 37 | var validation = [], 38 | $input = $(this), 39 | isRequired = $input.attr('required'), 40 | attrs = {}; 41 | 42 | switch ( ($input.attr('type') || '').toLowerCase() ) { 43 | case 'time': 44 | validation.push('time'); 45 | if( !$.formUtils.validators.validate_date && !hasLoadedDateModule ) { 46 | hasLoadedDateModule = true; 47 | $.formUtils.loadModules('date'); 48 | } 49 | break; 50 | case 'url': 51 | validation.push('url'); 52 | break; 53 | case 'email': 54 | validation.push('email'); 55 | break; 56 | case 'date': 57 | validation.push('date'); 58 | break; 59 | case 'number': 60 | validation.push('number'); 61 | var max = $input.attr('max'), 62 | min = $input.attr('min'); 63 | if( min || max ) { 64 | if ( !min ) { 65 | min = '0'; 66 | } 67 | if ( !max ) { 68 | max = '9007199254740992'; // js max int 69 | } 70 | 71 | attrs['data-validation-allowing'] = 'range['+min+';'+max+']'; 72 | if( min.indexOf('-') === 0 || max.indexOf('-') === 0 ) { 73 | attrs['data-validation-allowing'] += ',negative'; 74 | } 75 | if( min.indexOf('.') > -1 || max.indexOf('.') > -1 ) { 76 | attrs['data-validation-allowing'] += ',float'; 77 | } 78 | } 79 | break; 80 | } 81 | 82 | if( $input.attr('pattern') ) { 83 | validation.push('custom'); 84 | attrs['data-validation-regexp'] = $input.attr('pattern'); 85 | } 86 | if( $input.attr('maxlength') ) { 87 | validation.push('length'); 88 | attrs['data-validation-length'] = 'max'+$input.attr('maxlength'); 89 | } 90 | 91 | if( !SUPPORTS_DATALIST && $input.attr('list') ) { 92 | var suggestions = [], 93 | $list = $('#'+$input.attr('list')); 94 | 95 | $list.find('option').each(function() { 96 | suggestions.push($(this).text()); 97 | }); 98 | 99 | if( suggestions.length === 0 ) { 100 | // IE fix 101 | var opts = $.trim($('#'+$input.attr('list')).text()).split('\n'); 102 | $.each(opts, function(i, option) { 103 | suggestions.push($.trim(option)); 104 | }); 105 | } 106 | 107 | $list.remove(); 108 | 109 | $.formUtils.suggest( $input, suggestions ); 110 | } 111 | 112 | if ( isRequired && validation.length === 0 ) { 113 | validation.push('required'); 114 | } 115 | 116 | if( validation.length ) { 117 | if( !isRequired ) { 118 | attrs['data-validation-optional'] = 'true'; 119 | } 120 | 121 | foundHtml5Rule = true; 122 | $input.attr('data-validation', validation.join(' ')); 123 | 124 | $.each(attrs, function(attrName, attrVal) { 125 | $input.attr(attrName, attrVal); 126 | }); 127 | } 128 | }); 129 | 130 | if( foundHtml5Rule ) { 131 | $f.trigger('html5ValidationAttrsFound'); 132 | } 133 | 134 | if( !SUPPORTS_PLACEHOLDER ) { 135 | $formInputs.filter('input[placeholder]').each(function() { 136 | this.defaultValue = this.getAttribute('placeholder'); 137 | $(this) 138 | .bind('focus', function() { 139 | if(this.value === this.defaultValue) { 140 | this.value = ''; 141 | $(this).removeClass('showing-placeholder'); 142 | } 143 | }) 144 | .bind('blur', function() { 145 | if($.trim(this.value) === '') { 146 | this.value = this.defaultValue; 147 | $(this).addClass('showing-placeholder'); 148 | } 149 | }); 150 | }); 151 | } 152 | 153 | }); 154 | }; 155 | 156 | $(window).bind('validatorsLoaded formValidationSetup', function(evt, $form) { 157 | if( !$form ) { 158 | $form = $('form'); 159 | } 160 | setupValidationUsingHTML5Attr($form); 161 | }); 162 | 163 | // Make this method available outside the module 164 | $.formUtils.setupValidationUsingHTML5Attr = setupValidationUsingHTML5Attr; 165 | 166 | })(jQuery, window); 167 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/html5.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){"use strict";var c="placeholder"in document.createElement("INPUT"),d="options"in document.createElement("DATALIST"),e=!1,f=function(b){b.each(function(){var b=a(this),f=b.find("input,textarea,select"),g=!1;f.each(function(){var b=[],c=a(this),f=c.attr("required"),h={};switch((c.attr("type")||"").toLowerCase()){case"time":b.push("time"),a.formUtils.validators.validate_date||e||(e=!0,a.formUtils.loadModules("date"));break;case"url":b.push("url");break;case"email":b.push("email");break;case"date":b.push("date");break;case"number":b.push("number");var i=c.attr("max"),j=c.attr("min");(j||i)&&(j||(j="0"),i||(i="9007199254740992"),h["data-validation-allowing"]="range["+j+";"+i+"]",(0===j.indexOf("-")||0===i.indexOf("-"))&&(h["data-validation-allowing"]+=",negative"),(j.indexOf(".")>-1||i.indexOf(".")>-1)&&(h["data-validation-allowing"]+=",float"))}if(c.attr("pattern")&&(b.push("custom"),h["data-validation-regexp"]=c.attr("pattern")),c.attr("maxlength")&&(b.push("length"),h["data-validation-length"]="max"+c.attr("maxlength")),!d&&c.attr("list")){var k=[],l=a("#"+c.attr("list"));if(l.find("option").each(function(){k.push(a(this).text())}),0===k.length){var m=a.trim(a("#"+c.attr("list")).text()).split("\n");a.each(m,function(b,c){k.push(a.trim(c))})}l.remove(),a.formUtils.suggest(c,k)}f&&0===b.length&&b.push("required"),b.length&&(f||(h["data-validation-optional"]="true"),g=!0,c.attr("data-validation",b.join(" ")),a.each(h,function(a,b){c.attr(a,b)}))}),g&&b.trigger("html5ValidationAttrsFound"),c||f.filter("input[placeholder]").each(function(){this.defaultValue=this.getAttribute("placeholder"),a(this).bind("focus",function(){this.value===this.defaultValue&&(this.value="",a(this).removeClass("showing-placeholder"))}).bind("blur",function(){""===a.trim(this.value)&&(this.value=this.defaultValue,a(this).addClass("showing-placeholder"))})})})};a(b).bind("validatorsLoaded formValidationSetup",function(b,c){c||(c=a("form")),f(c)}),a.formUtils.setupValidationUsingHTML5Attr=f}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/jsconf.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator Module: JSconf 3 | * ------------------------------------------ 4 | * Created by Victor Jonsson 5 | * 6 | * This module makes it possible to configure form validation using javascript 7 | * 8 | * @website http://formvalidator.net/#location-validators 9 | * @license MIT 10 | * @version 2.2.83 11 | */ 12 | (function($) { 13 | 14 | 'use strict'; 15 | 16 | $.setupValidation = function(conf) { 17 | var $forms = $(conf.form || 'form'); 18 | $.each(conf.validate || conf.validation || {}, function(elemRef, attr) { 19 | var $elem; 20 | if ( elemRef[0] === '#' ) { 21 | $elem = $(elemRef); 22 | } 23 | else if ( elemRef[0] === '.' ) { 24 | $elem = $forms.find(elemRef); 25 | } 26 | else { 27 | $elem = $forms.find('*[name="' +elemRef+ '"]'); 28 | } 29 | 30 | $elem.attr('data-validation', attr.validation); 31 | 32 | $.each(attr, function(name, val) { 33 | if( name !== 'validation' && val !== false) { 34 | if( val === true ){ 35 | val = 'true'; 36 | } 37 | $elem.valAttr(name, val); 38 | } 39 | }); 40 | }); 41 | 42 | $.validate(conf); 43 | }; 44 | 45 | })(jQuery); 46 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/jsconf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a){"use strict";a.setupValidation=function(b){var c=a(b.form||"form");a.each(b.validate||b.validation||{},function(b,d){var e;e="#"===b[0]?a(b):c.find("."===b[0]?b:'*[name="'+b+'"]'),e.attr("data-validation",d.validation),a.each(d,function(a,b){"validation"!==a&&b!==!1&&(b===!0&&(b="true"),e.valAttr(a,b))})}),a.validate(b)}}(jQuery); -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/cz.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator 3 | * ------------------------------------------ 4 | * 5 | * Czech language package 6 | * 7 | * @website http://formvalidator.net/ 8 | * @license MIT 9 | * @version 2.2.83 10 | */ 11 | (function($, window) { 12 | 13 | 'use strict'; 14 | 15 | $(window).bind('validatorsLoaded', function() { 16 | 17 | $.formUtils.LANG = { 18 | errorTitle: 'Podání formuláře selhalo!', 19 | requiredField: 'Toto pole je povinné', 20 | requiredfields: 'Nebyly vyplněny všechny požadované pole', 21 | badTime: 'Neplatný čas', 22 | badEmail: 'Neplatná e-mailová adresa', 23 | badTelephone: 'Neplatné telefonní číslo', 24 | badSecurityAnswer: 'Chybná odpověď na bezpečnostní otázku', 25 | badDate: 'Nesprávné datum', 26 | lengthBadStart: 'Zadaná hodnota musí být v rozmezí ', 27 | lengthBadEnd: ' znaků', 28 | lengthTooLongStart: 'Zadaná hodnota je větší než ', 29 | lengthTooShortStart: 'Zadaná hodnota je menší než ', 30 | notConfirmed: 'Zadané hodnoty nebyly potvrzené', 31 | badDomain: 'Neplatná doména', 32 | badUrl: 'Neplatný URL', 33 | badCustomVal: 'Zadaná hodnota je chybná', 34 | andSpaces: ' a mezery', 35 | badInt: 'Neplatné číslo', 36 | badSecurityNumber: 'Neplatné číslo zabezpečení', 37 | badUKVatAnswer: 'Neplatné číslo DIČ ', 38 | badStrength: 'Vaše heslo není dostatečně silné', 39 | badNumberOfSelectedOptionsStart: 'Musíte vybrat nejméně ', 40 | badNumberOfSelectedOptionsEnd: ' odpověď', 41 | badAlphaNumeric: 'Zadaná hodnota může obsahovat pouze alfanumerické znaky ', 42 | badAlphaNumericExtra: ' a ', 43 | wrongFileSize: 'Soubor je příliš velký (max %s)', 44 | wrongFileType: 'Pouze soubory typu %s', 45 | groupCheckedRangeStart: 'Prosím, vyberte ', 46 | groupCheckedTooFewStart: 'Vyberte prosím nejméně ', 47 | groupCheckedTooManyStart: 'Vyberte prosím maximálně ', 48 | groupCheckedEnd: ' složka(y)', 49 | badCreditCard: 'Číslo kreditní karty je neplatné', 50 | badCVV: 'Číslo CVV je neplatné', 51 | wrongFileDim: 'Nesprávné rozměry obrázku,', 52 | imageTooTall: 'obraz nemůže být vyšší než', 53 | imageTooWide: 'obraz nemůže být širší než', 54 | imageTooSmall: 'obraz je příliš malý', 55 | min: 'min', 56 | max: 'max', 57 | imageRatioNotAccepted: 'Poměr obrázku je nesprávný', 58 | badBrazilTelephoneAnswer: 'Neplatné telefonní číslo', 59 | badBrazilCEPAnswer: 'Neplatné CEP', 60 | badBrazilCPFAnswer: 'Neplatné CPF' 61 | }; 62 | 63 | }); 64 | 65 | })(jQuery, window); 66 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/cz.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){"use strict";a(b).bind("validatorsLoaded",function(){a.formUtils.LANG={errorTitle:"Podání formuláře selhalo!",requiredfields:"Nebyly vyplněny všechny požadované pole",badTime:"Neplatný čas",badEmail:"Neplatná e-mailová adresa",badTelephone:"Neplatné telefonní číslo",badSecurityAnswer:"Chybná odpověď na bezpečnostní otázku",badDate:"Nesprávné datum",lengthBadStart:"Zadaná hodnota musí být v rozmezí",lengthBadEnd:"znaků",lengthTooLongStart:"Zadaná hodnota je větší než",lengthTooShortStart:"Zadaná hodnota je menší než",notConfirmed:"Zadané hodnoty nebyly potvrzené",badDomain:"Neplatná doména",badUrl:"Neplatný URL",badCustomVal:"Zadaná hodnota je chybná",andSpaces:"a mezery",badInt:"Neplatné číslo",badSecurityNumber:"Neplatné číslo zabezpečení",badUKVatAnswer:"Neplatné číslo DIČ ",badStrength:"Vaše heslo není dostatečně silné",badNumberOfSelectedOptionsStart:"Musíte vybrat nejméně",badNumberOfSelectedOptionsEnd:"odpověď",badAlphaNumeric:"Zadaná hodnota může obsahovat pouze alfanumerické znaky",badAlphaNumericExtra:"a",wrongFileSize:"Soubor je příliš velký (max %s)",wrongFileType:"Pouze soubory typu %s",groupCheckedRangeStart:"Prosím, vyberte",groupCheckedTooFewStart:"Vyberte prosím nejméně",groupCheckedTooManyStart:"Vyberte prosím maximálně",groupCheckedEnd:"složka(y)",badCreditCard:"Číslo kreditní karty je neplatné",badCVV:"Číslo CVV je neplatné",wrongFileDim:"Nesprávné rozměry obrázku,",imageTooTall:"obraz nemůže být vyšší než",imageTooWide:"obraz nemůže být širší než",imageTooSmall:"obraz je příliš malý",min:"min",max:"max",imageRatioNotAccepted:"Poměr obrázku je nesprávný",badBrazilTelephoneAnswer:"Neplatné telefonní číslo",badBrazilCEPAnswer:"Neplatné CEP",badBrazilCPFAnswer:"Neplatné CPF"}})}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/de.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator 3 | * ------------------------------------------ 4 | * 5 | * German language package 6 | * 7 | * @website http://formvalidator.net/ 8 | * @license MIT 9 | * @version 2.2.83 10 | */ 11 | (function($, window) { 12 | 13 | 'use strict'; 14 | 15 | $(window).bind('validatorsLoaded', function() { 16 | 17 | $.formUtils.LANG = { 18 | errorTitle: 'Ihre Anfrage konnte nicht gesendet werden!', 19 | requiredField: 'Dies ist ein Pflichtfeld', 20 | requiredFields: 'Sie haben nicht alle Fragen beantwortet', 21 | badTime: 'Sie haben nicht die korrekte Zeit eingegeben', 22 | badEmail: 'Sie haben keine gültige E-Mail-Adresse eingegeben', 23 | badTelephone: 'Sie haben keine richtige Telefonnummer eingetragen', 24 | badSecurityAnswer: 'Sie haben die falsche Antwort auf die Sicherheitsfrage eingegeben', 25 | badDate: 'Re-Eingabe eines falschen Datums', 26 | lengthBadStart: 'Der eingegebene Wert muss da zwischen sein ', 27 | lengthBadEnd: '  Zeichen', 28 | lengthTooLongStart: 'Eingegebene Wert ist größer als ', 29 | lengthTooShortStart: 'Eingegebene Wert ist größer als ', 30 | notConfirmed: 'Die Antworten könnten nicht gegenseitig bestätigen,', 31 | badDomain: 'Sie haben die falsche Domäne eingetragen', 32 | badUrl: 'Sie haben nicht die richtige URL eingegeben', 33 | badCustomVal: 'Re-Eingabe einer falschen Antwort', 34 | andSpaces: ' und Leerzeichen', 35 | badInt: 'Sie haben keine Nummer eingegeben', 36 | badSecurityNumber: 'Sie haben eine falsche Sozialversicherungsnummer eingegeben', 37 | badUKVatAnswer: 'Sie haben keine UK Umsatzsteuer-Identifikationsnummer eingegeben', 38 | badStrength: 'Sie haben ein Kennwort, das nicht sicher genug ist eingegeben', 39 | badNumberOfSelectedOptionsStart: 'Wählen Sie zu mindestens ', 40 | badNumberOfSelectedOptionsEnd: ' Antwort', 41 | badAlphaNumeric: 'Sie können nur mit alphanumerische Zeichen (Buchstaben und Zahlen) eingaben', 42 | badAlphaNumericExtra: ' und', 43 | wrongFileSize: 'Die Datei, die Sie hochzuladen versuchen, zu groß ist (max %s)', 44 | wrongFileType: 'Nur Dateien vom Typ %s sind zulässig', 45 | groupCheckedRangeStart: 'Wählen Sie zwischen', 46 | groupCheckedTooFewStart: 'Dann müssen Sie zumindest sicher,', 47 | groupCheckedTooManyStart: 'Sie können nicht mehr als zu machen', 48 | groupCheckedEnd: ' Auswahl', 49 | badCreditCard: 'Sie haben eine ungültige Kreditkartennummer eingegeben', 50 | badCVV: 'Sie haben eine falsche CVV eingegeben', 51 | wrongFileDim: 'Illegal Bildgröße,', 52 | imageTooTall: 'Bild kann nicht größer als', 53 | imageTooWide: 'Bild kann nicht breiter sein als', 54 | imageTooSmall: 'Bild ist zu klein', 55 | min: 'min', 56 | max: 'max', 57 | imageRatioNotAccepted : 'Bildverhältnis wird nicht akzeptiert', 58 | badBrazilTelephoneAnswer: 'Die eingegebene Telefonnummer ist nicht korrekt', 59 | badBrazilCEPAnswer: 'Der CEP ist ungültig', 60 | badBrazilCPFAnswer: 'Der CEP ist ungültig' 61 | }; 62 | 63 | }); 64 | 65 | })(jQuery, window); 66 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/de.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){"use strict";a(b).bind("validatorsLoaded",function(){a.formUtils.LANG={errorTitle:"Ihre Anfrage konnte nicht gesendet werden!",requiredFields:"Sie haben nicht alle Fragen beantwortet",badTime:"Sie haben nicht die korrekte Zeit eingegeben",badEmail:"Sie haben keine gültige E-Mail-Adresse eingegeben",badTelephone:"Sie haben keine richtige Telefonnummer eingetragen",badSecurityAnswer:"Sie haben die falsche Antwort auf die Sicherheitsfrage eingegeben",badDate:"Re-Eingabe eines falschen Datums",lengthBadStart:"Ihre Eingabe muss zwischen %s lang sein",lengthBadEnd:" Zeichen",lengthTooLongStart:"Sie haben eine Antwort die länger als %s angegeben",lengthTooShortStart:"Sie haben eine Antwort die kürzer ist als %s eingegebene",notConfirmed:"Die Antworten könnten nicht gegenseitig bestätigen,",badDomain:"Sie haben die falsche Domäne eingetragen",badUrl:"Sie haben nicht die richtige URL eingegeben",badCustomVal:"Re-Eingabe einer falschen Antwort",andSpaces:" und Leerzeichen",badInt:"Sie haben keine Nummer eingegeben",badSecurityNumber:"Sie haben eine falsche Sozialversicherungsnummer eingegeben",badUKVatAnswer:"Sie haben keine UK Umsatzsteuer-Identifikationsnummer eingegeben",badStrength:"Sie haben ein Kennwort, das nicht sicher genug ist eingegeben",badNumberOfSelectedOptionsStart:"Sie müssen mindestens %s wählen",badNumberOfSelectedOptionsEnd:" Antwort",badAlphaNumeric:"Sie können nur mit alphanumerische Zeichen (Buchstaben und Zahlen) eingaben",badAlphaNumericExtra:" und",wrongFileSize:"Die Datei, die Sie hochzuladen versuchen, zu groß ist (max %s)",wrongFileType:"Nur Dateien vom Typ %s sind zulässig",groupCheckedRangeStart:"Wählen Sie zwischen",groupCheckedTooFewStart:"Dann müssen Sie zumindest sicher,",groupCheckedTooManyStart:"Sie können nicht mehr als zu machen",groupCheckedEnd:" Auswahl",badCreditCard:"Sie haben eine ungültige Kreditkartennummer eingegeben",badCVV:"Sie haben eine falsche CVV eingegeben",wrongFileDim:"Illegal Bildgröße,",imageTooTall:"Das Bild kann nicht höher als %s sein",imageTooWide:"Das Bild kann nicht breiter als %s sein",imageTooSmall:"das Bild ist zu klein",min:"min",max:"max",imageRatioNotAccepted:"Bildverhältnis wird nicht akzeptiert"}})}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/es.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator 3 | * ------------------------------------------ 4 | * 5 | * Spanish language package 6 | * 7 | * @website http://formvalidator.net/ 8 | * @license Dual licensed under the MIT or GPL Version 2 licenses 9 | * @version 2.2.83 10 | */ 11 | (function($, window) { 12 | 13 | 'use strict'; 14 | 15 | $(window).bind('validatorsLoaded', function() { 16 | 17 | $.formUtils.LANG = { 18 | errorTitle: 'El formulario no se ha podido enviar!', 19 | requiredField: 'Este campo es obligatorio', 20 | requiredFields: 'No ha contestado todos los campos requeridos', 21 | badTime: 'La hora proporcionada no es válida', 22 | badEmail: 'La dirección de e-mail no es válida', 23 | badTelephone: 'El número de teléfono proporcionado no es válido', 24 | badSecurityAnswer: 'La respuesta a su pregunta de seguridad es incorrecta', 25 | badDate: 'La fecha proporcionada no es válida', 26 | lengthBadStart: 'Su respuesta debe incluir entre ', 27 | lengthBadEnd: ' caracteres', 28 | lengthTooLongStart: 'Su respuesta debe de ser menor a ', 29 | lengthTooShortStart: 'Su respuesta debe de ser mayor a ', 30 | notConfirmed: 'Los valores proporcionados no pudieron ser confirmados', 31 | badDomain: 'Ha introducido un dominio incorrecto', 32 | badUrl: 'La URL proporcionada no es válida', 33 | badCustomVal: 'Los valores proporcionados no son válidos', 34 | andSpaces: ' y espacios ', 35 | badInt: 'El valor proporcionado no es un número válido', 36 | badSecurityNumber: 'El número de seguridad social proporcionado es incorrecto', 37 | badUKVatAnswer: 'No número VAT proporcionado no es válido para el Reino Unido', 38 | badStrength: 'La contraseña proporcionada no es lo suficientemente segura', 39 | badNumberOfSelectedOptionsStart: 'Debe seleccionar al menos', 40 | badNumberOfSelectedOptionsEnd: ' respuesta(s)', 41 | badAlphaNumeric: 'El valor proporcionado solo debe contener caracteres alfanuméricos (a-z y números)', 42 | badAlphaNumericExtra: ' y', 43 | wrongFileSize: 'El archivo que está tratando de subir es demasiado grande (máx. %s)', 44 | wrongFileType: 'Sólo los archivos del tipo %s están permitido', 45 | groupCheckedRangeStart: 'Por favor, elija entre ', 46 | groupCheckedTooFewStart: 'Por favor, elija al menos ', 47 | groupCheckedTooManyStart: 'Por favor, elija un máximo de ', 48 | groupCheckedEnd: ' ítem(s)', 49 | badCreditCard: 'El número de tarjeta de crédito proporcionado no es válido', 50 | badCVV: 'CVV proporcionado no es válido', 51 | wrongFileDim: 'Las dimensiones de la imagen no son validas,', 52 | imageTooTall: 'el alto de la imagen no puede ser mayor a', 53 | imageTooWide: 'el ancho de la imagen no puede ser mayor a', 54 | imageTooSmall: 'la imagen es demasiado pequeña', 55 | min: 'min.', 56 | max: 'máx.', 57 | imageRatioNotAccepted : 'La proporción de imagen (alto x ancho) no es válida' 58 | }; 59 | 60 | }); 61 | 62 | })(jQuery, window); 63 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/es.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){"use strict";a(b).bind("validatorsLoaded",function(){a.formUtils.LANG={errorTitle:"El formulario no se ha podido enviar!",requiredFields:"No ha respondido a todas las preguntas",badTime:"No ha introducido la hora correcta",badEmail:"No ha entrado en una dirección de e-mail válida",badTelephone:"Usted no ha entrado en el número de teléfono correcto",badSecurityAnswer:"Ha introducido la respuesta incorrecta a la pregunta de seguridad",badDate:"Re-escribiendo una fecha incorrecta",lengthBadStart:"Su respuesta debe incluir entre",lengthBadEnd:" signo",lengthTooLongStart:"Ha introducido una respuesta que es más largo que",lengthTooShortStart:"Ha introducido una respuesta que es más corta que",notConfirmed:"Las respuestas no pudieron confirmar entre sí",badDomain:"Ha introducido un dominio incorrecto",badUrl:"Usted no ha entrado en el URL correcto",badCustomVal:"Re-escribiendo una respuesta incorrecta",andSpaces:" y espacios",badInt:"No ha introducido un número",badSecurityNumber:"Ha introducido un número de seguro social incorrecto",badUKVatAnswer:"No ha introducido un número de IVA del Reino Unido",badStrength:"Ha introducido una contraseña que no es lo suficientemente seguro",badNumberOfSelectedOptionsStart:"Debe seleccionar al menos",badNumberOfSelectedOptionsEnd:" respuesta",badAlphaNumeric:"Sólo se puede responder con alfanumersika caracteres (az y números)",badAlphaNumericExtra:" y",wrongFileSize:"El archivo que está tratando de subir es demasiado grande (máx %s)",wrongFileType:"Sólo los archivos de tipo %s está permitido",groupCheckedRangeStart:"Elegir entre",groupCheckedTooFewStart:"Entonces usted debe hacer por lo menos",groupCheckedTooManyStart:"Usted no puede hacer más de",groupCheckedEnd:" selección",badCreditCard:"Ha introducido un número de tarjeta de crédito válida",badCVV:"Usted ha introducido una CVV incorrecta",wrongFileDim:"Tamaño de la imagen Ilegal,",imageTooTall:"el cuadro no puede ser superior a",imageTooWide:"el cuadro no puede ser más amplio que",imageTooSmall:"la imagen es demasiado pequeña",min:"menos",max:"max",imageRatioNotAccepted:"Cociente de la imagen no es ser aceptado"}})}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/fr.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator 3 | * ------------------------------------------ 4 | * 5 | * French language package 6 | * 7 | * @website http://formvalidator.net/ 8 | * @license MIT 9 | * @version 2.2.83 10 | */ 11 | (function($, window) { 12 | 13 | 'use strict'; 14 | 15 | $(window).bind('validatorsLoaded', function() { 16 | 17 | $.formUtils.LANG = { 18 | errorTitle: 'Le formulaire n\'a pas pu être envoyé!', 19 | requiredField: 'Ce champ est obligatoire', 20 | requiredFields: 'Vous n\'avez pas rempli tous les champs', 21 | badTime: 'Vous n\'avez pas saisi l\'heure correctement', 22 | badEmail: 'Vous n\'avez pas saisi une adresse e-mail valide', 23 | badTelephone: 'Vous n\'avez pas saisi un numéro de téléphone valide', 24 | badSecurityAnswer: 'Vous avez saisi une mauvaise réponse à la question de sécurité', 25 | badDate: 'Vous n\'avez pas saisi une date correcte', 26 | lengthBadStart: 'Votre saisie doit comporter entre', 27 | lengthBadEnd: ' caractères', 28 | lengthTooLongStart: 'Vous avez saisi une réponse qui est plus longue que', 29 | lengthTooShortStart: 'Votre saisie est plus courte que', 30 | notConfirmed: 'Les saisies ne sont pas identiques', 31 | badDomain: 'Vous avez saisi un domaine incorrect', 32 | badUrl: 'Vous avez saisi une URL incorrecte', 33 | badCustomVal: 'Re-saisissez une réponse correcte', 34 | andSpaces: ' et des espaces', 35 | badInt: 'Vous n\'avez pas saisi un numéro', 36 | badSecurityNumber: 'Vous avez saisi un mauvais numéro de sécurité sociale', 37 | badUKVatAnswer: 'Vous n\'avez pas saisi un numéro de TVA au Royaume-Uni', 38 | badStrength: 'Vous avez saisi un mot de passe pas assez sécurisé', 39 | badNumberOfSelectedOptionsStart: 'Vous devez sélectionner au moins', 40 | badNumberOfSelectedOptionsEnd: ' réponse(s)', 41 | badAlphaNumeric: 'Vous ne pouvez répondre qu\'avec des caractères alphanumériques et des chiffres', 42 | badAlphaNumericExtra: ' et', 43 | wrongFileSize: 'Le fichier que vous essayez de télécharger est trop grand (max %s)', 44 | wrongFileType: 'Seuls les fichiers du type %s sont autorisés', 45 | groupCheckedRangeStart: 'Choisissez entre', 46 | groupCheckedTooFewStart: 'Vous devez faire au moins', 47 | groupCheckedTooManyStart: 'Vous ne pouvez pas faire plus de', 48 | groupCheckedEnd: ' sélection(s)', 49 | badCreditCard: 'Vous avez saisi un numéro de carte de crédit invalide', 50 | badCVV: 'Vous avez saisi un CVV incorrect', 51 | wrongFileDim: 'Mauvaise taille de l\'image,', 52 | imageTooTall: 'l\'image ne peut pas être plus élevée que', 53 | imageTooWide: 'l\'image ne peut pas être plus large que', 54 | imageTooSmall: 'l\'image est trop petite', 55 | min: 'moins', 56 | max: 'max', 57 | imageRatioNotAccepted: 'Ratio de l\'image non accepté' 58 | }; 59 | 60 | }); 61 | 62 | })(jQuery, window); 63 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/fr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){"use strict";a(b).bind("validatorsLoaded",function(){a.formUtils.LANG={errorTitle:"Le formulaire n'a pas pu être envoyé!",requiredFields:"Vous n'avez pas saisi tous les champs",badTime:"Vous n'avez pas saisi l'heure correctement",badEmail:"Vous n'avez pas saisi une adresse e-mail valide",badTelephone:"Vous n'avez pas saisi un numéro de téléphone valide",badSecurityAnswer:"Vous avez saisi une mauvaise réponse à la question de la sécurité",badDate:"Vous n'avez pas saisi une date correcte",lengthBadStart:"Votre saisie doit comporter entre",lengthBadEnd:" caractères",lengthTooLongStart:"Vous avez saisi une réponse qui est plus longue que",lengthTooShortStart:"Votre saisie est plus courte que",notConfirmed:"Les saisies ne sont pas identiques",badDomain:"Vous avez saisi un domaine incorrect",badUrl:"Vous avez saisi une URL incorrecte",badCustomVal:"Re-saisissez une réponse correcte",andSpaces:" et des espaces",badInt:"Vous n'avez pas saisi un numéro",badSecurityNumber:"Vous avez saisi un mauvais numéro de sécurité sociale",badUKVatAnswer:"Vous n'avez pas saisi un numéro de TVA au Royaume-Uni",badStrength:"Vous avez saisi un mot de passe pas assez sécurisé",badNumberOfSelectedOptionsStart:"Vous devez sélectionner au moins",badNumberOfSelectedOptionsEnd:" réponse",badAlphaNumeric:"Vous ne pouvez répondre qu'avec des caractères alphanumériques et des chiffres",badAlphaNumericExtra:" et",wrongFileSize:"Le fichier que vous essayez de télécharger est trop grand (max %s)",wrongFileType:"Seuls les fichiers de type %s sont autorisés",groupCheckedRangeStart:"Choisissez entre",groupCheckedTooFewStart:"Ensuite, vous devez faire au moins",groupCheckedTooManyStart:"Vous ne pouvez pas faire plus de",groupCheckedEnd:" sélection",badCreditCard:"Vous avez saisi un numéro de carte de crédit invalide",badCVV:"Vous avez saisi un CVV incorrecte",wrongFileDim:"Mauvaise taille de l'image,",imageTooTall:"l'image ne peut pas être plus élevée que",imageTooWide:"l'image ne peut pas être plus large que",imageTooSmall:"l'image est trop petite",min:"moins",max:"max",imageRatioNotAccepted:"Ratio de l'image non accepté"}})}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/it.dev.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/js/form-validator/lang/it.dev.js -------------------------------------------------------------------------------- /www/dist/js/form-validator/lang/it.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roccomuso/iot-433mhz/8d0ea6ca6625a6c5c6f11f598df920de747d5c54/www/dist/js/form-validator/lang/it.js -------------------------------------------------------------------------------- /www/dist/js/form-validator/location.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator Module: Date 3 | * ------------------------------------------ 4 | * Created by Victor Jonsson 5 | * 6 | * The following validators will be added by this module: 7 | * - Country 8 | * - US state 9 | * - longitude and latitude 10 | * 11 | * @website http://formvalidator.net/#location-validators 12 | * @license MIT 13 | * @version 2.2.83 14 | */ 15 | (function($) { 16 | 17 | /* 18 | * Validate that country exists 19 | */ 20 | $.formUtils.addValidator({ 21 | name : 'country', 22 | validatorFunction : function(str) { 23 | return $.inArray(str.toLowerCase(), this.countries) > -1; 24 | }, 25 | countries : ['afghanistan','albania','algeria','american samoa','andorra','angola','anguilla','antarctica','antigua and barbuda','arctic ocean','argentina','armenia','aruba','ashmore and cartier islands','atlantic ocean','australia','austria','azerbaijan','bahamas','bahrain','baltic sea','baker island','bangladesh','barbados','bassas da india','belarus','belgium','belize','benin','bermuda','bhutan','bolivia','borneo','bosnia and herzegovina','botswana','bouvet island','brazil','british virgin islands','brunei','bulgaria','burkina faso','burundi','cambodia','cameroon','canada','cape verde','cayman islands','central african republic','chad','chile','china','christmas island','clipperton island','cocos islands','colombia','comoros','cook islands','coral sea islands','costa rica','croatia','cuba','cyprus','czech republic','democratic republic of the congo','denmark','djibouti','dominica','dominican republic','east timor','ecuador','egypt','el salvador','equatorial guinea','eritrea','estonia','ethiopia','europa island','falkland islands','faroe islands','fiji','finland','france','french guiana','french polynesia','french southern and antarctic lands','gabon','gambia','gaza strip','georgia','germany','ghana','gibraltar','glorioso islands','greece','greenland','grenada','guadeloupe','guam','guatemala','guernsey','guinea','guinea-bissau','guyana','haiti','heard island and mcdonald islands','honduras','hong kong','howland island','hungary','iceland','india','indian ocean','indonesia','iran','iraq','ireland','isle of man','israel','italy','jamaica','jan mayen','japan','jarvis island','jersey','johnston atoll','jordan','juan de nova island','kazakhstan','kenya','kerguelen archipelago','kingman reef','kiribati','kosovo','kuwait','kyrgyzstan','laos','latvia','lebanon','lesotho','liberia','libya','liechtenstein','lithuania','luxembourg','macau','macedonia','madagascar','malawi','malaysia','maldives','mali','malta','marshall islands','martinique','mauritania','mauritius','mayotte','mediterranean sea','mexico','micronesia','midway islands','moldova','monaco','mongolia','montenegro','montserrat','morocco','mozambique','myanmar','namibia','nauru','navassa island','nepal','netherlands','netherlands antilles','new caledonia','new zealand','nicaragua','niger','nigeria','niue','norfolk island','north korea','north sea','northern mariana islands','norway','oman','pacific ocean','pakistan','palau','palmyra atoll','panama','papua new guinea','paracel islands','paraguay','peru','philippines','pitcairn islands','poland','portugal','puerto rico','qatar','republic of the congo','reunion','romania','ross sea','russia','rwanda','saint helena','saint kitts and nevis','saint lucia','saint pierre and miquelon','saint vincent and the grenadines','samoa','san marino','sao tome and principe','saudi arabia','senegal','serbia','seychelles','sierra leone','singapore','slovakia','slovenia','solomon islands','somalia','south africa','south georgia and the south sandwich islands','south korea','southern ocean','spain','spratly islands','sri lanka','sudan','suriname','svalbard','swaziland','sweden','switzerland','syria','taiwan','tajikistan','tanzania','tasman sea','thailand','togo','tokelau','tonga','trinidad and tobago','tromelin island','tunisia','turkey','turkmenistan','turks and caicos islands','tuvalu','uganda','ukraine','united arab emirates','united kingdom','uruguay','usa','uzbekistan','vanuatu','venezuela','viet nam','virgin islands','wake island','wallis and futuna','west bank','western sahara','yemen','zambia','zimbabwe'], 26 | errorMessage : '', 27 | errorMessageKey: 'badCustomVal' 28 | }); 29 | 30 | /* 31 | * Is this a valid federate state in the US 32 | */ 33 | $.formUtils.addValidator({ 34 | name : 'federatestate', 35 | validatorFunction : function(str) { 36 | return $.inArray(str.toLowerCase(), this.states) > -1; 37 | }, 38 | states : ['alabama','alaska', 'arizona', 'arkansas','california','colorado','connecticut','delaware','florida','georgia','hawaii','idaho','illinois','indiana','iowa','kansas','kentucky','louisiana','maine','maryland', 'district of columbia', 'massachusetts','michigan','minnesota','mississippi','missouri','montana','nebraska','nevada','new hampshire','new jersey','new mexico','new york','north carolina','north dakota','ohio','oklahoma','oregon','pennsylvania','rhode island','south carolina','south dakota','tennessee','texas','utah','vermont','virginia','washington','west virginia','wisconsin','wyoming'], 39 | errorMessage : '', 40 | errorMessageKey: 'badCustomVal' 41 | }); 42 | 43 | 44 | $.formUtils.addValidator({ 45 | name : 'longlat', 46 | validatorFunction : function(str) { 47 | var regexp = /^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/; 48 | return regexp.test(str); 49 | }, 50 | errorMessage:'', 51 | errorMessageKey:'badCustomVal' 52 | }); 53 | 54 | /** 55 | * @private 56 | * @param {Array} listItems 57 | * @return {Array} 58 | */ 59 | var _makeSortedList = function(listItems) { 60 | var newList = []; 61 | $.each(listItems, function(i, v) { 62 | newList.push(v.substr(0,1).toUpperCase() + v.substr(1, v.length)); 63 | }); 64 | newList.sort(); 65 | return newList; 66 | }; 67 | 68 | $.fn.suggestCountry = function(settings) { 69 | var country = _makeSortedList($.formUtils.validators.validate_country.countries); 70 | return $.formUtils.suggest(this, country, settings); 71 | }; 72 | 73 | $.fn.suggestState = function(settings) { 74 | var states = _makeSortedList($.formUtils.validators.validate_federatestate.states); 75 | return $.formUtils.suggest(this, states, settings); 76 | }; 77 | 78 | })(jQuery); 79 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/location.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a){a.formUtils.addValidator({name:"country",validatorFunction:function(b){return a.inArray(b.toLowerCase(),this.countries)>-1},countries:["afghanistan","albania","algeria","american samoa","andorra","angola","anguilla","antarctica","antigua and barbuda","arctic ocean","argentina","armenia","aruba","ashmore and cartier islands","atlantic ocean","australia","austria","azerbaijan","bahamas","bahrain","baltic sea","baker island","bangladesh","barbados","bassas da india","belarus","belgium","belize","benin","bermuda","bhutan","bolivia","borneo","bosnia and herzegovina","botswana","bouvet island","brazil","british virgin islands","brunei","bulgaria","burkina faso","burundi","cambodia","cameroon","canada","cape verde","cayman islands","central african republic","chad","chile","china","christmas island","clipperton island","cocos islands","colombia","comoros","cook islands","coral sea islands","costa rica","croatia","cuba","cyprus","czech republic","democratic republic of the congo","denmark","djibouti","dominica","dominican republic","east timor","ecuador","egypt","el salvador","equatorial guinea","eritrea","estonia","ethiopia","europa island","falkland islands","faroe islands","fiji","finland","france","french guiana","french polynesia","french southern and antarctic lands","gabon","gambia","gaza strip","georgia","germany","ghana","gibraltar","glorioso islands","greece","greenland","grenada","guadeloupe","guam","guatemala","guernsey","guinea","guinea-bissau","guyana","haiti","heard island and mcdonald islands","honduras","hong kong","howland island","hungary","iceland","india","indian ocean","indonesia","iran","iraq","ireland","isle of man","israel","italy","jamaica","jan mayen","japan","jarvis island","jersey","johnston atoll","jordan","juan de nova island","kazakhstan","kenya","kerguelen archipelago","kingman reef","kiribati","kosovo","kuwait","kyrgyzstan","laos","latvia","lebanon","lesotho","liberia","libya","liechtenstein","lithuania","luxembourg","macau","macedonia","madagascar","malawi","malaysia","maldives","mali","malta","marshall islands","martinique","mauritania","mauritius","mayotte","mediterranean sea","mexico","micronesia","midway islands","moldova","monaco","mongolia","montenegro","montserrat","morocco","mozambique","myanmar","namibia","nauru","navassa island","nepal","netherlands","netherlands antilles","new caledonia","new zealand","nicaragua","niger","nigeria","niue","norfolk island","north korea","north sea","northern mariana islands","norway","oman","pacific ocean","pakistan","palau","palmyra atoll","panama","papua new guinea","paracel islands","paraguay","peru","philippines","pitcairn islands","poland","portugal","puerto rico","qatar","republic of the congo","reunion","romania","ross sea","russia","rwanda","saint helena","saint kitts and nevis","saint lucia","saint pierre and miquelon","saint vincent and the grenadines","samoa","san marino","sao tome and principe","saudi arabia","senegal","serbia","seychelles","sierra leone","singapore","slovakia","slovenia","solomon islands","somalia","south africa","south georgia and the south sandwich islands","south korea","southern ocean","spain","spratly islands","sri lanka","sudan","suriname","svalbard","swaziland","sweden","switzerland","syria","taiwan","tajikistan","tanzania","tasman sea","thailand","togo","tokelau","tonga","trinidad and tobago","tromelin island","tunisia","turkey","turkmenistan","turks and caicos islands","tuvalu","uganda","ukraine","united arab emirates","united kingdom","uruguay","usa","uzbekistan","vanuatu","venezuela","viet nam","virgin islands","wake island","wallis and futuna","west bank","western sahara","yemen","zambia","zimbabwe"],errorMessage:"",errorMessageKey:"badCustomVal"}),a.formUtils.addValidator({name:"federatestate",validatorFunction:function(b){return a.inArray(b.toLowerCase(),this.states)>-1},states:["alabama","alaska","arizona","arkansas","california","colorado","connecticut","delaware","florida","georgia","hawaii","idaho","illinois","indiana","iowa","kansas","kentucky","louisiana","maine","maryland","district of columbia","massachusetts","michigan","minnesota","mississippi","missouri","montana","nebraska","nevada","new hampshire","new jersey","new mexico","new york","north carolina","north dakota","ohio","oklahoma","oregon","pennsylvania","rhode island","south carolina","south dakota","tennessee","texas","utah","vermont","virginia","washington","west virginia","wisconsin","wyoming"],errorMessage:"",errorMessageKey:"badCustomVal"}),a.formUtils.addValidator({name:"longlat",validatorFunction:function(a){var b=/^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/;return b.test(a)},errorMessage:"",errorMessageKey:"badCustomVal"});var b=function(b){var c=[];return a.each(b,function(a,b){c.push(b.substr(0,1).toUpperCase()+b.substr(1,b.length))}),c.sort(),c};a.fn.suggestCountry=function(c){var d=b(a.formUtils.validators.validate_country.countries);return a.formUtils.suggest(this,d,c)},a.fn.suggestState=function(c){var d=b(a.formUtils.validators.validate_federatestate.states);return a.formUtils.suggest(this,d,c)}}(jQuery); -------------------------------------------------------------------------------- /www/dist/js/form-validator/sanitize.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator Module: sanitize 3 | * ------------------------------------------ 4 | * Created by Victor Jonsson 5 | * 6 | * This module makes it possible to add sanitation functions to 7 | * inputs. The functions is triggered on blur. Example: 8 | * 9 | * 10 | * 11 | * Available functions are: 12 | * - uppercase 13 | * - lowercase 14 | * - capitalize 15 | * - trim 16 | * - trimLeft 17 | * - trimRight 18 | * - numberFormat 19 | * - insertLeft 20 | * - insertRight 21 | * - escape (replace <, >, &, ' and " with HTML entities) 22 | * 23 | * @website http://formvalidator.net/ 24 | * @license MIT 25 | * @version 2.2.83 26 | */ 27 | (function($, window) { 28 | 29 | 'use strict'; 30 | 31 | var inputsThatCantBeSanitized = '[type="button"], [type="submit"], [type="radio"], [type="checkbox"], [type="reset"], [type="search"]', 32 | sanitizeCommands = { 33 | upper : function(val) { 34 | return val.toLocaleUpperCase(); 35 | }, 36 | lower : function(val) { 37 | return val.toLocaleLowerCase(); 38 | }, 39 | trim : function(val) { 40 | return $.trim(val); 41 | }, 42 | trimLeft : function(val) { 43 | return val.replace(/^\s+/,''); 44 | }, 45 | trimRight : function(val) { 46 | return val.replace(/\s+$/,''); 47 | }, 48 | capitalize : function(val) { 49 | var words = val.split(' '); 50 | $.each(words, function(i, word) { 51 | words[i] = word.substr(0,1).toUpperCase() + word.substr(1, word.length); 52 | }); 53 | return words.join(' '); 54 | }, 55 | insert : function(val, $input, pos) { 56 | var extra = ($input.attr('data-sanitize-insert-'+pos) || '').replace(/\[SPACE\]/g, ' '); 57 | if ( (pos === 'left' && val.indexOf(extra) === 0) || (pos === 'right' && val.substring(val.length - extra.length) === extra)) { 58 | return val; 59 | } 60 | return (pos === 'left' ? extra:'') + val + (pos === 'right' ? extra : ''); 61 | }, 62 | insertRight : function(val, $input) { 63 | return this.insert(val, $input, 'right'); 64 | }, 65 | insertLeft : function(val, $input) { 66 | return this.insert(val, $input, 'left'); 67 | }, 68 | numberFormat : function(val, $input) { 69 | if ( 'numeral' in window ) { 70 | val = numeral(val).format( $input.attr('data-sanitize-number-format') ); 71 | } 72 | else { 73 | throw new Error('Using sanitation function "numberFormat" requires that you include numeraljs (http://http://numeraljs.com/)'); 74 | } 75 | return val; 76 | }, 77 | escape : function(val) { 78 | var symbols = { 79 | '<' : '__%AMP%__lt;', 80 | '>' : '__%AMP%__gt;', 81 | '&' : '__%AMP%__amp;', 82 | '\'': '__%AMP%__#8217;', 83 | '"' : '__%AMP%__quot;' 84 | }; 85 | $.each(symbols, function(symbol, replacement) { 86 | val = val.replace(new RegExp(symbol, 'g'), replacement); 87 | }); 88 | return val.replace(new RegExp('__\%AMP\%__', 'g'), '&'); 89 | } 90 | }, 91 | setupSanitation = function(evt, $forms, config) { 92 | 93 | if ( !$forms ) { 94 | $forms = $('form'); 95 | } 96 | if ( !$forms.each ) { 97 | $forms = $($forms); 98 | } 99 | 100 | var execSanitationCommands = function() { 101 | var $input = $(this), 102 | value = $input.val(); 103 | $.split($input.attr('data-sanitize'), function(command) { 104 | if ( command in sanitizeCommands ) { 105 | value = sanitizeCommands[command](value, $input, config); 106 | } 107 | else { 108 | throw new Error('Use of unknown sanitize command "'+command+'"'); 109 | } 110 | }); 111 | $input 112 | .val(value) 113 | .trigger('keyup.validation'); // we need to re-validate in case it gets validated on blur 114 | }; 115 | 116 | $forms.each(function() { 117 | var $form = $(this); 118 | if( config.sanitizeAll ) { 119 | $form.find('input,textarea').not(inputsThatCantBeSanitized).each(function() { 120 | $(this).attr('data-sanitize', config.sanitizeAll+ ' '+ ($(this).attr('data-sanitize') || '')); 121 | }); 122 | } 123 | 124 | $form.find('[data-sanitize]') 125 | .unbind('blur', execSanitationCommands) 126 | .bind('blur', execSanitationCommands); 127 | 128 | }); 129 | }; 130 | 131 | $(window).on('validatorsLoaded formValidationSetup', setupSanitation); 132 | 133 | // Only for unit testing 134 | $.formUtils.setupSanitation = setupSanitation; 135 | 136 | })(jQuery, window); 137 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/sanitize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){"use strict";var c='[type="button"], [type="submit"], [type="radio"], [type="checkbox"], [type="reset"], [type="search"]',d={upper:function(a){return a.toLocaleUpperCase()},lower:function(a){return a.toLocaleLowerCase()},trim:function(b){return a.trim(b)},trimLeft:function(a){return a.replace(/^\s+/,"")},trimRight:function(a){return a.replace(/\s+$/,"")},capitalize:function(b){var c=b.split(" ");return a.each(c,function(a,b){c[a]=b.substr(0,1).toUpperCase()+b.substr(1,b.length)}),c.join(" ")},insert:function(a,b,c){var d=(b.attr("data-sanitize-insert-"+c)||"").replace(/\[SPACE\]/g," ");return"left"===c&&0===a.indexOf(d)||"right"===c&&a.substring(a.length-d.length)===d?a:("left"===c?d:"")+a+("right"===c?d:"")},insertRight:function(a,b){return this.insert(a,b,"right")},insertLeft:function(a,b){return this.insert(a,b,"left")},numberFormat:function(a,c){if(!("numeral"in b))throw new Error('Using sanitation function "numberFormat" requires that you include numeraljs (http://http://numeraljs.com/)');return a=numeral(a).format(c.attr("data-sanitize-number-format"))},escape:function(b){var c={"<":"__%AMP%__lt;",">":"__%AMP%__gt;","&":"__%AMP%__amp;","'":"__%AMP%__#8217;",'"':"__%AMP%__quot;"};return a.each(c,function(a,c){b=b.replace(new RegExp(a,"g"),c)}),b.replace(new RegExp("__%AMP%__","g"),"&")}},e=function(b,e,f){e||(e=a("form")),e.each||(e=a(e));var g=function(){var b=a(this),c=b.val();a.split(b.attr("data-sanitize"),function(a){if(!(a in d))throw new Error('Use of unknown sanitize command "'+a+'"');c=d[a](c,b,f)}),b.val(c).trigger("keyup.validation")};e.each(function(){var b=a(this);f.sanitizeAll&&b.find("input,textarea").not(c).each(function(){a(this).attr("data-sanitize",f.sanitizeAll+" "+(a(this).attr("data-sanitize")||""))}),b.find("[data-sanitize]").unbind("blur",g).bind("blur",g)})};a(b).on("validatorsLoaded formValidationSetup",e),a.formUtils.setupSanitation=e}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/security.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){"use strict";a.formUtils.addValidator({name:"spamcheck",validatorFunction:function(a,b){var c=b.valAttr("captcha");return c===a},errorMessage:"",errorMessageKey:"badSecurityAnswer"}),a.formUtils.addValidator({name:"confirmation",validatorFunction:function(a,b,c,d,e){var f="",g=b.valAttr("confirm")||b.attr("name")+"_confirmation",h=e.find('[name="'+g+'"]').eq(0);return h?f=h.val():alert('Could not find an input with name "'+g+'"'),a===f},errorMessage:"",errorMessageKey:"notConfirmed"});var c={amex:[15,15],diners_club:[14,14],cjb:[16,16],laser:[16,19],visa:[16,16],mastercard:[16,16],maestro:[12,19],discover:[16,16]},d=!1,e=!1;a.formUtils.addValidator({name:"creditcard",validatorFunction:function(f,g){var h=a.split(g.valAttr("allowing")||"");if(e=a.inArray("amex",h)>-1,d=e&&1===h.length,h.length>0){var i=!1;if(a.each(h,function(a,d){if(d in c){if(f.length>=c[d][0]&&f.length<=c[d][1])return i=!0,!1}else b.console&&console.warn('Use of unknown credit card "'+d+'"')}),!i)return!1}if(""!==f.replace(new RegExp("[0-9]","g"),""))return!1;var j=0;return a.each(f.split("").reverse(),function(a,b){b=parseInt(b,10),a%2===0?j+=b:(b*=2,j+=10>b?b:b-9)}),j%10===0},errorMessage:"",errorMessageKey:"badCreditCard"}),a.formUtils.addValidator({name:"cvv",validatorFunction:function(a){return""===a.replace(/[0-9]/g,"")?(a+="",d?4===a.length:e?3===a.length||4===a.length:3===a.length):!1},errorMessage:"",errorMessageKey:"badCVV"}),a.formUtils.addValidator({name:"strength",validatorFunction:function(b,c){var d=c.valAttr("strength")||2;return d&&d>3&&(d=3),a.formUtils.validators.validate_strength.calculatePasswordStrength(b)>=d},errorMessage:"",errorMessageKey:"badStrength",calculatePasswordStrength:function(a){if(a.length<4)return 0;var b=0,c=function(a,b){for(var c="",d=0;df&&f+d+af&&(e=!1),e?(d+=a-1,e=!1):c+=b.charAt(d)}return c};return b+=4*a.length,b+=1*(c(1,a).length-a.length),b+=1*(c(2,a).length-a.length),b+=1*(c(3,a).length-a.length),b+=1*(c(4,a).length-a.length),a.match(/(.*[0-9].*[0-9].*[0-9])/)&&(b+=5),a.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)&&(b+=5),a.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)&&(b+=10),a.match(/([a-zA-Z])/)&&a.match(/([0-9])/)&&(b+=15),a.match(/([!,@,#,$,%,^,&,*,?,_,~])/)&&a.match(/([0-9])/)&&(b+=15),a.match(/([!,@,#,$,%,^,&,*,?,_,~])/)&&a.match(/([a-zA-Z])/)&&(b+=15),(a.match(/^\w+$/)||a.match(/^\d+$/))&&(b-=10),0>b&&(b=0),b>100&&(b=100),20>b?0:40>b?1:60>=b?2:3},strengthDisplay:function(b,c){var d={fontSize:"12pt",padding:"4px",bad:"Very bad",weak:"Weak",good:"Good",strong:"Strong"};c&&a.extend(d,c),b.bind("keyup",function(){var b=a(this).val(),c="undefined"==typeof d.parent?a(this).parent():a(d.parent),e=c.find(".strength-meter"),f=a.formUtils.validators.validate_strength.calculatePasswordStrength(b),g={background:"pink",color:"#FF0000",fontWeight:"bold",border:"red solid 1px",borderWidth:"0px 0px 4px",display:"inline-block",fontSize:d.fontSize,padding:d.padding},h=d.bad;0===e.length&&(e=a(""),e.addClass("strength-meter").appendTo(c)),b?e.show():e.hide(),1===f?h=d.weak:2===f?(g.background="lightyellow",g.borderColor="yellow",g.color="goldenrod",h=d.good):f>=3&&(g.background="lightgreen",g.borderColor="darkgreen",g.color="darkgreen",h=d.strong),e.css(g).text(h)})}});var f=function(b,c,d,e,f){var g=c.valAttr("req-params")||c.data("validation-req-params")||{},h=function(b,d){b.valid?c.valAttr("backend-valid","true"):(c.valAttr("backend-invalid","true"),b.message&&c.attr(e.validationErrorMsgAttribute,b.message)),c.valAttr("has-keyup-event")||c.valAttr("has-keyup-event","1").bind("keyup change",function(b){9!==b.keyCode&&16!==b.keyCode&&a(this).valAttr("backend-valid",!1).valAttr("backend-invalid",!1)}),d()};g||(g={}),"string"==typeof g&&(g=a.parseJSON(g)),g[c.valAttr("param-name")||c.attr("name")]=d,a.ajax({url:b,type:"POST",cache:!1,data:g,dataType:"json",error:function(a){return h({valid:!1,message:"Connection failed with status: "+a.statusText},f),!1},success:function(a){h(a,f)}})},g=function(){return!1};a.formUtils.addValidator({name:"server",validatorFunction:function(b,c,d,e,h){var i=c.valAttr("backend-valid"),j=c.valAttr("backend-invalid"),k=document.location.href;return c.valAttr("url")?k=c.valAttr("url"):"serverURL"in d&&(k=d.backendUrl),i?!0:j?!1:"keyup"===a.formUtils.eventType?null:a.formUtils.isValidatingEntireForm?(h.bind("submit",g).addClass("validating-server-side").addClass("on-blur"),c.addClass("validating-server-side"),a.formUtils.haltValidation=!0,f(k,c,b,d,function(){h.removeClass("validating-server-side").removeClass("on-blur").get(0).onsubmit=function(){},h.unbind("submit",g),c.removeClass("validating-server-side"),c.valAttr("value-length",b.length),a.formUtils.haltValidation=!1,h.trigger("submit")}),null):(h.addClass("validating-server-side"),c.addClass("validating-server-side"),f(k,c,b,d,function(){h.removeClass("validating-server-side"),c.removeClass("validating-server-side"),c.trigger("blur")}),null)},errorMessage:"",errorMessageKey:"badBackend",validateOnKeyUp:!1}),a.formUtils.addValidator({name:"letternumeric",validatorFunction:function(b,c,d,e){var f="^([a-zA-Z0-9ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԧԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠࢢ-ࢬऄ-हऽॐक़-ॡॱ-ॷॹ-ॿঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-ళవ-హఽౘౙౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൠൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤜᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎↃↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ々〆〱-〵〻〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚗꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞓꞠ-Ɦꟸ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꪀ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ",g="]+)$",h=c.valAttr("allowing"),i="";if(h){i=f+h+g;var j=h.replace(/\\/g,"");j.indexOf(" ")>-1&&(j=j.replace(" ",""),j+=e.andSpaces||a.formUtils.LANG.andSpaces),this.errorMessage=e.badAlphaNumeric+e.badAlphaNumericExtra+j}else i=f+g,this.errorMessage=e.badAlphaNumeric;return new RegExp(i).test(b)},errorMessage:"",errorMessageKey:"requiredFields"}),a.fn.displayPasswordStrength=function(b){return new a.formUtils.validators.validate_strength.strengthDisplay(this,b),this}}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/sweden.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b){a.formUtils.addValidator({name:"swesec",validatorFunction:function(c,d){var e,f,g,h;if(d.valAttr("use-hyphen")){if(h=c.split("-"),2!==h.length)return!1;c=h.join("")}if(!c.match(/^(\d{4})(\d{2})(\d{2})(\d{4})$/))return!1;e=RegExp.$1,f=a.formUtils.parseDateInt(RegExp.$2),g=a.formUtils.parseDateInt(RegExp.$3),b.ssnGender=parseInt(RegExp.$4.substring(2,3))%2===0?"female":"male";var i=new Array(31,28,31,30,31,30,31,31,30,31,30,31);if((e%400===0||e%4===0&&e%100!==0)&&(i[1]=29),1>f||f>12||1>g||g>i[f-1])return!1;c=c.substring(2,c.length);for(var j="",k=0;k-1:!1:!0},errorMessage:"",errorMessageKey:"badCustomVal",counties:["stockholms län","uppsala län","södermanlands län","östergötlands län","jönköpings län","kronobergs län","kalmar län","gotlands län","blekinge län","skåne län","hallands län","västra götalands län","värmlands län","örebro län","västmanlands län","dalarnas län","gävleborgs län","västernorrlands län","jämtlands län","västerbottens län","norrbottens län"]}),a.formUtils.addValidator({name:"swemunicipality",validatorFunction:function(b){return b=b.toLowerCase(),-1===a.inArray(b,this.municipalities)?"s kommun"===b.substr(-8)&&a.inArray(b.substr(0,b.length-8),this.municipalities)>-1?!0:" kommun"===b.substr(-7)?a.inArray(b.substr(0,b.length-7),this.municipalities)>-1:!1:!0},errorMessage:"",errorMessageKey:"badCustomVal",municipalities:["ale","alingsås","alvesta","aneby","arboga","arjeplog","arvidsjaur","arvika","askersund","avesta","bengtsfors","berg","bjurholm","bjuv","boden","bollebygd","bollnäs","borgholm","borlänge","borås","botkyrka","boxholm","bromölla","bräcke","burlöv","båstad","dals-ed","danderyd","degerfors","dorotea","eda","ekerö","eksjö","emmaboda","enköpings","eskilstuna","eslövs","essunga","fagersta","falkenberg","falköping","falu","filipstad","finspång","flen","forshaga","färgelanda","gagnef","gislaved","gnesta","gnosjö","gotland","grum","grästorp","gullspång","gällivare","gävle","göteborg","götene","habo","hagfor","hallsberg","hallstahammar","halmstad","hammarö","haninge","haparanda","heby","hedemora","helsingborg","herrljunga","hjo","hofor","huddinge","hudiksvall","hultsfred","hylte","håbo","hällefor","härjedalen","härnösand","härryda","hässleholm","höganäs","högsby","hörby","höör","jokkmokk","järfälla","jönköping","kalix","kalmar","karlsborg","karlshamn","karlskoga","karlskrona","karlstad","katrineholm","kil","kinda","kiruna","klippan","knivsta","kramfors","kristianstad","kristinehamn","krokoms","kumla","kungsbacka","kungsör","kungälv","kävlinge","köping","laholm","landskrona","laxå","lekeberg","leksand","lerum","lessebo","lidingö","lidköping","lilla edets","lindesbergs","linköpings","ljungby","ljusdals","ljusnarsbergs","lomma","ludvika","luleå","lunds","lycksele","lysekil","malmö","malung-sälen","malå","mariestad","marks","markaryd","mellerud","mjölby","mora","motala","mullsjö","munkedal","munkfors","mölndal","mönsterås","mörbylånga","nacka","nora","norberg","nordanstig","nordmaling","norrköping","norrtälje","norsjö","nybro","nykvarn","nyköping","nynäshamn","nässjö","ockelbo","olofström","orsa","orust","osby","oskarshamn","ovanåker","oxelösund","pajala","partille","perstorp","piteå","ragunda","robertsfors","ronneby","rättvik","sala","salem","sandviken","sigtuna","simrishamn","sjöbo","skara","skellefteå","skinnskatteberg","skurup","skövde","smedjebacken","sollefteå","sollentuna","solna","sorsele","sotenäs","staffanstorp","stenungsund","stockholm","storfors","storuman","strängnäs","strömstad","strömsund","sundbyberg","sundsvall","sunne","surahammar","svalöv","svedala","svenljunga","säffle","säter","sävsjö","söderhamns","söderköping","södertälje","sölvesborg","tanum","tibro","tidaholm","tierp","timrå","tingsryd","tjörn","tomelilla","torsby","torså","tranemo","tranå","trelleborg","trollhättan","trosa","tyresö","täby","töreboda","uddevalla","ulricehamns","umeå","upplands väsby","upplands-bro","uppsala","uppvidinge","vadstena","vaggeryd","valdemarsvik","vallentuna","vansbro","vara","varberg","vaxholm","vellinge","vetlanda","vilhelmina","vimmerby","vindeln","vingåker","vårgårda","vänersborg","vännäs","värmdö","värnamo","västervik","västerås","växjö","ydre","ystad","åmål","ånge","åre","årjäng","åsele","åstorp","åtvidaberg","älmhult","älvdalen","älvkarleby","älvsbyn","ängelholm","öckerö","ödeshög","örebro","örkelljunga","örnsköldsvik","östersund","österåker","östhammar","östra göinge","överkalix","övertorneå"]}),a.formUtils.addValidator({name:"swephone",validatorFunction:function(a){var b=a.match(/\+/g),c=a.match(/-/g);return null!==b&&b.length>1||null!==c&&c.length>1?!1:null!==b&&0!==a.indexOf("+")?!1:(a=a.replace(/([-|\+])/g,""),a.length>8&&null===a.match(/[^0-9]/g))},errorMessage:"",errorMessageKey:"badTelephone"}),a.formUtils.addValidator({name:"swemobile",validatorFunction:function(b){if(!a.formUtils.validators.validate_swephone.validatorFunction(b))return!1;b=b.replace(/[^0-9]/g,"");var c=b.substring(0,3);return 10!==b.length&&"467"!==c?!1:11!==b.length&&"467"===c?!1:/07[0-9{1}]/.test(c)||"467"===c},errorMessage:"",errorMessageKey:"badTelephone"});var c=function(b){var c=[];return a.each(b,function(a,b){c.push(b.substr(0,1).toUpperCase()+b.substr(1,b.length))}),c.sort(),c};a.fn.suggestSwedishCounty=function(b){var d=c(a.formUtils.validators.validate_swecounty.counties);return a.formUtils.suggest(this,d,b)},a.fn.suggestSwedishMunicipality=function(b){var d=c(a.formUtils.validators.validate_swemunicipality.municipalities);return a.formUtils.suggest(this,d,b)}}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/toggleDisabled.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator Module: Toggle Disabled 3 | * ------------------------------------------ 4 | * Created by Victor Jonsson 5 | * 6 | * This module will take care of disabling/enabling submit buttons 7 | * in forms, depending on if the inputs of the form is valid or not. 8 | * 9 | * @website http://formvalidator.net/ 10 | * @license MIT 11 | * @version 2.2.83 12 | */ 13 | (function($, window, undefined) { 14 | 15 | 'use strict'; 16 | 17 | // Function that can enable/disable form 18 | var toggleFormState = function($form, state) { 19 | if( state === 'disabled' ) { 20 | $form.find('*[type="submit"]') 21 | .addClass('disabled') 22 | .attr('disabled', 'disabled'); 23 | } else { 24 | $form.find('*[type="submit"]') 25 | .removeClass('disabled') 26 | .removeAttr('disabled'); 27 | } 28 | }, 29 | isCheckingIfFormValid = false; 30 | 31 | $(window).bind('validatorsLoaded formValidationSetup', function(evt, $forms, conf) { 32 | 33 | var $formsToDisable = conf.disabledFormFilter ? $forms.filter(conf.disabledFormFilter) : $forms, 34 | showErrorDialogs = conf.showErrorDialogs === undefined || conf.showErrorDialogs; 35 | 36 | // Toggle form state depending on if it has only valid inputs or not. 37 | $formsToDisable 38 | .addClass(showErrorDialogs ? 'disabled-with-errors' : 'disabled-without-errors') 39 | .find('*[data-validation]') 40 | .attr('data-validation-event','keyup') 41 | .on('validation', function(evt, valid) { 42 | if( !isCheckingIfFormValid ) { 43 | isCheckingIfFormValid = true; 44 | var $form = $(this).closest('form'); 45 | if( valid && $form.isValid(conf, conf.language, false) ) { 46 | toggleFormState($form, 'enabled'); 47 | } else { 48 | toggleFormState($form, 'disabled'); 49 | } 50 | isCheckingIfFormValid = false; 51 | } 52 | }); 53 | 54 | 55 | // Make all inputs validated on keyup, require validateOnEvent in validation config 56 | toggleFormState($formsToDisable, 'disabled'); 57 | 58 | $formsToDisable.validateOnEvent(conf.language, conf); 59 | 60 | }) 61 | .on('validationErrorDisplay', function(evt, $input, $elem) { 62 | if ( $input.closest('form').hasClass('disabled-without-errors') ) { 63 | $elem.hide(); 64 | } 65 | }); 66 | 67 | })(jQuery, window); 68 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/toggleDisabled.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | !function(a,b,c){"use strict";var d=function(a,b){"disabled"===b?a.find('*[type="submit"]').addClass("disabled").attr("disabled","disabled"):a.find('*[type="submit"]').removeClass("disabled").removeAttr("disabled")},e=!1;a(b).bind("validatorsLoaded formValidationSetup",function(b,f,g){var h=g.disabledFormFilter?f.filter(g.disabledFormFilter):f,i=g.showErrorDialogs===c||g.showErrorDialogs;h.addClass(i?"disabled-with-errors":"disabled-without-errors").find("*[data-validation]").attr("data-validation-event","keyup").on("validation",function(b,c){if(!e){e=!0;var f=a(this).closest("form");c&&f.isValid(g,g.language,!1)?d(f,"enabled"):d(f,"disabled"),e=!1}}),d(h,"disabled"),h.validateOnEvent(g.language,g)}).on("validationErrorDisplay",function(a,b,c){b.closest("form").hasClass("disabled-without-errors")&&c.hide()})}(jQuery,window); -------------------------------------------------------------------------------- /www/dist/js/form-validator/uk.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Form Validator Module: Security 3 | * ------------------------------------------ 4 | * Created by Victor Jonsson 5 | * 6 | * This form validation module adds validators typically used on 7 | * websites in the UK. This module adds the following validators: 8 | * - ukvatnumber 9 | * 10 | * @website http://formvalidator.net/#uk-validators 11 | * @license MIT 12 | * @version 2.2.83 13 | */ 14 | $.formUtils.addValidator({ 15 | name : 'ukvatnumber', 16 | validatorFunction : function(number) { 17 | 18 | // Code Adapted from http://www.codingforums.com/showthread.php?t=211967 19 | // TODO: Extra Checking for other VAT Numbers (Other countries and UK Government/Health Authorities) 20 | 21 | number = number.replace(/[^0-9]/g, ''); 22 | 23 | //Check Length 24 | if(number.length < 9) { 25 | return false; 26 | } 27 | 28 | var valid = false; 29 | 30 | var VATsplit = []; 31 | VATsplit = number.split(''); 32 | 33 | var checkDigits = Number(VATsplit[7] + VATsplit[8]); // two final digits as a number 34 | 35 | var firstDigit = VATsplit[0]; 36 | var secondDigit = VATsplit[1]; 37 | if ((firstDigit === 0) && (secondDigit > 0)) { 38 | return false; 39 | } 40 | 41 | var total = 0; 42 | for (var i = 0; i < 7; i++) { // first 7 digits 43 | total += VATsplit[i]* (8-i); // sum weighted cumulative total 44 | } 45 | 46 | var c = 0; 47 | var j = 0; 48 | 49 | for (var m = 8; m >= 2; m--) { 50 | c += VATsplit[j] * m; 51 | j++; 52 | } 53 | 54 | // Traditional Algorithm for VAT numbers issued before 2010 55 | 56 | while (total > 0) { 57 | total -= 97; // deduct 97 repeatedly until total is negative 58 | } 59 | total = Math.abs(total); // make positive 60 | 61 | if (checkDigits === total) { 62 | valid = true; 63 | } 64 | 65 | // If not valid try the new method (introduced November 2009) by subtracting 55 from the mod 97 check digit if we can - else add 42 66 | 67 | if (!valid) { 68 | total = total%97; // modulus 97 69 | 70 | if (total >= 55) { 71 | total = total - 55; 72 | } else { 73 | total = total + 42; 74 | } 75 | 76 | if (total === checkDigits) { 77 | valid = true; 78 | } 79 | } 80 | 81 | return valid; 82 | }, 83 | errorMessage : '', 84 | errorMessageKey: 'badUKVatAnswer' 85 | }); 86 | -------------------------------------------------------------------------------- /www/dist/js/form-validator/uk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * JQUERY-FORM-VALIDATOR 3 | * 4 | * @website by 5 | * @license MIT 6 | * @version 2.2.83 7 | */ 8 | $.formUtils.addValidator({name:"ukvatnumber",validatorFunction:function(a){if(a=a.replace(/[^0-9]/g,""),a.length<9)return!1;var b=!1,c=[];c=a.split("");var d=Number(c[7]+c[8]),e=c[0],f=c[1];if(0===e&&f>0)return!1;for(var g=0,h=0;7>h;h++)g+=c[h]*(8-h);for(var i=0,j=0,k=8;k>=2;k--)i+=c[j]*k,j++;for(;g>0;)g-=97;return g=Math.abs(g),d===g&&(b=!0),b||(g%=97,g>=55?g-=55:g+=42,g===d&&(b=!0)),b},errorMessage:"",errorMessageKey:"badUKVatAnswer"}); -------------------------------------------------------------------------------- /www/dist/js/shake.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Alex Gibson 3 | * https://github.com/alexgibson/shake.js 4 | * License: MIT license 5 | */ 6 | 7 | (function(global, factory) { 8 | if (typeof define === 'function' && define.amd) { 9 | define(function() { 10 | return factory(global, global.document); 11 | }); 12 | } else if (typeof module !== 'undefined' && module.exports) { 13 | module.exports = factory(global, global.document); 14 | } else { 15 | global.Shake = factory(global, global.document); 16 | } 17 | } (typeof window !== 'undefined' ? window : this, function (window, document) { 18 | 19 | 'use strict'; 20 | 21 | function Shake(options) { 22 | //feature detect 23 | this.hasDeviceMotion = 'ondevicemotion' in window; 24 | 25 | this.options = { 26 | threshold: 15, //default velocity threshold for shake to register 27 | timeout: 1000 //default interval between events 28 | }; 29 | 30 | if (typeof options === 'object') { 31 | for (var i in options) { 32 | if (options.hasOwnProperty(i)) { 33 | this.options[i] = options[i]; 34 | } 35 | } 36 | } 37 | 38 | //use date to prevent multiple shakes firing 39 | this.lastTime = new Date(); 40 | 41 | //accelerometer values 42 | this.lastX = null; 43 | this.lastY = null; 44 | this.lastZ = null; 45 | 46 | //create custom event 47 | if (typeof document.CustomEvent === 'function') { 48 | this.event = new document.CustomEvent('shake', { 49 | bubbles: true, 50 | cancelable: true 51 | }); 52 | } else if (typeof document.createEvent === 'function') { 53 | this.event = document.createEvent('Event'); 54 | this.event.initEvent('shake', true, true); 55 | } else { 56 | return false; 57 | } 58 | } 59 | 60 | //reset timer values 61 | Shake.prototype.reset = function () { 62 | this.lastTime = new Date(); 63 | this.lastX = null; 64 | this.lastY = null; 65 | this.lastZ = null; 66 | }; 67 | 68 | //start listening for devicemotion 69 | Shake.prototype.start = function () { 70 | this.reset(); 71 | if (this.hasDeviceMotion) { 72 | window.addEventListener('devicemotion', this, false); 73 | } 74 | }; 75 | 76 | //stop listening for devicemotion 77 | Shake.prototype.stop = function () { 78 | if (this.hasDeviceMotion) { 79 | window.removeEventListener('devicemotion', this, false); 80 | } 81 | this.reset(); 82 | }; 83 | 84 | //calculates if shake did occur 85 | Shake.prototype.devicemotion = function (e) { 86 | var current = e.accelerationIncludingGravity; 87 | var currentTime; 88 | var timeDifference; 89 | var deltaX = 0; 90 | var deltaY = 0; 91 | var deltaZ = 0; 92 | 93 | if ((this.lastX === null) && (this.lastY === null) && (this.lastZ === null)) { 94 | this.lastX = current.x; 95 | this.lastY = current.y; 96 | this.lastZ = current.z; 97 | return; 98 | } 99 | 100 | deltaX = Math.abs(this.lastX - current.x); 101 | deltaY = Math.abs(this.lastY - current.y); 102 | deltaZ = Math.abs(this.lastZ - current.z); 103 | 104 | if (((deltaX > this.options.threshold) && (deltaY > this.options.threshold)) || ((deltaX > this.options.threshold) && (deltaZ > this.options.threshold)) || ((deltaY > this.options.threshold) && (deltaZ > this.options.threshold))) { 105 | //calculate time in milliseconds since last shake registered 106 | currentTime = new Date(); 107 | timeDifference = currentTime.getTime() - this.lastTime.getTime(); 108 | 109 | if (timeDifference > this.options.timeout) { 110 | window.dispatchEvent(this.event); 111 | this.lastTime = new Date(); 112 | } 113 | } 114 | 115 | this.lastX = current.x; 116 | this.lastY = current.y; 117 | this.lastZ = current.z; 118 | 119 | }; 120 | 121 | //event handler 122 | Shake.prototype.handleEvent = function (e) { 123 | if (typeof (this[e.type]) === 'function') { 124 | return this[e.type](e); 125 | } 126 | }; 127 | 128 | return Shake; 129 | })); 130 | -------------------------------------------------------------------------------- /www/js/RFcodes.js: -------------------------------------------------------------------------------- 1 | ;(function (window) { 2 | // events (publish subscribe) pattern [aka Event Emitter] 3 | var _events = { 4 | events: {}, 5 | on: function (eventName, fn) { 6 | this.events[eventName] = this.events[eventName] || [] 7 | this.events[eventName].push(fn) 8 | }, 9 | off: function (eventName, fn) { 10 | if (this.events[eventName]) { 11 | for (var i = 0; i < this.events[eventName].length; i++) { 12 | if (this.events[eventName][i] === fn) { 13 | this.events[eventName].splice(i, 1) 14 | break 15 | } 16 | } 17 | } 18 | }, 19 | emit: function (eventName, data) { 20 | if (this.events[eventName]) { 21 | this.events[eventName].forEach(function (fn) { 22 | fn(data) 23 | }) 24 | } 25 | } 26 | } 27 | 28 | var Codes = function () { // Class RFcodes 29 | // Attributes 30 | this.incoming_codes = {} 31 | 32 | // Methods 33 | this.putCode = function (code, data) { 34 | this.incoming_codes[code] = data 35 | _events.emit('newCode', code) // emit event 36 | } 37 | 38 | this.deleteCode = function (code) { 39 | delete this.incoming_codes[code] 40 | _events.emit('removedCode', code) // emit event 41 | } 42 | 43 | this.deleteCodes = function (codesArray) { 44 | var self = this 45 | codesArray.forEach(function (code) { 46 | self.deleteCode(code) 47 | }) 48 | } 49 | 50 | this.getCodesInHTML = function () { 51 | var html = '' 52 | Object.keys(this.incoming_codes).forEach(function (key) { 53 | html += '' 54 | }) 55 | return html 56 | } 57 | 58 | // event emitting methods 59 | this.on = function (event_name, callback) { 60 | _events.on(event_name, callback) 61 | } 62 | 63 | this.off = function (event_name, fn) { // Note: to be removed pass the same function used for the on listener. 64 | _events.off(event_name, fn) 65 | } 66 | 67 | this.emit = function (event_name, data) { 68 | _events.emit(event_name, data) 69 | } 70 | } 71 | 72 | /* Events provided: 73 | ** RFcodes.on('newCode', function(code){ . . .}); 74 | ** RFcodes.on('removedCode', function(code){ . . . }); 75 | ** 76 | ** We expose only the istanciated object to the global namespace 77 | */ 78 | window.RFcodes = new Codes() 79 | })(window) 80 | -------------------------------------------------------------------------------- /www/js/bg-handler.js: -------------------------------------------------------------------------------- 1 | if (window.localStorage) { 2 | if (localStorage.bg) { 3 | document.body.style.backgroundImage = "url('../assets/img/backgrounds/" + localStorage.bg + "')" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /www/js/client.socketing.js: -------------------------------------------------------------------------------- 1 | // set up your socket 2 | 3 | var socket = io.connect('//' + location.host, { 4 | 'reconnect': true, 5 | 'reconnection delay': 50, 6 | 'max reconnection attempts': 300 7 | }) 8 | 9 | socket.on('connect', function () { 10 | notie.alert(1, ' Connected to the server!', 3) 11 | ga('send', 'event', 'Socket', 'connection', 'connected') 12 | }) 13 | 14 | socket.on('connect_error', function () { 15 | console.log('WebSocket Connection error...') 16 | }) 17 | 18 | socket.on('disconnect', function () { 19 | notie.alert(3, ' Disconnected. Trying to reconnect... ', 0) 20 | ga('send', 'event', 'Socket', 'connection', 'disconnected') 21 | }) 22 | 23 | // receiving initCards, initialize the UI 24 | socket.on('initCards', function (initData) { 25 | events.emit('renderInitCards', initData) 26 | }) 27 | 28 | // handle the new RFCode. Show a snackbar. 29 | socket.on('newRFCode', function (data) { 30 | var _code = data.code 31 | events.emit('renderSnackbar', _code) 32 | ga('send', 'event', 'Core', 'newCode', 'New RF code', _code) 33 | }) 34 | 35 | // Randomize Cards, new shake detected on a mobile device 36 | socket.on('randomizeCards', function () { 37 | $('#cards_container').mixItUp('sort', 'random', true) 38 | ga('send', 'event', 'UI', 'shake', 'true') 39 | }) 40 | 41 | // commute the button on the UI. 42 | socket.on('uiSwitchToggle', function (data) { 43 | $('#switch-' + data.card_id).prop('checked', data.set) 44 | if (data.sound) ion.sound.play('switch-toggle') // sound notification 45 | ga('send', 'event', 'UI', 'switch', 'toggle') 46 | }) 47 | 48 | // trigger Alarm 49 | socket.on('uiTriggerAlarm', function (card) { 50 | events.emit('uiTriggerAlarm', card) 51 | ga('send', 'event', 'Core', 'alarm', 'Triggered') 52 | }) 53 | 54 | // need to update card dropdown menu mute status 55 | socket.on('uiMuteStatus', function (data) { 56 | events.emit('uiMuteStatus', data) 57 | }) 58 | 59 | // need to update card dropdown menu arm/disarm status 60 | socket.on('uiArmStatus', function (data) { 61 | events.emit('uiArmStatus', data) 62 | ga('send', 'event', 'Core', 'arm', 'Arm status update') 63 | }) 64 | 65 | socket.on('serverError', function (data) { 66 | // notie.js alert 67 | // TODO 68 | 69 | }) 70 | -------------------------------------------------------------------------------- /www/js/main.js: -------------------------------------------------------------------------------- 1 | 2 | // Cards 3 | 4 | $.material.init() 5 | $.material.ripples() 6 | // NB. on dynamic refresh always call these 2 lines below 7 | // $('#cards_container').mixItUp('destroy'); 8 | $('#cards_container').mixItUp({animation: { animateResizeContainer: false}}); 9 | 10 | // Handler to know if we are on a mobile device 11 | (function () { 12 | // media query event handler 13 | if (matchMedia) { // matchMedia supported 14 | var mq = window.matchMedia('(max-width: 600px)') 15 | mq.addListener(WidthChange) 16 | WidthChange(mq) 17 | } 18 | 19 | // media query change 20 | function WidthChange (mq) { 21 | if (mq.matches) { 22 | // window width is <= 600px 23 | templating.isMobile = true 24 | } else { 25 | // window width is more than 600px 26 | templating.isMobile = false 27 | } 28 | } 29 | 30 | // accelerometer supported 31 | if (typeof window.DeviceMotionEvent !== 'undefined') { templating.hasAccelerometer = true } else templating.hasAccelerometer = false 32 | })() 33 | 34 | // Init Iot.Sound 35 | 36 | // init bunch of sounds 37 | ion.sound({ 38 | sounds: [ 39 | {name: 'button_tiny'}, // for cards retrieved. 40 | {name: 'glass'}, 41 | {name: 'notification1'}, 42 | {name: 'switch-toggle'}, // for switch toggling 43 | {name: 'siren-sound', loop: 10}, // for alarm siren 44 | {name: 'water_droplet_3'} // for code detected (snackbar opened) 45 | ], 46 | 47 | // main config 48 | path: 'assets/sounds/', 49 | preload: true, 50 | multiplay: true, 51 | volume: 0.9 52 | }) 53 | 54 | // play sound: 55 | // ion.sound.play('button_tiny'); 56 | 57 | /* Handle Shake Event on Mobile Devices */ 58 | 59 | // create a new instance of shake.js. 60 | var myShakeEvent = new Shake({ 61 | threshold: 10 62 | }) 63 | 64 | // start listening to device motion 65 | myShakeEvent.start() 66 | 67 | // register a shake event 68 | window.addEventListener('shake', shakeEventDidOccur, false) 69 | 70 | // shake event callback 71 | function shakeEventDidOccur () { 72 | console.log('Shake detected!') 73 | events.emit('shakeOccurred') 74 | } 75 | 76 | /* Init Favicon js */ 77 | 78 | var favicon = new Favico({ 79 | animation: 'popFade' 80 | }) 81 | var badge = 0 82 | -------------------------------------------------------------------------------- /www/js/templating.js: -------------------------------------------------------------------------------- 1 | 2 | ;(function (window) { 3 | var templating = { 4 | isMobile: false, 5 | hasAccelerometer: false, 6 | dir: '/templates/', 7 | renderTemplate: function (templateFile, $domElem, view) { 8 | return new Promise(function (resolve, reject) { 9 | $.get(templating.dir + templateFile, function (template) { 10 | var rendered = Mustache.render(template, view) 11 | $domElem.html(rendered) 12 | resolve() 13 | }).fail(function () { 14 | reject('GET ' + templateFile + ' Error.') 15 | }) 16 | }) 17 | } 18 | } 19 | 20 | // exposing only 'templating' to the global namespace 21 | window.templating = templating 22 | })(window) 23 | -------------------------------------------------------------------------------- /www/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Internet of Things 433Mhz", 3 | "short_name": "IoT 433Mhz", 4 | "lang": "en-US", 5 | "start_url": "./index.html", 6 | "display": "standalone", 7 | "icons": [{ 8 | "src": "assets/img/icon_48.png", 9 | "sizes": "48x48", 10 | "type": "image/png" 11 | }, { 12 | "src": "assets/img/icon_128.png", 13 | "sizes": "128x128", 14 | "type": "image/png" 15 | }] 16 | } -------------------------------------------------------------------------------- /www/templates/about.mustache: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/templates/assignCode.mustache: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/templates/cards.mustache: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 8 |
9 | 14 | 19 |
20 |

Filter by

21 | 22 | {{#rooms}} 23 | 24 | {{/rooms}} 25 |
26 |
27 | 28 | 29 | 30 |
31 | 32 | 33 | {{#CARDS}} 34 |
35 | 36 |
37 | 38 | {{#img}} 39 |
40 | 41 |

{{headline}}

42 |
43 | {{/img}} 44 | 45 | 60 | 61 |
62 | {{{card_body}}} 63 |
64 | 65 |
66 | {{#device}} 67 | {{#on_code}} {{! Switch section}} 68 |
69 | 70 | 74 |
75 | {{/on_code}} 76 | {{#trigger_code}} {{! Alarm section}} 77 | 78 |
79 |
80 | Last alert: {{#last_alert}}{{last_alert}}{{/last_alert}}{{^last_alert}}never fired{{/last_alert}} 81 |
82 | 83 | {{/trigger_code}} 84 | {{/device}} 85 |
86 | 87 |
88 | 89 |
90 | {{/CARDS}} 91 | 92 | 93 | 94 |
95 | 96 | -------------------------------------------------------------------------------- /www/templates/ignoredCodes.mustache: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/templates/newCardForm.mustache: -------------------------------------------------------------------------------- 1 | 89 | -------------------------------------------------------------------------------- /www/templates/settings.mustache: -------------------------------------------------------------------------------- 1 | 69 | --------------------------------------------------------------------------------