File Coverage

blib/lib/AquariumHive/Simulator.pm
Criterion Covered Total %
statement 16 91 17.5
branch 0 26 0.0
condition 0 12 0.0
subroutine 6 23 26.0
pod 0 9 0.0
total 22 161 13.6


line stmt bran cond sub pod time code
1             package AquariumHive::Simulator;
2             BEGIN {
3 1     1   28 $AquariumHive::Simulator::AUTHORITY = 'cpan:GETTY';
4             }
5             $AquariumHive::Simulator::VERSION = '0.003';
6 1     1   4 use Moo;
  1         2  
  1         8  
7 1     1   243 use AnyEvent::Handle;
  1         2  
  1         21  
8 1     1   24 use AnyEvent::Util 'portable_socketpair';
  1         1  
  1         48  
9 1     1   4 use HiveJSO;
  1         1  
  1         13  
10 1     1   3 use DDP;
  1         1  
  1         6  
11              
12             sub BUILD {
13 0     0 0   my ( $self ) = @_;
14 0           $self->handle;
15 0           $self->pulse;
16             }
17              
18             has _portable_socketpair => (
19             is => 'lazy',
20             init_arg => undef,
21             );
22              
23             sub _build__portable_socketpair {
24 0     0     my ($fh1, $fh2) = portable_socketpair;
25 0           return [ $fh1, $fh2 ];
26             }
27              
28             has handle => (
29             is => 'lazy',
30             init_arg => undef,
31             );
32              
33             sub _build_handle {
34 0     0     my ( $self ) = @_;
35 0           my $handle = AnyEvent::Handle->new(
36             fh => $self->_portable_socketpair->[1],
37             );
38             $handle->on_read(sub {
39             $_[0]->push_read( hivejso => sub {
40 0           my ( $handle, $data ) = @_;
41 0 0         if (ref $data eq 'HiveJSO::Error') {
42 0           p($data->error); p($data->garbage);
  0            
43 0           return;
44             }
45 0           $self->on_hivejso($data);
46 0     0     });
47 0           });
48 0           return $handle;
49             }
50              
51             has fh => (
52             is => 'lazy',
53             init_arg => undef,
54             );
55              
56             sub _build_fh {
57 0     0     my ( $self ) = @_;
58 0           return $self->_portable_socketpair->[0];
59             }
60              
61             has sensor_rows => (
62             is => 'lazy',
63             );
64              
65 0     0     sub _build_sensor_rows { 2 }
66              
67             has pulse => (
68             is => 'lazy',
69             );
70              
71             sub _build_pulse {
72 0     0     my ( $self ) = @_;
73 0 0         return unless $self->sensor_rows;
74             return AE::timer 0, 60, sub {
75 0     0     for my $no (1..$self->sensor_rows) {
76 0           for my $sensor (qw( ph orp ec temp )) {
77 0           my $attr = $sensor.$no;
78 0           my $next = 'next_'.$sensor;
79 0           my $current = $self->state->{$attr};
80 0           my $new = $self->$next($current);
81 0           $self->state->{$attr} = $new;
82             }
83             }
84 0           };
85             }
86              
87             has state => (
88             is => 'lazy',
89             init_arg => undef,
90             );
91              
92             sub _build_state {
93 0     0     my ( $self ) = @_;
94             return {
95 0           (map { 'pwm'.$_, 0 } (1..6)),
  0            
96 0           (map { 'ph'.$_, $self->next_ph } (1..$self->sensor_rows)),
97 0           (map { 'orp'.$_, $self->next_orp } (1..$self->sensor_rows)),
98 0           (map { 'ec'.$_, $self->next_ec } (1..$self->sensor_rows)),
99 0           (map { 'temp'.$_, $self->next_temp } (1..$self->sensor_rows)),
100             };
101             }
102              
103             sub hivejso_base {
104 0     0 0   return unit => 'aqhive';
105             }
106              
107             sub state_to_hivejso {
108 0     0 0   my ( $self ) = @_;
109 0           my %state = %{$self->state};
  0            
110 0           my @data;
111 0           for my $key (keys %state) {
112 0           push @data, [$key, $state{$key}];
113             }
114 0           return HiveJSO->new( $self->hivejso_base, data => \@data );
115             }
116              
117             sub on_hivejso {
118 0     0 0   my ( $self, $hivejso ) = @_;
119 0 0         if ($hivejso->has_command) {
120             # "o":"data"
121 0 0         if ($hivejso->command_cmd eq 'data') {
122 0           $self->send_state;
123             }
124             # "o":["set_pwm1",100]
125 0 0         if ($hivejso->command_cmd eq 'set_pwm') {
126 0           my ( $no, $value ) = $hivejso->command_args;
127 0           my $func = 'pwm'.$no;
128 0           $self->state->{$func} = $value;
129 0           $self->send_state;
130             }
131             }
132             }
133              
134             sub send_state {
135 0     0 0   my ( $self ) = @_;
136 0           $self->handle->push_write($self->state_to_hivejso->hivejso_short);
137             }
138              
139             sub next_temp {
140 0     0 0   my ( $self, $current ) = @_;
141 0 0         return 615 unless defined $current;
142 0           my $new = $current + (int(rand(3)) - 2);
143 0 0 0       return $self->next_temp($current) if $new > 619 || $new < 610;
144 0           return $new;
145             }
146              
147             sub next_ph {
148 0     0 0   my ( $self, $current ) = @_;
149 0 0         return 512 unless defined $current;
150 0           my $new = $current + (int(rand(5)) - 3);
151 0 0 0       return $self->next_ph($current) if $new > 525 || $new < 500;
152 0           return $new;
153             }
154              
155             sub next_orp {
156 0     0 0   my ( $self, $current ) = @_;
157 0 0         return 458 unless defined $current;
158 0           my $new = $current + (int(rand(5)) - 3);
159 0 0 0       return $self->next_orp($current) if $new > 475 || $new < 425;
160 0           return $new;
161             }
162              
163             sub next_ec {
164 0     0 0   my ( $self, $current ) = @_;
165 0 0         return 120 unless defined $current;
166 0           my $new = $current + (int(rand(5)) - 3);
167 0 0 0       return $self->next_ec($current) if $new > 140 || $new < 100;
168 0           return $new;
169             }
170              
171             1;
172              
173             __END__
174              
175             =pod
176              
177             =head1 NAME
178              
179             AquariumHive::Simulator
180              
181             =head1 VERSION
182              
183             version 0.003
184              
185             =head1 DESCRIPTION
186              
187             B<IN DEVELOPMENT, DO NOT USE YET>
188              
189             See L<http://aquariumhive.com/> for now.
190              
191             =head1 SUPPORT
192              
193             IRC
194              
195             Join #AquariumHive on irc.freenode.net. Highlight Getty for fast reaction :).
196              
197             Repository
198              
199             https://github.com/homehivelab/aquariumhive
200             Pull request and additional contributors are welcome
201              
202             Issue Tracker
203              
204             https://github.com/homehivelab/aquariumhive/issues
205              
206             =head1 AUTHOR
207              
208             Torsten Raudssus <torsten@raudss.us>
209              
210             =head1 COPYRIGHT AND LICENSE
211              
212             This software is copyright (c) 2014 by Torsten Raudssus.
213              
214             This is free software; you can redistribute it and/or modify it under
215             the same terms as the Perl 5 programming language system itself.
216              
217             =cut