+sub decode0
+{
+ my ($self, $type, $data) = @_;
+
+ my %r;
+ $r{type} = $type;
+
+ ($r{id}, $r{schema}, $r{version}, $r{revision}) = eval {unpack 'l>/a N l>/a l>/a', $data};
+ if ($@) {
+ dbg($@);
+ } else {
+ my $j = $json->encode(\%r);
+ dbg($j);
+ }
+
+}
+
+sub decode1
+{
+ my ($self, $type, $data) = @_;
+
+ my %r;
+ $r{type} = $type;
+
+ (
+ $r{id}, $r{qrg}, $r{mode}, $r{dxcall}, $r{report}, $r{txmode},
+ $r{txenabled}, $r{txing}, $r{decoding}, $r{rxdf}, $r{txdf},
+ $r{decall}, $r{degrid}, $r{dxgrid}, $r{txwatch}, $r{som},
+ $r{fast}, $r{qrgtol}, $r{trperiod}, $r{confname}
+
+ ) = eval {unpack 'l>/a Q> l>/a l>/a l>/a l>/a C C C l> l> l>/a l>/a l>/a C l>/a c l> l> l>/a', $data};
+ if ($@) {
+ dbg($@);
+ } else {
+ my $j = $json->encode(\%r);
+ dbg($j);
+ }
+}
+
+sub decode2
+{
+ my ($self, $type, $data) = @_;
+
+ my %r;
+ $r{type} = $type;
+
+ (
+ $r{id}, $r{new}, $r{tms}, $r{snr}, $r{deltat}, $r{deltaqrg}, $r{mode}, $r{msg}, $r{lowconf}, $r{offair}
+ ) = eval {unpack 'l>/a C N l> d> N l>/a l>/a C C ', $data};
+ if ($@) {
+ dbg($@);
+ } else {
+ my $j = $json->encode(\%r);
+ dbg($j);
+ }
+}
+
+use constant NAME => 0;
+use constant SORT => 1;
+use constant FUNCTION => 3;
+
+sub unpack
+{
+ my $self = shift;
+ my $data = shift;
+ my $spec = shift;
+ my $end = shift;
+
+ my $pos = $self->{unpackpos} || 0;
+ my $out = $pos ? '{' : '';
+
+ foreach my $r (@$spec) {
+ my $v = 'NULL';
+ my $l;
+ my $alpha;
+
+ last if $pos >= length $data;
+
+ if ($r->[SORT] eq 'int32') {
+ $l = 4;
+ ($v) = unpack 'l>', substr $data, $pos, $l;
+ } elsif ($r->[SORT] eq 'int64') {
+ $l = 8;
+ ($v) = unpack 'Q>', substr $data, $pos, $l;
+ } elsif ($r->[SORT] eq 'int8') {
+ $l = 1;
+ ($v) = unpack 'c', substr $data, $pos, $l;
+ } elsif ($r->[SORT] eq 'bool') {
+ $l = 1;
+ ($v) = unpack 'c', substr $data, $pos, $l;
+ $v += 0;
+ } elsif ($r->[SORT] eq 'float') {
+ $l = 8;
+ ($v) = unpack 'd>', substr $data, $pos, $l;
+ $v = sprintf '%.3f', $v;
+ $v += 0;
+ } elsif ($r->[SORT] eq 'utf') {
+ $l = 4;
+ ($v) = unpack 'l>', substr $data, $pos, 4;
+ if ($v > 0) {
+ ($v) = unpack "a$v", substr $data, $pos;
+ $l += length $v;
+ ++$alpha;
+ } else {
+ next; # null alpha field
+ }
+ }
+
+ $out .= qq{"$r->[NAME]":};
+ $out .= $alpha ? qq{"$v"} : $v;
+ $out .= ',';
+ $pos += $l;
+ }
+
+ if ($end) {
+ $out =~ s/,$//;
+ $out .= '}';
+ delete $self->{unpackpos};
+ } else {
+ $self->{unpackpos} = $pos;
+ }
+ return $out;
+}
+