File Coverage

blib/lib/App/AquariumHive/Plugin/AqHive.pm
Criterion Covered Total %
statement 17 19 89.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 24 26 92.3


line stmt bran cond sub pod time code
1             package App::AquariumHive::Plugin::AqHive;
2             BEGIN {
3 1     1   1149 $App::AquariumHive::Plugin::AqHive::AUTHORITY = 'cpan:GETTY';
4             }
5             $App::AquariumHive::Plugin::AqHive::VERSION = '0.003';
6 1     1   7 use Moo;
  1         1  
  1         6  
7 1     1   265 use App::AquariumHive::Tile;
  1         1  
  1         15  
8 1     1   3 use JSON::MaybeXS;
  1         2  
  1         58  
9 1     1   5 use utf8;
  1         1  
  1         7  
10 1         5 use Digital qw(
11             AqHive::Temp
12             AqHive::ORP
13             AqHive::EC
14             AqHive::pH
15 1     1   600 );
  1         409  
16              
17             with qw(
18             App::AquariumHive::Role
19             );
20              
21 1     1   286 use AnyEvent::JSONRPC::TCP::Client;
  0            
  0            
22              
23             has kioskd_client => (
24             is => 'rw',
25             );
26              
27             sub new_kioskd_client {
28             my ( $self ) = @_;
29             return AnyEvent::JSONRPC::TCP::Client->new(
30             host => '127.0.0.1',
31             port => 24025,
32             on_error => sub {
33             $self->kioskd_client($self->new_kioskd_client);
34             },
35             );
36             }
37              
38             our @pwm_steps = qw(
39             0 1 1 2 2 2 2 2 3 3
40             3 4 4 5 5 6 6 7 8 9
41             10 11 12 13 15 17 19 21 23 26
42             29 32 36 40 44 49 55 61 68 76
43             85 94 105 117 131 146 162 181 202 225
44             250 279 311 346 386 430 479 534 595 663
45             739 824 918 1023
46             );
47              
48             our %sensor_names_and_units = (
49             ec => [ EC => yScm => 'yS/cm' ],
50             orp => [ ORP => mV => 'mV' ],
51             temp => [ Temp => C => '°C' ],
52             ph => [ pH => pH => 'pH' ],
53             );
54              
55             has pwm_step_state => (
56             is => 'rw',
57             default => sub {{
58             1 => '0',
59             2 => '0',
60             3 => '0',
61             4 => '0',
62             5 => '0',
63             6 => '0',
64             }},
65             );
66              
67             sub pwm_to_step {
68             my ( $self, $pwm ) = @_;
69             return 63 if $pwm >= 1023;
70             my $step;
71             for (0..62) {
72             $step = $_ if $pwm_steps[$_] <= $pwm;
73             }
74             return $step;
75             }
76              
77             sub BUILD {
78             my ( $self ) = @_;
79              
80             $self->kioskd_client($self->new_kioskd_client);
81              
82             if ($self->app->simulation) {
83             $self->web_mount( 'simulator', sub {
84             return [ 200, [ "Content-Type" => "application/json" ], [encode_json({
85             html => <<__HTML__,
86             <h1 class="text-center">AquariumHive 1 Simulationseinstellungen</h1>
87             <hr/>
88              
89             __HTML__
90             })] ];
91             });
92              
93             $self->add_tile( 'simulator' => App::AquariumHive::Tile->new(
94             id => 'simulator',
95             bgcolor => 'orange',
96             content => <<"__HTML__",
97              
98             <div class="large">
99             <div class="fattext">AqHive 1</div>
100             <div class="fattext">Simulator</div>
101             </div>
102              
103             __HTML__
104             js => <<"__JS__",
105              
106             \$('#simulator').click(function(){
107             call_app('simulator');
108             });
109              
110             __JS__
111             ));
112             }
113              
114             $self->on_data(sub {
115             my ( $app, $data ) = @_;
116             my %aqhive;
117             for my $d (@{$data}) {
118             my ( $key, $val ) = @{$d};
119             my ( $sensor, $no ) = $key =~ m/^([a-zA-Z]+)(\d+)$/;
120             if ($sensor_names_and_units{$sensor}) {
121             my ( $name, $func, $unit ) = @{$sensor_names_and_units{$sensor}};
122             $aqhive{$key} = sprintf('%.1f',input( 'aqhive_'.$sensor, $val )->$func);
123             } elsif ($sensor eq 'pwm' && !$self->no_pwm) {
124             $self->pwm_step_state->{$no} = $self->pwm_to_step($val);
125             $aqhive{$key} = ( $self->pwm_step_state->{$no} == 63
126             ? 'MAX' : $self->pwm_step_state->{$no} );
127             }
128             }
129             $app->send( aqhive => \%aqhive );
130             if ($self->sensor_rows) {
131             for my $no (1..$self->sensor_rows) {
132             $self->kioskd_client->call( Update => {
133             name => 'values'.$no,
134             type => 'text',
135             text => join(' ',(
136             $aqhive{'ph'.$no},'ph',
137             $aqhive{'orp'.$no},'mV',
138             $aqhive{'temp'.$no},'C',
139             $aqhive{'ec'.$no},'yS/cm',
140             )),
141             x => ( 6 + ( 30 * ( $no - 1 ) ) ),
142             y => 6,
143             w => 1000,
144             h => 30,
145             font_path => '/opt/kioskd/fonts/din1451alt.ttf',
146             font_point_size => 24,
147             colour => [255, 255, 255, 255],
148             })->cb(sub {
149             eval { $_[0]->recv };
150             });
151             }
152             }
153             });
154              
155             $self->on_socketio( aqhive => sub {
156             my ( $app, $data ) = @_;
157             if ($data->{cmd}) {
158             $app->command_aqhive($data->{cmd});
159             }
160             });
161              
162             if ($self->sensor_rows) {
163             for my $no (1..$self->sensor_rows) {
164             my $app = 'aqhive_sensors'.$no;
165             $self->web_mount( $app, sub {
166             return [ 200, [ "Content-Type" => "application/json" ], [encode_json({
167             html => <<__HTML__,
168             <h1 class="text-center">AquariumHive 1 Sensors $no</h1>
169             <hr/>
170              
171             __HTML__
172             })] ];
173             });
174             for my $sensor (qw( temp ph orp ec )) {
175             my $id = 'aqhive_'.$sensor.$no;
176             my ( $name, $func, $unit ) = @{$sensor_names_and_units{$sensor}};
177             $self->add_tile( 'aqhive_'.$sensor.$no => App::AquariumHive::Tile->new(
178             id => $id,
179             bgcolor => 'lightTeal',
180             content => <<"__HTML__",
181              
182             <div class="large">
183             <div>AqHive 1</div>
184             <div>$name $no</div>
185             <div><span class="fattext" id="aqhive_val_$sensor$no"></span> $unit</div>
186             </div>
187              
188             __HTML__
189             js => <<"__JS__",
190              
191             socket.on('aqhive', function(aqhive){
192             \$('#aqhive_val_$sensor$no').text(aqhive.$sensor$no);
193             });
194              
195             \$('#$id').click(function(){
196             call_app('$app');
197             });
198              
199             __JS__
200             ));
201             }
202             }
203             }
204              
205             unless ($self->no_pwm) {
206             for my $pwm (1..6) {
207             $self->on_socketio ( 'pwm'.$pwm, sub {
208             my ( $app, $data ) = @_;
209             if ($data->{cmd}) {
210             my $cmd = $data->{cmd};
211             if ($cmd eq 'next') {
212             my $next = $self->pwm_step_state->{$pwm} + 1;
213             $next = 63 if $next > 63;
214             $app->command_aqhive( 'set_pwm', "".$pwm, "".$pwm_steps[$next]);
215             } elsif ($cmd eq 'prev') {
216             my $prev = $self->pwm_step_state->{$pwm} - 1;
217             $prev = 0 if $prev < 0;
218             $app->command_aqhive( 'set_pwm', "".$pwm, "".$pwm_steps[$prev]);
219             } elsif ($cmd eq 'first') {
220             $app->command_aqhive( 'set_pwm', "".$pwm, "0");
221             } elsif ($cmd eq 'last') {
222             $app->command_aqhive( 'set_pwm', "".$pwm, "1023");
223             }
224             }
225             });
226             $self->add_tile( 'aqhive_pwm'.$pwm, App::AquariumHive::Tile->new(
227             id => 'aqhive_pwm'.$pwm,
228             bgcolor => 'cyan',
229             class => 'pwm-tile',
230             content => <<"__HTML__",
231              
232             <a id="aqhive_first_pwm$pwm" class="button">
233             <i class="icon-first-2"></i>
234             </a>
235             <a id="aqhive_prev_pwm$pwm" class="button">
236             <i class="icon-previous"></i>
237             </a>
238             <div>AqHive 1</div>
239             <div>PWM $pwm</div>
240             <div id="aqhive_val_pwm$pwm">...</div>
241             <a id="aqhive_next_pwm$pwm" class="button">
242             <i class="icon-next"></i>
243             </a>
244             <a id="aqhive_last_pwm$pwm" class="button">
245             <i class="icon-last-2"></i>
246             </a>
247              
248             __HTML__
249             js => <<"__JS__",
250              
251             socket.on('aqhive', function(aqhive){
252             \$('#aqhive_val_pwm$pwm').text(aqhive.pwm$pwm);
253             });
254              
255             \$('#aqhive_prev_pwm$pwm').click(function(){
256             socket.emit('pwm$pwm',{ cmd: 'prev' });
257             });
258              
259             \$('#aqhive_next_pwm$pwm').click(function(){
260             socket.emit('pwm$pwm',{ cmd: 'next' });
261             });
262              
263             \$('#aqhive_first_pwm$pwm').click(function(){
264             socket.emit('pwm$pwm',{ cmd: 'first' });
265             });
266              
267             \$('#aqhive_last_pwm$pwm').click(function(){
268             socket.emit('pwm$pwm',{ cmd: 'last' });
269             });
270              
271             __JS__
272             ));
273             }
274             }
275              
276             }
277              
278             1;
279              
280             __END__
281              
282             =pod
283              
284             =head1 NAME
285              
286             App::AquariumHive::Plugin::AqHive
287              
288             =head1 VERSION
289              
290             version 0.003
291              
292             =head1 DESCRIPTION
293              
294             B<IN DEVELOPMENT, DO NOT USE YET>
295              
296             See L<http://aquariumhive.com/> for now.
297              
298             =head1 SUPPORT
299              
300             IRC
301              
302             Join #AquariumHive on irc.freenode.net. Highlight Getty for fast reaction :).
303              
304             Repository
305              
306             https://github.com/homehivelab/aquariumhive
307             Pull request and additional contributors are welcome
308              
309             Issue Tracker
310              
311             https://github.com/homehivelab/aquariumhive/issues
312              
313             =head1 AUTHOR
314              
315             Torsten Raudssus <torsten@raudss.us>
316              
317             =head1 COPYRIGHT AND LICENSE
318              
319             This software is copyright (c) 2014 by Torsten Raudssus.
320              
321             This is free software; you can redistribute it and/or modify it under
322             the same terms as the Perl 5 programming language system itself.
323              
324             =cut