File Coverage

blib/lib/Device/WebIO/Dancer.pm
Criterion Covered Total %
statement 29 29 100.0
branch 4 6 66.6
condition n/a
subroutine 8 8 100.0
pod 0 1 0.0
total 41 44 93.1


line stmt bran cond sub pod time code
1             package Device::WebIO::Dancer;
2             $Device::WebIO::Dancer::VERSION = '0.002';
3             # ABSTRACT: REST interface for Device::WebIO using Dancer
4 6     6   1241943 use v5.12;
  6         19  
  6         221  
5 6     6   40 use Dancer;
  6         7  
  6         30  
6 6     6   5308 use Time::HiRes 'sleep';
  6         17  
  6         47  
7              
8 6     6   568 use constant VID_READ_LENGTH => 4096;
  6         12  
  6         309  
9 6     6   23 use constant PULSE_TIME => 0.1;
  6         7  
  6         13062  
10              
11              
12             my ($webio, $default_name);
13              
14             sub init
15             {
16 5     5 0 9038 my ($webio_ext, $default_name_ext) = @_;
17 5         11 $webio = $webio_ext;
18 5         8 $default_name = $default_name_ext;
19 5         9 return 1;
20             }
21              
22              
23             get '/devices/:name/count' => sub {
24             my $name = params->{name};
25             my $count = $webio->digital_input_pin_count( $name );
26             return $count;
27             };
28              
29             get '/devices/:name/:pin/integer' => sub {
30             my ($name) = params->{name};
31             my ($pin) = params->{pin};
32             my $int = $webio->digital_input_port( $name );
33             return $int;
34             };
35              
36             get '/devices/:name/:pin/value' => sub {
37             my $name = params->{name};
38             my $pin = params->{pin};
39              
40             my $in;
41             if( $pin eq '*' ) {
42             my $int = $webio->digital_input_port( $name );
43             my @values = _int_to_array( $int,
44             reverse(0 .. $webio->digital_input_pin_count( $name ) - 1) );
45             $in = join ',', @values;
46             }
47             else {
48             $in = $webio->digital_input( $name, $pin );
49             }
50             return $in;
51             };
52              
53             get '/devices/:name/:pin/function' => sub {
54             my $name = params->{name};
55             my $pin = params->{pin};
56              
57             my $type = _get_io_type( $name, $pin );
58             return $type;
59             };
60              
61             post '/devices/:name/:pin/function/:func' => sub {
62             my $name = params->{name};
63             my $pin = params->{pin};
64             my $func = uc params->{func};
65              
66             if( 'IN' eq $func ) {
67             $webio->set_as_input( $name, $pin );
68             }
69             elsif( 'OUT' eq $func ) {
70             $webio->set_as_output( $name, $pin );
71             }
72             else {
73             # TODO
74             }
75              
76             return '';
77             };
78              
79             get '/devices/:name/:pin' => sub {
80             my $name = params->{name};
81             my $pin = params->{pin};
82             my $pin_count = $webio->digital_input_pin_count( $name );
83             my @pin_index_list = 0 .. ($pin_count - 1);
84              
85             my (@values, @type_values);
86             foreach (@pin_index_list) {
87             my $type = _get_io_type( $name, $_ );
88             push @type_values, $type;
89              
90             my $int = ($type eq 'IN') ? $webio->digital_input( $name, $_ ) :
91             ($type eq 'OUT') ? 0 :
92             0;
93             push @values, $int;
94             }
95              
96             my $combined_types = join ',', reverse map {
97             $values[$_] . ':' . $type_values[$_]
98             } @pin_index_list;
99             return $combined_types;
100             };
101              
102             post '/devices/:name/:pin/value/:digit' => sub {
103             my $name = params->{name};
104             my $pin = params->{pin};
105             my $digit = params->{digit};
106              
107             $webio->digital_output( $name, $pin, $digit );
108              
109             return '';
110             };
111              
112             post '/devices/:name/:pin/integer/:value' => sub {
113             my $name = params->{name};
114             my $pin = params->{pin};
115             my $value = params->{value};
116              
117             $webio->digital_output_port( $name, $value );
118              
119             return '';
120             };
121              
122             get '/devices/:name/video/count' => sub {
123             my $name = params->{name};
124             my $val = $webio->vid_channels( $name );
125             return $val;
126             };
127              
128             get '/devices/:name/video/:channel/resolution' => sub {
129             my $name = params->{name};
130             my $channel = params->{channel};
131              
132             my $width = $webio->vid_width( $name, $channel );
133             my $height = $webio->vid_height( $name, $channel );
134             my $fps = $webio->vid_fps( $name, $channel );
135              
136             return $width . 'x' . $height . 'p' . $fps;
137             };
138              
139             post '/devices/:name/video/:channel/resolution/:width/:height/:framerate'
140             => sub {
141             my $name = params->{name};
142             my $channel = params->{channel};
143             my $width = params->{width};
144             my $height = params->{height};
145             my $fps = params->{framerate};
146              
147             $webio->vid_set_width( $name, $channel, $width );
148             $webio->vid_set_height( $name, $channel, $height );
149             $webio->vid_set_fps( $name, $channel, $fps );
150              
151             return '';
152             };
153              
154             get '/devices/:name/video/:channel/kbps' => sub {
155             my $name = params->{name};
156             my $channel = params->{channel};
157              
158             my $bitrate = $webio->vid_kbps( $name, $channel );
159              
160             return $bitrate;
161             };
162              
163             post '/devices/:name/video/:channel/kbps/:bitrate' => sub {
164             my $name = params->{name};
165             my $channel = params->{channel};
166             my $bitrate = params->{bitrate};
167             $webio->vid_set_kbps( $name, $channel, $bitrate );
168             return '';
169             };
170              
171             get '/devices/:name/video/:channel/allowed-content-types' => sub {
172             my $name = params->{name};
173             my $channel = params->{channel};
174             my $allowed = $webio->vid_allowed_content_types( $name, $channel );
175             return join( "\n", @$allowed );
176             };
177              
178             get '/devices/:name/video/:channel/stream/:type1/:type2' => sub {
179             my $name = params->{name};
180             my $channel = params->{channel};
181             my $type1 = params->{type1};
182             my $type2 = params->{type2};
183             my $mime_type = $type1 . '/' . $type2;
184              
185             my $in_fh = $webio->vid_stream( $name, $channel, $mime_type );
186              
187             return send_file( '/etc/hosts',
188             streaming => 1,
189             system_path => 1,
190             content_type => $mime_type,
191             callbacks => {
192             around_content => sub {
193             my ($writer, $chunk) = @_;
194              
195             my $buf;
196             while( read( $in_fh, $buf, VID_READ_LENGTH ) ) {
197             $writer->write( $buf );
198             }
199             close $in_fh;
200             }
201             },
202             );
203             };
204              
205             get '/devices/:name/analog/count' => sub {
206             my $name = params->{name};
207             my $count = $webio->adc_count( $name );
208             return $count;
209             };
210              
211             get '/devices/:name/analog/maximum' => sub {
212             # TODO deprecate this more explicitly (301 Moved Permanently?)
213             my $name = params->{name};
214             my $max = $webio->adc_max_int( $name, 0 );
215             return $max;
216             };
217              
218             get '/devices/:name/analog/:pin/maximum' => sub {
219             my $name = params->{name};
220             my $pin = params->{pin};
221             my $max = $webio->adc_max_int( $name, $pin );
222             return $max;
223             };
224              
225             get '/devices/:name/analog/:pin/integer/vref' => sub {
226             my $name = params->{name};
227             my $pin = params->{pin};
228             my $value = $webio->adc_volt_ref( $name, $pin );
229             return $value;
230             };
231              
232             get '/devices/:name/analog/integer/vref' => sub {
233             # TODO deprecate this more explicitly (301 Moved Permanently?)
234             my $name = params->{name};
235             my $value = $webio->adc_volt_ref( $name, 0 );
236             return $value;
237             };
238              
239             get '/devices/:name/analog/:pin/integer' => sub {
240             my $name = params->{name};
241             my $pin = params->{pin};
242              
243             my $value;
244             if( $pin eq '*' ) {
245             my @val = map {
246             $webio->adc_input_int( $name, $_ ) // 0
247             } 0 .. ($webio->adc_count( $name ) - 1);
248             $value = join ',', @val;
249             }
250             else {
251             $value = $webio->adc_input_int( $name, $pin );
252             }
253             return $value;
254             };
255              
256             get '/devices/:name/analog/:pin/float' => sub {
257             my $name = params->{name};
258             my $pin = params->{pin};
259             my $value = $webio->adc_input_float( $name, $pin );
260             return $value;
261             };
262              
263             get '/devices/:name/analog/:pin/volt' => sub {
264             my $name = params->{name};
265             my $pin = params->{pin};
266             my $value = $webio->adc_input_volts( $name, $pin );
267             return $value;
268             };
269              
270             get '/devices/:name/image/count' => sub {
271             my $name = params->{name};
272             my $value = $webio->img_channels( $name );
273             return $value;
274             };
275              
276             get '/devices/:name/image/:pin/resolution' => sub {
277             my $name = params->{name};
278             my $pin = params->{pin};
279             my $width = $webio->img_width( $name, $pin );
280             my $height = $webio->img_height( $name, $pin );
281             return $width . 'x' . $height;
282             };
283              
284             post '/devices/:name/image/:pin/resolution/:width/:height' => sub {
285             my $name = params->{name};
286             my $pin = params->{pin};
287             my $width = params->{width};
288             my $height = params->{height};
289             $webio->img_set_width( $name, $pin, $width );
290             $webio->img_set_height( $name, $pin, $height );
291             return 1;
292             };
293              
294             get '/devices/:name/image/:pin/allowed-content-types' => sub {
295             my $name = params->{name};
296             my $pin = params->{pin};
297             my $types = $webio->img_allowed_content_types( $name, $pin );
298             return join( "\n", @$types );
299             };
300              
301             get '/devices/:name/image/:pin/stream/:mime1/:mime2' => sub {
302             my $name = params->{name};
303             my $pin = params->{pin};
304             my $mime1 = params->{mime1};
305             my $mime2 = params->{mime2};
306             my $fh = $webio->img_stream( $name, $pin, "$mime1/$mime2" );
307              
308             local $/ = undef;
309             my $buffer = <$fh>;
310             close $fh;
311              
312             return $buffer;
313             };
314              
315              
316             get '/GPIO/:pin/function' => sub {
317             my $pin = params->{pin};
318              
319             my $type = lc _get_io_type( $default_name, $pin );
320             return $type;
321             };
322              
323             post '/GPIO/:pin/function/:func' => sub {
324             my $pin = params->{pin};
325             my $func = uc params->{func};
326              
327             if( 'IN' eq $func ) {
328             $webio->set_as_input( $default_name, $pin );
329             }
330             elsif( 'OUT' eq $func ) {
331             $webio->set_as_output( $default_name, $pin );
332             }
333             else {
334             # TODO
335             }
336              
337             return '';
338             };
339              
340             get '/GPIO/:pin/value' => sub {
341             my $pin = params->{pin};
342             my $in = $webio->digital_input( $default_name, $pin );
343             return $in;
344             };
345              
346             post '/GPIO/:pin/value/:value' => sub {
347             my $pin = params->{pin};
348             my $value = params->{value};
349              
350             $webio->digital_output( $default_name, $pin, $value );
351              
352             return '';
353             };
354              
355             post '/GPIO/:pin/pulse' => sub {
356             my $pin = params->{pin};
357              
358             $webio->digital_output( $default_name, $pin, 1 );
359             sleep PULSE_TIME;
360             $webio->digital_output( $default_name, $pin, 0 );
361              
362             return '';
363             };
364              
365             post '/GPIO/:pin/sequence/:seq' => sub {
366             my $pin = params->{pin};
367             my $seq = params->{seq};
368             my ($duration, $bits) = split /,/, $seq, 2;
369             my @bits = split //, $bits;
370              
371             foreach my $value (@bits) {
372             my $duration_ms = $duration / 1000;
373              
374             $webio->digital_output( $default_name, $pin, $value );
375             sleep $duration_ms;
376             }
377              
378             return '';
379             };
380              
381              
382             get '/map' => sub {
383             return to_json( $webio->pin_desc( $default_name ) );
384             };
385              
386             get qr{\A / \* }x => sub {
387             return to_json( $webio->all_desc( $default_name ) );
388             };
389              
390              
391             get '/' => sub {
392             return 'Hello, world!';
393             };
394              
395              
396              
397             sub _int_to_array
398             {
399 1     1   18 my ($int, @index_list) = @_;
400 8         10 my @values = map {
401 1         2 ($int >> $_) & 1
402             } @index_list;
403 1         3 return @values;
404             }
405              
406             sub _get_io_type
407             {
408 12     12   16 my ($name, $pin) = @_;
409             # Ignore exceptions
410 12         30 my $type = eval { $webio->is_set_input( $name, $pin ) } ? 'IN'
411 12 50       9 : eval { $webio->is_set_output( $name, $pin ) } ? 'OUT'
  4 100       262  
412             : 'UNSET';
413 12 50       397 warn "Caught exception while getting IO type for pin '$pin': $@\n" if $@;
414 12         15 return $type;
415             }
416              
417              
418             1;
419             __END__