kwasinski

Collector - collector.pl

Jun 17th, 2020
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 5.84 KB | None | 0 0
  1. #!perl -w
  2.  
  3. use 5.10.0;
  4.  
  5. ##
  6. ## Loading local modules
  7. BEGIN {
  8.     use File::Basename;
  9.     use Cwd qw/abs_path/;
  10.  
  11.     my $basePath = dirname abs_path $0;
  12.     push @INC,
  13.         $basePath.'/lib',
  14. }
  15.  
  16. use utf8;
  17. use Getopt::Long;
  18. use POSIX;
  19. use Try::Tiny;
  20. use Device::Modbus;
  21. use Device::Modbus::RTU::Client;
  22. use Device::Modbus::TCP::Client;
  23. use JSON qw | to_json encode_json|;
  24. use DBI;
  25. use DBD::mysql;
  26. use YAML::Tiny;
  27. ##
  28. ## Self Modules
  29. use Hazel::Db qw|initDB|;
  30.  
  31. ##
  32. ## Load config file
  33. my $configFilename = 'default_config.yaml';
  34. my $yaml = YAML::Tiny->read($configFilename);
  35. my $config = $yaml->[0];
  36. my $dbConfig =  $yaml->[1];
  37. ##
  38. ## Data Structure
  39. my %dataStructure = (
  40.     -configFilename     => 'default_config.yaml',
  41.     -collectInterval    => 5,
  42.     -portType           => 'TCP',
  43.     -ipAddress          => $config->{tcp}->{ipAddress},
  44.     -rtuRelatedPort     => $config->{rtu}->{rtuRelatedPort}, #default
  45.     -baudrate           => $config->{rtu}->{baudrate},
  46.     -parity             => $config->{rtu}->{parity},
  47.     -help               => '',
  48.     -install            => '',
  49.     -verbose            => 0,
  50.     -DB                 => {
  51.         -db_name    => $dbConfig->{database}->{db_name},
  52.         -host       => $dbConfig->{database}->{host},
  53.         -port       => $dbConfig->{database}->{port},
  54.         -user       => $dbConfig->{database}->{user},
  55.         -passwd     => $dbConfig->{database}->{passwd},
  56.     },
  57. );
  58.  
  59. ##
  60. ## Populate essential vars from cli
  61. GetOptions(
  62.     "ptype=s" => \$dataStructure{-portType},
  63.     "ip=s" => \$dataStructure{-ipAddress},
  64.     "collectInterval=i" => \$dataStructure{-interval},
  65.     "port=s" => \$dataStructure{-rtuRelatedPort},
  66.     "help" => \$dataStructure{-help},
  67.     "install" => \$dataStructure{-install},
  68.     "verbose" => \$dataStructure{-verbose},
  69.     "conf=s" => \$dataStructure{-configFilename},
  70. );
  71.  
  72. ##
  73. ## configuration routines
  74. install()  if ($dataStructure{-install} ne '');
  75. die(<DATA>)  if ($dataStructure{-help} ne '');
  76.  
  77.  
  78. print 'Initializing database interface...',"\n"  if $dataStructure{-verbose};
  79. my $dbConnection = initDB(%dataStructure);
  80. print 'Local database ready!', "\n"  if $dataStructure{-verbose};
  81.  
  82. ##
  83. ## Magic goes here
  84. print 'Initializing reading...', "\n" if $dataStructure{-verbose};
  85. $yaml = YAML::Tiny->read($dataStructure{-configFilename});
  86. my $registers = $yaml->[2]->{'readings'};
  87. my $numberOfRegisters = keys %{$registers};
  88. while(1)
  89. {
  90.     { # Request scope
  91.         my %response;
  92.  
  93.         try { for (my $i = 0; $i <= $numberOfRegisters -1; $i++) {
  94.             ##
  95.             ## Define the instance type accordingly with [ptype]
  96.             my $clientBus = (sub(){
  97.                 my $client;
  98.                 ##
  99.                 ## RTU Modbus object instance
  100.                 if ($dataStructure{-portType} eq 'rtu') {
  101.                     $client = Device::Modbus::RTU::Client->new(
  102.                         port        => $dataStructure{-rtuRelatedPort},
  103.                         baudrate    => $dataStructure{-baudrate},
  104.                         parity      => $dataStructure{-parity},
  105.                     );
  106.                 }
  107.                 ##
  108.                 ## TCP Modbus object instance
  109.                 if ($dataStructure{-portType} eq 'tcp') {
  110.                     $client = Device::Modbus::TCP::Client->new(
  111.                         host    => $dataStructure{-ipAddress},
  112.                     );
  113.                 }
  114.                 return $client;
  115.             })->();
  116.  
  117.             ##
  118.             ## mounting request based in conf file
  119.             my %request = (
  120.                 unit     => $registers->{$i}->{unit},
  121.                 address  => $registers->{$i}->{address},
  122.                 quantity => $registers->{$i}->{quantity},
  123.             );
  124.  
  125.             my $readings;
  126.             if ($registers->{$i}->{function} eq 'read_coils') {
  127.                 $request = $clientBus->read_coils(%request);
  128.  
  129.             } elsif ($registers->{$i}->{function} eq 'read_holding_registers') {
  130.  
  131.                 $request = $clientBus->read_holding_registers(%request);
  132.             }
  133.  
  134.             print 'Mounting request: ', join "\t", %request, "\n" if $dataStructure{-verbose};
  135.             print 'Sending request...'  if $dataStructure{-verbose};
  136.             $clientBus->send_request($request);
  137.             $response{$i} = $clientBus->receive_response and $clientBus->disconnect;
  138.  
  139.             print 'Request done!!', "\n\n"  if defined $response{$i};
  140.             my %readings = (
  141.                 station_id => $config->{station_id},
  142.                 id => $response{$i}->{id},
  143.                 register => $registers->{$i}->{address},
  144.                 value => $response{$i}->{message}->{values}[0],
  145.                 zone => $response{$i}->{message}->{function},
  146.                 code => $response{$i}->{message}->{code},
  147.                 created_at => strftime("%Y-%m-%d %H:%M:%S", localtime(time)),
  148.             );
  149.             $readings{data} = encode_json \%readings;
  150.  
  151.             $dbConnection->do("INSERT INTO data_readings (station_id, data, created_at) VALUES ($readings{station_id},'$readings{data}','$readings{created_at}')");
  152.         }}
  153.  
  154.         catch
  155.         {
  156.             print 'Error:: error while sending request to device: ', $!, "\n";
  157.         }
  158.  
  159.  
  160.     } #EOS
  161.  
  162.     sleep $dataStructure{-collectInterval};
  163. }
  164.  
  165. ## Functions below ##
  166.  
  167. ##
  168. ## Installation routine
  169. sub install {
  170.     `echo "alias collector='\$PWD/collector.pl \$\@'" >> ~/.bashrc`;
  171.     exit;
  172. }
  173.  
  174.  
  175. __DATA__
  176. ############################################################################################################
  177. ######################################## Collertor Script ##################################################
  178.  
  179. Usage:
  180.     [perl] collector[.pl] --ptype=[tcp||rtu] (--port=/dev/ttyUSB0 ||--ip=127.0.0.1) --collectInterval=1
  181.  
  182.     --ptype             Set the port type to use, it can hold the 'rtu' and 'tcp' values
  183.                         If 'tcp' value is settled, the parameter --ip turns out to be obligatory
  184.  
  185.     --port              Define the linux device port, the default value if not specified is: /dev/ttyUSB0
  186.  
  187.  
  188.     --ip                Define the ipv4 address of the master CLP to connect
  189.  
  190.  
  191.     --collecInterval    Define interval between requests for the given connection.
  192.                         if not defined assume interval equals 1s
  193.  
  194.  
  195.     --pipe              Point its value to the filename of the pipe who will hold the data structure
  196.  
  197.  
  198.     --install           Install the Perl script as an alias using his own filename.
  199.  
  200.  
  201.     --verbose           Enable verbosity
  202.  
  203. ############################################################################################################
  204. ############################################################################################################
Add Comment
Please, Sign In to add comment