Device-CableModem-Motorola-SB4200

 view release on metacpan or  search on metacpan

lib/Device/CableModem/Motorola/SB4200.pm  view on Meta::CPAN

    my $name  = shift || croak 'Config name not present';
    my $value = shift;
    croak 'Config value not present' if not defined $value;
    my $raw   = $self->_get( $self->{page_conf} );
    my $form  = HTML::Form->parse( $raw, $self->{page_conf} );

    my $input;
    foreach my $e ( @{ $form->inputs } ) {
        next if $e->type eq 'submit' || $e->name ne $name;
        if ( my @possible = $e->possible_values ) {
            my %valid = map { ( (defined $_ ? $_ : 0), 1 ) } @possible;
            if ( ! $valid{ $value } ) {
                croak "The value ($value) for $name is not valid. "
                     .'You should select one of  these: ' . join q{ }, keys %valid;
            }
        }
        $input = $e;
        last;
    }

    croak "$name is not a valid configuration option" if ! $input;

    # good to go
    $input->value($value);
    my $req = $form->click() || croak "Saving $name=$value failed";
    $req->uri( $self->{page_conf} );
    my $response = $self->_req( $req );
    return;
}

sub addresses {
    my $self = shift;
    my $raw  = $self->_get( $self->{page_addr} );

    my(%list, @mac);

    my $list = sub {
        my ( $id, $line, $cols, $udata ) = @_;
        (my $name = lc $cols->[0]) =~ tr/ /_/;
        $list{ $name } = $cols->[1];
        return;
    };

    my $mac = sub {
        my ( $id, $line, $cols, $udata ) = @_;
        my($num, $addr, $status) = @{ $cols };
        push @mac, { address => $addr, status => $status };
        return;
    };

    HTML::TableParser->new(
        [
            { id => 1.4, row  => $list },
            { id => 1.5, row  => $mac  },
        ],
        { Decode => 1, Trim => 1, Chomp => 1 },
    )->parse( $raw );

    my $di = $list{dhcp_information};
    $list{dhcp_information} = {};
    foreach my $info ( split m{ \r?\n }xmsi, $di ) {
        my($name, $value)        = split m{ : \s+ }xms, $info;
        my($num,  $type, $other) = split m{   \s+ }xms, $value;
        my $has_type = defined $num && defined $type && ! defined $other;
        $list{dhcp_information}->{ $name } = $has_type
                                           ? { value => $num, type => $type }
                                           : { value => $value }
                                           ;
    }

    my %rv = (
        %list,
        known_cpe_mac_addresses => [ @mac ],
    );

    return %rv;
}

sub signal {
    my $self = shift;
    my $raw  = $self->_get( $self->{page_signal} );

    # remove junk info, otherwise it will not be parsed correctly
    $raw =~ s{
        <table \s+ WIDTH="300" .+? >
            .+?
            \QThe Downstream Power Level reading is\E
            .+?
        </table>
    }{}xmsi;

    my(%down, %up);

    my $down_row = sub {
        my ( $id, $line, $cols, $udata ) = @_;
        (my $name = lc $cols->[0]) =~ tr/ /_/;
        $down{ $name } = $cols->[1];
        return;
    };

    my $up_row = sub {
        my ( $id, $line, $cols, $udata ) = @_;
        (my $name = lc $cols->[0]) =~ tr/ /_/;
        $up{ $name } = $cols->[1];
        return;
    };

    HTML::TableParser->new(
        [
            { id => 1.4, row  => $down_row },
            { id => 1.5, row  => $up_row   },
        ],
        { Decode => 1, Trim => 1, Chomp => 1 },
    )->parse( $raw );

    foreach my $v (
        \@up{   qw( frequency power_level symbol_rate           ) },
        \@down{ qw( frequency power_level signal_to_noise_ratio ) },
    ) {
        my($value, $unit, $status) = split m{\s+}xms, ${$v};
        ${$v} = {
            value  => $value,
            unit   => $unit,
        };
        ${$v}->{status} = $status if defined $status;
    }

    my %rv = (
        upstream   => { %up },
        downstream => { %down },
    );

    return %rv;
}

sub status {
    my $self = shift;
    my $raw  = $self->_get( $self->{page_status} );
    my %rv;

    my $cb_row = sub {
        my ( $id, $line, $cols, $udata ) = @_;
        (my $name = lc $cols->[0]) =~ tr/ /_/;
        $rv{ $name } = $cols->[1];
        return;
    };

    HTML::TableParser->new(
        [
            { id => 1.4, row  => $cb_row                 },
            { id => 1  , cols => qr/(?:Task|Status)/xmsi },
        ],
        { Decode => 1, Trim => 1, Chomp => 1 },
    )->parse( $raw );

    return %rv;
}

sub logs {
    my $self = shift;
    my $raw  = $self->_get( $self->{page_logs} );
    my @logs;

    my $cb_row = sub {
        my ( $id, $line, $cols, $udata ) = @_;
        push @logs, {
            time     => shift @{ $cols },
            priority => shift @{ $cols },
            code     => shift @{ $cols },
            message  => shift @{ $cols },
        };
        my $cur = $logs[-1];
        my($pn,$ps) = split m/\-/xms, $cur->{priority};
        $cur->{priority} = {
            code   => $pn,
            string => $ps,
        };
        $cur->{time} = undef if $cur->{time} eq '************';
        return;
    };

    HTML::TableParser->new(
        [
            { id => 1.4, row  => $cb_row                                },
            { id => 1  , cols => qr/(?:Time|Priority|Code|Message)/xmsi },
        ],
        { Decode => 1, Trim => 1, Chomp => 1 },
    )->parse( $raw );

    return @logs;
}

sub versions {
    my $self = shift;
    my $raw  = $self->_get( $self->{page_help} );
    my $v;
    if ( $raw =~ m{<td.+?>(.+?version.+?)</td>}xmsi ) {
       ($v = $1) =~ s{<br>}{}xmsig;
    }
    else {
       croak "Can not get version from $self->{page_help} output: $raw"
    };
    my %rv;
    foreach my $vs ( split m/ \r? \n /xms, $self->_trim( $v ) ) {
        my($name, $value) = split m/ : \s+ /xms, $vs;
          ($name, undef)  = split m/   \s+ /xms, $name;
        $rv{ lc $name }   = $value;
    }
    my @soft = split m/ \- /xms, $rv{software};
    $rv{software} = {
        model   => shift @soft,
        version => shift @soft,
        string  => join( q{-}, @soft ),
    };
    return %rv;
}

sub _trim {
    my $self = shift;
    my $s = shift;
    $s =~ s{ \A \s+    }{}xmsg;
    $s =~ s{    \s+ \z }{}xmsg;
    return $s;
}

sub agent {
    my $self = shift;
    my $ua   = LWP::UserAgent->new;
    $ua->agent($AGENT);
    $ua->timeout( UA_TIMEOUT );
    return $ua;
}

sub _get {
    my $self = shift;
    my $url  = shift;
    my $r    = $self->agent->get($url);

    if ( $r->is_success ) {
        my $raw = $r->decoded_content;
        HTTP::Error::NotFound->throw(
            "The address $url is invalid. Server returned a 404 error"
        ) if $raw =~ RE_404;
        return $raw;
    }

    return  HTTP::Error::Connection->throw(
                'GET request failed: ' . $r->as_string
            );
}

sub _req {
    my $self = shift;
    my $req  = shift;
    my $r    = $self->agent->request($req);

    if ( $r->is_success ) {
        my $raw = $r->decoded_content;
        HTTP::Error::NotFound->throw(
            'The request is invalid. Server returned a 404 error'
        ) if $raw =~ RE_404;
        return $raw;
    }

    return  HTTP::Error::Connection->throw(
                'HTTP::Request failed: ' . $r->as_string
            );
}



( run in 0.495 second using v1.01-cache-2.11-cpan-71847e10f99 )