Modularizing the print.pl ESCPOS script I made a long time
ago
This commit is contained in:
commit
74e0c2438c
45
lib/Exd/DeviceToImage.pm
Normal file
45
lib/Exd/DeviceToImage.pm
Normal file
@ -0,0 +1,45 @@
|
||||
package Exd::DeviceToImage;
|
||||
|
||||
use v5.40.0;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Moo;
|
||||
|
||||
use GD::Image;
|
||||
use Path::Tiny;
|
||||
|
||||
has output_file => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
has current_image => ( is => 'rw', );
|
||||
|
||||
sub image( $self, $image ) {
|
||||
my $current_image = $self->current_image;
|
||||
|
||||
if ( !defined $current_image ) {
|
||||
$self->current_image($image);
|
||||
return;
|
||||
}
|
||||
|
||||
my $new_current = GD::Image->new( $current_image->width,
|
||||
$current_image->height + $image->height );
|
||||
|
||||
$new_current->copy( $current_image, 0, 0, 0, 0,
|
||||
$current_image->width, $current_image->height);
|
||||
say $current_image->height;
|
||||
$new_current->copy( $image, 0, $current_image->height, 0, 0,
|
||||
$image->width, $image->height );
|
||||
$self->current_image($new_current);
|
||||
path($self->output_file)->spew_raw($new_current->png);
|
||||
}
|
||||
|
||||
sub lf {
|
||||
}
|
||||
|
||||
sub print {
|
||||
}
|
||||
1;
|
41
lib/Exd/DeviceToRawFile.pm
Normal file
41
lib/Exd/DeviceToRawFile.pm
Normal file
@ -0,0 +1,41 @@
|
||||
package Exd::DeviceToRawFile;
|
||||
|
||||
use v5.40.0;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Moo;
|
||||
|
||||
use GD::Image;
|
||||
use Path::Tiny;
|
||||
use Printer::ESCPOS;
|
||||
|
||||
has output_file => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
has _guts_device => (
|
||||
is => 'lazy'
|
||||
);
|
||||
|
||||
sub _build__guts_device($self) {
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'File',
|
||||
deviceFilePath => $self->output_file,
|
||||
);
|
||||
}
|
||||
|
||||
sub image( $self, $image ) {
|
||||
$self->_guts_device->printer->image($image);
|
||||
}
|
||||
|
||||
sub lf($self) {
|
||||
$self->_guts_device->printer->lf;
|
||||
}
|
||||
|
||||
sub print($self) {
|
||||
$self->_guts_device->printer->print;
|
||||
}
|
||||
1;
|
359
lib/Exd/Printer.pm
Normal file
359
lib/Exd/Printer.pm
Normal file
@ -0,0 +1,359 @@
|
||||
package Exd::Printer;
|
||||
|
||||
use v5.40.0;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Moo;
|
||||
use Exd::Utils;
|
||||
use Encode qw/decode/;
|
||||
use Path::Tiny;
|
||||
use Pango;
|
||||
|
||||
has device => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
sub qr( $self, $url ) {
|
||||
my $tmpdir = Path::Tiny->tempdir;
|
||||
my $image_file = $tmpdir->child('image.png');
|
||||
my $qrcode = Imager::QRCode->new( size => 8 );
|
||||
my $img = $qrcode->plot( $url, {} );
|
||||
$img->write( file => '' . $image_file ) or die $img->errstr;
|
||||
$self->image( $image_file );
|
||||
$self->print_text( $url, 20 );
|
||||
}
|
||||
|
||||
sub image( $self, $file ) {
|
||||
my $image = Exd::Utils::get_gd_image($file);
|
||||
my $width = $image->width;
|
||||
my $height = $image->height;
|
||||
my $dest_width = 380;
|
||||
my $dest_height = $dest_width * ( $height / $width );
|
||||
my $image_dest = GD::Image->new( $dest_width, $dest_height );
|
||||
$image_dest->copyResampled( $image, 0, 0, 0, 0, $dest_width, $dest_height,
|
||||
$width, $height, );
|
||||
|
||||
for (
|
||||
my $single_image_y = 0 ;
|
||||
$single_image_y < $dest_height + 255 ;
|
||||
$single_image_y += 255
|
||||
)
|
||||
{
|
||||
if ( $single_image_y >= $dest_height ) {
|
||||
last;
|
||||
}
|
||||
my $final_height = 255;
|
||||
if ( $single_image_y + 255 > $dest_height ) {
|
||||
$final_height = $dest_height - $single_image_y;
|
||||
}
|
||||
my $image_final = GD::Image->new( $dest_width, $final_height );
|
||||
$image_final->copy( $image_dest, 0, 0, 0, $single_image_y, $dest_width,
|
||||
$final_height );
|
||||
my ($alpha) = $image_final->colorAllocateAlpha( 0, 0, 0, 127 );
|
||||
$image_final->colorDeallocate($alpha);
|
||||
$image_final->colorAllocate( 255, 255, 255 );
|
||||
my $device = $self->device;
|
||||
$device->image($image_final);
|
||||
}
|
||||
}
|
||||
|
||||
sub split_text_lines( $self, $text, $max_width, $font, $font_size ) {
|
||||
my @return;
|
||||
my @lines;
|
||||
if ( !ref $text ) {
|
||||
@lines = map { $_ } split "\n", $text, -1;
|
||||
}
|
||||
else {
|
||||
my $i = 0;
|
||||
for my $element (@$text) {
|
||||
if ( ref $element ) {
|
||||
push @lines, $element;
|
||||
$i++;
|
||||
next;
|
||||
}
|
||||
$element = decode 'utf-8', $element;
|
||||
push @lines, $element;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
my $surface = Cairo::ImageSurface->create( 'argb32', 380, 100 );
|
||||
my $cr = Cairo::Context->create($surface);
|
||||
my $layout = Pango::Cairo::create_layout($cr);
|
||||
$layout->set_font_description($font);
|
||||
while (@lines) {
|
||||
my $current_line = $self->get_next_line( \@lines );
|
||||
my ( $w, $h ) =
|
||||
$self->_get_size_text( $cr, $layout, $font, $font_size, $current_line );
|
||||
my $final_line = [];
|
||||
my $remainder = [];
|
||||
if ( $w > $max_width ) {
|
||||
LOOP_SPLIT: while (1) {
|
||||
my $word = $self->get_word($current_line);
|
||||
if ( !defined $word ) {
|
||||
die 'wtf?';
|
||||
}
|
||||
my ( $w, $h ) =
|
||||
$self->_get_size_text( $cr, $layout, $font, $font_size,
|
||||
$self->join_line_with_word( $final_line, $word ) );
|
||||
if ( $w > $max_width ) {
|
||||
my ( $w_cutted_word, $h_cutted_word ) =
|
||||
$self->_get_size_text( $cr, $layout, $font, $font_size,
|
||||
[$word] );
|
||||
if ( $w_cutted_word > $max_width ) {
|
||||
my $i = 0;
|
||||
$final_line = $self->join_line_with_word( $final_line, $word );
|
||||
while (1) {
|
||||
my $possible_cut =
|
||||
$self->substr_line( $final_line, 0, $i );
|
||||
my ( $w_cutted_word, $h_cutted_word ) =
|
||||
$self->_get_size_text( $cr, $layout, $font, $font_size,
|
||||
$possible_cut );
|
||||
if ( $w_cutted_word > $max_width ) {
|
||||
$remainder =
|
||||
$self->substr_line( [ @$final_line, @$current_line ],
|
||||
$i - 1 );
|
||||
$final_line =
|
||||
$self->substr_line( $final_line, 0, $i - 1 );
|
||||
$current_line = $final_line;
|
||||
last LOOP_SPLIT;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
$remainder = $self->unshift_line_with_word( $word, $current_line );
|
||||
$current_line = $final_line;
|
||||
last;
|
||||
}
|
||||
$final_line = $self->join_line_with_word( $final_line, $word );
|
||||
}
|
||||
}
|
||||
$remainder->[0] =~ s/^\s+//
|
||||
if defined $remainder->[0] && !( ref $remainder->[0] );
|
||||
unshift @lines, @$remainder if scalar @$remainder > 0;
|
||||
push @return, $current_line;
|
||||
}
|
||||
return @return;
|
||||
}
|
||||
|
||||
sub substr_line( $self, $text, $offset, $how_much = undef ) {
|
||||
my $result = [];
|
||||
my $cur_offset = 0;
|
||||
my $element = 0;
|
||||
my $needed_offset = 0;
|
||||
while ( $cur_offset < $offset ) {
|
||||
if ( !defined $text->[$element] ) {
|
||||
die 'Overflow';
|
||||
}
|
||||
if ( ref $text->[$element] ) {
|
||||
$cur_offset += 1;
|
||||
}
|
||||
else {
|
||||
my $length = ( length $text->[$element] ) - 1;
|
||||
if ( $cur_offset + $length > $offset ) {
|
||||
$needed_offset = $offset - $cur_offset;
|
||||
last;
|
||||
}
|
||||
$cur_offset += $length;
|
||||
}
|
||||
$element++;
|
||||
}
|
||||
my $gotten = 0;
|
||||
while ( !defined $how_much || $gotten < $how_much ) {
|
||||
if ( !defined $text->[$element] ) {
|
||||
last;
|
||||
}
|
||||
if ( ref $text->[$element] ) {
|
||||
push @$result, $text->[$element];
|
||||
$gotten += 1;
|
||||
}
|
||||
else {
|
||||
my $substr_length = ( length $text->[$element] ) - $needed_offset;
|
||||
if ( defined $how_much && $gotten + $substr_length > $how_much ) {
|
||||
$substr_length = $how_much - $gotten;
|
||||
}
|
||||
$result = $self->join_line_with_word( $result, substr $text->[$element],
|
||||
$needed_offset, $substr_length );
|
||||
$needed_offset = 0;
|
||||
$gotten += $substr_length;
|
||||
}
|
||||
$element++;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub unshift_line_with_word( $self, $word, $line ) {
|
||||
my $result = [@$line];
|
||||
if ( defined $result->[0] && !ref $result->[0] ) {
|
||||
$result->[0] = $word . $result->[0];
|
||||
}
|
||||
else {
|
||||
unshift @$result, $word;
|
||||
}
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
sub join_line_with_word( $self, $line, $word ) {
|
||||
my $result = [@$line];
|
||||
if ( scalar @$result == 0
|
||||
|| scalar @$result == 0
|
||||
|| ref $word
|
||||
|| ref $result->[$#$result] )
|
||||
{
|
||||
push @$result, $word;
|
||||
}
|
||||
else {
|
||||
$result->[$#$result] .= $word;
|
||||
}
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
sub get_word($self, $line) {
|
||||
if ( ref $line->[0] ) {
|
||||
return shift @$line;
|
||||
}
|
||||
return unless @$line;
|
||||
$line->[0] =~ /^(\s*\S*)(.*)$/;
|
||||
if ( $2 eq '' ) {
|
||||
shift @$line;
|
||||
}
|
||||
else {
|
||||
$line->[0] = $2;
|
||||
}
|
||||
return $1;
|
||||
}
|
||||
|
||||
sub get_next_line($self, $lines) {
|
||||
my @result;
|
||||
my $last_is_image = 0;
|
||||
my $first = 1;
|
||||
my $finish = 0;
|
||||
state $calls = 0;
|
||||
$calls++;
|
||||
while (1) {
|
||||
my $current_line = shift @$lines;
|
||||
my $pre_split;
|
||||
my $post_split;
|
||||
if ( !defined $current_line ) {
|
||||
last;
|
||||
}
|
||||
if ( ( !( ref $current_line ) && !$first && !$last_is_image )
|
||||
|| ( $current_line =~ /^(.*?)?\n(.*)?$/s ) )
|
||||
{
|
||||
$pre_split = $1 if defined $1;
|
||||
$post_split = $2 if defined $2;
|
||||
$finish = 1;
|
||||
}
|
||||
$first = 0;
|
||||
$last_is_image = !!( ref $current_line );
|
||||
if ($finish) {
|
||||
if ($post_split) {
|
||||
push @result, $pre_split if $pre_split || $post_split;
|
||||
unshift @$lines, $post_split if $post_split;
|
||||
}
|
||||
else {
|
||||
unshift @$lines, $current_line;
|
||||
}
|
||||
last;
|
||||
}
|
||||
push @result, $current_line;
|
||||
}
|
||||
return \@result;
|
||||
}
|
||||
|
||||
sub print_text( $self, $text, $font_size ) {
|
||||
if ( !( ref $text ) ) {
|
||||
$text = decode 'utf-8', $text;
|
||||
}
|
||||
my $tempdir = Path::Tiny->tempdir;
|
||||
my $file = $tempdir->child('result.png');
|
||||
my $font = Pango::FontDescription->from_string(
|
||||
'Noto Sans CJK JP ' . ( $font_size - ( 2 * 50 / 30 ) ) );
|
||||
|
||||
my @lines = $self->split_text_lines( $text, 380, $font, $font_size );
|
||||
while (@lines) {
|
||||
my $current_line = shift @lines;
|
||||
my $height = $font_size * 30 / 17;
|
||||
my $surface = Cairo::ImageSurface->create( 'argb32', 380, $height );
|
||||
my $cr = Cairo::Context->create($surface);
|
||||
$cr->set_source_rgb( 1, 1, 1 );
|
||||
|
||||
$cr->rectangle( 0, 0, 380, $font_size * 30 / 17 );
|
||||
|
||||
$cr->fill;
|
||||
$cr->set_source_rgb( 0, 0, 0 );
|
||||
|
||||
my $x = 0;
|
||||
my $layout = Pango::Cairo::create_layout($cr);
|
||||
for my $part (@$current_line) {
|
||||
$cr->move_to( 0, 0 );
|
||||
if ( !ref $part ) {
|
||||
Pango::Cairo::update_layout( $cr, $layout );
|
||||
$layout->set_text($part);
|
||||
$layout->set_font_description($font);
|
||||
$cr->move_to( $x, 0 );
|
||||
my ($new_x) = $layout->get_pixel_size;
|
||||
$x += $new_x;
|
||||
Pango::Cairo::show_layout( $cr, $layout );
|
||||
next;
|
||||
}
|
||||
my $gd_image = $part;
|
||||
my $tempdir = Path::Tiny->tempdir( CLEANUP => 0 );
|
||||
my $image_file = $tempdir->child('out.png');
|
||||
$gd_image->_file($image_file);
|
||||
my $image = Cairo::ImageSurface->create_from_png($image_file);
|
||||
my $ori_width = $gd_image->width;
|
||||
my $ori_height = $gd_image->height;
|
||||
my $scale_w = $font_size / $ori_width;
|
||||
my $total_height = $font_size * 30 / 17 / $scale_w;
|
||||
my $scale_h = $scale_w;
|
||||
$cr->save;
|
||||
$cr->scale( $scale_w, $scale_h );
|
||||
$cr->set_source_surface(
|
||||
$image,
|
||||
$x / $scale_w,
|
||||
( $total_height - $x * $scale_w ) / 4
|
||||
);
|
||||
$cr->paint;
|
||||
$cr->restore;
|
||||
$x += $font_size;
|
||||
}
|
||||
|
||||
$surface->write_to_png( $file . '' );
|
||||
my $img = GD::Image->newFromPng( $file . '' );
|
||||
my $device = $self->device;
|
||||
$device->image($img);
|
||||
}
|
||||
}
|
||||
|
||||
sub print($self) {
|
||||
$self->device->print;
|
||||
}
|
||||
|
||||
sub print_n_lf($self, $n) {
|
||||
for (my $i = 0; $i < $n; $i++) {
|
||||
$self->device->lf;
|
||||
}
|
||||
}
|
||||
|
||||
sub _get_size_text( $self, $cr, $layout, $font, $font_size, $text ) {
|
||||
my $x = 0;
|
||||
my $i;
|
||||
for my $element (@$text) {
|
||||
$cr->move_to( $x, 0 );
|
||||
if ( ref $element ) {
|
||||
$x += $font_size;
|
||||
next;
|
||||
}
|
||||
$layout->set_text($element);
|
||||
$layout->set_font_description($font);
|
||||
my ($new_x) = $layout->get_pixel_size;
|
||||
$x += $new_x;
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
1;
|
30
lib/Exd/Utils.pm
Normal file
30
lib/Exd/Utils.pm
Normal file
@ -0,0 +1,30 @@
|
||||
package Exd::Utils;
|
||||
|
||||
use v5.40.0;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Path::Tiny;
|
||||
|
||||
sub get_gd_image($file) {
|
||||
$file = path($file);
|
||||
my ($extension) = $file =~ /\.(.*?)$/;
|
||||
my $tempdir = Path::Tiny->tempdir;
|
||||
my $new_image = $tempdir->child( 'image.' . $extension );
|
||||
die 'Could not use the convert command'
|
||||
if system 'convert', $file, '-background', 'white', '-alpha', 'remove',
|
||||
$new_image;
|
||||
$file = $new_image;
|
||||
my $image;
|
||||
if ( $file =~ /\.png$/ ) {
|
||||
$image = GD::Image->newFromPng( $file . '' );
|
||||
}
|
||||
elsif ( $file =~ /\.jpg$/ ) {
|
||||
$image = GD::Image->newFromJpeg( $file . '' );
|
||||
}
|
||||
else {
|
||||
die "$image format not recognized";
|
||||
}
|
||||
return $image;
|
||||
}
|
||||
1;
|
609
lib/Printer/ESCPOS.pm
Normal file
609
lib/Printer/ESCPOS.pm
Normal file
@ -0,0 +1,609 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS;
|
||||
|
||||
# PODNAME: Printer::ESCPOS
|
||||
# ABSTRACT: Interface for all thermal, dot-matrix and other receipt printers that support ESC-POS specification.
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
# Dependencies
|
||||
use 5.010;
|
||||
use Moo;
|
||||
use Class::Load;
|
||||
use Carp;
|
||||
use Type::Tiny;
|
||||
use aliased 'Printer::ESCPOS::Roles::Profile' => 'ESCPOSProfile';
|
||||
|
||||
|
||||
has driverType => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
|
||||
has profile => (
|
||||
is => 'ro',
|
||||
default => 'Generic',
|
||||
);
|
||||
|
||||
|
||||
has deviceFilePath => ( is => 'ro', );
|
||||
|
||||
|
||||
has portName => ( is => 'ro', );
|
||||
|
||||
|
||||
has deviceIP => ( is => 'ro', );
|
||||
|
||||
|
||||
has devicePort => (
|
||||
is => 'ro',
|
||||
default => '9100',
|
||||
);
|
||||
|
||||
|
||||
has baudrate => (
|
||||
is => 'ro',
|
||||
default => 38400,
|
||||
);
|
||||
|
||||
|
||||
has serialOverUSB => (
|
||||
is => 'ro',
|
||||
default => '1',
|
||||
);
|
||||
|
||||
|
||||
has vendorId => ( is => 'ro', );
|
||||
|
||||
|
||||
has productId => ( is => 'ro', );
|
||||
|
||||
|
||||
has endPoint => (
|
||||
is => 'ro',
|
||||
default => 0x01,
|
||||
);
|
||||
|
||||
|
||||
has timeout => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
default => 1000,
|
||||
);
|
||||
|
||||
has _driver => (
|
||||
is => 'lazy',
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
sub _build__driver {
|
||||
my ($self) = @_;
|
||||
|
||||
if ( $self->driverType eq 'File' ) {
|
||||
Class::Load::load_class('Printer::ESCPOS::Connections::File');
|
||||
return Printer::ESCPOS::Connections::File->new(
|
||||
deviceFilePath => $self->deviceFilePath, );
|
||||
}
|
||||
elsif ( $self->driverType eq 'Network' ) {
|
||||
Class::Load::load_class('Printer::ESCPOS::Connections::Network');
|
||||
return Printer::ESCPOS::Connections::Network->new(
|
||||
deviceIP => $self->deviceIP,
|
||||
devicePort => $self->devicePort,
|
||||
);
|
||||
}
|
||||
elsif ( $self->driverType eq 'Serial' ) {
|
||||
Class::Load::load_class('Printer::ESCPOS::Connections::Serial');
|
||||
return Printer::ESCPOS::Connections::Serial->new(
|
||||
deviceFilePath => $self->deviceFilePath,
|
||||
baudrate => $self->baudrate,
|
||||
serialOverUSB => $self->serialOverUSB,
|
||||
);
|
||||
}
|
||||
elsif ( $self->driverType eq 'USB' ) {
|
||||
Class::Load::load_class('Printer::ESCPOS::Connections::USB');
|
||||
return Printer::ESCPOS::Connections::USB->new(
|
||||
productId => $self->productId,
|
||||
vendorId => $self->vendorId,
|
||||
endPoint => $self->endPoint,
|
||||
timeout => $self->timeout,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
has printer => ( is => 'lazy', );
|
||||
|
||||
sub _build_printer {
|
||||
my ($self) = @_;
|
||||
|
||||
my $base = __PACKAGE__ . "::Profiles::";
|
||||
my $class = $base . $self->profile;
|
||||
|
||||
Class::Load::load_class($class);
|
||||
unless ( $class->does(ESCPOSProfile) ) {
|
||||
confess
|
||||
"Class ${class} in ${base} does not implement the Printer::ESCPOS::Roles::Profile Interface";
|
||||
}
|
||||
my $object = $class->new( driver => $self->_driver, );
|
||||
|
||||
$object->init();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
no Moo;
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS - Interface for all thermal, dot-matrix and other receipt printers that support ESC-POS specification.
|
||||
|
||||
|
||||
|
||||
=begin html
|
||||
|
||||
<p>
|
||||
<img src="https://img.shields.io/badge/perl-5.10+-brightgreen.svg" alt="Requires Perl 5.10+" />
|
||||
<a href="https://travis-ci.org/shantanubhadoria/perl-Printer-ESCPOS"><img src="https://api.travis-ci.org/shantanubhadoria/perl-Printer-ESCPOS.svg?branch=build/master" alt="Travis status" /></a>
|
||||
<a href="http://matrix.cpantesters.org/?dist=Printer-ESCPOS%201.006"><img src="http://badgedepot.code301.com/badge/cpantesters/Printer-ESCPOS/1.006" alt="CPAN Testers result" /></a>
|
||||
<a href="http://cpants.cpanauthors.org/release/_/Printer-ESCPOS-1.006"><img src="http://badgedepot.code301.com/badge/kwalitee/_/Printer-ESCPOS/1.006" alt="Distribution kwalitee" /></a>
|
||||
<a href="https://gratipay.com/shantanubhadoria"><img src="https://img.shields.io/gratipay/shantanubhadoria.svg" alt="Gratipay" /></a>
|
||||
</p>
|
||||
|
||||
=end html
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
If you are just starting up with POS RECEIPT Printers, you must first refer to L<Printer::ESCPOS::Manual> to get started.
|
||||
|
||||
Printer::ESCPOS provides four different types of printer connections to talk to a ESCPOS printer.
|
||||
As of v0.012 I<driverType> B<Serial>, B<Network>, B<File> and B<USB> are all implemented in this module. B<USB> I<driverType>
|
||||
is not supported prior to v0.012.
|
||||
|
||||
=head2 USB Printer
|
||||
|
||||
B<USB> I<driverType> allows you to talk to your Printer using the I<vendorId> and I<productId> values for your printer.
|
||||
These can be retrieved using lsusb command
|
||||
|
||||
shantanu@shantanu-G41M-ES2L:~/github$ lsusb
|
||||
. . .
|
||||
Bus 003 Device 002: ID 1504:0006
|
||||
. . .
|
||||
|
||||
The output gives us the I<vendorId> 0x1504 and I<productId> 0x0006
|
||||
|
||||
For USB Printers L<Printer::ESCPOS> uses a default I<endPoint> of 0x01 and a default I<timeout> of
|
||||
1000, however these can be specified manually in case your printer requires a different value.
|
||||
|
||||
use Printer::ESCPOS;
|
||||
|
||||
my $vendorId = 0x1504;
|
||||
my $productId = 0x0006;
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'USB',
|
||||
vendorId => $vendorId,
|
||||
productId => $productId,
|
||||
);
|
||||
|
||||
use GD;
|
||||
my $img = newFromGif GD::Image('header.gif') || die "Error $!";
|
||||
$device->printer->image($img); # Takes a GD image object
|
||||
|
||||
$device->printer->qr("Don't Panic!"); # Print a QR Code
|
||||
|
||||
$device->printer->printAreaWidth(5000);
|
||||
$device->printer->text("Print Area Width Modified\n");
|
||||
$device->printer->printAreaWidth(); # Reset to default
|
||||
$device->printer->text("print area width reset\n");
|
||||
$device->printer->tab();
|
||||
$device->printer->underline(1);
|
||||
$device->printer->text("underline on\n");
|
||||
$device->printer->invert(1);
|
||||
$device->printer->text("Inverted Text\n");
|
||||
$device->printer->justification('right');
|
||||
$device->printer->text("Right Justified\n");
|
||||
$device->printer->upsideDown(1);
|
||||
$device->printer->text("Upside Down\n");
|
||||
$device->printer->cutPaper();
|
||||
|
||||
$device->printer->print(); # Dispatch the above commands from module buffer to the Printer.
|
||||
|
||||
=head2 Network Printer
|
||||
|
||||
For Network Printers $port is 9100 in most cases but might differ depending on how
|
||||
you have configured your printer
|
||||
|
||||
use Printer::ESCPOS;
|
||||
|
||||
my $printer_id = '192.168.0.10';
|
||||
my $port = '9100';
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'Network',
|
||||
deviceIp => $printer_ip,
|
||||
devicePort => $port,
|
||||
);
|
||||
|
||||
# These commands won't actually send anything to the printer but will store all the
|
||||
# merged data including control codes to module buffer.
|
||||
$device->printer->printAreaWidth(7000);
|
||||
$device->printer->text("Print Area Width Modified\n");
|
||||
$device->printer->printAreaWidth(); # Reset to default
|
||||
$device->printer->text("print area width reset\n");
|
||||
$device->printer->tab();
|
||||
$device->printer->underline(1);
|
||||
$device->printer->text("underline on\n");
|
||||
$device->printer->invert(1);
|
||||
$device->printer->text("Inverted Text\n");
|
||||
$device->printer->justification('right');
|
||||
$device->printer->text("Right Justified\n");
|
||||
$device->printer->upsideDown(1);
|
||||
$device->printer->text("Upside Down\n");
|
||||
$device->printer->cutPaper();
|
||||
|
||||
$device->printer->print(); # Dispatch the above commands from module buffer to the Printer.
|
||||
# This command takes care of read text buffers for the printer.
|
||||
|
||||
=head2 Serial Printer
|
||||
|
||||
Use the B<Serial> I<driverType> for local printer connected on serial port(or a printer connected via
|
||||
a physical USB port in USB to Serial mode), check syslog(Usually under E<sol>varE<sol>logE<sol>syslog)
|
||||
for what device file was created for your printer when you connect it to your system(For
|
||||
plug and play printers). You may also use a Windows port name like 'COM1', 'COM2' etc. as
|
||||
deviceFilePath param when running this under windows. The Device::SerialPort claims to support this
|
||||
syntax. (Drop me a email if you are able to make it work in windows as I have not tested it out yet)
|
||||
|
||||
use Printer::ESCPOS;
|
||||
use Data::Dumper; # Just to get dumps of status functions supported for Serial driverType.
|
||||
|
||||
my $path = '/dev/ttyACM0';
|
||||
$device = Printer::ESCPOS->new(
|
||||
driverType => 'Serial',
|
||||
deviceFilePath => $path,
|
||||
);
|
||||
|
||||
say Dumper $device->printer->printerStatus();
|
||||
say Dumper $device->printer->offlineStatus();
|
||||
say Dumper $device->printer->errorStatus();
|
||||
say Dumper $device->printer->paperSensorStatus();
|
||||
|
||||
$device->printer->bold(1);
|
||||
$device->printer->text("Bold Text\n");
|
||||
$device->printer->bold(0);
|
||||
$device->printer->text("Bold Text Off\n");
|
||||
|
||||
$device->printer->print();
|
||||
|
||||
=head2 File(Direct to Device File) Printer
|
||||
|
||||
A B<File> I<driverType> is similar to the B<Serial> I<driverType> in all functionality except that it
|
||||
doesn't support the status functions for the printer. i.e. you will not be able to use
|
||||
printerStatus, offlineStatus, errorStatus or paperSensorStatus functions
|
||||
|
||||
use Printer::ESCPOS;
|
||||
|
||||
my $path = '/dev/usb/lp0';
|
||||
$device = Printer::ESCPOS->new(
|
||||
driverType => 'File',
|
||||
deviceFilePath => $path,
|
||||
);
|
||||
|
||||
$device->printer->bold(1);
|
||||
$device->printer->text("Bold Text\n");
|
||||
$device->printer->bold(0);
|
||||
$device->printer->text("Bold Text Off\n");
|
||||
|
||||
$device->printer->print();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
You can use this module for all your ESC-POS Printing needs. If some of your printer's functions are not included, you
|
||||
may extend this module by adding specialized funtions for your printer in it's own subclass. Refer to
|
||||
L<Printer::ESCPOS::Roles::Profile> and L<Printer::ESCPOS::Profiles::Generic>
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=head2 driverType
|
||||
|
||||
"Required attribute". The driver type to use for your printer. This can be B<File>, B<Network>, B<USB> or B<Serial>.
|
||||
If you choose B<File> or B<Serial> driver, you must provide the I<deviceFilePath>,
|
||||
for B<Network> I<driverType> you must provide the I<printerIp> and I<printerPort>,
|
||||
For B<USB> I<driverType> you must provide I<vendorId> and I<productId>.
|
||||
|
||||
USB driver type:
|
||||
|
||||
my $vendorId = 0x1504;
|
||||
my $productId = 0x0006;
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'USB'
|
||||
vendorId => $vendorId,
|
||||
productId => $productId,
|
||||
);
|
||||
|
||||
Network driver type:
|
||||
|
||||
my $printer_id = '192.168.0.10';
|
||||
my $port = '9100';
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'Network',
|
||||
deviceIp => $printer_ip,
|
||||
devicePort => $port,
|
||||
);
|
||||
|
||||
Serial driver type:
|
||||
|
||||
my $path = '/dev/ttyACM0';
|
||||
$device = Printer::ESCPOS->new(
|
||||
driverType => 'Serial',
|
||||
deviceFilePath => $path,
|
||||
);
|
||||
|
||||
File driver type:
|
||||
|
||||
my $path = '/dev/usb/lp0';
|
||||
$device = Printer::ESCPOS->new(
|
||||
driverType => 'File',
|
||||
deviceFilePath => $path,
|
||||
);
|
||||
|
||||
=head2 profile
|
||||
|
||||
There are minor differences in ESC POS printers across different brands and models in terms of specifications and extra
|
||||
features. For using special features of a particular brand you may create a sub class in the name space
|
||||
Printer::ESCPOS::Profiles::* and load your profile here. I would recommend extending the Generic
|
||||
Profile( L<Printer::ESCPOS::Profiles::Generic> ).
|
||||
Use the following classes as examples.
|
||||
L<Printer::ESCPOS::Profiles::Generic>
|
||||
L<Printer::ESCPOS::Profiles::SinocanPSeries>
|
||||
|
||||
Note that your driver class will have to implement the Printer::ESCPOS::Roles::Profile Interface. This is a L<Moo::Role>
|
||||
and can be included in your class with the following line.
|
||||
|
||||
use Moo;
|
||||
with 'Printer::ESCPOS::Roles::Profile';
|
||||
|
||||
By default the generic profile is loaded but if you have written your own Printer::ESCPOS::Profile::* class and want to
|
||||
override the generic class pass the I<profile> Param during object creation.
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'Network',
|
||||
deviceIp => $printer_ip,
|
||||
devicePort => $port,
|
||||
profile => 'USERCUSTOM'
|
||||
);
|
||||
|
||||
The above $device object will use the Printer::ESCPOS::Profile::USERCUSTOM profile.
|
||||
|
||||
=head2 deviceFilePath
|
||||
|
||||
File path for UNIX device file. e.g. "/dev/ttyACM0", or port name for Win32 (untested) like 'COM1', COM2' etc. This is a
|
||||
mandatory parameter if you are using B<File> or B<Serial> I<driverType>. I haven't had a chance to test this on windows
|
||||
so if you are able to successfully use this with a serial port on windows, drop me a email to let me know that I got it
|
||||
right :)
|
||||
|
||||
=head2 portName
|
||||
|
||||
Win32 serial port name
|
||||
|
||||
=head2 deviceIP
|
||||
|
||||
Contains the IP address of the device when its a network printer. The module creates L<IO:Socket::INET> object to
|
||||
connect to the printer. This can be passed in the constructor.
|
||||
|
||||
=head2 devicePort
|
||||
|
||||
Contains the network port of the device when its a network printer. The module creates L<IO:Socket::INET> object to
|
||||
connect to the printer. This can be passed in the constructor.
|
||||
|
||||
=head2 baudrate
|
||||
|
||||
When used as a local serial device you can set the I<baudrate> of the printer too. Default (38400) will usually work,
|
||||
but not always.
|
||||
|
||||
=head2 serialOverUSB
|
||||
|
||||
Set this value to 1 if you are connecting your printer using the USB Cable but it shows up as a serial device and you
|
||||
are using the B<Serial> driver.
|
||||
|
||||
=head2 vendorId
|
||||
|
||||
This is a required param for B<USB> I<driverType>. It contains the USB printer's Vendor ID when using B<USB>
|
||||
I<driverType>. Use lsusb command to get this value for your printer.
|
||||
|
||||
=head2 productId
|
||||
|
||||
This is a required param for B<USB> I<driverType>. It contains the USB printer's product Id when using B<USB>
|
||||
I<driverType>. Use lsusb command to get this value for your printer.
|
||||
|
||||
=head2 endPoint
|
||||
|
||||
This is a optional param for B<USB> I<driverType>. It contains the USB endPoint for L<Device::USB> to write to if the
|
||||
value is not 0x01 for your printer. Get it using the following command:
|
||||
|
||||
shantanu@shantanu-G41M-ES2L:~$ sudo lsusb -vvv -d 1504:0006 | grep bEndpointAddress | grep OUT
|
||||
bEndpointAddress 0x01 EP 1 OUT
|
||||
|
||||
Replace 1504:0006 with your own printer's vendor id and product id in the above command.
|
||||
|
||||
=head2 timeout
|
||||
|
||||
Timeout for bulk write functions for the USB printer. Optional param.
|
||||
|
||||
=head2 printer
|
||||
|
||||
Use this attribute to send commands to the printer
|
||||
|
||||
$device->printer->setFont('a');
|
||||
$device->printer->text("blah blah blah\n");
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
Refer to the following manual to get started with L<Printer::ESCPOS>
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Manual>
|
||||
|
||||
=back
|
||||
|
||||
=head2 Quick usage summary in steps:
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
Create a device object $device by providing parameters for one of the supported printer types. Call
|
||||
$device-E<gt>printer-E<gt>init to initialize the printer.
|
||||
|
||||
=item 2.
|
||||
|
||||
call text() and other Text formatting functions on $device-E<gt>printer for the data to be sent to the printer. Make sure
|
||||
to end it all with a linefeed $device-E<gt>printer-E<gt>lf().
|
||||
|
||||
=item 3.
|
||||
|
||||
Then call the print() method to dispatch the sequences from the module buffer to the printer
|
||||
|
||||
=back
|
||||
|
||||
$device->printer->print()
|
||||
|
||||
Note: While you may call print() after every single command code, this is not advisable as some printers tend to choke
|
||||
up if you send them too many print commands in quick succession. To avoid this, aggregate the data to be sent to the
|
||||
printer with text() and other text formatting functions and then send it all in one go using print() at the very end.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
In Serial mode if the printer prints out garbled characters instead of proper text, try specifying the baudrate
|
||||
parameter when you create the printer object. The default baudrate is set at 38400
|
||||
|
||||
=back
|
||||
|
||||
$device = Printer::ESCPOS->new(
|
||||
driverType => 'Serial',
|
||||
deviceFilePath => $path,
|
||||
baudrate => 9600,
|
||||
);
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
For ESC-P codes refer the guide from Epson L<http://support.epson.ru/upload/library_file/14/esc-p.pdf>
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Manual>
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Profiles::Generic>
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Profiles::SinocanPSeries>
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Roles::Profile>
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Roles::Connection>
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Connections::USB>
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Connections::Serial>
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Connections::Network>
|
||||
|
||||
=item *
|
||||
|
||||
L<Printer::ESCPOS::Connections::File>
|
||||
|
||||
=back
|
||||
|
||||
=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
=head2 Bugs / Feature Requests
|
||||
|
||||
Please report any bugs or feature requests through github at
|
||||
L<https://github.com/shantanubhadoria/perl-printer-escpos/issues>.
|
||||
You will be notified automatically of any progress on your issue.
|
||||
|
||||
=head2 Source Code
|
||||
|
||||
This is open source software. The code repository is available for
|
||||
public review and contribution under the terms of the license.
|
||||
|
||||
L<https://github.com/shantanubhadoria/perl-printer-escpos>
|
||||
|
||||
git clone git://github.com/shantanubhadoria/perl-printer-escpos.git
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 CONTRIBUTORS
|
||||
|
||||
=for stopwords Dominic Sonntag Shantanu Bhadoria
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Dominic Sonntag <dominic@s5g.de>
|
||||
|
||||
=item *
|
||||
|
||||
Shantanu Bhadoria <shantanu att cpan dott org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
77
lib/Printer/ESCPOS/Connections/File.pm
Normal file
77
lib/Printer/ESCPOS/Connections/File.pm
Normal file
@ -0,0 +1,77 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS::Connections::File;
|
||||
|
||||
# PODNAME: Printer::ESCPOS::Connections::File
|
||||
# ABSTRACT: Bare Device File Connection Interface for L<Printer::ESCPOS>
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
# Dependencies
|
||||
|
||||
use 5.010;
|
||||
use Moo;
|
||||
with 'Printer::ESCPOS::Roles::Connection';
|
||||
|
||||
use IO::File;
|
||||
|
||||
|
||||
has deviceFilePath => ( is => 'ro', );
|
||||
|
||||
has _connection => (
|
||||
is => 'lazy',
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
sub _build__connection {
|
||||
my ($self) = @_;
|
||||
my $printer;
|
||||
|
||||
$printer = new IO::File ">>" . $self->deviceFilePath;
|
||||
|
||||
return $printer;
|
||||
}
|
||||
|
||||
no Moo;
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS::Connections::File - Bare Device File Connection Interface for L<Printer::ESCPOS>
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=head2 deviceFilePath
|
||||
|
||||
This variable contains the path for the printer device file on UNIX-like systems.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
113
lib/Printer/ESCPOS/Connections/Network.pm
Normal file
113
lib/Printer/ESCPOS/Connections/Network.pm
Normal file
@ -0,0 +1,113 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS::Connections::Network;
|
||||
|
||||
# PODNAME: Printer::ESCPOS::Connections::Network
|
||||
# ABSTRACT: Network Connection Interface for L<Printer::ESCPOS>
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
# Dependencies
|
||||
|
||||
use 5.010;
|
||||
use Moo;
|
||||
with 'Printer::ESCPOS::Roles::Connection';
|
||||
|
||||
use IO::Socket;
|
||||
|
||||
|
||||
has deviceIP => ( is => 'ro', );
|
||||
|
||||
|
||||
has devicePort => (
|
||||
is => 'ro',
|
||||
default => '9100',
|
||||
);
|
||||
|
||||
has _connection => (
|
||||
is => 'lazy',
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
sub _build__connection {
|
||||
my ($self) = @_;
|
||||
my $printer;
|
||||
|
||||
$printer = IO::Socket::INET->new(
|
||||
Proto => "tcp",
|
||||
PeerAddr => $self->deviceIP,
|
||||
PeerPort => $self->devicePort,
|
||||
Timeout => 1,
|
||||
) or die " Can't connect to printer";
|
||||
|
||||
return $printer;
|
||||
}
|
||||
|
||||
|
||||
sub read {
|
||||
my ( $self, $question, $bytes ) = @_;
|
||||
my $data;
|
||||
$bytes ||= 2;
|
||||
|
||||
say unpack( "H*", $question );
|
||||
$self->_connection->write($question);
|
||||
$self->_connection->read( $data, $bytes );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
no Moo;
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS::Connections::Network - Network Connection Interface for L<Printer::ESCPOS>
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=head2 deviceIP
|
||||
|
||||
Contains the IP address of the device when its a network printer. The module creates IO:Socket::INET object to connect
|
||||
to the printer. This can be passed in the constructor.
|
||||
|
||||
=head2 devicePort
|
||||
|
||||
Contains the network port of the device when its a network printer. The module creates IO:Socket::INET object to connect
|
||||
to the printer. This can be passed in the constructor.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 read
|
||||
|
||||
Read Data from the printer
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
168
lib/Printer/ESCPOS/Connections/Serial.pm
Normal file
168
lib/Printer/ESCPOS/Connections/Serial.pm
Normal file
@ -0,0 +1,168 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS::Connections::Serial;
|
||||
|
||||
# PODNAME: Printer::ESCPOS::Connections::Serial
|
||||
# ABSTRACT: Serial Connection Interface for L<Printer::ESCPOS> (supports status commands)
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
# Dependencies
|
||||
|
||||
use 5.010;
|
||||
use Moo;
|
||||
with 'Printer::ESCPOS::Roles::Connection';
|
||||
|
||||
use Device::SerialPort;
|
||||
use Time::HiRes qw(usleep);
|
||||
|
||||
|
||||
has deviceFilePath => ( is => 'ro', );
|
||||
|
||||
|
||||
has baudrate => (
|
||||
is => 'ro',
|
||||
default => 38400,
|
||||
);
|
||||
|
||||
|
||||
has readConstTime => (
|
||||
is => 'ro',
|
||||
default => 150,
|
||||
);
|
||||
|
||||
|
||||
has serialOverUSB => (
|
||||
is => 'rw',
|
||||
default => '0',
|
||||
);
|
||||
|
||||
has _connection => (
|
||||
is => 'lazy',
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
sub _build__connection {
|
||||
my ($self) = @_;
|
||||
|
||||
my $printer = new Device::SerialPort( $self->deviceFilePath )
|
||||
|| die "Can't open Port: $!\n";
|
||||
$printer->baudrate( $self->baudrate );
|
||||
$printer->read_const_time( $self->readConstTime )
|
||||
; # 1 second per unfulfilled "read" call
|
||||
$printer->read_char_time(0); # don't wait for each character
|
||||
|
||||
return $printer;
|
||||
}
|
||||
|
||||
|
||||
sub read {
|
||||
my ( $self, $question, $bytes ) = @_;
|
||||
$bytes |= 1024;
|
||||
|
||||
$self->_connection->write($question);
|
||||
my ( $count, $data ) = $self->_connection->read($bytes);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
sub print {
|
||||
my ( $self, $raw ) = @_;
|
||||
my @chunks;
|
||||
|
||||
my $buffer = $self->_buffer;
|
||||
if ( defined $raw ) {
|
||||
$buffer = $raw;
|
||||
}
|
||||
else {
|
||||
$self->_buffer('');
|
||||
}
|
||||
|
||||
my $n = 8; # Size of each chunk in bytes
|
||||
$n = 64 if ( $self->serialOverUSB );
|
||||
|
||||
@chunks = unpack "a$n" x ( ( length($buffer) / $n ) - 1 ) . "a*", $buffer;
|
||||
for my $chunk (@chunks) {
|
||||
$self->_connection->write($chunk);
|
||||
if ( $self->serialOverUSB ) {
|
||||
$self->_connection->read();
|
||||
}
|
||||
else {
|
||||
usleep(10000)
|
||||
; # Serial Port is annoying, it doesn't tell you when it is ready to get the next chunk
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
no Moo;
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS::Connections::Serial - Serial Connection Interface for L<Printer::ESCPOS> (supports status commands)
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=head2 deviceFilePath
|
||||
|
||||
This variable contains the path for the printer device file like '/dev/ttyS0' when connected as a serial device on
|
||||
UNIX-like systems. For Windows this will be the serial port name like 'COM1', 'COM2' etc. This must be passed in the
|
||||
constructor. I haven't tested this on windows, so if you are able to use serial port successfully on windows, drop me a
|
||||
email to let me know that I got it right :)
|
||||
|
||||
=head2 baudrate
|
||||
|
||||
When used as a local serial device you can set the baudrate of the printer too. Default (38400) will usually work, but
|
||||
not always.This param may be specified when creating printer object to make sure it works properly.
|
||||
|
||||
$printer = Printer::Thermal->new(deviceFilePath => '/dev/ttyACM0', baudrate => 9600);
|
||||
|
||||
=head2 readConstTime
|
||||
|
||||
Seconds per unfulfilled read call, default 150
|
||||
|
||||
=head2 serialOverUSB
|
||||
|
||||
Set this value to 1 if you are connecting your printer using the USB Cable but it shows up as a serial device
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 read
|
||||
|
||||
Read Data from the printer
|
||||
|
||||
=head2 print
|
||||
|
||||
Sends buffer data to the printer.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
211
lib/Printer/ESCPOS/Connections/USB.pm
Normal file
211
lib/Printer/ESCPOS/Connections/USB.pm
Normal file
@ -0,0 +1,211 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS::Connections::USB;
|
||||
|
||||
# PODNAME: Printer::ESCPOS::Connections::USB
|
||||
# ABSTRACT: USB Connection Interface for L<Printer::ESCPOS>
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
# Dependencies
|
||||
|
||||
use 5.010;
|
||||
use Moo;
|
||||
with 'Printer::ESCPOS::Roles::Connection';
|
||||
|
||||
use Device::USB;
|
||||
use Time::HiRes qw(usleep);
|
||||
|
||||
|
||||
has vendorId => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
|
||||
has productId => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
|
||||
has endPoint => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
default => 0x01,
|
||||
);
|
||||
|
||||
|
||||
has timeout => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
default => 1000,
|
||||
);
|
||||
|
||||
has _connection => (
|
||||
is => 'lazy',
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
sub _build__connection {
|
||||
my ($self) = @_;
|
||||
|
||||
my $usb = Device::USB->new();
|
||||
my $device = $usb->find_device( $self->vendorId, $self->productId );
|
||||
|
||||
if ( $device->get_driver_np(0) ) {
|
||||
$device->detach_kernel_driver_np();
|
||||
}
|
||||
$device->open();
|
||||
$device->reset();
|
||||
|
||||
return $device;
|
||||
}
|
||||
|
||||
|
||||
sub read {
|
||||
my ( $self, $question, $bytes ) = @_;
|
||||
my $data;
|
||||
$bytes |= 1024;
|
||||
|
||||
$self->_connection->bulk_write( $self->endPoint, $question,
|
||||
$self->timeout );
|
||||
$self->_connection->bulk_read( $self->endPoint, $data, $bytes,
|
||||
$self->timeout );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
sub print {
|
||||
my ( $self, $raw ) = @_;
|
||||
my @chunks;
|
||||
|
||||
my $buffer = $self->_buffer;
|
||||
if ( defined $raw ) {
|
||||
$buffer = $raw;
|
||||
}
|
||||
else {
|
||||
$self->_buffer('');
|
||||
}
|
||||
|
||||
my $n = 2**14; # Size of each chunk in bytes
|
||||
@chunks = unpack "a$n" x ( ( length($buffer) / $n ) - 1 ) . "a*", $buffer;
|
||||
for my $chunk (@chunks) {
|
||||
$self->_connection->bulk_write( $self->endPoint, $chunk,
|
||||
$self->timeout );
|
||||
usleep(10000)
|
||||
; # USB Port is sometimes annoying, it doesn't always tell you when it is ready to get the next chunk
|
||||
}
|
||||
}
|
||||
|
||||
no Moo;
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS::Connections::USB - USB Connection Interface for L<Printer::ESCPOS>
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
For using the printer in USB mode you will need to get a few details for your printer.
|
||||
|
||||
retrieve the I<vendorId> and I<productId> params using the lsusb command
|
||||
|
||||
shantanu@shantanu-G41M-ES2L:~$ lsusb
|
||||
Bus 002 Device 002: ID 8087:8000 Intel Corp.
|
||||
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
|
||||
Bus 001 Device 002: ID 8087:8008 Intel Corp.
|
||||
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
|
||||
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
|
||||
Bus 003 Device 020: ID 05e0:1200 Symbol Technologies Bar Code Scanner
|
||||
Bus 003 Device 005: ID 413c:2111 Dell Computer Corp.
|
||||
Bus 003 Device 004: ID 046d:c03e Logitech, Inc. Premium Optical Wheel Mouse (M-BT58)
|
||||
Bus 003 Device 009: ID 1cbe:0002 Luminary Micro Inc.
|
||||
Bus 003 Device 007: ID 0cf3:0036 Atheros Communications, Inc.
|
||||
Bus 003 Device 008: ID 1504:0006
|
||||
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
|
||||
|
||||
My printer shows up at the second to last line in the list.
|
||||
|
||||
Bus 003 Device 008: ID 1504:0006
|
||||
|
||||
The I<vendorId> and I<productId> for my printer is 0x1504 and 0x0006 respectively
|
||||
|
||||
Now to get the I<endPoint> value for my printer I use this command:
|
||||
|
||||
shantanu@shantanu-G41M-ES2L:~/test$ sudo lsusb -vvv -d 1504:0006 | grep bEndpointAddress | grep OUT
|
||||
bEndpointAddress 0x01 EP 1 OUT
|
||||
|
||||
The endpoint address is 0x01 which is the default for the module.
|
||||
|
||||
Now you have all the values you need for your printer to work in USB mode.
|
||||
|
||||
$device = Printer::ESCPOS->new(
|
||||
driverType => 'USB',
|
||||
vendorId => 0x1504,
|
||||
productId => 0x0006,
|
||||
endPoint => 0x01, # There is no need to specify endPOint in
|
||||
# this case as 0x01 is the default value
|
||||
);
|
||||
$device->printer->text("Blah Blah\n");
|
||||
$device->printer->print();
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=head2 vendorId
|
||||
|
||||
USB Printers VendorId. use lsusb command to get this value
|
||||
|
||||
=head2 productId
|
||||
|
||||
USB Printers product Id. use lsusb command to get this value
|
||||
|
||||
=head2 endPoint
|
||||
|
||||
USB endPoint to write to.
|
||||
|
||||
=head2 timeout
|
||||
|
||||
Timeout for bulk write functions for the USB printer.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 read
|
||||
|
||||
Read Data from the printer
|
||||
|
||||
=head2 print
|
||||
|
||||
Sends buffer data to the printer.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
735
lib/Printer/ESCPOS/Manual.pm
Normal file
735
lib/Printer/ESCPOS/Manual.pm
Normal file
@ -0,0 +1,735 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS::Manual;
|
||||
|
||||
# PODNAME: Printer::ESCPOS::Manual
|
||||
# ABSTRACT: Manual for Printing POS Receipts using L<Printer::ESCPOS>
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS::Manual - Manual for Printing POS Receipts using L<Printer::ESCPOS>
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
=head2 BASIC USAGE
|
||||
|
||||
use Printer::ESCPOS;
|
||||
|
||||
# Create a Printer object, Initialize the printer.
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'Serial'
|
||||
deviceFilePath => '/dev/ttyACM0'
|
||||
);
|
||||
|
||||
# All Printers have their own initialization
|
||||
# recommendations(Cleaning buffers etc.). Run
|
||||
# this command to let the module do this for you.
|
||||
$device->printer->init();
|
||||
|
||||
|
||||
# Prepare some data to send to the printer using
|
||||
# formatting and text commands
|
||||
$device->printer->bold(1);
|
||||
$device->printer->text("Heading text\n");
|
||||
$device->printer->bold(0);
|
||||
$device->printer->text("Content here\n");
|
||||
$device->printer->text(". . .\n");
|
||||
|
||||
|
||||
# Add a cut paper command at the end to cut the receipt
|
||||
# This command will be ignored by your printer if it
|
||||
# doesn't have a paper cutter on it
|
||||
$device->printer->cutPaper();
|
||||
|
||||
|
||||
# Send the Prepared data to the printer.
|
||||
$device->printer->print();
|
||||
|
||||
=head1 PRINTING TO YOUR PRINTER IN THREE STEPS
|
||||
|
||||
L<Printer::ESCPOS> uses a three step mechanism for sending the data to the Printer i.e initialization, preparation of data to send to the printer, and finally sending the prepared data to the printer. Separation of preparation and printing steps allows L<Printer::ESCPOS> to deal with communication speed and buffer limitations found in most common ESCPOS printers.
|
||||
|
||||
=head2 INITIALIZATION
|
||||
|
||||
=head3 USB PRINTER
|
||||
|
||||
The B<USB> I<driverType> allows you to talk to a printer using its vendorId and productId as params.
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'USB',
|
||||
vendorId => 0x1504,
|
||||
productId => 0x0006,
|
||||
);
|
||||
|
||||
Optional parameters:
|
||||
|
||||
The driver uses a default I<endPoint> value of 0x01. To get valid values for I<endPoint> for your printer use the following command:
|
||||
|
||||
shantanu@shantanu-G41M-ES2L:~$ sudo lsusb -vvv -d 1504:0006 | grep bEndpointAddress | grep OUT
|
||||
bEndpointAddress 0x01 EP 1 OUT
|
||||
|
||||
Replace 1504:0006 with your own printer's vendor id and product id in the above command
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'USB',
|
||||
vendorId => 0x1504,
|
||||
productId => 0x0006,
|
||||
endPoint => 0x01,
|
||||
);
|
||||
|
||||
You may also specify USB device timeout, although default value(1000 ms) should be sufficient in most cases:
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'USB',
|
||||
vendorId => 0x1504,
|
||||
productId => 0x0006,
|
||||
endPoint => 0x01,
|
||||
timeout => 500,
|
||||
);
|
||||
|
||||
=head3 SERIAL PRINTER
|
||||
|
||||
The Mandatory parameters for a B<Serial> I<driverType> are I<driverType>( B<Serial> ) and I<deviceFilePath>
|
||||
This is the preferred I<driverType> for connecting to a printer. This connection type is valid for printers connected over serial ports or for printers connected on physical USB ports but showing up as B<Serial> devices(check syslog when you connect the printer). Note that not all printers show up as Serial devices when connected on USB port.
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'Serial',
|
||||
deviceFilePath => '/dev/ttyACM0',
|
||||
);
|
||||
|
||||
Optional parameters:
|
||||
|
||||
the driver uses 38400 as default baudrate. If necessary you can change this value by providing a I<baudrate> parameter.
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'Serial',
|
||||
deviceFilePath => '/dev/ttyACM0',
|
||||
baudrate => 9600,
|
||||
);
|
||||
|
||||
If your printer is not printing properly when connected on physical serial port try setting the flag I<serialOverUSB> to
|
||||
B<0> to tell L<Printer::ESCPOS> to use special buffer management optimizations for physical serial ports
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'Serial',
|
||||
deviceFilePath => '/dev/ttyACM0',
|
||||
baudrate => 9600,
|
||||
serialOverUSB => 0
|
||||
);
|
||||
|
||||
=head3 NETWORK PRINTER
|
||||
|
||||
The Mandatory parameters for a B<Network> I<driverType> are I<driverType>( B<Network> ), I<deviceIP> and I<devicePort>
|
||||
This is a I<driverType> for printers connected over a network.
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'Network',
|
||||
deviceIP => '10.0.13.108',
|
||||
devicePort => '9100',
|
||||
);
|
||||
|
||||
=head3 BASIC DEVICE FILE Driver
|
||||
|
||||
The Mandatory parameters for a B<File> I<driverType> are I<driverType>( B<File> ) and I<deviceFilePath>
|
||||
This Driver is included for those instances when your printing needs are simple(You don't want to check the printer for
|
||||
printer status etc. and are only interested in pushing data to the printer for printing) and B<Serial> driver type is
|
||||
just refusing to work altogether. In this I<driverType> the data is written directly to the printer device file and from
|
||||
there sent to the printer. This is the basic text method for ESCPOS printers and it almost always works but it doesn't
|
||||
allow you to read Printer Status which might not be a deal breaker for most people. This I<driverType> can also be used
|
||||
for Printers which connect on USB ports but don't show up as Serial devices in syslog
|
||||
|
||||
my $device = Printer::ESCPOS->new(
|
||||
driverType => 'File',
|
||||
deviceFilePath => '/dev/usb/lp0',
|
||||
);
|
||||
|
||||
=head2 PREPARING FORMATTED TEXT FOR PRINTER
|
||||
|
||||
In all the methods described below its assumed that variable C<<< $device >>> has been initialized using the appropriate
|
||||
connection to the printer with one of the driverTypes mentioned above.
|
||||
The following methods prepare the text and text formatting data to be sent to the printer.
|
||||
|
||||
=head3 qr
|
||||
|
||||
Prints a qr code to the printer. In Generic profile, this creates a QR Code image using LE<lt>GD::Barcode::QRcodeE<gt>. A native
|
||||
implementation may be created using a printer model specific profile.
|
||||
|
||||
$device->printer->qr('Print this QR Code');
|
||||
$device->printer->qr('WIFI:T:WPA;S:ShantanusWifi;P:wifipasswordhere;;') # Create a QR code for connecting to a Wifi
|
||||
|
||||
You may also pass in optional QR Code format parameters like Ecc, Version and moduleSize. Read more about these params
|
||||
at L<http://www.qrcode.com/en/about/version.html>.
|
||||
|
||||
my $ecc = 'L'; # Default value
|
||||
my $version = 5; # Default value
|
||||
my $moduleSize = 3; # Default value
|
||||
$device->printer->qr("Don't Panic!", $ecc, $version, $moduleSize);
|
||||
|
||||
You may also call align() before calling qr() to set alignment on the page.
|
||||
|
||||
=head3 utf8ImagedText
|
||||
|
||||
use utf8;
|
||||
|
||||
$device->printer->utf8ImagedText("Hello World",
|
||||
fontFamily => "Rubik",
|
||||
fontStyle => "Normal",
|
||||
fontSize => 25,
|
||||
lineHeight => 40
|
||||
);
|
||||
|
||||
This method uses native fonts to print utf8 compatible characters including international wide characters. This method
|
||||
is slower than direct text printing but it allows exceptional styling options allowing you to print text using system
|
||||
fonts in a wide range of font sizes and styles with many more choices than what a thermal printer otherwise provides.
|
||||
|
||||
In the background this function uses L<Pango> and L<Cairo> libraries to create a one line image from a given font styles,
|
||||
font family in a given font size. Note that you must not use this method to print more than a single line at a time.
|
||||
When you want to print the next line call this method again to print to the next line.
|
||||
|
||||
I<string>: String to be printed in the line.
|
||||
|
||||
I<fontFamily> (optional, default B<'Purisa'>): Font family to use. On linux systems with font config installed use the
|
||||
following command to choose from the list of available fonts:
|
||||
|
||||
fc-list | sed 's/.*:\(.*,\|\s\)\(.*\):.*/\2/'
|
||||
|
||||
You may also install more fonts from https:E<sol>E<sol>fonts.google.comE<sol> to your system fonts( copy the font to E<sol>usrE<sol>shareE<sol>fonts )
|
||||
|
||||
I<fontStyle> (optional, default B<'Normal'>): Font style like Bold, Normal, Italic etc.
|
||||
|
||||
I<fontSize> (optional, default B<20>): Font size
|
||||
|
||||
I<lineHeight> (optional, default B<42>): Line Height in pixels, make sure this is bigger than the font height in pixels for your chosen font size.
|
||||
|
||||
I<paperWidth> (optional, default B<500>): This is set to 500 pixels by default as this is the most common width for receipt printers. Change this
|
||||
as per your printer specs.
|
||||
|
||||
=head3 image
|
||||
|
||||
Prints a GD image object to the printer
|
||||
|
||||
use GD;
|
||||
|
||||
my $img = newFromGif GD::Image('header.gif') || die "Error $!";
|
||||
$device->printer->image($img);
|
||||
|
||||
=head3 text
|
||||
|
||||
Sends raw text to the printer.
|
||||
|
||||
$device->printer->text("Hello Printer::ESCPOS\n")
|
||||
|
||||
=head3 printAreaWidth
|
||||
|
||||
Sets the Print area width specified by width which is a int between B<0> to B<65535>
|
||||
|
||||
$device->printer->printAreaWidth( 255 );
|
||||
|
||||
Note: If you are using Printer::ESCPOS version prior to v1.* Please check documentation for older version of this module
|
||||
the nL and nH syntax for this method.
|
||||
|
||||
=head3 tabPositions
|
||||
|
||||
Sets horizontal tab positions for tab stops. Upto 32 tab positions can be set in most receipt printers.
|
||||
|
||||
$device->printer->tabPositions( 5, 9, 13 );
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
Default tab positions are usually in intervals of 8 chars (9, 17, 25) etc.
|
||||
|
||||
=back
|
||||
|
||||
=head3 tab
|
||||
|
||||
moves the cursor to next horizontal tab position like a C<<< "\t" >>>. This command is ignored unless the next horizontal tab
|
||||
position has been set. You may substitute this command with a C<<< "\t" >>> as well.
|
||||
|
||||
This
|
||||
|
||||
$device->printer->text("blah blah");
|
||||
$device->printer->tab();
|
||||
$device->printer->text("blah2 blah2");
|
||||
|
||||
is same as this
|
||||
|
||||
$device->printer->text("blah blah\tblah2 blah2");
|
||||
|
||||
=head3 lf
|
||||
|
||||
line feed. Moves to the next line. You can substitute this method with C<<< "\n" >>> in your print or text method e.g. :
|
||||
|
||||
This
|
||||
|
||||
$device->printer->text("blah blah");
|
||||
$device->printer->lf();
|
||||
$device->printer->text("blah2 blah2");
|
||||
|
||||
is same as this
|
||||
|
||||
$device->printer->text("blah blah\nblah2 blah2");
|
||||
|
||||
=head3 font
|
||||
|
||||
Set Font style, you can pass B<a>, B<b> or B<c>. Many printers don't support style B<c> and only have two supported styles.
|
||||
|
||||
$device->printer->font('a');
|
||||
$device->printer->text('Writing in Font A');
|
||||
$device->printer->font('b');
|
||||
$device->printer->text('Writing in Font B');
|
||||
|
||||
=head3 bold
|
||||
|
||||
Set bold mode B<0> for off and B<1> for on. Also called emphasized mode in some printer manuals
|
||||
|
||||
$device->printer->bold(1);
|
||||
$device->printer->text("This is Bold Text\n");
|
||||
$device->printer->bold(0);
|
||||
$device->printer->text("This is not Bold Text\n");
|
||||
|
||||
=head3 doubleStrike
|
||||
|
||||
Set double-strike mode B<0> for off and B<1> for on
|
||||
|
||||
$device->printer->doubleStrike(1);
|
||||
$device->printer->text("This is Double Striked Text\n");
|
||||
$device->printer->doubleStrike(0);
|
||||
$device->printer->text("This is not Double Striked Text\n");
|
||||
|
||||
=head3 underline
|
||||
|
||||
set underline, B<0> for off, B<1> for on and B<2> for double thickness
|
||||
|
||||
$device->printer->underline(1);
|
||||
$device->printer->text("This is Underlined Text\n");
|
||||
$device->printer->underline(2);
|
||||
$device->printer->text("This is Underlined Text with thicker underline\n");
|
||||
$device->printer->underline(0);
|
||||
$device->printer->text("This is not Underlined Text\n");
|
||||
|
||||
=head3 invert
|
||||
|
||||
Reverse whiteE<sol>black printing mode pass B<0> for off and B<1> for on
|
||||
|
||||
$device->printer->invert(1);
|
||||
$device->printer->text("This is Inverted Text\n");
|
||||
$device->printer->invert(0);
|
||||
$device->printer->text("This is not Inverted Text\n");
|
||||
|
||||
=head3 color
|
||||
|
||||
Most thermal printers support just one color, black. Some ESCPOS printers(especially dot matrix) also support a second
|
||||
color, usually red. In many models, this only works when the color is set at the beginning of a new line before any text
|
||||
is printed. Pass B<0> or B<1> to switch between the two colors.
|
||||
|
||||
$device->printer->lf();
|
||||
$device->printer->color(0); #black
|
||||
$device->printer->text("black");
|
||||
$device->printer->lf();
|
||||
$device->printer->color(1); #red
|
||||
$device->printer->text("Red");
|
||||
$device->printer->print();
|
||||
|
||||
=head3 justify
|
||||
|
||||
Set Justification. Options B<left>, B<right> and B<center>
|
||||
|
||||
$device->printer->justify( 'right' );
|
||||
$device->printer->text("This is right justified");
|
||||
|
||||
=head3 upsideDown
|
||||
|
||||
Sets Upside Down Printing onE<sol>off (pass B<0> or B<1>)
|
||||
|
||||
$device->printer->upsideDownPrinting(1);
|
||||
$device->printer->text("This text is upside down");
|
||||
|
||||
=head3 fontHeight
|
||||
|
||||
Set font height. Only supports B<0> or B<1> for printmode set to 1, supports values B<0>, B<1>, B<2>, B<3>, B<4>, B<5>, B<6> and
|
||||
B<7> for non-printmode state (default)
|
||||
|
||||
$device->printer->fontHeight(1);
|
||||
$device->printer->text("double height\n");
|
||||
$device->printer->fontHeight(2);
|
||||
$device->printer->text("triple height\n");
|
||||
$device->printer->fontHeight(3);
|
||||
$device->printer->text("quadruple height\n");
|
||||
. . .
|
||||
|
||||
=head3 fontWidth
|
||||
|
||||
Set font width. Only supports B<0> or B<1> for printmode set to 1, supports values B<0>, B<1>, B<2>, B<3>, B<4>, B<5>, B<6> and
|
||||
B<7> for non-printmode state (default)
|
||||
|
||||
$device->printer->fontWidth(1);
|
||||
$device->printer->text("double width\n");
|
||||
$device->printer->fontWidth(2);
|
||||
$device->printer->text("triple width\n");
|
||||
$device->printer->fontWidth(3);
|
||||
$device->printer->text("quadruple width\n");
|
||||
. . .
|
||||
|
||||
=head3 charSpacing
|
||||
|
||||
Sets character spacing. Takes a value between 0 and 255
|
||||
|
||||
$device->printer->charSpacing(5);
|
||||
$device->printer->text("Blah Blah Blah\n");
|
||||
$device->printer->print();
|
||||
|
||||
=head3 lineSpacing
|
||||
|
||||
Sets the line spacing i.e the spacing between each line of printout.
|
||||
|
||||
$device->printer->lineSpacing($spacing);
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
0 E<lt>= $spacing E<lt>= 255
|
||||
|
||||
=back
|
||||
|
||||
=head3 selectDefaultLineSpacing
|
||||
|
||||
Reverts to default line spacing for the printer
|
||||
|
||||
$device->printer->selectDefaultLineSpacing();
|
||||
|
||||
=head3 printPosition
|
||||
|
||||
Sets the distance from the beginning of the line to the position at which characters are to be printed.
|
||||
|
||||
$device->printer->printPosition( $length, $height );
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
0 E<lt>= $length E<lt>= 255
|
||||
|
||||
=item *
|
||||
|
||||
0 E<lt>= $height E<lt>= 255
|
||||
|
||||
=back
|
||||
|
||||
=head3 leftMargin
|
||||
|
||||
Sets the left margin for printing. Set the left margin at the beginning of a line. The printer ignores any data
|
||||
preceding this command on the same line in the buffer.
|
||||
|
||||
In page mode sets the left margin to leftMargin x (horizontal motion unit) from the left edge of the printable area
|
||||
|
||||
Left Margin, range: 0 to 65535. If the margin exceeds the printable area, the left margin is automatically set to the
|
||||
maximum value of the printable area.
|
||||
|
||||
$device->printer->leftMargin($leftMargin);
|
||||
|
||||
=head3 rot90
|
||||
|
||||
Rotate printout by 90 degrees
|
||||
|
||||
$device->printer->rot90(1);
|
||||
$device->printer->text("This is rotated 90 degrees\n");
|
||||
$device->printer->rot90(0);
|
||||
$device->printer->text("This is not rotated 90 degrees\n");
|
||||
|
||||
=head3 barcode
|
||||
|
||||
This method prints a barcode to the printer. This can be bundled with other text formatting commands at the appropriate
|
||||
point where you would like to print a barcode on your print out. takes argument I<barcode> as the barcode value.
|
||||
|
||||
In the simplest form you can use this command as follows:
|
||||
|
||||
#Default barcode printed in code93 system with a width of 2 and HRI Chars printed below the barcode
|
||||
$device->printer->barcode(
|
||||
barcode => 'SHANTANU BHADORIA',
|
||||
);
|
||||
|
||||
However there are several customizations available including barcode I<system>, I<font>, I<height> etc.
|
||||
|
||||
my $hripos = 'above';
|
||||
my $font = 'a';
|
||||
my $height = 100;
|
||||
my $system = 'UPC-A';
|
||||
$device->printer->barcode(
|
||||
HRIPosition => $hripos, # Position of Human Readable characters
|
||||
# 'none','above','below','aboveandbelow'
|
||||
font => $font, # Font for HRI characters. 'a' or 'b'
|
||||
height => $height, # no of dots in vertical direction
|
||||
system => $system, # Barcode system
|
||||
width => 2 # 2:0.25mm, 3:0.375mm, 4:0.5mm, 5:0.625mm, 6:0.75mm
|
||||
barcode => '123456789012', # Check barcode system you are using for allowed
|
||||
# characters in barcode
|
||||
);
|
||||
$device->printer->barcode(
|
||||
system => 'CODE39',
|
||||
HRIPosition => 'above',
|
||||
barcode => '*1-I.I/ $IA*',
|
||||
);
|
||||
$device->printer->barcode(
|
||||
system => 'CODE93',
|
||||
HRIPosition => 'above',
|
||||
barcode => 'Shan',
|
||||
);
|
||||
|
||||
Available barcode I<systems>:
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
UPC-A
|
||||
|
||||
=item *
|
||||
|
||||
UPC-C
|
||||
|
||||
=item *
|
||||
|
||||
JAN13
|
||||
|
||||
=item *
|
||||
|
||||
JAN8
|
||||
|
||||
=item *
|
||||
|
||||
CODE39
|
||||
|
||||
=item *
|
||||
|
||||
ITF
|
||||
|
||||
=item *
|
||||
|
||||
CODABAR
|
||||
|
||||
=item *
|
||||
|
||||
CODE93
|
||||
|
||||
=item *
|
||||
|
||||
CODE128
|
||||
|
||||
=back
|
||||
|
||||
=head3 printNVImage
|
||||
|
||||
Prints bit image stored in Non-Volatile (NV) memory of the printer.
|
||||
|
||||
$device->printer->printNVImage($flag);
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
$flag = 0 # Normal width and Normal Height
|
||||
|
||||
=item *
|
||||
|
||||
$flag = 1 # Double width and Normal Height
|
||||
|
||||
=item *
|
||||
|
||||
$flag = 2 # Normal width and Double Height
|
||||
|
||||
=item *
|
||||
|
||||
$flag = 3 # Double width and Double Height
|
||||
|
||||
=back
|
||||
|
||||
=head3 printImage
|
||||
|
||||
Prints bit image stored in Volatile memory of the printer. This image gets erased when printer is reset.
|
||||
|
||||
$device->printer->printImage($flag);
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
$flag = 0 # Normal width and Normal Height
|
||||
|
||||
=item *
|
||||
|
||||
$flag = 1 # Double width and Normal Height
|
||||
|
||||
=item *
|
||||
|
||||
$flag = 2 # Normal width and Double Height
|
||||
|
||||
=item *
|
||||
|
||||
$flag = 3 # Double width and Double Height
|
||||
|
||||
=back
|
||||
|
||||
=head3 cutPaper
|
||||
|
||||
Cuts the paper, if I<feed> is set to B<0> then printer doesnt feed paper to cutting position before cutting it. The
|
||||
default behavior is that the printer doesn't feed paper to cutting position before cutting. One pre-requisite line feed
|
||||
is automatically executed before paper cut though.
|
||||
|
||||
$device->printer->cutPaper( feed => 0 )
|
||||
|
||||
While not strictly a text formatting option, in receipt printer the cut paper instruction is sent along with the rest of
|
||||
the text and text formatting data and the printer cuts the paper at the appropriate points wherever this command is
|
||||
used.
|
||||
|
||||
=head3 drawerKickPulse
|
||||
|
||||
Trigger drawer kick. Used to open cash drawer connected to the printer. In some use cases it may be used to trigger
|
||||
other devices by close contact.
|
||||
|
||||
$device->printer->drawerKickPulse( $pin, $time );
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
$pin is either 0( for pin 2 ) and 1( for pin5 ) default value is 0
|
||||
|
||||
=item *
|
||||
|
||||
$time is a value between 1 to 8 and the pulse duration in multiples of 100ms. default value is 8
|
||||
|
||||
=back
|
||||
|
||||
For default values use without any params to kick drawer pin 2 with a 800ms pulse
|
||||
|
||||
$device->printer->drawerKickPulse();
|
||||
|
||||
Again like cutPaper command this is obviously not a text formatting command but this command is sent along with the rest
|
||||
of the text and text formatting data and the printer sends the pulse at the appropriate points wherever this command is
|
||||
used. While originally designed for triggering a cash drawer to open, in practice this port can be used for all sorts of
|
||||
devices like pulsing light, or sound alarm etc.
|
||||
|
||||
=head2 PRINTING
|
||||
|
||||
=head3 print
|
||||
|
||||
Once Initialization is done and the formatted text for printing is prepared using the above commands, its time to send
|
||||
these commands to printer. This is a single easy step.
|
||||
|
||||
$device->printer->print();
|
||||
|
||||
Why an extra print step to send this data to the printer?
|
||||
This is necessary because many printers have difficulty handling large amount of print data sent across in a single
|
||||
large stream. Separating the preparation of data from transmission of data to the printer allows L<Printer::ESCPOS> to do
|
||||
some buffer management and optimization in the way the entire data is sent to the printer with tiny timed breaks between
|
||||
chunks of data for a reliable printer output.
|
||||
|
||||
=head2 GETTING PRINTER HEALTH STATUS
|
||||
|
||||
The B<Serial> I<driverType> allows reading of printer health, paper and other status parameters from the printer.
|
||||
At the moment there are following commands available for getting printer status.
|
||||
|
||||
=head3 printerStatus
|
||||
|
||||
Returns printer status in a hashref.
|
||||
|
||||
return {
|
||||
drawer_pin3_high => $flags[5],
|
||||
offline => $flags[4],
|
||||
waiting_for_online_recovery => $flags[2],
|
||||
feed_button_pressed => $flags[1],
|
||||
};
|
||||
|
||||
=head3 offlineStatus
|
||||
|
||||
Returns a hashref for paper cover closed status, feed button pressed status, paper end stop status, and a aggregate
|
||||
error status either of which will prevent the printer from processing a printing request.
|
||||
|
||||
return {
|
||||
cover_is_closed => $flags[5],
|
||||
feed_button_pressed => $flags[4],
|
||||
paper_end => $flags[2],
|
||||
error => $flags[1],
|
||||
};
|
||||
|
||||
=head3 errorStatus
|
||||
|
||||
Returns hashref with error flags for auto_cutter_error, unrecoverable error and auto-recoverable error
|
||||
|
||||
return {
|
||||
auto_cutter_error => $flags[4],
|
||||
unrecoverable_error => $flags[2],
|
||||
autorecoverable_error => $flags[1],
|
||||
};
|
||||
|
||||
=head3 paperSensorStatus
|
||||
|
||||
Gets printer paper Sensor status. Returns a hashref with four sensor statuses. Two paper near end sensors and two paper
|
||||
end sensors for printers supporting this feature. The exact returned status might differ based on the make of your
|
||||
printer. If any of the flags is set to 1 it implies that the paper is out or near end.
|
||||
|
||||
return {
|
||||
paper_roll_near_end_sensor_1 => $flags[5],
|
||||
paper_roll_near_end_sensor_2 => $flags[4],
|
||||
paper_roll_status_sensor_1 => $flags[2],
|
||||
paper_roll_status_sensor_2 => $flags[1],
|
||||
};
|
||||
|
||||
=head3 inkStatusA
|
||||
|
||||
Only available for dot-matrix and other ink consuming printers. Gets printer ink status for inkA(usually black ink).
|
||||
Returns a hashref with ink statuses.
|
||||
|
||||
return {
|
||||
ink_near_end => $flags[5],
|
||||
ink_end => $flags[4],
|
||||
ink_cartridge_missing => $flags[2],
|
||||
cleaning_in_progress => $flags[1],
|
||||
};
|
||||
|
||||
=head3 inkStatusB
|
||||
|
||||
Only available for dot-matrix and other ink consuming printers. Gets printer ink status for inkB(usually red ink).
|
||||
Returns a hashref with ink statuses.
|
||||
|
||||
return {
|
||||
ink_near_end => $flags[5],
|
||||
ink_end => $flags[4],
|
||||
ink_cartridge_missing => $flags[2],
|
||||
};
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
1363
lib/Printer/ESCPOS/Profiles/Generic.pm
Normal file
1363
lib/Printer/ESCPOS/Profiles/Generic.pm
Normal file
File diff suppressed because it is too large
Load Diff
52
lib/Printer/ESCPOS/Profiles/SinocanPSeries.pm
Normal file
52
lib/Printer/ESCPOS/Profiles/SinocanPSeries.pm
Normal file
@ -0,0 +1,52 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS::Profiles::SinocanPSeries;
|
||||
|
||||
# PODNAME: Printer::ESCPOS::Profiles::SinocanPSeries
|
||||
# ABSTRACT: Sinocan P Series Profile for Printers for L<Printer::ESCPOS>.
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
# Dependencies
|
||||
use 5.010;
|
||||
use Moo;
|
||||
extends 'Printer::ESCPOS::Profiles::Generic';
|
||||
with 'Printer::ESCPOS::Roles::Profile';
|
||||
|
||||
no Moo;
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS::Profiles::SinocanPSeries - Sinocan P Series Profile for Printers for L<Printer::ESCPOS>.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
97
lib/Printer/ESCPOS/Roles/Connection.pm
Normal file
97
lib/Printer/ESCPOS/Roles/Connection.pm
Normal file
@ -0,0 +1,97 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS::Roles::Connection;
|
||||
|
||||
# PODNAME: Printer::ESCPOS::Roles::Connection
|
||||
# ABSTRACT: Role for Connection Classes for L<Printer::ESCPOS>
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
# Dependencies
|
||||
|
||||
use 5.010;
|
||||
use Moo::Role;
|
||||
|
||||
has _buffer => (
|
||||
is => 'rw',
|
||||
default => '',
|
||||
);
|
||||
|
||||
|
||||
sub write {
|
||||
my ( $self, $raw ) = @_;
|
||||
|
||||
$self->_buffer( $self->_buffer . $raw );
|
||||
}
|
||||
|
||||
|
||||
sub print {
|
||||
my ( $self, $raw ) = @_;
|
||||
my @chunks;
|
||||
|
||||
my $printString;
|
||||
if ( defined $raw ) {
|
||||
$printString = $raw;
|
||||
}
|
||||
else {
|
||||
$printString = $self->_buffer;
|
||||
$self->_buffer('');
|
||||
}
|
||||
my $n = 64; # Size of each chunk in bytes
|
||||
my $initial_pattern = "a$n" x int(length($printString) / $n - 1 );
|
||||
@chunks = unpack "a$n" x int( ( length($printString) / $n ) - 1 ) . "a*",
|
||||
$printString;
|
||||
for my $chunk (@chunks) {
|
||||
$self->_connection->write($chunk);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS::Roles::Connection - Role for Connection Classes for L<Printer::ESCPOS>
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 write
|
||||
|
||||
Writes prepared data to the module buffer. This data is dispatched to printer with print() method. The print method
|
||||
takes care of buffer control issues.
|
||||
|
||||
=head2 print
|
||||
|
||||
If a string is passed then it passes the string to the printer else passes the buffer data to the printer and clears
|
||||
the buffer.
|
||||
|
||||
$device->printer->print(); # Prints and clears the Buffer.
|
||||
$device->printer->print($raw); # Prints $raw
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
163
lib/Printer/ESCPOS/Roles/Profile.pm
Normal file
163
lib/Printer/ESCPOS/Roles/Profile.pm
Normal file
@ -0,0 +1,163 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
package Printer::ESCPOS::Roles::Profile;
|
||||
|
||||
# PODNAME: Printer::ESCPOS::Roles::Profile
|
||||
# ABSTRACT: Role for all Printer Profiles for L<Printer::ESCPOS>
|
||||
#
|
||||
# This file is part of Printer-ESCPOS
|
||||
#
|
||||
# This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify it under
|
||||
# the same terms as the Perl 5 programming language system itself.
|
||||
#
|
||||
our $VERSION = '1.006'; # VERSION
|
||||
|
||||
# Dependencies
|
||||
use 5.010;
|
||||
use Moo::Role;
|
||||
requires 'init';
|
||||
|
||||
|
||||
has driver => (
|
||||
is => 'rw',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
|
||||
has usePrintMode => (
|
||||
is => 'rw',
|
||||
default => '0',
|
||||
);
|
||||
|
||||
|
||||
has fontStyle => (
|
||||
is => 'rw',
|
||||
default => 'a',
|
||||
);
|
||||
|
||||
|
||||
has emphasizedStatus => (
|
||||
is => 'rw',
|
||||
default => 0,
|
||||
);
|
||||
|
||||
|
||||
has heightStatus => (
|
||||
is => 'rw',
|
||||
default => 0,
|
||||
);
|
||||
|
||||
|
||||
has widthStatus => (
|
||||
is => 'rw',
|
||||
default => 0,
|
||||
);
|
||||
|
||||
|
||||
has underlineStatus => (
|
||||
is => 'rw',
|
||||
default => 0,
|
||||
);
|
||||
|
||||
|
||||
sub text {
|
||||
my ( $self, $text ) = @_;
|
||||
$self->driver->write($text);
|
||||
}
|
||||
|
||||
|
||||
sub print {
|
||||
my ( $self, $text ) = @_;
|
||||
$self->driver->print($text);
|
||||
}
|
||||
|
||||
|
||||
sub read {
|
||||
my ( $self, $bytes ) = @_;
|
||||
if ( $self->driver->can('read') ) {
|
||||
return $self->driver->read($bytes);
|
||||
}
|
||||
else {
|
||||
die
|
||||
"read is not supported by the Printer Driver in use use a different driverType $!";
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Printer::ESCPOS::Roles::Profile - Role for all Printer Profiles for L<Printer::ESCPOS>
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 1.006
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=head2 driver
|
||||
|
||||
Stores the connection object from the Printer::ESCPOS::Connections::*. In any normal use case you must not modify this
|
||||
attribute.
|
||||
|
||||
=head2 usePrintMode
|
||||
|
||||
Use Print mode to set font, underline, double width, double height and emphasized if false uses the individual command
|
||||
ESC M n for font "c" ESC M is forced irrespective of this flag
|
||||
|
||||
=head2 fontStyle
|
||||
|
||||
Set ESC-POS Font pass "a" "b" or "c". Note "c" is not supported across all printers.
|
||||
|
||||
=head2 emphasizedStatus
|
||||
|
||||
Set/unset emphasized property
|
||||
|
||||
=head2 heightStatus
|
||||
|
||||
set unset double height property
|
||||
|
||||
=head2 widthStatus
|
||||
|
||||
set unset double width property
|
||||
|
||||
=head2 underlineStatus
|
||||
|
||||
Set/unset underline property
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 text
|
||||
|
||||
Sends raw text to the local buffer ready for sending this to the printer. This would contain a set of strings to print
|
||||
or ESCPOS Codes.
|
||||
|
||||
$device->printer->text("Hello World\n");
|
||||
|
||||
=head2 print
|
||||
|
||||
prints data in the buffer
|
||||
|
||||
=head2 read
|
||||
|
||||
Reads n bytes from the printer. This function is used internally to get printer statuses when supported.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Shantanu Bhadoria <shantanu@cpan.org> L<https://www.shantanubhadoria.com>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2017 by Shantanu Bhadoria.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
26
scripts/demo.pl
Normal file
26
scripts/demo.pl
Normal file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use v5.40.0;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Exd::Printer;
|
||||
use Exd::DeviceToImage;
|
||||
use Exd::DeviceToRawFile;
|
||||
use Exd::Utils;
|
||||
|
||||
{
|
||||
my $device = Exd::DeviceToImage->new( output_file => 'a.png' );
|
||||
my $printer = Exd::Printer->new( device => $device );
|
||||
|
||||
my $hoz = Exd::Utils::get_gd_image('scripts/hoz.jpg');
|
||||
|
||||
$printer->print_text(
|
||||
[ $hoz, ' The best software belongs to everybody ', $hoz ], 27 );
|
||||
$printer->image('scripts/hoz.jpg');
|
||||
$printer->print_n_lf(4);
|
||||
|
||||
$printer->print;
|
||||
}
|
||||
|
BIN
scripts/hoz.jpg
Normal file
BIN
scripts/hoz.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Loading…
Reference in New Issue
Block a user