Current section

Files

Jump to
escpos src escpos@printer.erl
Raw

src/escpos@printer.erl

-module(escpos@printer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/escpos/printer.gleam").
-export([device/1, connect/2, print/2, disconnect/1]).
-export_type([command_buffer/0, printer/0, printer_error/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Functions for connecting to and communicating with ESC/POS printers.\n"
"\n"
" Supports both USB (device file) and network (TCP socket) connections.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" // USB printer\n"
" let assert Ok(printer) = printer.device(\"/dev/usb/lp0\")\n"
"\n"
" // Network printer\n"
" let assert Ok(printer) = printer.connect(\"192.168.1.100\", 9100)\n"
"\n"
" escpos.new()\n"
" |> escpos.writeln(\"Hello!\")\n"
" |> escpos.cut()\n"
" |> printer.print(printer)\n"
"\n"
" // Close network printer socket\n"
" printer.disconnect(printer)\n"
" ```\n"
).
-type command_buffer() :: {command_buffer, bitstring()}.
-opaque printer() :: {network_printer, mug:socket()} | {usb_printer, binary()}.
-opaque printer_error() :: {connection_failed, mug:connect_error()} |
{disconnection_failed, mug:error()} |
{transmission_error, mug:error()} |
{network_print_error, mug:error()} |
{usb_print_error, simplifile:file_error()} |
{usb_device_error, simplifile:file_error()}.
-file("src/escpos/printer.gleam", 51).
?DOC(
" Opens a USB printer by its device file path (e.g. `/dev/usb/lp0`) and writes\n"
" the initialization command.\n"
).
-spec device(binary()) -> {ok, printer()} | {error, printer_error()}.
device(Path) ->
case simplifile_erl:file_info(Path) of
{ok, _} ->
gleam@result:'try'(
begin
_pipe = simplifile_erl:write_bits(Path, <<(27), "@"/utf8>>),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {usb_device_error, Field@0} end
)
end,
fun(_) -> {ok, {usb_printer, Path}} end
);
{error, Err} ->
{error, {usb_device_error, Err}}
end.
-file("src/escpos/printer.gleam", 66).
?DOC(" Connects to a network printer over TCP and sends the initialization command.\n").
-spec connect(binary(), integer()) -> {ok, printer()} | {error, printer_error()}.
connect(Ip, Port) ->
gleam@result:'try'(
begin
_pipe = mug:new(Ip, Port),
_pipe@1 = mug:timeout(_pipe, 1000),
_pipe@2 = mug:connect(_pipe@1),
gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {connection_failed, Field@0} end
)
end,
fun(Socket) ->
gleam@result:'try'(
begin
_pipe@3 = mug:send(Socket, <<(27), "@"/utf8>>),
gleam@result:map_error(
_pipe@3,
fun(Field@0) -> {transmission_error, Field@0} end
)
end,
fun(_) -> {ok, {network_printer, Socket}} end
)
end
).
-file("src/escpos/printer.gleam", 86).
?DOC(
" Sends a command buffer to the printer.\n"
"\n"
" For network printers this writes to the TCP socket. For USB printers\n"
" this writes directly to the device file.\n"
).
-spec print(command_buffer(), printer()) -> {ok, nil} | {error, printer_error()}.
print(Cb, Printer) ->
case Printer of
{network_printer, Socket} ->
_pipe = mug:send(Socket, erlang:element(2, Cb)),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {network_print_error, Field@0} end
);
{usb_printer, Device} ->
_pipe@1 = simplifile_erl:write_bits(Device, erlang:element(2, Cb)),
gleam@result:map_error(
_pipe@1,
fun(Field@0) -> {usb_print_error, Field@0} end
)
end.
-file("src/escpos/printer.gleam", 98).
?DOC(" Closes the connection to a network printer. For USB printers this is a no-op.\n").
-spec disconnect(printer()) -> {ok, nil} | {error, printer_error()}.
disconnect(Printer) ->
case Printer of
{network_printer, Socket} ->
_pipe = mug_ffi:shutdown(Socket),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {disconnection_failed, Field@0} end
);
{usb_printer, _} ->
{ok, nil}
end.