From d7eace127b1ef8b14de427cab858d94451fb4813 Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 00:10:00 +0200 Subject: [PATCH 01/12] enabling the plugin to use the newer rr_model endpoint. --- README.md | 6 +- custom_components/duet3d_printer/__init__.py | 130 +++++++----------- .../duet3d_printer/manifest.json | 6 +- custom_components/duet3d_printer/sensor.py | 38 +---- 4 files changed, 56 insertions(+), 124 deletions(-) diff --git a/README.md b/README.md index 8a3f4cc..0a4d460 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Code Based on the OctoPrint integration from Hass: [octoprint integration github](https://github.com/home-assistant/home-assistant/tree/dev/homeassistant/components/octoprint) +I forked from https://github.com/garethbradley/hass-Duet3D because his version uses a soon-to-be deprecated API endpoint /rr_status instead of /rr_model + This is a work in progress, the code is working but there is still lots to do ## Installation @@ -9,13 +11,13 @@ This is a work in progress, the code is working but there is still lots to do ### From HACS 1. Install HACS if you haven't already (see [installation guide](https://hacs.netlify.com/docs/installation/manual)). -2. Add custom repository `https://github.com/garethbradley/hass-Duet3D` as "Integration" in the settings tab of HACS. +2. Add custom repository `https://github.com/DJGummikuh/hass-Duet3D` as "Integration" in the settings tab of HACS. 3. Find and install "Duet3D" integration in HACS's "Integrations" tab. 4. Restart your Home Assistant. ### Manual -1. Download and unzip the [repo archive](https://github.com/garethbradley/hass-Duet3D/archive/master.zip). (You could also click "Download ZIP" after pressing the green button in the repo, alternatively, you could clone the repo from SSH add-on). +1. Download and unzip the [repo archive](https://github.com/DJGummikuh/hass-Duet3D/archive/master.zip). (You could also click "Download ZIP" after pressing the green button in the repo, alternatively, you could clone the repo from SSH add-on). 2. Copy contents of the archive/repo into your `/config` directory. 3. Restart your Home Assistant. diff --git a/custom_components/duet3d_printer/__init__.py b/custom_components/duet3d_printer/__init__.py index 1625fda..c77cff9 100644 --- a/custom_components/duet3d_printer/__init__.py +++ b/custom_components/duet3d_printer/__init__.py @@ -4,13 +4,10 @@ import requests import voluptuous as vol -from aiohttp.hdrs import CONTENT_TYPE -# from homeassistant.components.discovery import SERVICE_OCTOPRINT +import homeassistant.helpers.config_validation as cv from homeassistant.const import ( - CONF_API_KEY, CONF_HOST, - CONTENT_TYPE_JSON, CONF_NAME, CONF_PATH, CONF_PORT, @@ -20,8 +17,6 @@ CONF_SENSORS, CONF_BINARY_SENSORS, ) -from homeassistant.helpers import discovery -import homeassistant.helpers.config_validation as cv from homeassistant.helpers.discovery import load_platform from homeassistant.util import slugify as util_slugify @@ -33,6 +28,8 @@ DEFAULT_NAME = "Duet3D Printer" DOMAIN = "duet3d_printer" +MIN_INTERVAL = 30.0 + def has_all_unique_names(value): """Validate that printers have an unique name.""" @@ -69,18 +66,14 @@ def ensure_valid_path(value): SENSOR_TYPES = { # API Endpoint, Group, Key, unit, icon # Group, subgroup, key, unit, icon - "Temperatures": ["temps", "temperature", "*", TEMP_CELSIUS], + "Temperatures": ["heat", "heaters", "0,1", TEMP_CELSIUS], "Current State": ["job", "status", "text", None, "mdi:printer-3d"], "Job Percentage": ["job", "fractionPrinted", "completion", "%", "mdi:file-percent"], "Time Remaining": ["job", "timesLeft", "file", "seconds", "mdi:clock-end"], "Time Elapsed": ["job", "printDuration", "printTime", "seconds", "mdi:clock-start"], - "Position": [ - "array", - "coords.xyz", - "x,y,z", - "mm,mm,mm", - "mdi:axis-x-arrow,mdi:axis-y-arrow,mdi:axis-z-arrow", - ], + "Job Name": ["job", "fileName", "text", None, "mdi:printer-3d"], + "Position": ["move", "axes", "0,1,2", "mm,mm,mm", "mdi:axis-x-arrow,mdi:axis-y-arrow,mdi:axis-z-arrow", + ], } SENSOR_SCHEMA = vol.Schema( @@ -105,7 +98,7 @@ def ensure_valid_path(value): vol.Optional(CONF_PORT, default=80): cv.port, # type 2, extended infos, type 3, print status infos vol.Optional( - CONF_PATH, default="/rr_status?type=3" + CONF_PATH, default="/rr_model?flags=d99vn" ): ensure_valid_path, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NUMBER_OF_TOOLS, default=0): cv.positive_int, @@ -125,16 +118,9 @@ def ensure_valid_path(value): def setup(hass, config): - """Set up the OctoPrint component.""" printers = hass.data[DOMAIN] = {} success = False - # def device_discovered(service, info): - # """Gets called when a Duet3D device has been discovered.""" - # _LOGGER.debug("Found a Duet3D device: %s", info) - # - # discovery.listen(hass, SERVICE_OCTOPRINT, device_discovered) - if DOMAIN not in config: # Skip the setup if there is no configuration present return True @@ -142,19 +128,18 @@ def setup(hass, config): for printer in config[DOMAIN]: name = printer[CONF_NAME] ssl = "s" if printer[CONF_SSL] else "" - base_url = "http{}://{}:{}{}api/".format( + base_url = "http{}://{}:{}{}".format( ssl, printer[CONF_HOST], printer[CONF_PORT], printer[CONF_PATH] ) - api_key = 0 number_of_tools = printer[CONF_NUMBER_OF_TOOLS] bed = printer[CONF_BED] try: - octoprint_api = Duet3dAPI(base_url, api_key, bed, number_of_tools) + octoprint_api = Duet3dAPI(base_url, bed, number_of_tools) printers[base_url] = octoprint_api octoprint_api.get("printer") octoprint_api.get("job") except requests.exceptions.RequestException as conn_err: - _LOGGER.error("Error setting up OctoPrint API: %r", conn_err) + _LOGGER.error("Error setting up Duet3d API: %r", conn_err) continue sensors = printer[CONF_SENSORS][CONF_MONITORED_CONDITIONS] @@ -179,17 +164,18 @@ def setup(hass, config): class Duet3dAPI: - """Simple JSON wrapper for OctoPrint's API.""" + """Simple JSON wrapper for Duet3D's API.""" - def __init__(self, api_url, key, bed, number_of_tools): - """Initialize OctoPrint API and set headers needed later.""" + def __init__(self, api_url, bed, number_of_tools): + """Initialize Duet3D API and set headers needed later.""" self.api_url = api_url self.headers = { - CONTENT_TYPE: CONTENT_TYPE_JSON, - #'X-Api-Key': key, + 'Content-Type': 'application/json', } - self.printer_last_reading = [{}, None] self.job_last_reading = [{}, None] + self.fans_last_reading = [{}, None] + self.move_last_reading = [{}, None] + self.heat_last_reading = [{}, None] self.job_available = False self.printer_available = False self.available = False @@ -204,31 +190,27 @@ def get_tools(self): if self.number_of_tools > 0: # tools start at 1 bed is 0 for tool_number in range(1, self.number_of_tools + 1): - tools.append(tool_number) #'tool' + str(tool_number)) + tools.append(tool_number) # 'tool' + str(tool_number)) if self.bed: tools.append("bed") if not self.bed and self.number_of_tools == 0: - temps = self.printer_last_reading[0].get("temperature") + temps = self.heat_last_reading.get("temperature") if temps is not None: tools = temps.keys() return tools def get(self, endpoint): """Send a get request, and return the response as a dict.""" - # Only query the API at most every 30 seconds + # Only query the API every 30 seconds at most now = time.time() if endpoint == "job": last_time = self.job_last_reading[1] if last_time is not None: - if now - last_time < 30.0: + if now - last_time < MIN_INTERVAL: return self.job_last_reading[0] - elif endpoint == "printer": - last_time = self.printer_last_reading[1] - if last_time is not None: - if now - last_time < 30.0: - return self.printer_last_reading[0] - url = self.api_url # + endpoint + url = self.api_url + "&key=" + endpoint + url = url.replace("/&", "&") try: response = requests.get(url, headers=self.headers, timeout=9) response.raise_for_status() @@ -236,17 +218,16 @@ def get(self, endpoint): self.job_last_reading[0] = response.json() self.job_last_reading[1] = time.time() self.job_available = True - elif endpoint == "printer": - self.printer_last_reading[0] = response.json() - self.printer_last_reading[1] = time.time() - self.printer_available = True + elif endpoint == "move": + self.move_last_reading[0] = response.json() + self.move_last_reading[1] = time.time() 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() except Exception as conn_exc: # pylint: disable=broad-except - log_string = "Failed to update OctoPrint status. " + " Error: %s" % ( + log_string = "Failed to update Duet3D status. " + " Error: %s" % ( conn_exc ) # Only log the first failure @@ -283,42 +264,23 @@ def update(self, sensor_type, end_point, group, tool=None): def get_value_from_json(json_dict, end_point, sensor_type, group, tool): """Return the value for sensor_type from the JSON.""" - if end_point == "temps": - if sensor_type == "current": - if tool == "bed": - return json_dict[end_point][sensor_type][0] - else: - return json_dict[end_point][sensor_type][tool] - elif sensor_type == "active": - if tool == "bed": - return json_dict[end_point]["bed"][sensor_type] - else: - return json_dict[end_point]["tools"][sensor_type][tool - 1][tool - 1] - # elif end_point == "array": - - # if "coords" not in json_dict: - # return 0 - # return json_dict["coords"][group][int(tool)] - else: - levels = group.split(".") - data = json_dict - - if group == "timesLeft": - return json_dict[group]["file"] - - for level in levels: - _LOGGER.debug( - "Updating API Duet3D sensor: get_value_from_json, array, %s, %r", - level, - data, - ) - if level not in data: - return 0 - data = data[level] - - if end_point == "array": - return data[int(tool)] + if end_point == "heat": + if tool == "bed": + return json_dict["result"][group][0][sensor_type] else: - return data - + return json_dict["result"][group][int(tool)][sensor_type] + elif end_point == "move": + return json_dict["result"][group][int(sensor_type)]["userPosition"] + elif end_point == "job": + if group == "fileName": + return json_dict["result"]["file"][group] or json_dict["result"]["lastFileName"] + elif group == "fractionPrinted": + return 100.0 * json_dict["result"]["filePosition"] / json_dict["result"]["file"]["size"] + elif group == "timesLeft": + return json_dict["result"]["timesLeft"]["slicer"] + elif group == "printDuration": + return json_dict["result"]["duration"] + else: + return None # HACK + else: return None diff --git a/custom_components/duet3d_printer/manifest.json b/custom_components/duet3d_printer/manifest.json index ac062ec..e37e49f 100644 --- a/custom_components/duet3d_printer/manifest.json +++ b/custom_components/duet3d_printer/manifest.json @@ -3,15 +3,15 @@ "name": "Duet3D Printer", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/duet3d_printer", - "issue_tracker": "https://github.com/garethbradley/hass-Duet3D/issues", + "issue_tracker": "https://github.com/djgummikuh/hass-Duet3D/issues", "requirements": [], "ssdp": [], "zeroconf": [], "homekit": {}, "dependencies": [], "codeowners": [ - "@garethbradley" + "@djgummikuh" ], "iot_class": "local_polling", - "version": "v1.2.0" + "version": "v1.3.0" } diff --git a/custom_components/duet3d_printer/sensor.py b/custom_components/duet3d_printer/sensor.py index 144c386..f495819 100644 --- a/custom_components/duet3d_printer/sensor.py +++ b/custom_components/duet3d_printer/sensor.py @@ -74,23 +74,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): tool, ) devices.append(new_sensor) - elif endpoint == "array": - # "Position": [ - # "array", - # "coords.xyz", - # "x,y,z", - # "mm,mm,mm", - # "mdi:format-vertical-align-top,mdi:format-vertical-align-top,mdi:format-vertical-align-top", - # ], - # api, - # condition, - # sensor_type, - # sensor_name, - # unit, - # endpoint, - # group, - # tool=None, - # icon=None, + elif endpoint == "move": group = SENSOR_TYPES[duet3d_type][1] keys = SENSOR_TYPES[duet3d_type][2].split(",") units = SENSOR_TYPES[duet3d_type][3].split(",") @@ -172,7 +156,7 @@ def __init__( self.sensor_name = sensor_name if tool is None: self._name = f"{sensor_name} {condition}" - elif endpoint is "array": + elif endpoint is "move": self._name = f"{sensor_name} {condition}" else: self._name = f"{sensor_name} {condition} tool{tool} temp" @@ -194,25 +178,9 @@ def name(self): @property def state(self): - """Return the state of the sensor.""" - print_status_dict = { - "S": "Stopped", - "M": "Simulating", - "P": "Printing", - "I": "Idle", - "C": "Configuring", - "B": "Busy", - "D": "Decelerating", - "R": "Resuming", - "H": "Halted", - "F": "Flashing Firmware", - "T": "Changin Tool", - } - sensor_unit = self.unit_of_measurement - if self._state in print_status_dict: - self._state = print_status_dict[self._state] + sensor_unit = self.unit_of_measurement if sensor_unit in (TEMP_CELSIUS, "%"): # API sometimes returns null and not 0 From ca1524d23c7100f0659068adf08b7b4847a133d4 Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 00:10:36 +0200 Subject: [PATCH 02/12] removing binaries --- .../__pycache__/__init__.cpython-37.pyc | Bin 6596 -> 0 bytes .../__pycache__/binary_sensor.cpython-37.pyc | Bin 2551 -> 0 bytes .../__pycache__/sensor.cpython-37.pyc | Bin 3971 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 custom_components/duet3d_printer/__pycache__/__init__.cpython-37.pyc delete mode 100644 custom_components/duet3d_printer/__pycache__/binary_sensor.cpython-37.pyc delete mode 100644 custom_components/duet3d_printer/__pycache__/sensor.cpython-37.pyc diff --git a/custom_components/duet3d_printer/__pycache__/__init__.cpython-37.pyc b/custom_components/duet3d_printer/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 8e8800e9160ab7b7c52e5f22b58eb8245abe96f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6596 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 Ruv{6zVu6sIZeA%l{|90XxY+;z diff --git a/custom_components/duet3d_printer/__pycache__/binary_sensor.cpython-37.pyc b/custom_components/duet3d_printer/__pycache__/binary_sensor.cpython-37.pyc deleted file mode 100644 index 775c0c5b54efe1352bfbe06ea360098a647f9ad2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2551 zcmZ`*-EI>{6rTO{?#6K=3M~PYZbLzJRXL^fPc1?~;-W~wiDFv7YBkz;#%6=PyUeU9 zF`KL83Hk)dWgn??+bdq7>P63)wbQsVYt5N6KYR9@bG~!N4;B{#0#E19e}1Wh_7@JO zj}6K_X!0otMmmHU%p4dUL-%IKgx(rhL%U-egxSm)I77GN4l5ncAlx|dd2niU7FfVs zRyj60)rW+6%s(c~=k}4+S!8CL)ECBIv`1N%iahM4A{?ekoTnmA`r&prPj^7e!@W3( z#6c)|B2yt7ZvhW!)eUvwfnI3q`3?Rm?((+=tkq5R{)5fd{oQA@-E6hDcj@D2JI%Io zH?|+$-)wd9WcVyV!}G60lfQ!~EM~m$M3otB)XimbXhUy7??7)u?-pdA%%AfxdKJZkXm7yZ?VXmglW545w--rHM`EBV6UV(Z;fQZ7 z5CXj> zmD^2|UffsJh%w5OJkDb-RgJ~6o4(@WfW`?#*~PC{@coOEcymVKO$OW3M5@IULZ4yi zX_UpP!gOe*@^PN#2N_pE!hfUXx&9zx8EpN1YpwkFT6ZM#bO;8AS(*R{xyD93zs=T4 z9!*|rWCyAyc|OW$Hi&Y7HCzNUas>o2J;R2EznWCv&+A_Lk0`EBknhq=e($mqDBSD2^u3g|uywC=G5Ry`&iUnfRQ)WF#I zvt6DE4kyhcbWRv0?+SgR)%D>Ge6Yv(tV5GM5QSY3N`P2M?-gdA7%*d=nlNi7wb^lD z!K_snAZ>=aQ#c^q0;o?bKyX66!UO5&!N~#x%coPaI^)$%$lo{`#A6_92thiBwhULJ zHFn+{hHnmk9Ivhm9_5^!+cT5u;SEu*s)h1Bs#)z~oT6Mg<#4*DIbk7LTq?m+TwSCi zKtj_V9r8$y1RsJ6ftOhfykuDlr-fA#KX8ZTjIl5hH28c zi>8$ENEti2R_Uq*bzgi8^Yc+FCzdo#et-=UT|uk>5_x=eK6br#2K<>HF?)3VHOF61 zp+f!b4xq}FZUl^_A3qO!A{~Ys&7U{dn{<8ae!JalH(J`C??72CD;m}2HW2K@$*c2$ zp5H!$*MoPpv+sg(5Td&wwaGpt_CBQUJ|yS9bBf9DJ|W3vo8*;!Z{L3ri0=#_O?k&W zou2f=pE9@uc&IZ7PdUxldQj5e9qA1v_piez#V06`%Q`5^6a3|f%Ur5}zwYv^tmp5o zr%A%QIA{uyiuqm!8 uQhuN3TVRe0@hwi?M1ePu{^&fM%DYoK;4acx;x%F$p6QuYbIA;>;L^XIxRS#F diff --git a/custom_components/duet3d_printer/__pycache__/sensor.cpython-37.pyc b/custom_components/duet3d_printer/__pycache__/sensor.cpython-37.pyc deleted file mode 100644 index 81b307c733ce99d0598841a2dfa4d2ffe0098ca0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3971 zcmbtX&2JmW72jDdmrH6zeOO7V#Bdia;()0uwN0HSs1exFhr`0AT#<(3McVC(Gm=(X z?$WbMSz?wa`H({b1amk7yMj0S3R@H<&h{PYa@Ho@Tr@@&$`Z;lN(-f37<)#}7LB5e zTBWEwHBXF@!^?%eZ%e;$G9M#Kd)6KfFSqjwuY6Nt#*Q(na)%CUr!=aOwquT_zGa7Y zVXqp0_{k{lg=H;okCA@TdJB|{u zbYn|;%bzs2y`yyC@zevLyvHGS!?4}(Kv4S+Yov)cp5TSK7sj!dM?H~U^TLGd1sBaUj6CE*VAp1d78%BaBWOC zO}3+*$t>C#-%Q1E9NR_bfvl84v zlEX=IlxHRh(mIVPW$`c%)$Gc~-Fq9YwN@vXIAnE4rfXlt^NHcWx#xWI%rW|g%Y zW*OGg=b&61VSwGDJQA6z^C;`42SOeNQ33|4V5)Rz{=(!s1P?HiV|bcmer-Y|VL!s* z(K)LM7Y9)nYnAh(zR3J4PAJf-s-{4r)|Ewr{VHARxS^Ja$H5qge=}qQTYmTc^4P}Z z?jXz49`-#wrseUr%j5A&{UcS^bQSdDFo)T_dCbr5Kp3XOEWGrqGly!>OxuKRu^OZc zi4rf`*aDknv*r)_f@xyjo9t~!`7^B7rA1F4y7-%Tvp+%z0|COI;NX||90&V><}FdC zpzy>vX1)!*!X2$wpi>~Ac4r(2{3_a}d0n^FpwIAGtxxIDFfT7-li}4((FbC2W16+$ ziGckJZobs&>hOjcR1yL-XCFW*tilM4!qLoqg_}22fcazO$m;fWI)+dsjBEM2#cyj zh_wT_F??zv7{Ib1-41$S6_8&K#|zKsNAL{ZPr-nyO0^xC4*JR=l`O-`5g@8+!5QJI zN^oc6_U*MzRpw%Au+yk1D--dy{3T9aRnJ^U{sMLRb856`bLE`vRMxx5_jDhvuf1U` z-ls+|GKQo0EsE#N)Z9USkr5vnrQzHKD`>eh3&@Yo@``O#DA6Jh zBHtmOAzvXc`ODM@2;4J9KTEXNs*W*7=UT+Zu-*qPvErF1-ZC@>l4SbOovm^dbV3 z^lkZbIw)&+xoe=^=@!oU;`mac%+rDD=$aQ1>m4ltc^|-*R{-$$=z5Iz6o8W)x~-$)(o4?j z43A_mMLq2i&a(m)uTp)d3!Xv&e| z(E!;?rfTA_EBZPns~LbX5y(^0WR0@-SDa1Q^tLY21@YkP_s1V1NhkC2 zEx_TYdGR-A8=1p5FMR6RkcQc6HC!TFqN*SO%Ll!b4`R~YAb2zg<4I2?2zc5J0(lF| zDyJ_~WO4b?ID2ZNO%fC(ow&S7;&T#|mv&R~7)l^vV83KmoN70ikOnjrLiwb;$CIQG79+y z37sxddU^-TWE8{>oegg}zv-?f1h3_lk{f#eEd I3Lkd;f8vTDcmMzZ From 6250edce99c435cca30a8d8d769374eea20352ce Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 11:15:06 +0200 Subject: [PATCH 03/12] - Cleaning up timeout management - Fixing division by zero --- custom_components/duet3d_printer/__init__.py | 67 ++++++++++++++------ 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/custom_components/duet3d_printer/__init__.py b/custom_components/duet3d_printer/__init__.py index c77cff9..f7f9aff 100644 --- a/custom_components/duet3d_printer/__init__.py +++ b/custom_components/duet3d_printer/__init__.py @@ -28,7 +28,7 @@ DEFAULT_NAME = "Duet3D Printer" DOMAIN = "duet3d_printer" -MIN_INTERVAL = 30.0 +MIN_INTERVAL = 10.0 def has_all_unique_names(value): @@ -136,8 +136,9 @@ def setup(hass, config): try: octoprint_api = Duet3dAPI(base_url, bed, number_of_tools) printers[base_url] = octoprint_api - octoprint_api.get("printer") + octoprint_api.get("heat") octoprint_api.get("job") + octoprint_api.get("move") except requests.exceptions.RequestException as conn_err: _LOGGER.error("Error setting up Duet3d API: %r", conn_err) continue @@ -172,15 +173,17 @@ def __init__(self, api_url, bed, number_of_tools): self.headers = { 'Content-Type': 'application/json', } - self.job_last_reading = [{}, None] - self.fans_last_reading = [{}, None] - self.move_last_reading = [{}, None] - self.heat_last_reading = [{}, None] + self.job_last_reading = [{}, 0.0] + self.fans_last_reading = [{}, 0.0] + self.move_last_reading = [{}, 0.0] + self.heat_last_reading = [{}, 0.0] self.job_available = False - self.printer_available = False + self.heat_available = False + self.move_available = False self.available = False - self.printer_error_logged = False self.job_error_logged = False + self.heat_error_logged = False + self.move_error_logged = False self.bed = bed self.number_of_tools = number_of_tools @@ -205,14 +208,21 @@ def get(self, endpoint): now = time.time() if endpoint == "job": last_time = self.job_last_reading[1] - if last_time is not None: - if now - last_time < MIN_INTERVAL: - return self.job_last_reading[0] + if now - last_time < MIN_INTERVAL: + return self.job_last_reading[0] + if endpoint == "heat": + last_time = self.job_last_reading[1] + if now - last_time < MIN_INTERVAL: + return self.job_last_reading[0] + if endpoint == "move": + last_time = self.job_last_reading[1] + if now - last_time < MIN_INTERVAL: + return self.job_last_reading[0] url = self.api_url + "&key=" + endpoint url = url.replace("/&", "&") try: - response = requests.get(url, headers=self.headers, timeout=9) + response = requests.get(url, headers=self.headers, timeout=2) response.raise_for_status() if endpoint == "job": self.job_last_reading[0] = response.json() @@ -221,10 +231,16 @@ def get(self, endpoint): elif endpoint == "move": self.move_last_reading[0] = response.json() self.move_last_reading[1] = time.time() - self.available = self.printer_available and self.job_available + self.move_available = True + elif endpoint == "heat": + self.heat_last_reading[0] = response.json() + self.heat_last_reading[1] = time.time() + self.heat_available = True + self.available = self.heat_available and self.job_available and self.move_available if self.available: self.job_error_logged = False - self.printer_error_logged = False + self.heat_error_logged = False + self.move_error_logged = False return response.json() except Exception as conn_exc: # pylint: disable=broad-except log_string = "Failed to update Duet3D status. " + " Error: %s" % ( @@ -237,12 +253,19 @@ def get(self, endpoint): _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: + if endpoint == "heat": + log_string = "Endpoint: heat " + log_string + if not self.heat_error_logged: _LOGGER.error(log_string) - self.printer_error_logged = True - self.printer_available = False + self.heat_error_logged = True + self.heat_available = False + if endpoint == "move": + log_string = "Endpoint: move " + log_string + if not self.move_error_logged: + _LOGGER.error(log_string) + self.move_error_logged = True + self.move_available = False + self.available = False return None @@ -275,7 +298,11 @@ def get_value_from_json(json_dict, end_point, sensor_type, group, tool): if group == "fileName": return json_dict["result"]["file"][group] or json_dict["result"]["lastFileName"] elif group == "fractionPrinted": - return 100.0 * json_dict["result"]["filePosition"] / json_dict["result"]["file"]["size"] + filesize = json_dict["result"]["file"]["size"] + if filesize > 0: + return 100.0 * json_dict["result"]["filePosition"] / filesize + else: + return 0 elif group == "timesLeft": return json_dict["result"]["timesLeft"]["slicer"] elif group == "printDuration": From 78dd37d528c820f20c2a38cccc13a7186940d4aa Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 11:15:48 +0200 Subject: [PATCH 04/12] Bumping version, hopefully this will trigger an update? --- custom_components/duet3d_printer/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/duet3d_printer/manifest.json b/custom_components/duet3d_printer/manifest.json index e37e49f..7ab0034 100644 --- a/custom_components/duet3d_printer/manifest.json +++ b/custom_components/duet3d_printer/manifest.json @@ -13,5 +13,5 @@ "@djgummikuh" ], "iot_class": "local_polling", - "version": "v1.3.0" + "version": "v1.3.1" } From d7ad6cf01e8e1f150fb28a26ef38e46e25dfa8d7 Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 11:22:27 +0200 Subject: [PATCH 05/12] Fixing copy&paste error --- custom_components/duet3d_printer/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/custom_components/duet3d_printer/__init__.py b/custom_components/duet3d_printer/__init__.py index f7f9aff..b16744e 100644 --- a/custom_components/duet3d_printer/__init__.py +++ b/custom_components/duet3d_printer/__init__.py @@ -211,13 +211,13 @@ def get(self, endpoint): if now - last_time < MIN_INTERVAL: return self.job_last_reading[0] if endpoint == "heat": - last_time = self.job_last_reading[1] + last_time = self.heat_last_reading[1] if now - last_time < MIN_INTERVAL: - return self.job_last_reading[0] + return self.heat_last_reading[0] if endpoint == "move": - last_time = self.job_last_reading[1] + last_time = self.move_last_reading[1] if now - last_time < MIN_INTERVAL: - return self.job_last_reading[0] + return self.move_last_reading[0] url = self.api_url + "&key=" + endpoint url = url.replace("/&", "&") From 5a1f95d3d8f75ea14c9196b444e0d21beee7ebf4 Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 11:42:24 +0200 Subject: [PATCH 06/12] Fixing state not being reported because I forgot it >.< --- custom_components/duet3d_printer/__init__.py | 28 ++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/custom_components/duet3d_printer/__init__.py b/custom_components/duet3d_printer/__init__.py index b16744e..be8c773 100644 --- a/custom_components/duet3d_printer/__init__.py +++ b/custom_components/duet3d_printer/__init__.py @@ -67,7 +67,7 @@ def ensure_valid_path(value): # API Endpoint, Group, Key, unit, icon # Group, subgroup, key, unit, icon "Temperatures": ["heat", "heaters", "0,1", TEMP_CELSIUS], - "Current State": ["job", "status", "text", None, "mdi:printer-3d"], + "Current State": ["state", "status", "text", None, "mdi:printer-3d"], "Job Percentage": ["job", "fractionPrinted", "completion", "%", "mdi:file-percent"], "Time Remaining": ["job", "timesLeft", "file", "seconds", "mdi:clock-end"], "Time Elapsed": ["job", "printDuration", "printTime", "seconds", "mdi:clock-start"], @@ -139,6 +139,7 @@ def setup(hass, config): octoprint_api.get("heat") octoprint_api.get("job") octoprint_api.get("move") + octoprint_api.get("state") except requests.exceptions.RequestException as conn_err: _LOGGER.error("Error setting up Duet3d API: %r", conn_err) continue @@ -177,13 +178,16 @@ def __init__(self, api_url, bed, number_of_tools): self.fans_last_reading = [{}, 0.0] self.move_last_reading = [{}, 0.0] self.heat_last_reading = [{}, 0.0] + self.state_last_reading = [{}, 0.0] self.job_available = False self.heat_available = False self.move_available = False + self.state_available = False self.available = False self.job_error_logged = False self.heat_error_logged = False self.move_error_logged = False + self.state_error_logged = False self.bed = bed self.number_of_tools = number_of_tools @@ -218,6 +222,10 @@ def get(self, endpoint): last_time = self.move_last_reading[1] if now - last_time < MIN_INTERVAL: return self.move_last_reading[0] + if endpoint == "state": + last_time = self.state_last_reading[1] + if now - last_time < MIN_INTERVAL: + return self.state_last_reading[0] url = self.api_url + "&key=" + endpoint url = url.replace("/&", "&") @@ -236,35 +244,43 @@ def get(self, endpoint): self.heat_last_reading[0] = response.json() self.heat_last_reading[1] = time.time() self.heat_available = True - self.available = self.heat_available and self.job_available and self.move_available + elif endpoint == "state": + self.state_last_reading[0] = response.json() + self.state_last_reading[1] = time.time() + self.state_available = True + self.available = self.state_available and self.job_available and self.move_available and self.heat_available if self.available: self.job_error_logged = False self.heat_error_logged = False self.move_error_logged = False + self.state_error_logged = False return response.json() except Exception as conn_exc: # pylint: disable=broad-except log_string = "Failed to update Duet3D status. " + " Error: %s" % ( conn_exc ) # Only log the first failure + log_string = "Endpoint: " + endpoint + " " + log_string 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 if endpoint == "heat": - log_string = "Endpoint: heat " + log_string if not self.heat_error_logged: _LOGGER.error(log_string) self.heat_error_logged = True self.heat_available = False if endpoint == "move": - log_string = "Endpoint: move " + log_string if not self.move_error_logged: _LOGGER.error(log_string) self.move_error_logged = True self.move_available = False + if endpoint == "state": + if not self.state_error_logged: + _LOGGER.error(log_string) + self.state_error_logged = True + self.state_available = False self.available = False return None @@ -309,5 +325,7 @@ def get_value_from_json(json_dict, end_point, sensor_type, group, tool): return json_dict["result"]["duration"] else: return None # HACK + elif end_point == "state": + return json_dict["result"]["status"] else: return None From c9730cbde8de0ec2b489892ec31d5c1cde170856 Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 11:48:19 +0200 Subject: [PATCH 07/12] Adding some information for the HACS information card --- info.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 info.md diff --git a/info.md b/info.md new file mode 100644 index 0000000..d046e00 --- /dev/null +++ b/info.md @@ -0,0 +1,70 @@ +# Duet3D integration for Home Assistant + +Code Based on the OctoPrint integration from Hass: [octoprint integration github](https://github.com/home-assistant/home-assistant/tree/dev/homeassistant/components/octoprint) + +I forked from https://github.com/garethbradley/hass-Duet3D because his version uses a soon-to-be deprecated API endpoint /rr_status instead of /rr_model + +This is a work in progress, the code is working but there is still lots to do + +## Installation + +### From HACS + +1. Install HACS if you haven't already (see [installation guide](https://hacs.netlify.com/docs/installation/manual)). +2. Add custom repository `https://github.com/DJGummikuh/hass-Duet3D` as "Integration" in the settings tab of HACS. +3. Find and install "Duet3D" integration in HACS's "Integrations" tab. +4. Restart your Home Assistant. + +### Manual + +1. Download and unzip the [repo archive](https://github.com/DJGummikuh/hass-Duet3D/archive/master.zip). (You could also click "Download ZIP" after pressing the green button in the repo, alternatively, you could clone the repo from SSH add-on). +2. Copy contents of the archive/repo into your `/config` directory. +3. Restart your Home Assistant. + +### Config +The following configuration is taken from the excellent article: [Getting started with Duet Wifi, RepRapFirmware, and Home Assistant](https://begala.io/home-assistant/duet-wifi-feat-home-assistant/). + +Add the following config to the `/config/configuration.yaml` file: + +```yaml +# Duet Integration +duet3d_printer: + host: + name: + number_of_tools: 1 + bed: true + sensors: + monitored_conditions: + - 'Current State' + - 'Temperatures' + - 'Job Percentage' + - 'Time Elapsed' + - 'Time Remaining' + - 'Job Name' + - 'Position' +``` + +Also, add the following to your `/config/secrets.yaml` file: + +```yaml + +``` + +Add the following to your Lovelace dashboard. Remember to update the entity names with those of your own printer (defined by the value of `duet3d-name`) +```yaml +- card: + cards: + - type: glance + entities: + - entity: sensor._current_toolbed_temp + name: Bed + - entity: sensor._current_tool1_temp + name: Tool + - entity: sensor._current_state + name: Status + type: horizontal-stack + conditions: + - entity: switch. + state: 'on' + type: conditional +``` From 694736801d4d8839c9d36b0f1c31de8df7d35ffe Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 11:53:42 +0200 Subject: [PATCH 08/12] Further documentation cleanup --- README.md | 15 ++++++++------- info.md | 19 +------------------ 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 0a4d460..fcfd2bf 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ Add the following config to the `/config/configuration.yaml` file: ```yaml # Duet Integration duet3d_printer: - host: !secret duet3d-host - name: !secret duet3d-name + host: + name: number_of_tools: 1 bed: true sensors: @@ -40,6 +40,7 @@ duet3d_printer: - 'Job Percentage' - 'Time Elapsed' - 'Time Remaining' + - 'Job Name' - 'Position' ``` @@ -49,15 +50,15 @@ Add the following to your Lovelace dashboard. Remember to update the entity name cards: - type: glance entities: - - entity: sensor.blv_mgn_cube_current_toolbed_temp + - entity: sensor._current_toolbed_temp name: Bed - - entity: sensor.blv_mgn_cube_current_tool1_temp + - entity: sensor._current_tool1_temp name: Tool - - entity: sensor.blv_mgn_cube_current_state + - entity: sensor._current_state name: Status type: horizontal-stack conditions: - - entity: switch.blv_mgn_cube + - entity: switch. state: 'on' type: conditional -``` +``` \ No newline at end of file diff --git a/info.md b/info.md index d046e00..8233482 100644 --- a/info.md +++ b/info.md @@ -8,18 +8,7 @@ This is a work in progress, the code is working but there is still lots to do ## Installation -### From HACS - -1. Install HACS if you haven't already (see [installation guide](https://hacs.netlify.com/docs/installation/manual)). -2. Add custom repository `https://github.com/DJGummikuh/hass-Duet3D` as "Integration" in the settings tab of HACS. -3. Find and install "Duet3D" integration in HACS's "Integrations" tab. -4. Restart your Home Assistant. - -### Manual - -1. Download and unzip the [repo archive](https://github.com/DJGummikuh/hass-Duet3D/archive/master.zip). (You could also click "Download ZIP" after pressing the green button in the repo, alternatively, you could clone the repo from SSH add-on). -2. Copy contents of the archive/repo into your `/config` directory. -3. Restart your Home Assistant. +Well obviously you're reading this in HACS so chances are you already installed this ;-) ### Config The following configuration is taken from the excellent article: [Getting started with Duet Wifi, RepRapFirmware, and Home Assistant](https://begala.io/home-assistant/duet-wifi-feat-home-assistant/). @@ -44,12 +33,6 @@ duet3d_printer: - 'Position' ``` -Also, add the following to your `/config/secrets.yaml` file: - -```yaml - -``` - Add the following to your Lovelace dashboard. Remember to update the entity names with those of your own printer (defined by the value of `duet3d-name`) ```yaml - card: From 60520d8d930edfdf651a618fedc6242c179b5acb Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 13:49:31 +0200 Subject: [PATCH 09/12] Adding Filament reporting to the mix --- custom_components/duet3d_printer/__init__.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/custom_components/duet3d_printer/__init__.py b/custom_components/duet3d_printer/__init__.py index be8c773..6321827 100644 --- a/custom_components/duet3d_printer/__init__.py +++ b/custom_components/duet3d_printer/__init__.py @@ -28,7 +28,7 @@ DEFAULT_NAME = "Duet3D Printer" DOMAIN = "duet3d_printer" -MIN_INTERVAL = 10.0 +MIN_INTERVAL = 15.0 def has_all_unique_names(value): @@ -71,6 +71,8 @@ def ensure_valid_path(value): "Job Percentage": ["job", "fractionPrinted", "completion", "%", "mdi:file-percent"], "Time Remaining": ["job", "timesLeft", "file", "seconds", "mdi:clock-end"], "Time Elapsed": ["job", "printDuration", "printTime", "seconds", "mdi:clock-start"], + "Filament Amount": ["job", "filamentAmount", "", "mm", "mdi:printer-3d-nozzle"], + "Filament Used": ["job", "rawExtrusion", "", "mm", "mdi:printer-3d-nozzle-outline"], "Job Name": ["job", "fileName", "text", None, "mdi:printer-3d"], "Position": ["move", "axes", "0,1,2", "mm,mm,mm", "mdi:axis-x-arrow,mdi:axis-y-arrow,mdi:axis-z-arrow", ], @@ -230,7 +232,7 @@ def get(self, endpoint): url = self.api_url + "&key=" + endpoint url = url.replace("/&", "&") try: - response = requests.get(url, headers=self.headers, timeout=2) + response = requests.get(url, headers=self.headers, timeout=5) response.raise_for_status() if endpoint == "job": self.job_last_reading[0] = response.json() @@ -323,6 +325,10 @@ def get_value_from_json(json_dict, end_point, sensor_type, group, tool): return json_dict["result"]["timesLeft"]["slicer"] elif group == "printDuration": return json_dict["result"]["duration"] + elif group == "filamentAmount": + return json_dict["result"]["file"]["filament"][0] + elif group == "rawExtrusion": + return json_dict["result"]["rawExtrusion"] else: return None # HACK elif end_point == "state": From c3c544ea8a38ea518ea9e265232af8de51d72cd9 Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 13:50:55 +0200 Subject: [PATCH 10/12] appending documentation --- README.md | 2 ++ info.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index fcfd2bf..b070e17 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ duet3d_printer: - 'Time Remaining' - 'Job Name' - 'Position' + - "Filament Amount" + - "Filament Used" ``` Add the following to your Lovelace dashboard. Remember to update the entity names with those of your own printer (defined by the value of `duet3d-name`) diff --git a/info.md b/info.md index 8233482..5aa7865 100644 --- a/info.md +++ b/info.md @@ -31,6 +31,8 @@ duet3d_printer: - 'Time Remaining' - 'Job Name' - 'Position' + - "Filament Amount" + - "Filament Used" ``` Add the following to your Lovelace dashboard. Remember to update the entity names with those of your own printer (defined by the value of `duet3d-name`) From f8f643bcbd6c860798b2159237df28f688d4c617 Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 13:51:22 +0200 Subject: [PATCH 11/12] Going to new version due to additional elements --- custom_components/duet3d_printer/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/duet3d_printer/manifest.json b/custom_components/duet3d_printer/manifest.json index 7ab0034..b4aa624 100644 --- a/custom_components/duet3d_printer/manifest.json +++ b/custom_components/duet3d_printer/manifest.json @@ -13,5 +13,5 @@ "@djgummikuh" ], "iot_class": "local_polling", - "version": "v1.3.1" + "version": "v1.3.2" } From 07a216aae799b46728c63b380f3e48ffcdde0913 Mon Sep 17 00:00:00 2001 From: DJGummikuh Date: Sun, 16 Apr 2023 13:54:26 +0200 Subject: [PATCH 12/12] fixing typos --- README.md | 4 ++-- info.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b070e17..98c71dd 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,8 @@ duet3d_printer: - 'Time Remaining' - 'Job Name' - 'Position' - - "Filament Amount" - - "Filament Used" + - 'Filament Amount' + - 'Filament Used' ``` Add the following to your Lovelace dashboard. Remember to update the entity names with those of your own printer (defined by the value of `duet3d-name`) diff --git a/info.md b/info.md index 5aa7865..4f9b76a 100644 --- a/info.md +++ b/info.md @@ -31,8 +31,8 @@ duet3d_printer: - 'Time Remaining' - 'Job Name' - 'Position' - - "Filament Amount" - - "Filament Used" + - 'Filament Amount' + - 'Filament Used' ``` Add the following to your Lovelace dashboard. Remember to update the entity names with those of your own printer (defined by the value of `duet3d-name`)