warn "## protocol = ",dump( $protocol ) if $debug;
-my $pkg_nr = 0;
-
-sub protocol_decode {
+sub print_hex {
my ( $up_down, $hex ) = @_;
-warn "up/down: $up_down hex = ",dump($hex);
-
-my $bin = join('', map { chr(hex($_)) } split(/\s+/,$hex));
-
-warn "bin = ", dump($bin);
-
-if ( $debug ) {
- open(my $dump, '>', "/dev/shm/zc.$pkg_nr.$up_down");
- print $dump $bin;
- close($dump);
- $pkg_nr++;
-}
-
-my $cksum = substr($bin, -2, 2);
-
-if ( my $crc = modbus_crc16( substr($bin,0,-2) ) ) {
- if ( $crc ne $cksum ) {
- warn "CRC error, got ",unpack('H*',$crc), " expected ", unpack('H*',$cksum), "\n";
- } else {
- warn "CRC OK ", unpack('H*',$crc), "\n";
- }
-}
-
-my ( $header, $ver, $function_code, $len ) = unpack("CCCv", $bin);
-
-my $data = substr($bin,5,-2);
-
-warn "header = $header ver = $ver function_code = $function_code len = $len == ",length($data), " data = ",dump($data), " cksum = ", unpack('H*',$cksum);
-
-warn "header corrupt: $header" if $header != 0x5a;
-warn "invalid length $len got ",length($data) if length($data) != $len;
-
-my $function_code_upstream = {
-0x07 => 'Upstream Heartbeat Frame',
-0x08 => 'Upstream alarm frame',
-0x03 => 'Upstream Read Parameter Frame',
-0x06 => 'Upstream return write parameter frame',
-};
-
-my $function_code_downstream = {
-0x03 => 'Downstream read parameter frame',
-0x06 => 'Downstream write parameter frame',
-};
-
-print "Function code: $function_code ",
- $up_down eq 'up' ? $function_code_upstream->{ $function_code } : $function_code_downstream->{ $function_code }, "\n";
-
-
-
+ warn "hex = $hex\n";
-while ( $data ) {
- my $hex = unpack('H*', $data);
- $hex =~ s/(..)/$1 /g;
- warn "XXX data = $hex\n";
+ my $raw = join('', map { chr(hex($_)) } split(/\s+/,$hex));
- my $data_id = unpack( 'C', substr($data,0,1) );
- if ( ! exists( $protocol->{$data_id}->{description} ) ) {
- my $len = unpack('C', substr($data,1,1));
- printf "ERROR: no description for data_id %d 0x%2x len %d [%s] SKIPPING!\n", $data_id, $data_id, $len, unpack('H*', substr($data,2,$len));
- $data = substr($data,2 + $len);
- next;
- }
- my $data_id_desc = $protocol->{$data_id}->{description};
- my $pack_fmt = $protocol->{$data_id}->{pack_fmt} || die "can't find pack_fmt for data_id $data_id";
-
- my $data_range;
- my $data_len;
-
- if ( $data_id == 0x00 ) {
- # sequence number
-
- $data_range = substr($data,2,4);
- $data = substr($data,6);
-
- } elsif ( $up_down eq 'down' && $function_code == 0x03 ) {
- # type A
-
- $data_range = substr($data,0,1);
- $data = substr($data,1);
-
- } elsif ( $up_down eq 'up' && ( $function_code == 0x07 || $function_code == 0x08 || $function_code == 0x03 ) ) {
- # type B
-
- $data_len = unpack('C', substr($data,1,1));
- $data_range = substr($data,2, $data_len);
-
- $data = substr($data,2 + $data_len);
-
- } elsif ( $up_down eq 'down' && $function_code == 0x06 ) {
- # type B
+ warn "raw = ", hex_dump($raw);
- $data_len = unpack('C', substr($data,1,1));
- $data_range = substr($data,2, $data_len);
+ my $hash = protocol_decode( $up_down, $raw );
- $data = substr($data,2 + $data_len);
+ warn "hash = ",dump($hash);
- } elsif ( $up_down eq 'up' && $function_code == 0x06 ) {
- # type C
+ my $function_code = $hash->{function_code} || die "no function_code";
+ my $fc_desc = $function_code_description->{$up_down}->{$function_code} || die "no function_code_description for $up_down $function_code";
+ print " function_code=$function_code ",
+ $fc_desc,
+ " ver=", $hash->{ver},
+ " len=", $hash->{len},
+ "\n";
- # FIXME check first byte?
- my $data_range = substr($data,1,1);
-
- $data = substr($data,2);
-
- } else {
- warn "ERROR unknown function_code = $function_code";
- }
-
- my @v = unpack($pack_fmt, $data_range);
-
- my $v = join(' ', @v);
-
- if ( $data_id == 0x0c ) {
- $v = $v / 100;
- } elsif ( $data_id == 0x0d ) {
- $v = $v / 100;
+ foreach my $data_id ( @{ $hash->{data_id_order} } ) {
+ print join(" | ",
+ $hash->{up_down},
+ unpack('H*', chr($data_id)),
+ $protocol->{$data_id}->{description},
+ $hash->{data_id}->{$data_id},
+ "hex:" . unpack('H*', $hash->{data_range}->{$data_id}),
+ "len:" . $hash->{data_len}->{$data_id},
+ "fmt:" . $protocol->{$data_id}->{pack_fmt},
+ "range:" . $protocol->{$data_id}->{range},
+ "remark:" . $protocol->{$data_id}->{remark}
+ ),"\n";
}
-
- my $description = $protocol->{$data_id}->{description} || die "can't find description for data_id $data_id";
- print "$up_down | $data_id 0x",unpack('H*', chr($data_id))," $data_len | $description | v=$v | hex:", unpack('H*', $data_range), " fmt:$pack_fmt | range:",$protocol->{$data_id}->{range}, " | remark:", $protocol->{$data_id}->{remark},"\n";
+ print "\n";
}
-
-} # protocol_decode
-
my $raw;
my ( $timestamp, $sensor, $imei, $up_down );
my $stat;
if ( $raw ) {
$raw =~ s{^\s+}{}; # strip leading spaces
print "## $timestamp $sensor $imei $up_down $raw\n";
- protocol_decode( $up_down, $raw );
+ print_hex( $up_down, $raw );
$raw = '';
}
( $timestamp, $sensor, $imei, $up_down ) = ( $1, $2, $3, $4 );
if ( $raw ) {
$raw =~ s{^\s+}{}; # strip leading spaces
print "## $timestamp $sensor $imei $up_down $raw\n";
- protocol_decode( $up_down, $raw );
+ print_hex( $up_down, $raw );
}
print "stat = ",dump($stat), "\n";