package POEDaemon::WheelRun::GPIOInterrupt; use strict; use warnings FATAL => 'all'; no warnings 'redefine'; #use POSIX qw(strftime); use POE; use POEDaemon; sub states { return $_[0], [qw( gpiointerrupt_start gpiointerrupt_stop gpiointerrupt_init gpiointerrupt_restart gpiointerrupt_childexit gpiointerrupt_stdout_line gpiointerrupt_stderr_line )]; } sub gpiointerrupt_start { my ($kernel, $heap) = @_[KERNEL, HEAP]; #if (cfg->{poesession_mode} eq 'client') #{ # log_enabled && logline "ignored: delayed, poeserver-configured start is used in poesession mode '%s'", cfg->{poesession_mode}; # # return; #} #$heap->{gpiointerrupt_start_executed} = 1; $kernel->yield('gpiointerrupt_init'); } sub gpiointerrupt_stop { my $kernel = $_[KERNEL]; $kernel->yield(wheelrun_kill => { wheel_name => 'gpiointerrupt' }); } sub gpiointerrupt_init { my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0]; log_enabled && logline 'event fired'; my @pins = (); if (cfg->{interrupt_gpio_pins} && ref cfg->{interrupt_gpio_pins} eq 'ARRAY') { @pins = (@pins, @{cfg->{interrupt_gpio_pins}}); } #if ($args->{pins} && ref $args->{pins} eq 'ARRAY') #{ # @pins = (@pins, @{$args->{pins}}); #} if ($heap->{tcpclient_dynamic_gpio_pins}->{in_interrupt} && ref $heap->{tcpclient_dynamic_gpio_pins}->{in_interrupt} eq 'HASH') { @pins = (@pins, keys %{$heap->{tcpclient_dynamic_gpio_pins}->{in_interrupt}}); } if (cfg->{interrupt_gpio_pins_extra} && ref cfg->{interrupt_gpio_pins_extra} eq 'ARRAY') { @pins = (@pins, @{cfg->{interrupt_gpio_pins_extra}}); } if (@pins) { my $prog = [ 'util/gpio-irq-event', '-n', join(' ', sort {$a <=> $b} @pins), ]; log_enabled && logline 'wheelrun_exec'; $kernel->yield(wheelrun_exec => { prog => $prog, name => 'gpiointerrupt', stdout_event => 'gpiointerrupt_stdout_line', stderr_event => 'gpiointerrupt_stderr_line', }); } } sub gpiointerrupt_restart { my ($kernel, $heap) = @_[KERNEL, HEAP]; log_enabled && logline "event fired, gpiointerrupt_start_executed = '%s'", $heap->{gpiointerrupt_start_executed} || 'n/a'; if ($heap->{wheel_run}->{children_by_name}->{gpiointerrupt}) { $heap->{wheelrun_gpiointerrupt_restartmode} = 1; $kernel->yield('gpiointerrupt_stop'); } else { #$kernel->yield(gpiointerrupt_init => #{ # pins => [ keys %{$heap->{tcpclient_dynamic_gpiointerrupt_pins}} ], #}); $kernel->yield('gpiointerrupt_init'); } } sub gpiointerrupt_childexit { my ($kernel, $heap) = @_[KERNEL, HEAP]; if ($heap->{wheelrun_gpiointerrupt_restartmode}) { delete $heap->{wheelrun_gpiointerrupt_restartmode}; #$kernel->yield(gpiointerrupt_init => #{ # pins => [ keys %{$heap->{tcpclient_dynamic_gpiointerrupt_pins}} ], #}); $kernel->yield('gpiointerrupt_init'); } else { unless ($heap->{shutdown}) { $kernel->yield(shutdown => 'gpiointerrupt child abnormally terminated'); } } } sub gpiointerrupt_stdout_line { my ($kernel, $session, $heap, $line) = @_[KERNEL, SESSION, HEAP, ARG0]; my ($ts, $ts_last, $pin, $level); if ($line =~ /^\s*gpiointerrupt\s+ts=(\d+\.\d+)\s+ts_last=(\d+\.\d+)\s+pin=(\d+)\s+level=(\d+)\s*$/i) { $ts = $1; $ts_last = $2; $pin = $3; $level = $4; } else { log_enabled && logline "invalid line = '%s'", $line; return; } $heap->{gpiointerrupt}->{$pin} = { level => $level, ts => $ts, }; my $output_per_target; $output_per_target->{tcpserver} = sprintf "GPIOINTERRUPT %s %s %s=%s", $ts, $ts_last, $pin, $level; $output_per_target->{tcpclient} = sprintf "%s %s", POECLIENT_CMD_PREFIX, $line; #foreach my $target (qw(tcpserver tcpclient)) #{ # next unless exists $heap->{$target} && exists $heap->{$target}->{connections}; # # # my $tcpserver = $target eq 'tcpserver'; # my $tcpclient = $target eq 'tcpclient'; # # # my $output; # # # if ($tcpserver) # { # $output = sprintf "WATCH %s=%s", # $pin, # $level; # } # elsif ($tcpclient) # { # $output = sprintf "%s %s", # POECLIENT_CMD_PREFIX, # $line; # } # else # { # next; # } # # # foreach my $wheel_id (keys %{$heap->{$target}->{connections}}) # { # next if $tcpserver && !$heap->{$target}->{connections}->{$wheel_id}->{gpio_watch}; # # # next unless $heap->{$target}->{connections}->{$wheel_id}->{wheel}; # # # $kernel->call($session => sprintf("%s_output", $target) => # { # wheel_id => $wheel_id, # output => $output, # use_flush => 1, # }); # } #} $kernel->call($session => wheelrun_send_network_reply => { output_per_target => $output_per_target, }); #log_enabled && logline "gpio interrupt %s=%s", # $pin, # $level; log_enabled && logline "gpiointerrupt %s=%s", $pin, $level; } sub gpiointerrupt_stderr_line { my ($kernel, $session, $heap, $line) = @_[KERNEL, SESSION, HEAP, ARG0]; log_enabled && logline "line = '%s'", $line; return unless $line =~ /^ready$/i; $line = lc $line; my $output_per_target; $output_per_target->{tcpserver} = sprintf "GPIOINTERRUPT %s", $line; $output_per_target->{tcpclient} = sprintf "%s gpiointerrupt %s", POECLIENT_CMD_PREFIX, $line; #my $output = sprintf "%s gpiointerrupt %s", # POECLIENT_CMD_PREFIX, # lc $line; # # #foreach my $wheel_id (keys %{$heap->{tcpclient}->{connections}}) #{ # next unless $heap->{tcpclient}->{connections}->{$wheel_id}; # # # next unless $heap->{tcpclient}->{connections}->{$wheel_id}->{wheel}; # # # $kernel->yield(tcpclient_output => # { # wheel_id => $wheel_id, # output => $output, # }); #} $kernel->call($session => wheelrun_send_network_reply => { output_per_target => $output_per_target, }); } 1;