Skip to content

Commit

Permalink
json config file, frontend update/cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
John Lifsey committed Dec 20, 2015
1 parent 4eedfcd commit 026a705
Show file tree
Hide file tree
Showing 39 changed files with 274 additions and 123 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,14 @@ Demonstrated in the video below:
* [WWW::Wunderground::API](https://metacpan.org/module/WWW::Wunderground::API)
* [IO::Termios](https://metacpan.org/module/IO::Termios) optional for RS485 serial monitoring
* Try::Tiny
* Cache::FileCache
* JSON

###### Raspbian-specific
###### Raspbian-specific
* Some CPAN Modules will time out if the command to install them is not run in verbose mode. For instance: ```curl -L https://cpanmin.us | perl - -M https://cpan.metacpan.org/ -n IO::Termios --verbose```
* expat-devel must be installed before installing Wunderground for parsing, so you should do "apt-get install expat libexpat1-dev"

##### Hardware
* Basic hardware capable of running Linux. This could be a desktop machine, a Raspberry Pi, or an embedded device. The author runs Infinitude on ArchLinux using a [Pogoplug v4](http://www.amazon.com/Pogoplug-Series-4-Backup-Device/dp/B006I5MKZY/ref=sr_1_1?ie=UTF8&tag=sbhq-20&qid=1415825203&sr=8-1&keywords=pogoplug) which can be obtained for less than $20 USD and sits on top of the air handler like so:
* Basic hardware capable of running Linux. This could be a desktop machine, a Raspberry Pi, or an embedded device. The author runs Infinitude on ArchLinux using a [Pogoplug v4](http://www.amazon.com/Pogoplug-Series-4-Backup-Device/dp/B006I5MKZY/ref=sr_1_1?ie=UTF8&tag=sbhq-20&qid=1415825203&sr=8-1&keywords=pogoplug) which can be obtained for less than $10 USD and sits on top of the air handler like so:

<a href="http://imgur.com/a/bkcHX#1"><img src="http://i.imgur.com/IESJCCw.jpg" title="source: imgur.com" /></a>

Expand Down
47 changes: 26 additions & 21 deletions infinitude
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,29 @@ use Mojolicious::Lite;
use Mojo::JSON qw/encode_json decode_json/;
use DateTime;
use WWW::Wunderground::API;
use Cache::FileCache;
use Try::Tiny;
use Time::HiRes qw/time/;

use Cache::FileDump;
use XML::Simple::Minded;

# -------------- Config ------------------------
our $config ||= {
wunderground_key => '', #Weather underground API key
store_base => 'state', #State storage base directory
serial_tty => '/dev/ttyUSB0', #RS485 serial tty interface
app_secret => 'Pogotudinal', #Mojolicious cookie signature
pass_reqs => 60*60*2 #Pass requests to Carrier webservice every 2 hours (set to 0 to disable)
};
# ----------------------------------------------
my $store = Cache::FileDump->new(base=>'state', _serializer=>sub{ shift }, _deserializer=>sub{ shift });
$store->set(started=>time);

our $config;
if (my $config_json = $store->get('infinitude.json')) {
$config = decode_json($config_json);
} else {
# Default configuration if no state/infinitude.json file is found.
# customize config by editing state/infinitude.json
$config = {
wunderground_key => '', #Weather underground API key
serial_tty => '/dev/ttyUSB0', #RS485 serial tty interface
app_secret => 'Pogotudinal', #Mojolicious cookie signature
pass_reqs => 60*60*0 #Pass requests to Carrier webservice every 2 hours (set to 0 to disable)
};
$store->set('infinitude.json', encode_json($config));
}

if (defined($config->{serial_tty})) {
if (-e $config->{serial_tty}) {
Expand All @@ -35,21 +42,16 @@ if (defined($config->{serial_tty})) {
}
}

my $store = Cache::FileDump->new(base=>$config->{store_base});
$store->set(started=>time);

my $req_cache =Cache::FileCache->new({ namespace=>'myinfinity', default_expires_in=>$config->{pass_reqs} });
my $req_cache = Cache::FileDump->new( base=>$store->base, default_expires_in=>$config->{pass_reqs} );

app->secrets([$config->{app_secret}]);
#push @{app->static->paths}, 'public/app'; #development
push @{app->static->paths}, 'public/dist'; #production
push @{app->static->paths}, $ENV{MOJO_MODE} eq 'development' ? 'public/app' : 'public/dist';

hook before_dispatch => sub {
my $c = shift;

my $url = $c->req->url;
if ($url->to_abs->host =~ /carrier/) {

if ($url->to_abs->host =~ /(bryant|carrier)/) {
my $nk = $url->path->to_string;
$nk =~ s/\//-/g;
$nk =~ s/^-//;
Expand Down Expand Up @@ -250,7 +252,7 @@ get '/weather/:zip/forecast' => sub {
my $c = shift;
my $xml;
if ($config->{wunderground_key}) {
my $wunderground = WWW::Wunderground::API->new(auto_api=>1, api_key=>$config->{wunderground_key}, location=>$c->stash('zip'), cache=>Cache::FileCache->new({ namespace=>'infinitude', default_expires_in=>60*240 }));
my $wunderground = WWW::Wunderground::API->new(auto_api=>1, api_key=>$config->{wunderground_key}, location=>$c->stash('zip'), cache=>$store);
my $forecast = $wunderground->forecast10day->simpleforecast->forecastday;

sub map_wx {
Expand Down Expand Up @@ -296,13 +298,15 @@ get '/weather/:zip/forecast' => sub {
$c->render(text=>$xml, format=>'xml');
};

my $handle;
my $stream;
my $carbus;
websocket '/serial' => sub {
my $c = shift;
if ($config->{serial_tty}) {
$c->app->log->debug('WebSocket opened.');
$stream ||= Mojo::IOLoop::Stream->new(IO::Termios->open($config->{serial_tty},"38400,8,n,1"));
$c->app->log->debug('WebSocket opened. Attempting to access '.$config->{serial_tty});
$handle ||= IO::Termios->open($config->{serial_tty},"38400,8,n,1");
$stream ||= Mojo::IOLoop::Stream->new($handle);
$carbus ||= CarBus->new(async=>1);

$stream->on(read => sub {
Expand Down Expand Up @@ -336,6 +340,7 @@ websocket '/serial' => sub {
$c->app->log->debug("Closed: $code");
$stream->stop;
$stream = undef;
$handle = undef;
});
$stream->start;
$stream->reactor->start unless $stream->reactor->is_running;
Expand Down
48 changes: 43 additions & 5 deletions lib/Cache/FileDump.pm
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
package Cache::FileDump;

our $VERSION = '0.01';
our $VERSION = '0.02';

# Simple file store implementation.
# Any CHI or Cache::Cache or key/value store should work
# Any CHI or Cache::Cache or key/value store should work better
use Moo;
use Data::Dumper;
has base =>(is=>'rw', default=>'.');
has store => (is=>'rw', default=>sub{{}});
has default_expires_in => (is=>'ro', default=>sub{ 'never' });
has _exp_cache => (is=>'rw', default=>sub{{}});

has _serializer => (is=>'ro', default=>sub { return sub {
my $obj = shift;
my $dumper = Data::Dumper->new([]);
$dumper->Terse(1);
$dumper->Values([$obj]);
return $dumper->Dump;
}
});

has _deserializer => (is=>'ro', default=>sub{ return sub {
my $str = shift||'';
my $out = eval $str;
return $out;
}
});

sub set {
my $self = shift;
my ($key, $value) = @_;
$value = $value.'';
my ($key, $value, $exp) = @_;
my $ser = $self->_serializer;
$value = &$ser($value).'';
$exp ||= $self->default_expires_in;
my $stored = $self->get($key) || '';
if (!exists($self->store->{$key}) or $stored ne $value) {
my $F;
Expand All @@ -19,8 +41,12 @@ sub set {
close $F;
}
}
if ($exp =~ /^\d+$/) {
$self->_exp_cache->{$key} = (time+$exp);
}
$self->store->{$key} = $value;
}

sub get {
my $self = shift;
my ($key) = @_;
Expand All @@ -32,6 +58,18 @@ sub get {
$self->store->{$key} = $value;
}
}
return $value;

if (defined($value)) {
my $exp = $self->_exp_cache->{$key};
if (defined($exp)) {
if (time>$exp) {
$value = undef;
delete $self->store->{$key};
delete $self->_exp_cache->{$key};
}
}
}
my $des = $self->_deserializer();
return &$des($value);
}
1;
20 changes: 20 additions & 0 deletions lib/cbt.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/perl
use CarBus;
use IO::Termios;
use Data::Dumper;

#$Data::ParseBinary::print_debug_info = 1;
use IO::File;

#my $sfh = new IO::File("tty.raw");
my $sfh = new IO::File("ttysync.raw");
#my $sfh = IO::Termios->open("/dev/ttyUSB0","38400,8,n,1");

my $carbus = new CarBus($sfh);

while(1) {
my $frame = $carbus->get_frame();
print Dumper($frame);
exit if $frame->{error};
}

Empty file added lib/debug.txt
Empty file.
Binary file added lib/tty.raw
Binary file not shown.
Binary file added lib/ttysync.raw
Binary file not shown.
3 changes: 2 additions & 1 deletion public/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<![endif]-->

<!-- Add your site or application content here -->
<span style="display:none" ng-controller="SerialCtrl"></span>
<div class="header" ng-controller="MainCtrl">
<ul class="nav nav-pills pull-right">
<li ng-class="{active:isActive('/')}"><a ng-href="#status">Status</a></li>
Expand All @@ -33,7 +34,7 @@
<li ng-class="{active:isActive('/serial')}"><a ng-href="#serial">Serial</a></li>
<li ng-class="{active:isActive('/about')}"><a ng-href="#about">About</a></li>
</ul>
<h3 class="text-muted">Infinitude</h3>
<h3 class="text-muted">&infin; Infinitude</h3>
</div>

<div class="container-fluid" ng-view></div>
Expand Down
40 changes: 11 additions & 29 deletions public/app/scripts/controllers/main.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,25 @@
'use strict';

angular.module('infinitude')
.controller('MainCtrl', function ($scope, $http, $interval, $location) {
$scope.debounce = 0;
$scope.carbus = $scope.carbus||{};

$scope.systems = JSON.parse(window.localStorage.getItem("infinitude-systems")) || {};
$scope.status = JSON.parse(window.localStorage.getItem("infinitude-status")) || {};
$scope.notifications = JSON.parse(window.localStorage.getItem("infinitude-notifications")) || {};
var store = angular.fromJson(window.localStorage.getItem('infinitude')) || {};

var reloadData = function() {
if ($scope.debounce > 0) {
$scope.debounce = $scope.debounce - 1;
return;
}
$http.get('/systems.json').
success(function(data) {
$scope.systems = data;
window.localstorage.setItem("infinitude-systems", data);
//console.log('systems:',$scope.systems);
});
$http.get('/status.json').
success(function(data) {
$scope.status = data.status[0];
window.localstorage.setItem("infinitude-status", data.status[0]);
//console.log('status:',$scope.status);
});
$http.get('/notifications.json').
success(function(data) {
$scope.notifications = data.notifications[0];
window.localstorage.setItem("infinitude-notifications", data.notifications[0]);
//console.log('status:',$scope.status);
});
/*$http.get('/energy.json').
success(function(data) {
$scope.energy = data.energy[0];
//console.log('status:',$scope.status);
});
*/
var keys = ['systems','status','notifications','energy'];
angular.forEach(keys, function(key) {
$http.get('/'+key+'.json').
success(function(data) {
var rkey = key;
if (rkey === 'systems') { rkey = 'system'; }
$scope[key] = store[key] = data[rkey][0];
});
});
window.localStorage.setItem('infinitude', angular.toJson(store));
};

$scope.$watch('systems', function(newValue,oldValue) {
Expand Down
Loading

0 comments on commit 026a705

Please sign in to comment.