OpenEAFDSS Tutorial

In this tutorial we will see step by step the development of the OpenEAFDSS.pl utility (which can be found in the examples directory of the CPAN distribution). But before we start developing let's see how to install the OpenEAFDSS library on our system.

In a linux/UNIX system you can either do it manually by downloading the tar from the CPAN page and then doing the standard

  1. perl Makefile.PL
  2. make
  3. make test
  4. make install

If you go this way you will have to manually install all the required perl modules (Config::IniFiles, Class::Base, Digest::SHA1, IO::Socket::INET, Device::SerialPort). If you don't want to bother with all that you can use the help of CPAN.

  1. perl -e shell -MCPAN

and then on the cpan shell give the "install EAFDSS" command.

If unfortunately you have to deal with a windows system, make sure to install perl (a good choice will be ActivePerl). The following url also might be of help in case you have trouble with the Win32::SerialPort module:

http://www.cpan.org/modules/by-module/Win32API/

There is a function (init_progie) that take care of the command line interface, so that we can simply get all the required parameters for our EAFDSS object initialization.

  1. sub main() {
  2. my($verbal, $driver, $params, $serial, $sDir, $cmd) = init_progie();
  3.  
  4. my($dh) = new EAFDSS(
  5. "DRIVER" => $driver . "::" . $params,
  6. "SN" => $serial,
  7. "DIR" => $sDir,
  8. "DEBUG" => $verbal
  9. );
  10.  
  11. if (! $dh) {
  12. print("ERROR: " . EAFDSS->error() ."\n");
  13. exit -1;
  14. }
  15.  
  16. my($cmdType, $cmdParam) = split(/\s+/, $cmd, 2);
  17.  
  18. switch (uc($cmdType)) {
  19. case "SIGN" { cmdSign($dh, $cmdParam) }
  20. case "REPORT" { cmdReport($dh) }
  21. case "STATUS" { cmdStatus($dh) }
  22. case "INFO" { cmdInfo($dh) }
  23. case "TIME" { cmdTime($dh, $cmdParam) }
  24. case "HEADERS" { cmdHeaders($dh, $cmdParam) }
  25. }
  26. }

The constructor of the EAFDSS (new) return a driver handle to our device. The object type of the handle depends on "DRIVER" parameter. The "SN" parameter is the Serial number of the device we want to connect to. Make sure to use the correct one, otherwise the library will not initialize the object for security reasons. "DIR" is the directory to save the A, B, C fiscal files that the library routinely creates during the fiscal operations. The final "DEBUG" parameter if is set will print details (on stderr) of what it does. That will be a useful output to send back in case of a bug report.

On lines 11-14 there is what we should always do after an EAFDSS function call, check for errors. You can see all the error codes on the manual page (man EAFDSS). Finally depending on the request of the user we go to the relevant function.

  1. sub cmdSign() {
  2. my($dh) = shift @_;
  3. my($fname) = shift @_;
  4.  
  5. my($result) = $dh->Sign($fname);
  6. if ($result) {
  7. printf("%s\n", $result);
  8. exit(0);
  9. } else {
  10. my($errNo) = $dh->error();
  11. my($errMsg) = $dh->errMessage($errNo);
  12. printf(STDERR "ERROR [0x%02X]: %s\n", $errNo, $errMsg);
  13. exit($errNo);
  14. }
  15. }

The "SIGN" action is the most used one. The only parameter is the filename to sign. The good news is that you can give the "-" in order to sign what comes from STDIN. As usual we have to check afterwards for errors and respond accordingly. During that command the A and B fiscal files will be created under the "DIR" parameter we provided during the initialization of the driver handle. The function will return the full signature string. Then all your application have to do is make sure to print that one at the bottom of your invoice printout.

  1. sub cmdReport() {
  2. my($dh) = shift @_;
  3.  
  4. my($result) = $dh->Report();
  5. if ($result) {
  6. printf("%s\n", $result);
  7. exit(0);
  8. } else {
  9. my($errNo) = $dh->error();
  10. my($errMsg) = $dh->errMessage($errNo);
  11. printf(STDERR "ERROR [0x%02X]: %s\n", $errNo, $errMsg);
  12. exit($errNo);
  13. }
  14. }

Second most important action is "z report" at the end of the day. No parameters here, and during the action the C fiscal file will be created. The return value is the signature of the day.

  1. sub cmdStatus() {
  2. my($dh) = shift @_;
  3.  
  4. my($result) = $dh->Status();
  5. if ($result) {
  6. printf("%s\n", $result);
  7. exit(0);
  8. } else {
  9. my($errNo) = $dh->error();
  10. my($errMsg) = $dh->errMessage($errNo);
  11. printf(STDERR "ERROR [0x%02X]: %s\n", $errNo, $errMsg);
  12. exit($errNo);
  13. }
  14. }

To get the status of the device, including information on number of signs and z reports.

  1. sub cmdInfo() {
  2. my($dh) = shift @_;
  3.  
  4. my($result) = $dh->Info();
  5. if ($result) {
  6. printf("%s\n", $result);
  7. exit(0);
  8. } else {
  9. my($errNo) = $dh->error();
  10. my($errMsg) = $dh->errMessage($errNo);
  11. printf(STDERR "ERROR [0x%02X]: %s\n", $errNo, $errMsg);
  12. exit($errNo);
  13. }
  14. }

To get the info about device firmware version.

  1. sub cmdTime() {
  2. my($dh) = shift @_;
  3. my($time) = shift @_;
  4.  
  5. if ($time) {
  6. my($result) = $dh->SetTime($time);
  7. if ( defined $result && ($result == 0)) {
  8. printf("Time successfully set\n");
  9. exit(0);
  10. } else {
  11. my($errNo) = $dh->error();
  12. my($errMsg) = $dh->errMessage($errNo);
  13. printf(STDERR "ERROR [0x%02X]: %s\n", $errNo, $errMsg);
  14. exit($errNo);
  15. }
  16. } else {
  17. my($result) = $dh->GetTime();
  18. if ($result) {
  19. printf("%s\n", $result);
  20. exit(0);
  21. } else {
  22. my($errNo) = $dh->error();
  23. my($errMsg) = $dh->errMessage($errNo);
  24. printf(STDERR "ERROR [0x%02X]: %s\n", $errNo, $errMsg);
  25. exit($errNo);
  26. }
  27. }
  28.  
  29. }

Here is the way to get or set the time of the device. Changing of time might need special arrangement on the device menu. Also make sure to provide the time in "DD/MM/YY HH:MM:SS" format.

Get/Set Headers

  1. sub cmdHeaders() {
  2. my($dh) = shift @_;
  3. my($headers) = shift @_;
  4.  
  5. if ($headers) {
  6. my($result) = $dh->SetHeaders($headers);
  7. if ( defined $result && ($result == 0)) {
  8. printf("Headers successfully set\n");
  9. exit(0);
  10. } else {
  11. my($errNo) = $dh->error();
  12. my($errMsg) = $dh->errMessage($errNo);
  13. printf(STDERR "ERROR [0x%02X]: %s\n", $errNo, $errMsg);
  14. exit($errNo);
  15. }
  16. } else {
  17. my(@headersArray) = $dh->GetHeaders();
  18. if (@headersArray) {
  19. my($i);
  20. for ($i=0; $i < 12; $i+=2) {
  21. if ($headersArray[$i] ne '') {
  22. printf("[Line %d] [Type:%d] --> %s\n", $i/2+1, $headersArray[$i], $headersArray[$i+1]);
  23. }
  24. }
  25. exit(0);
  26. } else {
  27. my($errNo) = $dh->error();
  28. my($errMsg) = $dh->errMessage($errNo);
  29. printf(STDERR "ERROR [0x%02X]: %s\n", $errNo, $errMsg);
  30. exit($errNo);
  31. }
  32. }
  33.  
  34. }

Last are the two function to Get or Set the headers. When you get the headers the structure is an array. While to set them you need to give them in the following format:

  1. Style1/Line1/Style2/Line2/Style3/Line3/Style4/Line4/Style5/Line5/Style6/Line6

Limit on the number of header changes you can perform on a device might apply.


Warning: Table './openeafdss/watchdog' is marked as crashed and should be repaired query: INSERT INTO watchdog (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (0, 'php', '%message in %file on line %line.', 'a:4:{s:6:\"%error\";s:12:\"user warning\";s:8:\"%message\";s:338:\"Table &#039;./openeafdss/accesslog&#039; is marked as crashed and should be repaired\nquery: INSERT INTO accesslog (title, path, url, hostname, uid, sid, timer, timestamp) values(&#039;OpenEAFDSS Tutorial&#039;, &#039;node/4&#039;, &#039;&#039;, &#039;54.224.204.189&#039;, 0, &#039;aaa02d7078678c29fd618069cc145edf&#039;, 159, 1493350891)\";s:5:\"%file\";s:68:\"/var/www/openeafdss.gr/httpdocs/modules/statistics/statistics.module\";s:5:\"%line\";i:64;}', 3, '', 'http://openeafdss.gr/tutorial', '', '54.22 in /var/www/openeafdss.gr/httpdocs/includes/database.mysqli.inc on line 128