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.003';
3             # ABSTRACT: REST interface for Device::WebIO using Dancer
4 6     6   1195746 use v5.12;
  6         18  
  6         238  
5 6     6   46 use Dancer;
  6         8  
  6         37  
6 6     6   5988 use Time::HiRes 'sleep';
  6         17  
  6         52  
7              
8 6     6   667 use constant VID_READ_LENGTH => 4096;
  6         10  
  6         381  
9 6     6   26 use constant PULSE_TIME => 0.1;
  6         6  
  6         14560  
10              
11              
12             my ($webio, $default_name);
13              
14             sub init
15             {
16 5     5 0 8798 my ($webio_ext, $default_name_ext) = @_;
17 5         12 $webio = $webio_ext;
18 5         9 $default_name = $default_name_ext;
19 5         11 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 $mime = "$mime1/$mime2";
307             my $fh = $webio->img_stream( $name, $pin, $mime );
308              
309             local $/ = undef;
310             my $buffer = <$fh>;
311             close $fh;
312              
313             content_type $mime;
314             return $buffer;
315             };
316              
317              
318             get '/GPIO/:pin/function' => sub {
319             my $pin = params->{pin};
320              
321             my $type = lc _get_io_type( $default_name, $pin );
322             return $type;
323             };
324              
325             post '/GPIO/:pin/function/:func' => sub {
326             my $pin = params->{pin};
327             my $func = uc params->{func};
328              
329             if( 'IN' eq $func ) {
330             $webio->set_as_input( $default_name, $pin );
331             }
332             elsif( 'OUT' eq $func ) {
333             $webio->set_as_output( $default_name, $pin );
334             }
335             else {
336             # TODO
337             }
338              
339             return '';
340             };
341              
342             get '/GPIO/:pin/value' => sub {
343             my $pin = params->{pin};
344             my $in = $webio->digital_input( $default_name, $pin );
345             return $in;
346             };
347              
348             post '/GPIO/:pin/value/:value' => sub {
349             my $pin = params->{pin};
350             my $value = params->{value};
351              
352             $webio->digital_output( $default_name, $pin, $value );
353              
354             return '';
355             };
356              
357             post '/GPIO/:pin/pulse' => sub {
358             my $pin = params->{pin};
359              
360             $webio->digital_output( $default_name, $pin, 1 );
361             sleep PULSE_TIME;
362             $webio->digital_output( $default_name, $pin, 0 );
363              
364             return '';
365             };
366              
367             post '/GPIO/:pin/sequence/:seq' => sub {
368             my $pin = params->{pin};
369             my $seq = params->{seq};
370             my ($duration, $bits) = split /,/, $seq, 2;
371             my @bits = split //, $bits;
372              
373             foreach my $value (@bits) {
374             my $duration_ms = $duration / 1000;
375              
376             $webio->digital_output( $default_name, $pin, $value );
377             sleep $duration_ms;
378             }
379              
380             return '';
381             };
382              
383              
384             get '/map' => sub {
385             return to_json( $webio->pin_desc( $default_name ) );
386             };
387              
388             get qr{\A / \* }x => sub {
389             return to_json( $webio->all_desc( $default_name ) );
390             };
391              
392              
393             get '/' => sub {
394             return 'Hello, world!';
395             };
396              
397              
398              
399             sub _int_to_array
400             {
401 1     1   19 my ($int, @index_list) = @_;
402 8         9 my @values = map {
403 1         3 ($int >> $_) & 1
404             } @index_list;
405 1         4 return @values;
406             }
407              
408             sub _get_io_type
409             {
410 12     12   15 my ($name, $pin) = @_;
411             # Ignore exceptions
412 12         29 my $type = eval { $webio->is_set_input( $name, $pin ) } ? 'IN'
413 12 50       11 : eval { $webio->is_set_output( $name, $pin ) } ? 'OUT'
  4 100       141  
414             : 'UNSET';
415 12 50       393 warn "Caught exception while getting IO type for pin '$pin': $@\n" if $@;
416 12         19 return $type;
417             }
418              
419              
420             1;
421             __END__