
#####################################################################################################
#####################################################################################################
# helper functions for wp_monitor backend in common use
# (c) 2009 alexander.philipp.lintenhofer
#

#####################################################################################################
# fetchFrameData():
# - isolates raw data from frame
#   frame format: 'FF' DLE STX <DATA> DLE ETX <CRC> 'FF'
#                 DATA ::= <READ>
#                 READ ::= '00 17' XX..XX - bytes
# - checks crc16

sub fetchFrameData
{
    my @frame = @_;

    my $crc1 = sprintf("%02x%02x",@frame[(scalar(@frame)-3)],@frame[(scalar(@frame)-2)]);
    my $crc2 = sprintf("%04x",GetCRC16(@frame));

    if ($crc1 eq $crc2)
    {
        my $headerbytes  = 5; # strip 'FF' DLE STX '00 17'
        my $trailerbytes = 5; # strip DLE ETX <CRC> 'FF'
        my @data;

        for(my $i=0,my $offset=$headerbytes;$offset<(scalar(@frame)-$trailerbytes);$offset++,$i++)
        {
            if (($frame[$offset]==16)&&($frame[$offset+1]==16)) { $offset++; }
            $data[$i] = $frame[$offset];
        }
        return @data;
    }
    else
    {
        print STDERR (localtime().": checksum error (frame:0x".$crc1.", calculated:0x".$crc2."): ");
        foreach (@frame) { printf(STDERR "%02x ",$_); }
        print STDERR "\n";
        return ();
    }
}

#####################################################################################################
# createXML()
# - formats %yield to XML-structure
# - in this file since early declaration for the prototype check is needed
#

sub createXML()
{
    my @dateVal = split('-',$yield{'05.01'}{'val'});
    my @timeVal = split(':',$yield{'05.00'}{'val'});
    my $tsp = mktime($timeVal[2],$timeVal[1],$timeVal[0],$dateVal[2],($dateVal[1]-1),($dateVal[0]+100),0,0,-1);

    my $xml = "<entry datetime='".$yield{'05.01'}{'val'}.'/'.$yield{'05.00'}{'val'}."'>\n";
    $xml .= "\t<tsp_0501_0500>".$tsp."</tsp_0501_0500>\n";
    foreach (sort keys %yield)
    {
        my $menuentry = $_;
        my $name = $yield{$_}{'desc'};

        $name =~ s/\</&lt\;/;
        $name =~ s/\>/&gt\;/;
        $menuentry =~ s/(\d\d)(\.)(\d\d)/m_$1$3/;

        $xml .= "\t<".$menuentry." name='".$name."'>".$yield{$_}{'val'}.'</'.$menuentry.">\n";
    }
    $xml .= "</entry>\n\n";
    return $xml;
}

#####################################################################################################
# hex2float()

sub hex2float1
{
    my $h = $_[0];
    $h = substr($h,6,2).substr($h,4,2).substr($h,2,2).substr($h,0,2);
    return sprintf("%0.1f",unpack("f", pack("I", hex($h))));
}
sub hex2float3
{
    my $h = $_[0];
    $h = substr($h,6,2).substr($h,4,2).substr($h,2,2).substr($h,0,2);
    return sprintf("%0.3f",unpack("f", pack("I", hex($h))));
}

#####################################################################################################
# float2hex()

sub float2hex
{
    my $f = $_[0];
    return unpack("H8",pack("f",$f));
}

#####################################################################################################
# hex2bytearray(): returns array with bytes from given hexword

sub hex2bytearray
{
    my $word  = $_[0];
    my $bytes = $_[1];
    my @arr;

    # shift right...
    for($i=0;$i<$bytes;$i++,$word>>=8) { @arr[($bytes-$i-1)] = $word & 0xFF;}
    return @arr;
}

#####################################################################################################
# GetCRC16(): calculate crc16

sub GetCRC16
{
    # strip header ('FF' DLE STX)...
    # and trailer (DLE ETX <CRC> 'FF')
    my @data = @_[3..(scalar(@_)-6)];

    # fill checksum-fields with 0x00
    $data[++$#data] = 0x00;
    $data[++$#data] = 0x00;

    my $CRCinit = 0x0000;
    my $CRCpoly = 0x8005;

    my $CRCreg = $CRCinit << 8;
    my $PLYreg = $CRCpoly << 8;

    for (my $i=0; $i < scalar(@data); $i++)
    {
        $CRCreg |= $data[$i];

        for (my $bp=0; $bp<8; $bp++)
        {
            $CRCreg <<= 1;
            if ($CRCreg & 0x1000000) { $CRCreg ^= $PLYreg; }
            $CRCreg &= 0xffffff;
        }
    }
    return $CRCreg >> 8;
}

1;
