Porting a perl script to Processing

I am trying to port over the Perl script below to processing. I only know a little about Processing Java and even less about Perl. Where I am having issues is with Perl unpack and dig. Please, will someone help me port the below Perl segment to Processing?

Thank you.

#!/usr/bin/perl
use IO::Socket::INET;
use Math::BaseCnv;
use Math::BaseCnv dig; # enable the dig option
use LWP::Simple;
dig('url'); # select the right alphabet for the base64

$apikey="YOUR-API-KEY-HERE";

# auto-flush on socket
$| = 1;

# creating a listening socket
my $socket = new IO::Socket::INET (
    LocalHost => '0.0.0.0',
    LocalPort => '5040',
    Proto => 'tcp',
    Listen => 5,
    Reuse => 1
);
die "cannot create socket $!\n" unless $socket;
print "Server waiting for client connections...check log file EnecsysLogfile.txt for details.\n";

while(1)
{
    # waiting for a new client connection
    my $client_socket = $socket->accept();

    # get information about a newly connected client
    my $client_address = $client_socket->peerhost();
    my $client_port = $client_socket->peerport();


    open WRITEFILE, ">>", "EnecsysLogfile.txt" or die $!; # define outputfile

    # read up to 1024 characters from the connected client
    my $data = "";
    $client_socket->recv($data, 1024);
    print WRITEFILE "connection from $client_address:$client_port $data\n";

    $ZigbeeRaw = $data;
    chomp $ZigbeeRaw;
    $Zigbee = substr($ZigbeeRaw,18);


        $Zigbee =~ s/\r//g;     #Remove lifefeed and CR from the string
        $Zigbee =~ s/\n//g;     #Usually chomp is used for that, but there are issues between platforms with that



        if ($Zigbee =~ /^WZ/)  #Gateway strings will just be logged
                {
                #open WRITEFILE, ">>", "EnecsysLogfile.txt" or die $!; # define outputfile
                #print WRITEFILE $date, "\t", $time, "\t", $Zigbee, "\n";
                #close WRITEFILE;
                }

        # START OF PROBLEM
        if ($Zigbee =~ /^WS/  && length($Zigbee)==59  ) #Normal inverter strings are parsed
                {
                dig('url');
                $DecZigbee = cnv('A'.substr($Zigbee,3,54),64,10); #decimal representation of whole Zigbee string
                dig('HEX'); #the url alphabet messes up de dec hex conversions, so change to HEX
                $HexZigbee = cnv($DecZigbee,10,16); #Hex representation of zigbeestring
                if (length($HexZigbee) ==80) # if we have a leading 0 it gets chopped off, this is a fix for that.
                        {
                        $HexZigbee="0".$HexZigbee;
                        }
                $HexID = substr($HexZigbee,0,8); #Device ID in hex
                $IDEndian = unpack("H*", pack("V*", unpack("N*", pack("H*", $HexID)))); # some magic to convert from little to big endian
        # END OF PROBLEM
                $IDDec = cnv($IDEndian,16,10); #Device ID in decimal numbers. Should match Enecsys monitor site
                $HexTime1 = cnv(substr($HexZigbee,18,4),16,10);
                $HexTime2 = cnv(substr($HexZigbee,30,6),16,10);
                $HexDCCurrent = 0.025*cnv(substr($HexZigbee,46,4),16,10); #25 mA units?
                $HexDCPower = cnv(substr($HexZigbee,50,4),16,10);
                $HexEfficiency = 0.001*cnv(substr($HexZigbee,54,4),16,10);#expressed as fraction
                $HexACFreq = cnv(substr($HexZigbee,58,2),16,10);
                $HexACVolt = cnv(substr($HexZigbee,60,4),16,10);
                $HexTemperature = cnv(substr($HexZigbee,64,2),16,10);
                $HexWh = cnv(substr($HexZigbee,66,4),16,10);
                $HexkWh = cnv(substr($HexZigbee,70,4),16,10);
                $LifekWh = (0.001*$HexWh)+$HexkWh;
                $ACpower = $HexDCPower * $HexEfficiency;
                $HexDCVolt = sprintf("%0.2f",$HexDCPower / $HexDCCurrent);

                my $url = "http://" . "emoncms.org/input/post.json?node=1&json={$IDDec:$ACpower}&apikey=$apikey";
                my $content = get $url or print WRITEFILE "Unable to get $url\n";
                print WRITEFILE "sent data".$url."-".$content."\n";


                #open WRITEFILE, ">>", "EnecsysLogfile.txt" or die $!; # define outputfile
                #print $IDDec, "\t",$HexDCPower, "W\t",$LifekWh, "kWh\t",$HexTemperature, "C\n";
                # print WRITEFILE $date, "\t", $time, "\t", $Zigbee, "\t", $deviceID, "\t",$Zdcpower, "\t",$ZEfficiency, "\t", $ACpower, "\t",$Zdccurrent, "\t",$ZDCenergy, "\t",$Zmonth, "\t",$Ztime, "\t",$Zacvolt, "\t",$Zacfreq, "\t",$Ztemperature, "\t",$ZUptime, "\t",$LifekWh, "\t",$HexZigbee, "\t",$IDDec,"\n";
                #print WRITEFILE $Zigbee, "\t", $IDDec, "\t",$HexDCPower, "\t",$HexEfficiency, "\t", $ACpower, "\t",$HexDCCurrent, "\t",$HexDCVolt, "\t",$LifekWh, "\t",$HexTime1, "\t",$HexTime2, "\t",$HexACVolt, "\t",$HexACFreq, "\t",$HexTemperature, "\t",$HexZigbee,"\n";
                #print $IDDec, "\t",$HexDCPower, "\t",$HexEfficiency, "\t", $ACpower, "\t",$HexDCCurrent, "\t",$HexDCVolt, "\t",$LifekWh, "\t time1=",$HexTime1, "\t time2=",$HexTime2, "\t",$HexACVolt, "\t",$HexACFreq, "\t",$HexTemperature, "\t",$HexZigbee,"\n";
                #                close WRITEFILE;
                }
        if ($Zigbee =~ /^WS/  && length($Zigbee)!=57  )  #other inverter strings (startup?)
                {
                #print $date, "\t", $time, "\t", $Zigbee, "\n";
              #  open WRITEFILE, ">>", "EnecsysLogfile.txt" or die $!; # define outputfile
              #  print WRITEFILE $date, "\t", $time, "\t", $Zigbee, "\n";
              #  close WRITEFILE;
                }


    # notify client that response has been sent
    shutdown($client_socket, 1);
}

$socket->close();

Answers

  • is that doing something specific with zigbee or is it just general?

    try searching for a java version, it'll be easier to convert.

  • (it is, based on the filename - Enecsys are a range of solar panels)

  • There is no Java version that I am aware of, the zigbee is really unimportant, a rose by any other name etc. What I need is a Java version of unpack and dig. Because I don't really know Perl, I am not sure how they work.

    Thanks for your response.

  • That unpack command is just converting from big endian to little endian, or vice versa, it's not doing a lot. (Basically you get 4 bytes from the device, lowest first, and it conveys then too highest first. In decimal it would be sending the number 1234 as 4, 3, 2, 1 and needs converting)

    Dig, I don't know.

  • here's the dig documentation

    http://search.cpan.org/~pip/Math-BaseCnv-1.4.75O6Pbr/BaseCnv.pm#dig(\@newd)

    dig('hex') appears to put it into hex mode.

    dig('url') puts it into url mode.

    the problem with this is that it'll be easy enough to convert the data from the input to the output but we've no way of getting the input data without access to a zigbee / inverter. (unless you could dump it into a file somewhere and upload it for us to test with - it only looks like 60 bytes of data...)

  • running this little perl script:

    $HexID = "0102030405060708090a0b0c0d0e0f";
    $IDEndian = unpack("H*", pack("V*", unpack("N*", pack("H*", $HexID))));
    
    print("$IDEndian\n");
    

    prints "04030201080706050c0b0a09". it's swapping the order of each group of bytes.

  • edited November 2017

    AWE!! Thank you, the feed works, I can read a string using the following code.

    I need the following ported to Java

    $HexID = "0102030405060708090a0b0c0d0e0f";
    $IDEndian = unpack("H*", pack("V*", unpack("N*", pack("H*", $HexID))));
    
    print("$IDEndian\n");
    

    //The following is very crude but I can read the input stream with it

        import processing.net.*;
    
        int port = 5040;
        boolean myServerRunning = true;
        int bgColor = 0;
        int direction = 1;
        int textLine = 60;
        float DecZigbee;
    
        String data, RecData, Zigbee, ZigbeeRaw, HexZigbee, HexID;
        String[] m1;
    
        Server myServer;
    
        void setup()
        {
          size(1280, 800);
          textFont(createFont("SanSerif", 10));
          myServer = new Server(this, port); 
          background(0);
        }
    
        void mousePressed()
        {
          // If the mouse clicked the myServer stops
          myServer.stop();
          myServerRunning = false;
        }
    
        void draw()
        {
          if (myServerRunning == true)
          {
            text("server", 15, 45);
            Client thisClient = myServer.available();
            if (thisClient != null) {
              if (thisClient.available() > 0) {
    
              ZigbeeRaw = thisClient.readString();
              Zigbee = ZigbeeRaw.substring(18);
    
             if (match(Zigbee,"WS") !=null);{
                DecZigbee = unhex(Zigbee.substring(3,54));
            println(ZigbeeRaw); // for testing only
               }
              }
            }
          } 
          else 
          {
            text("server", 15, 45);
            text("stopped", 15, 65);
          }
        }
    
Sign In or Register to comment.