use inc::Module::Install;
name 'CWMP';
-version '0.10';
+version '0.11';
license 'GPL';
requires 'Net::Server';
requires 'HTTP::Daemon';
requires 'Cwd';
requires 'File::Slurp';
requires 'DBM::Deep';
+requires 'Clone'; # CWMP::Store::DBMDeep
requires 'Getopt::Long';
#requires 'Term::Shelly' => '0.03';
requires 'Module::Pluggable';
}
$self->state( $state );
- $self->store->update_state( ID => $state->{ID}, $state );
+ $self->store->update_state( $state );
} else {
$sock->send( "Set-Cookie: ID=" . $state->{ID} . "; path=/\r\n" ) if ( $state->{ID} );
- my $uid = $self->store->ID_to_uid( $state->{ID}, $state );
+ my $uid = $self->store->state_to_uid( $state );
my $queue = CWMP::Queue->new({
id => $uid,
=head2 update_state
- $store->update_state( ID => $ID, $state );
- $store->update_state( uid => $uid, $state );
+ $store->update_state( $state );
=cut
sub update_state {
my $self = shift;
- my ( $k, $v, $state ) = @_;
+ my ( $state ) = @_;
- confess "need ID or uid" unless $k =~ m/^(ID|uid)$/;
- confess "need $k value" unless $v;
confess "need state" unless $state;
- warn "#### update_state( $k => $v, ", dump( $state ), " )\n" if $self->debug > 4;
-
- my $uid;
-
- if ( $k eq 'ID' ) {
- if ( $uid = $self->ID_to_uid( $v, $state ) ) {
- # nop
- } else {
- warn "## no uid for $v, first seen?\n" if $self->debug;
- return;
- }
- } else {
- $uid = $v;
- }
+ my $uid = $self->state_to_uid( $state );
+ warn "#### update_state( ", dump( $state ), " ) for $uid\n" if $self->debug > 2;
$self->current_store->update_uid_state( $uid, $state );
}
=head2 get_state
- my $state = $store->get_state( ID => $ID );
- my $state = $store->get_state( uid => $uid );
+ my $state = $store->get_state( $uid );
Returns normal unblessed hash (actually, in-memory copy of state in database).
sub get_state {
my $self = shift;
- my ( $k, $v ) = @_;
- confess "need ID or uid" unless $k =~ m/^(ID|uid)$/;
- confess "need $k value" unless $v;
-
- warn "#### get_state( $k => $v )\n" if $self->debug > 4;
+ my ( $uid ) = @_;
+ confess "need uid" unless $uid;
- my $uid;
-
- if ( $k eq 'ID' ) {
- if ( $uid = $self->ID_to_uid( $v ) ) {
- # nop
- } else {
- warn "## no uid for $v so no state!\n" if $self->debug;
- return;
- }
- } else {
- $uid = $v;
- }
+ warn "#### get_state( $uid )\n" if $self->debug > 4;
return $self->current_store->get_state( $uid );
return @cpes;
}
-=head2 ID_to_uid
+=head2 state_to_uid
- my $CPE_uid = $store->ID_to_uid( $ID, $state );
+ my $CPE_uid = $store->ID_to_uid( $state );
It uses C<< DeviceID.SerialNumber >> from C<Inform> message as unique ID
for each CPE.
=cut
-my $session;
-
-sub ID_to_uid {
+sub state_to_uid {
my $self = shift;
- my ( $ID, $state ) = @_;
-
- confess "need ID" unless $ID;
-
- warn "#### ID_to_uid",dump( $ID, $state ),$/ if $self->debug > 4;
-
- warn "##### current session = ",dump( $session ), $/ if $self->debug > 5;
-
- $session->{ $ID }->{last_seen} = time();
-
- my $uid;
+ my ( $state ) = @_;
- if ( $uid = $session->{ $ID }->{ ID_to_uid } ) {
- return $uid;
- } elsif ( $uid = $state->{DeviceID}->{SerialNumber} ) {
- warn "## created new session for $uid session $ID\n" if $self->debug;
- $session->{ $ID } = {
- last_seen => time(),
- ID_to_uid => $uid,
- };
- return $uid;
- } else {
- warn "## can't find uid for ID $ID, first seen?\n";
- }
+ warn "#### state_to_uid",dump( $state ),$/ if $self->debug > 4;
- # TODO: expire sessions longer than 30m
+ my $uid = $state->{DeviceID}->{SerialNumber} ||
+ confess "no DeviceID.SerialNumber in ",dump( $state );
- return;
+ return $uid;
}
1;
use DBM::Deep;
use Data::Dump qw/dump/;
+use Clone qw/clone/;
use Carp qw/confess/;
=head1 NAME
sub update_uid_state {
my ( $self, $uid, $state ) = @_;
+ my $data = clone( $state );
+
if ( my $o = $db->get( $uid ) ) {
warn "## update state of $uid\n" if $debug;
- return $o->import( $state );
+ $o->import( $data );
} else {
warn "## create new state for $uid\n" if $debug;
- return $db->put( $uid => $state );
+ $db->put( $uid => $data );
}
}
my ( $self, $uid ) = @_;
if ( my $state = $db->get( $uid ) ) {
- return $state->export;
- } else {
- return;
+ $state->export;
}
}
my $cpe_faulty;
my $serial2ip = {
- 'CP0636JT3SH' => '192.168.1.242',
- 'CP0644JTHJ4' => '192.168.1.253',
+ 'CP0636JT3SH' => '10.0.0.1',
+ 'CP0644JTHJ4' => '10.0.0.2',
+ 'CP0624BH55U' => '10.0.0.3',
};
my ( $last_ip, $last_serial );
+=head2 state2serial
+
+ my $serial = state2serial( $state );
+
+=cut
+
sub state2serial {
my $state = shift;
return ( $serial, $ip );
}
+=head2 add_triggers
+
+Install all custom triggers
+
+ CWMP::Vendor->add_triggers;
+
+=cut
+
sub add_triggers {
warn __PACKAGE__, "->add_triggers\n" if $debug;
--- /dev/null
+:software upgrade
my $debug = shift @ARGV;
-use Test::More tests => 34;
+use Test::More tests => 32;
use Data::Dump qw/dump/;
use Cwd qw/abs_path/;
use lib 'lib';
},
};
- cmp_ok( $store->ID_to_uid( 42, $state ), 'eq', 123456, 'ID_to_uid' );
+ cmp_ok( $store->state_to_uid( $state ), 'eq', 123456, 'state_to_uid' );
- ok( $store->update_state( ID => 42, $state ), 'update_state new' );
+ ok( $store->update_state( $state ), 'update_state new' );
- ok( my $store_state = $store->get_state( ID => '42'), 'get_state ID' );
+ ok( my $store_state = $store->get_state( 123456 ), 'get_state' );
- is_deeply( $store_state, $state, 'state ID' );
+ isa_ok( $state, 'HASH' );
+ isa_ok( $store_state, 'HASH' );
- ok( $store_state = $store->get_state( uid => 123456 ), 'get_state uid' );
+ if ( $debug ) {
- is_deeply( $store_state, $state, 'state ID same as uid' );
+ diag "store_state = ",dump( $store_state );
+
+ }
- ok( $store->update_state( ID => 42, { baz => 12345 } ), 'update_state existing' );
+ is_deeply( $state, $store_state, 'state ID same as uid' );
- $state->{baz} = 12345;
+ ok( $store->update_state( {
+ DeviceID => {
+ SerialNumber => 123456,
+ },
+ baz => 12345
+ } ), 'update_state existing' );
- is_deeply( $store->get_state( ID => 42 ), $state, 'get_state ID' );
+ $state->{baz} = 12345;
- is_deeply( $store->get_state( uid => 123456 ), $state, 'get_state uid' );
+ is_deeply( $store->get_state( 123456 ), $state, 'get_state' );
is_deeply( [ $store->all_uids ], [ 123456 ], 'all_uids' );
- ok( $store->update_state( ID => 11, { DeviceID => { SerialNumber => 99999 } } ), 'new device' );
+ ok( $store->update_state( { DeviceID => { SerialNumber => 99999 } } ), 'new device' );
is_deeply( [ $store->all_uids ], [ 123456, 99999 ], 'all_uids' );