"defined service is invalid. provide a service in the format domain.service" - esc/pos receipt printer integration

I am doing an extension to hook up a thermal receipt printer with home assistant for all kinds of notifications. The service code seems to be ok, but when trying to run the service in the developer console I get in german

Der definierte Dienst ist ungültig. Bitte stelle einen Dienst im Format domain.service bereit (which translates to what is written in the headline)

My manifest looks like this:

{
  "domain": "receipt_printer",
  "name": "ESC-POS Receipt Printer",
  "codeowners": [],
  "dependencies": [],
  "documentation": "https://www.web.de",
  "iot_class": "local_polling",
  "requirements": ["python-escpos==3.0"]
}

And the service implementation (init.py) looks like this:

import homeassistant.helpers.config_validation as cv
import voluptuous as vol
from homeassistant.core import ServiceCall
from homeassistant.helpers.entity_component import EntityComponent
from escpos.escpos import Escpos
from escpos.exceptions import Error

DOMAIN = "receipt_printer"

SERVICE_PRINT_RECEIPT = "print_receipt"
PRINT_RECEIPT_SCHEMA = vol.Schema(
    {
        vol.Required("message"): cv.string,
        vol.Required("printer_ip", default="192.168.1.100"): cv.string,
        vol.Required("printer_port", default=9100): cv.positive_int,
    }
)

CONFIG_SCHEMA = PRINT_RECEIPT_SCHEMA


async def async_setup(hass, config):
    component = EntityComponent(_LOGGER, DOMAIN, hass)

    async def handle_print_receipt(call: ServiceCall):
        message = call.data.get("message")
        printer_ip = call.data.get("printer_ip")
        printer_port = call.data.get("printer_port")

        try:
            printer = Escpos.Network(printer_ip, port=printer_port)
            printer.text(message)
            printer.cut()
        except Error as e:
            _LOGGER.error("Error printing receipt: %s", e)
            return False

        return True

    hass.services.async_register(
        DOMAIN, SERVICE_PRINT_RECEIPT, handle_print_receipt, schema=PRINT_RECEIPT_SCHEMA
    )

    return True

Could you please point me in the direction how to fix this?

The line CONFIG_SCHEMA = PRINT_RECEIPT_SCHEMA needs to change to another schema which is for loading the integration and not loading the service schema.

Could probably be as easy as CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN) and then you put receipt_printer: into config.yaml for loading the integration.

Then it should likely make you service register properly as domain.service_call_name

1 Like

pls find below the now working code:

import homeassistant.helpers.config_validation as cv
import voluptuous as vol
from homeassistant.core import ServiceCall
from homeassistant.helpers.entity_component import EntityComponent
from escpos import printer

import logging

_LOGGER = logging.getLogger(__name__)

DOMAIN = "receipt_printer"

SERVICE_PRINT_RECEIPT = "print_receipt"
PRINT_RECEIPT_SCHEMA = vol.Schema(
    {
        vol.Required("message"): cv.string,
        vol.Required("printer_ip", default="192.168.1.100"): cv.string,
        vol.Required("printer_port", default=9100): cv.positive_int,
    }
)

# CONFIG_SCHEMA = PRINT_RECEIPT_SCHEMA
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)


async def async_setup(hass, config):
    component = EntityComponent(_LOGGER, DOMAIN, hass)

    async def handle_print_receipt(call: ServiceCall):
        message = call.data.get("message")
        printer_ip = call.data.get("printer_ip")
        printer_port = call.data.get("printer_port")

        try:
            # printer = Escpos.Network(printer_ip, port=printer_port)
            _printer = printer.Network(host=printer_ip, port=printer_port)
            _printer.text(message)
            _printer.cut()
        except Exception as e:
            _LOGGER.error("Error printing receipt: %s", e)
            return False

        return True

    hass.services.async_register(
        DOMAIN, SERVICE_PRINT_RECEIPT, handle_print_receipt, schema=PRINT_RECEIPT_SCHEMA
    )

    print("Service registered.")

    return True