Documentation Ethernet POS - Exemple PHP d'impression Cloud

Notes

Cet exemple montre une implementation PHP du mode de connexion Cloud de Ethernet POS. Dans ce mode, les travaux d'impression sont générés et stockés sur un serveur web. Via l'appel d'une page spéciale, ces travaux d'impression sont ensuite récupérés par Ethernet POS, et envoyés directement sur l'imprimante.

Cet exemple comporte trois fichiers importants :

  • print_queue.php : Implemente une file d'attente d'impression stockée sur disque sous la forme d'une classe PHP. Les travaux d'impression sont écris à la suite les uns des autres, et lus tous ensembles.
  • client.php : Implemente la partie cliente de cet exemple. Il s'agit d'une page PHP simple, qui en réponse à la soumission du formulaire d'impression, va écrire un travail d'impression dans la file d'attente.
  • server.php : Implemente la partie serveur de cet exemple. Il s'agit d'une page PHP qui doit être téléchargée régulièrement par Ethernet POS. Lorsque cette page est appelée, elle lit le contenu complet de la file d'attente, retourne son contenu et la vide. Ethernet POS enverra ensuite le contenu téléchargé à l'imprimante.

Pour tester ce code, vous devez copier les 3 fichiers .php sur un serveur web PHP, dans un même dossier. Ensuite, activez le mode téléchargement HTTP(S) de Ethernet POS, et entrez l'URL correspondante au fichier server.php sur le serveur PHP. Enfin, pour tester l'impression distante, ouvrez un navigateur web, et entrez l'URL correspondant du fichier client.php sur le serveur web.

Code de la file d'impression <?php

// This file implements a printer virtual queue. It exposes an object that
// allows to either append a printing job, or retreive and flush the whole jobs
// queue. To simplify security setup for this sample, queue persistance is done
// in a temporary file.

class PrintQueue
{
    private $name;
    private $file;
    private $lock;
    private $last_error;

    public function __construct($name = "default")
    {
        $this->name = $name;
        $this->file = false;
        $this->last_error = '';
    }

    public function open()
    {
        if ($this->file !== false)
            return true;

        $path = sprintf("%s/ethpos_%s.queue",
                        sys_get_temp_dir(),
                        $this->name);

        // File must be opened read/write.
        $file = @fopen($path, 'a+');
        if ($file === false) {
            $this->fillLastError();
            return false;
        }

        // And we serialize its access through an exclusive lock.
        if (!@flock($file, LOCK_EX)) {
            $this->fillLastError();
            return false;
        }

        $this->file = $file;

        return true;
    }

    public function close()
    {
        if ($this->file !== false) {
            flock($this->file, LOCK_UN);
            fclose($this->file);
            $this->file = false;
        }
    }

    public function write($data)
    {
        if (@fwrite($this->file, $data) === false) {
            $this->fillLastError();
            return false;
        }

        return true;
    }

    public function read()
    {
        $data = '';

        if (@fseek($this->file, 0) < 0) {
            $this->fillLastError();
            return false;
        }

        for (;;) {
            // Read by chunck of 4 KB.
            $r = @fread($this->file, 4096);
            if ($r === false) {
                $this->fillLastError();
                return false;
            }

            // Stop if there is no more data to read.
            if (strlen($r) == 0)
                break;

            $data .= $r;
        }

        return $data;
    }

    public function truncate()
    {
        if (!@ftruncate($this->file, 0)) {
            $this->fillLastError();
            return false;
        }

        return true;
    }

    public function lastError()
    {
        return $this->last_error;
    }

    private function fillLastError()
    {
        $err = error_get_last();
        $err_msg = $err['message'];

        // Remove function prefix if any, to report just the error
        // message.
        $pos = strpos($err_msg, "): ");
        if ($pos !== false)
            $err_msg = substr($err_msg, $pos + 3);
    
        $this->last_error = $err_msg;
    }
}

Télécharger print_queue.php

Code client <?php

// This file implements a simple page that allows to add a print job to the
// print queue, in response to a click to the Print button.

include 'print_queue.php';

// Helper function
function post($key, $default = '')
{
    return isset($_POST[$key]) ? $_POST[$key] : $default;
}

// Initializations
$def_text = "This is a PHP client/server Ethernet POS\nsample.\n\n" .
            "Regards\nThe Active+ Software Team";
$text = post('text', $def_text);
$qrcode = post('qrcode') == 'yes';
$cut = post('cut', 'yes') == 'yes';
$error = '';

if (post('print') != '') {
    // Prepare data to print
    $url = "https://www.activeplus.com";
    $data = "\x1b@";

    // Align center
    $data .= "\x1ba\x01";

    // Set bold
    $data .= "\x1bE\x01";

    // Write header
    $data .= "Ethernet POS sample.\n$url\n\n";

    // Align left
    $data .= "\x1ba\x00";

    // Remove bold
    $data .= "\x1bE\x00";

    if ($text != '') {
        // Add Raw text
        $data .= trim($text) . "\n\n";
    }
    if ($qrcode) {
        // Align center
        $data .= "\x1ba\x01";

        // Set QR code size 4
        $data .= sprintf("\x1d(k\x03\x00\x31%c%c", 67, 4);

        // Set QR code data
        $len = strlen($url) + 3;
        $data .= sprintf("\x1d(k%c%c\x31%c\x30%s", $len & 0xff,
                         $len >> 8,
                         80,
                         $url);

        // Add QR code print command
        $data .= sprintf("\x1d(k\x03\x00\x31%c%c", 81, 48);
        $data .= "\n\n";
    }
    if ($cut) {
        // Add paper cut command
        $data .= "\x1dV\x41\x03";
    }

    $queue = new PrintQueue();
    if (!$queue->open() || !$queue->write($data))
        $error = $queue->lastError();
    $queue->close();
}

?>
<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Ethernet POS sample of a PHP client/server implementation</title>
    </head>
    <body>
        <form action="<?= htmlspecialchars($_SERVER['REQUEST_URI']) ?>" method="post">
            <h3>Ethernet POS sample of PHP client/server implementation</h3>
            <p>
                This page contains the client side implementation
                of this sample. Each click on Print button will
                generate a print job according to the following
                inputs.
            </p>
            <table>
                <tr>
                    <td>Text to print:</td>
                    <td>
                        <textarea name="text" cols="43" rows="10"><?= htmlspecialchars($text) ?></textarea>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <input type="checkbox" name="qrcode" value="yes"<? if ($qrcode) echo ' checked="checked"'; ?> />
                        Print a QR code
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <input type="checkbox" name="cut" value="yes"<? if ($cut) echo ' checked="checked"'; ?> />
                        Add a cut paper command
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <input type="submit" name="print" value="Print" />
                    </td>
                </tr>
            </table>
        </form>
    </body>
</html>

Télécharger client.php

Code serveur <?php

// This page just returns the whole contents of the print queue, or a server
// error if something wrong occured. No security mechanism is provided for this
// sample, but an authentication mechanism should be setup for a production
// system.

include 'print_queue.php';

$queue = new PrintQueue();
if (!$queue->open()) {
    header('HTTP/1.0 500 ' . $queue->lastError());
    die();
}

$data = $queue->read();
if ($data === false) {
    header('HTTP/1.0 500 ' . $queue->lastError());
    die();
}

// Ethernet POS requires application/octet-stream content type.
header('Content-Type: application/octet-stream');
header('Content-Length: ' . strlen($data));
echo $data;

// Once data has been sent, reset queue file contents.
$queue->truncate();

// And cleanup.
$queue->close();

?>

Télécharger server.php