Skip to content

Configuration

Jürgen Pabel edited this page Feb 27, 2024 · 6 revisions

General

Both the system-configuration (everything that circuitpython manages, including network connectivity) and application-configuration (specific to this escpos-server code) is contained in settings.toml - but the application-specific logic is inside "tables" (as the TOML spec calls them, "sections" is a more common term known from INI-files). Because CircuitPython doesn't parse (and thus not expose as environment vars) tables/sections in settings.toml, this application uses circuitpython_toml to load the application-specific configurations from settings.toml (circuitpython itself just ignores them).

WIFI

WIFI connectivity can either be configured using the circuitpython built-in settings (in the global table/section of settings.toml)

CIRCUITPY_WIFI_SSID = "<WIFI-SSID>"
CIRCUITPY_WIFI_PASSWORD = "<WIFI-PASSWORD>"

but these settings also always start the circuitpython web-workflow (providing a HTML-UI for managing the device). For connecting to a WIFI without the circuitpython web-workflow, you can configure these settings (in the global table/section of settings.toml)

WIFI_SSID = "<WIFI-SSID>"
WIFI_PSK = "<WIFI-PASSWORD>"

A technical implementation difference between those two is that the CIRCUITPY_WIFI_... settings will be used by circuitpython to connect to the WIFI even before the application (code.py) starts. The WIFI_... settings are used by the circuitpython-escpos-server application to connect to the WIFI as part of the startup-phase of the application (in code.py).

ESCPOS

The ESCPOS table/section in settings.toml is the root of the application-specific configuration and (currently) contains only two items:

SERVICES = [ "tcp" ]             # services that shall be started
PRINTERS = [ "black", "white" ]  # printers that shall receive printjobs

Both configuration items are TOML arrays/lists; the application iterates through them to start the corresponding (network) services and (attached) printers. Referenced services are configured in tables/sections with the given name and a prefix of "SERVICE:" while printers have a "PRINTER:" prefix. So for example:

[ESCPOS]
SERVICES = [ "tcp" ]             # services that shall be started
PRINTERS = [ "black", "white" ]  # printers that shall receive printjobs

[SERVICE:tcp]
...

[PRINTER:black]
...

[PRINTER:white]
...

For information about service- and printer-specific configuration items, skip to the corresponding sections.

The default logic is that services receive ESC/POS printjobs and send them to all (active) printers; this behavior can be modified using a PRINTER setting inside a given service configuration (see section below).

SERVICES

Services are configured inside tables/sections that carry a "SERVICE:" prefix plus the name of the service, as listed in the SERVICES setting in the ESCPOS table/section (see above). It is valid to declare service (sections) and not reference them, they won't be activated/started than.

The only (for all service tables/sections) mandatory configuration item is DRIVER, which points to the corresponding service implementation to use for this service. Depending on the service implementation, other configuration items may be required. Take for example the network service TCP that simply receives ESC/POS printjobs over TCP:

[SERVICE:tcp]
DRIVER = "TCP"
SERVER_IPV4 = "0.0.0.0"   # default = "0.0.0.0"
SERVER_PORT = 9100        # default = 9100
CLIENT_TIMEOUT = 5        # default = 3
PRINTERS = [ "black" ]    # default = all (active) printers

With this configuration (and assuming that "tcp" is listed in the SERVICES item in the ESCPOS table/section) the application at startup will load the python class that implements the TCP service and pass it "its" configuration (the IPv4 address to bind to, the TCP port and the client timeout). Due to the PRINTERS setting, any received printjob for this service is only passed to the printer named "black"; if that printer is not active (not connected or misconfigured) this service wouldn't serve any purpose (no output) and wouldn't be started.

Implemented DRIVER values are: "HTTP", "MQTT" and "TCP":

  • For DRIVER = "HTTP" the following configuration keys are used: SERVER_IPV4 (default="0.0.0.0"), SERVER_PORT (default=8080) and SERVER_PATH (default="/").
  • For DRIVER = "MQTT" the following configuration keys are used: BROKER_IPV4 (no default, mandatory), BROKER_USER (optional, as required by broker), BROKER_USER (optional, as required by broker) and BROKER_TOPIC (no default, mandatory).
  • For DRIVER = "TCP" the following configuration keys are used: SERVER_IPV4 (default="0.0.0.0"), SERVER_PORT (default=9100) and CLIENT_TIMEOUT (default=3).

PRINTERS

Printers are configured inside tables/sections that carry a "PRINTER:" prefix plus the name of the printer, as listed in the PRINTERS setting in the ESCPOS table/section (see above). It is valid to declare printer (sections) and not reference them, they won't be activated/started than.

The only (for all printer tables/sections) mandatory configuration item is DRIVER, which points to the corresponding printer implementation to use for this printer. Depending on the printer implementation, other configuration items may be required. Take for example the USB printer that sends printjobs to a USB-connected printer:

[PRINTER:black]
DRIVER = "USB"
USB_VID = "04b8"                           # mandatory, 04b8 = EPSON
USB_PID = "0e15"                           # mandatory, 0e15 = TM-T20II

With this configuration (and assuming that "black" is listed in the PRINTERS item in the ESCPOS table/section) the application at startup will load the python class that implements a USB printer and pass it "its" configuration (the USB VendorID and ProductID). Please note though, that for USB-based printers, an additional configuration is required: the USB host-port configuration, refer to the SYSTEM section below.

Implemented DRIVER values are: "USB", "SERIAL" and "DEBUG":

  • For DRIVER = "USB" the following settings are used: USB_VID (no default, mandatory) and USB_PID (no default, mandatory).
  • For DRIVER = "SERIAL" the following settings are used: PIN_TX (no default, mandatory), PIN_RX (no default, mandatory), SERIAL_BAUD (default=9600), SERIAL_BITS (default=8), SERIAL_PARITY (default="none", supported by circuitpython is also "even" and "odd"), SERIAL_STOPBITS (default=1, supported by circuitpython is also 2).
  • For DRIVER = "DEBUG" no settings are implemented.

SYSTEM

Configuration items in the SYSTEM table/section are used globally, so for example: USB-based printers need a USB host-port, which has to be instantiated only once an can be used by one-or-more connected USB-based printers. Instead of configuring the USB host-port in the corresponding printer section, it is configured in the SYSTEM section like so:

[SYSTEM]
USB_HOST_PIN_DP = "GP26"   # required for USB printer(s), specific to board; GP26 is a PicoW specific pin name
USB_HOST_PIN_DM = "GP27"   # required for USB printer(s), specific to board; GP27 is a PicoW specific pin name

The python class that implements USB-based printers will instantiate the USB host-port for the first USB-based printer and reuse it for (if any) other USB-based printers.

LOGGING

The logging configuration is (primarily) contained in the SYSTEM table/section:

[SYSTEM]
LOG_LEVEL = "INFO"
LOG_SERVER = "192.168.1.1"
LOG_PRINTER = "black"

This (default) log-level can be overridden by a setting within any printer or service table/section for that given instance (LOG_LEVEL="DEBUG"). A configured (and valid) LOG_SERVER item (an IPv4 address) activates sending log messages to a syslog-server on the network via UDP (port 514). A configured (and valid) LOG_PRINTER item (a printer name) sends the logs to that printer for printing (probably only useful in case of network outage issues or for some one-of odd debugging scenarios).

Especially relevant during application startup: the logging handler implementations of both LOG_SERVER and LOG_PRINTER implement a (non-persistent) message-queuing in RAM. So that no log messages should be lost if the log target is not ready yet (for LOG_PRINTER) or if the WIFI is temporarily offline (for LOG_SERVER).

Clone this wiki locally