\n
\n \n \n ";
- }
- return itemHtml.trim();
- };
-
- Autocomplete.prototype.renderNavbar = function renderNavbar () {
- var ac = this;
- if (ac.params.renderNavbar) { return ac.params.renderNavbar.call(ac); }
- var pageTitle = ac.params.pageTitle;
- if (typeof pageTitle === 'undefined' && ac.$openerEl && ac.$openerEl.length) {
- pageTitle = ac.$openerEl.find('.item-title').text().trim();
- }
- var navbarHtml = ("\n
\n
\n
\n " + (pageTitle ? ("
" + pageTitle + "
") : '') + "\n " + (ac.params.preloader ? ("\n
\n " + (ac.renderPreloader()) + "\n
\n ") : '') + "\n
" + (ac.renderSearchbar()) + "
\n
\n
\n ").trim();
- return navbarHtml;
- };
- Autocomplete.prototype.renderDropdown = function renderDropdown () {
- var ac = this;
- if (ac.params.renderDropdown) { return ac.params.renderDropdown.call(ac, ac.items); }
- var dropdownHtml = ("\n
\n
\n " + (ac.params.preloader ? ac.renderPreloader() : '') + "\n
\n ").trim();
- return dropdownHtml;
- };
- Autocomplete.prototype.renderPage = function renderPage () {
- var ac = this;
- if (ac.params.renderPage) { return ac.params.renderPage.call(ac, ac.items); }
-
- var pageHtml = ("\n
\n " + (ac.renderNavbar()) + "\n
\n
\n
\n
\n
\n " + (ac.params.notFoundText) + "
\n
\n
\n
\n
\n
\n ").trim();
- return pageHtml;
- };
- Autocomplete.prototype.renderPopup = function renderPopup () {
- var ac = this;
- if (ac.params.renderPopup) { return ac.params.renderPopup.call(ac, ac.items); }
- var popupHtml = ("\n \n ").trim();
- return popupHtml;
- };
- Autocomplete.prototype.onOpen = function onOpen (type, el) {
- var ac = this;
- var app = ac.app;
- var $el = $$1(el);
- ac.$el = $el;
- ac.el = $el[0];
- ac.openedIn = type;
- ac.opened = true;
-
- if (ac.params.openIn === 'dropdown') {
- ac.attachDropdownEvents();
-
- ac.$dropdownEl.addClass('autocomplete-dropdown-in');
- ac.$inputEl.trigger('input');
- } else {
- // Init SB
- var $searchbarEl = $el.find('.searchbar');
- if (ac.params.openIn === 'page' && app.theme === 'ios' && $searchbarEl.length === 0) {
- $searchbarEl = $$1(app.navbar.getElByPage($el)).find('.searchbar');
- }
- ac.searchbar = app.searchbar.create({
- el: $searchbarEl,
- backdropEl: $el.find('.searchbar-backdrop'),
- customSearch: true,
- on: {
- searchbarSearch: function searchbarSearch(sb, query) {
- if (query.length === 0 && ac.searchbar.enabled) {
- ac.searchbar.backdropShow();
- } else {
- ac.searchbar.backdropHide();
- }
- ac.source(query);
- },
- },
- });
-
- // Attach page events
- ac.attachPageEvents();
-
- // Update Values On Page Init
- ac.updateValues();
-
- // Source on load
- if (ac.params.requestSourceOnOpen) { ac.source(''); }
- }
-
- ac.emit('local::open autocompleteOpen', ac);
- };
- Autocomplete.prototype.onOpened = function onOpened () {
- var ac = this;
- if (ac.params.openIn !== 'dropdown' && ac.params.autoFocus) {
- ac.autoFocus();
- }
- ac.emit('local::opened autocompleteOpened', ac);
- };
- Autocomplete.prototype.onClose = function onClose () {
- var ac = this;
- if (ac.destroyed) { return; }
-
- // Destroy SB
- if (ac.searchbar && ac.searchbar.destroy) {
- ac.searchbar.destroy();
- ac.searchbar = null;
- delete ac.searchbar;
- }
-
- if (ac.params.openIn === 'dropdown') {
- ac.detachDropdownEvents();
- ac.$dropdownEl.removeClass('autocomplete-dropdown-in').remove();
- ac.$inputEl.parents('.item-content-dropdown-expanded').removeClass('item-content-dropdown-expanded');
- } else {
- ac.detachPageEvents();
- }
-
- ac.emit('local::close autocompleteClose', ac);
- };
- Autocomplete.prototype.onClosed = function onClosed () {
- var ac = this;
- if (ac.destroyed) { return; }
- ac.opened = false;
- ac.$el = null;
- ac.el = null;
- delete ac.$el;
- delete ac.el;
-
- ac.emit('local::closed autocompleteClosed', ac);
- };
- Autocomplete.prototype.openPage = function openPage () {
- var ac = this;
- if (ac.opened) { return ac; }
- var pageHtml = ac.renderPage();
- ac.view.router.navigate({
- url: ac.url,
- route: {
- content: pageHtml,
- path: ac.url,
- on: {
- pageBeforeIn: function pageBeforeIn(e, page) {
- ac.onOpen('page', page.el);
- },
- pageAfterIn: function pageAfterIn(e, page) {
- ac.onOpened('page', page.el);
- },
- pageBeforeOut: function pageBeforeOut(e, page) {
- ac.onClose('page', page.el);
- },
- pageAfterOut: function pageAfterOut(e, page) {
- ac.onClosed('page', page.el);
- },
- },
- options: {
- animate: ac.params.animate,
- },
- },
- });
- return ac;
- };
- Autocomplete.prototype.openPopup = function openPopup () {
- var ac = this;
- if (ac.opened) { return ac; }
- var popupHtml = ac.renderPopup();
-
- var popupParams = {
- content: popupHtml,
- animate: ac.params.animate,
- on: {
- popupOpen: function popupOpen(popup) {
- ac.onOpen('popup', popup.el);
- },
- popupOpened: function popupOpened(popup) {
- ac.onOpened('popup', popup.el);
- },
- popupClose: function popupClose(popup) {
- ac.onClose('popup', popup.el);
- },
- popupClosed: function popupClosed(popup) {
- ac.onClosed('popup', popup.el);
- },
- },
- };
-
- if (ac.params.routableModals) {
- ac.view.router.navigate({
- url: ac.url,
- route: {
- path: ac.url,
- popup: popupParams,
- },
- });
- } else {
- ac.modal = ac.app.popup.create(popupParams).open(ac.params.animate);
- }
- return ac;
- };
- Autocomplete.prototype.openDropdown = function openDropdown () {
- var ac = this;
-
- if (!ac.$dropdownEl) {
- ac.$dropdownEl = $$1(ac.renderDropdown());
- }
- var $listEl = ac.$inputEl.parents('.list');
- if ($listEl.length && ac.$inputEl.parents('.item-content').length > 0 && ac.params.expandInput) {
- ac.$inputEl.parents('.item-content').addClass('item-content-dropdown-expanded');
- }
- ac.positionDropDown();
- var $pageContentEl = ac.$inputEl.parents('.page-content');
- if (ac.params.dropdownel) {
- $$1(ac.params.dropdownel).append(ac.$dropdownEl);
- } else if ($pageContentEl.length === 0) {
- ac.$dropdownEl.insertAfter(ac.$inputEl);
- } else {
- $pageContentEl.append(ac.$dropdownEl);
- }
- ac.onOpen('dropdown', ac.$dropdownEl);
- ac.onOpened('dropdown', ac.$dropdownEl);
- };
- Autocomplete.prototype.open = function open () {
- var ac = this;
- if (ac.opened) { return ac; }
- var openIn = ac.params.openIn;
- ac[("open" + (openIn.split('').map(function (el, index) {
- if (index === 0) { return el.toUpperCase(); }
- return el;
- }).join('')))]();
- return ac;
- };
- Autocomplete.prototype.close = function close () {
- var ac = this;
- if (!ac.opened) { return ac; }
- if (ac.params.openIn === 'dropdown') {
- ac.onClose();
- ac.onClosed();
- } else if (ac.params.routableModals || ac.openedIn === 'page') {
- ac.view.router.back({ animate: ac.params.animate });
- } else {
- ac.modal.once('modalClosed', function () {
- Utils.nextTick(function () {
- ac.modal.destroy();
- delete ac.modal;
- });
- });
- ac.modal.close();
- }
- return ac;
- };
- Autocomplete.prototype.init = function init () {
- var ac = this;
- ac.attachEvents();
- };
- Autocomplete.prototype.destroy = function destroy () {
- var ac = this;
- ac.emit('local::beforeDestroy autocompleteBeforeDestroy', ac);
- ac.detachEvents();
- if (ac.$inputEl && ac.$inputEl[0]) {
- delete ac.$inputEl[0].f7Autocomplete;
- }
- if (ac.$openerEl && ac.$openerEl[0]) {
- delete ac.$openerEl[0].f7Autocomplete;
- }
- Utils.deleteProps(ac);
- ac.destroyed = true;
- };
-
- return Autocomplete;
- }(Framework7Class));
-
- var Autocomplete$1 = {
- name: 'autocomplete',
- params: {
- autocomplete: {
- openerEl: undefined,
- inputEl: undefined,
- view: undefined,
-
- // DropDown
- dropdownContainerEl: undefined,
- dropdownPlaceholderText: undefined,
- typeahead: false,
- highlightMatches: true,
- expandInput: false,
- updateInputValueOnSelect: true,
- inputEvents: 'input',
-
- value: undefined,
- multiple: false,
-
- source: undefined,
- limit: undefined,
- valueProperty: 'id',
- textProperty: 'text',
-
- openIn: 'page', // or 'popup' or 'dropdown'
- pageBackLinkText: 'Back',
- popupCloseLinkText: 'Close',
- pageTitle: undefined,
- searchbarPlaceholder: 'Search...',
- searchbarDisableText: 'Cancel',
-
- animate: true,
-
- autoFocus: false,
- closeOnSelect: false,
- notFoundText: 'Nothing found',
- requestSourceOnOpen: false,
-
- // Preloader
- preloaderColor: undefined,
- preloader: false,
-
- // Colors
- formColorTheme: undefined,
- navbarColorTheme: undefined,
-
- // Routing
- routableModals: true,
- url: 'select/',
-
- // Custom render functions
- renderDropdown: undefined,
- renderPage: undefined,
- renderPopup: undefined,
- renderItem: undefined,
- renderSearchbar: undefined,
- renderNavbar: undefined,
-
- },
- },
- static: {
- Autocomplete: Autocomplete,
- },
- create: function create() {
- var app = this;
- app.autocomplete = Utils.extend(
- ConstructorMethods({
- defaultSelector: undefined,
- constructor: Autocomplete,
- app: app,
- domProp: 'f7Autocomplete',
- }),
- {
- open: function open(autocompleteEl) {
- var ac = app.autocomplete.get(autocompleteEl);
- if (ac && ac.open) { return ac.open(); }
- return undefined;
- },
- close: function close(autocompleteEl) {
- var ac = app.autocomplete.get(autocompleteEl);
- if (ac && ac.close) { return ac.close(); }
- return undefined;
- },
- }
- );
- },
- };
-
- var ViAd = (function (Framework7Class$$1) {
- function ViAd(app, params) {
- if ( params === void 0 ) params = {};
-
- Framework7Class$$1.call(this, params, [app]);
- var vi = this;
- if (!win.vi) {
- throw new Error('f7:vi SDK not found.');
- }
-
- var orientation;
- if (typeof win.orientation !== 'undefined') {
- orientation = win.orientation === -90 || win.orientation === 90 ? 'horizontal' : 'vertical';
- }
- var defaults = Utils.extend(
- {},
- app.params.vi,
- {
- appId: app.id,
- appVer: app.version,
- language: app.language,
- width: app.width,
- height: app.height,
- os: Device.os,
- osVersion: Device.osVersion,
- orientation: orientation,
- }
- );
-
- // Extend defaults with modules params
- vi.useModulesParams(defaults);
-
- vi.params = Utils.extend(defaults, params);
-
- var adParams = {};
- var skipParams = ('on autoplay fallbackOverlay fallbackOverlayText enabled').split(' ');
- Object.keys(vi.params).forEach(function (paramName) {
- if (skipParams.indexOf(paramName) >= 0) { return; }
- var paramValue = vi.params[paramName];
- if ([null, undefined].indexOf(paramValue) >= 0) { return; }
- adParams[paramName] = paramValue;
- });
-
- if (!vi.params.appId) {
- throw new Error('Framework7:"app.id" is required to display an ad. Make sure you have specified it on app initialization.');
- }
- if (!vi.params.placementId) {
- throw new Error('Framework7:"placementId" is required to display an ad.');
- }
-
- function onResize() {
- var $viFrame = $$1('iframe#viAd');
- if ($viFrame.length === 0) { return; }
- $viFrame
- .css({
- width: ((app.width) + "px"),
- height: ((app.height) + "px"),
- });
- }
-
- function removeOverlay() {
- if (!vi.$overlayEl) { return; }
- vi.$overlayEl.off('click touchstart');
- vi.$overlayEl.remove();
- }
- function createOverlay(videoEl) {
- if (!videoEl) { return; }
- vi.$overlayEl = $$1(("\n
\n " + (vi.params.fallbackOverlayText ? ("
" + (vi.params.fallbackOverlayText) + "
") : '') + "\n
\n
\n ").trim());
-
- var touchStartTime;
- vi.$overlayEl.on('touchstart', function () {
- touchStartTime = Utils.now();
- });
- vi.$overlayEl.on('click', function () {
- var timeDiff = Utils.now() - touchStartTime;
- if (timeDiff > 300) { return; }
- if (videoEl) {
- videoEl.play();
- removeOverlay();
- return;
- }
- vi.start();
- removeOverlay();
- });
- app.root.append(vi.$overlayEl);
- }
-
- // Create ad
- vi.ad = new win.vi.Ad(adParams);
-
- Utils.extend(vi.ad, {
- onAdReady: function onAdReady() {
- app.on('resize', onResize);
- vi.emit('local::ready');
- if (vi.params.autoplay) {
- vi.start();
- }
- },
- onAdStarted: function onAdStarted() {
- vi.emit('local::started');
- },
- onAdClick: function onAdClick(targetUrl) {
- vi.emit('local::click', targetUrl);
- },
- onAdImpression: function onAdImpression() {
- vi.emit('local::impression');
- },
- onAdStopped: function onAdStopped(reason) {
- app.off('resize', onResize);
- removeOverlay();
-
- vi.emit('local::stopped', reason);
- if (reason === 'complete') {
- vi.emit('local::complete');
- vi.emit('local::completed');
- }
- if (reason === 'userexit') {
- vi.emit('local::userexit');
- }
- vi.destroyed = true;
- },
- onAutoPlayFailed: function onAutoPlayFailed(reason, videoEl) {
- vi.emit('local::autoplayFailed', reason, videoEl);
- if (reason && reason.name && reason.name.indexOf('NotAllowedError') !== -1 && vi.params.fallbackOverlay) {
- createOverlay(videoEl);
- }
- },
- onAdError: function onAdError(msg) {
- removeOverlay();
- app.off('resize', onResize);
- vi.emit('local::error', msg);
- vi.destroyed = true;
- },
- });
-
- vi.init();
-
- Utils.extend(vi, {
- app: app,
- });
- }
-
- if ( Framework7Class$$1 ) ViAd.__proto__ = Framework7Class$$1;
- ViAd.prototype = Object.create( Framework7Class$$1 && Framework7Class$$1.prototype );
- ViAd.prototype.constructor = ViAd;
- ViAd.prototype.start = function start () {
- var vi = this;
- if (vi.destroyed) { return; }
- if (vi.ad) { vi.ad.startAd(); }
- };
- ViAd.prototype.pause = function pause () {
- var vi = this;
- if (vi.destroyed) { return; }
- if (vi.ad) { vi.ad.pauseAd(); }
- };
- ViAd.prototype.resume = function resume () {
- var vi = this;
- if (vi.destroyed) { return; }
- if (vi.ad) { vi.ad.resumeAd(); }
- };
- ViAd.prototype.stop = function stop () {
- var vi = this;
- if (vi.destroyed) { return; }
- if (vi.ad) { vi.ad.stopAd(); }
- };
- ViAd.prototype.init = function init () {
- var vi = this;
- if (vi.destroyed) { return; }
- if (vi.ad) { vi.ad.initAd(); }
- };
- ViAd.prototype.destroy = function destroy () {
- var vi = this;
- vi.destroyed = true;
- vi.emit('local::beforeDestroy');
- Utils.deleteProps(vi);
- };
-
- return ViAd;
- }(Framework7Class));
-
- var Vi = {
- name: 'vi',
- params: {
- vi: {
- enabled: false,
- autoplay: true,
- fallbackOverlay: true,
- fallbackOverlayText: 'Please watch this ad',
- showMute: true,
- startMuted: (Device.ios || Device.android) && !Device.cordova,
- appId: null,
- appVer: null,
- language: null,
- width: null,
- height: null,
- placementId: 'pltd4o7ibb9rc653x14',
- placementType: 'interstitial',
- videoSlot: null,
- showProgress: true,
- showBranding: true,
- os: null,
- osVersion: null,
- orientation: null,
- age: null,
- gender: null,
- advertiserId: null,
- latitude: null,
- longitude: null,
- accuracy: null,
- storeId: null,
- ip: null,
- manufacturer: null,
- model: null,
- connectionType: null,
- connectionProvider: null,
- },
- },
- create: function create() {
- var app = this;
- app.vi = {
- sdkReady: false,
- createAd: function createAd(adParams) {
- return new ViAd(app, adParams);
- },
- loadSdk: function loadSdk() {
- if (app.vi.skdReady) { return; }
- var script = doc.createElement('script');
- script.onload = function onload() {
- app.emit('viSdkReady');
- app.vi.skdReady = true;
- };
- script.src = 'https://c.vi-serve.com/viadshtml/vi.min.js';
- $$1('head').append(script);
- },
- };
- },
- on: {
- init: function init() {
- var app = this;
- if (app.params.vi.enabled || (app.passedParams.vi && app.passedParams.vi.enabled !== false)) { app.vi.loadSdk(); }
- },
- },
- };
-
- var Typography = {
- name: 'typography',
- };
-
- {
- if (typeof window !== 'undefined') {
- // Template7
- if (!window.Template7) { window.Template7 = Template7; }
-
- // Dom7
- if (!window.Dom7) { window.Dom7 = $$1; }
- }
- }
-
- // Install Core Modules & Components
- Framework7.use([
- DeviceModule,
- SupportModule,
- UtilsModule,
- ResizeModule,
- RequestModule,
- TouchModule,
- ClicksModule,
- Router$1,
- HistoryModule,
- StorageModule,
- Statusbar$1,
- View$1,
- Navbar$1,
- Toolbar$1,
- Subnavbar,
- TouchRipple$1,
- Modal$1,
- Dialog$1,
- Popup$1,
- LoginScreen$1,
- Popover$1,
- Actions$1,
- Sheet$1,
- Toast$1,
- Preloader$1,
- Progressbar$1,
- Sortable$1,
- Swipeout$1,
- Accordion$1,
- VirtualList$1,
- ListIndex$1,
- Timeline,
- Tabs,
- Panel$1,
- Card,
- Chip,
- Form,
- Input$1,
- Checkbox,
- Radio,
- Toggle$1,
- Range$1,
- Stepper$1,
- SmartSelect$1,
- Grid,
- Calendar$1,
- Picker$1,
- InfiniteScroll$1,
- PullToRefresh$1,
- Lazy$1,
- DataTable$1,
- Fab$1,
- Searchbar$1,
- Messages$1,
- Messagebar$1,
- Swiper$1,
- PhotoBrowser$1,
- Notification$1,
- Autocomplete$1,
- Vi,
- Typography
- ]);
-
- return Framework7;
-
-})));
-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.io=e():t.io=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t,e){"object"===("undefined"==typeof t?"undefined":o(t))&&(e=t,t=void 0),e=e||{};var n,r=i(t),s=r.source,u=r.id,h=r.path,f=p[u]&&h in p[u].nsps,l=e.forceNew||e["force new connection"]||!1===e.multiplex||f;return l?(c("ignoring socket cache for %s",s),n=a(s,e)):(p[u]||(c("new io instance for %s",s),p[u]=a(s,e)),n=p[u]),r.query&&!e.query&&(e.query=r.query),n.socket(r.path,e)}var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=n(1),s=n(7),a=n(13),c=n(3)("socket.io-client");t.exports=e=r;var p=e.managers={};e.protocol=s.protocol,e.connect=r,e.Manager=n(13),e.Socket=n(37)},function(t,e,n){(function(e){"use strict";function r(t,n){var r=t;n=n||e.location,null==t&&(t=n.protocol+"//"+n.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?n.protocol+t:n.host+t),/^(https?|wss?):\/\//.test(t)||(i("protocol-less url %s",t),t="undefined"!=typeof n?n.protocol+"//"+t:"https://"+t),i("parse %s",t),r=o(t)),r.port||(/^(http|ws)$/.test(r.protocol)?r.port="80":/^(http|ws)s$/.test(r.protocol)&&(r.port="443")),r.path=r.path||"/";var s=r.host.indexOf(":")!==-1,a=s?"["+r.host+"]":r.host;return r.id=r.protocol+"://"+a+":"+r.port,r.href=r.protocol+"://"+a+(n&&n.port===r.port?"":":"+r.port),r}var o=n(2),i=n(3)("socket.io-client:url");t.exports=r}).call(e,function(){return this}())},function(t,e){var n=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,r=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];t.exports=function(t){var e=t,o=t.indexOf("["),i=t.indexOf("]");o!=-1&&i!=-1&&(t=t.substring(0,o)+t.substring(o,i).replace(/:/g,";")+t.substring(i,t.length));for(var s=n.exec(t||""),a={},c=14;c--;)a[r[c]]=s[c]||"";return o!=-1&&i!=-1&&(a.source=e,a.host=a.host.substring(1,a.host.length-1).replace(/;/g,":"),a.authority=a.authority.replace("[","").replace("]","").replace(/;/g,":"),a.ipv6uri=!0),a}},function(t,e,n){(function(r){function o(){return!("undefined"==typeof window||!window.process||"renderer"!==window.process.type)||("undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))}function i(t){var n=this.useColors;if(t[0]=(n?"%c":"")+this.namespace+(n?" %c":" ")+t[0]+(n?"%c ":" ")+"+"+e.humanize(this.diff),n){var r="color: "+this.color;t.splice(1,0,r,"color: inherit");var o=0,i=0;t[0].replace(/%[a-zA-Z%]/g,function(t){"%%"!==t&&(o++,"%c"===t&&(i=o))}),t.splice(i,0,r)}}function s(){return"object"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function a(t){try{null==t?e.storage.removeItem("debug"):e.storage.debug=t}catch(n){}}function c(){var t;try{t=e.storage.debug}catch(n){}return!t&&"undefined"!=typeof r&&"env"in r&&(t=r.env.DEBUG),t}function p(){try{return window.localStorage}catch(t){}}e=t.exports=n(5),e.log=s,e.formatArgs=i,e.save=a,e.load=c,e.useColors=o,e.storage="undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage?chrome.storage.local:p(),e.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],e.formatters.j=function(t){try{return JSON.stringify(t)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}},e.enable(c())}).call(e,n(4))},function(t,e){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(t){if(u===setTimeout)return setTimeout(t,0);if((u===n||!u)&&setTimeout)return u=setTimeout,setTimeout(t,0);try{return u(t,0)}catch(e){try{return u.call(null,t,0)}catch(e){return u.call(this,t,0)}}}function i(t){if(h===clearTimeout)return clearTimeout(t);if((h===r||!h)&&clearTimeout)return h=clearTimeout,clearTimeout(t);try{return h(t)}catch(e){try{return h.call(null,t)}catch(e){return h.call(this,t)}}}function s(){y&&l&&(y=!1,l.length?d=l.concat(d):m=-1,d.length&&a())}function a(){if(!y){var t=o(s);y=!0;for(var e=d.length;e;){for(l=d,d=[];++m
1)for(var n=1;n100)){var e=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(t);if(e){var n=parseFloat(e[1]),r=(e[2]||"ms").toLowerCase();switch(r){case"years":case"year":case"yrs":case"yr":case"y":return n*u;case"days":case"day":case"d":return n*p;case"hours":case"hour":case"hrs":case"hr":case"h":return n*c;case"minutes":case"minute":case"mins":case"min":case"m":return n*a;case"seconds":case"second":case"secs":case"sec":case"s":return n*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n;default:return}}}}function r(t){return t>=p?Math.round(t/p)+"d":t>=c?Math.round(t/c)+"h":t>=a?Math.round(t/a)+"m":t>=s?Math.round(t/s)+"s":t+"ms"}function o(t){return i(t,p,"day")||i(t,c,"hour")||i(t,a,"minute")||i(t,s,"second")||t+" ms"}function i(t,e,n){if(!(t0)return n(t);if("number"===i&&isNaN(t)===!1)return e["long"]?o(t):r(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))}},function(t,e,n){function r(){}function o(t){var n=""+t.type;return e.BINARY_EVENT!==t.type&&e.BINARY_ACK!==t.type||(n+=t.attachments+"-"),t.nsp&&"/"!==t.nsp&&(n+=t.nsp+","),null!=t.id&&(n+=t.id),null!=t.data&&(n+=JSON.stringify(t.data)),h("encoded %j as %s",t,n),n}function i(t,e){function n(t){var n=d.deconstructPacket(t),r=o(n.packet),i=n.buffers;i.unshift(r),e(i)}d.removeBlobs(t,n)}function s(){this.reconstructor=null}function a(t){var n=0,r={type:Number(t.charAt(0))};if(null==e.types[r.type])return u();if(e.BINARY_EVENT===r.type||e.BINARY_ACK===r.type){for(var o="";"-"!==t.charAt(++n)&&(o+=t.charAt(n),n!=t.length););if(o!=Number(o)||"-"!==t.charAt(n))throw new Error("Illegal attachments");r.attachments=Number(o)}if("/"===t.charAt(n+1))for(r.nsp="";++n;){var i=t.charAt(n);if(","===i)break;if(r.nsp+=i,n===t.length)break}else r.nsp="/";var s=t.charAt(n+1);if(""!==s&&Number(s)==s){for(r.id="";++n;){var i=t.charAt(n);if(null==i||Number(i)!=i){--n;break}if(r.id+=t.charAt(n),n===t.length)break}r.id=Number(r.id)}return t.charAt(++n)&&(r=c(r,t.substr(n))),h("decoded %s as %j",t,r),r}function c(t,e){try{t.data=JSON.parse(e)}catch(n){return u()}return t}function p(t){this.reconPack=t,this.buffers=[]}function u(){return{type:e.ERROR,data:"parser error"}}var h=n(3)("socket.io-parser"),f=n(8),l=n(9),d=n(11),y=n(12);e.protocol=4,e.types=["CONNECT","DISCONNECT","EVENT","ACK","ERROR","BINARY_EVENT","BINARY_ACK"],e.CONNECT=0,e.DISCONNECT=1,e.EVENT=2,e.ACK=3,e.ERROR=4,e.BINARY_EVENT=5,e.BINARY_ACK=6,e.Encoder=r,e.Decoder=s,r.prototype.encode=function(t,n){if(t.type!==e.EVENT&&t.type!==e.ACK||!l(t.data)||(t.type=t.type===e.EVENT?e.BINARY_EVENT:e.BINARY_ACK),h("encoding packet %j",t),e.BINARY_EVENT===t.type||e.BINARY_ACK===t.type)i(t,n);else{var r=o(t);n([r])}},f(s.prototype),s.prototype.add=function(t){var n;if("string"==typeof t)n=a(t),e.BINARY_EVENT===n.type||e.BINARY_ACK===n.type?(this.reconstructor=new p(n),0===this.reconstructor.reconPack.attachments&&this.emit("decoded",n)):this.emit("decoded",n);else{if(!y(t)&&!t.base64)throw new Error("Unknown type: "+t);if(!this.reconstructor)throw new Error("got binary data when not reconstructing a packet");n=this.reconstructor.takeBinaryData(t),n&&(this.reconstructor=null,this.emit("decoded",n))}},s.prototype.destroy=function(){this.reconstructor&&this.reconstructor.finishedReconstruction()},p.prototype.takeBinaryData=function(t){if(this.buffers.push(t),this.buffers.length===this.reconPack.attachments){var e=d.reconstructPacket(this.reconPack,this.buffers);return this.finishedReconstruction(),e}return null},p.prototype.finishedReconstruction=function(){this.reconPack=null,this.buffers=[]}},function(t,e,n){function r(t){if(t)return o(t)}function o(t){for(var e in r.prototype)t[e]=r.prototype[e];return t}t.exports=r,r.prototype.on=r.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},r.prototype.once=function(t,e){function n(){this.off(t,n),e.apply(this,arguments)}return n.fn=e,this.on(t,n),this},r.prototype.off=r.prototype.removeListener=r.prototype.removeAllListeners=r.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var r,o=0;o0&&!this.encoding){var t=this.packetBuffer.shift();this.packet(t)}},r.prototype.cleanup=function(){h("cleanup");for(var t=this.subs.length,e=0;e=this._reconnectionAttempts)h("reconnect failed"),this.backoff.reset(),this.emitAll("reconnect_failed"),this.reconnecting=!1;else{var e=this.backoff.duration();h("will wait %dms before reconnect attempt",e),this.reconnecting=!0;var n=setTimeout(function(){t.skipReconnect||(h("attempting reconnect"),t.emitAll("reconnect_attempt",t.backoff.attempts),t.emitAll("reconnecting",t.backoff.attempts),t.skipReconnect||t.open(function(e){e?(h("reconnect attempt error"),t.reconnecting=!1,t.reconnect(),t.emitAll("reconnect_error",e.data)):(h("reconnect success"),t.onreconnect())}))},e);this.subs.push({destroy:function(){clearTimeout(n)}})}},r.prototype.onreconnect=function(){var t=this.backoff.attempts;this.reconnecting=!1,this.backoff.reset(),this.updateSocketIds(),this.emitAll("reconnect",t)}},function(t,e,n){t.exports=n(15),t.exports.parser=n(22)},function(t,e,n){(function(e){function r(t,n){if(!(this instanceof r))return new r(t,n);n=n||{},t&&"object"==typeof t&&(n=t,t=null),t?(t=u(t),n.hostname=t.host,n.secure="https"===t.protocol||"wss"===t.protocol,n.port=t.port,t.query&&(n.query=t.query)):n.host&&(n.hostname=u(n.host).host),this.secure=null!=n.secure?n.secure:e.location&&"https:"===location.protocol,n.hostname&&!n.port&&(n.port=this.secure?"443":"80"),this.agent=n.agent||!1,this.hostname=n.hostname||(e.location?location.hostname:"localhost"),this.port=n.port||(e.location&&location.port?location.port:this.secure?443:80),this.query=n.query||{},"string"==typeof this.query&&(this.query=h.decode(this.query)),this.upgrade=!1!==n.upgrade,this.path=(n.path||"/engine.io").replace(/\/$/,"")+"/",this.forceJSONP=!!n.forceJSONP,this.jsonp=!1!==n.jsonp,this.forceBase64=!!n.forceBase64,this.enablesXDR=!!n.enablesXDR,this.timestampParam=n.timestampParam||"t",this.timestampRequests=n.timestampRequests,this.transports=n.transports||["polling","websocket"],this.transportOptions=n.transportOptions||{},this.readyState="",this.writeBuffer=[],this.prevBufferLen=0,this.policyPort=n.policyPort||843,this.rememberUpgrade=n.rememberUpgrade||!1,this.binaryType=null,this.onlyBinaryUpgrades=n.onlyBinaryUpgrades,this.perMessageDeflate=!1!==n.perMessageDeflate&&(n.perMessageDeflate||{}),!0===this.perMessageDeflate&&(this.perMessageDeflate={}),this.perMessageDeflate&&null==this.perMessageDeflate.threshold&&(this.perMessageDeflate.threshold=1024),this.pfx=n.pfx||null,this.key=n.key||null,this.passphrase=n.passphrase||null,this.cert=n.cert||null,this.ca=n.ca||null,this.ciphers=n.ciphers||null,this.rejectUnauthorized=void 0===n.rejectUnauthorized||n.rejectUnauthorized,this.forceNode=!!n.forceNode;var o="object"==typeof e&&e;o.global===o&&(n.extraHeaders&&Object.keys(n.extraHeaders).length>0&&(this.extraHeaders=n.extraHeaders),n.localAddress&&(this.localAddress=n.localAddress)),this.id=null,this.upgrades=null,this.pingInterval=null,this.pingTimeout=null,this.pingIntervalTimer=null,this.pingTimeoutTimer=null,this.open()}function o(t){var e={};for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}var i=n(16),s=n(8),a=n(3)("engine.io-client:socket"),c=n(36),p=n(22),u=n(2),h=n(30);t.exports=r,r.priorWebsocketSuccess=!1,s(r.prototype),r.protocol=p.protocol,r.Socket=r,r.Transport=n(21),r.transports=n(16),r.parser=n(22),r.prototype.createTransport=function(t){a('creating transport "%s"',t);var e=o(this.query);e.EIO=p.protocol,e.transport=t;var n=this.transportOptions[t]||{};this.id&&(e.sid=this.id);var r=new i[t]({query:e,socket:this,agent:n.agent||this.agent,hostname:n.hostname||this.hostname,port:n.port||this.port,secure:n.secure||this.secure,path:n.path||this.path,forceJSONP:n.forceJSONP||this.forceJSONP,jsonp:n.jsonp||this.jsonp,forceBase64:n.forceBase64||this.forceBase64,enablesXDR:n.enablesXDR||this.enablesXDR,timestampRequests:n.timestampRequests||this.timestampRequests,timestampParam:n.timestampParam||this.timestampParam,policyPort:n.policyPort||this.policyPort,pfx:n.pfx||this.pfx,key:n.key||this.key,passphrase:n.passphrase||this.passphrase,cert:n.cert||this.cert,ca:n.ca||this.ca,ciphers:n.ciphers||this.ciphers,rejectUnauthorized:n.rejectUnauthorized||this.rejectUnauthorized,perMessageDeflate:n.perMessageDeflate||this.perMessageDeflate,extraHeaders:n.extraHeaders||this.extraHeaders,forceNode:n.forceNode||this.forceNode,localAddress:n.localAddress||this.localAddress,requestTimeout:n.requestTimeout||this.requestTimeout,protocols:n.protocols||void 0});return r},r.prototype.open=function(){var t;if(this.rememberUpgrade&&r.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1)t="websocket";else{if(0===this.transports.length){var e=this;return void setTimeout(function(){e.emit("error","No transports available")},0)}t=this.transports[0]}this.readyState="opening";try{t=this.createTransport(t)}catch(n){return this.transports.shift(),void this.open()}t.open(),this.setTransport(t)},r.prototype.setTransport=function(t){a("setting transport %s",t.name);var e=this;this.transport&&(a("clearing existing transport %s",this.transport.name),this.transport.removeAllListeners()),this.transport=t,t.on("drain",function(){e.onDrain()}).on("packet",function(t){e.onPacket(t)}).on("error",function(t){e.onError(t)}).on("close",function(){e.onClose("transport close")})},r.prototype.probe=function(t){function e(){if(f.onlyBinaryUpgrades){var e=!this.supportsBinary&&f.transport.supportsBinary;h=h||e}h||(a('probe transport "%s" opened',t),u.send([{type:"ping",data:"probe"}]),u.once("packet",function(e){if(!h)if("pong"===e.type&&"probe"===e.data){if(a('probe transport "%s" pong',t),f.upgrading=!0,f.emit("upgrading",u),!u)return;r.priorWebsocketSuccess="websocket"===u.name,a('pausing current transport "%s"',f.transport.name),f.transport.pause(function(){h||"closed"!==f.readyState&&(a("changing transport and sending upgrade packet"),p(),f.setTransport(u),u.send([{type:"upgrade"}]),f.emit("upgrade",u),u=null,f.upgrading=!1,f.flush())})}else{a('probe transport "%s" failed',t);var n=new Error("probe error");n.transport=u.name,f.emit("upgradeError",n)}}))}function n(){h||(h=!0,p(),u.close(),u=null)}function o(e){var r=new Error("probe error: "+e);r.transport=u.name,n(),a('probe transport "%s" failed because of error: %s',t,e),f.emit("upgradeError",r)}function i(){o("transport closed")}function s(){o("socket closed")}function c(t){u&&t.name!==u.name&&(a('"%s" works - aborting "%s"',t.name,u.name),n())}function p(){u.removeListener("open",e),u.removeListener("error",o),u.removeListener("close",i),f.removeListener("close",s),f.removeListener("upgrading",c)}a('probing transport "%s"',t);var u=this.createTransport(t,{probe:1}),h=!1,f=this;r.priorWebsocketSuccess=!1,u.once("open",e),u.once("error",o),u.once("close",i),this.once("close",s),this.once("upgrading",c),u.open()},r.prototype.onOpen=function(){if(a("socket open"),this.readyState="open",r.priorWebsocketSuccess="websocket"===this.transport.name,this.emit("open"),this.flush(),"open"===this.readyState&&this.upgrade&&this.transport.pause){a("starting upgrade probes");for(var t=0,e=this.upgrades.length;t1?{type:b[o],data:t.substring(1)}:{type:b[o]}:w}var i=new Uint8Array(t),o=i[0],s=f(t,1);return k&&"blob"===n&&(s=new k([s])),{type:b[o],data:s}},e.decodeBase64Packet=function(t,e){var n=b[t.charAt(0)];if(!p)return{type:n,data:{base64:!0,data:t.substr(1)}};var r=p.decode(t.substr(1));return"blob"===e&&k&&(r=new k([r])),{type:n,data:r}},e.encodePayload=function(t,n,r){function o(t){return t.length+":"+t}function i(t,r){e.encodePacket(t,!!s&&n,!1,function(t){r(null,o(t))})}"function"==typeof n&&(r=n,n=null);var s=h(t);return n&&s?k&&!g?e.encodePayloadAsBlob(t,r):e.encodePayloadAsArrayBuffer(t,r):t.length?void c(t,i,function(t,e){return r(e.join(""))}):r("0:")},e.decodePayload=function(t,n,r){if("string"!=typeof t)return e.decodePayloadAsBinary(t,n,r);"function"==typeof n&&(r=n,n=null);var o;if(""===t)return r(w,0,1);for(var i,s,a="",c=0,p=t.length;c0;){for(var s=new Uint8Array(o),a=0===s[0],c="",p=1;255!==s[p];p++){if(c.length>310)return r(w,0,1);c+=s[p]}o=f(o,2+c.length),c=parseInt(c);var u=f(o,0,c);if(a)try{u=String.fromCharCode.apply(null,new Uint8Array(u))}catch(h){var l=new Uint8Array(u);u="";for(var p=0;pr&&(n=r),e>=r||e>=n||0===r)return new ArrayBuffer(0);for(var o=new Uint8Array(t),i=new Uint8Array(n-e),s=e,a=0;s=55296&&e<=56319&&o65535&&(e-=65536,o+=w(e>>>10&1023|55296),e=56320|1023&e),o+=w(e);return o}function c(t,e){if(t>=55296&&t<=57343){if(e)throw Error("Lone surrogate U+"+t.toString(16).toUpperCase()+" is not a scalar value");return!1}return!0}function p(t,e){return w(t>>e&63|128)}function u(t,e){if(0==(4294967168&t))return w(t);var n="";return 0==(4294965248&t)?n=w(t>>6&31|192):0==(4294901760&t)?(c(t,e)||(t=65533),n=w(t>>12&15|224),n+=p(t,6)):0==(4292870144&t)&&(n=w(t>>18&7|240),n+=p(t,12),n+=p(t,6)),n+=w(63&t|128)}function h(t,e){e=e||{};for(var n,r=!1!==e.strict,o=s(t),i=o.length,a=-1,c="";++a=v)throw Error("Invalid byte index");var t=255&g[b];if(b++,128==(192&t))return 63&t;throw Error("Invalid continuation byte")}function l(t){var e,n,r,o,i;if(b>v)throw Error("Invalid byte index");if(b==v)return!1;if(e=255&g[b],b++,0==(128&e))return e;if(192==(224&e)){if(n=f(),i=(31&e)<<6|n,i>=128)return i;throw Error("Invalid continuation byte")}if(224==(240&e)){if(n=f(),r=f(),i=(15&e)<<12|n<<6|r,i>=2048)return c(i,t)?i:65533;throw Error("Invalid continuation byte")}if(240==(248&e)&&(n=f(),r=f(),o=f(),i=(7&e)<<18|n<<12|r<<6|o,i>=65536&&i<=1114111))return i;throw Error("Invalid UTF-8 detected")}function d(t,e){e=e||{};var n=!1!==e.strict;g=s(t),v=g.length,b=0;for(var r,o=[];(r=l(n))!==!1;)o.push(r);return a(o)}var y="object"==typeof e&&e,m=("object"==typeof t&&t&&t.exports==y&&t,"object"==typeof o&&o);m.global!==m&&m.window!==m||(i=m);var g,v,b,w=String.fromCharCode,k={version:"2.1.2",encode:h,decode:d};r=function(){return k}.call(e,n,e,t),!(void 0!==r&&(t.exports=r))}(this)}).call(e,n(27)(t),function(){return this}())},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children=[],t.webpackPolyfill=1),t}},function(t,e){!function(){"use strict";for(var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=new Uint8Array(256),r=0;r>2],i+=t[(3&r[n])<<4|r[n+1]>>4],i+=t[(15&r[n+1])<<2|r[n+2]>>6],i+=t[63&r[n+2]];return o%3===2?i=i.substring(0,i.length-1)+"=":o%3===1&&(i=i.substring(0,i.length-2)+"=="),i},e.decode=function(t){var e,r,o,i,s,a=.75*t.length,c=t.length,p=0;"="===t[t.length-1]&&(a--,"="===t[t.length-2]&&a--);var u=new ArrayBuffer(a),h=new Uint8Array(u);for(e=0;e>4,h[p++]=(15&o)<<4|i>>2,h[p++]=(3&i)<<6|63&s;return u}}()},function(t,e){(function(e){function n(t){for(var e=0;e0);return e}function r(t){var e=0;for(u=0;u';i=document.createElement(e)}catch(t){i=document.createElement("iframe"),i.name=o.iframeId,i.src="javascript:0"}i.id=o.iframeId,o.form.appendChild(i),o.iframe=i}var o=this;if(!this.form){var i,s=document.createElement("form"),a=document.createElement("textarea"),u=this.iframeId="eio_iframe_"+this.index;s.className="socketio",s.style.position="absolute",s.style.top="-1000px",s.style.left="-1000px",s.target=u,s.method="POST",s.setAttribute("accept-charset","utf-8"),a.name="d",s.appendChild(a),document.body.appendChild(s),this.form=s,this.area=a}this.form.action=this.uri(),r(),t=t.replace(p,"\\\n"),this.area.value=t.replace(c,"\\n");try{this.form.submit()}catch(h){}this.iframe.attachEvent?this.iframe.onreadystatechange=function(){"complete"===o.iframe.readyState&&n()}:this.iframe.onload=n}}).call(e,function(){return this}())},function(t,e,n){(function(e){function r(t){var e=t&&t.forceBase64;e&&(this.supportsBinary=!1),this.perMessageDeflate=t.perMessageDeflate,this.usingBrowserWebSocket=h&&!t.forceNode,this.protocols=t.protocols,this.usingBrowserWebSocket||(l=o),i.call(this,t)}var o,i=n(21),s=n(22),a=n(30),c=n(31),p=n(32),u=n(3)("engine.io-client:websocket"),h=e.WebSocket||e.MozWebSocket;if("undefined"==typeof window)try{o=n(35)}catch(f){}var l=h;l||"undefined"!=typeof window||(l=o),t.exports=r,c(r,i),r.prototype.name="websocket",r.prototype.supportsBinary=!0,r.prototype.doOpen=function(){if(this.check()){var t=this.uri(),e=this.protocols,n={agent:this.agent,perMessageDeflate:this.perMessageDeflate};n.pfx=this.pfx,n.key=this.key,n.passphrase=this.passphrase,n.cert=this.cert,n.ca=this.ca,n.ciphers=this.ciphers,n.rejectUnauthorized=this.rejectUnauthorized,this.extraHeaders&&(n.headers=this.extraHeaders),this.localAddress&&(n.localAddress=this.localAddress);try{this.ws=this.usingBrowserWebSocket?e?new l(t,e):new l(t):new l(t,e,n)}catch(r){return this.emit("error",r)}void 0===this.ws.binaryType&&(this.supportsBinary=!1),this.ws.supports&&this.ws.supports.binary?(this.supportsBinary=!0,this.ws.binaryType="nodebuffer"):this.ws.binaryType="arraybuffer",this.addEventListeners()}},r.prototype.addEventListeners=function(){var t=this;this.ws.onopen=function(){t.onOpen()},this.ws.onclose=function(){t.onClose()},this.ws.onmessage=function(e){t.onData(e.data)},this.ws.onerror=function(e){t.onError("websocket error",e)}},r.prototype.write=function(t){function n(){r.emit("flush"),setTimeout(function(){r.writable=!0,r.emit("drain")},0)}var r=this;this.writable=!1;for(var o=t.length,i=0,a=o;i0&&t.jitter<=1?t.jitter:0,this.attempts=0}t.exports=n,n.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),n=Math.floor(e*this.jitter*t);t=0==(1&Math.floor(10*e))?t-n:t+n}return 0|Math.min(t,this.max)},n.prototype.reset=function(){this.attempts=0},n.prototype.setMin=function(t){this.ms=t},n.prototype.setMax=function(t){this.max=t},n.prototype.setJitter=function(t){this.jitter=t}}])});
-//# sourceMappingURL=socket.io.js.map
-
-/*
- * Custom scripts
- */
-var app_routes = [
- {
- path: '/radios/',
- templateUrl: './static/radios.html',
- on: {
- pageInit: function (e, page) {
- var request = {};
-
- request.action = 'radios_refresh';
- sendRequest(request, socket_radios);
-
- page.$el.find('#radios_action_btn').on('click', function () {
- radios_action_sheet.open();
- });
-
- page.$el.find('#lirc_update_btn').on('click', function () {
- var request = {};
-
- request.action = 'lirc_update';
- sendRequest(request, socket_remotes);
- });
- },
- }
- },
- {
- name: 'rc_create',
- path: '/rc_create/',
- templateUrl: './static/rc_create.html',
- on: {
- pageInit: function (e, page) {
- page.$el.find('#rc_save_btn').on('click', function () {
- app.input.validateInputs('#rc_create_form');
- var content = app.form.convertToData('#rc_create_form');
-
- if (content.rc_name && content.rc_icon) {
- var request = {};
- request.action = 'rc_save';
- request.content = content;
- sendRequest(request, socket_remotes);
- mainView.router.navigate('/radios/');
- }
- });
- },
- }
- },
- {
- name: 'radio_create',
- path: '/radio_create/',
- templateUrl: './static/radio_create.html',
- on: {
- pageInit: function (e, page) {
- page.$el.find('#radio_save_btn').on('click', function () {
- app.input.validateInputs('#radio_create_form');
- var content = app.form.convertToData('#radio_create_form');
-
- if (content.radio_name && content.radio_pipe && content.radio_order) {
- var request = {};
- request.action = 'radio_save';
- request.content = content;
- sendRequest(request, socket_radios);
- mainView.router.navigate('/radios/');
- }
- });
- },
- },
- },
- {
- name: 'rc',
- path: '/rc/:rc_id',
- templateUrl: './static/rc.html',
- on: {
- pageInit: function (e, page) {
- var rc_id = page.$el.attr('data-rc-id');
- var request = {};
-
- request.action = 'get_rc_buttons';
- request.content = {}
- request.content.rc_id = rc_id;
-
- sendRequest(request, socket_remotes);
- app.preloader.show();
-
- $$('#rc_action_sheet').on('click', function () {
- rc_action_sheet.open();
- });
- },
- pageAfterIn: function (e, page) {
- },
- },
- },
- {
- name: 'button',
- path: '/button/',
- templateUrl: './static/button.html',
- on: {
- pageInit: function (e, page) {
- page.$el.find('#catch_ir_signal_btn').on('click', function () {
- var request = {};
- request.action = 'catch_ir_signal';
- app.dialog.preloader('Waiting for signal');
- sendRequest(request, socket_remotes);
- });
-
- page.$el.find('#button_save_btn').on('click', function () {
- app.input.validateInputs('#button_form');
- var content = app.form.convertToData('#button_form');
-
- if (content.button_name && content.button_order_ver && content.button_order_hor) {
- var request = {};
- request.action = 'button_save';
- request.content = content;
- sendRequest(request, socket_remotes);
- app.preloader.show();
- }
- });
-
- page.$el.find('#test_signal_btn').on('click', function () {
- var form = page.$el.find('#button_form');
- var button_type = form.find('input[name=button_type]:checked').val();
-
- var request = {};
- request.action = 'test_signal';
- request.content = {}
-
- if (button_type == 'ir') {
- var ir_signal = form.find('#ir_signal').text();
-
- if (ir_signal) {
- request.content.signal = ir_signal;
- } else {
- app.dialog.alert('No IR signal', 'Invalid input');
- return;
- }
- } else {
- var command = form.find('input[name=button_command]').val();
-
- if (command) {
- request.content.signal = command;
- } else {
- app.dialog.alert('No command', 'Invalid input');
- return;
- }
- }
-
- request.content.button_type = button_type;
- request.content.radio_id = page.$el.find('input[name=test_radio_id]:checked').val();
- sendRequest(request, socket_remotes);
- });
- },
- pageAfterIn: function (e, page) {
- },
- },
- },
- {
- name: 'button_list',
- path: '/button_list/',
- templateUrl: './static/button_list.html',
- on: {
- pageInit: function (e, page) {
- $$('#button_remove_btn').on('click', function () {
- var request = {};
- var buttons = [];
- var content = app.form.convertToData('#button_list_form');
-
- request.action = 'rc_button_remove';
- request.content = content;
-
- sendRequest(request, socket_remotes);
- app.preloader.show();
- });
-
- $$('#button_edit_btn').on('click', function () {
- var button = page.$el.find('input[name=button]:checked').val();
-
- if (!button)
- return;
-
- var request = {};
- request.action = 'button_edit';
- request.content = {}
- request.content.rc_id = page.$el.find('input[name=rc_id]').val();
- request.content.button = button;
-
- sendRequest(request, socket_remotes);
- app.preloader.show();
- });
- },
- pageAfterIn: function (e, page) {
- },
- },
- },
-];
-// Initialize app
-var app = new Framework7({
- //Tell Framework7 to compile templates on app init
- root: '#app',
- panel: {
- swipe: 'right',
- leftBreakpoint: 768,
- rightBreakpoint: 1440,
- },
- routes: app_routes,
-});
-
-// If we need to use custom DOM library, let's save it to $$ variable:
-var $$ = Dom7;
-
-var socket_remotes = null;
-var socket_radios = null;
-
-// Add view
-var mainView = app.views.create('.view-main', {
- // url: '/'
-});
-
-var loginScreen = app.loginScreen.create({
- el: '.login-screen',
- // animate: true
-});
-
-app.request({
- url: '/api/v1.0/login',
- method: 'POST',
- success: function (data) {
- var d_obj = JSON.parse(data);
-
- if (d_obj.status_code == 100 || d_obj.status_code == 20) {
- mainView.router.navigate('/radios/');
-
- activateConnection();
- } else {
- var notif = app.notification.create({
- icon: '',
- title: 'Application',
- titleRightText: 'now',
- subtitle: 'This is a subtitle',
- text: 'Programm error',
- closeTimeout: 3000,
- closeButton: true,
- });
- notif.open();
- }
- },
- statusCode: {
- 401: function (xhr) {
- loginScreen.open();
- }
- }
-});
-$$('#login').on('click', function() {
- var username = $$('input[name=username]').val();
- var password = $$('input[name=password]').val();
-
- if (!username || !password) {
- app.dialog.alert('Enter both username and password', 'Input error');
- return;
- }
-
- app.request({
- url: '/api/v1.0/login',
- type: 'POST',
- data: {
- username: username,
- password: password
- },
- success: function (data) {
- var d_obj = JSON.parse(data);
- switch (d_obj.status_code) {
- case 10:
- // $$('#username').text(d_obj.result.current_user);
- // current_bidder = d_obj.result.current_bidder;
- // mainView.router.load({
- // url: 'static/status.html'
- // });
- mainView.router.navigate('/radios/');
- activateConnection();
- loginScreen.close();
- break;
- case 20:
- loginScreen.close();
- break;
- case 30:
- app.dialog.alert('Login or password incorect', 'Login error');
- break;
- }
- }
- });
-});
-
-$$('#logout').on('click', function() {
- app.request({
- url: '/api/v1.0/logout',
- type: 'POST',
- success: function (data) {
- var d_obj = JSON.parse(data);
- switch (d_obj.status_code) {
- case 40:
- loginScreen.open();
- break;
- default:
- app.dialog.alert('Refresh the page', 'Logout error');
- break;
- }
- }
- });
-});
-function activateConnection() {
- if (socket_remotes == null) {
-
- socket_remotes = io.connect('http://' + document.domain + ':' + location.port + '/remotes');
- socket_remotes.on('connect', function() {
- console.log('connected to remotes');
- var request = {};
-
- request.action = 'rc_refresh';
- sendRequest(request, socket_remotes);
- });
- socket_remotes.on('json', function(data) {
- console.log(data);
- if (data.response) {
- parseResponse(data.response);
- }
- });
- }
-
- if (socket_radios == null) {
- socket_radios = io.connect('http://' + document.domain + ':' + location.port + '/radios');
- socket_radios.on('connect', function() {
- console.log('connected to radios');
- });
- socket_radios.on('json', function(data) {
- console.log(data);
- if (data.response) {
- parseResponse(data.response);
- }
- });
- }
-}
-
-function sendRequest(request, socket) {
- if (socket != null) {
- console.log(request);
- socket.emit('json', request);
- } else {
- var notif = app.notification.create({
- icon: '',
- title: 'Socket',
- titleRightText: 'now',
- subtitle: 'This is a subtitle',
- text: 'No socket connection',
- closeTimeout: 3000,
- closeButton: true,
- });
- notif.open();
- }
-}
-
-function parseResponse(response) {
- if (response.result == 'success') {
- runCallback(response.callback, response);
- }
- else if (response.result == 'error') {
- var notif = app.notification.create({
- icon: '',
- title: 'Socket',
- titleRightText: 'now',
- subtitle: 'This is a subtitle',
- text: response.message,
- closeTimeout: 3000,
- closeButton: true,
- });
- notif.open();
- } else {
- var notif = app.notification.create({
- icon: '',
- title: 'Socket',
- titleRightText: 'now',
- subtitle: 'This is a subtitle',
- text: 'No socket connection',
- closeTimeout: 3000,
- closeButton: true,
- });
- notif.open();
- }
-}
-
-function redirectTo(page) {
- mainView.router.load({
- url: 'static/' + page + '.html'
- });
-}
-
-function runCallback(calback, args = '') {
- if (calback) {
- var func = callbacks[calback];
-
- if (typeof func === "function") {
- func(args);
- }
- }
-}
-/**
- * Custom callbacks
- */
- var callbacks = {
- rc_buttons_refresh: function(response) {
- var buttons = response.buttons;
- var page = $$('div.page[data-name=rc]');
-
- if (page.length && buttons.length) {
- var button_area = $$('#buttons_area');
-
- var row = 0;
-
- var content_block = $$('');
- var buttons_row = null;
-
- buttons.forEach(function(element) {
- if (element.order_ver != row) {
- row = element.order_ver;
-
- if (buttons_row)
- content_block.append(buttons_row);
-
- buttons_row = $$('');
- }
-
- var button = $$('');
- button.addClass(element.color);
- button.attr('data-btn-id', element.identificator);
- button.text(element.name);
- button.on('click', function (e) {
- var data = $$(this).dataset();
- var request = {};
-
- request.action = 'button_pushed';
- request.content = {}
- request.content.btn_id = data.btnId;
- sendRequest(request, socket_remotes);
- });
-
- buttons_row.append(button);
- });
-
- content_block.append(buttons_row);
- button_area.append(content_block);
- }
-
- if (response.rc_name) {
- page.find('.navbar .title').text(response.rc_name);
- }
-
- app.preloader.hide();
- },
- rc_refresh: function(response) {
- var remotes = response.remotes;
- var menu = $$('#remotes ul');
- menu.empty();
-
- remotes.forEach(function(element) {
- var li = $$('');
- var anchor = $$('');
- var icon = $$('
');
- var inner = $$('');
- var title = $$('').text(element.name);
-
- anchor.on('click', function (e) {
- mainView.router.navigate('/rc/' + element.identificator, {
- reloadCurrent : (mainView.router.currentRoute.name == 'rc'),
- });
- });
-
- inner.append(title);
- anchor.append(icon);
- anchor.append(inner);
- li.append(anchor);
- menu.append(li);
- });
- },
- ir_signal: function(response) {
- var page = $$('div.page[data-name=button]');
-
- if (page.length) {
- app.dialog.close();
-
- if (response.signal) {
- page.find('input[name=button_signal]').val(response.signal);
- page.find('#ir_signal').text(response.signal);
- } else {
- var notif = app.notification.create({
- icon: '',
- title: 'Application',
- titleRightText: 'now',
- subtitle: 'IR Cacher',
- text: 'A signal was not recieved',
- closeTimeout: 3000,
- closeButton: true,
- });
- notif.open();
- }
- }
- },
- button_edit: function(response) {
- if (response.button) {
- response.radios.forEach(function(el) {
- if (response.button.btn_radio_id == el.id)
- el.btn_selected = true;
- });
- }
-
- mainView.router.navigate('/button/', {
- context: {
- button: response.button,
- radios: response.radios
- }
- });
-
- app.preloader.hide();
- },
- back_to_rc: function(response) {
- app.preloader.hide();
- mainView.router.navigate('/rc/' + response.rc_id);
- },
- radios_refresh: function(response) {
- var radios = response.radios;
- var page = $$('div.page[data-name=radios]');
- var radios_area = $$('#radios_area');
- radios_area.empty();
-
- if (page.length && radios.length) {
- radios.forEach(function(element) {
- var card = $$('');
- var card_header = $$('');
- var card_content = $$('');
- var card_content_inner = $$('');
- var card_footer = $$('');
-
- card_header.append($$('').text(element.name + ' (radio number: ' + element.pipe + ')'));
-
- if (element.battery) {
- card_header.append($$('
'));
- }
- if (element.dht) {
- card_content_inner.append($$(' Temperature: --℃
'));
- card_content_inner.append($$(' Humidity: --%
'));
- }
-
- card_content.append(card_content_inner);
- card.append(card_header);
- card.append(card_content);
- card.append(card_footer);
- radios_area.append(card);
- });
-
- $$('.radio-edit-btn').on('click', function () {
- var request = {};
-
- request.action = 'radio_edit';
- request.content = {}
- request.content.id = $$(this).attr('data-id');
- sendRequest(request, socket_radios);
- });
-
- $$('.radio-remove-btn').on('click', function () {
- var request = {};
-
- request.action = 'radio_remove';
- request.content = {}
- request.content.radio = $$(this).attr('data-id');
- sendRequest(request, socket_radios);
- });
- }
- },
- radio_edit: function(response) {
- mainView.router.navigate('/radio_create/', {
- context: {
- radio: response.radio,
- new: false
- },
- });
- },
- radio_sensor_refresh: function(response) {
- var page = $$('div.page[data-name=radios]');
-
- if (page.length) {
- var radio = $$('#id_' + response.id);
-
- if (response.sensors.temp) {
- radio.find('.sensor-temp').html(response.sensors.temp)
- }
- if (response.sensors.hum) {
- radio.find('.sensor-hum').html(response.sensors.hum)
- }
- if (response.sensors.bat) {
- radio.find('.sensor-bat').html('v' + response.sensors.bat + ' ')
- }
- }
- },
-};
-var radios_action_sheet = app.actions.create({
- buttons: [
- {
- text: 'Add remote control',
- onClick: function () {
- mainView.router.navigate('/rc_create/');
- }
- },
- {
- text: 'Add radio',
- onClick: function () {
- mainView.router.navigate('/radio_create/', {
- context: {
- radio: {},
- new: true
- },
- });
- }
- },
- {
- text: 'Cancel',
- color: 'red',
- },
- ]
-});
-
-var rc_action_sheet = app.actions.create({
- buttons: [
- {
- text: 'Add button',
- onClick: function () {
-
- var request = {};
- request.action = 'button_edit';
- request.content = {}
- request.content.rc_id = $$('div.page[data-name=rc]').attr('data-rc-id');
-
- sendRequest(request, socket_remotes);
- app.preloader.show();
- }
- },
- // {
- // text: 'Sort Buttons',
- // onClick: function () {
- // app.alert('Button2 clicked');
- // }
- // },
- {
- text: 'Edit Button',
- onClick: function () {
- var rc_id = $$('div.page[data-name=rc]').attr('data-rc-id');
- var buttons = [];
-
- $$('#buttons_area button.button').each(function() {
- var btn = {};
-
- btn.id = $$(this).attr('data-btn-id');
- btn.name = $$(this).text();
-
- buttons.push(btn);
- });
-
- mainView.router.navigate('/button_list/', {
- context: {
- remove: false,
- buttons: buttons,
- rc_id: rc_id,
- }
- });
- }
- },
- {
- text: 'Remove Buttons',
- onClick: function () {
- var rc_id = $$('div.page[data-name=rc]').attr('data-rc-id');
- var buttons = [];
-
- $$('#buttons_area button.button').each(function() {
- var btn = {};
-
- btn.id = $$(this).attr('data-btn-id');
- btn.name = $$(this).text();
-
- buttons.push(btn);
- });
-
- mainView.router.navigate('/button_list/', {
- context: {
- remove: true,
- buttons: buttons,
- rc_id: rc_id,
- }
- });
- }
- },
- {
- text: 'Cancel',
- color: 'red',
- },
- ]
-});
\ No newline at end of file
diff --git a/app/static/login_screen.html b/app/static/login_screen.html
deleted file mode 100644
index 1de5bee..0000000
--- a/app/static/login_screen.html
+++ /dev/null
@@ -1,40 +0,0 @@
-
\ No newline at end of file
diff --git a/app/static/radio_create.html b/app/static/radio_create.html
deleted file mode 100755
index e65ce96..0000000
--- a/app/static/radio_create.html
+++ /dev/null
@@ -1,86 +0,0 @@
-
diff --git a/app/static/radios.html b/app/static/radios.html
deleted file mode 100755
index 21e0c2e..0000000
--- a/app/static/radios.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
Temperature: 20.00℃
-
Humidity: 60%
-
-
-
-
-
-
-
-
diff --git a/app/static/rc.html b/app/static/rc.html
deleted file mode 100755
index 1224a34..0000000
--- a/app/static/rc.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
diff --git a/app/static/rc_create.html b/app/static/rc_create.html
deleted file mode 100755
index 7480f19..0000000
--- a/app/static/rc_create.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
diff --git a/docker/.gitkeep b/app/templates/.gitkeep
similarity index 100%
rename from docker/.gitkeep
rename to app/templates/.gitkeep
diff --git a/app/templates/index.html b/app/templates/index.html
deleted file mode 100755
index c515e89..0000000
--- a/app/templates/index.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- Smart Remote
-
-
-
-
-
-
-
-
-
diff --git a/app/templates/index2.html b/app/templates/index2.html
deleted file mode 100644
index 8067679..0000000
--- a/app/templates/index2.html
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- Smart Remote
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/arduino/infrared_station.c b/arduino/infrared_station.c
index f923429..dc23eed 100755
--- a/arduino/infrared_station.c
+++ b/arduino/infrared_station.c
@@ -1,14 +1,14 @@
-#include
#include
#include
#include
#include
#include
#include
+#include
+#include
// Radio setting
RF24 radio(9, 10); // For nano pin 9 and 10
-uint64_t address = 0xAABBCCDD44LL;
int radioSpeedPin = 2;
int radioChannelPin1 = 3;
int radioChannelPin2 = 4;
@@ -16,42 +16,47 @@ int radio_retries = 5;
int radio_delay = 10;
byte radioSpeedState = 0; // 0 is RF24_250KBPS and 1 is RF24_1MBPS
+String pipe_str = "AABBCCDD99"; // Keep format
+
// IRremote setting
IRsend irsend;
unsigned char khz = 38;
-// DHT setting
-#define DHTTYPE DHT22 // DHT 11
-const byte dht_pin = 8;
-DHT dht(dht_pin, DHTTYPE);
-float hum;
+// BME280 setting
+float humi;
float temp;
+float pres;
+Adafruit_BME280 bme; // I2C
// Battery setting
int bat_pin = A0;
-// float max_v = 4.1;
-// float min_v = 2.5;
-float bat = 0;
+float bat;
unsigned long sleep_at;
+unsigned long status_timer;
void setup() {
+ delay(3000); // Sleep 3s before loop.
+
analogReference(INTERNAL);
pinMode(radioSpeedPin, INPUT);
// Serial.begin(9600);
radio.begin();
delay(100);
radio.powerUp();
- radio.setAutoAck(false);
- radio.setChannel(90); // (0 - 127)
- radio.setRetries(15,15);
+ radio.setAutoAck(false); // Disable hardware ACK, use program ACK
+ radio.setChannel(90); // (0 - 127)
+ // radio.setRetries(15,15);
radio.setPayloadSize(32);
radio.setCRCLength(RF24_CRC_8);
- radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
- radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
- radio.openWritingPipe(0xAABBCCDD55LL);
- radio.openReadingPipe(1, address);
+ radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
+ radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
+ radio.openWritingPipe(0xAABBCCDD88LL);
+ radio.openReadingPipe(1, 0xAABBCCDD99LL);
radio.startListening();
- getDhtParams();
+
+ bme.begin(0x76); // 0x76 or 0x77 for bme280
+
+ readBMP();
getBatteryVoltage();
sleep_at = millis();
}
@@ -68,11 +73,7 @@ void loop() {
// If recive IR signal (it starts with i)
if (code[1] == 105) {
// Serial.println("ir");
- if (readIrSignal(code)) {
- responseSuccess();
- } else {
- // Serial.println("recieve timeout");
- }
+ readIrSignal(code);
}
// If recive comand (it starts with c)
else if (code[1] == 99) {
@@ -83,24 +84,23 @@ void loop() {
}
}
- // Sleep each 15ms to save power
- while (millis() - sleep_at >= 20) {
- wdt_enable(WDTO_60MS); //Задаем интервал сторожевого таймера (30ms) WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS etc.
- WDTCSR |= (1 << WDIE); //Устанавливаем бит WDIE регистра WDTCSR для разрешения прерываний от сторожевого таймера
- set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Устанавливаем интересующий нас режим
+ // Send status periodically
+ if (false && millis() - status_timer > 8000) {
+ readBMP();
+ getBatteryVoltage();
+ sendStatus();
+ status_timer = millis();
+ }
+ // Sleep each 20ms to save power
+ while (false && millis() - sleep_at >= 20) {
radio.stopListening();
radio.powerDown();
- // ADCSRA &= ~(1 << ADEN); // Отключаем АЦП
- // set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Устанавливаем интересующий нас режим
- // sleep_enable();
- // // Отключаем детектор пониженного напряжения питания
- // MCUCR = bit (BODS) | bit (BODSE);
- // MCUCR = bit (BODS);
- // sleep_cpu(); // Переводим МК в спящий режим
-
- sleep_mode(); // Переводим МК в спящий режим
+ wdt_enable(WDTO_60MS); // WDT interval WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS etc.
+ WDTCSR |= (1 << WDIE); // Enable WDT
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode
+ sleep_mode(); // Go to sleep
sleep_at = millis();
radio.powerUp();
@@ -108,12 +108,14 @@ void loop() {
}
}
-boolean readIrSignal(byte * code) {
+void readIrSignal(byte * code) {
int zero = 0;
int one = 0;
+ // char buffer[10];
char buffer[5];
byte buffer_index = 0;
boolean bit_code = false;
+ // uint32_t raw_signal[300];
unsigned int raw_signal[300];
int raw_index = 0;
@@ -176,7 +178,7 @@ boolean readIrSignal(byte * code) {
if (code[i] > 47 && code[i] < 58) {
buffer[buffer_index] = code[i];
buffer_index++;
- } else if (code[i] == 32) {
+ } else if (code[i] == 32 && buffer_index > 0) {
raw_signal[raw_index] = atoi(buffer);
raw_index++;
memset(buffer, 0, sizeof(buffer));
@@ -212,6 +214,7 @@ boolean readIrSignal(byte * code) {
{
if (ir_code[i] == 10) {
timeout = false;
+ // raw_index--;
break;
}
if (ir_code[i] == 91) {
@@ -254,12 +257,13 @@ boolean readIrSignal(byte * code) {
if (ir_code[i] > 47 && ir_code[i] < 58) {
buffer[buffer_index] = ir_code[i];
buffer_index++;
- } else if (ir_code[i] == 32) {
+ } else if (ir_code[i] == 32 && buffer_index > 0) {
raw_signal[raw_index] = atoi(buffer);
raw_index++;
memset(buffer, 0, sizeof(buffer));
buffer_index = 0;
} else if (ir_code[i] == 10) {
+ raw_signal[raw_index] = atoi(buffer);
timeout = false;
break;
}
@@ -269,11 +273,18 @@ boolean readIrSignal(byte * code) {
}
if (!timeout) {
+ // Serial.print(raw_index);
irsend.sendRaw(raw_signal, raw_index, khz);
- return true;
+ // for (int m = 0; m < raw_index; m++)
+ // {
+ // Serial.println(raw_signal[m]);
+ // }
+ // delay(200);
+ // responseSuccess();
+ // return true;
}
- return false;
+ // return false;
}
void readCommand(byte * code) {
@@ -343,14 +354,10 @@ void checkRadioSetting() {
}
}
-void getDhtParams() {
- float h = dht.readHumidity();
- float t = dht.readTemperature();
-
- if (!isnan(t) && !isnan(h)) {
- hum = h;
- temp = t;
- }
+void readBMP() {
+ humi = bme.readHumidity();
+ temp = bme.readTemperature();
+ pres = bme.readPressure() / 100.0F;
}
void getBatteryVoltage() {
@@ -358,13 +365,16 @@ void getBatteryVoltage() {
}
void responseSuccess() {
- String responce = "0ok";
- responce += "\n";
-
- int rsize = responce.length();
+ // Max payload size in one package is 32 bytes
+ String payload_0 = "0"; // Package nubber
+ payload_0 += pipe_str; // Reading pipe of the station
+ payload_0 += "type r,";
+ payload_0 += "ir ok\n";
+ int rsize = payload_0.length();
+
byte byte_arr[rsize+1];
- responce.getBytes(byte_arr, rsize+1);
+ payload_0.getBytes(byte_arr, rsize+1);
if (!sendWithACK(byte_arr, rsize)) {
// Serial.println("sendStatus failed");
@@ -373,26 +383,41 @@ void responseSuccess() {
}
void sendStatus() {
- getBatteryVoltage();
- getDhtParams();
- // Add DHT params
- String responce = "0h ";
- responce += hum;
- responce += ",t ";
- responce += temp;
-
- // Add Battery voltage
- responce += ",b ";
- responce += bat;
- responce += "\n";
+ // Max payload size in one package is 32 bytes
+ String payload_0 = "0"; // Package nubber
+ payload_0 += pipe_str; // Reading pipe of the station
+ payload_0 += "type e,";
+ payload_0 += "h ";
+ payload_0 += humi;
- int rsize = responce.length();
+ int rsize = payload_0.length();
byte byte_arr[rsize+1];
- responce.getBytes(byte_arr, rsize+1);
+ payload_0.getBytes(byte_arr, rsize+1);
if (!sendWithACK(byte_arr, rsize)) {
// Serial.println("sendStatus failed");
+ return;
+ }
+
+ String payload_1 = "1"; // Package nubber
+ payload_1 += ",t ";
+ payload_1 += temp;
+ payload_1 += ",p ";
+ payload_1 += pres;
+
+ // Add Battery voltage
+ payload_1 += ",b ";
+ payload_1 += bat;
+ payload_1 += "\n";
+
+ rsize = payload_1.length();
+
+ byte byte_arr_2[rsize+1];
+ payload_1.getBytes(byte_arr_2, rsize+1);
+
+ if (!sendWithACK(byte_arr_2, rsize)) {
+ // Serial.println("sendStatus failed2");
}
}
@@ -447,7 +472,7 @@ void sendACK() {
radio.startListening();
}
-ISR (WDT_vect) {
- wdt_disable();
- // sleep_at = millis();
-}
+// ISR (WDT_vect) {
+// wdt_disable();
+// // sleep_at = millis();
+// }
diff --git a/arduino/infrared_station_v3.c b/arduino/infrared_station_v3.c
new file mode 100644
index 0000000..c682df7
--- /dev/null
+++ b/arduino/infrared_station_v3.c
@@ -0,0 +1,512 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Radio setting
+RF24 radio(9, 10); // For nano pin 9 and 10
+// int radioSpeedPin = 2;
+// int radioChannelPin1 = 3;
+// int radioChannelPin2 = 4;
+int radio_retries = 15;
+int radio_delay = 10;
+byte radioSpeedState = 0; // 0 is RF24_250KBPS and 1 is RF24_1MBPS
+
+uint8_t radio_id = 50;
+
+// IRremote setting
+IRsend irsend;
+unsigned char khz = 38;
+
+// BME280 setting
+float humi;
+float temp;
+float pres;
+Adafruit_BME280 bme; // I2C
+
+// Battery setting
+int bat_pin = A0;
+float bat;
+unsigned long sleep_at;
+unsigned long status_timer;
+
+// LED settings
+int led_pin_blue = A1;
+int led_pin_red = A2;
+
+void setup() {
+ delay(3000); // Sleep 3s before loop.
+
+ analogReference(INTERNAL);
+ // pinMode(radioSpeedPin, INPUT);
+ pinMode(led_pin_red, OUTPUT);
+ pinMode(led_pin_blue, OUTPUT);
+ Serial.begin(9600);
+ radio.begin();
+ delay(100);
+ radio.powerUp();
+ radio.setChannel(90); // (0 - 127)
+ radio.setAutoAck(false); // Disable hardware ACK, use program ACK
+ radio.setPayloadSize(32);
+ radio.setCRCLength(RF24_CRC_8);
+ radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
+ radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
+ radio.openWritingPipe(0xAAAAAAAA22LL);
+ radio.openReadingPipe(1, 0xAAAAAAAA11LL);
+ radio.startListening();
+
+ bme.begin(0x76); // 0x76 or 0x77 for bme280
+
+ readBMP();
+ getBatteryVoltage();
+ sleep_at = millis();
+}
+
+void loop() {
+ // checkRadioSetting();
+
+ if (radio.available()) {
+ byte payload[32];
+ radio.read(&payload, sizeof(payload));
+
+ if (payload[0] == radio_id && payload[1] == 48) {
+ sendACK(radio_id);
+
+ // If recive IR signal (it starts with i)
+ if (payload[2] == 105) {
+ // Serial.println("ir");
+ readIrSignal(payload);
+ }
+ // If recive comand (it starts with c)
+ else if (payload[2] == 99) {
+ // Serial.println("c");
+ readCommand(payload);
+ } else {
+ // Serial.println("wtf");
+ }
+ }
+ }
+
+ // Send status periodically
+ // if (millis() - status_timer > 8000) {
+ // readBMP();
+ // getBatteryVoltage();
+ // sendStatus();
+ // status_timer = millis();
+ // }
+
+ // Sleep each 20ms to save power
+ while (millis() - sleep_at >= 500) {
+ radio.stopListening();
+ radio.powerDown();
+
+ wdt_enable(WDTO_8S); // WDT interval WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS etc.
+ WDTCSR |= (1 << WDIE); // Enable WDT
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode
+ sleep_mode(); // Go to sleep
+ sleep_at = millis();
+
+ radio.powerUp();
+
+ sendRequest();
+ radio.startListening();
+ }
+}
+
+void readIrSignal(byte * code) {
+ int zero = 0;
+ int one = 0;
+ char buffer[5];
+ byte buffer_index = 0;
+ boolean bit_code = false;
+ unsigned int raw_signal[300];
+ int raw_index = 0;
+
+ // Setup zero length
+ buffer[0] = code[4];
+ buffer[1] = code[5];
+ buffer[2] = code[6];
+ buffer[3] = '\0';
+ zero = atoi(buffer);
+ memset(buffer, 0, sizeof(buffer));
+
+ // Setup one length
+ buffer[0] = code[8];
+ buffer[1] = code[9];
+ buffer[2] = code[10];
+ buffer[3] = code[11];
+ buffer[4] = '\0';
+ one = atoi(buffer);
+ memset(buffer, 0, sizeof(buffer));
+
+ for (int i = 13; i < 32; ++i)
+ {
+ if (code[i] == 91) {
+ bit_code = true;
+ continue;
+ } else if (code[i] == 93) {
+ bit_code = false;
+ continue;
+ }
+
+ if (bit_code) {
+ if (code[i] > 47 && code[i] < 58) {
+ buffer[buffer_index] = code[i];
+ buffer_index++;
+ continue;
+ } else if (code[i] == 97) {
+ int rep = atoi(buffer);
+
+ for (int j = 0; j < rep; ++j)
+ {
+ raw_signal[raw_index] = zero;
+ raw_index++;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ } else if (code[i] == 98) {
+ int rep = atoi(buffer);
+
+ for (int j = 0; j < rep; ++j)
+ {
+ raw_signal[raw_index] = one;
+ raw_index++;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ }
+ } else {
+ if (code[i] > 47 && code[i] < 58) {
+ buffer[buffer_index] = code[i];
+ buffer_index++;
+ } else if (code[i] == 32 && buffer_index > 0) {
+ raw_signal[raw_index] = atoi(buffer);
+ raw_index++;
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ }
+ }
+ }
+
+ byte package = 49;
+ byte ir_code[32];
+ boolean timeout = true;
+ unsigned long started_at = millis();
+
+ while (millis() - started_at <= radio_retries * radio_delay) {
+ if (radio.available()) {
+ radio.read(&ir_code, sizeof(ir_code));
+
+ if (ir_code[0] != radio_id) {
+ continue;
+ }
+
+ sendACK(radio_id);
+ started_at = millis();
+
+ if (ir_code[1] == package) {
+ package++;
+ } else {
+ continue;
+ }
+
+ for (int i = 2; i < 32; ++i)
+ {
+ if (ir_code[i] == 10) {
+ timeout = false;
+ // raw_index--;
+ break;
+ }
+ if (ir_code[i] == 91) {
+ bit_code = true;
+ continue;
+ } else if (ir_code[i] == 93) {
+ bit_code = false;
+ continue;
+ }
+
+ if (bit_code) {
+ if (ir_code[i] > 47 && ir_code[i] < 58) {
+ buffer[buffer_index] = ir_code[i];
+ buffer_index++;
+ continue;
+ } else if (ir_code[i] == 97) {
+ int rep = atoi(buffer);
+
+ for (int j = 0; j < rep; ++j)
+ {
+ raw_signal[raw_index] = zero;
+ raw_index++;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ } else if (ir_code[i] == 98) {
+ int rep = atoi(buffer);
+
+ for (int j = 0; j < rep; ++j)
+ {
+ raw_signal[raw_index] = one;
+ raw_index++;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ }
+ } else {
+ if (ir_code[i] > 47 && ir_code[i] < 58) {
+ buffer[buffer_index] = ir_code[i];
+ buffer_index++;
+ } else if (ir_code[i] == 32 && buffer_index > 0) {
+ raw_signal[raw_index] = atoi(buffer);
+ raw_index++;
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ } else if (ir_code[i] == 10) {
+ raw_signal[raw_index] = atoi(buffer);
+ timeout = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!timeout) {
+ // Serial.print("\nok\n");
+ irsend.sendRaw(raw_signal, raw_index, khz);
+ }
+}
+
+void readCommand(byte * code) {
+ byte data[32];
+ unsigned long started_at = millis();
+
+ char buffer[32] = "";
+ int buffer_index = 0;
+
+ for (int i = 3; i < 32; ++i) {
+ if (code[i] == 10) {
+ break;
+ }
+
+ buffer[buffer_index] = code[i];
+ buffer_index++;
+ }
+
+ // while (millis() - started_at <= radio_retries * radio_delay) {
+ // if (radio.available()) {
+ // radio.read(&data, sizeof(data));
+
+ // if (data[0] == 6) {
+ // continue;
+ // }
+
+ // sendACK(radio_id);
+
+ // if (data[0] == 48) {
+ // started_at = millis();
+ // } else {
+ // // Serial.println("same package");
+ // }
+ // }
+ // }
+
+ if (strcmp(buffer, "red_on") == 0) {
+ digitalWrite(led_pin_red, HIGH);
+ Serial.println("red_on");
+ } else if (strcmp(buffer, "red_off") == 0) {
+ digitalWrite(led_pin_red, LOW);
+ Serial.println("red_off");
+ } else if (strcmp(buffer, "blue_on") == 0) {
+ digitalWrite(led_pin_blue, HIGH);
+ Serial.println("blue_on");
+ } else if (strcmp(buffer, "blue_off") == 0) {
+ digitalWrite(led_pin_blue, LOW);
+ Serial.println("blue_off");
+ } else if (strcmp(buffer, "empty") == 0) {
+ // Serial.println("go to sleep");
+ sleep_at = millis() - 1000;
+ readBMP();
+ getBatteryVoltage();
+ sendStatus();
+ return;
+ } else {
+ unsupportedCommand();
+ }
+
+ radio.stopListening();
+ sendRequest();
+ radio.startListening();
+}
+
+// void checkRadioSetting() {
+// byte currentSpeed = 0;
+
+// if (digitalRead(radioSpeedPin) == HIGH) {
+// currentSpeed = 1;
+// }
+
+// if (radioSpeedState != currentSpeed)
+// {
+// if (currentSpeed == 0) {
+// radioSpeedState = 0;
+// // Serial.println("RF24_250KBPS");
+// // radio.setDataRate(RF24_250KBPS);
+// // Serial.println("RF24_1MBPS");
+// radio.setDataRate(RF24_1MBPS);
+// } else {
+// radioSpeedState = 1;
+// // Serial.println("RF24_1MBPS");
+// // radio.setDataRate(RF24_1MBPS);
+// // Serial.println("RF24_2MBPS");
+// radio.setDataRate(RF24_2MBPS);
+// }
+// }
+// }
+
+void readBMP() {
+ humi = bme.readHumidity();
+ temp = bme.readTemperature();
+ pres = bme.readPressure() / 100.0F;
+}
+
+void getBatteryVoltage() {
+ bat = ((analogRead(bat_pin) * 1.1) / 1023) * 10.86;
+}
+
+void responseSuccess() {
+ // Max payload size in one package is 32 bytes
+ // String payload_0 = "0"; // Package nubber
+ // payload_0 += pipe_str; // Reading pipe of the station
+ // payload_0 += "type r,";
+ // payload_0 += "ir ok\n";
+
+ // int rsize = payload_0.length();
+
+ // byte byte_arr[rsize+1];
+ // payload_0.getBytes(byte_arr, rsize+1);
+
+ // if (!sendWithACK(byte_arr, rsize)) {
+ // // Serial.println("sendStatus failed");
+ // return;
+ // }
+}
+
+void sendStatus() {
+ // Serial.print("status\n");
+ byte radio_buff[32];
+ byte radio_buff_index = 2;
+ byte radio_package = 48;
+
+ // Max payload size in one package is 32 bytes
+ String payload = "tp ev,";
+ payload += "h ";
+ payload += humi;
+ payload += ",t ";
+ payload += temp;
+ payload += ",p ";
+ payload += pres;
+ payload += ",b ";
+ payload += bat;
+ payload += "\n";
+
+ int rsize = payload.length();
+
+ radio_buff[0] = radio_id;
+ radio_buff[1] = radio_package;
+
+ for (int i = 0; i < rsize; i++) {
+ radio_buff[radio_buff_index] = payload[i];
+ radio_buff_index++;
+
+ if (radio_buff_index == 32 || payload[i] == 10) {
+ radio_buff[1] = radio_package;
+
+ if (!sendWithACK(radio_buff, radio_buff_index)) {
+ // Serial.print("fail\n");
+ return;
+ }
+
+ radio_package++;
+ radio_buff_index = 2;
+ }
+ }
+}
+
+void unsupportedCommand() {
+ String responce = "0unsupported command\n";
+
+ int rsize = responce.length();
+
+ byte byte_arr[rsize+1];
+ responce.getBytes(byte_arr, rsize+1);
+
+ if (!sendWithACK(byte_arr, rsize)) {
+ // Serial.println("unsupportedCommand failed");
+ return;
+ }
+}
+
+bool sendRequest() {
+ String responce = "20tp rq\n";
+
+ int rsize = responce.length();
+
+ byte byte_arr[rsize+1];
+ responce.getBytes(byte_arr, rsize+1);
+
+ if (!sendWithACK(byte_arr, rsize)) {
+ Serial.println("ok");
+ return true;
+ }
+
+ return false;
+}
+
+boolean sendWithACK(byte * data, byte size) {
+ byte response[32];
+ unsigned long ack_started_at;
+
+ for (int i = 0; i <= radio_retries; i++) {
+ radio.stopListening();
+ radio.writeFast(data, size);
+ radio.txStandBy();
+ radio.startListening();
+
+ ack_started_at = millis();
+ // Wait 15ms for responce
+ while (millis() - ack_started_at <= radio_delay) {
+ if (radio.available()) {
+ radio.read(&response, sizeof(response));
+
+ if (data[0] == response[0] && response[1] == 6) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void sendACK(byte radio_node) {
+ byte ack[2];
+ ack[0] = radio_node;
+ ack[1] = 6;
+ radio.stopListening();
+ radio.writeFast(ack, sizeof(ack));
+ radio.txStandBy();
+ radio.startListening();
+}
+
+ISR (WDT_vect) {
+ wdt_disable();
+ // sleep_at = millis();
+}
diff --git a/arduino/serial_driver.c b/arduino/serial_driver_v2.c
old mode 100755
new mode 100644
similarity index 53%
rename from arduino/serial_driver.c
rename to arduino/serial_driver_v2.c
index ffab826..1754e1a
--- a/arduino/serial_driver.c
+++ b/arduino/serial_driver_v2.c
@@ -3,9 +3,11 @@
#include
RF24 radio(9, 10);
int radio_retries = 15;
-int radio_delay = 5;
+int radio_delay = 10;
boolean isSucces = false;
+boolean recieveInterrupt = false;
+byte mode = 2; // 1 - tx mode, 2 - rx mode
void setup() {
Serial.begin(500000);
@@ -20,7 +22,8 @@ void setup() {
radio.setCRCLength(RF24_CRC_8);
radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
- radio.openReadingPipe(1, 0xAABBCCDD55LL);
+ radio.openReadingPipe(1, 0xAABBCCDD88LL);
+ // radio.openReadingPipe(2, 0xAABBCCDD55LL);
radio.startListening();
}
@@ -28,7 +31,9 @@ void loop() {
if (Serial.available() > 0) {
isSucces = false;
+ // mode = 1;
readSerial();
+ // mode = 2;
if (isSucces) {
Serial.print(":OK\n");
@@ -36,12 +41,28 @@ void loop() {
Serial.print(":FAIL\n");
}
}
+ if (radio.available()) {
+ isSucces = false;
+ recieveInterrupt = false;
+
+ recive();
+
+ if (recieveInterrupt == false) {
+ if (isSucces) {
+ Serial.print(":OK\n");
+ } else {
+ Serial.print(":FAIL\n");
+ }
+ }
+ }
}
void readSerial() {
byte b;
byte serial_buffer = 0;
boolean timeout = true;
+ boolean first_buff = true;
+ // boolean broadcast = false;
unsigned long started_waiting_at = millis();
char pipe_buf[10];
@@ -88,14 +109,18 @@ void readSerial() {
}
timeout = false;
-
break;
} else {
- buffer[buffer_index] = b;
+ // if (first_buff && b == 98) {
+ // broadcast = true;
+ // } else {
+ buffer[buffer_index] = b;
+ // }
buffer_index++;
}
if (buffer_index == 32) {
+ // first_buff = false;
if (!sendWithACK(buffer, buffer_index)) {
Serial.print("RADIO TRANSMIT SIGNAL 2");
return;
@@ -118,46 +143,123 @@ void readSerial() {
Serial.print("SERIAL READ TIMEOUT");
return;
} else {
- recive();
+ // if (!broadcast) {
+ // recive();
+ // }
}
}
void recive() {
- byte income_pipe;
+ // byte income_pipe;
byte response[32];
+ boolean pipe_set = false;
+ char pipe_buf[10];
+ int pipe_buf_i = 0;
boolean ended = false;
unsigned long started_at = millis();
byte package = 48;
int recive_limit = 500;
+ uint64_t pipe;
+
+ // if (mode == 2) {
+ // recive_limit = 30;
+ // }
while (millis() - started_at <= recive_limit) {
- if (radio.available(&income_pipe)) {
- if (income_pipe == 1) {
+ if (radio.available()) {
+ // if (income_pipe == mode) {
radio.read(&response, sizeof(response));
if (response[0] == 6) {
continue;
}
- sendACK();
+ // Get the pipe address from the package
+ // if (mode == 2) {
+ int i = 1;
+
+ // Set pipe to response from first package
+ if (package == 48 && response[0] == 48) {
+ for (i; i < 11; i++) {
+ pipe_buf[pipe_buf_i] = response[i];
+ pipe_buf_i++;
+ }
+ pipe = getUInt64fromHex(pipe_buf);
+ radio.openWritingPipe(pipe);
+ pipe_set = true;
- if (response[0] == package) {
- started_at = millis();
- package++;
+ Serial.write(114);
+ Serial.write(32);
- for (int i = 1; i < sizeof(response); i++) {
- if (response[i] == 10) {
- ended = true;
- recive_limit = 20;
- break;
+ for (int j = 0; j < sizeof(pipe_buf); j++) {
+ Serial.write(pipe_buf[j]);
}
+ Serial.write(44);
+ }
- Serial.write(response[i]);
+ if (!pipe_set) {
+ // Serial.print("PIPE DID NOT SET");
+ recieveInterrupt = true;
+ return;
}
- } else {
- // Serial.println("same package");
- }
- }
+
+ if (response[0] == package) {
+ sendACK();
+ started_at = millis();
+ package++;
+
+ for (i; i < sizeof(response); i++) {
+ if (response[i] == 10) {
+ ended = true;
+ break;
+ } else if (response[i] == 0) {
+ break;
+ }
+ Serial.write(response[i]);
+ }
+ } else {
+ // Check if the same pipe send the first package again
+ if (response[0] == 48) {
+ pipe_buf_i = 0;
+
+ for (byte n = 1; n < 11; n++) {
+ pipe_buf[pipe_buf_i] = response[i];
+ pipe_buf_i++;
+ }
+ uint64_t n_pipe = getUInt64fromHex(pipe_buf);
+ if (n_pipe == pipe) {
+ sendACK();
+ started_at = millis();
+ // Serial.println("same first package same pipe");
+ }
+ }
+ }
+ // } else {
+ // // To do
+ // // Add checking pipe
+ // sendACK();
+
+ // if (response[0] == package) {
+ // started_at = millis();
+ // package++;
+
+ // for (int i = 1; i < sizeof(response); i++) {
+ // if (response[i] == 10) {
+ // ended = true;
+ // recive_limit = 20;
+ // break;
+ // }
+
+ // Serial.write(response[i]);
+ // }
+ // } else {
+ // // Serial.println("same package");
+ // }
+ // }
+ // } else {
+ // Serial.print("MODE AND PIPE ARE NOT EQUAL");
+ // return;
+ // }
}
}
@@ -169,7 +271,7 @@ void recive() {
}
boolean sendWithACK(byte * data, int size) {
- byte income_pipe;
+ // byte income_pipe;
byte response[32];
unsigned long ack_started_at;
@@ -182,11 +284,11 @@ boolean sendWithACK(byte * data, int size) {
ack_started_at = millis();
// Wait 15ms for responce
- while (millis() - ack_started_at <= 15) {
- if (radio.available(&income_pipe)) {
- radio_sleep_retries = radio_retries;
+ while (millis() - ack_started_at <= radio_delay) {
+ if (radio.available()) {
+ // radio_sleep_retries = radio_retries;
- if (income_pipe == 1) {
+ // if (income_pipe == 1) {
radio.read(&response, sizeof(response));
if (response[0] == 6) {
@@ -194,7 +296,7 @@ boolean sendWithACK(byte * data, int size) {
} else {
continue;
}
- }
+ // }
}
}
}
diff --git a/arduino/serial_driver_v3.c b/arduino/serial_driver_v3.c
new file mode 100755
index 0000000..d41b42a
--- /dev/null
+++ b/arduino/serial_driver_v3.c
@@ -0,0 +1,240 @@
+#include
+#include
+#include
+RF24 radio(9, 10);
+uint8_t radio_retries = 15;
+uint8_t radio_delay = 10;
+
+bool isRadioSeted = true;
+
+void setup() {
+ Serial.begin(500000);
+ Serial.setTimeout(50);
+ radio.begin();
+ delay(100);
+
+ radio.powerUp();
+ radio.setChannel(90);
+
+ radio.setAutoAck(false); // Disable hardware ACK, use program ACK
+
+ radio.setPayloadSize(32);
+ radio.setCRCLength(RF24_CRC_8);
+ radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
+ radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
+ radio.openWritingPipe(0xAAAAAAAA11LL);
+ radio.openReadingPipe(1, 0xAAAAAAAA22LL);
+ radio.startListening();
+}
+
+void setupRadio() {
+ if (isRadioSeted) {
+ radio.stopListening();
+ }
+
+ uint8_t sum = 0;
+ uint8_t channel;
+ uint8_t crc_length;
+ uint8_t data_rate;
+ uint8_t pa_level;
+ uint64_t w_pipe;
+ uint64_t r_pipe;
+}
+
+void loop() {
+ uint8_t b = 18;
+ if (Serial.available() > 0) {
+ // b = Serial.read();
+ readSerial(b);
+ }
+
+ if (isRadioSeted) {
+ recive();
+ }
+}
+
+void readSerial(uint8_t type) {
+ bool setup_mode = false;
+ // max size 300 bytes
+ bool serial_timeout = true;
+ uint8_t serial_buff[300];
+ uint16_t serial_buff_index = 0;
+ // Serial buffer size is 64 bytes
+ uint8_t serial_chank_index = 0;
+
+ uint8_t radio_buff[32];
+ uint8_t radio_buff_index = 0;
+ uint8_t radio_package = 48;
+
+ uint8_t b;
+
+ unsigned long started_waiting_at = millis();
+
+ while (millis() - started_waiting_at < 100) {
+ if (Serial.available() == 0) {
+ continue;
+ }
+
+ b = Serial.read();
+
+ serial_chank_index++;
+
+ // Radio transmit mode
+ if (type == 18 && radio_buff_index == 0) {
+ radio_buff[0] = b;
+ radio_buff_index = 2;
+ continue;
+ }
+
+ serial_buff[serial_buff_index] = b;
+ serial_buff_index++;
+
+ if (b == 10) {
+ Serial.print(":ack:\n");
+ serial_timeout = false;
+ break;
+ }
+
+ if (serial_chank_index == 64) {
+ Serial.print(":next:\n");
+ serial_chank_index = 0;
+ continue;
+ // recive();
+ }
+
+ if (serial_buff_index == 299) {
+ Serial.print(":overflow:\n");
+ return;
+ }
+
+ // recive();
+ }
+
+ if (serial_timeout) {
+ Serial.print("\n:timeout:\n");
+ return;
+ }
+
+ // Radio transmit mode
+ if (type == 18) {
+ radio_buff[1] = radio_package;
+
+ for (uint16_t i = 0; i < serial_buff_index; i++) {
+ radio_buff[radio_buff_index] = serial_buff[i];
+ radio_buff_index++;
+
+ if (radio_buff_index == 32 || serial_buff[i] == 10) {
+ if (!sendWithACK(radio_buff, radio_buff_index)) {
+ Serial.print(":fail:\n");
+ return;
+ }
+
+ radio_buff_index = 2;
+ radio_package++;
+ radio_buff[1] = radio_package;
+ }
+ }
+ } else if (type == 17) {
+ // Setup mode
+ setupRadio();
+ }
+
+ Serial.print(":success:\n");
+}
+
+void recive() {
+ uint8_t payload[32];
+
+ if (radio.available()) {
+ radio.read(&payload, sizeof(payload));
+
+ // Send ACK to current radio node
+ sendACK(payload[0]);
+
+ for (uint8_t j = 0; j < sizeof(payload); j++) {
+ if (payload[j] == 10) {
+ Serial.write(23);
+ break;
+ }
+
+ Serial.write(payload[j]);
+ }
+
+ Serial.write(10);
+ }
+}
+
+boolean sendWithACK(uint8_t *data, uint8_t size) {
+ uint8_t response[32];
+ unsigned long ack_started_at;
+
+ for (uint8_t i = 0; i <= radio_retries; i++) {
+ radio.stopListening();
+ radio.writeFast(data, size);
+ radio.txStandBy();
+ radio.startListening();
+
+ ack_started_at = millis();
+
+ // Wait for responce
+ while (millis() - ack_started_at <= radio_delay) {
+ if (radio.available()) {
+ radio.read(&response, sizeof(response));
+
+ if (data[0] == response[0] && response[1] == 6) {
+ return true;
+ }
+
+ // Send ACK to current radio node
+ sendACK(response[0]);
+
+ for (uint8_t j = 0; j < sizeof(response); j++) {
+ if (response[j] == 10) {
+ Serial.write(23);
+ break;
+ }
+
+ Serial.write(response[j]);
+ }
+
+ Serial.write(10);
+ }
+ }
+ }
+
+ return false;
+}
+
+void sendACK(uint8_t radio_node) {
+ uint8_t ack[2];
+ ack[0] = radio_node;
+ ack[1] = 6;
+ radio.stopListening();
+ radio.writeFast(ack, sizeof(ack));
+ radio.txStandBy();
+ radio.startListening();
+}
+
+void serialFlush(){
+ while(Serial.available() > 0) {
+ char t = Serial.read();
+ }
+}
+
+uint64_t getUInt64fromHex(char const *str)
+{
+ uint64_t accumulator = 0;
+ for (size_t i = 0 ; isxdigit((unsigned char)str[i]) ; ++i)
+ {
+ char c = str[i];
+ accumulator *= 16;
+ if (isdigit(c)) /* '0' .. '9'*/
+ accumulator += c - '0';
+ else if (isupper(c)) /* 'A' .. 'F'*/
+ accumulator += c - 'A' + 10;
+ else /* 'a' .. 'f'*/
+ accumulator += c - 'a' + 10;
+ }
+
+ return accumulator;
+}
diff --git a/arduino/simple_rx.c b/arduino/simple_rx.c
new file mode 100644
index 0000000..a9212e9
--- /dev/null
+++ b/arduino/simple_rx.c
@@ -0,0 +1,39 @@
+#include
+#include
+#include
+
+// Radio setting
+RF24 radio(9, 10); // For nano pin 9 and 10
+
+void setup() {
+ Serial.begin(9600);
+ Serial.setTimeout(50);
+ radio.begin();
+ delay(100);
+ radio.powerUp();
+ radio.setChannel(70);
+
+ radio.setAutoAck(false); // Disable hardware ACK, use program ACK
+
+ radio.setPayloadSize(32);
+ radio.setCRCLength(RF24_CRC_8);
+ radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
+ radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
+ radio.openWritingPipe(0xBBBBBBBB22LL);
+ radio.openReadingPipe(1, 0xBBBBBBBB11LL);
+ radio.startListening();
+}
+
+void loop() {
+ if (radio.available()) {
+ Serial.println("recieved");
+ delay(1000);
+ byte payload[32];
+ radio.read(&payload, sizeof(payload));
+
+ // radio.powerDown();
+ // delay(5000);
+ // radio.powerUp();
+ // radio.startListening();
+ }
+}
diff --git a/arduino/simple_tx.c b/arduino/simple_tx.c
new file mode 100644
index 0000000..ef20ff0
--- /dev/null
+++ b/arduino/simple_tx.c
@@ -0,0 +1,45 @@
+#include
+#include
+#include
+
+boolean isRadioSeted = false;
+RF24 radio(9, 10);
+
+int data = 1;
+
+void setup() {
+ Serial.begin(9600);
+ Serial.setTimeout(50);
+ delay(3000);
+}
+
+void radioSetup() {
+
+ radio.begin();
+ delay(100);
+ radio.powerUp();
+ radio.setChannel(70);
+
+ radio.setAutoAck(false); // Disable hardware ACK, use program ACK
+
+ radio.setPayloadSize(32);
+ radio.setCRCLength(RF24_CRC_8);
+ radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
+ radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
+ radio.openWritingPipe(0xBBBBBBBB11LL);
+ radio.openReadingPipe(1, 0xBBBBBBBB22LL);
+ radio.startListening();
+}
+
+void loop() {
+ if (!isRadioSeted) {
+ radioSetup();
+ isRadioSeted = true;
+ }
+ radio.stopListening();
+ radio.writeFast(&data, sizeof(data));
+ radio.txStandBy();
+ radio.startListening();
+ Serial.println("sent");
+ delay(5000);
+}
diff --git a/arduino/sleeping_station.c b/arduino/sleeping_station.c
new file mode 100755
index 0000000..803cf44
--- /dev/null
+++ b/arduino/sleeping_station.c
@@ -0,0 +1,187 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Radio setting
+RF24 radio(9, 10); // For nano pin 9 and 10
+int radioSpeedPin = 2;
+int radioChannelPin1 = 3;
+int radioChannelPin2 = 4;
+int radio_retries = 5;
+int radio_delay = 10;
+byte radioSpeedState = 0; // 0 is RF24_250KBPS and 1 is RF24_1MBPS
+
+// DHT setting
+#define DHTTYPE DHT22 // DHT 11
+const byte dht_pin = 8;
+DHT dht(dht_pin, DHTTYPE);
+float humi;
+float temp;
+
+// Battery setting
+int bat_pin = A0;
+// float max_v = 4.1;
+// float min_v = 2.5;
+float bat = 0;
+
+String pipe_str = "AABBCCDD11"; // Keep the format
+
+void setup() {
+ analogReference(INTERNAL);
+ pinMode(radioSpeedPin, INPUT);
+ // Serial.begin(9600);
+ radio.begin();
+ delay(100);
+ radio.powerUp();
+ radio.setAutoAck(false);
+ radio.setChannel(90); // (0 - 127)
+ radio.setRetries(15,15);
+ radio.setPayloadSize(32);
+ radio.setCRCLength(RF24_CRC_8);
+ radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
+ radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
+ radio.openWritingPipe(0xAABBCCDD88LL);
+ radio.openReadingPipe(1, 0xAABBCCDD11LL);
+ // radio.startListening();
+ getDhtParams();
+ getBatteryVoltage();
+
+ delay(5000); // Sleep 5s before loop. It's Important!
+}
+
+void loop() {
+ // checkRadioSetting();
+ wdt_enable(WDTO_8S); //Задаем интервал сторожевого таймера (30ms) WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS etc.
+ WDTCSR |= (1 << WDIE); //Устанавливаем бит WDIE регистра WDTCSR для разрешения прерываний от сторожевого таймера
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Устанавливаем интересующий нас режим
+ radio.powerDown();
+
+ sleep_mode(); // Переводим МК в спящий режим
+
+ getBatteryVoltage();
+ getDhtParams();
+ delay(300);
+ getDhtParams();
+ radio.powerUp();
+ sendStatus();
+}
+
+void checkRadioSetting() {
+ byte currentSpeed = 0;
+
+ if (digitalRead(radioSpeedPin) == HIGH) {
+ currentSpeed = 1;
+ }
+
+ if (radioSpeedState != currentSpeed)
+ {
+ if (currentSpeed == 0) {
+ radioSpeedState = 0;
+ // Serial.println("RF24_250KBPS");
+ // radio.setDataRate(RF24_250KBPS);
+ // Serial.println("RF24_1MBPS");
+ radio.setDataRate(RF24_1MBPS);
+ } else {
+ radioSpeedState = 1;
+ // Serial.println("RF24_1MBPS");
+ // radio.setDataRate(RF24_1MBPS);
+ // Serial.println("RF24_2MBPS");
+ radio.setDataRate(RF24_2MBPS);
+ }
+ }
+}
+
+void getDhtParams() {
+ float h = dht.readHumidity();
+ float t = dht.readTemperature();
+
+ if (!isnan(t) && !isnan(h)) {
+ humi = h;
+ temp = t;
+ }
+}
+
+void getBatteryVoltage() {
+ bat = ((analogRead(bat_pin) * 1.1) / 1023) * 10.86;
+}
+
+void sendStatus() {
+ // Max payload size in one package is 32 bytes
+ String payload_0 = "0"; // Package nubber
+ payload_0 += pipe_str; // Reading pipe of the station
+ payload_0 += "type e,";
+ payload_0 += "h ";
+ payload_0 += humi;
+
+ int rsize = payload_0.length();
+
+ byte byte_arr[rsize+1];
+ payload_0.getBytes(byte_arr, rsize+1);
+
+ if (!sendWithACK(byte_arr, rsize)) {
+ // Serial.println("sendStatus failed");
+ return;
+ }
+
+ String payload_1 = "1"; // Package nubber
+ payload_1 += ",t ";
+ payload_1 += temp;
+
+ // Add Battery voltage
+ payload_1 += ",b ";
+ payload_1 += bat;
+ payload_1 += "\n";
+
+ rsize = payload_1.length();
+
+ byte byte_arr_2[rsize+1];
+ payload_1.getBytes(byte_arr_2, rsize+1);
+
+ if (!sendWithACK(byte_arr_2, rsize)) {
+ // Serial.println("sendStatus failed2");
+ }
+}
+
+boolean sendWithACK(byte * data, int size) {
+ byte income_pipe;
+ byte response[32];
+ unsigned long ack_started_at;
+
+ for (int i = 0; i <= radio_retries; i++) {
+ radio.stopListening();
+ radio.write(data, size);
+ radio.startListening();
+
+ ack_started_at = millis();
+ // Wait 15ms for responce
+ while (millis() - ack_started_at <= 15) {
+ if (radio.available(&income_pipe)) {
+ if (income_pipe == 1) {
+ radio.read(&response, sizeof(response));
+
+ if (response[0] == 6) {
+ return true;
+ } else {
+ continue;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void sendACK() {
+ byte ack[1] = {6};
+ radio.stopListening();
+ radio.write(ack, sizeof(ack));
+ radio.startListening();
+}
+
+ISR (WDT_vect) {
+ wdt_disable();
+}
diff --git a/arduino/sleeping_station_bme280_v2.c b/arduino/sleeping_station_bme280_v2.c
new file mode 100644
index 0000000..5bd2c8e
--- /dev/null
+++ b/arduino/sleeping_station_bme280_v2.c
@@ -0,0 +1,181 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Radio setting
+RF24 radio(9, 10); // For nano pin 9 and 10
+int radioSpeedPin = 2;
+int radioChannelPin1 = 3;
+int radioChannelPin2 = 4;
+int radio_retries = 3;
+int radio_delay = 8;
+byte radioSpeedState = 0; // 0 is RF24_250KBPS and 1 is RF24_1MBPS
+
+String pipe_str = "AABBCCCC22"; // Keep the format
+
+// BME280 setting
+float humi;
+float temp;
+float pres;
+Adafruit_BME280 bme; // I2C
+
+// Battery setting
+int bat_pin = A0;
+float bat;
+
+void setup() {
+ delay(3000); // Sleep 3s before loop.
+
+ analogReference(INTERNAL);
+ pinMode(radioSpeedPin, INPUT);
+ // Serial.begin(9600);
+ radio.begin();
+ delay(100);
+ radio.powerUp();
+ radio.setAutoAck(false); // Disable hardware ACK, use program ACK
+ radio.setChannel(90); // (0 - 127)
+ // radio.setRetries(15,15);
+ radio.setPayloadSize(32);
+ radio.setCRCLength(RF24_CRC_8);
+ radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
+ radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
+ radio.openWritingPipe(0xAABBCCDD88LL);
+ radio.openReadingPipe(1, 0xAABBCCCC22LL);
+
+ bme.begin(0x76); // 0x76 or 0x77 for bme280
+
+ readBMP();
+ getBatteryVoltage();
+}
+
+void loop() {
+ // checkRadioSetting();
+ radio.powerDown();
+ wdt_enable(WDTO_8S); // WDT interval WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS, WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S
+ WDTCSR |= (1 << WDIE); // Enable WDT
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode
+ sleep_mode(); // Go to sleep
+ getBatteryVoltage();
+ readBMP();
+ radio.powerUp();
+ sendStatus();
+}
+
+void checkRadioSetting() {
+ byte currentSpeed = 0;
+
+ if (digitalRead(radioSpeedPin) == HIGH) {
+ currentSpeed = 1;
+ }
+
+ if (radioSpeedState != currentSpeed)
+ {
+ if (currentSpeed == 0) {
+ radioSpeedState = 0;
+ // Serial.println("RF24_250KBPS");
+ // radio.setDataRate(RF24_250KBPS);
+ // Serial.println("RF24_1MBPS");
+ radio.setDataRate(RF24_1MBPS);
+ } else {
+ radioSpeedState = 1;
+ // Serial.println("RF24_1MBPS");
+ // radio.setDataRate(RF24_1MBPS);
+ // Serial.println("RF24_2MBPS");
+ radio.setDataRate(RF24_2MBPS);
+ }
+ }
+}
+
+void readBMP() {
+ humi = bme.readHumidity();
+ temp = bme.readTemperature();
+ pres = bme.readPressure() / 100.0F;
+}
+
+void getBatteryVoltage() {
+ bat = ((analogRead(bat_pin) * 1.1) / 1023) * 11;
+}
+
+void sendStatus() {
+ // Max payload size in one package is 32 bytes
+ String payload_0 = "0"; // Package nubber
+ payload_0 += pipe_str; // Reading pipe of the station
+ payload_0 += "type e,";
+ payload_0 += "h ";
+ payload_0 += humi;
+
+ int rsize = payload_0.length();
+
+ byte byte_arr[rsize+1];
+ payload_0.getBytes(byte_arr, rsize+1);
+
+ if (!sendWithACK(byte_arr, rsize)) {
+ // Serial.println("sendStatus failed");
+ return;
+ }
+
+ String payload_1 = "1"; // Package nubber
+ payload_1 += ",t ";
+ payload_1 += temp;
+ payload_1 += ",p ";
+ payload_1 += pres;
+
+ // Add Battery voltage
+ payload_1 += ",b ";
+ payload_1 += bat;
+ payload_1 += "\n";
+
+ rsize = payload_1.length();
+
+ byte byte_arr_2[rsize+1];
+ payload_1.getBytes(byte_arr_2, rsize+1);
+
+ if (!sendWithACK(byte_arr_2, rsize)) {
+ // Serial.println("sendStatus failed2");
+ }
+}
+
+boolean sendWithACK(byte * data, int size) {
+ byte income_pipe;
+ byte response[32];
+ unsigned long ack_started_at;
+
+ for (int i = 0; i <= radio_retries; i++) {
+ radio.stopListening();
+ radio.write(data, size);
+ radio.startListening();
+
+ ack_started_at = millis();
+ // Wait 15ms for responce
+ while (millis() - ack_started_at <= radio_delay) {
+ if (radio.available(&income_pipe)) {
+ if (income_pipe == 1) {
+ radio.read(&response, sizeof(response));
+
+ if (response[0] == 6) {
+ return true;
+ } else {
+ continue;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void sendACK() {
+ byte ack[1] = {6};
+ radio.stopListening();
+ radio.write(ack, sizeof(ack));
+ radio.startListening();
+}
+
+ISR (WDT_vect) {
+ wdt_disable();
+}
diff --git a/arduino/sleeping_station_bme280_v3.c b/arduino/sleeping_station_bme280_v3.c
new file mode 100644
index 0000000..865ac24
--- /dev/null
+++ b/arduino/sleeping_station_bme280_v3.c
@@ -0,0 +1,169 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Radio setting
+RF24 radio(9, 10); // For nano pin 9 and 10
+int radioSpeedPin = 2;
+int radioChannelPin1 = 3;
+int radioChannelPin2 = 4;
+int radio_retries = 15;
+int radio_delay = 15;
+byte radioSpeedState = 0; // 0 is RF24_250KBPS and 1 is RF24_1MBPS
+
+uint8_t radio_id = 49;
+// String pipe_str = "AABBCCCC22"; // Keep the format
+
+// BME280 setting
+float humi;
+float temp;
+float pres;
+Adafruit_BME280 bme; // I2C
+
+// Battery setting
+int bat_pin = A0;
+float bat;
+
+unsigned long status_timer;
+
+void setup() {
+ delay(3000); // Sleep 3s before loop.
+
+ analogReference(INTERNAL);
+ pinMode(radioSpeedPin, INPUT);
+ // Serial.begin(9600);
+ radio.begin();
+ delay(100);
+ radio.powerUp();
+ radio.setChannel(90); // (0 - 127)
+ radio.setAutoAck(false); // Disable hardware ACK, use program ACK
+ radio.setPayloadSize(32);
+ radio.setCRCLength(RF24_CRC_8);
+ radio.setDataRate(RF24_1MBPS); // (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
+ radio.setPALevel(RF24_PA_MAX); // (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
+ radio.openWritingPipe(0xAAAAAAAA22LL);
+ radio.openReadingPipe(1, 0xAAAAAAAA11LL);
+
+ bme.begin(0x76); // 0x76 or 0x77 for bme280
+ delay(50);
+ readBMP();
+ getBatteryVoltage();
+}
+
+void loop() {
+ // Serial.println("start");
+ // checkRadioSetting();
+ radio.powerDown();
+ wdt_enable(WDTO_8S); // WDT interval WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS, WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S
+ WDTCSR |= (1 << WDIE); // Enable WDT
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode
+ sleep_mode(); // Go to sleep
+ getBatteryVoltage();
+ readBMP();
+ radio.powerUp();
+ sendStatus();
+
+ // if (millis() - status_timer > 2000) {
+ // sendStatus();
+ // status_timer = millis();
+ // }
+}
+
+void readBMP() {
+ humi = bme.readHumidity();
+ temp = bme.readTemperature();
+ pres = bme.readPressure() / 100.0F;
+
+ // humi = 42.00;
+ // temp = 23.20;
+ // pres = 1030.00;
+}
+
+void getBatteryVoltage() {
+ bat = ((analogRead(bat_pin) * 1.1) / 1023) * 11;
+}
+
+void sendStatus() {
+ // Serial.print("status\n");
+ uint8_t radio_buff[32];
+ uint8_t radio_buff_index = 2;
+ uint8_t radio_package = 48;
+
+ // Max payload size in one package is 32 bytes
+ String payload = "tp ev,";
+ payload += "h ";
+ payload += humi;
+ payload += ",t ";
+ payload += temp;
+ payload += ",p ";
+ payload += pres;
+ payload += ",b ";
+ payload += bat;
+ payload += "\n";
+
+ int rsize = payload.length();
+
+ radio_buff[0] = radio_id;
+ radio_buff[1] = radio_package;
+
+ for (int i = 0; i < rsize; i++) {
+ radio_buff[radio_buff_index] = payload[i];
+ radio_buff_index++;
+
+ if (radio_buff_index == 32 || payload[i] == 10) {
+ radio_buff[1] = radio_package;
+
+ if (!sendWithACK(radio_buff, radio_buff_index)) {
+ // Serial.print("fail\n");
+ return;
+ } else {
+ // delay(15);
+ // Serial.print("success\n");
+ }
+
+ radio_package++;
+ radio_buff_index = 2;
+ }
+ }
+}
+
+boolean sendWithACK(uint8_t *data, uint8_t size) {
+ uint8_t response[32];
+ unsigned long ack_started_at;
+
+ for (int i = 0; i <= radio_retries; i++) {
+ radio.stopListening();
+ radio.writeFast(data, size);
+ radio.txStandBy();
+ radio.startListening();
+
+ ack_started_at = millis();
+ // Wait 15ms for responce
+ while (millis() - ack_started_at <= radio_delay) {
+ if (radio.available()) {
+ radio.read(&response, sizeof(response));
+
+ if (data[0] == response[0] && response[1] == 6) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void sendACK() {
+ uint8_t ack[1] = {6};
+ radio.stopListening();
+ radio.write(ack, sizeof(ack));
+ radio.startListening();
+}
+
+ISR (WDT_vect) {
+ wdt_disable();
+}
diff --git a/arduino/test_rx.c b/arduino/test_rx.c
old mode 100644
new mode 100755
diff --git a/arduino/test_tx.c b/arduino/test_tx.c
old mode 100644
new mode 100755
diff --git a/bower.json b/bower.json
deleted file mode 100755
index 95dbe06..0000000
--- a/bower.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "raspberry",
- "description": "raspberry",
- "main": "",
- "authors": [
- "Zazimko Alexey "
- ],
- "license": "MIT",
- "keywords": [
- "remote",
- "infrared",
- "raspberry"
- ],
- "homepage": "https://github.com/notfoundsam/raspberry",
- "private": true,
- "ignore": [
- "**/.*",
- "node_modules",
- "bower_components",
- "test",
- "tests"
- ],
- "devDependencies": {
- "components-font-awesome": "^4.7.0",
- "socket.io-client": "^2.0.3",
- "framework7": "^2.2.5"
- }
-}
diff --git a/config.py b/config.py
deleted file mode 100755
index d1db076..0000000
--- a/config.py
+++ /dev/null
@@ -1,10 +0,0 @@
-import os
-basedir = os.path.abspath(os.path.dirname(__file__))
-
-SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')
-SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')
-
-CSRF_ENABLED = True
-SECRET_KEY = 'you-will-never-guess'
-
-SQLALCHEMY_TRACK_MODIFICATIONS = False
diff --git a/db_create.py b/db_create.py
deleted file mode 100755
index 577e583..0000000
--- a/db_create.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!flask/bin/python
-from migrate.versioning import api
-from config import SQLALCHEMY_DATABASE_URI
-from config import SQLALCHEMY_MIGRATE_REPO
-from app import db
-import os.path
-from app.models import User
-
-db.create_all()
-if not os.path.exists(SQLALCHEMY_MIGRATE_REPO):
- api.create(SQLALCHEMY_MIGRATE_REPO, 'database repository')
- api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-else:
- api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO,
- api.version(SQLALCHEMY_MIGRATE_REPO))
-
-root = User(username = 'root', password = 'root', role = '1')
-
-db.session.add(root)
-db.session.commit()
diff --git a/db_downgrade.py b/db_downgrade.py
deleted file mode 100755
index 59200a9..0000000
--- a/db_downgrade.py
+++ /dev/null
@@ -1,8 +0,0 @@
-#!flask/bin/python
-from migrate.versioning import api
-from config import SQLALCHEMY_DATABASE_URI
-from config import SQLALCHEMY_MIGRATE_REPO
-v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-api.downgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, v - 1)
-v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-print('Current database version: ' + str(v))
diff --git a/db_migrate.py b/db_migrate.py
deleted file mode 100755
index 3d69474..0000000
--- a/db_migrate.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#!flask/bin/python
-import imp
-from migrate.versioning import api
-from app import db
-from config import SQLALCHEMY_DATABASE_URI
-from config import SQLALCHEMY_MIGRATE_REPO
-v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-migration = SQLALCHEMY_MIGRATE_REPO + ('/versions/%03d_migration.py' % (v+1))
-tmp_module = imp.new_module('old_model')
-old_model = api.create_model(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-exec old_model in tmp_module.__dict__
-script = api.make_update_script_for_model(SQLALCHEMY_DATABASE_URI,
- SQLALCHEMY_MIGRATE_REPO,
- tmp_module.meta, db.metadata)
-open(migration, "wt").write(script)
-api.upgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-print('New migration saved as ' + migration)
-print('Current database version: ' + str(v))
diff --git a/db_upgrade.py b/db_upgrade.py
deleted file mode 100755
index d17f322..0000000
--- a/db_upgrade.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!flask/bin/python
-from migrate.versioning import api
-from config import SQLALCHEMY_DATABASE_URI
-from config import SQLALCHEMY_MIGRATE_REPO
-api.upgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)
-print('Current database version: ' + str(v))
diff --git a/docker-compose-rpi.yml b/docker-compose-rpi.yml
old mode 100644
new mode 100755
diff --git a/docker-compose-server.yml b/docker-compose-server.yml
new file mode 100644
index 0000000..dd498a2
--- /dev/null
+++ b/docker-compose-server.yml
@@ -0,0 +1,62 @@
+version: '3'
+services:
+ db:
+ image: mysql:5.6
+ environment:
+ - MYSQL_ROOT_PASSWORD=root
+ - MYSQL_DATABASE=smart_remote
+ volumes:
+ - mysql-data:/var/lib/mysql
+ ports:
+ - "3306:3306"
+ networks:
+ - rpi-net
+ node-red:
+ build:
+ context: ./node-red
+ dockerfile: Dockerfile
+ environment:
+ - FLOWS=smart_remote.json
+ volumes:
+ - node-red:/data
+ ports:
+ - "1880:1880"
+ - "9090:9090"
+ user: node-red
+ networks:
+ - rpi-net
+ influxdb:
+ image: influxdb
+ environment:
+ - INFLUXDB_DB=smart_remote
+ volumes:
+ - influx-data:/var/lib/influxdb
+ ports:
+ - "8086:8086"
+ networks:
+ - rpi-net
+ grafana:
+ image: grafana/grafana
+ volumes:
+ - grafana:/var/lib/grafana
+ ports:
+ - "3000:3000"
+ networks:
+ - rpi-net
+ mosquitto:
+ image: eclipse-mosquitto
+ ports:
+ - "1883:1883"
+ - "9001:9001"
+ networks:
+ - rpi-net
+
+networks:
+ rpi-net:
+ driver: bridge
+
+volumes:
+ influx-data:
+ mysql-data:
+ node-red:
+ grafana:
diff --git a/docker-compose-swarm-server.yml b/docker-compose-swarm-server.yml
new file mode 100644
index 0000000..ade9529
--- /dev/null
+++ b/docker-compose-swarm-server.yml
@@ -0,0 +1,97 @@
+version: '3.3'
+services:
+ db:
+ image: mysql:5.6
+ environment:
+ - MYSQL_ROOT_PASSWORD=root
+ - MYSQL_DATABASE=smart_remote
+ volumes:
+ - mysql-data:/var/lib/mysql
+ ports:
+ - "3306:3306"
+ networks:
+ - rpi-net
+ deploy:
+ replicas: 1
+ placement:
+ constraints:
+ - node.role == manager
+ node-red:
+ build:
+ context: ./node-red
+ dockerfile: Dockerfile
+ image: notfoundsam/node-red-swarm
+ environment:
+ - FLOWS=smart_remote.json
+ ports:
+ - "1880:1880"
+ - "9090:9090"
+ user: node-red
+ networks:
+ - rpi-net
+ deploy:
+ replicas: 1
+ influxdb:
+ image: influxdb
+ environment:
+ - INFLUXDB_DB=smart_remote
+ ports:
+ - "8086:8086"
+ volumes:
+ - influx-data:/var/lib/influxdb
+ networks:
+ - rpi-net
+ deploy:
+ replicas: 1
+ placement:
+ constraints:
+ - node.role == manager
+ grafana:
+ image: grafana/grafana
+ ports:
+ - "3000:3000"
+ volumes:
+ - grafana-data:/var/lib/grafana
+ networks:
+ - rpi-net
+ deploy:
+ replicas: 1
+ placement:
+ constraints:
+ - node.role == manager
+ mosquitto:
+ image: eclipse-mosquitto
+ ports:
+ - "1883:1883"
+ - "9001:9001"
+ networks:
+ - rpi-net
+ deploy:
+ replicas: 1
+
+ cadvisor:
+ image: google/cadvisor
+ hostname: '{{.Node.Hostname}}'
+ command: -logtostderr -docker_only -storage_driver=influxdb -storage_driver_db=smart_remote -storage_driver_host=influxdb:8086
+ volumes:
+ - /:/rootfs:ro
+ - /var/run:/var/run:ro
+ - /sys:/sys:ro
+ - /var/lib/docker/:/var/lib/docker:ro
+ # - /dev/disk/:/dev/disk:ro
+ ports:
+ - "8080:8080"
+ networks:
+ - rpi-net
+ deploy:
+ mode: global
+
+networks:
+ rpi-net:
+ driver: overlay
+ attachable: true
+
+volumes:
+ influx-data:
+ mysql-data:
+ grafana-data:
diff --git a/docker-compose-swarm.yml b/docker-compose-swarm.yml
old mode 100644
new mode 100755
index 0a3aef2..ed4103e
--- a/docker-compose-swarm.yml
+++ b/docker-compose-swarm.yml
@@ -18,7 +18,24 @@ services:
volumes:
- influx-data:/var/lib/influxdb
deploy:
- replicas: 2
+ replicas: 1
+ placement:
+ constraints:
+ - node.role == manager
+ mysql:
+ image: hypriot/rpi-mysql
+ environment:
+ - MYSQL_ROOT_PASSWORD=root
+ - MYSQL_DATABASE=smart_remote
+ ports:
+ - "3306:3306"
+ volumes:
+ - mysql-data:/var/lib/mysql
+ deploy:
+ replicas: 1
+ placement:
+ constraints:
+ - node.role == manager
grafana:
image: fg2it/grafana-armhf:v5.1.3
ports:
@@ -35,3 +52,4 @@ services:
volumes:
influx-data:
+ mysql-data:
diff --git a/docker-compose.yml b/docker-compose.yml
index 198df94..4e30940 100755
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,30 +1,46 @@
version: '2'
services:
- # db:
- # image: mysql:5.6
- # environment:
- # - MYSQL_ROOT_PASSWORD=root
- # - MYSQL_DATABASE=smart_remote
- # volumes:
- # - ./docker/mysql-data:/var/lib/mysql
- # ports:
- # - "3390:3306"
+ db:
+ image: mysql:5.7
+ command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
+ environment:
+ - MYSQL_ROOT_PASSWORD=root
+ - MYSQL_DATABASE=smart_remote
+ volumes:
+ - mysql-data:/var/lib/mysql
+ ports:
+ - "3390:3306"
+ networks:
+ - rpi-net
web:
build:
context: .
dockerfile: Dockerfile
- command: bash -c "python run.py"
+ command: ["python3","-u","run.py"]
working_dir: /app
environment:
- - APP_ENV=development
+ - FLASK_ENV=development
+ - FLASK_DEBUG=1
- APP_DOCKER=true
+ - FLASK_APP=app/__init__.py
volumes:
- ./:/app
ports:
- "5000:5000"
+ - "5002:5002"
+ # - "9090:9090"
privileged: true
# devices:
# - "/dev/ttyUSB0:/dev/ttyUSB0"
+ networks:
+ - rpi-net
+ # network_mode: host
+ depends_on:
+ - influxdb
+ - db
+ - node-red
+ - grafana
+ - mosquitto
node-red:
build:
context: ./node-red
@@ -32,28 +48,45 @@ services:
environment:
- FLOWS=smart_remote.json
volumes:
- - ./node-red:/data:Z
+ - node-red:/data
ports:
- "1880:1880"
+ - "9090:9090"
user: node-red
+ networks:
+ - rpi-net
influxdb:
image: influxdb
environment:
- INFLUXDB_DB=smart_remote
volumes:
- - ./docker/influx-data:/var/lib/influxdb
+ - influx-data:/var/lib/influxdb
ports:
- "8086:8086"
+ networks:
+ - rpi-net
grafana:
image: grafana/grafana
+ volumes:
+ - grafana:/var/lib/grafana
ports:
- "3000:3000"
+ networks:
+ - rpi-net
mosquitto:
image: eclipse-mosquitto
ports:
- "1883:1883"
- "9001:9001"
+ networks:
+ - rpi-net
-# volumes:
-# mysql-data:
-# influx-data:
+networks:
+ rpi-net:
+ driver: bridge
+
+volumes:
+ influx-data:
+ mysql-data:
+ node-red:
+ grafana:
diff --git a/esp8266/mqtt.c b/esp8266/mqtt.c
new file mode 100644
index 0000000..f2de5a8
--- /dev/null
+++ b/esp8266/mqtt.c
@@ -0,0 +1,88 @@
+/*
+ This sketch sends a string to a TCP server, and prints a one-line response.
+ You must run a TCP server in your local network.
+ For example, on Linux you can use this command: nc -v -l 3000
+*/
+
+#include
+#include
+
+const char* ssid = "";
+const char* password = "";
+
+const char* mqtt_server = "192.168.100.10";
+
+WiFiClient client01;
+PubSubClient client(espClient);
+
+void setup_wifi() {
+ delay(10);
+ // We start by connecting to a WiFi network
+ Serial.println();
+ Serial.print("Connecting to ");
+ Serial.println(ssid);
+ WiFi.begin(ssid, password);
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(500);
+ Serial.print(".");
+ }
+ Serial.println("");
+ Serial.print("WiFi connected - ESP IP address: ");
+ Serial.println(WiFi.localIP());
+}
+
+void setup() {
+ Serial.begin(115200);
+
+ // We start by connecting to a WiFi network
+ WiFi.mode(WIFI_STA);
+ WiFiMulti.addAP(ssid, password);
+
+ Serial.println();
+ Serial.println();
+ Serial.print("Wait for WiFi... ");
+
+ while (WiFiMulti.run() != WL_CONNECTED) {
+ Serial.print(".");
+ delay(500);
+ }
+
+ Serial.println("");
+ Serial.println("WiFi connected");
+ Serial.println("IP address: ");
+ Serial.println(WiFi.localIP());
+
+ delay(500);
+}
+
+
+void loop() {
+ Serial.print("connecting to ");
+ Serial.print(host);
+ Serial.print(':');
+ Serial.println(port);
+
+ // Use WiFiClient class to create TCP connections
+ WiFiClient client;
+
+ if (!client.connect(host, port)) {
+ Serial.println("connection failed");
+ Serial.println("wait 5 sec...");
+ delay(5000);
+ return;
+ }
+
+ // This will send the request to the server
+ client.println("hello from ESP8266");
+
+ //read back one line from server
+ Serial.println("receiving from remote server");
+ String line = client.readStringUntil('\r');
+ Serial.println(line);
+
+ Serial.println("closing connection");
+ client.stop();
+
+ Serial.println("wait 5 sec...");
+ delay(5000);
+}
diff --git a/esp8266/mqtt2.h b/esp8266/mqtt2.h
new file mode 100644
index 0000000..2ebb30c
--- /dev/null
+++ b/esp8266/mqtt2.h
@@ -0,0 +1,150 @@
+#include "EspMQTTClient.h"
+#include
+
+void onConnectionEstablished();
+
+/*
+
+EspMQTTClient client(
+ "", // Wifi ssid
+ "", // Wifi password
+ onConnectionEstablished,// MQTT connection established callback
+ "192.168.100.111" // MQTT broker ip
+);
+*/
+
+#define MQTT_MAX_PACKET_SIZE 256
+
+EspMQTTClient client(
+ "", // Wifi ssid
+ "", // Wifi password
+ onConnectionEstablished,// Connection established callback
+ "192.168.100.111", // MQTT broker ip
+ 1883, // MQTT broker port
+ "", // MQTT username
+ "", // MQTT password
+ "esp02", // Client name
+ false, // Enable web updater
+ false // Enable debug messages
+);
+
+const uint16_t kIrLed = 4; // ESP8266 GPIO pin to use. Recommended: 4 (D2).
+
+IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message.
+
+// uint16_t raw_signal[400];
+
+void setup()
+{
+ irsend.begin();
+ Serial.begin(115200);
+}
+
+void onConnectionEstablished()
+{
+ // Subscribe to "mytopic/test" and display received message to Serial
+ client.subscribe("alexa/esp1", [](const String & code) {
+ Serial.println("event");
+ if (code[0] != 50) {
+ return;
+ }
+ Serial.println("start");
+
+ int zero = 0;
+ int one = 0;
+ char buffer[5];
+ byte buffer_index = 0;
+ boolean bit_code = false;
+ uint16_t raw_signal[300];
+ int raw_index = 0;
+
+ // Setup zero length
+ buffer[0] = code[1];
+ buffer[1] = code[2];
+ buffer[2] = code[3];
+ buffer[3] = '\0';
+ zero = atoi(buffer);
+ memset(buffer, 0, sizeof(buffer));
+
+ // Setup one length
+ buffer[0] = code[5];
+ buffer[1] = code[6];
+ buffer[2] = code[7];
+ buffer[3] = code[8];
+ buffer[4] = '\0';
+ one = atoi(buffer);
+ memset(buffer, 0, sizeof(buffer));
+ uint16_t rsize = code.length();
+
+ for (int i = 10; i < rsize; ++i)
+ {
+ if (code[i] == 91) {
+ bit_code = true;
+ continue;
+ } else if (code[i] == 93) {
+ bit_code = false;
+ continue;
+ }
+
+ if (bit_code) {
+ if (code[i] > 47 && code[i] < 58) {
+ buffer[buffer_index] = code[i];
+ buffer_index++;
+ continue;
+ } else if (code[i] == 97) {
+ int rep = atoi(buffer);
+
+ for (int j = 0; j < rep; ++j)
+ {
+ raw_signal[raw_index] = zero;
+ raw_index++;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ } else if (code[i] == 98) {
+ int rep = atoi(buffer);
+
+ for (int j = 0; j < rep; ++j)
+ {
+ raw_signal[raw_index] = one;
+ raw_index++;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ }
+ } else {
+ if (code[i] > 47 && code[i] < 58) {
+ buffer[buffer_index] = code[i];
+ buffer_index++;
+ } else if (code[i] == 32 && buffer_index > 0) {
+ raw_signal[raw_index] = atoi(buffer);
+ raw_index++;
+ memset(buffer, 0, sizeof(buffer));
+ buffer_index = 0;
+ } else if (code[i] == 10) {
+ raw_signal[raw_index] = atoi(buffer);
+ break;
+ }
+ }
+ }
+
+ Serial.println(code);
+ Serial.println(rsize);
+ irsend.sendRaw(raw_signal, raw_index, 38);
+ });
+
+ // Publish a message to "mytopic/test"
+ // client.publish("test/one", "This is a message");
+
+ // Execute delayed instructions
+ // client.executeDelayed(5 * 1000, []() {
+ // client.publish("test/one", "This is a message sent 5 seconds later");
+ // });
+}
+
+void loop()
+{
+ client.loop();
+}
\ No newline at end of file
diff --git a/esp8266/node_mcu/switch/init.lua b/esp8266/node_mcu/switch/init.lua
old mode 100644
new mode 100755
diff --git a/esp8266/node_mcu/switch/mqttmodule.lua b/esp8266/node_mcu/switch/mqttmodule.lua
old mode 100644
new mode 100755
diff --git a/esp8266/node_mcu/switch/wifimodule.lua b/esp8266/node_mcu/switch/wifimodule.lua
old mode 100644
new mode 100755
diff --git a/esp8266/node_mcu/weather_station/init.lua b/esp8266/node_mcu/weather_station/init.lua
old mode 100644
new mode 100755
diff --git a/esp8266/node_mcu/weather_station/init2.lua b/esp8266/node_mcu/weather_station/init2.lua
old mode 100644
new mode 100755
diff --git a/esp8266/node_mcu/weather_station/mqttmodule.lua b/esp8266/node_mcu/weather_station/mqttmodule.lua
old mode 100644
new mode 100755
diff --git a/esp8266/node_mcu/weather_station/wifimodule.lua b/esp8266/node_mcu/weather_station/wifimodule.lua
old mode 100644
new mode 100755
diff --git a/grafana/dashboard_weather.json b/grafana/dashboard_weather.json
old mode 100644
new mode 100755
index fb5f668..3e16159
--- a/grafana/dashboard_weather.json
+++ b/grafana/dashboard_weather.json
@@ -1,40 +1,4 @@
{
- "__inputs": [
- {
- "name": "DS_SMART_REMOTE",
- "label": "smart_remote",
- "description": "",
- "type": "datasource",
- "pluginId": "influxdb",
- "pluginName": "InfluxDB"
- }
- ],
- "__requires": [
- {
- "type": "grafana",
- "id": "grafana",
- "name": "Grafana",
- "version": "5.1.3"
- },
- {
- "type": "panel",
- "id": "graph",
- "name": "Graph",
- "version": "5.0.0"
- },
- {
- "type": "datasource",
- "id": "influxdb",
- "name": "InfluxDB",
- "version": "5.0.0"
- },
- {
- "type": "panel",
- "id": "singlestat",
- "name": "Singlestat",
- "version": "5.0.0"
- }
- ],
"annotations": {
"list": [
{
@@ -51,7 +15,7 @@
"editable": true,
"gnetId": null,
"graphTooltip": 0,
- "id": null,
+ "id": 1,
"links": [],
"panels": [
{
@@ -59,7 +23,8 @@
"bars": false,
"dashLength": 10,
"dashes": false,
- "datasource": "${DS_SMART_REMOTE}",
+ "datasource": "smart_remote",
+ "decimals": 2,
"fill": 1,
"gridPos": {
"h": 9,
@@ -76,7 +41,7 @@
"hideZero": false,
"max": false,
"min": false,
- "rightSide": true,
+ "rightSide": false,
"show": true,
"total": false,
"values": true
@@ -85,6 +50,7 @@
"linewidth": 1,
"links": [],
"nullPointMode": "connected",
+ "options": {},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -95,54 +61,11 @@
"steppedLine": false,
"targets": [
{
- "alias": "My room",
- "groupBy": [
- {
- "params": [
- "1m"
- ],
- "type": "time"
- },
- {
- "params": [
- "null"
- ],
- "type": "fill"
- }
- ],
- "measurement": "weather",
- "orderByTime": "ASC",
- "policy": "default",
- "refId": "A",
- "resultFormat": "time_series",
- "select": [
- [
- {
- "params": [
- "humiValue"
- ],
- "type": "field"
- },
- {
- "params": [],
- "type": "mean"
- }
- ]
- ],
- "tags": [
- {
- "key": "id",
- "operator": "=",
- "value": "station_1"
- }
- ]
- },
- {
- "alias": "Living",
+ "alias": "Outside",
"groupBy": [
{
"params": [
- "1m"
+ "5m"
],
"type": "time"
},
@@ -156,7 +79,7 @@
"measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "B",
+ "refId": "D",
"resultFormat": "time_series",
"select": [
[
@@ -174,18 +97,18 @@
],
"tags": [
{
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "station_2"
+ "value": "48"
}
]
},
{
- "alias": "Outside",
+ "alias": "Hall",
"groupBy": [
{
"params": [
- "1m"
+ "5m"
],
"type": "time"
},
@@ -199,7 +122,7 @@
"measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "C",
+ "refId": "A",
"resultFormat": "time_series",
"select": [
[
@@ -217,18 +140,18 @@
],
"tags": [
{
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "station_outside"
+ "value": "49"
}
]
},
{
- "alias": "Living arduino",
+ "alias": "Living top",
"groupBy": [
{
"params": [
- "1m"
+ "5m"
],
"type": "time"
},
@@ -242,7 +165,7 @@
"measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "D",
+ "refId": "B",
"resultFormat": "time_series",
"select": [
[
@@ -260,21 +183,16 @@
],
"tags": [
{
- "key": "type",
+ "key": "radio_pipe",
"operator": "=",
- "value": "arduino"
- },
- {
- "condition": "AND",
- "key": "id",
- "operator": "=",
- "value": "0xAABBCCDD44"
+ "value": "50"
}
]
}
],
"thresholds": [],
"timeFrom": null,
+ "timeRegions": [],
"timeShift": null,
"title": "Humidity",
"tooltip": {
@@ -319,7 +237,8 @@
"bars": false,
"dashLength": 10,
"dashes": false,
- "datasource": "${DS_SMART_REMOTE}",
+ "datasource": "smart_remote",
+ "decimals": 2,
"fill": 1,
"gridPos": {
"h": 9,
@@ -334,7 +253,7 @@
"current": true,
"max": false,
"min": false,
- "rightSide": true,
+ "rightSide": false,
"show": true,
"total": false,
"values": true
@@ -343,6 +262,7 @@
"linewidth": 1,
"links": [],
"nullPointMode": "connected",
+ "options": {},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -353,11 +273,11 @@
"steppedLine": false,
"targets": [
{
- "alias": "My room",
+ "alias": "Outside",
"groupBy": [
{
"params": [
- "1m"
+ "5m"
],
"type": "time"
},
@@ -371,7 +291,7 @@
"measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "A",
+ "refId": "D",
"resultFormat": "time_series",
"select": [
[
@@ -389,18 +309,18 @@
],
"tags": [
{
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "station_1"
+ "value": "48"
}
]
},
{
- "alias": "Living",
+ "alias": "Hall",
"groupBy": [
{
"params": [
- "1m"
+ "5m"
],
"type": "time"
},
@@ -414,7 +334,7 @@
"measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "B",
+ "refId": "A",
"resultFormat": "time_series",
"select": [
[
@@ -432,18 +352,18 @@
],
"tags": [
{
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "station_2"
+ "value": "49"
}
]
},
{
- "alias": "Outside",
+ "alias": "Living top",
"groupBy": [
{
"params": [
- "1m"
+ "5m"
],
"type": "time"
},
@@ -457,7 +377,7 @@
"measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "C",
+ "refId": "B",
"resultFormat": "time_series",
"select": [
[
@@ -475,18 +395,101 @@
],
"tags": [
{
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "station_outside"
+ "value": "50"
}
]
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeRegions": [],
+ "timeShift": null,
+ "title": "Temperature",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 1,
+ "format": "celsius",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
},
{
- "alias": "Living arduino",
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "smart_remote",
+ "decimals": 2,
+ "fill": 1,
+ "gridPos": {
+ "h": 9,
+ "w": 6,
+ "x": 0,
+ "y": 9
+ },
+ "id": 12,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": false,
+ "max": true,
+ "min": true,
+ "rightSide": false,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "connected",
+ "options": {},
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "alias": "Hall",
"groupBy": [
{
"params": [
- "1m"
+ "5m"
],
"type": "time"
},
@@ -500,13 +503,13 @@
"measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "D",
+ "refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
- "tempValue"
+ "presValue"
],
"type": "field"
},
@@ -518,23 +521,61 @@
],
"tags": [
{
- "key": "type",
+ "key": "radio_pipe",
"operator": "=",
- "value": "arduino"
+ "value": "49"
+ }
+ ]
+ },
+ {
+ "alias": "Outside",
+ "groupBy": [
+ {
+ "params": [
+ "5m"
+ ],
+ "type": "time"
},
{
- "condition": "AND",
- "key": "id",
+ "params": [
+ "null"
+ ],
+ "type": "fill"
+ }
+ ],
+ "measurement": "weather",
+ "orderByTime": "ASC",
+ "policy": "default",
+ "refId": "B",
+ "resultFormat": "time_series",
+ "select": [
+ [
+ {
+ "params": [
+ "presValue"
+ ],
+ "type": "field"
+ },
+ {
+ "params": [],
+ "type": "mean"
+ }
+ ]
+ ],
+ "tags": [
+ {
+ "key": "radio_pipe",
"operator": "=",
- "value": "0xAABBCCDD44"
+ "value": "50"
}
]
}
],
"thresholds": [],
"timeFrom": null,
+ "timeRegions": [],
"timeShift": null,
- "title": "Temperature",
+ "title": "Pressure",
"tooltip": {
"shared": true,
"sort": 0,
@@ -550,8 +591,8 @@
},
"yaxes": [
{
- "decimals": 1,
- "format": "celsius",
+ "decimals": 2,
+ "format": "pressurehpa",
"label": null,
"logBase": 1,
"max": null,
@@ -559,7 +600,8 @@
"show": true
},
{
- "format": "short",
+ "decimals": null,
+ "format": "none",
"label": null,
"logBase": 1,
"max": null,
@@ -577,12 +619,13 @@
"bars": false,
"dashLength": 10,
"dashes": false,
- "datasource": "${DS_SMART_REMOTE}",
+ "datasource": "smart_remote",
+ "decimals": 2,
"fill": 1,
"gridPos": {
"h": 9,
- "w": 12,
- "x": 0,
+ "w": 6,
+ "x": 6,
"y": 9
},
"id": 8,
@@ -592,7 +635,7 @@
"current": true,
"max": false,
"min": false,
- "rightSide": true,
+ "rightSide": false,
"show": true,
"total": false,
"values": true
@@ -601,6 +644,7 @@
"linewidth": 1,
"links": [],
"nullPointMode": "connected",
+ "options": {},
"percentage": false,
"pointradius": 5,
"points": false,
@@ -611,11 +655,11 @@
"steppedLine": false,
"targets": [
{
- "alias": "Battery outside",
+ "alias": "Outside",
"groupBy": [
{
"params": [
- "5m"
+ "10m"
],
"type": "time"
},
@@ -626,10 +670,10 @@
"type": "fill"
}
],
- "measurement": "battery",
+ "measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "A",
+ "refId": "B",
"resultFormat": "time_series",
"select": [
[
@@ -647,18 +691,18 @@
],
"tags": [
{
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "station_outside"
+ "value": "49"
}
]
},
{
- "alias": "Battery living",
+ "alias": "Hall",
"groupBy": [
{
"params": [
- "5m"
+ "10m"
],
"type": "time"
},
@@ -672,7 +716,7 @@
"measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
- "refId": "B",
+ "refId": "A",
"resultFormat": "time_series",
"select": [
[
@@ -690,21 +734,16 @@
],
"tags": [
{
- "key": "type",
- "operator": "=",
- "value": "arduino"
- },
- {
- "condition": "AND",
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "0xAABBCCDD44"
+ "value": "50"
}
]
}
],
"thresholds": [],
"timeFrom": null,
+ "timeRegions": [],
"timeShift": null,
"title": "Batteries",
"tooltip": {
@@ -753,7 +792,7 @@
"rgba(237, 129, 40, 0.89)",
"#299c46"
],
- "datasource": "${DS_SMART_REMOTE}",
+ "datasource": "smart_remote",
"decimals": 2,
"format": "none",
"gauge": {
@@ -786,6 +825,7 @@
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
+ "options": {},
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
@@ -821,7 +861,7 @@
"type": "fill"
}
],
- "measurement": "battery",
+ "measurement": "weather",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
@@ -842,9 +882,9 @@
],
"tags": [
{
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "station_outside"
+ "value": "50"
}
]
}
@@ -872,7 +912,7 @@
"rgba(237, 129, 40, 0.89)",
"#299c46"
],
- "datasource": "${DS_SMART_REMOTE}",
+ "datasource": "smart_remote",
"decimals": 2,
"format": "none",
"gauge": {
@@ -905,6 +945,7 @@
"maxDataPoints": 100,
"nullPointMode": "connected",
"nullText": null,
+ "options": {},
"postfix": "",
"postfixFontSize": "50%",
"prefix": "",
@@ -928,7 +969,7 @@
"groupBy": [
{
"params": [
- "2m"
+ "1m"
],
"type": "time"
},
@@ -960,22 +1001,16 @@
],
"tags": [
{
- "key": "type",
- "operator": "=",
- "value": "arduino"
- },
- {
- "condition": "AND",
- "key": "id",
+ "key": "radio_pipe",
"operator": "=",
- "value": "0xAABBCCDD44"
+ "value": "49"
}
]
}
],
"thresholds": "2.5,3,4.2",
"timeFrom": null,
- "title": "Battery living",
+ "title": "Battery hall",
"type": "singlestat",
"valueFontSize": "80%",
"valueMaps": [
@@ -989,14 +1024,14 @@
}
],
"refresh": "10s",
- "schemaVersion": 16,
+ "schemaVersion": 18,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
- "from": "now-6h",
+ "from": "now-24h",
"to": "now"
},
"timepicker": {
@@ -1027,5 +1062,5 @@
"timezone": "",
"title": "weather",
"uid": "nCkI-iigz",
- "version": 3
+ "version": 2
}
diff --git a/gulpfile.js b/gulpfile.js
deleted file mode 100755
index 617515a..0000000
--- a/gulpfile.js
+++ /dev/null
@@ -1,125 +0,0 @@
-'use strict';
-
-var gulp = require('gulp'),
- sass = require('gulp-sass'),
- logger = require('gulp-logger'),
- watch = require('gulp-watch'),
- prefixer = require('gulp-autoprefixer'),
- uglify = require('gulp-uglify'),
- rigger = require('gulp-rigger'),
- cssmin = require('gulp-minify-css'),
- rename = require('gulp-rename'),
- plumber = require('gulp-plumber'),
- livereload = require('gulp-livereload');
-
-var livereload_opt = {
- host: '0.0.0.0',
- port: 35729
-}
-
-var path = {
- build: {
- js: 'app/static/js',
- css: 'app/static/css/',
- fonts: 'app/static/fonts/'
- },
- src: {
- js: 'src/js/*.js',
- style: 'src/scss/*.scss',
- awesomeFonts: 'bower_components/components-font-awesome/fonts/**/*.*'
- },
- watch: {
- js: 'src/js/**/*.js',
- style: 'src/scss/**/*.scss',
- awesomeFonts: 'bower_components/components-font-awesome/fonts/**/*.*'
- }
-};
-
-gulp.task('js:build', function () {
- gulp.src(path.src.js)
- .pipe(plumber())
- .pipe(logger({
- before: 'Start JS concatination',
- after: 'JS concatination complete!',
- extname: '.js',
- showChange: true
- }))
- .pipe(rigger())
- .pipe(logger({
- before: 'Start JS compress',
- after: 'JS compress complete!',
- extname: '.js',
- showChange: true
- }))
- // .pipe(uglify()) // comment for the best speed
- .pipe(rename({
- suffix: '.min'
- }))
- .pipe(gulp.dest(path.build.js))
- .pipe(livereload());
-});
-
-gulp.task('style:build', function () {
- // Load path with sass files
- gulp.src(path.src.style)
- .pipe(plumber())
- .pipe(logger({
- before: '[STYLE] Start SASS comppile',
- after: '[STYLE] SASS comppile complete!',
- extname: '.css',
- showChange: true
- }))
- .pipe(sass())
- // Add vendor prefix
- .pipe(logger({
- before: '[STYLE] Start add vendor prefix',
- after: '[STYLE] Vendor prefix complete!',
- extname: '.css',
- showChange: true
- }))
- .pipe(prefixer())
- .pipe(logger({
- before: '[STYLE] Start minification',
- after: '[STYLE] Minification complete!',
- extname: '.css',
- showChange: true
- }))
- .pipe(cssmin())
- .pipe(rename({
- suffix: '.min'
- }))
- .pipe(gulp.dest(path.build.css))
- .pipe(livereload());
-});
-
-gulp.task('awesomeFonts:build', function() {
- gulp.src(path.src.awesomeFonts)
- .pipe(plumber())
- .pipe(logger({
- before: '[FONTS] Start FontsAwesome',
- after: '[FONTS] FontsAwesome complete!',
- showChange: true
- }))
- .pipe(gulp.dest(path.build.fonts))
-});
-
-gulp.task('build', [
- 'js:build',
- 'style:build',
- 'awesomeFonts:build',
-]);
-
-gulp.task('watch', function(){
- livereload.listen(livereload_opt);
- watch([path.watch.style], { usePolling: true }, function(event, cb) {
- gulp.start('style:build');
- });
- watch([path.watch.js], { usePolling: true }, function(event, cb) {
- gulp.start('js:build');
- });
- watch([path.watch.awesomeFonts], function(event, cb) {
- gulp.start('awesomeFonts:build');
- });
-});
-
-gulp.task('default', ['build', 'watch']);
diff --git a/lirc/hardware.conf b/lirc/hardware.conf
old mode 100644
new mode 100755
diff --git a/lirc/lirc_options.conf b/lirc/lirc_options.conf
old mode 100644
new mode 100755
diff --git a/migrations/README b/migrations/README
new file mode 100755
index 0000000..98e4f9c
--- /dev/null
+++ b/migrations/README
@@ -0,0 +1 @@
+Generic single-database configuration.
\ No newline at end of file
diff --git a/migrations/alembic.ini b/migrations/alembic.ini
new file mode 100755
index 0000000..f8ed480
--- /dev/null
+++ b/migrations/alembic.ini
@@ -0,0 +1,45 @@
+# A generic, single database configuration.
+
+[alembic]
+# template used to generate migration files
+# file_template = %%(rev)s_%%(slug)s
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S
diff --git a/migrations/env.py b/migrations/env.py
new file mode 100755
index 0000000..23663ff
--- /dev/null
+++ b/migrations/env.py
@@ -0,0 +1,87 @@
+from __future__ import with_statement
+from alembic import context
+from sqlalchemy import engine_from_config, pool
+from logging.config import fileConfig
+import logging
+
+# this is the Alembic Config object, which provides
+# access to the values within the .ini file in use.
+config = context.config
+
+# Interpret the config file for Python logging.
+# This line sets up loggers basically.
+fileConfig(config.config_file_name)
+logger = logging.getLogger('alembic.env')
+
+# add your model's MetaData object here
+# for 'autogenerate' support
+# from myapp import mymodel
+# target_metadata = mymodel.Base.metadata
+from flask import current_app
+config.set_main_option('sqlalchemy.url',
+ current_app.config.get('SQLALCHEMY_DATABASE_URI'))
+target_metadata = current_app.extensions['migrate'].db.metadata
+
+# other values from the config, defined by the needs of env.py,
+# can be acquired:
+# my_important_option = config.get_main_option("my_important_option")
+# ... etc.
+
+
+def run_migrations_offline():
+ """Run migrations in 'offline' mode.
+
+ This configures the context with just a URL
+ and not an Engine, though an Engine is acceptable
+ here as well. By skipping the Engine creation
+ we don't even need a DBAPI to be available.
+
+ Calls to context.execute() here emit the given string to the
+ script output.
+
+ """
+ url = config.get_main_option("sqlalchemy.url")
+ context.configure(url=url)
+
+ with context.begin_transaction():
+ context.run_migrations()
+
+
+def run_migrations_online():
+ """Run migrations in 'online' mode.
+
+ In this scenario we need to create an Engine
+ and associate a connection with the context.
+
+ """
+
+ # this callback is used to prevent an auto-migration from being generated
+ # when there are no changes to the schema
+ # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
+ def process_revision_directives(context, revision, directives):
+ if getattr(config.cmd_opts, 'autogenerate', False):
+ script = directives[0]
+ if script.upgrade_ops.is_empty():
+ directives[:] = []
+ logger.info('No changes in schema detected.')
+
+ engine = engine_from_config(config.get_section(config.config_ini_section),
+ prefix='sqlalchemy.',
+ poolclass=pool.NullPool)
+
+ connection = engine.connect()
+ context.configure(connection=connection,
+ target_metadata=target_metadata,
+ process_revision_directives=process_revision_directives,
+ **current_app.extensions['migrate'].configure_args)
+
+ try:
+ with context.begin_transaction():
+ context.run_migrations()
+ finally:
+ connection.close()
+
+if context.is_offline_mode():
+ run_migrations_offline()
+else:
+ run_migrations_online()
diff --git a/migrations/script.py.mako b/migrations/script.py.mako
new file mode 100755
index 0000000..2c01563
--- /dev/null
+++ b/migrations/script.py.mako
@@ -0,0 +1,24 @@
+"""${message}
+
+Revision ID: ${up_revision}
+Revises: ${down_revision | comma,n}
+Create Date: ${create_date}
+
+"""
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
+
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+branch_labels = ${repr(branch_labels)}
+depends_on = ${repr(depends_on)}
+
+
+def upgrade():
+ ${upgrades if upgrades else "pass"}
+
+
+def downgrade():
+ ${downgrades if downgrades else "pass"}
diff --git a/migrations/versions/001_.py b/migrations/versions/001_.py
new file mode 100755
index 0000000..fd1c193
--- /dev/null
+++ b/migrations/versions/001_.py
@@ -0,0 +1,97 @@
+"""empty message
+
+Revision ID: 001
+Revises:
+Create Date: 2019-04-04 12:32:11.992577
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '001'
+down_revision = None
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.create_table('node',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('name', sa.String(length=50), nullable=True),
+ sa.Column('host_name', sa.String(length=100), nullable=True),
+ sa.Column('order', sa.Integer(), nullable=True),
+ sa.Column('timestamp', sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('rc',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('name', sa.String(length=50), nullable=True),
+ sa.Column('public', sa.Boolean(), nullable=True),
+ sa.Column('order', sa.Integer(), nullable=True),
+ sa.Column('icon', sa.String(length=200), nullable=True),
+ sa.Column('timestamp', sa.DateTime(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('user',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('username', sa.String(length=50), nullable=True),
+ sa.Column('password', sa.String(length=255), nullable=True),
+ sa.Column('role', sa.SmallInteger(), nullable=True),
+ sa.Column('email', sa.String(length=190), nullable=True),
+ sa.PrimaryKeyConstraint('id'),
+ sa.UniqueConstraint('email'),
+ sa.UniqueConstraint('username')
+ )
+ op.create_table('arduino',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('node_id', sa.Integer(), nullable=True),
+ sa.Column('usb', sa.String(length=20), nullable=True),
+ sa.Column('name', sa.String(length=50), nullable=True),
+ sa.Column('order', sa.Integer(), nullable=True),
+ sa.Column('timestamp', sa.DateTime(), nullable=True),
+ sa.ForeignKeyConstraint(['node_id'], ['node.id'], ),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('button',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('rc_id', sa.Integer(), nullable=True),
+ sa.Column('radio_id', sa.Integer(), nullable=True),
+ sa.Column('name', sa.String(length=50), nullable=True),
+ sa.Column('order_hor', sa.Integer(), nullable=True),
+ sa.Column('order_ver', sa.Integer(), nullable=True),
+ sa.Column('color', sa.String(length=10), nullable=True),
+ sa.Column('type', sa.String(length=20), nullable=True),
+ sa.Column('message', sa.Text(), nullable=True),
+ sa.Column('timestamp', sa.DateTime(), nullable=True),
+ sa.ForeignKeyConstraint(['rc_id'], ['rc.id'], ),
+ sa.PrimaryKeyConstraint('id')
+ )
+ op.create_table('radio',
+ sa.Column('id', sa.Integer(), nullable=False),
+ sa.Column('arduino_id', sa.Integer(), nullable=True),
+ sa.Column('pipe', sa.String(length=12), nullable=True),
+ sa.Column('type', sa.String(length=20), nullable=True),
+ sa.Column('name', sa.String(length=50), nullable=True),
+ sa.Column('enabled', sa.Boolean(), nullable=True),
+ sa.Column('order', sa.Integer(), nullable=True),
+ sa.Column('on_request', sa.Boolean(), nullable=False),
+ sa.Column('expired_after', sa.Integer(), nullable=True),
+ sa.Column('timestamp', sa.DateTime(), nullable=True),
+ sa.ForeignKeyConstraint(['arduino_id'], ['arduino.id'], ),
+ sa.PrimaryKeyConstraint('id')
+ )
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_table('radio')
+ op.drop_table('button')
+ op.drop_table('arduino')
+ op.drop_table('user')
+ op.drop_table('rc')
+ op.drop_table('node')
+ # ### end Alembic commands ###
diff --git a/node-red/Dockerfile_rpi b/node-red/Dockerfile_rpi
old mode 100644
new mode 100755
diff --git a/node-red/smart_remote.json b/node-red/smart_remote.json
old mode 100755
new mode 100644
index 5866d30..124c32d
--- a/node-red/smart_remote.json
+++ b/node-red/smart_remote.json
@@ -1,360 +1 @@
-[
- {
- "id": "4d7ebdf8.2a3754",
- "type": "tab",
- "label": "Flow 1",
- "disabled": false,
- "info": ""
- },
- {
- "id": "c6b6c023.f4883",
- "type": "mqtt in",
- "z": "4d7ebdf8.2a3754",
- "name": "weather",
- "topic": "/weather",
- "qos": "2",
- "broker": "a54d4a26.ae4528",
- "x": 150,
- "y": 100,
- "wires": [
- [
- "f6e25327.6272b",
- "372f33d7.c9eb9c"
- ]
- ]
- },
- {
- "id": "71fffe61.a00fa",
- "type": "influxdb out",
- "z": "4d7ebdf8.2a3754",
- "influxdb": "f92a7551.0003e8",
- "name": "weather",
- "measurement": "weather",
- "precision": "",
- "retentionPolicy": "",
- "x": 560,
- "y": 100,
- "wires": []
- },
- {
- "id": "f6e25327.6272b",
- "type": "json",
- "z": "4d7ebdf8.2a3754",
- "name": "dht22",
- "property": "payload",
- "action": "obj",
- "pretty": false,
- "x": 350,
- "y": 100,
- "wires": [
- [
- "3b6a6a60.36d486",
- "71fffe61.a00fa"
- ]
- ]
- },
- {
- "id": "3b6a6a60.36d486",
- "type": "debug",
- "z": "4d7ebdf8.2a3754",
- "name": "dht object",
- "active": false,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "payload",
- "x": 560,
- "y": 160,
- "wires": []
- },
- {
- "id": "372f33d7.c9eb9c",
- "type": "debug",
- "z": "4d7ebdf8.2a3754",
- "name": "dht22 json",
- "active": false,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "payload",
- "x": 370,
- "y": 180,
- "wires": []
- },
- {
- "id": "91ea878f.888018",
- "type": "mqtt in",
- "z": "4d7ebdf8.2a3754",
- "name": "offline",
- "topic": "/offline",
- "qos": "2",
- "broker": "a54d4a26.ae4528",
- "x": 150,
- "y": 500,
- "wires": [
- [
- "ba35b295.fc0c"
- ]
- ]
- },
- {
- "id": "ba35b295.fc0c",
- "type": "debug",
- "z": "4d7ebdf8.2a3754",
- "name": "mosquitto offline",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "payload",
- "x": 380,
- "y": 500,
- "wires": []
- },
- {
- "id": "a676c8ef.632878",
- "type": "mqtt in",
- "z": "4d7ebdf8.2a3754",
- "name": "battery",
- "topic": "/battery",
- "qos": "2",
- "broker": "a54d4a26.ae4528",
- "x": 150,
- "y": 300,
- "wires": [
- [
- "4a8f9403.1c311c",
- "15ea2526.290fcb"
- ]
- ]
- },
- {
- "id": "15ea2526.290fcb",
- "type": "debug",
- "z": "4d7ebdf8.2a3754",
- "name": "battery json",
- "active": false,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "payload",
- "x": 370,
- "y": 380,
- "wires": []
- },
- {
- "id": "4a8f9403.1c311c",
- "type": "json",
- "z": "4d7ebdf8.2a3754",
- "name": "battery",
- "property": "payload",
- "action": "obj",
- "pretty": false,
- "x": 350,
- "y": 300,
- "wires": [
- [
- "80626e45.da981",
- "db8e28bf.af9c38"
- ]
- ]
- },
- {
- "id": "80626e45.da981",
- "type": "influxdb out",
- "z": "4d7ebdf8.2a3754",
- "influxdb": "f92a7551.0003e8",
- "name": "battery",
- "measurement": "battery",
- "precision": "",
- "retentionPolicy": "",
- "x": 550,
- "y": 300,
- "wires": []
- },
- {
- "id": "db8e28bf.af9c38",
- "type": "debug",
- "z": "4d7ebdf8.2a3754",
- "name": "battery object",
- "active": false,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "payload",
- "x": 580,
- "y": 380,
- "wires": []
- },
- {
- "id": "89a837a9.4816a8",
- "type": "comment",
- "z": "4d7ebdf8.2a3754",
- "name": "Convert json to js object",
- "info": "",
- "x": 360,
- "y": 60,
- "wires": []
- },
- {
- "id": "55ec4b0.fcebfb4",
- "type": "comment",
- "z": "4d7ebdf8.2a3754",
- "name": "Convert json to js object",
- "info": "",
- "x": 360,
- "y": 260,
- "wires": []
- },
- {
- "id": "88f49603.e586c8",
- "type": "comment",
- "z": "4d7ebdf8.2a3754",
- "name": "If sensor is offline just write it in debug window",
- "info": "",
- "x": 290,
- "y": 460,
- "wires": []
- },
- {
- "id": "23a78b39.9b8464",
- "type": "tcp in",
- "z": "4d7ebdf8.2a3754",
- "name": "arduino:9090",
- "server": "server",
- "host": "",
- "port": "9090",
- "datamode": "stream",
- "datatype": "utf8",
- "newline": "",
- "topic": "/weather",
- "base64": false,
- "x": 170,
- "y": 600,
- "wires": [
- [
- "9ea17c68.addc5"
- ]
- ]
- },
- {
- "id": "9ea17c68.addc5",
- "type": "json",
- "z": "4d7ebdf8.2a3754",
- "name": "arduino",
- "property": "payload",
- "action": "obj",
- "pretty": false,
- "x": 360,
- "y": 600,
- "wires": [
- [
- "e12812d.6f807f",
- "abe1024a.f45a1"
- ]
- ]
- },
- {
- "id": "3d0b697d.755946",
- "type": "influxdb out",
- "z": "4d7ebdf8.2a3754",
- "influxdb": "f92a7551.0003e8",
- "name": "arduino weather",
- "measurement": "weather",
- "precision": "",
- "retentionPolicy": "",
- "x": 820,
- "y": 640,
- "wires": []
- },
- {
- "id": "e12812d.6f807f",
- "type": "switch",
- "z": "4d7ebdf8.2a3754",
- "name": "if offline",
- "property": "payload.status",
- "propertyType": "msg",
- "rules": [
- {
- "t": "eq",
- "v": "offline",
- "vt": "str"
- },
- {
- "t": "else"
- }
- ],
- "checkall": "false",
- "repair": false,
- "outputs": 2,
- "x": 580,
- "y": 600,
- "wires": [
- [
- "c2406839.0cbf98"
- ],
- [
- "3d0b697d.755946"
- ]
- ]
- },
- {
- "id": "abe1024a.f45a1",
- "type": "debug",
- "z": "4d7ebdf8.2a3754",
- "name": "arduino input",
- "active": false,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "payload",
- "x": 590,
- "y": 680,
- "wires": []
- },
- {
- "id": "c2406839.0cbf98",
- "type": "debug",
- "z": "4d7ebdf8.2a3754",
- "name": "arduino offlime",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "payload",
- "x": 820,
- "y": 560,
- "wires": []
- },
- {
- "id": "a54d4a26.ae4528",
- "type": "mqtt-broker",
- "z": "",
- "name": "mosquitto",
- "broker": "mosquitto",
- "port": "1883",
- "clientid": "node_red",
- "usetls": false,
- "compatmode": true,
- "keepalive": "60",
- "cleansession": false,
- "willTopic": "",
- "willQos": "0",
- "willPayload": "",
- "birthTopic": "",
- "birthQos": "0",
- "birthPayload": ""
- },
- {
- "id": "f92a7551.0003e8",
- "type": "influxdb",
- "z": "",
- "hostname": "influxdb",
- "port": "8086",
- "protocol": "http",
- "database": "smart_remote",
- "name": "",
- "usetls": false,
- "tls": ""
- }
-]
+[{"id":"4d7ebdf8.2a3754","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"a54d4a26.ae4528","type":"mqtt-broker","z":"","name":"mosquitto","broker":"mosquitto","port":"1883","clientid":"node_red","usetls":false,"compatmode":true,"keepalive":"60","cleansession":false,"birthTopic":"","birthQos":"0","birthPayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"f92a7551.0003e8","type":"influxdb","z":"","hostname":"influxdb","port":"8086","protocol":"http","database":"smart_remote","name":"","usetls":false,"tls":""},{"id":"c6b6c023.f4883","type":"mqtt in","z":"4d7ebdf8.2a3754","name":"weather","topic":"/weather","qos":"2","broker":"a54d4a26.ae4528","x":150,"y":100,"wires":[["f6e25327.6272b","372f33d7.c9eb9c"]]},{"id":"71fffe61.a00fa","type":"influxdb out","z":"4d7ebdf8.2a3754","influxdb":"f92a7551.0003e8","name":"weather","measurement":"weather","precision":"","retentionPolicy":"","x":560,"y":100,"wires":[]},{"id":"f6e25327.6272b","type":"json","z":"4d7ebdf8.2a3754","name":"dht22","property":"payload","action":"obj","pretty":false,"x":350,"y":100,"wires":[["3b6a6a60.36d486","71fffe61.a00fa"]]},{"id":"3b6a6a60.36d486","type":"debug","z":"4d7ebdf8.2a3754","name":"dht object","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":560,"y":160,"wires":[]},{"id":"372f33d7.c9eb9c","type":"debug","z":"4d7ebdf8.2a3754","name":"dht22 json","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":370,"y":180,"wires":[]},{"id":"91ea878f.888018","type":"mqtt in","z":"4d7ebdf8.2a3754","name":"offline","topic":"/offline","qos":"2","broker":"a54d4a26.ae4528","x":150,"y":500,"wires":[["ba35b295.fc0c"]]},{"id":"ba35b295.fc0c","type":"debug","z":"4d7ebdf8.2a3754","name":"mosquitto offline","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":380,"y":500,"wires":[]},{"id":"a676c8ef.632878","type":"mqtt in","z":"4d7ebdf8.2a3754","name":"battery","topic":"/battery","qos":"2","broker":"a54d4a26.ae4528","x":150,"y":300,"wires":[["4a8f9403.1c311c","15ea2526.290fcb"]]},{"id":"15ea2526.290fcb","type":"debug","z":"4d7ebdf8.2a3754","name":"battery json","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":370,"y":380,"wires":[]},{"id":"4a8f9403.1c311c","type":"json","z":"4d7ebdf8.2a3754","name":"battery","property":"payload","action":"obj","pretty":false,"x":350,"y":300,"wires":[["80626e45.da981","db8e28bf.af9c38"]]},{"id":"80626e45.da981","type":"influxdb out","z":"4d7ebdf8.2a3754","influxdb":"f92a7551.0003e8","name":"battery","measurement":"battery","precision":"","retentionPolicy":"","x":550,"y":300,"wires":[]},{"id":"db8e28bf.af9c38","type":"debug","z":"4d7ebdf8.2a3754","name":"battery object","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":580,"y":380,"wires":[]},{"id":"89a837a9.4816a8","type":"comment","z":"4d7ebdf8.2a3754","name":"Convert json to js object","info":"","x":360,"y":60,"wires":[]},{"id":"55ec4b0.fcebfb4","type":"comment","z":"4d7ebdf8.2a3754","name":"Convert json to js object","info":"","x":360,"y":260,"wires":[]},{"id":"88f49603.e586c8","type":"comment","z":"4d7ebdf8.2a3754","name":"If sensor is offline just write it in debug window","info":"","x":290,"y":460,"wires":[]},{"id":"23a78b39.9b8464","type":"tcp in","z":"4d7ebdf8.2a3754","name":"arduino:9090","server":"server","host":"","port":"9090","datamode":"stream","datatype":"utf8","newline":"","topic":"/weather","base64":false,"x":170,"y":600,"wires":[["9ea17c68.addc5"]]},{"id":"9ea17c68.addc5","type":"json","z":"4d7ebdf8.2a3754","name":"arduino","property":"payload","action":"obj","pretty":false,"x":360,"y":600,"wires":[["e12812d.6f807f","abe1024a.f45a1"]]},{"id":"3d0b697d.755946","type":"influxdb out","z":"4d7ebdf8.2a3754","influxdb":"f92a7551.0003e8","name":"arduino weather","measurement":"weather","precision":"","retentionPolicy":"","x":820,"y":640,"wires":[]},{"id":"e12812d.6f807f","type":"switch","z":"4d7ebdf8.2a3754","name":"if offline","property":"payload.status","propertyType":"msg","rules":[{"t":"eq","v":"offline","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":580,"y":600,"wires":[["c2406839.0cbf98"],["3d0b697d.755946"]]},{"id":"abe1024a.f45a1","type":"debug","z":"4d7ebdf8.2a3754","name":"arduino input","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":590,"y":680,"wires":[]},{"id":"c2406839.0cbf98","type":"debug","z":"4d7ebdf8.2a3754","name":"arduino offlime","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":820,"y":560,"wires":[]}]
\ No newline at end of file
diff --git a/package.json b/package.json
deleted file mode 100755
index f452f11..0000000
--- a/package.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "name": "raspberry",
- "description": "raspberry",
- "version": "1.0.0",
- "license": "MIT",
- "private": true,
- "repository": {
- "type": "git",
- "url": "git@github.com:notfoundsam/raspberry.git"
- },
- "devDependencies": {
- "framework7": "^2.2.5",
- "gulp": "^3.9.1",
- "gulp-autoprefixer": "^3.1.1",
- "gulp-livereload": "^3.8.1",
- "gulp-logger": "0.0.2",
- "gulp-minify-css": "^1.2.4",
- "gulp-plumber": "^1.1.0",
- "gulp-rename": "^1.2.2",
- "gulp-rigger": "^0.5.8",
- "gulp-sass": "^3.1.0",
- "gulp-uglify": "^2.0.1",
- "gulp-watch": "^4.3.11"
- }
-}
diff --git a/requirements.txt b/requirements.txt
index 3edfb55..03f4580 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,25 +1,26 @@
-certifi==2018.1.18
-chardet==3.0.4
-click==6.7
-decorator==4.1.2
-Flask==0.12.2
-Flask-Login==0.4.0
-Flask-SocketIO==2.9.2
-Flask-SQLAlchemy==2.3.1
-idna==2.6
-itsdangerous==0.24
-Jinja2==2.9.6
-MarkupSafe==1.0
-pbr==3.1.1
-pyserial==3.4
-python-engineio==1.7.0
-python-socketio==1.8.1
-requests==2.18.4
-six==1.11.0
-SQLAlchemy==1.1.14
-sqlalchemy-migrate==0.11.0
-sqlparse==0.2.4
-Tempita==0.5.2
-urllib3==1.22
-virtualenv==15.1.0
-Werkzeug==0.12.2
+alembic==1.0.0
+certifi==2018.10.15
+chardet==3.0.4
+Click==7.0
+Flask==1.0.2
+Flask-Cors==3.0.6
+Flask-Login==0.4.1
+Flask-Migrate==2.2.1
+Flask-SocketIO==3.0.2
+Flask-SQLAlchemy==2.4.0
+idna==2.7
+itsdangerous==0.24
+Jinja2==2.10
+Mako==1.0.7
+MarkupSafe==1.0
+mysql-connector==2.2.9
+pyserial==3.4
+python-dateutil==2.7.3
+python-editor==1.0.3
+python-engineio==2.3.2
+python-socketio==2.0.0
+requests==2.20.0
+six==1.11.0
+SQLAlchemy==1.3.3
+urllib3==1.23
+Werkzeug==0.14.1
diff --git a/run.py b/run.py
index 8d2c834..431f9f1 100755
--- a/run.py
+++ b/run.py
@@ -1,29 +1,12 @@
-#!/usr/bin/env python
-from __future__ import print_function
+#!/usr/bin/env python3
import os, sys
-from app.drivers.arduino import Arduino
-from app.drivers.lirc import Lirc, LircDev
+from app.bootstrap import FirstRequest
+# from app.drivers.lirc import Lirc, LircDev
+from app import flask_app
-if 'APP_ENV' in os.environ and os.environ['APP_ENV'] == 'development':
- debug = True
-else:
- debug = False
+if __name__ == '__main__':
+ first_request = FirstRequest()
+ first_request.start()
-arduino = Arduino.Instance()
-lirc = None
-
-if not debug or os.environ.get("WERKZEUG_RUN_MAIN") == "true":
- if debug:
- print('RUN AS DEVELOPMENT', file=sys.stderr)
- arduino.connect('dev')
- lirc = LircDev()
- else:
- print('RUN AS PRODUCTION', file=sys.stderr)
- arduino.connect()
- lirc = Lirc()
-
-from app import app
-
-if __name__ == '__main__':
- app.run(debug=debug, host='0.0.0.0', threaded=True)
+ flask_app.run(host='0.0.0.0', threaded=True)
diff --git a/src/js/app/action_sheets.js b/src/js/app/action_sheets.js
old mode 100644
new mode 100755
diff --git a/src/js/app/routes.js b/src/js/app/routes.js
old mode 100644
new mode 100755
diff --git a/tests/client.py b/tests/client.py
old mode 100644
new mode 100755
index de10bcc..1fe067b
--- a/tests/client.py
+++ b/tests/client.py
@@ -11,7 +11,7 @@ def receving (sock):
port = 0
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
-s.connect(("192.168.100.50",9090))
+s.connect(("192.168.1.105",9090))
thread.start_new_thread(receving, (s,))
diff --git a/tests/client_broadcast.py b/tests/client_broadcast.py
new file mode 100755
index 0000000..43db4c3
--- /dev/null
+++ b/tests/client_broadcast.py
@@ -0,0 +1,15 @@
+import socket
+
+s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+s.bind(('', 9090))
+
+try:
+ while True:
+ data, addr = s.recvfrom(1024)
+ print("my-ip:%s" % socket.gethostbyname(socket.gethostname()))
+ print(data)
+
+except KeyboardInterrupt:
+ s.close()
+ print("exit")
diff --git a/tests/server.py b/tests/server.py
old mode 100644
new mode 100755
diff --git a/tests/server_broadcast.py b/tests/server_broadcast.py
new file mode 100755
index 0000000..7fe9ac7
--- /dev/null
+++ b/tests/server_broadcast.py
@@ -0,0 +1,14 @@
+import socket, time
+
+s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+
+try:
+ while True:
+ message = "s-ip:%s" % socket.gethostbyname(socket.gethostname())
+ s.sendto(message, ('255.255.255.255', 9090))
+ print("sent")
+ time.sleep(5)
+
+except KeyboardInterrupt:
+ s.close()
diff --git a/tests/test_arduino_driver_v3.py b/tests/test_arduino_driver_v3.py
new file mode 100644
index 0000000..9a534a2
--- /dev/null
+++ b/tests/test_arduino_driver_v3.py
@@ -0,0 +1,182 @@
+import serial
+import time
+import array
+
+def createIrSignal(radio_id, button_exec):
+ nec_protocol = 0
+ pre_data = []
+ data = []
+ pre_data.append('%si' % radio_id)
+
+ zero = []
+ one = []
+ zero_bit = 0
+ one_bit = 0
+ compressed = ''
+
+ for value in button_exec.split(' '):
+ if nec_protocol < 2:
+ data.append(value)
+ nec_protocol += 1
+ continue
+
+ x = int(value)
+
+ if x <= 1000:
+ # 0
+ zero.append(x)
+ if one_bit > 0:
+ compressed += "%db" % one_bit
+ one_bit = 0
+ zero_bit = 1
+ else:
+ zero_bit += 1
+
+ elif x < 1800:
+ # 1
+ one.append(x)
+ if zero_bit > 0:
+ compressed += "%da" % zero_bit
+ zero_bit = 0
+ one_bit = 1
+ else:
+ one_bit += 1
+ else:
+ # as it
+ if zero_bit > 0:
+ compressed += "%da" % zero_bit
+ zero_bit = 0
+ if one_bit > 0:
+ compressed += "%db" % one_bit
+ one_bit = 0
+ if compressed:
+ data.append("[%s]" % compressed)
+ compressed = ''
+ # Arduino int is too small, so cut it
+ if x > 65000:
+ value = '65000'
+ data.append(value)
+
+ if zero_bit > 0:
+ compressed += "%da" % zero_bit
+ if one_bit > 0:
+ compressed += "%db" % one_bit
+ if compressed:
+ data.append("[%s]" % compressed)
+
+ # data.append('\n')
+
+ pre_data.append(str(round(sum(zero)/len(zero))))
+ pre_data.append(str(round(sum(one)/len(one))))
+
+ execute = ' '.join(pre_data + data)
+ return '%s\n' % execute
+
+ir_signal = "8627 4464 584 539 586 1663 587 541 587 539 587 540 587 540 586 541 585 1664 587 1662 590 540 585 1666 585 1664 587 542 585 1663 586 1663 588 541 586 540 586 542 585 1665 587 1662 586 1665 586 1664 586 542 586 538 589 1664 586 1664 586 541 586 542 584 542 586 542 585 1662 587 1666 588"
+# ir_signal = "8851 4435 565 1644 591 512 568 565 566 540 567 1642 568 565 567 1644 592 539 540 565 592 1623 592 1647 594 511 589 1650 562 1646 593 1643 594 513 595 511 590 516 565 569 592 510 595 1615 570 564 592 514 593 513 566 565 541 567 591 515 592 513 567 565 541 565 592 515 565 565 541 565 591 517 564 541 590 515 591 541 591 1619 568 564 538 568 566 539 591 513 592 543 561 545 589 516 593 512 565 567 565 539 566 1644 565 567 593 1618 593 1643 594 515 590 514 565 1675 589 514 593"
+# ir_signal = "3430 1748 438 439 437 1314 435 433 436 435 438 430 438 433 437 432 436 433 437 434 438 432 435 435 436 433 437 433 439 1307 437 435 436 433 436 432 439 432 439 431 437 432 437 433 438 433 437 431 437 1316 432 431 435 434 439 430 438 435 477 393 435 434 437 433 435 434 438 1309 437 438 437 1314 439 1307 438 1307 439 1306 438 441 434 442 436 1314 436 432 437 1311 437 1307 438 1309 437 1312 437 435 436 1310 436 75114 3486 1749 438 435 432 1310 436 434 437 434 436 435 434 435 436 433 436 434 436 434 437 435 433 436 436 432 436 433 438 1309 437 434 435 433 437 434 435 434 438 433 437 433 435 434 437 433 436 435 434 1309 439 438 438 440 434 440 436 440 435 440 437 439 438 438 438 438 436 1316 437 431 437 1308 438 1310 436 1309 438 1313 436 435 436 434 435 1309 437 433 437 1308 438 1309 436 1314 438 1310 435 435 434 1311 435 75118 3488 1750 436 441 435 1316 435 435 435 436 434 434 436 435 434 434 435 437 433 435 437 433 435 435 435 436 435 433 437 1309 436 433 438 433 439 430 435 435 437 433 435 435 436 434 437 432 437 434 437 1308 435 436 435 432 438 435 434 436 436 433 435 433 437 434 436 435 435 1309 435 442 435 1314 438 1309 436 1309 437 1309 436 441 435 439 439 1314 436 432 436 1311 436 1309 437 1310 434 1316 436 433 438 1308 437"
+# ir_signal = "8851 4435 565 1644 591 512 568 565 566 540 567 1642 568 565 567 1644 592 539 1623 592 1647 594 511 589 1650 562 562 562 1650 562 1650 562 1650 562 1650 562 1650 562 1650 562 1650 562 1650 562 1650 562 1650"
+radio_id = '2'
+
+success = 0
+fail = 0
+error = 0
+serial_buff = 64
+
+ser = serial.Serial()
+ser.baudrate = 500000
+ser.port = '/dev/ttyUSB0'
+ser.timeout = 0.5
+ser.open()
+
+# Only after writing sketch into Arduino
+# print(repr(ser.readline()))
+time.sleep(2)
+ser.flushInput()
+ser.flushOutput()
+
+signal = createIrSignal(radio_id, ir_signal)
+print("-----signal------")
+print(signal)
+
+n = 64
+partial_signal = [signal[i:i+n] for i in range(0, len(signal), n)]
+
+now = time.time()
+
+try:
+ while True:
+ if int(time.time() - now) > 0.5:
+ now = time.time()
+ # continue
+ partial_signal = [signal[i:i+serial_buff] for i in range(0, len(signal), serial_buff)]
+
+ for part in partial_signal:
+ # print(part)
+ b_arr = bytearray(part.encode())
+ ser.write(b_arr)
+ ser.flush()
+
+ error = False
+
+ while True:
+ response = ser.readline()
+ response = response.decode('ascii', 'replace')
+ # print(response)
+
+ if int(time.time() - now) > 0.5:
+ print('waiting timeout')
+ error = True
+ break
+ elif response.strip() == '':
+ print('empty response')
+ elif response.strip() == ':next:':
+ break
+ elif response.strip() == ':overflow:':
+ print('overflow')
+ error = True
+ break
+ elif response.strip() == ':timeout:':
+ print('timeout')
+ error = True
+ break
+ elif response.strip() == ':ack:':
+ print('ack')
+ continue
+ # response = ser.readline()
+ # response = response.decode('ascii', 'replace')
+ # print(response)
+
+ elif response.strip() == ':fail:':
+ error = True
+ break
+ elif response.strip() == ':success:':
+ print('transfer success')
+ break
+ else:
+ print('.')
+
+ if error:
+ print('transfer error')
+ break
+
+ else:
+ incoming_size = ser.in_waiting
+ if incoming_size > 0:
+ response = ser.readline()
+ response = response.decode('ascii', 'replace')
+ # response = response.rstrip().decode('ascii', 'replace')
+ # print(response)
+ # last = response.strip()
+ # print(last)
+ # if last[-1].encode() == b"\x17":
+ # print('aaavvvv')
+ else:
+ time.sleep(0.05)
+
+except KeyboardInterrupt:
+ ser.flushInput()
+ ser.flushOutput()
+ ser.close()
+ print("QUIT")
+
diff --git a/tests/test_radio_command_two_receivers.py b/tests/test_radio_command_two_receivers.py
old mode 100644
new mode 100755
diff --git a/tests/test_radio_rx.py b/tests/test_radio_rx.py
new file mode 100755
index 0000000..fae7041
--- /dev/null
+++ b/tests/test_radio_rx.py
@@ -0,0 +1,71 @@
+import serial
+import time
+import array
+
+command = "status"
+# radio_pipe = 'AABBCCDD33'
+radio_pipe = 'AABBCCDD44'
+
+success = 0
+fail = 0
+error = 0
+
+ser = serial.Serial()
+ser.baudrate = 500000
+ser.port = '/dev/ttyUSB0'
+ser.timeout = 1
+ser.open()
+
+# Only after writing sketch into Arduino
+# print(repr(ser.readline()))
+time.sleep(2)
+ser.flushInput()
+ser.flushOutput()
+
+signal = '%sc%s\n' % (radio_pipe, command)
+
+print(signal)
+
+n = 32
+partial_signal = [signal[i:i+n] for i in range(0, len(signal), n)]
+
+try:
+ while True:
+ ser.flushInput()
+ ser.flushOutput()
+
+ # if ser.in_waiting > 0:
+ # print(ser.in_waiting)
+ # print "-----------------"
+ response_in = ser.readline()
+ response = response_in.rstrip()
+
+ if response == '':
+ continue
+
+ data = response.split(':')
+ print(repr(response_in))
+
+ if data[1] == 'FAIL':
+ fail += 1
+ time.sleep(0.5)
+ elif data[1] == 'OK':
+ success += 1
+ else:
+ error += 1
+ print(repr(response_in))
+
+ print "Success: %d Fail: %d Error: %d" % (success, fail, error)
+
+ if data[0]:
+ print(data[0])
+ # else:
+ # pass
+ # time.sleep(0.05)
+
+
+except KeyboardInterrupt:
+ ser.flushInput()
+ ser.flushOutput()
+ ser.close()
+ print("QUIT")