将perl转换为shell或bash,以便通过gpio进行通信

时间:2015-05-17 13:34:09

标签: bash perl

我是perl的新手但是了解C和C ++。我想将以下url下的perl脚本转换为shell或bash: https://code.google.com/p/busware/source/browse/trunk/SD0/Firmware_VZ/vzfeeder/vzfeeder.pl

以下是代码:

#!/usr/bin/perl

use warnings;
use strict;
use Time::HiRes qw/ gettimeofday /;;
use POE;
use POE::Wheel::ReadWrite;
use POE::Wheel::ReadLine;
use POE::Component::Client::HTTP;
use POE::Component::DBIAgent;
use Symbol qw(gensym);
use Device::SerialPort;
use POE::Filter::Line;
use HTTP::Request;
use Data::Dumper;
use DateTime;

sub DB_NAME () { "volkszaehler" }
sub DB_USER () { "vz" }
sub DB_PASS () { "demo" }

use Log::Log4perl qw/:easy/;
Log::Log4perl->easy_init( {
                           level  => $INFO,
                           layout => '[%d] %p %c - %m%n',
                          } );

INFO('starting logger process');

POE::Session->create(
  inline_states => {
    _start      => \&setup_device,
    open_serial => \&open_serial,
    program_serial => \&program_serial,
    got_serial  => \&got_serial,
    got_error   => \&handle_errors,
    cmd_V       => \&got_version,
    cmd_L       => \&got_portbits,
    queue_cmd   => \&queue_cmd,

    mod_reset   => \&mod_reset,
    mod_bl      => \&mod_bl,

    query_all_channels_done => \&handle_query_all_channels_response,
    finish_query_all_channels => \&finish_query_all_channels,
  },
)->option( trace => 1 );

POE::Kernel->run();
exit 0;

sub setup_device {
  my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];

  POE::Component::Client::HTTP->spawn(
                                      Alias     => 'ua',
                                      Timeout   => 10,
                                     );

  INFO('opening database link');
  my $dbi = $heap->{dbi_helper} = POE::Component::DBIAgent->new(
    DSN     => ['dbi:mysql:dbname=' . DB_NAME, DB_USER, DB_PASS],
    Count   => 3,
    Queries => {
      query_all_channels  => 'select * from entities',
      insert_tickdata     => 'insert into data (timestamp,channel_id,value) values (?, ?, ?)',
#      update => "update test set value = ? where name = ?",
#      delete => "delete from test where name = ?",
    },
  );

  $heap->{CHANNELS} = [];
  $dbi->query(query_all_channels => $session->ID => 'query_all_channels_done');

  $kernel->yield( 'open_serial' );
}

# open serial Port
sub open_serial {
  my ($kernel, $heap, $session, $data) = @_[KERNEL, HEAP, SESSION, ARG0];

  INFO('opening serial port');

  qx^if test ! -d /sys/class/gpio/gpio27; then echo 27 > /sys/class/gpio/export; fi^;
  qx^echo out > /sys/class/gpio/gpio27/direction^;
  qx^echo 1 > /sys/class/gpio/gpio27/value^;
  qx^if test ! -d /sys/class/gpio/gpio17; then echo 17 > /sys/class/gpio/export; fi^;
  qx^echo out > /sys/class/gpio/gpio17/direction^;
  qx^echo 0 > /sys/class/gpio/gpio17/value^;
  qx^echo 1 > /sys/class/gpio/gpio17/value^;

  # Open a serial port, and tie it to a file handle for POE.
  my $handle = gensym();
  my $port = tie(*$handle, "Device::SerialPort", "/dev/ttyAMA0");
  die "can't open port: $!" unless $port;

  $port->datatype('raw');
  $port->reset_error();
  $port->baudrate(38400);
  $port->databits(8);
  $port->parity('none');
  $port->stopbits(1);
  $port->handshake('none');

  $port->write_settings();

  $port->lookclear();

  # Start interacting with the GPS.
  $heap->{port}       = $port;
  $heap->{port_wheel} = POE::Wheel::ReadWrite->new(
    Handle => $handle,
    Filter => POE::Filter::Line->new(
      InputLiteral  => "\x0D\x0A",    # Received line endings.
      OutputLiteral => "\x0D",        # Sent line endings.
    ),
    InputEvent => "got_serial",
    ErrorEvent => "got_error",
  );

  $kernel->delay_add( queue_cmd => 2 => 'v' ); 
  $kernel->delay( program_serial => 5 ); 
}

# programming via serial Port
sub program_serial {
  my ($kernel, $heap, $session, $data) = @_[KERNEL, HEAP, SESSION, ARG0];

  INFO('flashing module @ serial port');

  delete $heap->{port_wheel};
  untie( $heap->{port} ) if $heap->{port};
  delete ( $heap->{port} );

  qx^if test ! -d /sys/class/gpio/gpio17; then echo 17 > /sys/class/gpio/export; fi^;
  qx^echo out > /sys/class/gpio/gpio17/direction^;
  qx^echo 0 > /sys/class/gpio/gpio17/value^;
  qx^if test ! -d /sys/class/gpio/gpio27; then echo 27 > /sys/class/gpio/export; fi^;
  qx^echo out > /sys/class/gpio/gpio27/direction^;
  qx^echo 0 > /sys/class/gpio/gpio27/value^;
  qx^echo 1 > /sys/class/gpio/gpio17/value^;
  qx^sleep 1^;
  qx^echo 1 > /sys/class/gpio/gpio27/value^;
  qx^avrdude -p atmega1284p -P /dev/ttyAMA0 -b 38400 -c avr109 -U flash:w:main.hex^;

  $kernel->yield( 'open_serial' );
}


# Port data (lines, separated by CRLF) are displayed on the console.
sub got_serial {
  my ($kernel, $heap, $session, $data) = @_[KERNEL, HEAP, SESSION, ARG0];
  INFO( 'got_serial: ' . $data );
  my @v = split( /\s+/, $data );

  # Channel ticks?
  if ($v[0] =~ /^([ABCD])$/) {
    my $ch = $1;
    INFO( 'Tick @ ' . $ch );
    my ($seconds, $microseconds) = gettimeofday;
    my $sec = sprintf( '%d%03d', $seconds, $microseconds/1000 );

    $heap->{dbi_helper}->query( insert_tickdata => $session->ID => undef => ($sec, ord($ch)-64, 1));

    return;
  } 

  my $cmd = sprintf 'cmd_%s', shift @v;
  $kernel->yield( $cmd => [@v] );
}

# Error on the serial port.  Shut down.
sub handle_errors {
  my $heap = $_[HEAP];
  ERROR( 'received error!' );
  delete $heap->{port_wheel};
}

sub got_version {
  my ($kernel, $heap, $data) = @_[KERNEL, HEAP, ARG0];
  INFO( 'VERSION: ' . $data->[0] );
  $heap->{VERSION} = $data->[0];

  $kernel->delay( 'program_serial' );
}

sub got_portbits {
  my ($kernel, $heap, $data) = @_[KERNEL, HEAP, ARG0];
  INFO( 'Portbits: ' . $data->[0] );
  $heap->{PORTBITS} = $data->[0];
}

sub queue_cmd {
  my ($kernel, $heap, $data) = @_[KERNEL, HEAP, ARG0];
  $heap->{port_wheel}->put( $data );
}

#
# DATABASE work
#

sub handle_query_all_channels_response {
  my ($kernel, $heap, $data) = @_[KERNEL, HEAP, ARG0];

  if (ref($data) eq 'ARRAY') {
    push $heap->{CHANNELS}, $data;
  } elsif ($data eq 'EOF') {
    $kernel->yield( finish_query_all_channels => $heap->{CHANNELS} );
  }

}

sub finish_query_all_channels {
  my ($kernel, $heap, $data) = @_[KERNEL, HEAP, ARG0];
  INFO( Dumper($heap->{CHANNELS}));
}

以下是perl脚本的一部分,如shell / bash:

#!/usr/bin/sh

function setup_device() {{

}
function open_Serial(){
    echo "opening serial port; Resetting\\Booting the SD0"

    if test ! -d /sys/class/gpio/gpio27; then echo 27 > /sys/class/gpio/export; fi
    echo out > /sys/class/gpio/gpio27/direction
    echo 1 > /sys/class/gpio/gpio27/value
    if test ! -d /sys/class/gpio/gpio17; then echo 17 > /sys/class/gpio/export; fi
    echo out > /sys/class/gpio/gpio17/direction
    echo 0 > /sys/class/gpio/gpio17/value
    echo 1 > /sys/class/gpio/gpio17/value
    minicom -b 38400 -o -D /dev/ttyAMA0
}

function program_Serial(){
    echo "flashing module @ serial port"
    echo calling co-processor bootloader ...

    if test ! -d /sys/class/gpio/gpio17; then echo 17 > /sys/class/gpio/export; fi
    echo out > /sys/class/gpio/gpio17/direction
    echo 0 > /sys/class/gpio/gpio17/value
    if test ! -d /sys/class/gpio/gpio27; then echo 27 > /sys/class/gpio/export; fi
    echo out > /sys/class/gpio/gpio27/direction
    echo 0 > /sys/class/gpio/gpio27/value
    echo 1 > /sys/class/gpio/gpio17/value
    sleep 1
    echo 1 > /sys/class/gpio/gpio27/value

    avrdude -p atmega1284p -P /dev/ttyAMA0 -b 38400 -c avr109 -U flash:w:SD0.hex
}

例如

my ($kernel, $heap, $session, $data) = @_[KERNEL, HEAP, SESSION, ARG0];

意思?我为函数(?)提供了参数,但是如何转换ARG? 或者下面的代码是做什么的?

my $handle = gensym();

是否有工具将perl脚本转换为shell?或者(好的Doc)可以帮助翻译?

1 个答案:

答案 0 :(得分:5)

您的Perl程序是围绕POE (the Perl Object Environment)构建的,这是一种事件循环机制,允许并行执行多个独立任务以响应事件,消息或已用时间。它是一套全面的模块,与其他语言相对应,但不能直接复制到任何地方

  

例如

my ($kernel, $heap, $session, $data) = @_[KERNEL, HEAP, SESSION, ARG0];
     

意思?我为函数(?)提供了参数,但是如何转换ARG?

这是POE调用机制的一部分。参数传递给@_数组中的Perl子例程,POE有一个约定,即相同的参数总是以相同的顺序传递给它的成员子例程。值KERNELHEAP等只是数字常量,用于将索引标记到参数列表中。例如SESSIONKERNELHEAP分别为1,2和3。 ARG0为10,因此它选择了@_的第11个元素。其他值已定义

  

或者下面的代码在做什么?

my $handle = gensym();

这是Perl的一个非常深奥的角落。 gensymSymbol module提供,在这种情况下,它是一种创建文件句柄而不为其提供特定标识符的方法

  

是否有工具将perl脚本转换为shell?或者(好的Doc)可以帮助翻译?

没有任何东西可以将一般的Perl程序转换为任何其他语言,因为正如我在上面的评论中暗示的那样,Perl有一种独特的方式来交织编译和执行阶段,这是其他语言所没有的。可能会有一些东西可以转换非常基本的Perl,但我没有遇到它,无论如何你的代码不符合 basic

Perl本身的最佳文档位于perldocmetacpan除了上面链接的POE网站外,还将为您提供单个模块的文档帮助