core/homeassistant/components/cups/sensor.py

148 lines
4.4 KiB
Python

"""
Details about printers which are connected to CUPS.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.cups/
"""
import importlib
import logging
from datetime import timedelta
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['pycups==1.9.73']
_LOGGER = logging.getLogger(__name__)
ATTR_DEVICE_URI = 'device_uri'
ATTR_PRINTER_INFO = 'printer_info'
ATTR_PRINTER_IS_SHARED = 'printer_is_shared'
ATTR_PRINTER_LOCATION = 'printer_location'
ATTR_PRINTER_MODEL = 'printer_model'
ATTR_PRINTER_STATE_MESSAGE = 'printer_state_message'
ATTR_PRINTER_STATE_REASON = 'printer_state_reason'
ATTR_PRINTER_TYPE = 'printer_type'
ATTR_PRINTER_URI_SUPPORTED = 'printer_uri_supported'
CONF_PRINTERS = 'printers'
DEFAULT_HOST = '127.0.0.1'
DEFAULT_PORT = 631
ICON = 'mdi:printer'
SCAN_INTERVAL = timedelta(minutes=1)
PRINTER_STATES = {
3: 'idle',
4: 'printing',
5: 'stopped',
}
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_PRINTERS): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
})
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the CUPS sensor."""
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
printers = config.get(CONF_PRINTERS)
try:
data = CupsData(host, port)
data.update()
except RuntimeError:
_LOGGER.error("Unable to connect to CUPS server: %s:%s", host, port)
return False
dev = []
for printer in printers:
if printer in data.printers:
dev.append(CupsSensor(data, printer))
else:
_LOGGER.error("Printer is not present: %s", printer)
continue
add_entities(dev, True)
class CupsSensor(Entity):
"""Representation of a CUPS sensor."""
def __init__(self, data, printer):
"""Initialize the CUPS sensor."""
self.data = data
self._name = printer
self._printer = None
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def state(self):
"""Return the state of the sensor."""
if self._printer is not None:
try:
return next(v for k, v in PRINTER_STATES.items()
if self._printer['printer-state'] == k)
except StopIteration:
return self._printer['printer-state']
@property
def icon(self):
"""Return the icon to use in the frontend, if any."""
return ICON
@property
def device_state_attributes(self):
"""Return the state attributes of the sensor."""
if self._printer is not None:
return {
ATTR_DEVICE_URI: self._printer['device-uri'],
ATTR_PRINTER_INFO: self._printer['printer-info'],
ATTR_PRINTER_IS_SHARED: self._printer['printer-is-shared'],
ATTR_PRINTER_LOCATION: self._printer['printer-location'],
ATTR_PRINTER_MODEL: self._printer['printer-make-and-model'],
ATTR_PRINTER_STATE_MESSAGE:
self._printer['printer-state-message'],
ATTR_PRINTER_STATE_REASON:
self._printer['printer-state-reasons'],
ATTR_PRINTER_TYPE: self._printer['printer-type'],
ATTR_PRINTER_URI_SUPPORTED:
self._printer['printer-uri-supported'],
}
def update(self):
"""Get the latest data and updates the states."""
self.data.update()
self._printer = self.data.printers.get(self._name)
# pylint: disable=no-name-in-module
class CupsData:
"""Get the latest data from CUPS and update the state."""
def __init__(self, host, port):
"""Initialize the data object."""
self._host = host
self._port = port
self.printers = None
def update(self):
"""Get the latest data from CUPS."""
cups = importlib.import_module('cups')
conn = cups.Connection(host=self._host, port=self._port)
self.printers = conn.getPrinters()