mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Prevent errors on Octoprint sensors and binary_sensors when Octoprint and/or Printer are off (#8343)
* Added platformnotready * Only log the first failure if octoprint/printer isn't up Remove blank line
This commit is contained in:
parent
b67c5df525
commit
652c006cbc
@ -12,13 +12,12 @@ import voluptuous as vol
|
|||||||
from homeassistant.const import CONF_NAME, CONF_MONITORED_CONDITIONS
|
from homeassistant.const import CONF_NAME, CONF_MONITORED_CONDITIONS
|
||||||
from homeassistant.components.binary_sensor import (
|
from homeassistant.components.binary_sensor import (
|
||||||
BinarySensorDevice, PLATFORM_SCHEMA)
|
BinarySensorDevice, PLATFORM_SCHEMA)
|
||||||
from homeassistant.loader import get_component
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['octoprint']
|
DEPENDENCIES = ['octoprint']
|
||||||
|
DOMAIN = "octoprint"
|
||||||
DEFAULT_NAME = 'OctoPrint'
|
DEFAULT_NAME = 'OctoPrint'
|
||||||
|
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
@ -37,7 +36,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Set up the available OctoPrint binary sensors."""
|
"""Set up the available OctoPrint binary sensors."""
|
||||||
octoprint = get_component('octoprint')
|
octoprint_api = hass.data[DOMAIN]["api"]
|
||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
monitored_conditions = config.get(
|
monitored_conditions = config.get(
|
||||||
CONF_MONITORED_CONDITIONS, SENSOR_TYPES.keys())
|
CONF_MONITORED_CONDITIONS, SENSOR_TYPES.keys())
|
||||||
@ -45,7 +44,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
devices = []
|
devices = []
|
||||||
for octo_type in monitored_conditions:
|
for octo_type in monitored_conditions:
|
||||||
new_sensor = OctoPrintBinarySensor(
|
new_sensor = OctoPrintBinarySensor(
|
||||||
octoprint.OCTOPRINT, octo_type, SENSOR_TYPES[octo_type][2],
|
octoprint_api, octo_type, SENSOR_TYPES[octo_type][2],
|
||||||
name, SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
|
name, SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
|
||||||
SENSOR_TYPES[octo_type][1], 'flags')
|
SENSOR_TYPES[octo_type][1], 'flags')
|
||||||
devices.append(new_sensor)
|
devices.append(new_sensor)
|
||||||
@ -98,6 +97,3 @@ class OctoPrintBinarySensor(BinarySensorDevice):
|
|||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
# Error calling the api, already logged in api.update()
|
# Error calling the api, already logged in api.update()
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._state is None:
|
|
||||||
_LOGGER.warning("Unable to locate value for %s", self.sensor_type)
|
|
||||||
|
@ -17,8 +17,6 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
DOMAIN = 'octoprint'
|
DOMAIN = 'octoprint'
|
||||||
|
|
||||||
OCTOPRINT = None
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.Schema({
|
DOMAIN: vol.Schema({
|
||||||
vol.Required(CONF_API_KEY): cv.string,
|
vol.Required(CONF_API_KEY): cv.string,
|
||||||
@ -32,14 +30,15 @@ def setup(hass, config):
|
|||||||
base_url = 'http://{}/api/'.format(config[DOMAIN][CONF_HOST])
|
base_url = 'http://{}/api/'.format(config[DOMAIN][CONF_HOST])
|
||||||
api_key = config[DOMAIN][CONF_API_KEY]
|
api_key = config[DOMAIN][CONF_API_KEY]
|
||||||
|
|
||||||
global OCTOPRINT
|
hass.data[DOMAIN] = {"api": None}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
OCTOPRINT = OctoPrintAPI(base_url, api_key)
|
octoprint_api = OctoPrintAPI(base_url, api_key)
|
||||||
OCTOPRINT.get('printer')
|
hass.data[DOMAIN]["api"] = octoprint_api
|
||||||
OCTOPRINT.get('job')
|
octoprint_api.get('printer')
|
||||||
|
octoprint_api.get('job')
|
||||||
except requests.exceptions.RequestException as conn_err:
|
except requests.exceptions.RequestException as conn_err:
|
||||||
_LOGGER.error("Error setting up OctoPrint API: %r", conn_err)
|
_LOGGER.error("Error setting up OctoPrint API: %r", conn_err)
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -54,6 +53,11 @@ class OctoPrintAPI(object):
|
|||||||
'X-Api-Key': key}
|
'X-Api-Key': key}
|
||||||
self.printer_last_reading = [{}, None]
|
self.printer_last_reading = [{}, None]
|
||||||
self.job_last_reading = [{}, None]
|
self.job_last_reading = [{}, None]
|
||||||
|
self.job_available = False
|
||||||
|
self.printer_available = False
|
||||||
|
self.available = False
|
||||||
|
self.printer_error_logged = False
|
||||||
|
self.job_error_logged = False
|
||||||
|
|
||||||
def get_tools(self):
|
def get_tools(self):
|
||||||
"""Get the dynamic list of tools that temperature is monitored on."""
|
"""Get the dynamic list of tools that temperature is monitored on."""
|
||||||
@ -62,6 +66,7 @@ class OctoPrintAPI(object):
|
|||||||
|
|
||||||
def get(self, endpoint):
|
def get(self, endpoint):
|
||||||
"""Send a get request, and return the response as a dict."""
|
"""Send a get request, and return the response as a dict."""
|
||||||
|
# Only query the API at most every 30 seconds
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if endpoint == "job":
|
if endpoint == "job":
|
||||||
last_time = self.job_last_reading[1]
|
last_time = self.job_last_reading[1]
|
||||||
@ -73,28 +78,52 @@ class OctoPrintAPI(object):
|
|||||||
if last_time is not None:
|
if last_time is not None:
|
||||||
if now - last_time < 30.0:
|
if now - last_time < 30.0:
|
||||||
return self.printer_last_reading[0]
|
return self.printer_last_reading[0]
|
||||||
|
|
||||||
url = self.api_url + endpoint
|
url = self.api_url + endpoint
|
||||||
try:
|
try:
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
url, headers=self.headers, timeout=30)
|
url, headers=self.headers, timeout=9)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
if endpoint == "job":
|
if endpoint == "job":
|
||||||
self.job_last_reading[0] = response.json()
|
self.job_last_reading[0] = response.json()
|
||||||
self.job_last_reading[1] = time.time()
|
self.job_last_reading[1] = time.time()
|
||||||
|
self.job_available = True
|
||||||
elif endpoint == "printer":
|
elif endpoint == "printer":
|
||||||
self.printer_last_reading[0] = response.json()
|
self.printer_last_reading[0] = response.json()
|
||||||
self.printer_last_reading[1] = time.time()
|
self.printer_last_reading[1] = time.time()
|
||||||
|
self.printer_available = True
|
||||||
|
self.available = self.printer_available and self.job_available
|
||||||
|
if self.available:
|
||||||
|
self.job_error_logged = False
|
||||||
|
self.printer_error_logged = False
|
||||||
return response.json()
|
return response.json()
|
||||||
except (requests.exceptions.ConnectionError,
|
except (requests.exceptions.ConnectionError,
|
||||||
requests.exceptions.HTTPError) as conn_exc:
|
requests.exceptions.HTTPError,
|
||||||
_LOGGER.error("Failed to update OctoPrint status. Error: %s",
|
requests.exceptions.ReadTimeout) as conn_exc:
|
||||||
conn_exc)
|
log_string = "Failed to update OctoPrint status. " + \
|
||||||
|
" Error: %s" % (conn_exc)
|
||||||
|
# Only log the first failure
|
||||||
|
if endpoint == "job":
|
||||||
|
log_string = "Endpoint: job " + log_string
|
||||||
|
if not self.job_error_logged:
|
||||||
|
_LOGGER.error(log_string)
|
||||||
|
self.job_error_logged = True
|
||||||
|
self.job_available = False
|
||||||
|
elif endpoint == "printer":
|
||||||
|
log_string = "Endpoint: printer " + log_string
|
||||||
|
if not self.printer_error_logged:
|
||||||
|
_LOGGER.error(log_string)
|
||||||
|
self.printer_error_logged = True
|
||||||
|
self.printer_available = False
|
||||||
|
self.available = False
|
||||||
|
return None
|
||||||
|
|
||||||
def update(self, sensor_type, end_point, group, tool=None):
|
def update(self, sensor_type, end_point, group, tool=None):
|
||||||
"""Return the value for sensor_type from the provided endpoint."""
|
"""Return the value for sensor_type from the provided endpoint."""
|
||||||
response = self.get(end_point)
|
response = self.get(end_point)
|
||||||
if response is not None:
|
if response is not None:
|
||||||
return get_value_from_json(response, sensor_type, group, tool)
|
return get_value_from_json(response, sensor_type, group, tool)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=unused-variable
|
# pylint: disable=unused-variable
|
||||||
@ -111,3 +140,5 @@ def get_value_from_json(json_dict, sensor_type, group, tool):
|
|||||||
elif tool is not None:
|
elif tool is not None:
|
||||||
if sensor_type in json_dict[group][tool]:
|
if sensor_type in json_dict[group][tool]:
|
||||||
return json_dict[group][tool][sensor_type]
|
return json_dict[group][tool][sensor_type]
|
||||||
|
|
||||||
|
return None
|
||||||
|
@ -13,13 +13,12 @@ from homeassistant.components.sensor import PLATFORM_SCHEMA
|
|||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
TEMP_CELSIUS, CONF_NAME, CONF_MONITORED_CONDITIONS)
|
TEMP_CELSIUS, CONF_NAME, CONF_MONITORED_CONDITIONS)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.loader import get_component
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['octoprint']
|
DEPENDENCIES = ['octoprint']
|
||||||
|
DOMAIN = "octoprint"
|
||||||
DEFAULT_NAME = 'OctoPrint'
|
DEFAULT_NAME = 'OctoPrint'
|
||||||
|
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
@ -38,7 +37,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Set up the available OctoPrint sensors."""
|
"""Set up the available OctoPrint sensors."""
|
||||||
octoprint = get_component('octoprint')
|
octoprint_api = hass.data[DOMAIN]["api"]
|
||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
monitored_conditions = config.get(CONF_MONITORED_CONDITIONS)
|
monitored_conditions = config.get(CONF_MONITORED_CONDITIONS)
|
||||||
|
|
||||||
@ -46,16 +45,16 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
types = ["actual", "target"]
|
types = ["actual", "target"]
|
||||||
for octo_type in monitored_conditions:
|
for octo_type in monitored_conditions:
|
||||||
if octo_type == "Temperatures":
|
if octo_type == "Temperatures":
|
||||||
for tool in octoprint.OCTOPRINT.get_tools():
|
for tool in octoprint_api.get_tools():
|
||||||
for temp_type in types:
|
for temp_type in types:
|
||||||
new_sensor = OctoPrintSensor(
|
new_sensor = OctoPrintSensor(
|
||||||
octoprint.OCTOPRINT, temp_type, temp_type, name,
|
octoprint_api, temp_type, temp_type, name,
|
||||||
SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
|
SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
|
||||||
SENSOR_TYPES[octo_type][1], tool)
|
SENSOR_TYPES[octo_type][1], tool)
|
||||||
devices.append(new_sensor)
|
devices.append(new_sensor)
|
||||||
else:
|
else:
|
||||||
new_sensor = OctoPrintSensor(
|
new_sensor = OctoPrintSensor(
|
||||||
octoprint.OCTOPRINT, octo_type, SENSOR_TYPES[octo_type][2],
|
octoprint_api, octo_type, SENSOR_TYPES[octo_type][2],
|
||||||
name, SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
|
name, SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
|
||||||
SENSOR_TYPES[octo_type][1])
|
SENSOR_TYPES[octo_type][1])
|
||||||
devices.append(new_sensor)
|
devices.append(new_sensor)
|
||||||
@ -116,7 +115,3 @@ class OctoPrintSensor(Entity):
|
|||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
# Error calling the api, already logged in api.update()
|
# Error calling the api, already logged in api.update()
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._state is None and self.sensor_type != "completion":
|
|
||||||
_LOGGER.warning("Unable to locate value for %s", self.sensor_type)
|
|
||||||
return
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user