package POEDaemon::TCPServer::Main::Cmds::POEClient; use strict; use warnings FATAL => 'all'; no warnings 'redefine'; use POE; use POEDaemon; sub states { return $_[0], [qw( tcpserver_client_commands_poeclient )]; } sub tcpserver_client_commands_poeclient { my ($kernel, $session, $heap, $args) = @_[KERNEL, SESSION, HEAP, ARG0]; return unless ref $args eq 'HASH'; my $wheel_id = $args->{wheel_id} || return; my $input = $args->{input}; return unless defined $input; my $client = $heap->{tcpserver}->{connections}->{$wheel_id}; return unless $client && $client->{poeclient}; my $sock_wheel_id = $client->{sock_wheel_id}; my $cn = $client->{cn} || return; my (@out, $no_output_log); return unless $input =~ s/^\s*poeclient\s*//i; if ($input =~ /^\s*ready(?:\s+(.{0,1024}))?\s*$/i) { my $ready_args = $1; if (defined $ready_args) { foreach (split /\s+/, $ready_args) { next unless /^\s*(allowed_(?:pwm|adc|gpio))\s*=\s*([\dab,]{1,512})\s*$/i; my $type = lc $1; my $items = $2; foreach my $item (split ',', $items) { $client->{poeclient_readyargs}->{$type}->{$item} = 1; } } } $client->{pins_configured} = 1; my $pinmap = { in => {}, in_interrupt => {}, out => {}, out_ws2801 => [], }; my $out_ws2801_pincfg = cfg->{ws2801_pincfg}->{$cn}; if (ref $out_ws2801_pincfg eq 'ARRAY' && $#$out_ws2801_pincfg == 1) { $pinmap->{out_ws2801} = $out_ws2801_pincfg; } foreach my $curr_key (keys %{cfg->{eventmap}}) { next unless ref cfg->{eventmap}->{$curr_key} eq 'HASH'; my ($c_i_type, $c_i_cn, $c_i_pin) = split ':', $curr_key; $pinmap->{in}->{$c_i_pin} = 1 if $c_i_type eq 'remote-gpio' && $c_i_cn eq $cn; $pinmap->{in_interrupt}->{$c_i_pin} = 1 if $c_i_type eq 'remote-gpiointerrupt' && $c_i_cn eq $cn; foreach my $curr_key2 (keys %{cfg->{eventmap}->{$curr_key}}) { next unless ref cfg->{eventmap}->{$curr_key}->{$curr_key2} eq 'ARRAY'; foreach my $curr_val (@{cfg->{eventmap}->{$curr_key}->{$curr_key2}}) { next unless ref $curr_val eq 'ARRAY'; my ($c_o_type, $c_o_cn, $c_o_pin) = split ':', $curr_val->[0]; $pinmap->{out}->{$c_o_pin} = 1 if $c_o_type eq 'remote-gpio' && $c_o_cn eq $cn; } } } my @pinmap_args; foreach (qw(in in_interrupt out out_ws2801)) { if ($_ eq 'out_ws2801') { next unless @{$pinmap->{$_}}; push @pinmap_args, sprintf "%s=%s", $_, join(',', @{$pinmap->{$_}}); } else { next unless %{$pinmap->{$_}}; push @pinmap_args, sprintf "%s=%s", $_, join(',', sort {$a <=> $b} keys %{$pinmap->{$_}}); } } push @out, sprintf "pins %s", join ' ', @pinmap_args if @pinmap_args; push @out, 'loadavg'; push @out, 'sysuptime'; push @out, 'ntpsyspeer'; push @out, 'sysversion'; push @out, 'rootfs'; push @out, 'poeinittime'; push @out, 'sysinittime'; push @out, 'adc all'; push @out, 'systemupgrade status'; push @out, 'i2csysutil'; push @out, 'ubootversion'; push @out, 'ubootbootcount'; push @out, 'compilerversion'; } elsif ($input =~ /^\s*pong(?:\s+(?:\d{10}\.\d{6}))?\s*$/i) { } elsif ($input =~ /^\s*gpio\s+(\d{1,3})\s*=\s*([01])\s*$/i) { my $pin = $1; my $value = $2; $kernel->call($session => eventsystem_input => { type => 'remote-gpio', cn => $cn, pin => $pin, value => $value, time => time_hires, }); } elsif ($input =~ /^\s*gpiointerrupt\s+ts=(\d+\.\d+)\s+ts_last=(\d+\.\d+)\s+pin=(\d+)\s+level=([01])\s*$/i) { my $ts = $1; my $ts_last = $2; my $pin = $3; my $level = $4; $kernel->call($session => eventsystem_input => { type => 'remote-gpiointerrupt', cn => $cn, pin => $pin, value => $level, time => time_hires, }); } elsif ($input =~ /^\s*pins\s+(.{1,1024})\s*$/i) { my $pinlist = $1; foreach (split /\s+/, $pinlist) { next unless /^\s*(in|in_interrupt|out|out_ws2801)\s*=\s*([\d,]{1,512})\s*$/i; my $type = lc $1; my $pins = $2; foreach my $pin (split ',', $pins) { if ($type eq 'out_ws2801') { push @{$client->{poeclient_pins}->{$type}}, $pin; } else { $client->{poeclient_pins}->{$type}->{$pin} = 1; } } } } elsif ($input =~ /^\s*gpiochange\s+ready(?:nochange)?\s*$/i) { push @out, 'connectedgpiopinon'; foreach my $pin (keys %{$heap->{eventsystem}->{output}->{'remote-gpio'}->{$cn}}) { my $value = $heap->{eventsystem}->{output}->{'remote-gpio'}->{$cn}->{$pin}->{value}; unless ($client->{poeclient_readyargs}->{allowed_gpio}->{$pin}) { delete $heap->{eventsystem}->{output}->{'remote-gpio'}->{$cn}->{$pin}; next; } next unless defined $value && $value == GPIO_HIGH; push @out, sprintf "gpio %s=%s", $pin, $value; } } elsif ($input =~ /^\s*gpiopoll\s+ready(?:nochange)?\s*$/i) { } elsif ($input =~ /^\s*gpiointerrupt\s+ready(?:nochange)?\s*$/i) { } elsif ($input =~ /^\s*gpiows2801\s+ready(?:nochange)?\s*$/i) { } elsif ($input =~ /^\s*idle\s*$/i) { } elsif ($input =~ /^\s*loadavg\s+([\d\.\x20]{1,256})\s*$/i) { $client->{poeclient_loadavg} = $1; } elsif ($input =~ /^\s*adc\s+([0-7])\s*=\s*raw:(\d{1,4}),mv:(\d{1,4}\.\d{1,6})\s*$/i) { my $adc = $1; my $raw = $2; my $mv = $3; $client->{adc}->{$adc} = { raw => $raw, mv => $mv, }; $kernel->yield(eventsystem_input => { type => 'remote-adc', cn => $cn, adc => $adc, raw => $raw, mv => $mv, time => time_hires, }); } elsif ($input =~ /^\s*sysuptime\s+(\d+\.\d+)\s*$/i) { $client->{poeclient_sysuptime} = $1; } elsif ($input =~ /^\s*sysversion\s+(.+)\s*$/i) { $client->{poeclient_sysversion} = $1; } elsif ($input =~ /^\s*ntpsyspeer\s+(\S+)\s*$/i) { $client->{poeclient_ntpsyspeer} = $1; } elsif ($input =~ /^\s*systemupgrade\s+status\s+(.{1,1024})\s*$/i) { my $status_args = lc $1; foreach (split /\s+/, $status_args) { next unless /^\s*(active|exitcode)\s*=\s*(\S{1,10})\s*$/i; my $name = $1; my $value = $2; $client->{sprintf "systemupgrade_%s", $name} = $value; } } elsif ($input =~ /^\s*rootfs\s+(\S{1,1024})\s*$/i) { $client->{poeclient_rootfs} = $1; } elsif ($input =~ /^\s*shutdown\s+(.{1,1024})\s*$/i) { $client->{shutdown_reason} = $1; } elsif ($input =~ /^\s*poeinittime\s+(\d{1,20}(?:\.\d{1,20})?)\s*$/i) { $client->{poeclient_poeinittime} = $1; } elsif ($input =~ /^\s*sysinittime\s+(\d{1,20}(?:\.\d{1,20})?)\s*$/i) { $client->{poeclient_sysinittime} = $1; } elsif ($input =~ /^\s*rtt\s+(\d{10}\.\d{6})\s*$/i) { my $response_time = $1; my $rtt = time_hires - $response_time; $client->{poeclient_rtt} = $rtt; if (!defined $client->{poeclient_rtt_max} || $client->{poeclient_rtt_max} < $rtt) { $client->{poeclient_rtt_max} = $rtt; } if (!defined $client->{poeclient_rtt_min} || $client->{poeclient_rtt_min} > $rtt) { $client->{poeclient_rtt_min} = $rtt; } log_enabled && logline "[tcpserver #%s conn #%s%s] client rtt = %.3f ms, one way = ~ %.3f ms", $sock_wheel_id, $wheel_id, (defined $cn ? sprintf " cn %s", $cn : ''), $rtt * 1000, ($rtt / 2) * 1000; } elsif ($input =~ /^\s*i2csysutil\s+(.{1,1024})\s*$/i) { my $i2csysutil_args = $1; foreach (split /\s+/, $i2csysutil_args) { next unless /^\s*(\S{1,256})\s*=\s*(\S{1,256})\s*$/i; my $name = $1; my $value = $2; $client->{i2csysutil}->{$name} = $value; } } elsif ($input =~ /^\s*ubootversion\s+(.{1,1024})\s*$/i) { $client->{poeclient_ubootversion} = $1; } elsif ($input =~ /^\s*ubootbootcount\s+(\d+)\s*$/i) { $client->{poeclient_ubootbootcount} = $1; } elsif ($input =~ /^\s*compilerversion\s+(.{1,1024})\s*$/i) { $client->{poeclient_compilerversion} = $1; } elsif ($input =~ /^\s*(shcppowercontrol)\s+(?:(\w{1,256}|all)(?:\s*=\s*(on|off))?)?\s*$/i) { my $real_cmd = lc $1; my $name = lc($2 || ''); my $value = lc($3 || ''); my @outargs; my $items = {}; foreach (sort keys %{cfg->{eventmap}}) { next unless /^fastcgi:(\w{1,256})$/; my $curr_name = lc $1; my $curr_value = $heap->{eventsystem}->{input}->{fastcgi}->{$curr_name}->{value}; $curr_value = 0 unless defined $curr_value; $curr_value =~ s/^1$/on/; $curr_value =~ s/^0$/off/; $items->{$curr_name} = $curr_value; } if (length $name && $name ne 'all' && length $value) { my $value_conv = $value; $value_conv =~ s/^on$/1/i; $value_conv =~ s/^off$/0/i; $kernel->call($session => eventsystem_input => { type => 'fastcgi', name => $name, value => $value_conv, time => time_hires, }); $items->{$name} = $value; } while (my ($key, $val) = each %$items) { push @outargs, join '=', $key, $val; } push @out, sprintf "%s%s", $real_cmd, (@outargs ? sprintf " %s", join ' ', @outargs : ''); } return unless @out && $client->{wheel}; my $output = join "\n", map { sprintf "%s %s", POESERVER_CMD_PREFIX, $_ } @out; $kernel->call($session => tcpserver_output => { wheel_id => $wheel_id, output => $output, no_log => $no_output_log, }); } 1;