From 3a1c6e75b199930b3bb01d6ea8f1fd1eaa7e9ed7 Mon Sep 17 00:00:00 2001 From: Vitor de Miranda Henrique Date: Tue, 16 Jan 2018 14:08:31 -0600 Subject: [PATCH 01/42] Code refactoring --- octoprint_enclosure/__init__.py | 478 ++++++++++++++++++-------------- 1 file changed, 270 insertions(+), 208 deletions(-) diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index 1355134..4c0d797 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -17,19 +17,20 @@ import requests scheduler = sched.scheduler(time.time, time.sleep) + class EnclosurePlugin(octoprint.plugin.StartupPlugin, - octoprint.plugin.TemplatePlugin, - octoprint.plugin.SettingsPlugin, - octoprint.plugin.AssetPlugin, - octoprint.plugin.BlueprintPlugin, - octoprint.plugin.EventHandlerPlugin): + octoprint.plugin.TemplatePlugin, + octoprint.plugin.SettingsPlugin, + octoprint.plugin.AssetPlugin, + octoprint.plugin.BlueprintPlugin, + octoprint.plugin.EventHandlerPlugin): previousTempControlStatus = False currentTempControlStatus = False - enclosureSetTemperature=0.0 - enclosureCurrentTemperature=0.0 - enclosureCurrentHumidity=0.0 - lastFilamentEndDetected=0 + enclosureSetTemperature = 0.0 + enclosureCurrentTemperature = 0.0 + enclosureCurrentHumidity = 0.0 + lastFilamentEndDetected = 0 temperature_reading = [] temperature_control = [] rpi_outputs = [] @@ -41,7 +42,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, disable_temeprature_log = True def startTimer(self): - self._checkTempTimer = RepeatedTimer(10, self.checkEnclosureTemp, None, None, True) + self._checkTempTimer = RepeatedTimer( + 10, self.checkEnclosureTemp, None, None, True) self._checkTempTimer.start() def toFloat(self, value): @@ -58,9 +60,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, except: return 0 - #~~ StartupPlugin mixin + # ~~ StartupPlugin mixin def on_after_startup(self): - self.PWM_INSTANCES = [] self.temperature_reading = self._settings.get(["temperature_reading"]) self.temperature_control = self._settings.get(["temperature_control"]) @@ -75,14 +76,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.configureGPIO() self.updateOutputUI() - #~~ Blueprintplugin mixin + # ~~ Blueprintplugin mixin @octoprint.plugin.BlueprintPlugin.route("/setEnclosureTemperature", methods=["GET"]) def setEnclosureTemperature(self): self.enclosureSetTemperature = flask.request.values["enclosureSetTemp"] - if self._settings.get(["debug"]) == True: - self._logger.info("DEBUG -> Seting enclosure temperature: %s",self.enclosureSetTemperature) + if self._settings.get(["debug"]) is True: + self._logger.info( + "DEBUG -> Seting enclosure temperature: %s", self.enclosureSetTemperature) self.handleTemperatureControl() - return flask.jsonify(enclosureSetTemperature=self.enclosureSetTemperature,enclosureCurrentTemperature=self.enclosureCurrentTemperature) + return flask.jsonify(enclosureSetTemperature=self.enclosureSetTemperature, enclosureCurrentTemperature=self.enclosureCurrentTemperature) @octoprint.plugin.BlueprintPlugin.route("/getEnclosureSetTemperature", methods=["GET"]) def getEnclosureSetTemperature(self): @@ -103,13 +105,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, getOutputStatusresult = '' for rpi_output in self.rpi_outputs: pin = self.toInt(rpi_output['gpioPin']) - if rpi_output['outputType']=='regular': - val = GPIO.input(pin) if not rpi_output['activeLow'] else (not GPIO.input(pin)) + if rpi_output['outputType'] == 'regular': + val = GPIO.input(pin) if not rpi_output['activeLow'] else ( + not GPIO.input(pin)) if getOutputStatusresult: getOutputStatusresult = getOutputStatusresult + ', ' - getOutputStatusresult = getOutputStatusresult + '"' + str(pin) + '": ' + str(val).lower() + getOutputStatusresult = getOutputStatusresult + \ + '"' + str(pin) + '": ' + str(val).lower() return '{' + getOutputStatusresult + '}' - @octoprint.plugin.BlueprintPlugin.route("/getEnclosureTemperature", methods=["GET"]) def getEnclosureTemperature(self): @@ -129,7 +132,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def setPWM(self): io = flask.request.values["io"] pwmVal = flask.request.values["pwmVal"] - self.writePWM(self.toInt(io),self.toInt(pwmVal)) + self.writePWM(self.toInt(io), self.toInt(pwmVal)) return flask.make_response("Ok.", 200) @octoprint.plugin.BlueprintPlugin.route("/setNeopixel", methods=["GET"]) @@ -139,43 +142,46 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, green = flask.request.values["green"] blue = flask.request.values["blue"] for rpi_output in self.rpi_outputs: - if self.toInt(io) == self.toInt(rpi_output['gpioPin']) and rpi_output['outputType']=='neopixel': + if self.toInt(io) == self.toInt(rpi_output['gpioPin']) and rpi_output['outputType'] == 'neopixel': ledCount = rpi_output['neopixelCount'] ledBrightness = rpi_output['neopixelBrightness'] address = rpi_output['microAddress'] - self.sendNeopixelCommand(io,ledCount,ledBrightness,red,green,blue,address) + self.sendNeopixelCommand( + io, ledCount, ledBrightness, red, green, blue, address) return flask.make_response("Ok.", 200) - #~~ Plugin Internal methods + # ~~ Plugin Internal methods def fixData(self): for rpi_output in self.rpi_outputs: - if not 'outputType' in rpi_output: + if 'outputType' not in rpi_output: rpi_output['outputType'] = 'regular' - if not 'frequency' in rpi_output: + if 'frequency' not in rpi_output: rpi_output['frequency'] = 50 - if not 'dutycycle' in rpi_output: + if 'dutycycle' not in rpi_output: rpi_output['dutycycle'] = 0 - if not 'color' in rpi_output: + if 'color' not in rpi_output: rpi_output['color'] = 'rgb(255,0,0)' - if not 'neopixelCount' in rpi_output: + if 'neopixelCount' not in rpi_output: rpi_output['neopixelCount'] = 0 - if not 'microAddress' in rpi_output: + if 'microAddress' not in rpi_output: rpi_output['microAddress'] = 0 - if not 'neopixelBrightness' in rpi_output: + if 'neopixelBrightness' not in rpi_output: rpi_output['neopixelBrightness'] = 255 for temp_reader in self.temperature_reading: - if not 'sensorAddress' in temp_reader: + if 'sensorAddress' not in temp_reader: temp_reader['sensorAddress'] = 0 - self._settings.set(["rpi_outputs"],self.rpi_outputs) - self._settings.set(["temperature_reading"],self.temperature_reading) + self._settings.set(["rpi_outputs"], self.rpi_outputs) + self._settings.set(["temperature_reading"], self.temperature_reading) - def sendNeopixelCommand(self,ledPin,ledCount,ledBrightness,red,green,blue,address): + def sendNeopixelCommand(self, ledPin, ledCount, ledBrightness, red, green, blue, address): try: - script = os.path.dirname(os.path.realpath(__file__)) + "/neopixel.py " - cmd ="sudo python " +script +str(ledPin)+" "+str(ledCount)+" "+str(ledBrightness)+" "+str(red)+" "+str(green)+" "+str(blue)+" "+str(address) - if self._settings.get(["debug"]) == True: + script = os.path.dirname( + os.path.realpath(__file__)) + "/neopixel.py " + cmd = "sudo python " + script + str(ledPin) + " " + str(ledCount) + " " + str( + ledBrightness) + " " + str(red) + " " + str(green) + " " + str(blue) + " " + str(address) + if self._settings.get(["debug"]) is True: self._logger.info("Sending neopixel cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() except Exception as ex: @@ -190,16 +196,20 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if temp_reader['isEnabled']: if temp_reader['sensorType'] in ["11", "22", "2302"]: self._logger.info("sensorType dht") - temp, hum = self.readDhtTemp(temp_reader['sensorType'],temp_reader['gpioPin']) + temp, hum = self.readDhtTemp( + temp_reader['sensorType'], temp_reader['gpioPin']) elif temp_reader['sensorType'] == "18b20": temp = self.read18b20Temp() hum = 0 elif temp_reader['sensorType'] == "bme280": - temp, hum = self.readBME280Temp(temp_reader['sensorAddress']) + temp, hum = self.readBME280Temp( + temp_reader['sensorAddress']) elif temp_reader['sensorType'] == "si7021": - temp, hum = self.readSI7021Temp(temp_reader['sensorAddress']) + temp, hum = self.readSI7021Temp( + temp_reader['sensorAddress']) elif temp_reader['sensorType'] == "tmp102": - temp = self.readTmp102Temp(temp_reader['sensorAddress']) + temp = self.readTmp102Temp( + temp_reader['sensorAddress']) hum = 0 else: self._logger.info("sensorType no match") @@ -207,13 +217,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, hum = 0 if temp != -1 and hum != -1: - self.enclosureCurrentTemperature = round(self.toFloat(temp),1) if not temp_reader['useFahrenheit'] else round(self.toFloat(temp)*1.8 + 32,1) - self.enclosureCurrentHumidity = round(self.toFloat(hum),1) + self.enclosureCurrentTemperature = round(self.toFloat( + temp), 1) if not temp_reader['useFahrenheit'] else round(self.toFloat(temp) * 1.8 + 32, 1) + self.enclosureCurrentHumidity = round( + self.toFloat(hum), 1) - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: - self._logger.info("Temperature: %s humidity %s", self.enclosureCurrentTemperature,self.enclosureCurrentHumidity) + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + self._logger.info( + "Temperature: %s humidity %s", self.enclosureCurrentTemperature, self.enclosureCurrentHumidity) - self._plugin_manager.send_plugin_message(self._identifier, dict(enclosuretemp=self.enclosureCurrentTemperature,enclosureHumidity=self.enclosureCurrentHumidity)) + self._plugin_manager.send_plugin_message(self._identifier, dict( + enclosuretemp=self.enclosureCurrentTemperature, enclosureHumidity=self.enclosureCurrentHumidity)) self.handleTemperatureControl() self.handleTemperatureEvents() except Exception as ex: @@ -226,61 +240,65 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for rpi_input in self.rpi_inputs: if self.toFloat(rpi_input['setTemp']) == 0: continue - if rpi_input['eventType']=='temperature' and (self.toFloat(rpi_input['setTemp']) < self.toFloat(self.enclosureCurrentTemperature)): + if rpi_input['eventType'] == 'temperature' and (self.toFloat(rpi_input['setTemp']) < self.toFloat(self.enclosureCurrentTemperature)): for rpi_output in self.rpi_outputs: if self.toInt(rpi_input['controlledIO']) == self.toInt(rpi_output['gpioPin']): val = GPIO.LOW if rpi_output['activeLow'] else GPIO.HIGH self.writeGPIO(self.toInt(rpi_output['gpioPin']), val) for notification in self.notifications: if notification['temperatureAction']: - msg = "Temperature action: enclosure temperature exceed " +rpi_input['setTemp'] + msg = "Temperature action: enclosure temperature exceed " + \ + rpi_input['setTemp'] self.sendNotification(msg) - def readDhtTemp(self,sensor,pin): + def readDhtTemp(self, sensor, pin): try: - script = os.path.dirname(os.path.realpath(__file__)) + "/getDHTTemp.py " - cmd ="sudo python " +script+str(sensor)+" "+str(pin) - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: + script = os.path.dirname( + os.path.realpath(__file__)) + "/getDHTTemp.py " + cmd = "sudo python " + script + str(sensor) + " " + str(pin) + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: self._logger.info("Temperature dht cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: self._logger.info("Dht result: %s", stdout) - temp,hum = stdout.split("|") - return (self.toFloat(temp.strip()),self.toFloat(hum.strip())) + temp, hum = stdout.split("|") + return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) except Exception as ex: template = "An exception of type {0} occurred on readDhtTemp. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) self._logger.warn(message) return (0, 0) - def readBME280Temp(self,address): + def readBME280Temp(self, address): try: - script = os.path.dirname(os.path.realpath(__file__)) + "/BME280.py " - cmd ="sudo python " +script +str(address) - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: + script = os.path.dirname( + os.path.realpath(__file__)) + "/BME280.py " + cmd = "sudo python " + script + str(address) + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: self._logger.info("Temperature BME280 cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: self._logger.info("BME280 result: %s", stdout) - temp,hum = stdout.split("|") - return (self.toFloat(temp.strip()),self.toFloat(hum.strip())) + temp, hum = stdout.split("|") + return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) except Exception as ex: template = "An exception of type {0} occurred on readBME280Temp. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) self._logger.warn(message) return (0, 0) - def readSI7021Temp(self,address): + def readSI7021Temp(self, address): try: - script = os.path.dirname(os.path.realpath(__file__)) + "/SI7021.py " - cmd ="sudo python " +script +str(address) - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: + script = os.path.dirname( + os.path.realpath(__file__)) + "/SI7021.py " + cmd = "sudo python " + script + str(address) + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: self._logger.info("Temperature SI7021 cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: self._logger.info("SI7021 result: %s", stdout) - temp,hum = stdout.split("|") - return (self.toFloat(temp.strip()),self.toFloat(hum.strip())) + temp, hum = stdout.split("|") + return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) except Exception as ex: template = "An exception of type {0} occurred on readSI7021Temp. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) @@ -297,7 +315,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, lines = self.readraw18b20Temp() equals_pos = lines[1].find('t=') if equals_pos != -1: - temp_string = lines[1][equals_pos+2:] + temp_string = lines[1][equals_pos + 2:] temp_c = float(temp_string) / 1000.0 return '{0:0.1f}'.format(temp_c) return 0 @@ -315,11 +333,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: script = os.path.dirname(os.path.realpath(__file__)) + "/tmp102.py" args = ["python", script, str(address)] - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: self._logger.info("Temperature TMP102 cmd: %s", " ".join(args)) proc = Popen(args, stdout=PIPE) stdout, _ = proc.communicate() - if self._settings.get(["debug"]) == True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: self._logger.info("TMP102 result: %s", stdout) return self.toFloat(stdout.strip()) except Exception as ex: @@ -328,24 +346,27 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) return 0 - def handleTemperatureControl(self): for control in self.temperature_control: - if control['isEnabled'] == True: - if control['controlType'] == 'heater': - self.currentTempControlStatus = self.toFloat(self.enclosureCurrentTemperature)self.toFloat(self.enclosureSetTemperature) + self.currentTempControlStatus = self.toFloat( + self.enclosureCurrentTemperature) > self.toFloat(self.enclosureSetTemperature) if self.currentTempControlStatus != self.previousTempControlStatus: if self.currentTempControlStatus: - self._logger.info("Turning gpio to control temperature on.") - val = False if control['activeLow'] else True - self.writeGPIO(self.toInt(control['gpioPin']),val) + self._logger.info( + "Turning gpio to control temperature on.") + val = False if control['activeLow'] else True + self.writeGPIO(self.toInt(control['gpioPin']), val) else: - self._logger.info("Turning gpio to control temperature off.") + self._logger.info( + "Turning gpio to control temperature off.") val = True if control['activeLow'] else False self.writeGPIO(self.toInt(control['gpioPin']), val) self.previousTempControlStatus = self.currentTempControlStatus @@ -353,18 +374,22 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def startGPIO(self): try: currentMode = GPIO.getmode() - setMode = GPIO.BOARD if self._settings.get(["useBoardPinNumber"]) else GPIO.BCM - if currentMode == None: + setMode = GPIO.BOARD if self._settings.get( + ["useBoardPinNumber"]) else GPIO.BCM + if currentMode is None: GPIO.setmode(setMode) tempstr = "BOARD" if setMode == GPIO.BOARD else "BCM" - self._logger.info("Setting GPIO mode to %s",tempstr) + self._logger.info("Setting GPIO mode to %s", tempstr) elif currentMode != setMode: GPIO.setmode(currentMode) tempstr = "BOARD" if currentMode == GPIO.BOARD else "BCM" - self._settings.set(["useBoardPinNumber"],True if currentMode == GPIO.BOARD else False) - warn_msg = "GPIO mode was configured before, GPIO mode will be forced to use: " + tempstr + " as pin numbers. Please update GPIO accordingly!" + self._settings.set(["useBoardPinNumber"], + True if currentMode == GPIO.BOARD else False) + warn_msg = "GPIO mode was configured before, GPIO mode will be forced to use: " + \ + tempstr + " as pin numbers. Please update GPIO accordingly!" self._logger.info(warn_msg) - self._plugin_manager.send_plugin_message(self._identifier,dict(isMsg=True,msg=warn_msg)) + self._plugin_manager.send_plugin_message( + self._identifier, dict(isMsg=True, msg=warn_msg)) GPIO.setwarnings(False) except Exception as ex: template = "An exception of type {0} occurred on startGPIO. Arguments:\n{1!r}" @@ -392,7 +417,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def clearChannel(self,channel): + def clearChannel(self, channel): try: GPIO.cleanup(self.toInt(channel)) except Exception as ex: @@ -405,56 +430,64 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: for control in self.temperature_control: if control['isEnabled']: - GPIO.setup(self.toInt(control['gpioPin']), GPIO.OUT, initial=GPIO.HIGH if control['activeLow'] else GPIO.LOW) + GPIO.setup(self.toInt( + control['gpioPin']), GPIO.OUT, initial=GPIO.HIGH if control['activeLow'] else GPIO.LOW) for rpi_output in self.rpi_outputs: pin = self.toInt(rpi_output['gpioPin']) if rpi_output['outputType'] == 'regular': - if self.toInt(rpi_output['gpioPin']) not in self.previous_rpi_outputs : + if self.toInt(rpi_output['gpioPin']) not in self.previous_rpi_outputs: initialValue = GPIO.HIGH if rpi_output['activeLow'] else GPIO.LOW - GPIO.setup(pin, GPIO.OUT,initial=initialValue) + GPIO.setup(pin, GPIO.OUT, initial=initialValue) if rpi_output['outputType'] == 'pwm': - for pwm in (pwm for pwm in self.PWM_INSTANCES if pin in pwm): - self.PWM_INSTANCES.remove(pwm) - self.clearChannel(pin) - GPIO.setup(pin, GPIO.OUT) - p = GPIO.PWM(pin, self.toInt(rpi_output['frequency'])) - self.PWM_INSTANCES.append({pin:p}) + for pwm in (pwm for pwm in self.PWM_INSTANCES if pin in pwm): + self.PWM_INSTANCES.remove(pwm) + self.clearChannel(pin) + GPIO.setup(pin, GPIO.OUT) + p = GPIO.PWM(pin, self.toInt(rpi_output['frequency'])) + self.PWM_INSTANCES.append({pin: p}) if rpi_output['outputType'] == 'neopixel': - self.clearChannel(pin) + self.clearChannel(pin) for rpi_input in self.rpi_inputs: - pullResistor = pull_up_down=GPIO.PUD_UP if rpi_input['inputPull'] == 'inputPullUp' else GPIO.PUD_DOWN - GPIO.setup(self.toInt(rpi_input['gpioPin']), GPIO.IN, pullResistor) + pullResistor = pull_up_down = GPIO.PUD_UP if rpi_input[ + 'inputPull'] == 'inputPullUp' else GPIO.PUD_DOWN + GPIO.setup(self.toInt( + rpi_input['gpioPin']), GPIO.IN, pullResistor) if rpi_input['eventType'] == 'gpio' and self.toInt(rpi_input['gpioPin']) != 0: - edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING - GPIO.add_event_detect(self.toInt(rpi_input['gpioPin']), edge, callback= self.handleGPIOControl, bouncetime=200) + edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING + GPIO.add_event_detect(self.toInt( + rpi_input['gpioPin']), edge, callback=self.handleGPIOControl, bouncetime=200) if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] != 'filament' and self.toInt(rpi_input['gpioPin']) != 0: - edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING - GPIO.add_event_detect(self.toInt(rpi_input['gpioPin']), edge, callback= self.handlePrinterAction, bouncetime=200) + edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING + GPIO.add_event_detect(self.toInt( + rpi_input['gpioPin']), edge, callback=self.handlePrinterAction, bouncetime=200) except Exception as ex: template = "An exception of type {0} occurred on configureGPIO. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) self._logger.warn(message) pass - def handleFilammentDetection(self,channel): + def handleFilammentDetection(self, channel): try: for rpi_input in self.rpi_inputs: if channel == self.toInt(rpi_input['gpioPin']) and rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament' \ - and ((rpi_input['edge']=='fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): - if time.time() - self.lastFilamentEndDetected > self._settings.get_int(["filamentSensorTimeout"]): + and ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): + if time.time() - self.lastFilamentEndDetected > self._settings.get_int(["filamentSensorTimeout"]): self._logger.info("Detected end of filament.") self.lastFilamentEndDetected = time.time() for line in self._settings.get(["filamentSensorGcode"]).split('\n'): if line: self._printer.commands(line.strip().upper()) - self._logger.info("Sending GCODE command: %s",line.strip( ).upper()) + self._logger.info( + "Sending GCODE command: %s", line.strip().upper()) time.sleep(0.2) for notification in self.notifications: if notification['filamentChange']: - msg = "Filament change action caused by sensor: " + str(rpi_input['label']) + msg = "Filament change action caused by sensor: " + \ + str(rpi_input['label']) self.sendNotification(msg) else: - self._logger.info("Prevented end of filament detection, filament sensor timeout not elapsed.") + self._logger.info( + "Prevented end of filament detection, filament sensor timeout not elapsed.") except Exception as ex: template = "An exception of type {0} occurred on handleFilammentDetection. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) @@ -466,12 +499,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: for rpi_input in self.rpi_inputs: if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament' and self.toInt(rpi_input['gpioPin']) != 0: - edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING + edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING if GPIO.input(self.toInt(rpi_input['gpioPin'])) == (edge == GPIO.RISING): self._printer.pause_print() self._logger.info("Started printing with no filament.") else: - GPIO.add_event_detect(self.toInt(rpi_input['gpioPin']), edge, callback= self.handleFilammentDetection, bouncetime=200) + GPIO.add_event_detect(self.toInt( + rpi_input['gpioPin']), edge, callback=self.handleFilammentDetection, bouncetime=200) except Exception as ex: template = "An exception of type {0} occurred on startFilamentDetection. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) @@ -489,21 +523,24 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def handleGPIOControl(self,channel): + def handleGPIOControl(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.toInt(rpi_input['gpioPin']) and rpi_input['eventType']=='gpio' and \ - ((rpi_input['edge']=='fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): + if channel == self.toInt(rpi_input['gpioPin']) and rpi_input['eventType'] == 'gpio' and \ + ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): for rpi_output in self.rpi_outputs: - if self.toInt(rpi_input['controlledIO']) == self.toInt(rpi_output['gpioPin']) and rpi_output['outputType']=='regular': - if rpi_input['setControlledIO']=='toggle': - val = GPIO.LOW if GPIO.input(self.toInt(rpi_output['gpioPin']))==GPIO.HIGH else GPIO.HIGH + if self.toInt(rpi_input['controlledIO']) == self.toInt(rpi_output['gpioPin']) and rpi_output['outputType'] == 'regular': + if rpi_input['setControlledIO'] == 'toggle': + val = GPIO.LOW if GPIO.input(self.toInt( + rpi_output['gpioPin'])) == GPIO.HIGH else GPIO.HIGH else: - val = GPIO.LOW if rpi_input['setControlledIO']=='low' else GPIO.HIGH - self.writeGPIO(self.toInt(rpi_output['gpioPin']),val) + val = GPIO.LOW if rpi_input['setControlledIO'] == 'low' else GPIO.HIGH + self.writeGPIO(self.toInt( + rpi_output['gpioPin']), val) for notification in self.notifications: if notification['gpioAction']: - msg = "GPIO control action caused by input " + str(rpi_input['label']) + ". Setting GPIO" + str(rpi_input['controlledIO']) + " to: " + str(rpi_input['setControlledIO']) + msg = "GPIO control action caused by input " + str(rpi_input['label']) + ". Setting GPIO" + str( + rpi_input['controlledIO']) + " to: " + str(rpi_input['setControlledIO']) self.sendNotification(msg) except Exception as ex: template = "An exception of type {0} occurred on handleGPIOControl. Arguments:\n{1!r}" @@ -511,11 +548,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def handlePrinterAction(self,channel): + def handlePrinterAction(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.toInt(rpi_input['gpioPin']) and rpi_input['eventType']=='printer' and \ - ((rpi_input['edge']=='fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): + if channel == self.toInt(rpi_input['gpioPin']) and rpi_input['eventType'] == 'printer' and \ + ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): if rpi_input['printerAction'] == 'resume': self._logger.info("Printer action resume.") self._printer.resume_print() @@ -526,12 +563,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("Printer action cancel.") self._printer.cancel_print() elif rpi_input['printerAction'] == 'stopTemperatureControl': - self._logger.info("Printer action stoping temperature control.") - self.enclosureSetTemperature = 0; + self._logger.info( + "Printer action stoping temperature control.") + self.enclosureSetTemperature = 0 self.handleTemperatureControl() for notification in self.notifications: if notification['printerAction']: - msg = "Printer action: " + rpi_input['printerAction'] + " caused by input: " + str(rpi_input['label']) + msg = "Printer action: " + \ + rpi_input['printerAction'] + \ + " caused by input: " + str(rpi_input['label']) self.sendNotification(msg) except Exception as ex: template = "An exception of type {0} occurred on handlePrinterAction. Arguments:\n{1!r}" @@ -539,11 +579,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def writeGPIO(self,gpio,value): + def writeGPIO(self, gpio, value): try: GPIO.output(gpio, value) - if self._settings.get(["debug"]) == True: - self._logger.info("Writing on gpio: %s value %s", gpio,value) + if self._settings.get(["debug"]) is True: + self._logger.info("Writing on gpio: %s value %s", gpio, value) self.updateOutputUI() except Exception as ex: template = "An exception of type {0} occurred on writeGPIO. Arguments:\n{1!r}" @@ -551,16 +591,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def writePWM(self,gpio,pwmValue): + def writePWM(self, gpio, pwmValue): try: for pwm in self.PWM_INSTANCES: if gpio in pwm: pwm_object = pwm[gpio] - pwm['dutycycle']=pwmValue + pwm['dutycycle'] = pwmValue pwm_object.stop() pwm_object.start(pwmValue) - if self._settings.get(["debug"]) == True: - self._logger.info("Writing PWM on gpio: %s value %s", gpio,pwmValue) + if self._settings.get(["debug"]) is True: + self._logger.info( + "Writing PWM on gpio: %s value %s", gpio, pwmValue) self.updateOutputUI() break except Exception as ex: @@ -576,23 +617,25 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for rpi_output in self.rpi_outputs: pin = self.toInt(rpi_output['gpioPin']) - if rpi_output['outputType']=='regular': - val = GPIO.input(pin) if not rpi_output['activeLow'] else (not GPIO.input(pin)) - result.append({pin:val}) - if rpi_output['outputType']=='pwm': + if rpi_output['outputType'] == 'regular': + val = GPIO.input(pin) if not rpi_output['activeLow'] else ( + not GPIO.input(pin)) + result.append({pin: val}) + if rpi_output['outputType'] == 'pwm': # self._logger.info("outputType is PWM") # self._logger.info("Got pin number: %s",pin) # self._logger.info("PWM_INSTANCES: %s",self.PWM_INSTANCES) for pwm in self.PWM_INSTANCES: if pin in pwm: if 'dutycycle' in pwm: - pwmVal = pwm['dutycycle']; + pwmVal = pwm['dutycycle'] val = self.toInt(pwmVal) else: val = 100 - result_pwm.append({pin:val}) + result_pwm.append({pin: val}) # self._logger.info("result_pwm: %s", result_pwm) - self._plugin_manager.send_plugin_message(self._identifier, dict(rpi_output=result,rpi_output_pwm=result_pwm)) + self._plugin_manager.send_plugin_message( + self._identifier, dict(rpi_output=result, rpi_output_pwm=result_pwm)) except Exception as ex: template = "An exception of type {0} occurred on updateOutputUI. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) @@ -607,14 +650,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def sendNotification(self, message): try: - provider = self._settings.get(["notificationProvider"]) + provider = self._settings.get(["notificationProvider"]) if provider == 'ifttt': - event = self._settings.get(["event_name"]) - api_key = self._settings.get(["apiKEY"]) - if self._settings.get(["debug"]) == True: - self._logger.info("Sending notification to: %s with msg: %s with key: %s", provider,message,api_key) + event = self._settings.get(["event_name"]) + api_key = self._settings.get(["apiKEY"]) + if self._settings.get(["debug"]) is True: + self._logger.info( + "Sending notification to: %s with msg: %s with key: %s", provider, message, api_key) try: - res = self.iftttNotification(message,event,api_key) + res = self.iftttNotification(message, event, api_key) except requests.exceptions.ConnectionError: self._logger.info("Error: Could not connect to IFTTT") except requests.exceptions.HTTPError: @@ -629,7 +673,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: j = res.json() except ValueError: - self._logger.info('Error: Could not parse server response. Event not sent') + self._logger.info( + 'Error: Could not parse server response. Event not sent') for err in j['errors']: self._logger.info('Error: {}'.format(err['message'])) except Exception as ex: @@ -638,12 +683,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def iftttNotification(self,message,event,api_key): - url = "https://maker.ifttt.com/trigger/{e}/with/key/{k}/".format(e=event,k=api_key) + def iftttNotification(self, message, event, api_key): + url = "https://maker.ifttt.com/trigger/{e}/with/key/{k}/".format( + e=event, k=api_key) payload = {'value1': message} return requests.post(url, data=payload) - #~~ EventPlugin mixin + # ~~ EventPlugin mixin def on_event(self, event, payload): if event == Events.CONNECTED: @@ -656,50 +702,59 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, map(scheduler.cancel, scheduler.queue) self.startFilamentDetection() for rpi_output in self.rpi_outputs: - if rpi_output['autoStartup'] and rpi_output['outputType']=='regular': + if rpi_output['autoStartup'] and rpi_output['outputType'] == 'regular': value = False if rpi_output['activeLow'] else True - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writeGPIO, (self.toInt(rpi_output['gpioPin']),value,)) - if rpi_output['autoStartup'] and rpi_output['outputType']=='pwm': + scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writeGPIO, (self.toInt( + rpi_output['gpioPin']), value,)) + if rpi_output['autoStartup'] and rpi_output['outputType'] == 'pwm': value = self.toInt(rpi_output['dutycycle']) - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writePWM, (self.toInt(rpi_output['gpioPin']),value,)) - if rpi_output['autoStartup'] and rpi_output['outputType']=='neopixel': + scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writePWM, (self.toInt( + rpi_output['gpioPin']), value,)) + if rpi_output['autoStartup'] and rpi_output['outputType'] == 'neopixel': gpioPin = rpi_output['gpioPin'] ledCount = rpi_output['neopixelCount'] ledBrightness = rpi_output['neopixelBrightness'] address = rpi_output['microAddress'] stringColor = rpi_output['color'] - stringColor = stringColor.replace('rgb(','') + stringColor = stringColor.replace('rgb(', '') - red = stringColor[:stringColor.index(',')] - stringColor = stringColor[stringColor.index(',')+1:] - green = stringColor[:stringColor.index(',')] - stringColor = stringColor[stringColor.index(',')+1:] + red = stringColor[:stringColor.index(',')] + stringColor = stringColor[stringColor.index(',') + 1:] + green = stringColor[:stringColor.index(',')] + stringColor = stringColor[stringColor.index(',') + 1:] blue = stringColor[:stringColor.index(')')] - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.sendNeopixelCommand, (gpioPin,ledCount,ledBrightness,red,green,blue,address,)) + scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.sendNeopixelCommand, ( + gpioPin, ledCount, ledBrightness, red, green, blue, address,)) scheduler.run() for control in self.temperature_control: - if control['autoStartup'] == True: - self.enclosureSetTemperature = self.toInt(control['defaultTemp']) - self._plugin_manager.send_plugin_message(self._identifier, dict(enclosureSetTemp=self.enclosureSetTemperature)) + if control['autoStartup'] is True: + self.enclosureSetTemperature = self.toInt( + control['defaultTemp']) + self._plugin_manager.send_plugin_message( + self._identifier, dict(enclosureSetTemp=self.enclosureSetTemperature)) elif event in (Events.PRINT_DONE, Events.PRINT_FAILED, Events.PRINT_CANCELLED): self.stopFilamentDetection() self.enclosureSetTemperature = 0 - self._plugin_manager.send_plugin_message(self._identifier, dict(enclosureSetTemp=self.enclosureSetTemperature)) + self._plugin_manager.send_plugin_message( + self._identifier, dict(enclosureSetTemp=self.enclosureSetTemperature)) for rpi_output in self.rpi_outputs: - if rpi_output['autoShutdown'] and rpi_output['outputType']=='regular': + if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'regular': value = True if rpi_output['activeLow'] else False - scheduler.enter(self.toFloat(rpi_output['shutdownTimeDelay']), 1, self.writeGPIO, (self.toInt(rpi_output['gpioPin']),value,)) - if rpi_output['autoShutdown'] and rpi_output['outputType']=='pwm': + scheduler.enter(self.toFloat(rpi_output['shutdownTimeDelay']), 1, self.writeGPIO, (self.toInt( + rpi_output['gpioPin']), value,)) + if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'pwm': value = 0 - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writePWM, (self.toInt(rpi_output['gpioPin']),value,)) - if rpi_output['autoShutdown'] and rpi_output['outputType']=='neopixel': + scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writePWM, (self.toInt( + rpi_output['gpioPin']), value,)) + if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'neopixel': gpioPin = rpi_output['gpioPin'] ledCount = rpi_output['neopixelCount'] ledBrightness = rpi_output['neopixelBrightness'] address = rpi_output['microAddress'] - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.sendNeopixelCommand, (gpioPin,ledCount,0,0,0,0,address,)) + scheduler.enter(self.toFloat( + rpi_output['startupTimeDelay']), 1, self.sendNeopixelCommand, (gpioPin, ledCount, 0, 0, 0, 0, address,)) scheduler.run() if event == Events.PRINT_DONE: @@ -707,12 +762,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if notification['printFinish']: file_name = os.path.basename(payload["file"]) elapsed_time_in_seconds = payload["time"] - elapsed_time = octoprint.util.get_formatted_timedelta(datetime.timedelta(seconds=elapsed_time_in_seconds)) - msg = "Print job finished: " + file_name + "finished printing in " + file_name,elapsed_time + elapsed_time = octoprint.util.get_formatted_timedelta( + datetime.timedelta(seconds=elapsed_time_in_seconds)) + msg = "Print job finished: " + file_name + \ + "finished printing in " + file_name, elapsed_time self.sendNotification(msg) - - #~~ SettingsPlugin mixin + # ~~ SettingsPlugin mixin def on_settings_save(self, data): self._logger.info("data: %s", data) @@ -731,62 +787,66 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for pin in (pin for pin in outputsBeforeSave if pin not in commonPins): self.clearChannel(pin) - self.previous_rpi_outputs = commonPins; + self.previous_rpi_outputs = commonPins self.clearGPIO() - if self._settings.get(["debug"]) == True: - self._logger.info("temperature_reading: %s", self.temperature_reading) - self._logger.info("temperature_control: %s", self.temperature_control) + if self._settings.get(["debug"]) is True: + self._logger.info("temperature_reading: %s", + self.temperature_reading) + self._logger.info("temperature_control: %s", + self.temperature_control) self._logger.info("rpi_outputs: %s", self.rpi_outputs) self._logger.info("rpi_inputs: %s", self.rpi_inputs) self.startGPIO() self.configureGPIO() - def get_settings_defaults(self): return dict( - temperature_reading = [{ 'isEnabled': False, 'gpioPin': 4, 'useFahrenheit':False, 'sensorType':'','sensorAddress':0}], - temperature_control = [{ 'isEnabled': False, 'controlType':'heater', 'gpioPin': 17, 'activeLow': True, 'autoStartup': False,'defaultTemp':0}], - rpi_outputs = [], - rpi_inputs = [], - filamentSensorGcode = "G91 ;Set Relative Mode \n" + - "G1 E-5.000000 F500 ;Retract 5mm\n" + - "G1 Z15 F300 ;move Z up 15mm\n" + - "G90 ;Set Absolute Mode\n " + - "G1 X20 Y20 F9000 ;Move to hold position\n" + - "G91 ;Set Relative Mode\n" + - "G1 E-40 F500 ;Retract 40mm\n" + - "M0 ;Idle Hold\n" + - "G90 ;Set Absolute Mode\n" + - "G1 F5000 ;Set speed limits\n" + - "G28 X0 Y0 ;Home X Y\n" + - "M82 ;Set extruder to Absolute Mode\n" + - "G92 E0 ;Set Extruder to 0", + temperature_reading=[{'isEnabled': False, 'gpioPin': 4, + 'useFahrenheit': False, 'sensorType': '', 'sensorAddress': 0}], + temperature_control=[{'isEnabled': False, 'controlType': 'heater', + 'gpioPin': 17, 'activeLow': True, 'autoStartup': False, 'defaultTemp': 0}], + rpi_outputs=[], + rpi_inputs=[], + filamentSensorGcode="G91 ;Set Relative Mode \n" + + "G1 E-5.000000 F500 ;Retract 5mm\n" + + "G1 Z15 F300 ;move Z up 15mm\n" + + "G90 ;Set Absolute Mode\n " + + "G1 X20 Y20 F9000 ;Move to hold position\n" + + "G91 ;Set Relative Mode\n" + + "G1 E-40 F500 ;Retract 40mm\n" + + "M0 ;Idle Hold\n" + + "G90 ;Set Absolute Mode\n" + + "G1 F5000 ;Set speed limits\n" + + "G28 X0 Y0 ;Home X Y\n" + + "M82 ;Set extruder to Absolute Mode\n" + + "G92 E0 ;Set Extruder to 0", debug=True, useBoardPinNumber=False, filamentSensorTimeout=120, - notificationProvider = "disabled", - apiKEY = "", + notificationProvider="disabled", + apiKEY="", event_name="printer_event", showTempNavbar=False, - notifications=[{'printFinish':True,'filamentChange':True,'printerAction':True,'temperatureAction':True,'gpioAction':True}] + notifications=[{'printFinish': True, 'filamentChange': True, + 'printerAction': True, 'temperatureAction': True, 'gpioAction': True}] ) - #~~ TemplatePlugin + # ~~ TemplatePlugin def get_template_configs(self): return [ - dict(type="settings", custom_bindings=True), - dict(type="tab", custom_bindings=True) + dict(type="settings", custom_bindings=True), + dict(type="tab", custom_bindings=True) ] - ##~~ AssetPlugin mixin + # ~~ AssetPlugin mixin def get_assets(self): return dict( - js=["js/enclosure.js","js/bootstrap-colorpicker.min.js"], + js=["js/enclosure.js", "js/bootstrap-colorpicker.min.js"], css=["css/bootstrap-colorpicker.css"] ) - ##~~ Softwareupdate hook + # ~~ Softwareupdate hook def get_update_information(self): return dict( enclosure=dict( @@ -804,8 +864,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, ) ) + __plugin_name__ = "Enclosure Plugin" + def __plugin_load__(): global __plugin_implementation__ __plugin_implementation__ = EnclosurePlugin() -- 2.39.5 From 86612ae71c305a347a6e1f517c5668a6ad471e96 Mon Sep 17 00:00:00 2001 From: Vitor de Miranda Henrique Date: Wed, 17 Jan 2018 19:53:28 -0600 Subject: [PATCH 02/42] fixed threading issue and improved error handling.. --- octoprint_enclosure/__init__.py | 211 +++++++++++++++++--------------- 1 file changed, 110 insertions(+), 101 deletions(-) diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index 4c0d797..c52a94a 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -6,7 +6,6 @@ from subprocess import Popen, PIPE import octoprint.plugin import RPi.GPIO as GPIO import flask -import sched import time import sys import glob @@ -14,8 +13,7 @@ import os import datetime import octoprint.util import requests - -scheduler = sched.scheduler(time.time, time.sleep) +import inspect class EnclosurePlugin(octoprint.plugin.StartupPlugin, @@ -38,8 +36,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, previous_rpi_outputs = [] notifications = [] - PWM_INSTANCES = [] - disable_temeprature_log = True + pwm_intances = [] + queue = [] def startTimer(self): self._checkTempTimer = RepeatedTimer( @@ -62,7 +60,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # ~~ StartupPlugin mixin def on_after_startup(self): - self.PWM_INSTANCES = [] + self.pwm_intances = [] + self.queue = [] self.temperature_reading = self._settings.get(["temperature_reading"]) self.temperature_control = self._settings.get(["temperature_control"]) self.rpi_outputs = self._settings.get(["rpi_outputs"]) @@ -72,7 +71,6 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.previous_rpi_outputs = [] self.startTimer() self.startGPIO() - # self.clearGPIO() self.configureGPIO() self.updateOutputUI() @@ -152,28 +150,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # ~~ Plugin Internal methods def fixData(self): - for rpi_output in self.rpi_outputs: - if 'outputType' not in rpi_output: - rpi_output['outputType'] = 'regular' - if 'frequency' not in rpi_output: - rpi_output['frequency'] = 50 - if 'dutycycle' not in rpi_output: - rpi_output['dutycycle'] = 0 - if 'color' not in rpi_output: - rpi_output['color'] = 'rgb(255,0,0)' - if 'neopixelCount' not in rpi_output: - rpi_output['neopixelCount'] = 0 - if 'microAddress' not in rpi_output: - rpi_output['microAddress'] = 0 - if 'neopixelBrightness' not in rpi_output: - rpi_output['neopixelBrightness'] = 255 - - for temp_reader in self.temperature_reading: - if 'sensorAddress' not in temp_reader: - temp_reader['sensorAddress'] = 0 - - self._settings.set(["rpi_outputs"], self.rpi_outputs) - self._settings.set(["temperature_reading"], self.temperature_reading) + if not self._settings.get(["settingsVersion"]) == "3.6": + self._settings.set(["rpi_outputs"], []) + self._settings.set(["rpi_inputs"], []) def sendNeopixelCommand(self, ledPin, ledCount, ledBrightness, red, green, blue, address): try: @@ -185,8 +164,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("Sending neopixel cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() except Exception as ex: - template = "An exception of type {0} occurred on sendNeopixelCommand. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -222,7 +202,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.enclosureCurrentHumidity = round( self.toFloat(hum), 1) - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info( "Temperature: %s humidity %s", self.enclosureCurrentTemperature, self.enclosureCurrentHumidity) @@ -231,8 +211,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.handleTemperatureControl() self.handleTemperatureEvents() except Exception as ex: - template = "An exception of type {0} occurred on checkEnclosureTemp. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -256,16 +237,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, script = os.path.dirname( os.path.realpath(__file__)) + "/getDHTTemp.py " cmd = "sudo python " + script + str(sensor) + " " + str(pin) - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("Temperature dht cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("Dht result: %s", stdout) temp, hum = stdout.split("|") return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) except Exception as ex: - template = "An exception of type {0} occurred on readDhtTemp. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) return (0, 0) @@ -274,16 +256,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, script = os.path.dirname( os.path.realpath(__file__)) + "/BME280.py " cmd = "sudo python " + script + str(address) - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("Temperature BME280 cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("BME280 result: %s", stdout) temp, hum = stdout.split("|") return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) except Exception as ex: - template = "An exception of type {0} occurred on readBME280Temp. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) return (0, 0) @@ -292,16 +275,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, script = os.path.dirname( os.path.realpath(__file__)) + "/SI7021.py " cmd = "sudo python " + script + str(address) - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("Temperature SI7021 cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("SI7021 result: %s", stdout) temp, hum = stdout.split("|") return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) except Exception as ex: - template = "An exception of type {0} occurred on readSI7021Temp. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) return (0, 0) @@ -333,16 +317,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: script = os.path.dirname(os.path.realpath(__file__)) + "/tmp102.py" args = ["python", script, str(address)] - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("Temperature TMP102 cmd: %s", " ".join(args)) proc = Popen(args, stdout=PIPE) stdout, _ = proc.communicate() - if self._settings.get(["debug"]) is True and not self.disable_temeprature_log: + if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("TMP102 result: %s", stdout) return self.toFloat(stdout.strip()) except Exception as ex: - template = "An exception of type {0} occurred on readTmp102Temp. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) return 0 @@ -392,8 +377,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._identifier, dict(isMsg=True, msg=warn_msg)) GPIO.setwarnings(False) except Exception as ex: - template = "An exception of type {0} occurred on startGPIO. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -412,8 +398,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, pass GPIO.cleanup(self.toInt(rpi_input['gpioPin'])) except Exception as ex: - template = "An exception of type {0} occurred on clearGPIO. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -421,8 +408,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: GPIO.cleanup(self.toInt(channel)) except Exception as ex: - template = "An exception of type {0} occurred on clearChannel. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -439,12 +427,12 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, initialValue = GPIO.HIGH if rpi_output['activeLow'] else GPIO.LOW GPIO.setup(pin, GPIO.OUT, initial=initialValue) if rpi_output['outputType'] == 'pwm': - for pwm in (pwm for pwm in self.PWM_INSTANCES if pin in pwm): - self.PWM_INSTANCES.remove(pwm) + for pwm in (pwm for pwm in self.pwm_intances if pin in pwm): + self.pwm_intances.remove(pwm) self.clearChannel(pin) GPIO.setup(pin, GPIO.OUT) p = GPIO.PWM(pin, self.toInt(rpi_output['frequency'])) - self.PWM_INSTANCES.append({pin: p}) + self.pwm_intances.append({pin: p}) if rpi_output['outputType'] == 'neopixel': self.clearChannel(pin) for rpi_input in self.rpi_inputs: @@ -461,8 +449,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, GPIO.add_event_detect(self.toInt( rpi_input['gpioPin']), edge, callback=self.handlePrinterAction, bouncetime=200) except Exception as ex: - template = "An exception of type {0} occurred on configureGPIO. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -489,8 +478,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info( "Prevented end of filament detection, filament sensor timeout not elapsed.") except Exception as ex: - template = "An exception of type {0} occurred on handleFilammentDetection. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -507,8 +497,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, GPIO.add_event_detect(self.toInt( rpi_input['gpioPin']), edge, callback=self.handleFilammentDetection, bouncetime=200) except Exception as ex: - template = "An exception of type {0} occurred on startFilamentDetection. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -518,11 +509,16 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament': GPIO.remove_event_detect(self.toInt(rpi_input['gpioPin'])) except Exception as ex: - template = "An exception of type {0} occurred on stopFilamentDetection. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass + def cancelEventsOnQueue(self): + for task in self.queue: + task.cancel() + def handleGPIOControl(self, channel): try: for rpi_input in self.rpi_inputs: @@ -543,8 +539,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, rpi_input['controlledIO']) + " to: " + str(rpi_input['setControlledIO']) self.sendNotification(msg) except Exception as ex: - template = "An exception of type {0} occurred on handleGPIOControl. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -574,8 +571,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, " caused by input: " + str(rpi_input['label']) self.sendNotification(msg) except Exception as ex: - template = "An exception of type {0} occurred on handlePrinterAction. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -586,14 +584,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("Writing on gpio: %s value %s", gpio, value) self.updateOutputUI() except Exception as ex: - template = "An exception of type {0} occurred on writeGPIO. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass def writePWM(self, gpio, pwmValue): try: - for pwm in self.PWM_INSTANCES: + for pwm in self.pwm_intances: if gpio in pwm: pwm_object = pwm[gpio] pwm['dutycycle'] = pwmValue @@ -605,8 +604,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.updateOutputUI() break except Exception as ex: - template = "An exception of type {0} occurred on writePWM. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -624,8 +624,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if rpi_output['outputType'] == 'pwm': # self._logger.info("outputType is PWM") # self._logger.info("Got pin number: %s",pin) - # self._logger.info("PWM_INSTANCES: %s",self.PWM_INSTANCES) - for pwm in self.PWM_INSTANCES: + # self._logger.info("pwm_intances: %s",self.pwm_intances) + for pwm in self.pwm_intances: if pin in pwm: if 'dutycycle' in pwm: pwmVal = pwm['dutycycle'] @@ -637,8 +637,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._plugin_manager.send_plugin_message( self._identifier, dict(rpi_output=result, rpi_output_pwm=result_pwm)) except Exception as ex: - template = "An exception of type {0} occurred on updateOutputUI. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass @@ -678,14 +679,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for err in j['errors']: self._logger.info('Error: {}'.format(err['message'])) except Exception as ex: - template = "An exception of type {0} occurred on sendNotification. Arguments:\n{1!r}" - message = template.format(type(ex).__name__, ex.args) + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass def iftttNotification(self, message, event, api_key): - url = "https://maker.ifttt.com/trigger/{e}/with/key/{k}/".format( - e=event, k=api_key) + url = "https://maker.ifttt.com/trigger/{e}/with/key/{k}/".format(e=event, k=api_key) payload = {'value1': message} return requests.post(url, data=payload) @@ -699,17 +700,19 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.startFilamentDetection() if event == Events.PRINT_STARTED: - map(scheduler.cancel, scheduler.queue) + self.cancelEventsOnQueue() self.startFilamentDetection() for rpi_output in self.rpi_outputs: if rpi_output['autoStartup'] and rpi_output['outputType'] == 'regular': value = False if rpi_output['activeLow'] else True - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writeGPIO, (self.toInt( - rpi_output['gpioPin']), value,)) + self.queue.append(threading.Timer(self.toFloat(rpi_output['startupTimeDelay']), + self.writeGPIO, + args=[self.toInt(rpi_output['gpioPin']), value])) if rpi_output['autoStartup'] and rpi_output['outputType'] == 'pwm': value = self.toInt(rpi_output['dutycycle']) - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writePWM, (self.toInt( - rpi_output['gpioPin']), value,)) + self.queue.append(threading.Timer(self.toFloat(rpi_output['startupTimeDelay']), + self.writePWM, + args=[self.toInt(rpi_output['gpioPin']), value])) if rpi_output['autoStartup'] and rpi_output['outputType'] == 'neopixel': gpioPin = rpi_output['gpioPin'] ledCount = rpi_output['neopixelCount'] @@ -724,9 +727,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, stringColor = stringColor[stringColor.index(',') + 1:] blue = stringColor[:stringColor.index(')')] - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.sendNeopixelCommand, ( - gpioPin, ledCount, ledBrightness, red, green, blue, address,)) - scheduler.run() + self.queue.append(threading.Timer(self.toFloat(rpi_output['startupTimeDelay']), + self.sendNeopixelCommand, + args=[gpioPin, ledCount, ledBrightness, red, green, blue, address])) + for task in self.queue: + task.start() for control in self.temperature_control: if control['autoStartup'] is True: self.enclosureSetTemperature = self.toInt( @@ -742,20 +747,24 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for rpi_output in self.rpi_outputs: if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'regular': value = True if rpi_output['activeLow'] else False - scheduler.enter(self.toFloat(rpi_output['shutdownTimeDelay']), 1, self.writeGPIO, (self.toInt( - rpi_output['gpioPin']), value,)) + self.queue.append(threading.Timer(self.toFloat(rpi_output['shutdownTimeDelay']), + self.writeGPIO, + args=[self.toInt(rpi_output['gpioPin']), value])) if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'pwm': value = 0 - scheduler.enter(self.toFloat(rpi_output['startupTimeDelay']), 1, self.writePWM, (self.toInt( - rpi_output['gpioPin']), value,)) + self.queue.append(threading.Timer(self.toFloat(rpi_output['shutdownTimeDelay']), + self.writePWM, + args=[self.toInt(rpi_output['gpioPin']), value])) if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'neopixel': gpioPin = rpi_output['gpioPin'] ledCount = rpi_output['neopixelCount'] ledBrightness = rpi_output['neopixelBrightness'] address = rpi_output['microAddress'] - scheduler.enter(self.toFloat( - rpi_output['startupTimeDelay']), 1, self.sendNeopixelCommand, (gpioPin, ledCount, 0, 0, 0, 0, address,)) - scheduler.run() + self.queue.append(threading.Timer(self.toFloat(rpi_output['shutdownTimeDelay']), + self.sendNeopixelCommand, + args=[gpioPin, ledCount, 0, 0, 0, 0, address])) + for task in self.queue: + task.start() if event == Events.PRINT_DONE: for notification in self.notifications: @@ -822,12 +831,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, "M82 ;Set extruder to Absolute Mode\n" + "G92 E0 ;Set Extruder to 0", debug=True, + enableTemperatureLog=False, useBoardPinNumber=False, filamentSensorTimeout=120, notificationProvider="disabled", apiKEY="", event_name="printer_event", showTempNavbar=False, + settingsVersion="", notifications=[{'printFinish': True, 'filamentChange': True, 'printerAction': True, 'temperatureAction': True, 'gpioAction': True}] ) @@ -852,13 +863,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, enclosure=dict( displayName="Enclosure Plugin", displayVersion=self._plugin_version, - # version check: github repository type="github_release", user="vitormhenrique", repo="OctoPrint-Enclosure", current=self._plugin_version, - # update method: pip pip="https://github.com/vitormhenrique/OctoPrint-Enclosure/archive/{target_version}.zip" ) -- 2.39.5 From 5a516f5c40fe73b9187dde57591cd374420d1344 Mon Sep 17 00:00:00 2001 From: de Miranda Henrique Date: Thu, 18 Jan 2018 17:02:46 -0600 Subject: [PATCH 03/42] more code refactoring + fixing issue #68 --- code.code-workspace | 12 + octoprint_enclosure/__init__.py | 434 +++++------ .../static/css/bootstrap-colorpicker.css | 0 .../alpha-horizontal.png | Bin .../img/bootstrap-colorpicker/alpha.png | Bin .../bootstrap-colorpicker/hue-horizontal.png | Bin .../static/img/bootstrap-colorpicker/hue.png | Bin .../img/bootstrap-colorpicker/saturation.png | Bin .../static/js/bootstrap-colorpicker.min.js | 0 octoprint_enclosure/static/js/enclosure.js | 677 +++++++++--------- .../templates/enclosure_tab.jinja2 | 2 +- 11 files changed, 565 insertions(+), 560 deletions(-) create mode 100644 code.code-workspace mode change 100755 => 100644 octoprint_enclosure/static/css/bootstrap-colorpicker.css mode change 100755 => 100644 octoprint_enclosure/static/img/bootstrap-colorpicker/alpha-horizontal.png mode change 100755 => 100644 octoprint_enclosure/static/img/bootstrap-colorpicker/alpha.png mode change 100755 => 100644 octoprint_enclosure/static/img/bootstrap-colorpicker/hue-horizontal.png mode change 100755 => 100644 octoprint_enclosure/static/img/bootstrap-colorpicker/hue.png mode change 100755 => 100644 octoprint_enclosure/static/img/bootstrap-colorpicker/saturation.png mode change 100755 => 100644 octoprint_enclosure/static/js/bootstrap-colorpicker.min.js diff --git a/code.code-workspace b/code.code-workspace new file mode 100644 index 0000000..616c67c --- /dev/null +++ b/code.code-workspace @@ -0,0 +1,12 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "terminal.integrated.env.osx": { + "PATH": "/Users/vitormhenrique/.platformio/penv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin" + } + } +} \ No newline at end of file diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index c52a94a..dc89f00 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -23,12 +23,12 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, octoprint.plugin.BlueprintPlugin, octoprint.plugin.EventHandlerPlugin): - previousTempControlStatus = False - currentTempControlStatus = False - enclosureSetTemperature = 0.0 - enclosureCurrentTemperature = 0.0 - enclosureCurrentHumidity = 0.0 - lastFilamentEndDetected = 0 + previous_temp_control_status = False + current_temp_control_status = False + enclosure_set_temperature = 0.0 + enclosure_current_temperature = 0.0 + enclosure_current_humidity = 0.0 + last_filament_end_detected = 0 temperature_reading = [] temperature_control = [] rpi_outputs = [] @@ -39,19 +39,34 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, pwm_intances = [] queue = [] - def startTimer(self): - self._checkTempTimer = RepeatedTimer( - 10, self.checkEnclosureTemp, None, None, True) - self._checkTempTimer.start() + def start_timer(self): + """ + Function to start timer that checks enclosure temperature + """ + + self._check_temp_timer = RepeatedTimer( + 10, self.check_enclosure_temp, None, None, True) + self._check_temp_timer.start() + + @staticmethod + def to_float(value): + """Converts value to flow + + Arguments: + value {any} -- value to be + + Returns: + float -- value converted + """ - def toFloat(self, value): try: val = float(value) return val except: return 0 - def toInt(self, value): + @staticmethod + def to_int(value): try: val = int(value) return val @@ -67,99 +82,114 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.rpi_outputs = self._settings.get(["rpi_outputs"]) self.rpi_inputs = self._settings.get(["rpi_inputs"]) self.notifications = self._settings.get(["notifications"]) - self.fixData() + self.fix_data() self.previous_rpi_outputs = [] - self.startTimer() - self.startGPIO() - self.configureGPIO() - self.updateOutputUI() + self.start_timer() + self.start_gpio() + self.configure_gpio() + self.update_output_ui() # ~~ Blueprintplugin mixin @octoprint.plugin.BlueprintPlugin.route("/setEnclosureTemperature", methods=["GET"]) - def setEnclosureTemperature(self): - self.enclosureSetTemperature = flask.request.values["enclosureSetTemp"] + def set_enclosure_temperature(self): + self.enclosure_set_temperature = flask.request.values["enclosureSetTemp"] if self._settings.get(["debug"]) is True: self._logger.info( - "DEBUG -> Seting enclosure temperature: %s", self.enclosureSetTemperature) - self.handleTemperatureControl() - return flask.jsonify(enclosureSetTemperature=self.enclosureSetTemperature, enclosureCurrentTemperature=self.enclosureCurrentTemperature) + "DEBUG -> Seting enclosure temperature: %s", self.enclosure_set_temperature) + self.handle_temperature_control() + return flask.jsonify(enclosureSetTemperature=self.enclosure_set_temperature, enclosureCurrentTemperature=self.enclosure_current_temperature) @octoprint.plugin.BlueprintPlugin.route("/getEnclosureSetTemperature", methods=["GET"]) - def getEnclosureSetTemperature(self): - return str(self.enclosureSetTemperature) + def get_enclosure_set_temperature(self): + return str(self.enclosure_set_temperature) @octoprint.plugin.BlueprintPlugin.route("/clearGPIOMode", methods=["GET"]) - def clearGPIOMode(self): + def clear_gpio_mode(self): GPIO.cleanup() return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/getUpdateBtnStatus", methods=["GET"]) - def getUpdateBtnStatus(self): - self.updateOutputUI() + def get_update_btn_status(self): + self.update_output_ui() return flask.make_response("Ok.", 200) @octoprint.plugin.BlueprintPlugin.route("/getOutputStatus", methods=["GET"]) - def getOutputStatus(self): - getOutputStatusresult = '' + def get_output_status(self): + result = '' for rpi_output in self.rpi_outputs: - pin = self.toInt(rpi_output['gpioPin']) + pin = self.to_int(rpi_output['gpioPin']) if rpi_output['outputType'] == 'regular': val = GPIO.input(pin) if not rpi_output['activeLow'] else ( not GPIO.input(pin)) - if getOutputStatusresult: - getOutputStatusresult = getOutputStatusresult + ', ' - getOutputStatusresult = getOutputStatusresult + \ + if result: + result = result + ', ' + result = result + \ '"' + str(pin) + '": ' + str(val).lower() - return '{' + getOutputStatusresult + '}' + return '{' + result + '}' @octoprint.plugin.BlueprintPlugin.route("/getEnclosureTemperature", methods=["GET"]) - def getEnclosureTemperature(self): - return str(self.enclosureCurrentTemperature) + def get_enclosure_temperature(self): + return str(self.enclosure_current_temperature) @octoprint.plugin.BlueprintPlugin.route("/setIO", methods=["GET"]) - def setIO(self): - io = flask.request.values["io"] + def set_io(self): + gpio = flask.request.values["io"] value = True if flask.request.values["status"] == "on" else False for rpi_output in self.rpi_outputs: - if self.toInt(io) == self.toInt(rpi_output['gpioPin']): + if self.to_int(gpio) == self.to_int(rpi_output['gpioPin']): val = (not value) if rpi_output['activeLow'] else value - self.writeGPIO(self.toInt(io), val) + self.write_gpio(self.to_int(gpio), val) return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/setPWM", methods=["GET"]) - def setPWM(self): - io = flask.request.values["io"] - pwmVal = flask.request.values["pwmVal"] - self.writePWM(self.toInt(io), self.toInt(pwmVal)) + def set_pwm(self): + gpio = flask.request.values["io"] + pwm_val = flask.request.values["pwmVal"] + self.write_pwm(self.to_int(gpio), self.to_int(pwm_val)) return flask.make_response("Ok.", 200) @octoprint.plugin.BlueprintPlugin.route("/setNeopixel", methods=["GET"]) - def setNeopixel(self): - io = flask.request.values["io"] + def set_neopixel(self): + """ set_neopixel method get request from octoprint and send the comand to arduino or neopixel""" + gpio = flask.request.values["io"] red = flask.request.values["red"] green = flask.request.values["green"] blue = flask.request.values["blue"] for rpi_output in self.rpi_outputs: - if self.toInt(io) == self.toInt(rpi_output['gpioPin']) and rpi_output['outputType'] == 'neopixel': - ledCount = rpi_output['neopixelCount'] - ledBrightness = rpi_output['neopixelBrightness'] + if self.to_int(gpio) == self.to_int(rpi_output['gpioPin']) and rpi_output['outputType'] == 'neopixel': + led_count = rpi_output['neopixelCount'] + led_brightness = rpi_output['neopixelBrightness'] address = rpi_output['microAddress'] - self.sendNeopixelCommand( - io, ledCount, ledBrightness, red, green, blue, address) + self.send_neopixel_command( + gpio, led_count, led_brightness, red, green, blue, address) return flask.make_response("Ok.", 200) # ~~ Plugin Internal methods - def fixData(self): + def fix_data(self): + """ Fix setting dada commin from old releases of the plugin""" + if not self._settings.get(["settingsVersion"]) == "3.6": self._settings.set(["rpi_outputs"], []) self._settings.set(["rpi_inputs"], []) - def sendNeopixelCommand(self, ledPin, ledCount, ledBrightness, red, green, blue, address): + def send_neopixel_command(self, led_pin, led_count, led_brightness, red, green, blue, address): + """Send neopixel command + + Arguments: + led_pin {int} -- GPIO number + ledCount {int} -- number of LEDS + ledBrightness {int} -- brightness from 0 to 255 + red {int} -- red value from 0 to 255 + green {int} -- gren value from 0 to 255 + blue {int} -- blue value from 0 to 255 + address {int} -- i2c address from microcontroler + """ + try: script = os.path.dirname( os.path.realpath(__file__)) + "/neopixel.py " - cmd = "sudo python " + script + str(ledPin) + " " + str(ledCount) + " " + str( - ledBrightness) + " " + str(red) + " " + str(green) + " " + str(blue) + " " + str(address) + cmd = "sudo python " + script + str(led_pin) + " " + str(led_count) + " " + str( + led_brightness) + " " + str(red) + " " + str(green) + " " + str(blue) + " " + str(address) if self._settings.get(["debug"]) is True: self._logger.info("Sending neopixel cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() @@ -170,25 +200,25 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def checkEnclosureTemp(self): + def check_enclosure_temp(self): try: for temp_reader in self.temperature_reading: if temp_reader['isEnabled']: if temp_reader['sensorType'] in ["11", "22", "2302"]: self._logger.info("sensorType dht") - temp, hum = self.readDhtTemp( + temp, hum = self.read_dht_temp( temp_reader['sensorType'], temp_reader['gpioPin']) elif temp_reader['sensorType'] == "18b20": - temp = self.read18b20Temp() + temp = self.read_18b20_temp() hum = 0 elif temp_reader['sensorType'] == "bme280": - temp, hum = self.readBME280Temp( + temp, hum = self.read_bme280_temp( temp_reader['sensorAddress']) elif temp_reader['sensorType'] == "si7021": - temp, hum = self.readSI7021Temp( + temp, hum = self.read_si7021_temp( temp_reader['sensorAddress']) elif temp_reader['sensorType'] == "tmp102": - temp = self.readTmp102Temp( + temp = self.read_tmp102_temp( temp_reader['sensorAddress']) hum = 0 else: @@ -197,19 +227,19 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, hum = 0 if temp != -1 and hum != -1: - self.enclosureCurrentTemperature = round(self.toFloat( - temp), 1) if not temp_reader['useFahrenheit'] else round(self.toFloat(temp) * 1.8 + 32, 1) - self.enclosureCurrentHumidity = round( - self.toFloat(hum), 1) + self.enclosure_current_temperature = round(self.to_float( + temp), 1) if not temp_reader['useFahrenheit'] else round(self.to_float(temp) * 1.8 + 32, 1) + self.enclosure_current_humidity = round( + self.to_float(hum), 1) if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info( - "Temperature: %s humidity %s", self.enclosureCurrentTemperature, self.enclosureCurrentHumidity) + "Temperature: %s humidity %s", self.enclosure_current_temperature, self.enclosure_current_humidity) self._plugin_manager.send_plugin_message(self._identifier, dict( - enclosuretemp=self.enclosureCurrentTemperature, enclosureHumidity=self.enclosureCurrentHumidity)) - self.handleTemperatureControl() - self.handleTemperatureEvents() + enclosuretemp=self.enclosure_current_temperature, enclosureHumidity=self.enclosure_current_humidity)) + self.handle_temperature_control() + self.handle_temperature_events() except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -217,22 +247,22 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def handleTemperatureEvents(self): + def handle_temperature_events(self): for rpi_input in self.rpi_inputs: - if self.toFloat(rpi_input['setTemp']) == 0: + if self.to_float(rpi_input['setTemp']) == 0: continue - if rpi_input['eventType'] == 'temperature' and (self.toFloat(rpi_input['setTemp']) < self.toFloat(self.enclosureCurrentTemperature)): + if rpi_input['eventType'] == 'temperature' and (self.to_float(rpi_input['setTemp']) < self.to_float(self.enclosure_current_temperature)): for rpi_output in self.rpi_outputs: - if self.toInt(rpi_input['controlledIO']) == self.toInt(rpi_output['gpioPin']): + if self.to_int(rpi_input['controlledIO']) == self.to_int(rpi_output['gpioPin']): val = GPIO.LOW if rpi_output['activeLow'] else GPIO.HIGH - self.writeGPIO(self.toInt(rpi_output['gpioPin']), val) + self.write_gpio(self.to_int(rpi_output['gpioPin']), val) for notification in self.notifications: if notification['temperatureAction']: msg = "Temperature action: enclosure temperature exceed " + \ rpi_input['setTemp'] - self.sendNotification(msg) + self.send_notification(msg) - def readDhtTemp(self, sensor, pin): + def read_dht_temp(self, sensor, pin): try: script = os.path.dirname( os.path.realpath(__file__)) + "/getDHTTemp.py " @@ -243,7 +273,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("Dht result: %s", stdout) temp, hum = stdout.split("|") - return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) + return (self.to_float(temp.strip()), self.to_float(hum.strip())) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -251,7 +281,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) return (0, 0) - def readBME280Temp(self, address): + def read_bme280_temp(self, address): try: script = os.path.dirname( os.path.realpath(__file__)) + "/BME280.py " @@ -262,7 +292,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("BME280 result: %s", stdout) temp, hum = stdout.split("|") - return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) + return (self.to_float(temp.strip()), self.to_float(hum.strip())) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -270,7 +300,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) return (0, 0) - def readSI7021Temp(self, address): + def read_si7021_temp(self, address): try: script = os.path.dirname( os.path.realpath(__file__)) + "/SI7021.py " @@ -281,7 +311,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("SI7021 result: %s", stdout) temp, hum = stdout.split("|") - return (self.toFloat(temp.strip()), self.toFloat(hum.strip())) + return (self.to_float(temp.strip()), self.to_float(hum.strip())) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -289,14 +319,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) return (0, 0) - def read18b20Temp(self): + def read_18b20_temp(self): os.system('modprobe w1-gpio') os.system('modprobe w1-therm') - lines = self.readraw18b20Temp() + lines = self.read_raw_18b20_temp() while lines[0].strip()[-3:] != 'YES': time.sleep(0.2) - lines = self.readraw18b20Temp() + lines = self.read_raw_18b20_temp() equals_pos = lines[1].find('t=') if equals_pos != -1: temp_string = lines[1][equals_pos + 2:] @@ -304,16 +334,16 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, return '{0:0.1f}'.format(temp_c) return 0 - def readraw18b20Temp(self): + def read_raw_18b20_temp(self): base_dir = '/sys/bus/w1/devices/' device_folder = glob.glob(base_dir + '28*')[0] device_file = device_folder + '/w1_slave' - f = open(device_file, 'r') - lines = f.readlines() - f.close() + device_file_result = open(device_file, 'r') + lines = device_file_result.readlines() + device_file_result.close() return lines - def readTmp102Temp(self, address): + def read_tmp102_temp(self, address): try: script = os.path.dirname(os.path.realpath(__file__)) + "/tmp102.py" args = ["python", script, str(address)] @@ -323,7 +353,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, stdout, _ = proc.communicate() if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: self._logger.info("TMP102 result: %s", stdout) - return self.toFloat(stdout.strip()) + return self.to_float(stdout.strip()) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -331,32 +361,32 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) return 0 - def handleTemperatureControl(self): + def handle_temperature_control(self): for control in self.temperature_control: if control['isEnabled'] is True: if control['controlType'] is 'heater': - self.currentTempControlStatus = self.toFloat( - self.enclosureCurrentTemperature) < self.toFloat(self.enclosureSetTemperature) + self.current_temp_control_status = self.to_float( + self.enclosure_current_temperature) < self.to_float(self.enclosure_set_temperature) else: - if self.toFloat(self.enclosureSetTemperature) == 0: - self.currentTempControlStatus = False + if self.to_float(self.enclosure_set_temperature) == 0: + self.current_temp_control_status = False else: - self.currentTempControlStatus = self.toFloat( - self.enclosureCurrentTemperature) > self.toFloat(self.enclosureSetTemperature) - if self.currentTempControlStatus != self.previousTempControlStatus: - if self.currentTempControlStatus: + self.current_temp_control_status = self.to_float( + self.enclosure_current_temperature) > self.to_float(self.enclosure_set_temperature) + if self.current_temp_control_status != self.previous_temp_control_status: + if self.current_temp_control_status: self._logger.info( "Turning gpio to control temperature on.") val = False if control['activeLow'] else True - self.writeGPIO(self.toInt(control['gpioPin']), val) + self.write_gpio(self.to_int(control['gpioPin']), val) else: self._logger.info( "Turning gpio to control temperature off.") val = True if control['activeLow'] else False - self.writeGPIO(self.toInt(control['gpioPin']), val) - self.previousTempControlStatus = self.currentTempControlStatus + self.write_gpio(self.to_int(control['gpioPin']), val) + self.previous_temp_control_status = self.current_temp_control_status - def startGPIO(self): + def start_gpio(self): try: currentMode = GPIO.getmode() setMode = GPIO.BOARD if self._settings.get( @@ -383,20 +413,20 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def clearGPIO(self): + def clear_gpio(self): try: for control in self.temperature_control: if control['isEnabled']: - GPIO.cleanup(self.toInt(control['gpioPin'])) + GPIO.cleanup(self.to_int(control['gpioPin'])) for rpi_output in self.rpi_outputs: - if self.toInt(rpi_output['gpioPin']) not in self.previous_rpi_outputs: - GPIO.cleanup(self.toInt(rpi_output['gpioPin'])) + if self.to_int(rpi_output['gpioPin']) not in self.previous_rpi_outputs: + GPIO.cleanup(self.to_int(rpi_output['gpioPin'])) for rpi_input in self.rpi_inputs: try: - GPIO.remove_event_detect(self.toInt(rpi_input['gpioPin'])) + GPIO.remove_event_detect(self.to_int(rpi_input['gpioPin'])) except: pass - GPIO.cleanup(self.toInt(rpi_input['gpioPin'])) + GPIO.cleanup(self.to_int(rpi_input['gpioPin'])) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -404,9 +434,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def clearChannel(self, channel): + def clear_channel(self, channel): try: - GPIO.cleanup(self.toInt(channel)) + GPIO.cleanup(self.to_int(channel)) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -414,40 +444,40 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def configureGPIO(self): + def configure_gpio(self): try: for control in self.temperature_control: if control['isEnabled']: - GPIO.setup(self.toInt( + GPIO.setup(self.to_int( control['gpioPin']), GPIO.OUT, initial=GPIO.HIGH if control['activeLow'] else GPIO.LOW) for rpi_output in self.rpi_outputs: - pin = self.toInt(rpi_output['gpioPin']) + pin = self.to_int(rpi_output['gpioPin']) if rpi_output['outputType'] == 'regular': - if self.toInt(rpi_output['gpioPin']) not in self.previous_rpi_outputs: + if self.to_int(rpi_output['gpioPin']) not in self.previous_rpi_outputs: initialValue = GPIO.HIGH if rpi_output['activeLow'] else GPIO.LOW GPIO.setup(pin, GPIO.OUT, initial=initialValue) if rpi_output['outputType'] == 'pwm': for pwm in (pwm for pwm in self.pwm_intances if pin in pwm): self.pwm_intances.remove(pwm) - self.clearChannel(pin) + self.clear_channel(pin) GPIO.setup(pin, GPIO.OUT) - p = GPIO.PWM(pin, self.toInt(rpi_output['frequency'])) + p = GPIO.PWM(pin, self.to_int(rpi_output['frequency'])) self.pwm_intances.append({pin: p}) if rpi_output['outputType'] == 'neopixel': - self.clearChannel(pin) + self.clear_channel(pin) for rpi_input in self.rpi_inputs: pullResistor = pull_up_down = GPIO.PUD_UP if rpi_input[ 'inputPull'] == 'inputPullUp' else GPIO.PUD_DOWN - GPIO.setup(self.toInt( + GPIO.setup(self.to_int( rpi_input['gpioPin']), GPIO.IN, pullResistor) - if rpi_input['eventType'] == 'gpio' and self.toInt(rpi_input['gpioPin']) != 0: + if rpi_input['eventType'] == 'gpio' and self.to_int(rpi_input['gpioPin']) != 0: edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING - GPIO.add_event_detect(self.toInt( - rpi_input['gpioPin']), edge, callback=self.handleGPIOControl, bouncetime=200) - if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] != 'filament' and self.toInt(rpi_input['gpioPin']) != 0: + GPIO.add_event_detect(self.to_int( + rpi_input['gpioPin']), edge, callback=self.handle_gpio_Control, bouncetime=200) + if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] != 'filament' and self.to_int(rpi_input['gpioPin']) != 0: edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING - GPIO.add_event_detect(self.toInt( - rpi_input['gpioPin']), edge, callback=self.handlePrinterAction, bouncetime=200) + GPIO.add_event_detect(self.to_int( + rpi_input['gpioPin']), edge, callback=self.handle_printer_action, bouncetime=200) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -455,14 +485,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def handleFilammentDetection(self, channel): + def handle_filamment_detection(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.toInt(rpi_input['gpioPin']) and rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament' \ - and ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): - if time.time() - self.lastFilamentEndDetected > self._settings.get_int(["filamentSensorTimeout"]): + if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament' \ + and ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): + if time.time() - self.last_filament_end_detected > self._settings.get_int(["filamentSensorTimeout"]): self._logger.info("Detected end of filament.") - self.lastFilamentEndDetected = time.time() + self.last_filament_end_detected = time.time() for line in self._settings.get(["filamentSensorGcode"]).split('\n'): if line: self._printer.commands(line.strip().upper()) @@ -473,7 +503,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if notification['filamentChange']: msg = "Filament change action caused by sensor: " + \ str(rpi_input['label']) - self.sendNotification(msg) + self.send_notification(msg) else: self._logger.info( "Prevented end of filament detection, filament sensor timeout not elapsed.") @@ -484,18 +514,18 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def startFilamentDetection(self): - self.stopFilamentDetection() + def start_filament_detection(self): + self.stop_filament_detection() try: for rpi_input in self.rpi_inputs: - if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament' and self.toInt(rpi_input['gpioPin']) != 0: + if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament' and self.to_int(rpi_input['gpioPin']) != 0: edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING - if GPIO.input(self.toInt(rpi_input['gpioPin'])) == (edge == GPIO.RISING): + if GPIO.input(self.to_int(rpi_input['gpioPin'])) == (edge == GPIO.RISING): self._printer.pause_print() self._logger.info("Started printing with no filament.") else: - GPIO.add_event_detect(self.toInt( - rpi_input['gpioPin']), edge, callback=self.handleFilammentDetection, bouncetime=200) + GPIO.add_event_detect(self.to_int( + rpi_input['gpioPin']), edge, callback=self.handle_filamment_detection, bouncetime=200) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -503,11 +533,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def stopFilamentDetection(self): + def stop_filament_detection(self): try: for rpi_input in self.rpi_inputs: if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament': - GPIO.remove_event_detect(self.toInt(rpi_input['gpioPin'])) + GPIO.remove_event_detect(self.to_int(rpi_input['gpioPin'])) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -515,29 +545,29 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def cancelEventsOnQueue(self): + def cancel_events_on_queue(self): for task in self.queue: task.cancel() - def handleGPIOControl(self, channel): + def handle_gpio_Control(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.toInt(rpi_input['gpioPin']) and rpi_input['eventType'] == 'gpio' and \ - ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): + if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['eventType'] == 'gpio' and \ + ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): for rpi_output in self.rpi_outputs: - if self.toInt(rpi_input['controlledIO']) == self.toInt(rpi_output['gpioPin']) and rpi_output['outputType'] == 'regular': + if self.to_int(rpi_input['controlledIO']) == self.to_int(rpi_output['gpioPin']) and rpi_output['outputType'] == 'regular': if rpi_input['setControlledIO'] == 'toggle': - val = GPIO.LOW if GPIO.input(self.toInt( + val = GPIO.LOW if GPIO.input(self.to_int( rpi_output['gpioPin'])) == GPIO.HIGH else GPIO.HIGH else: val = GPIO.LOW if rpi_input['setControlledIO'] == 'low' else GPIO.HIGH - self.writeGPIO(self.toInt( + self.write_gpio(self.to_int( rpi_output['gpioPin']), val) for notification in self.notifications: if notification['gpioAction']: msg = "GPIO control action caused by input " + str(rpi_input['label']) + ". Setting GPIO" + str( rpi_input['controlledIO']) + " to: " + str(rpi_input['setControlledIO']) - self.sendNotification(msg) + self.send_notification(msg) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -545,11 +575,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def handlePrinterAction(self, channel): + def handle_printer_action(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.toInt(rpi_input['gpioPin']) and rpi_input['eventType'] == 'printer' and \ - ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.toInt(rpi_input['gpioPin']))): + if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['eventType'] == 'printer' and \ + ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): if rpi_input['printerAction'] == 'resume': self._logger.info("Printer action resume.") self._printer.resume_print() @@ -562,14 +592,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, elif rpi_input['printerAction'] == 'stopTemperatureControl': self._logger.info( "Printer action stoping temperature control.") - self.enclosureSetTemperature = 0 - self.handleTemperatureControl() + self.enclosure_set_temperature = 0 + self.handle_temperature_control() for notification in self.notifications: if notification['printerAction']: msg = "Printer action: " + \ rpi_input['printerAction'] + \ " caused by input: " + str(rpi_input['label']) - self.sendNotification(msg) + self.send_notification(msg) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -577,12 +607,12 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def writeGPIO(self, gpio, value): + def write_gpio(self, gpio, value): try: GPIO.output(gpio, value) if self._settings.get(["debug"]) is True: self._logger.info("Writing on gpio: %s value %s", gpio, value) - self.updateOutputUI() + self.update_output_ui() except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -590,7 +620,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def writePWM(self, gpio, pwmValue): + def write_pwm(self, gpio, pwmValue): try: for pwm in self.pwm_intances: if gpio in pwm: @@ -601,7 +631,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if self._settings.get(["debug"]) is True: self._logger.info( "Writing PWM on gpio: %s value %s", gpio, pwmValue) - self.updateOutputUI() + self.update_output_ui() break except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" @@ -610,26 +640,23 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def updateOutputUI(self): + def update_output_ui(self): try: result = [] result_pwm = [] for rpi_output in self.rpi_outputs: - pin = self.toInt(rpi_output['gpioPin']) + pin = self.to_int(rpi_output['gpioPin']) if rpi_output['outputType'] == 'regular': val = GPIO.input(pin) if not rpi_output['activeLow'] else ( not GPIO.input(pin)) result.append({pin: val}) if rpi_output['outputType'] == 'pwm': - # self._logger.info("outputType is PWM") - # self._logger.info("Got pin number: %s",pin) - # self._logger.info("pwm_intances: %s",self.pwm_intances) for pwm in self.pwm_intances: if pin in pwm: if 'dutycycle' in pwm: pwmVal = pwm['dutycycle'] - val = self.toInt(pwmVal) + val = self.to_int(pwmVal) else: val = 100 result_pwm.append({pin: val}) @@ -643,13 +670,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def getOutputList(self): + def get_output_list(self): result = [] for rpi_output in self.rpi_outputs: - result.append(self.toInt(rpi_output['gpioPin'])) + result.append(self.to_int(rpi_output['gpioPin'])) return result - def sendNotification(self, message): + def send_notification(self, message): try: provider = self._settings.get(["notificationProvider"]) if provider == 'ifttt': @@ -659,7 +686,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info( "Sending notification to: %s with msg: %s with key: %s", provider, message, api_key) try: - res = self.iftttNotification(message, event, api_key) + res = self.ifttt_notification(message, event, api_key) except requests.exceptions.ConnectionError: self._logger.info("Error: Could not connect to IFTTT") except requests.exceptions.HTTPError: @@ -685,8 +712,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def iftttNotification(self, message, event, api_key): - url = "https://maker.ifttt.com/trigger/{e}/with/key/{k}/".format(e=event, k=api_key) + def ifttt_notification(self, message, event, api_key): + url = "https://maker.ifttt.com/trigger/{e}/with/key/{k}/".format( + e=event, k=api_key) payload = {'value1': message} return requests.post(url, data=payload) @@ -694,25 +722,25 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def on_event(self, event, payload): if event == Events.CONNECTED: - self.updateOutputUI() + self.update_output_ui() if event == Events.PRINT_RESUMED: - self.startFilamentDetection() + self.start_filament_detection() if event == Events.PRINT_STARTED: - self.cancelEventsOnQueue() - self.startFilamentDetection() + self.cancel_events_on_queue() + self.start_filament_detection() for rpi_output in self.rpi_outputs: if rpi_output['autoStartup'] and rpi_output['outputType'] == 'regular': value = False if rpi_output['activeLow'] else True - self.queue.append(threading.Timer(self.toFloat(rpi_output['startupTimeDelay']), - self.writeGPIO, - args=[self.toInt(rpi_output['gpioPin']), value])) + self.queue.append(threading.Timer(self.to_float(rpi_output['startupTimeDelay']), + self.write_gpio, + args=[self.to_int(rpi_output['gpioPin']), value])) if rpi_output['autoStartup'] and rpi_output['outputType'] == 'pwm': - value = self.toInt(rpi_output['dutycycle']) - self.queue.append(threading.Timer(self.toFloat(rpi_output['startupTimeDelay']), - self.writePWM, - args=[self.toInt(rpi_output['gpioPin']), value])) + value = self.to_int(rpi_output['dutycycle']) + self.queue.append(threading.Timer(self.to_float(rpi_output['startupTimeDelay']), + self.write_pwm, + args=[self.to_int(rpi_output['gpioPin']), value])) if rpi_output['autoStartup'] and rpi_output['outputType'] == 'neopixel': gpioPin = rpi_output['gpioPin'] ledCount = rpi_output['neopixelCount'] @@ -727,44 +755,44 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, stringColor = stringColor[stringColor.index(',') + 1:] blue = stringColor[:stringColor.index(')')] - self.queue.append(threading.Timer(self.toFloat(rpi_output['startupTimeDelay']), - self.sendNeopixelCommand, + self.queue.append(threading.Timer(self.to_float(rpi_output['startupTimeDelay']), + self.send_neopixel_command, args=[gpioPin, ledCount, ledBrightness, red, green, blue, address])) for task in self.queue: task.start() for control in self.temperature_control: if control['autoStartup'] is True: - self.enclosureSetTemperature = self.toInt( + self.enclosure_set_temperature = self.to_int( control['defaultTemp']) self._plugin_manager.send_plugin_message( - self._identifier, dict(enclosureSetTemp=self.enclosureSetTemperature)) + self._identifier, dict(enclosureSetTemp=self.enclosure_set_temperature)) elif event in (Events.PRINT_DONE, Events.PRINT_FAILED, Events.PRINT_CANCELLED): - self.stopFilamentDetection() - self.enclosureSetTemperature = 0 + self.stop_filament_detection() + self.enclosure_set_temperature = 0 self._plugin_manager.send_plugin_message( - self._identifier, dict(enclosureSetTemp=self.enclosureSetTemperature)) + self._identifier, dict(enclosureSetTemp=self.enclosure_set_temperature)) for rpi_output in self.rpi_outputs: if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'regular': value = True if rpi_output['activeLow'] else False - self.queue.append(threading.Timer(self.toFloat(rpi_output['shutdownTimeDelay']), - self.writeGPIO, - args=[self.toInt(rpi_output['gpioPin']), value])) + self.queue.append(threading.Timer(self.to_float(rpi_output['shutdownTimeDelay']), + self.write_gpio, + args=[self.to_int(rpi_output['gpioPin']), value])) if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'pwm': value = 0 - self.queue.append(threading.Timer(self.toFloat(rpi_output['shutdownTimeDelay']), - self.writePWM, - args=[self.toInt(rpi_output['gpioPin']), value])) + self.queue.append(threading.Timer(self.to_float(rpi_output['shutdownTimeDelay']), + self.write_pwm, + args=[self.to_int(rpi_output['gpioPin']), value])) if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'neopixel': gpioPin = rpi_output['gpioPin'] ledCount = rpi_output['neopixelCount'] ledBrightness = rpi_output['neopixelBrightness'] address = rpi_output['microAddress'] - self.queue.append(threading.Timer(self.toFloat(rpi_output['shutdownTimeDelay']), - self.sendNeopixelCommand, + self.queue.append(threading.Timer(self.to_float(rpi_output['shutdownTimeDelay']), + self.send_neopixel_command, args=[gpioPin, ledCount, 0, 0, 0, 0, address])) for task in self.queue: - task.start() + task.start() if event == Events.PRINT_DONE: for notification in self.notifications: @@ -775,29 +803,29 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, datetime.timedelta(seconds=elapsed_time_in_seconds)) msg = "Print job finished: " + file_name + \ "finished printing in " + file_name, elapsed_time - self.sendNotification(msg) + self.send_notification(msg) # ~~ SettingsPlugin mixin def on_settings_save(self, data): self._logger.info("data: %s", data) - outputsBeforeSave = self.getOutputList() + outputsBeforeSave = self.get_output_list() octoprint.plugin.SettingsPlugin.on_settings_save(self, data) self.temperature_reading = self._settings.get(["temperature_reading"]) self.temperature_control = self._settings.get(["temperature_control"]) self.rpi_outputs = self._settings.get(["rpi_outputs"]) self.rpi_inputs = self._settings.get(["rpi_inputs"]) self.notifications = self._settings.get(["notifications"]) - outputsAfterSave = self.getOutputList() + outputsAfterSave = self.get_output_list() commonPins = list(set(outputsBeforeSave) & set(outputsAfterSave)) for pin in (pin for pin in outputsBeforeSave if pin not in commonPins): - self.clearChannel(pin) + self.clear_channel(pin) self.previous_rpi_outputs = commonPins - self.clearGPIO() + self.clear_gpio() if self._settings.get(["debug"]) is True: self._logger.info("temperature_reading: %s", @@ -806,8 +834,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.temperature_control) self._logger.info("rpi_outputs: %s", self.rpi_outputs) self._logger.info("rpi_inputs: %s", self.rpi_inputs) - self.startGPIO() - self.configureGPIO() + self.start_gpio() + self.configure_gpio() def get_settings_defaults(self): return dict( diff --git a/octoprint_enclosure/static/css/bootstrap-colorpicker.css b/octoprint_enclosure/static/css/bootstrap-colorpicker.css old mode 100755 new mode 100644 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/alpha-horizontal.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/alpha-horizontal.png old mode 100755 new mode 100644 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/alpha.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/alpha.png old mode 100755 new mode 100644 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/hue-horizontal.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/hue-horizontal.png old mode 100755 new mode 100644 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/hue.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/hue.png old mode 100755 new mode 100644 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/saturation.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/saturation.png old mode 100755 new mode 100644 diff --git a/octoprint_enclosure/static/js/bootstrap-colorpicker.min.js b/octoprint_enclosure/static/js/bootstrap-colorpicker.min.js old mode 100755 new mode 100644 diff --git a/octoprint_enclosure/static/js/enclosure.js b/octoprint_enclosure/static/js/enclosure.js index 3e28bc1..fa6fd69 100644 --- a/octoprint_enclosure/static/js/enclosure.js +++ b/octoprint_enclosure/static/js/enclosure.js @@ -1,382 +1,347 @@ -$(function() { - function EnclosureViewModel(parameters) { - var self = this; +$(function () { + function EnclosureViewModel(parameters) { + var self = this; - self.pluginName = "enclosure"; + self.pluginName = "enclosure"; - self.global_settings = parameters[0]; - self.connection = parameters[1]; - self.printerStateViewModel = parameters[2]; + self.global_settings = parameters[0]; + self.connection = parameters[1]; + self.printerStateViewModel = parameters[2]; - self.temperature_reading = ko.observableArray(); - self.temperature_control = ko.observableArray(); - self.rpi_outputs = ko.observableArray(); - self.rpi_inputs = ko.observableArray(); - self.filamentSensorGcode = ko.observable(); + self.temperature_reading = ko.observableArray(); + self.temperature_control = ko.observableArray(); + self.rpi_outputs = ko.observableArray(); + self.rpi_inputs = ko.observableArray(); + self.filamentSensorGcode = ko.observable(); - self.enclosureTemp = ko.observable(); - self.enclosureSetTemperature = ko.observable(); - self.enclosureHumidity = ko.observable(); + self.enclosureTemp = ko.observable(); + self.enclosureSetTemperature = ko.observable(); + self.enclosureHumidity = ko.observable(); - self.previousGpioStatus; - self.previousGpioPWMStatus; - self.navbarTemp= ko.observable(); - self.navbarHum= ko.observable(); + self.previousGpioStatus; + self.previousGpioPWMStatus; + self.navbarTemp = ko.observable(); + self.navbarHum = ko.observable(); - self.showTempNavbar= ko.observable(); + self.showTempNavbar = ko.observable(); - self.notificationProvider = ko.observable(); - self.event_name = ko.observable(); - self.apiKEY = ko.observable(); - self.notifications = ko.observable(); + self.notificationProvider = ko.observable(); + self.event_name = ko.observable(); + self.apiKEY = ko.observable(); + self.notifications = ko.observable(); - self.onDataUpdaterPluginMessage = function(plugin, data) { - if (plugin != "enclosure") { - return; + self.onDataUpdaterPluginMessage = function (plugin, data) { + if (plugin != "enclosure") { + return; + } + + if (data.hasOwnProperty("enclosuretemp")) { + self.enclosureTemp(data.enclosuretemp); + + + self.temperature_reading().forEach(function (element) { + if ("useFahrenheit" in element) { + useFahrenheit = element['useFahrenheit']() + + if (useFahrenheit) { + self.navbarTemp(_.sprintf("Enc: %.1f°F", data.enclosuretemp)); + } else { + self.navbarTemp(_.sprintf("Enc: %.1f°C", data.enclosuretemp)); } - - if (data.hasOwnProperty("enclosuretemp")) { - self.enclosureTemp(data.enclosuretemp); - - - self.temperature_reading().forEach(function(element) { - if("useFahrenheit" in element ){ - useFahrenheit = element['useFahrenheit']() - - if(useFahrenheit){ - self.navbarTemp(_.sprintf("Enc: %.1f°F", data.enclosuretemp)); - }else{ - self.navbarTemp(_.sprintf("Enc: %.1f°C", data.enclosuretemp)); - } - } - }); - } - if (data.hasOwnProperty("enclosureHumidity")) { - self.enclosureHumidity(data.enclosureHumidity); - self.navbarHum(_.sprintf("Hum: %.1f%%", data.enclosureHumidity)); - } - - if (data.hasOwnProperty("enclosureSetTemp")){ - if (parseFloat(data.enclosureSetTemp)>0.0){ - $("#enclosureSetTemp").attr("placeholder", data.enclosureSetTemp); - }else{ - $("#enclosureSetTemp").attr("placeholder", "off"); - } - } - - if(!data.rpi_output){ - data.rpi_output = self.previousGpioStatus; - } - - if(!data.rpi_output_pwm){ - data.rpi_output_pwm = self.previousGpioPWMStatus; - } - - if(data.rpi_output){ - data.rpi_output.forEach(function(gpio) { - key = Object.keys(gpio)[0]; - if(gpio[key]){ - $("#btn_off_"+key).removeClass('active'); - $("#btn_on_"+key).addClass('active'); - }else{ - $("#btn_off_"+key).addClass('active'); - $("#btn_on_"+key).removeClass('active'); - } - }); - self.previousGpioStatus = data.rpi_output; - } - - if(data.rpi_output_pwm){ - data.rpi_output_pwm.forEach(function(gpio) { - key = Object.keys(gpio)[0]; - val = gpio[key]; - if (parseFloat(val)!=100){ - $("#dutycycle_"+key).attr("placeholder", val); - }else{ - $("#dutycycle_"+key).attr("placeholder", "off"); - } - }); - self.previousGpioPWMStatus = data.rpi_output_pwm; - } - - if (data.isMsg) { - new PNotify({title:"Enclosure", text:data.msg, type: "error"}); - } - }; - - self.enableBtn = ko.computed(function() { - // return self.connection.loginState.isUser() && self.printerStateViewModel.isOperational(); - return self.connection.loginState.isUser(); + } }); + } + if (data.hasOwnProperty("enclosureHumidity")) { + self.enclosureHumidity(data.enclosureHumidity); + self.navbarHum(_.sprintf("Hum: %.1f%%", data.enclosureHumidity)); + } - self.onBeforeBinding = function () { - self.settings = self.global_settings.settings.plugins.enclosure; - self.temperature_reading(self.settings.temperature_reading()); - // self.temperature_control(self.settings.temperature_control.slice(0)); - self.rpi_outputs(self.settings.rpi_outputs()); - self.rpi_inputs(self.settings.rpi_inputs()); - self.filamentSensorGcode(self.settings.filamentSensorGcode()); - - self.notificationProvider(self.settings.notificationProvider()); - self.showTempNavbar(self.settings.showTempNavbar()); - - self.event_name(self.settings.event_name()); - self.apiKEY(self.settings.apiKEY()); - self.notifications(self.settings.notifications()); - }; - - self.onStartupComplete = function () { - self.getUpdateBtnStatus(); - }; - - self.onDataUpdaterReconnect = function () { - self.getUpdateBtnStatus(); - }; - - self.onSettingsShown = function(){ - self.fixUI(); - }; - - self.showColorPicker = function(){ - $('[name=colorpicker]').colorpicker({format: 'rgb'}); + if (data.hasOwnProperty("enclosureSetTemp")) { + if (parseFloat(data.enclosureSetTemp) > 0.0) { + $("#enclosureSetTemp").attr("placeholder", data.enclosureSetTemp); + } else { + $("#enclosureSetTemp").attr("placeholder", "off"); } + } - self.onSettingsHidden = function(){ - self.getUpdateBtnStatus(); - }; + if (!data.rpi_output) { + data.rpi_output = self.previousGpioStatus; + } - self.getRegularOutputs = function(){ - return self.global_settings.settings.plugins.enclosure.rpi_outputs().filter(function(rpi_outputs) { - return rpi_outputs.outputType == 'regular'; - }); - }; - self.setTemperature = function(){ - if(self.isNumeric($("#enclosureSetTemp").val())){ - $.ajax({ - url: self.buildPluginUrl("/setEnclosureTemperature"), - type: "GET", - dataType: "json", - data: {"enclosureSetTemp": Number($("#enclosureSetTemp").val())}, - success: function(data) { - $("#enclosureSetTemp").val(''); - $("#enclosureSetTemp").attr("placeholder", self.getStatusHeater(data.enclosureSetTemperature,data.enclosureCurrentTemperature)); - } - }); - }else{ - alert("Temperature is not a number"); - } - }; + if (!data.rpi_output_pwm) { + data.rpi_output_pwm = self.previousGpioPWMStatus; + } - self.addRpiOutput = function(){ - self.global_settings.settings.plugins.enclosure.rpi_outputs.push({label: ko.observable("Ouput "+ - (self.global_settings.settings.plugins.enclosure.rpi_outputs().length+1)) , - gpioPin:ko.observable(0),activeLow: true, - autoStartup:ko.observable(false), startupTimeDelay:0, autoShutdown:ko.observable(false),shutdownTimeDelay:0, - outputType:ko.observable('regular'),frequency:50,dutycycle:0,color:"rgb(255,0,0)",neopixelCount:0,neopixelBrightness:255,microAddress:0}); - }; - - self.removeRpiOutput = function(definition) { - self.global_settings.settings.plugins.enclosure.rpi_outputs.remove(definition); - }; - - self.addRpiInput = function(){ - self.global_settings.settings.plugins.enclosure.rpi_inputs.push({label:ko.observable( "Input "+ - (self.global_settings.settings.plugins.enclosure.rpi_inputs().length+1)), gpioPin: 0,inputPull: "inputPullUp", - eventType:ko.observable("temperature"),setTemp:100,controlledIO:ko.observable(""),setControlledIO:"low", - edge:"fall",printerAction:"filament"}); - }; - - self.removeRpiInput = function(definition) { - self.global_settings.settings.plugins.enclosure.rpi_inputs.remove(definition); - }; - - self.turnOffHeater = function(){ - $.ajax({ - url: self.buildPluginUrl("/setEnclosureTemperature"), - type: "GET", - dataType: "json", - data: {"enclosureSetTemp":0}, - success: function(data) { - $("#enclosureSetTemp").val(''); - $("#enclosureSetTemp").attr("placeholder", self.getStatusHeater(data.enclosureSetTemperature,data.enclosureCurrentTemperature)); - } - }); - }; - - self.clearGPIOMode = function(){ - $.ajax({ - url: self.buildPluginUrl("/clearGPIOMode"), - type: "GET", - dataType: "json", - success: function(data) { - new PNotify({title:"Enclosure", text:"GPIO Mode cleared successfully", type: "success"}); - } - }); - }; - - self.getUpdateBtnStatus = function(){ - - $.ajax({ - url: self.buildPluginUrl("/getUpdateBtnStatus"), - type: "GET" - }); - }; - - self.requestEnclosureTemperature = function(){ - return $.ajax({ - type: "GET", - url: self.buildPluginUrl("/getEnclosureTemperature"), - async: false - }).responseText; - }; - - self.requestEnclosureSetTemperature = function(){ - return $.ajax({ - type: "GET", - url: self.buildPluginUrl("/getEnclosureSetTemperature"), - async: false - }).responseText; - }; - - self.getStatusHeater = function(setTemp,currentTemp){ - if (parseFloat(setTemp)>0.0){ - return cleanTemperature(setTemp); - } - return "off"; - }; - - self.handleIO = function(data, event){ - $.ajax({ - type: "GET", - dataType: "json", - data: {"io": data[0], "status": data[1]}, - url: self.buildPluginUrl("/setIO"), - async: false - }); - }; - - self.handlePWM = function(data, event){ - io = parseInt(data[0]); - pwmVal = parseInt($("#dutycycle_"+io).val()); - if(pwmVal<0 || pwmVal>100 || isNaN(pwmVal)){ - $("#dutycycle_"+io).val('') - new PNotify({title:"Enclosure", text:"Duty Cycle value needs to be between 0 and 100!", type: "error"}); - }else{ - // console.log(pwmVal); - $("#dutycycle_"+io).val('') - $("#dutycycle_"+io).attr("placeholder", pwmVal); - $.ajax({ - type: "GET", - dataType: "json", - data: {"io": io, "pwmVal": pwmVal}, - url: self.buildPluginUrl("/setPWM"), - }); - } - }; - - self.handleNeopixel = function(data, event){ - io = parseInt(data[0]); - tempStr = ($("#color_"+io).val()).replace("rgb(", ""); - - r = parseInt(tempStr.substring(0, tempStr.indexOf(","))); - tempStr = tempStr.slice(tempStr.indexOf(",")+1); - g = parseInt(tempStr.substring(0, tempStr.indexOf(","))); - tempStr = tempStr.slice(tempStr.indexOf(",")+1); - b = parseInt(tempStr.substring(0, tempStr.indexOf(")"))); - - if(r<0 || r>255 || g<0 || g>255 || b<0 || b >255 || isNaN(r) || isNaN(g) || isNaN(b)){ - new PNotify({title:"Enclosure", text:"Color needs to follow the format rgb(value_red,value_green,value_blue)!", type: "error"}); - }else { - $.ajax({ - type: "GET", - dataType: "json", - data: {"io": io, "red": r,"green": g,"blue": b}, - url: self.buildPluginUrl("/setNeopixel"), - }); - } - }; - - self.fixUI = function(){ - if($('#enableTemperatureReading').is(':checked')){ - $('#enableHeater').prop('disabled', false); - $('#temperature_reading_content').show("blind"); - // $('#temperature_control_content').show("blind"); - }else{ - $('#enableHeater').prop('disabled', true); - $('#enableHeater').prop('checked', false); - $('#temperature_reading_content').hide("blind"); - // $('#temperature_control_content').hide("blind"); + if (data.rpi_output) { + data.rpi_output.forEach(function (gpio) { + key = Object.keys(gpio)[0]; + if (gpio[key]) { + $("#btn_off_" + key).removeClass('active'); + $("#btn_on_" + key).addClass('active'); + } else { + $("#btn_off_" + key).addClass('active'); + $("#btn_on_" + key).removeClass('active'); } + }); + self.previousGpioStatus = data.rpi_output; + } - if($('#enableHeater').is(':checked')){ - $('#temperature_control_content').show("blind"); - }else{ - $('#temperature_control_content').hide("blind"); + if (data.rpi_output_pwm) { + data.rpi_output_pwm.forEach(function (gpio) { + key = Object.keys(gpio)[0]; + val = gpio[key]; + if (parseFloat(val) != 100) { + $("#dutycycle_" + key).attr("placeholder", val); + } else { + $("#dutycycle_" + key).attr("placeholder", "off"); } + }); + self.previousGpioPWMStatus = data.rpi_output_pwm; + } - }; + if (data.isMsg) { + new PNotify({ title: "Enclosure", text: data.msg, type: "error" }); + } + }; - // self.fixEventTypeUI = function(){ - // $('[name^="eventType_"]').each(function() { - // if($( this ).is(':checked')){ - // selectedType = $( this ).val(); - // idNumber = $( this ).attr('name').replace("eventType_", ""); - // self.eventTypeUI(idNumber,selectedType); - // } - // }); - // }; - // - // self.eventTypeUI = function(idNumber,selectedType){ - // - // $('#input_io_'+idNumber).hide(); - // $('#temp_controlled_'+idNumber).hide(); - // $('#filament_controlled_'+idNumber).hide(); - // $('#gpio_controlled_'+idNumber).hide(); - // - // if(selectedType=='temperature'){ - // $('#temp_controlled_'+idNumber).show(); - // console.log("temperature"); - // }else if(selectedType=='filament'){ - // $('#filament_controlled_'+idNumber).show(); - // $('#input_io_'+idNumber).show(); - // console.log("filament"); - // }else if(selectedType=='gpio'){ - // $('#gpio_controlled_'+idNumber).show(); - // $('#input_io_'+idNumber).show(); - // console.log("gpio"); - // } - // }; + self.enableBtn = ko.computed(function () { + // return self.connection.loginState.isUser() && self.printerStateViewModel.isOperational(); + return self.connection.loginState.isUser(); + }); - // - // self.fixAutoStartupUI = function(idNumber){ - // if($('#autoStartup_'+idNumber).is(':checked')){ - // $('#autoStartupField_'+idNumber).show("blind"); - // }else{ - // $('#autoStartupField_'+idNumber).hide("blind"); - // } - // }; - // - // self.fixAutoShutdownUI = function(idNumber){ - // if($('#autoShutdown_'+idNumber).is(':checked')){ - // $('#autoShutdownField_'+idNumber).show("blind"); - // }else{ - // $('#autoShutdownField_'+idNumber).hide("blind"); - // } - // }; - self.isNumeric = function(n){ - return !isNaN(parseFloat(n)) && isFinite(n); - }; - - self.buildPluginUrl = function(path) { - return window.PLUGIN_BASEURL + self.pluginName + path; - }; + self.getCleanTemperature = function (temp) { + if (temp === undefined || !_.isNumber(temp)) return "-"; + if (temp < 10) return gettext("off"); + return temp; } - OCTOPRINT_VIEWMODELS.push([ - EnclosureViewModel, - ["settingsViewModel","connectionViewModel","printerStateViewModel"], - ["#tab_plugin_enclosure","#settings_plugin_enclosure","#navbar_plugin_enclosure"] - ]); + + self.onBeforeBinding = function () { + self.settings = self.global_settings.settings.plugins.enclosure; + self.temperature_reading(self.settings.temperature_reading()); + // self.temperature_control(self.settings.temperature_control.slice(0)); + self.rpi_outputs(self.settings.rpi_outputs()); + self.rpi_inputs(self.settings.rpi_inputs()); + self.filamentSensorGcode(self.settings.filamentSensorGcode()); + + self.notificationProvider(self.settings.notificationProvider()); + self.showTempNavbar(self.settings.showTempNavbar()); + + self.event_name(self.settings.event_name()); + self.apiKEY(self.settings.apiKEY()); + self.notifications(self.settings.notifications()); + }; + + self.onStartupComplete = function () { + self.getUpdateBtnStatus(); + }; + + self.onDataUpdaterReconnect = function () { + self.getUpdateBtnStatus(); + }; + + self.onSettingsShown = function () { + self.fixUI(); + }; + + self.showColorPicker = function () { + $('[name=colorpicker]').colorpicker({ format: 'rgb' }); + } + + self.onSettingsHidden = function () { + self.getUpdateBtnStatus(); + }; + + self.getRegularOutputs = function () { + return self.global_settings.settings.plugins.enclosure.rpi_outputs().filter(function (rpi_outputs) { + return rpi_outputs.outputType == 'regular'; + }); + }; + self.setTemperature = function () { + if (self.isNumeric($("#enclosureSetTemp").val())) { + $.ajax({ + url: self.buildPluginUrl("/setEnclosureTemperature"), + type: "GET", + dataType: "json", + data: { "enclosureSetTemp": Number($("#enclosureSetTemp").val()) }, + success: function (data) { + $("#enclosureSetTemp").val(''); + $("#enclosureSetTemp").attr("placeholder", self.getStatusHeater(data.enclosureSetTemperature, data.enclosureCurrentTemperature)); + } + }); + } else { + alert("Temperature is not a number"); + } + }; + + self.addRpiOutput = function () { + self.global_settings.settings.plugins.enclosure.rpi_outputs.push({ + label: ko.observable("Ouput " + + (self.global_settings.settings.plugins.enclosure.rpi_outputs().length + 1)), + gpioPin: ko.observable(0), activeLow: true, + autoStartup: ko.observable(false), startupTimeDelay: 0, autoShutdown: ko.observable(false), shutdownTimeDelay: 0, + outputType: ko.observable('regular'), frequency: 50, dutycycle: 0, color: "rgb(255,0,0)", + neopixelCount: 0, neopixelBrightness: 255, microAddress: 0 + }); + }; + + self.removeRpiOutput = function (definition) { + self.global_settings.settings.plugins.enclosure.rpi_outputs.remove(definition); + }; + + self.addRpiInput = function () { + self.global_settings.settings.plugins.enclosure.rpi_inputs.push({ + label: ko.observable("Input " + + (self.global_settings.settings.plugins.enclosure.rpi_inputs().length + 1)), gpioPin: 0, inputPull: "inputPullUp", + eventType: ko.observable("temperature"), setTemp: 100, controlledIO: ko.observable(""), setControlledIO: "low", + edge: "fall", printerAction: "filament" + }); + }; + + self.removeRpiInput = function (definition) { + self.global_settings.settings.plugins.enclosure.rpi_inputs.remove(definition); + }; + + self.turnOffHeater = function () { + $.ajax({ + url: self.buildPluginUrl("/setEnclosureTemperature"), + type: "GET", + dataType: "json", + data: { "enclosureSetTemp": 0 }, + success: function (data) { + $("#enclosureSetTemp").val(''); + $("#enclosureSetTemp").attr("placeholder", self.getStatusHeater(data.enclosureSetTemperature, data.enclosureCurrentTemperature)); + } + }); + }; + + self.clearGPIOMode = function () { + $.ajax({ + url: self.buildPluginUrl("/clearGPIOMode"), + type: "GET", + dataType: "json", + success: function (data) { + new PNotify({ title: "Enclosure", text: "GPIO Mode cleared successfully", type: "success" }); + } + }); + }; + + self.getUpdateBtnStatus = function () { + + $.ajax({ + url: self.buildPluginUrl("/getUpdateBtnStatus"), + type: "GET" + }); + }; + + self.requestEnclosureTemperature = function () { + return $.ajax({ + type: "GET", + url: self.buildPluginUrl("/getEnclosureTemperature"), + async: false + }).responseText; + }; + + self.requestEnclosureSetTemperature = function () { + return $.ajax({ + type: "GET", + url: self.buildPluginUrl("/getEnclosureSetTemperature"), + async: false + }).responseText; + }; + + self.getStatusHeater = function (setTemp, currentTemp) { + if (parseFloat(setTemp) > 0.0) { + return self.getCleanTemperature(setTemp); + } + return "off"; + }; + + self.handleIO = function (data, event) { + $.ajax({ + type: "GET", + dataType: "json", + data: { "io": data[0], "status": data[1] }, + url: self.buildPluginUrl("/setIO"), + async: false + }); + }; + + self.handlePWM = function (data, event) { + io = parseInt(data[0]); + pwmVal = parseInt($("#dutycycle_" + io).val()); + if (pwmVal < 0 || pwmVal > 100 || isNaN(pwmVal)) { + $("#dutycycle_" + io).val('') + new PNotify({ title: "Enclosure", text: "Duty Cycle value needs to be between 0 and 100!", type: "error" }); + } else { + // console.log(pwmVal); + $("#dutycycle_" + io).val('') + $("#dutycycle_" + io).attr("placeholder", pwmVal); + $.ajax({ + type: "GET", + dataType: "json", + data: { "io": io, "pwmVal": pwmVal }, + url: self.buildPluginUrl("/setPWM"), + }); + } + }; + + self.handleNeopixel = function (data, event) { + io = parseInt(data[0]); + tempStr = ($("#color_" + io).val()).replace("rgb(", ""); + + r = parseInt(tempStr.substring(0, tempStr.indexOf(","))); + tempStr = tempStr.slice(tempStr.indexOf(",") + 1); + g = parseInt(tempStr.substring(0, tempStr.indexOf(","))); + tempStr = tempStr.slice(tempStr.indexOf(",") + 1); + b = parseInt(tempStr.substring(0, tempStr.indexOf(")"))); + + if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || isNaN(r) || isNaN(g) || isNaN(b)) { + new PNotify({ title: "Enclosure", text: "Color needs to follow the format rgb(value_red,value_green,value_blue)!", type: "error" }); + } else { + $.ajax({ + type: "GET", + dataType: "json", + data: { "io": io, "red": r, "green": g, "blue": b }, + url: self.buildPluginUrl("/setNeopixel"), + }); + } + }; + + self.fixUI = function () { + if ($('#enableTemperatureReading').is(':checked')) { + $('#enableHeater').prop('disabled', false); + $('#temperature_reading_content').show("blind"); + // $('#temperature_control_content').show("blind"); + } else { + $('#enableHeater').prop('disabled', true); + $('#enableHeater').prop('checked', false); + $('#temperature_reading_content').hide("blind"); + // $('#temperature_control_content').hide("blind"); + } + + if ($('#enableHeater').is(':checked')) { + $('#temperature_control_content').show("blind"); + } else { + $('#temperature_control_content').hide("blind"); + } + + }; + + self.isNumeric = function (n) { + return !isNaN(parseFloat(n)) && isFinite(n); + }; + + self.buildPluginUrl = function (path) { + return window.PLUGIN_BASEURL + self.pluginName + path; + }; + } + + OCTOPRINT_VIEWMODELS.push([ + EnclosureViewModel, + ["settingsViewModel", "connectionViewModel", "printerStateViewModel"], + ["#tab_plugin_enclosure", "#settings_plugin_enclosure", "#navbar_plugin_enclosure"] + ]); }); diff --git a/octoprint_enclosure/templates/enclosure_tab.jinja2 b/octoprint_enclosure/templates/enclosure_tab.jinja2 index 57b50e6..9c4553e 100644 --- a/octoprint_enclosure/templates/enclosure_tab.jinja2 +++ b/octoprint_enclosure/templates/enclosure_tab.jinja2 @@ -18,7 +18,7 @@
+ data-bind="attr: {placeholder:getCleanTemperature($root.requestEnclosureSetTemperature())}"> °F °C
-- 2.39.5 From 7d47d0fad8cc8714a8d9d4e76d74884879cd747a Mon Sep 17 00:00:00 2001 From: Vitor de Miranda Henrique Date: Sun, 21 Jan 2018 21:00:18 -0600 Subject: [PATCH 04/42] fixing issue 68 --- octoprint_enclosure/__init__.py | 2 + .../static/css/bootstrap-colorpicker.css | 0 .../alpha-horizontal.png | Bin .../img/bootstrap-colorpicker/alpha.png | Bin .../bootstrap-colorpicker/hue-horizontal.png | Bin .../static/img/bootstrap-colorpicker/hue.png | Bin .../img/bootstrap-colorpicker/saturation.png | Bin .../static/js/bootstrap-colorpicker.min.js | 0 octoprint_enclosure/static/js/enclosure.js | 16 +- .../templates/enclosure_settings.jinja2 | 759 +++++++++--------- .../templates/enclosure_tab.jinja2 | 2 +- 11 files changed, 407 insertions(+), 372 deletions(-) mode change 100644 => 100755 octoprint_enclosure/static/css/bootstrap-colorpicker.css mode change 100644 => 100755 octoprint_enclosure/static/img/bootstrap-colorpicker/alpha-horizontal.png mode change 100644 => 100755 octoprint_enclosure/static/img/bootstrap-colorpicker/alpha.png mode change 100644 => 100755 octoprint_enclosure/static/img/bootstrap-colorpicker/hue-horizontal.png mode change 100644 => 100755 octoprint_enclosure/static/img/bootstrap-colorpicker/hue.png mode change 100644 => 100755 octoprint_enclosure/static/img/bootstrap-colorpicker/saturation.png mode change 100644 => 100755 octoprint_enclosure/static/js/bootstrap-colorpicker.min.js diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index dc89f00..e1bb2d7 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -23,6 +23,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, octoprint.plugin.BlueprintPlugin, octoprint.plugin.EventHandlerPlugin): + + previous_temp_control_status = False current_temp_control_status = False enclosure_set_temperature = 0.0 diff --git a/octoprint_enclosure/static/css/bootstrap-colorpicker.css b/octoprint_enclosure/static/css/bootstrap-colorpicker.css old mode 100644 new mode 100755 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/alpha-horizontal.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/alpha-horizontal.png old mode 100644 new mode 100755 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/alpha.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/alpha.png old mode 100644 new mode 100755 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/hue-horizontal.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/hue-horizontal.png old mode 100644 new mode 100755 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/hue.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/hue.png old mode 100644 new mode 100755 diff --git a/octoprint_enclosure/static/img/bootstrap-colorpicker/saturation.png b/octoprint_enclosure/static/img/bootstrap-colorpicker/saturation.png old mode 100644 new mode 100755 diff --git a/octoprint_enclosure/static/js/bootstrap-colorpicker.min.js b/octoprint_enclosure/static/js/bootstrap-colorpicker.min.js old mode 100644 new mode 100755 diff --git a/octoprint_enclosure/static/js/enclosure.js b/octoprint_enclosure/static/js/enclosure.js index fa6fd69..199e4f7 100644 --- a/octoprint_enclosure/static/js/enclosure.js +++ b/octoprint_enclosure/static/js/enclosure.js @@ -112,8 +112,8 @@ $(function () { self.getCleanTemperature = function (temp) { - if (temp === undefined || !_.isNumber(temp)) return "-"; - if (temp < 10) return gettext("off"); + if (temp === undefined || isNaN(parseFloat(temp))) return "-"; + if (temp < 10) return String("off"); return temp; } @@ -168,7 +168,8 @@ $(function () { data: { "enclosureSetTemp": Number($("#enclosureSetTemp").val()) }, success: function (data) { $("#enclosureSetTemp").val(''); - $("#enclosureSetTemp").attr("placeholder", self.getStatusHeater(data.enclosureSetTemperature, data.enclosureCurrentTemperature)); + cleanTemperature = self.getCleanTemperature(data.enclosureSetTemperature); + $("#enclosureSetTemp").attr("placeholder", cleanTemperature); } }); } else { @@ -212,7 +213,7 @@ $(function () { data: { "enclosureSetTemp": 0 }, success: function (data) { $("#enclosureSetTemp").val(''); - $("#enclosureSetTemp").attr("placeholder", self.getStatusHeater(data.enclosureSetTemperature, data.enclosureCurrentTemperature)); + $("#enclosureSetTemp").attr("placeholder", self.getCleanTemperature(data.enclosureSetTemperature)); } }); }; @@ -252,13 +253,6 @@ $(function () { }).responseText; }; - self.getStatusHeater = function (setTemp, currentTemp) { - if (parseFloat(setTemp) > 0.0) { - return self.getCleanTemperature(setTemp); - } - return "off"; - }; - self.handleIO = function (data, event) { $.ajax({ type: "GET", diff --git a/octoprint_enclosure/templates/enclosure_settings.jinja2 b/octoprint_enclosure/templates/enclosure_settings.jinja2 index 6b6bdb5..d9247aa 100644 --- a/octoprint_enclosure/templates/enclosure_settings.jinja2 +++ b/octoprint_enclosure/templates/enclosure_settings.jinja2 @@ -3,11 +3,10 @@
-
+
@@ -21,8 +20,10 @@ - Attention You need to install and configure the necessary - libraries for the temperature sensor, check the documentation on github page + + Attention You need to install and configure the necessary libraries for the temperature sensor, check + the documentation on + github page
@@ -39,14 +40,16 @@
- GPIO pin for temperature sensor need to connect the sensor to I2C. SCL Clock to GPIO 3 (SCL) and SDA Data to GPIO 2 (SDA) + GPIO pin for temperature sensor need to connect the sensor to I2C. SCL Clock to GPIO 3 (SCL) and SDA Data to GPIO + 2 (SDA)
- Sensor address in HEX value, you can find it by runing i2cdetect -y 1 on your Raspberry Pi + Sensor address in HEX value, you can find it by runing + i2cdetect -y 1 on your Raspberry Pi
@@ -61,24 +64,25 @@
Choose if you want to work with Celsius or Fahrenheit
+

{{ _('Temperature Control') }}

-
+
@@ -89,7 +93,7 @@
Active low means that the heater will turn on when receive a low signal (ground) from Raspbery PI
@@ -97,16 +101,18 @@
- +
- +
Choose if you want to automatically startup temperature control when the print starts
@@ -129,152 +135,178 @@ -
- -
- - Name displayed on Enclosure Tab -
-
-
- -
- - - GPIO number that will be controlled. - - - Attention Neopixel requires a microcontroler (ex: arduino) connected to I2C bus. - This is the pin on the microcontroler that is connected to the Neopixel. - -
-
-
-
- - Choose if GPIO should turn on automatomatically when print starts -
-
- -
- +
- - Time delay to turn on GPIO when print starts + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+ + Name displayed on Enclosure Tab +
+
+
+ +
+ + + GPIO number that will be controlled. + + + + Attention Neopixel requires a microcontroler (ex: arduino) connected to I2C bus. This is the pin on the + microcontroler that is connected to the Neopixel. + +
+
+
+ +
+ + When the event happen, you want control which IO? +
+
+
+
+ + Choose if GPIO should turn on automatomatically when print starts +
+
+ +
+
+ +
+ + Time delay to turn on GPIO when print starts +
+
+
+ +
+
+ + Choose if GPIO should turn off automatomatically when print finishes +
+
+ +
+
+ +
+ + Time delay to turn off GPIO when print finishes +
+
+
+ + +
+
+ + Active low means that the GPIO will turn on when receive a low signal (ground) from Raspbery PI +
+
+ + +
+ +
+ + Value is in Hz +
+
+
+ +
+ + Value is in percentage, between 0 and 100 +
+
+ + +
+ +
+ + Microcontroller address in HEX value, you can find it by runing + i2cdetect -y 1 on your Raspberry Pi +
+
+ + +
+ +
+ + Number of led's on strip +
+
+
+ +
+ + Value between 0 and 255 +
+
+
+ +
+ + Value needs to follow the format rgb(value_red,value_green,value_blue) where values should be between 0 and 255 +
+
+ +
+ + + +
+
+
+
-
-
- - Choose if GPIO should turn off automatomatically when print finishes -
+
- -
-
- -
- - Time delay to turn off GPIO when print finishes -
-
-
- -
- -
- -
-
- -
-
- -
-
- -
-
- - Active low means that the GPIO will turn on when receive a low signal (ground) from Raspbery PI -
-
- - -
- -
- - Value is in Hz -
-
-
- -
- - Value is in percentage, between 0 and 100 -
-
- - -
- -
- - Microcontroller address in HEX value, you can find it by runing i2cdetect -y 1 on your Raspberry Pi -
-
-
- -
- - Number of led's on strip -
-
-
- -
- - Value between 0 and 255 -
-
-
- -
- - Value needs to follow the format rgb(value_red,value_green,value_blue) where values should be between - 0 and 255 -
-
- -
- -
-
-
-
-
-
-
-
- -

{{ _('Raspberry Pi Inputs') }}

@@ -290,49 +322,54 @@
- {{ _('Temperature') }} + {{ _('Temperature') }}
-
- {{ _('GPIO Control') }} + {{ _('Printer') }} +
+
+ {{ _('GPIO Control') }}
- Info: Events will run actions when a certain temperature of the sensor is hit. - You can control a OUTPUT pin and set that to a LOW or HIGH value when that happens. - You can use this as a safety measure and trigger alarm lights for example. Warning - You should always have proper smoke detector on your house. DO NOT use this as your only safety device. + + Info: Events will run actions when a certain temperature of the sensor is hit. You can control a OUTPUT + pin and set that to a LOW or HIGH value when that happens. You can use this as a safety measure and trigger alarm + lights for example. + Warning + You should always have proper smoke detector on your house. DO NOT use this as your only safety device. - Info: Events will run PRINTER actions when a condition is met, that can be a filament sensor, button, etc. - Actions can be Pause \ Resume \ Cancel a printer job, change the filament or disable Temperature Control. You can use the "change filament" action and set up the input - GPIO acording to your sensor, for example, if your filament sensor conects to ground when detects the end of the filament, - you should choose PULL UP resistors and detect the event on the falling edge. + + Info: Events will run PRINTER actions when a condition is met, that can be a filament sensor, button, etc. + Actions can be Pause \ Resume \ Cancel a printer job, change the filament or disable Temperature Control. You can + use the "change filament" action and set up the input GPIO acording to your sensor, for example, if your filament + sensor conects to ground when detects the end of the filament, you should choose PULL UP resistors and detect the + event on the falling edge. - Info: Events will control GPIO outputs when a condition is met, for example detect a press of a button. - You can use this to control any previous configured OUTPUTS, basically beeing able to control your lights / fan / pritner - using mechanical buttons buttons instead of the octoprint interface. You can only control REGULAR outputs. - - + + Info: Events will control GPIO outputs when a condition is met, for example detect a press of a button. + You can use this to control any previous configured OUTPUTS, basically beeing able to control your lights / fan + / pritner using mechanical buttons buttons instead of the octoprint interface. You can only control REGULAR outputs. + + +
-
- -
-
- -
- - Input GPIO that will detect the event that should trigger the action. For example if you have a filament - sensor you put the GPIO pin that the sensor is connected. This can also be a press of a button or any other signal that you want to detect. - You can not use GPIO 4 here if you are using temeprature sensor DS18B20 + +
+
+ +
+ + Input GPIO that will detect the event that should trigger the action. For example if you have a filament sensor + you put the GPIO pin that the sensor is connected. This can also be a press of a button or any other signal that + you want to detect. You can not use GPIO 4 here if you are using temeprature sensor DS18B20
@@ -342,60 +379,60 @@ - Choose what type of pull resistors that you want on the output. If you signal is active low, - that means it should run the action when receive a low signal (ground), you should choose PULL UP resistors. -
+ Choose what type of pull resistors that you want on the output. If you signal is active low, that means it should + run the action when receive a low signal (ground), you should choose PULL UP resistors.
- - -
-
- -
- - Do you want thrigger the event on the rise or falling edge? If you signal is active low, - that means it should run the action when receive a low signal (ground), you should choose FALLING EDGE. -
-
-
- -
- + + + + Do you want thrigger the event on the rise or falling edge? If you signal is active low, that means it should run + the action when receive a low signal (ground), you should choose FALLING EDGE. +
+
+
+ +
+ - When the event happen, you want control which IO? -
-
-
- -
- - When the event happen, you want to turn the controlled IO HIGH or LOW? -
+ + When the event happen, you want control which IO?
- - -
-
- -
- - Set temperature that will trigger the event -
+
+ +
+ + When the event happen, you want to turn the controlled IO HIGH or LOW?
-
- -
- + Set temperature that will trigger the event +
+
+
+ +
+ When the event happen, you want control which IO? @@ -422,140 +459,142 @@ - Do you want thrigger the event on the rise or falling edge? If you signal is active low, - that means it should run the action when receive a low signal (ground), you should choose FALLING EDGE. -
-
-
-
- -
- - You can use filament change on your filament detectors and add buttons to resume and pause the print job. -
-
- - -
- -
-
-
-
+ Do you want thrigger the event on the rise or falling edge? If you signal is active low, that means it should run + the action when receive a low signal (ground), you should choose FALLING EDGE.
- + +
+ + You can use filament change on your filament detectors and add buttons to resume and pause the print job. +
+ + +
+ + + +
+
+
+
+
+
+
+
+ +
+ + + + Advanced options + +
+
+
+
+ + Log additional information on octoprint log to help trouble shoot the plugin +
+
+
+
+ + Display enclosure temperature and humidity on navbar +
+
+
+
+ + Use BOARD pin numbers instead of BCM pin numbers +
+
+
+
+ + This will clear any GPIO configuration that might exist on your system, use with caution, it might break other plugins + that use GPIO +
+
+ +
+ + Time that filament sensor will be inactive after sensing end of filament. This is to avoid sending multiple M600 commands + to the printer. +
+
+ +
+ + GCODE that will be sent to the printer to pause and allow filament to be changed. You should add + ; on the end of every line sent to the printer +
+
+
+ +
+ +
+
+ +
+ +
+ + Event name that was configured on the maker chanel of IFTTT, don't use space between the words +
+
+
+ +
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
- - - Advanced options - -
-
-
-
- - Log additional information on octoprint log to help trouble shoot the plugin -
-
-
-
- - Display enclosure temperature and humidity on navbar -
-
-
-
- - Use BOARD pin numbers instead of BCM pin numbers -
-
-
-
- - This will clear any GPIO configuration that might exist on your system, use with caution, - it might break other plugins that use GPIO -
-
- -
- - Time that filament sensor will be inactive after sensing end of filament. This is to avoid sending multiple M600 - commands to the printer. -
-
- -
- - GCODE that will be sent to the printer to pause and allow filament to be changed. - You should add ; on the end of every line sent to the printer -
-
-
- -
- -
-
- -
- -
- - Event name that was configured on the maker chanel of IFTTT, don't use space between the words -
-
-
- -
- -
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
+
\ No newline at end of file diff --git a/octoprint_enclosure/templates/enclosure_tab.jinja2 b/octoprint_enclosure/templates/enclosure_tab.jinja2 index 9c4553e..47ae6b7 100644 --- a/octoprint_enclosure/templates/enclosure_tab.jinja2 +++ b/octoprint_enclosure/templates/enclosure_tab.jinja2 @@ -18,7 +18,7 @@
+ data-bind="attr: {placeholder:$root.getCleanTemperature($root.requestEnclosureSetTemperature())}"> °F °C
-- 2.39.5 From a9edbf2c88ef989fe1814e61a9824c9594ae8010 Mon Sep 17 00:00:00 2001 From: Vitor de Miranda Henrique Date: Sun, 21 Jan 2018 22:45:37 -0600 Subject: [PATCH 05/42] Delete code.code-workspace this file was supposed to be on gitignore.... --- code.code-workspace | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 code.code-workspace diff --git a/code.code-workspace b/code.code-workspace deleted file mode 100644 index 616c67c..0000000 --- a/code.code-workspace +++ /dev/null @@ -1,12 +0,0 @@ -{ - "folders": [ - { - "path": "." - } - ], - "settings": { - "terminal.integrated.env.osx": { - "PATH": "/Users/vitormhenrique/.platformio/penv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin" - } - } -} \ No newline at end of file -- 2.39.5 From 0a4524cd722949726989b898307ba583c4301c85 Mon Sep 17 00:00:00 2001 From: de Miranda Henrique Date: Thu, 25 Jan 2018 12:43:28 -0600 Subject: [PATCH 06/42] Rebuilding settings --- octoprint_enclosure/__init__.py | 16 +- octoprint_enclosure/static/js/enclosure.js | 5 +- .../templates/enclosure_settings.jinja2 | 189 +++++++++++------- 3 files changed, 124 insertions(+), 86 deletions(-) diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index e1bb2d7..c995034 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -253,7 +253,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for rpi_input in self.rpi_inputs: if self.to_float(rpi_input['setTemp']) == 0: continue - if rpi_input['eventType'] == 'temperature' and (self.to_float(rpi_input['setTemp']) < self.to_float(self.enclosure_current_temperature)): + if rpi_input['actionType'] == 'temperature' and (self.to_float(rpi_input['setTemp']) < self.to_float(self.enclosure_current_temperature)): for rpi_output in self.rpi_outputs: if self.to_int(rpi_input['controlledIO']) == self.to_int(rpi_output['gpioPin']): val = GPIO.LOW if rpi_output['activeLow'] else GPIO.HIGH @@ -472,11 +472,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, 'inputPull'] == 'inputPullUp' else GPIO.PUD_DOWN GPIO.setup(self.to_int( rpi_input['gpioPin']), GPIO.IN, pullResistor) - if rpi_input['eventType'] == 'gpio' and self.to_int(rpi_input['gpioPin']) != 0: + if rpi_input['actionType'] == 'gpio' and self.to_int(rpi_input['gpioPin']) != 0: edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING GPIO.add_event_detect(self.to_int( rpi_input['gpioPin']), edge, callback=self.handle_gpio_Control, bouncetime=200) - if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] != 'filament' and self.to_int(rpi_input['gpioPin']) != 0: + if rpi_input['actionType'] == 'printer' and rpi_input['printerAction'] != 'filament' and self.to_int(rpi_input['gpioPin']) != 0: edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING GPIO.add_event_detect(self.to_int( rpi_input['gpioPin']), edge, callback=self.handle_printer_action, bouncetime=200) @@ -490,7 +490,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_filamment_detection(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament' \ + if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['actionType'] == 'printer' and rpi_input['printerAction'] == 'filament' \ and ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): if time.time() - self.last_filament_end_detected > self._settings.get_int(["filamentSensorTimeout"]): self._logger.info("Detected end of filament.") @@ -520,7 +520,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.stop_filament_detection() try: for rpi_input in self.rpi_inputs: - if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament' and self.to_int(rpi_input['gpioPin']) != 0: + if rpi_input['actionType'] == 'printer' and rpi_input['printerAction'] == 'filament' and self.to_int(rpi_input['gpioPin']) != 0: edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING if GPIO.input(self.to_int(rpi_input['gpioPin'])) == (edge == GPIO.RISING): self._printer.pause_print() @@ -538,7 +538,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def stop_filament_detection(self): try: for rpi_input in self.rpi_inputs: - if rpi_input['eventType'] == 'printer' and rpi_input['printerAction'] == 'filament': + if rpi_input['actionType'] == 'printer' and rpi_input['printerAction'] == 'filament': GPIO.remove_event_detect(self.to_int(rpi_input['gpioPin'])) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" @@ -554,7 +554,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_gpio_Control(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['eventType'] == 'gpio' and \ + if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['actionType'] == 'gpio' and \ ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): for rpi_output in self.rpi_outputs: if self.to_int(rpi_input['controlledIO']) == self.to_int(rpi_output['gpioPin']) and rpi_output['outputType'] == 'regular': @@ -580,7 +580,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_printer_action(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['eventType'] == 'printer' and \ + if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['actionType'] == 'printer' and \ ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): if rpi_input['printerAction'] == 'resume': self._logger.info("Printer action resume.") diff --git a/octoprint_enclosure/static/js/enclosure.js b/octoprint_enclosure/static/js/enclosure.js index 199e4f7..ee4935f 100644 --- a/octoprint_enclosure/static/js/enclosure.js +++ b/octoprint_enclosure/static/js/enclosure.js @@ -18,7 +18,6 @@ $(function () { self.enclosureSetTemperature = ko.observable(); self.enclosureHumidity = ko.observable(); - self.previousGpioStatus; self.previousGpioPWMStatus; self.navbarTemp = ko.observable(); @@ -143,7 +142,7 @@ $(function () { }; self.onSettingsShown = function () { - self.fixUI(); + // self.fixUI(); }; self.showColorPicker = function () { @@ -196,7 +195,7 @@ $(function () { self.global_settings.settings.plugins.enclosure.rpi_inputs.push({ label: ko.observable("Input " + (self.global_settings.settings.plugins.enclosure.rpi_inputs().length + 1)), gpioPin: 0, inputPull: "inputPullUp", - eventType: ko.observable("temperature"), setTemp: 100, controlledIO: ko.observable(""), setControlledIO: "low", + actionType: ko.observable("temperature"), setTemp: 100, controlledIO: ko.observable(""), setControlledIO: "low", edge: "fall", printerAction: "filament" }); }; diff --git a/octoprint_enclosure/templates/enclosure_settings.jinja2 b/octoprint_enclosure/templates/enclosure_settings.jinja2 index d9247aa..9963e4e 100644 --- a/octoprint_enclosure/templates/enclosure_settings.jinja2 +++ b/octoprint_enclosure/templates/enclosure_settings.jinja2 @@ -139,7 +139,7 @@
@@ -165,6 +165,35 @@
+
+ +
+
+ +
+
+
+ + + Info: WRITE SOMETHING HERE + Warning + + + + Info: TODO. + + + + Info: TODO + +
+
@@ -244,6 +273,36 @@
+ +
+
+ +
+ + Set temperature that will trigger the event +
+
+
+ +
+ + When the event happen, you want control which IO? +
+
+
+ +
+ + When the event happen, you want to turn the controlled IO HIGH or LOW? +
+
+
+
@@ -318,50 +377,60 @@ Name of Input
- -
- -
- {{ _('Temperature') }} -
-
-
-
- {{ _('GPIO Control') }} - -
-
-
-
- - - Info: Events will run actions when a certain temperature of the sensor is hit. You can control a OUTPUT - pin and set that to a LOW or HIGH value when that happens. You can use this as a safety measure and trigger alarm - lights for example. - Warning - You should always have proper smoke detector on your house. DO NOT use this as your only safety device. - - - - Info: Events will run PRINTER actions when a condition is met, that can be a filament sensor, button, etc. - Actions can be Pause \ Resume \ Cancel a printer job, change the filament or disable Temperature Control. You can - use the "change filament" action and set up the input GPIO acording to your sensor, for example, if your filament - sensor conects to ground when detects the end of the filament, you should choose PULL UP resistors and detect the - event on the falling edge. - - - - Info: Events will control GPIO outputs when a condition is met, for example detect a press of a button. - You can use this to control any previous configured OUTPUTS, basically beeing able to control your lights / fan - / pritner using mechanical buttons buttons instead of the octoprint interface. You can only control REGULAR outputs. - - +
+ +
+ {{ _('Printer') }} +
+
+ {{ _('GPIO Control') }} +
+
+
+ + + Info: GPIO will input status of the pin, HIGH / LOW + + + + Info: Temperature Sensors will input temperature and humidity data. + + +
- + +
+ +
+ {{ _('Printer') }} +
+
+ {{ _('GPIO Control') }} +
+
+
+ + + Info: PRINTER actions when a condition is met, that can be a filament sensor, button, + etc. Actions can be Pause \ Resume \ Cancel a printer job, change the filament or disable Temperature Control. + You can use the "change filament" action and set up the input GPIO acording to your sensor, for example, if your + filament sensor conects to ground when detects the end of the filament, you should choose PULL UP resistors and + detect the event on the falling edge. + + + + Info: Action will control GPIO outputs when a condition is met, for example detect a press of a button. + You can use this to control any previous configured OUTPUTS, basically beeing able to control your lights / fan + / pritner using mechanical buttons buttons instead of the octoprint interface. You can only control REGULAR outputs. + + +
+
+
+ +
@@ -385,7 +454,7 @@
- +
@@ -420,37 +489,7 @@
- -
-
- -
- - Set temperature that will trigger the event -
-
-
- -
- - When the event happen, you want control which IO? -
-
-
- -
- - When the event happen, you want to turn the controlled IO HIGH or LOW? -
-
-
- - +
@@ -478,7 +517,7 @@
- +
-- 2.39.5 From f5c68f0f13897acea59e26db13b56cbf7f28c1b6 Mon Sep 17 00:00:00 2001 From: Vitor de Miranda Henrique Date: Tue, 6 Feb 2018 17:04:01 -0600 Subject: [PATCH 07/42] code review to line 421 --- .../octoprint_neopixel/octoprint_neopixel.ino | 8 +- octoprint_enclosure/__init__.py | 570 ++++++++------ octoprint_enclosure/static/js/enclosure.js | 273 ++++--- .../templates/enclosure_navbar.jinja2 | 8 - .../templates/enclosure_settings.jinja2 | 732 +++++++++--------- .../templates/enclosure_tab.jinja2 | 94 --- .../templates/enclosure_tab_temp.html | 98 +++ .../templates/navbar_temp.html | 10 + .../templates/settings_temp.html | 0 octoprint_enclosure/templates/temp.html | 131 ++++ 10 files changed, 1120 insertions(+), 804 deletions(-) create mode 100644 octoprint_enclosure/templates/enclosure_tab_temp.html create mode 100644 octoprint_enclosure/templates/navbar_temp.html create mode 100644 octoprint_enclosure/templates/settings_temp.html create mode 100644 octoprint_enclosure/templates/temp.html diff --git a/extras/octoprint_neopixel/octoprint_neopixel.ino b/extras/octoprint_neopixel/octoprint_neopixel.ino index 67ecd8e..7bd483c 100644 --- a/extras/octoprint_neopixel/octoprint_neopixel.ino +++ b/extras/octoprint_neopixel/octoprint_neopixel.ino @@ -30,7 +30,7 @@ bool gotData = false; int command = 0; int neopixelPin = 0; int neopixelLeds = 0; -int neopixelBrightness = 0; +int neopixel_brightness = 0; int redValue = 0; int greenValue = 0; int blueValue = 0; @@ -51,8 +51,8 @@ void receiveEvent(int byteCount){ DEBUG_PRINTLN(neopixelLeds); DEBUG_PRINT("BRIGHTNESS "); - neopixelBrightness = Wire.read(); - DEBUG_PRINTLN(neopixelBrightness); + neopixel_brightness = Wire.read(); + DEBUG_PRINTLN(neopixel_brightness); DEBUG_PRINT("RED "); redValue = Wire.read(); @@ -85,7 +85,7 @@ void loop() { if(gotData){ strip.setPin(neopixelPin); - strip.setBrightness(neopixelBrightness); + strip.setBrightness(neopixel_brightness); strip.updateLength(neopixelLeds); strip.updateType(LED_TYPE); strip.begin(); diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index c995034..ccfc897 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -14,6 +14,7 @@ import datetime import octoprint.util import requests import inspect +import threading class EnclosurePlugin(octoprint.plugin.StartupPlugin, @@ -23,23 +24,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, octoprint.plugin.BlueprintPlugin, octoprint.plugin.EventHandlerPlugin): - - - previous_temp_control_status = False - current_temp_control_status = False - enclosure_set_temperature = 0.0 - enclosure_current_temperature = 0.0 - enclosure_current_humidity = 0.0 last_filament_end_detected = 0 - temperature_reading = [] - temperature_control = [] rpi_outputs = [] rpi_inputs = [] - previous_rpi_outputs = [] + rpi_outputs_not_changed = [] notifications = [] - pwm_intances = [] - queue = [] + event_queue = [] + temperature_control_status = [] + temperature_sensor_data = [] def start_timer(self): """ @@ -53,13 +46,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, @staticmethod def to_float(value): """Converts value to flow - + Arguments: value {any} -- value to be - + Returns: float -- value converted - """ + """ try: val = float(value) @@ -78,14 +71,12 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # ~~ StartupPlugin mixin def on_after_startup(self): self.pwm_intances = [] - self.queue = [] - self.temperature_reading = self._settings.get(["temperature_reading"]) - self.temperature_control = self._settings.get(["temperature_control"]) + self.event_queue = [] self.rpi_outputs = self._settings.get(["rpi_outputs"]) self.rpi_inputs = self._settings.get(["rpi_inputs"]) self.notifications = self._settings.get(["notifications"]) self.fix_data() - self.previous_rpi_outputs = [] + self.rpi_outputs_not_changed = [] self.start_timer() self.start_gpio() self.configure_gpio() @@ -94,34 +85,46 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # ~~ Blueprintplugin mixin @octoprint.plugin.BlueprintPlugin.route("/setEnclosureTemperature", methods=["GET"]) def set_enclosure_temperature(self): - self.enclosure_set_temperature = flask.request.values["enclosureSetTemp"] - if self._settings.get(["debug"]) is True: - self._logger.info( - "DEBUG -> Seting enclosure temperature: %s", self.enclosure_set_temperature) + set_temperature = flask.request.values["set_temperature"] + index = flask.request.values["index"] + for temperature_control in list(filter(lambda item: + item['output_type'] == 'temperature_control' and + item['index'] == index, self.rpi_outputs)): + temperature_control['temperature_control_set_temperature'] = set_temperature + if self._settings.get(["debug"]) is True: + self._logger.info( + "DEBUG -> Seting output index %s to temperature: %s", index, set_temperature) self.handle_temperature_control() - return flask.jsonify(enclosureSetTemperature=self.enclosure_set_temperature, enclosureCurrentTemperature=self.enclosure_current_temperature) + return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/getEnclosureSetTemperature", methods=["GET"]) def get_enclosure_set_temperature(self): - return str(self.enclosure_set_temperature) + result = [] + for temperature_control_output in list(filter(lambda item: + item['output_type'] == 'temperature_control', + self.rpi_outputs)): + set_temperature = self.to_float( + temperature_control_output['temperature_control_set_temperature']) + result.append(set_temperature) + return flask.jsonify(result) @octoprint.plugin.BlueprintPlugin.route("/clearGPIOMode", methods=["GET"]) def clear_gpio_mode(self): GPIO.cleanup() return flask.jsonify(success=True) - @octoprint.plugin.BlueprintPlugin.route("/getUpdateBtnStatus", methods=["GET"]) + @octoprint.plugin.BlueprintPlugin.route("/updateBtnStatus", methods=["GET"]) def get_update_btn_status(self): self.update_output_ui() - return flask.make_response("Ok.", 200) + return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/getOutputStatus", methods=["GET"]) def get_output_status(self): result = '' for rpi_output in self.rpi_outputs: - pin = self.to_int(rpi_output['gpioPin']) - if rpi_output['outputType'] == 'regular': - val = GPIO.input(pin) if not rpi_output['activeLow'] else ( + pin = self.to_int(rpi_output['gpio_pin']) + if rpi_output['output_type'] == 'regular': + val = GPIO.input(pin) if not rpi_output['active_low'] else ( not GPIO.input(pin)) if result: result = result + ', ' @@ -131,40 +134,48 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, @octoprint.plugin.BlueprintPlugin.route("/getEnclosureTemperature", methods=["GET"]) def get_enclosure_temperature(self): - return str(self.enclosure_current_temperature) + return flask.jsonify(self.temperature_sensor_data) @octoprint.plugin.BlueprintPlugin.route("/setIO", methods=["GET"]) def set_io(self): - gpio = flask.request.values["io"] + gpio_index = flask.request.values["index"] value = True if flask.request.values["status"] == "on" else False for rpi_output in self.rpi_outputs: - if self.to_int(gpio) == self.to_int(rpi_output['gpioPin']): - val = (not value) if rpi_output['activeLow'] else value - self.write_gpio(self.to_int(gpio), val) + if self.to_int(gpio_index) == self.to_int(rpi_output['index']): + val = (not value) if rpi_output['active_low'] else value + self.write_gpio(self.to_int(rpi_output['gpio_pin']), val) return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/setPWM", methods=["GET"]) def set_pwm(self): - gpio = flask.request.values["io"] + gpio_index = flask.request.values["index"] pwm_val = flask.request.values["pwmVal"] - self.write_pwm(self.to_int(gpio), self.to_int(pwm_val)) - return flask.make_response("Ok.", 200) + for rpi_output in self.rpi_outputs: + if self.to_int(gpio_index) == self.to_int(rpi_output['index']): + self.write_pwm(self.to_int(rpi_output['gpio_pin']), self.to_int(pwm_val)) + return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/setNeopixel", methods=["GET"]) def set_neopixel(self): """ set_neopixel method get request from octoprint and send the comand to arduino or neopixel""" - gpio = flask.request.values["io"] + gpio_index = flask.request.values["index"] red = flask.request.values["red"] green = flask.request.values["green"] blue = flask.request.values["blue"] for rpi_output in self.rpi_outputs: - if self.to_int(gpio) == self.to_int(rpi_output['gpioPin']) and rpi_output['outputType'] == 'neopixel': - led_count = rpi_output['neopixelCount'] - led_brightness = rpi_output['neopixelBrightness'] - address = rpi_output['microAddress'] - self.send_neopixel_command( - gpio, led_count, led_brightness, red, green, blue, address) - return flask.make_response("Ok.", 200) + if self.to_int(gpio_index) == self.to_int(rpi_output['index']): + led_count = rpi_output['neopixel_count'] + led_brightness = rpi_output['neopixel_brightness'] + address = rpi_output['microcontroller_address'] + if not address: + self.send_neopixel_command( + self.to_int(rpi_output['gpio_pin']), + led_count, led_brightness, red, green, blue, address) + else: + self.send_neopixel_command_direct( + self.to_int(rpi_output['gpio_pin']), + led_count, led_brightness, red, green, blue) + return flask.jsonify(success=True) # ~~ Plugin Internal methods def fix_data(self): @@ -173,6 +184,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if not self._settings.get(["settingsVersion"]) == "3.6": self._settings.set(["rpi_outputs"], []) self._settings.set(["rpi_inputs"], []) + self._logger.warn("######### settings not compatible #########") def send_neopixel_command(self, led_pin, led_count, led_brightness, red, green, blue, address): """Send neopixel command @@ -194,7 +206,34 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, led_brightness) + " " + str(red) + " " + str(green) + " " + str(blue) + " " + str(address) if self._settings.get(["debug"]) is True: self._logger.info("Sending neopixel cmd: %s", cmd) - stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() + Popen(cmd, shell=True) + except Exception as ex: + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) + self._logger.warn(message) + pass + + def send_neopixel_command_direct(self, led_pin, led_count, led_brightness, red, green, blue): + """Send neopixel command + + Arguments: + led_pin {int} -- GPIO number + ledCount {int} -- number of LEDS + ledBrightness {int} -- brightness from 0 to 255 + red {int} -- red value from 0 to 255 + green {int} -- gren value from 0 to 255 + blue {int} -- blue value from 0 to 255 + """ + + try: + script = os.path.dirname( + os.path.realpath(__file__)) + "/neopixel.py " + cmd = "sudo python " + script + str(led_pin) + " " + str(led_count) + " " + str( + led_brightness) + " " + str(red) + " " + str(green) + " " + str(blue) + if self._settings.get(["debug"]) is True: + self._logger.info("Sending neopixel cmd: %s", cmd) + Popen(cmd, shell=True) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -204,44 +243,55 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def check_enclosure_temp(self): try: - for temp_reader in self.temperature_reading: - if temp_reader['isEnabled']: - if temp_reader['sensorType'] in ["11", "22", "2302"]: - self._logger.info("sensorType dht") - temp, hum = self.read_dht_temp( - temp_reader['sensorType'], temp_reader['gpioPin']) - elif temp_reader['sensorType'] == "18b20": - temp = self.read_18b20_temp() - hum = 0 - elif temp_reader['sensorType'] == "bme280": - temp, hum = self.read_bme280_temp( - temp_reader['sensorAddress']) - elif temp_reader['sensorType'] == "si7021": - temp, hum = self.read_si7021_temp( - temp_reader['sensorAddress']) - elif temp_reader['sensorType'] == "tmp102": - temp = self.read_tmp102_temp( - temp_reader['sensorAddress']) - hum = 0 - else: - self._logger.info("sensorType no match") - temp = 0 - hum = 0 + sensor_data = [] + for sensor in list( + filter(lambda item: item['input_type'] == 'temperature_sensor', self.rpi_inputs)): + temp, hum = self.get_sensor_data(sensor) + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: + self._logger.info( + "Sensor %s Temperature: %s humidity %s", sensor['label'], temp, hum) + sensor_data.append( + dict(id=sensor['index'], temperature=temp, humidity=hum)) + self._plugin_manager.send_plugin_message( + self._identifier, dict(sensor_data=sensor_data)) + self.temperature_sensor_data = sensor_data + self.handle_temperature_control() + self.handle_temperature_events() + except Exception as ex: + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) + self._logger.warn(message) + pass - if temp != -1 and hum != -1: - self.enclosure_current_temperature = round(self.to_float( - temp), 1) if not temp_reader['useFahrenheit'] else round(self.to_float(temp) * 1.8 + 32, 1) - self.enclosure_current_humidity = round( - self.to_float(hum), 1) - - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: - self._logger.info( - "Temperature: %s humidity %s", self.enclosure_current_temperature, self.enclosure_current_humidity) - - self._plugin_manager.send_plugin_message(self._identifier, dict( - enclosuretemp=self.enclosure_current_temperature, enclosureHumidity=self.enclosure_current_humidity)) - self.handle_temperature_control() - self.handle_temperature_events() + def get_sensor_data(self, sensor): + try: + if sensor['temperature_sensor_type'] in ["11", "22", "2302"]: + self._logger.info("temperature_sensor_type dht") + temp, hum = self.read_dht_temp( + sensor['temperature_sensor_type'], sensor['gpio_pin']) + elif sensor['temperature_sensor_type'] == "18b20": + temp = self.read_18b20_temp() + hum = 0 + elif sensor['temperature_sensor_type'] == "bme280": + temp, hum = self.read_bme280_temp( + sensor['temperature_sensor_address']) + elif sensor['temperature_sensor_type'] == "si7021": + temp, hum = self.read_si7021_temp( + sensor['temperature_sensor_address']) + elif sensor['temperature_sensor_type'] == "tmp102": + temp = self.read_tmp102_temp( + sensor['temperature_sensor_address']) + hum = 0 + else: + self._logger.info("temperature_sensor_type no match") + temp = 0 + hum = 0 + if temp != -1 and hum != -1: + temp = round(self.to_float( + temp), 1) if not sensor['use_fahrenheit'] else round(self.to_float(temp) * 1.8 + 32, 1) + hum = round(self.to_float(hum), 1) + return temp, hum except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -250,18 +300,23 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, pass def handle_temperature_events(self): - for rpi_input in self.rpi_inputs: - if self.to_float(rpi_input['setTemp']) == 0: + for temperature_alarm in list(filter(lambda item: item['output_type'] == 'temperature_alarm', self.rpi_outputs)): + if self.to_float(temperature_alarm['alarm_set_temperature']) == 0: continue - if rpi_input['actionType'] == 'temperature' and (self.to_float(rpi_input['setTemp']) < self.to_float(self.enclosure_current_temperature)): - for rpi_output in self.rpi_outputs: - if self.to_int(rpi_input['controlledIO']) == self.to_int(rpi_output['gpioPin']): - val = GPIO.LOW if rpi_output['activeLow'] else GPIO.HIGH - self.write_gpio(self.to_int(rpi_output['gpioPin']), val) + linked_data = list(filter( + lambda sensor: sensor['index'] == temperature_alarm['linked_temperature_sensor'], + self.temperature_sensor_data)).pop() + sensor_temperature = linked_data['temperature'] + if self.to_float(temperature_alarm['alarm_set_temperature']) < sensor_temperature: + for rpi_controlled_output in self.rpi_outputs: + if self.to_int(temperature_alarm['controlled_io']) == self.to_int(rpi_controlled_output['index']): + val = GPIO.LOW if rpi_controlled_output['active_low'] else GPIO.HIGH + self.write_gpio(self.to_int( + rpi_controlled_output['gpio_pin']), val) for notification in self.notifications: if notification['temperatureAction']: msg = "Temperature action: enclosure temperature exceed " + \ - rpi_input['setTemp'] + temperature_alarm['setTemp'] self.send_notification(msg) def read_dht_temp(self, sensor, pin): @@ -269,10 +324,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, script = os.path.dirname( os.path.realpath(__file__)) + "/getDHTTemp.py " cmd = "sudo python " + script + str(sensor) + " " + str(pin) - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info("Temperature dht cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info("Dht result: %s", stdout) temp, hum = stdout.split("|") return (self.to_float(temp.strip()), self.to_float(hum.strip())) @@ -288,10 +343,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, script = os.path.dirname( os.path.realpath(__file__)) + "/BME280.py " cmd = "sudo python " + script + str(address) - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info("Temperature BME280 cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info("BME280 result: %s", stdout) temp, hum = stdout.split("|") return (self.to_float(temp.strip()), self.to_float(hum.strip())) @@ -307,10 +362,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, script = os.path.dirname( os.path.realpath(__file__)) + "/SI7021.py " cmd = "sudo python " + script + str(address) - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info("Temperature SI7021 cmd: %s", cmd) stdout = (Popen(cmd, shell=True, stdout=PIPE).stdout).read() - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info("SI7021 result: %s", stdout) temp, hum = stdout.split("|") return (self.to_float(temp.strip()), self.to_float(hum.strip())) @@ -349,11 +404,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: script = os.path.dirname(os.path.realpath(__file__)) + "/tmp102.py" args = ["python", script, str(address)] - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info("Temperature TMP102 cmd: %s", " ".join(args)) proc = Popen(args, stdout=PIPE) stdout, _ = proc.communicate() - if self._settings.get(["debug"]) is True and self._settings.get(["enableTemperatureLog"]) is True: + if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info("TMP102 result: %s", stdout) return self.to_float(stdout.strip()) except Exception as ex: @@ -364,29 +419,45 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, return 0 def handle_temperature_control(self): - for control in self.temperature_control: - if control['isEnabled'] is True: - if control['controlType'] is 'heater': - self.current_temp_control_status = self.to_float( - self.enclosure_current_temperature) < self.to_float(self.enclosure_set_temperature) + for temperature_control in list(filter(lambda item: + item['output_type'] == 'temperature_control', self.rpi_outputs)): + + set_temperature = self.to_float( + temperature_control['temperature_control_set_temperature']) + + if set_temperature == 0: + current_status = False + else: + linked_data = list(filter(lambda sensor: + sensor['index'] == temperature_control['linked_temperature_sensor'], + self.temperature_sensor_data)).pop() + current_temperature = self.to_float(linked_data['temperature']) + + current_status = set_temperature < current_temperature + + if temperature_control['temperature_control_type'] is 'cooler': + current_status != current_status + + previous_status = filter( + lambda item: item['index'] == temperature_control['index'], + self.temperature_control_status).pop()['status'] + + if current_status != previous_status: + if current_status: + self._logger.info( + "Turning gpio to control temperature on.") + val = False if temperature_control['active_low'] else True + self.write_gpio(self.to_int( + temperature_control['gpio_pin']), val) else: - if self.to_float(self.enclosure_set_temperature) == 0: - self.current_temp_control_status = False - else: - self.current_temp_control_status = self.to_float( - self.enclosure_current_temperature) > self.to_float(self.enclosure_set_temperature) - if self.current_temp_control_status != self.previous_temp_control_status: - if self.current_temp_control_status: - self._logger.info( - "Turning gpio to control temperature on.") - val = False if control['activeLow'] else True - self.write_gpio(self.to_int(control['gpioPin']), val) - else: - self._logger.info( - "Turning gpio to control temperature off.") - val = True if control['activeLow'] else False - self.write_gpio(self.to_int(control['gpioPin']), val) - self.previous_temp_control_status = self.current_temp_control_status + self._logger.info( + "Turning gpio to control temperature off.") + val = True if temperature_control['active_low'] else False + self.write_gpio(self.to_int( + temperature_control['gpio_pin']), val) + for control_status in self.temperature_control_status: + if control_status['index'] == temperature_control['index']: + self.temperature_control_status['status'] = current_status def start_gpio(self): try: @@ -394,9 +465,16 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, setMode = GPIO.BOARD if self._settings.get( ["useBoardPinNumber"]) else GPIO.BCM if currentMode is None: - GPIO.setmode(setMode) - tempstr = "BOARD" if setMode == GPIO.BOARD else "BCM" - self._logger.info("Setting GPIO mode to %s", tempstr) + gpios = list(filter(lambda item: item['output_type'] == 'regular' or + item['output_type'] == 'pwm' or + item['output_type'] == 'temperature_control' or + item['output_type'] == 'neopixel_direct', self.rpi_outputs)) + gpios.append(list(filter( + lambda item: item['input_type'] == 'gpio', self.rpi_inputs))) + if gpios.count() > 0: + GPIO.setmode(setMode) + tempstr = "BOARD" if setMode == GPIO.BOARD else "BCM" + self._logger.info("Setting GPIO mode to %s", tempstr) elif currentMode != setMode: GPIO.setmode(currentMode) tempstr = "BOARD" if currentMode == GPIO.BOARD else "BCM" @@ -419,16 +497,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: for control in self.temperature_control: if control['isEnabled']: - GPIO.cleanup(self.to_int(control['gpioPin'])) + GPIO.cleanup(self.to_int(control['gpio_pin'])) for rpi_output in self.rpi_outputs: - if self.to_int(rpi_output['gpioPin']) not in self.previous_rpi_outputs: - GPIO.cleanup(self.to_int(rpi_output['gpioPin'])) + if self.to_int(rpi_output['gpio_pin']) not in self.rpi_outputs_not_changed: + GPIO.cleanup(self.to_int(rpi_output['gpio_pin'])) for rpi_input in self.rpi_inputs: try: - GPIO.remove_event_detect(self.to_int(rpi_input['gpioPin'])) + GPIO.remove_event_detect( + self.to_int(rpi_input['gpio_pin'])) except: pass - GPIO.cleanup(self.to_int(rpi_input['gpioPin'])) + GPIO.cleanup(self.to_int(rpi_input['gpio_pin'])) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -446,40 +525,50 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass + def generate_temperature_control_status(self): + status = [] + for temperature_control in list(filter(lambda item: + item['output_type'] == 'temperature_control', self.rpi_outputs)): + status.append( + dict(index=temperature_control['index'], status=False)) + self.temperature_control_status = status + def configure_gpio(self): try: for control in self.temperature_control: if control['isEnabled']: GPIO.setup(self.to_int( - control['gpioPin']), GPIO.OUT, initial=GPIO.HIGH if control['activeLow'] else GPIO.LOW) + control['gpio_pin']), GPIO.OUT, initial=GPIO.HIGH if control['active_low'] else GPIO.LOW) for rpi_output in self.rpi_outputs: - pin = self.to_int(rpi_output['gpioPin']) - if rpi_output['outputType'] == 'regular': - if self.to_int(rpi_output['gpioPin']) not in self.previous_rpi_outputs: - initialValue = GPIO.HIGH if rpi_output['activeLow'] else GPIO.LOW + pin = self.to_int(rpi_output['gpio_pin']) + if rpi_output['output_type'] == 'regular': + if self.to_int(rpi_output['gpio_pin']) not in self.rpi_outputs_not_changed: + initialValue = GPIO.HIGH if rpi_output['active_low'] else GPIO.LOW GPIO.setup(pin, GPIO.OUT, initial=initialValue) - if rpi_output['outputType'] == 'pwm': + if rpi_output['output_type'] == 'pwm': for pwm in (pwm for pwm in self.pwm_intances if pin in pwm): self.pwm_intances.remove(pwm) self.clear_channel(pin) GPIO.setup(pin, GPIO.OUT) - p = GPIO.PWM(pin, self.to_int(rpi_output['frequency'])) + p = GPIO.PWM(pin, self.to_int(rpi_output['pwm_frequency'])) self.pwm_intances.append({pin: p}) - if rpi_output['outputType'] == 'neopixel': + if rpi_output['output_type'] == 'neopixel': self.clear_channel(pin) for rpi_input in self.rpi_inputs: - pullResistor = pull_up_down = GPIO.PUD_UP if rpi_input[ - 'inputPull'] == 'inputPullUp' else GPIO.PUD_DOWN + pullResistor = GPIO.PUD_UP if rpi_input[ + 'input_pull_resistor'] == 'input_pull_up' else GPIO.PUD_DOWN GPIO.setup(self.to_int( - rpi_input['gpioPin']), GPIO.IN, pullResistor) - if rpi_input['actionType'] == 'gpio' and self.to_int(rpi_input['gpioPin']) != 0: + rpi_input['gpio_pin']), GPIO.IN, pullResistor) + if rpi_input['action_type'] == 'gpio' and self.to_int(rpi_input['gpio_pin']) != 0: edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING GPIO.add_event_detect(self.to_int( - rpi_input['gpioPin']), edge, callback=self.handle_gpio_Control, bouncetime=200) - if rpi_input['actionType'] == 'printer' and rpi_input['printerAction'] != 'filament' and self.to_int(rpi_input['gpioPin']) != 0: + rpi_input['gpio_pin']), edge, callback=self.handle_gpio_control, bouncetime=200) + if (rpi_input['action_type'] == 'printer_control' and + rpi_input['printer_action'] != 'filament' and + self.to_int(rpi_input['gpio_pin']) != 0): edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING GPIO.add_event_detect(self.to_int( - rpi_input['gpioPin']), edge, callback=self.handle_printer_action, bouncetime=200) + rpi_input['gpio_pin']), edge, callback=self.handle_printer_action, bouncetime=200) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -490,12 +579,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_filamment_detection(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['actionType'] == 'printer' and rpi_input['printerAction'] == 'filament' \ - and ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): + if (channel == self.to_int(rpi_input['gpio_pin']) and rpi_input['action_type'] == 'printer_control' and + rpi_input['printer_action'] == 'filament' and + ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpio_pin'])))): if time.time() - self.last_filament_end_detected > self._settings.get_int(["filamentSensorTimeout"]): self._logger.info("Detected end of filament.") self.last_filament_end_detected = time.time() - for line in self._settings.get(["filamentSensorGcode"]).split('\n'): + for line in self._settings.get(["filament_sensor_gcode"]).split('\n'): if line: self._printer.commands(line.strip().upper()) self._logger.info( @@ -520,14 +610,16 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.stop_filament_detection() try: for rpi_input in self.rpi_inputs: - if rpi_input['actionType'] == 'printer' and rpi_input['printerAction'] == 'filament' and self.to_int(rpi_input['gpioPin']) != 0: + if (rpi_input['action_type'] == 'printer_control' and + rpi_input['printer_action'] == 'filament' and + self.to_int(rpi_input['gpio_pin']) != 0): edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING - if GPIO.input(self.to_int(rpi_input['gpioPin'])) == (edge == GPIO.RISING): + if GPIO.input(self.to_int(rpi_input['gpio_pin'])) == (edge == GPIO.RISING): self._printer.pause_print() self._logger.info("Started printing with no filament.") else: GPIO.add_event_detect(self.to_int( - rpi_input['gpioPin']), edge, callback=self.handle_filamment_detection, bouncetime=200) + rpi_input['gpio_pin']), edge, callback=self.handle_filamment_detection, bouncetime=200) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -538,8 +630,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def stop_filament_detection(self): try: for rpi_input in self.rpi_inputs: - if rpi_input['actionType'] == 'printer' and rpi_input['printerAction'] == 'filament': - GPIO.remove_event_detect(self.to_int(rpi_input['gpioPin'])) + if rpi_input['action_type'] == 'printer_control' and rpi_input['printer_action'] == 'filament': + GPIO.remove_event_detect( + self.to_int(rpi_input['gpio_pin'])) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -547,28 +640,30 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def cancel_events_on_queue(self): - for task in self.queue: + def cancel_events_on_event_queue(self): + for task in self.event_queue: task.cancel() - def handle_gpio_Control(self, channel): + def handle_gpio_control(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['actionType'] == 'gpio' and \ - ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): + if (channel == self.to_int(rpi_input['gpio_pin']) and + rpi_input['action_type'] == 'gpio' and + ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpio_pin'])))): for rpi_output in self.rpi_outputs: - if self.to_int(rpi_input['controlledIO']) == self.to_int(rpi_output['gpioPin']) and rpi_output['outputType'] == 'regular': - if rpi_input['setControlledIO'] == 'toggle': + if (self.to_int(rpi_input['controlled_io']) == self.to_int(rpi_output['gpio_pin']) and + rpi_output['output_type'] == 'regular'): + if rpi_input['controlled_io_set_value'] == 'toggle': val = GPIO.LOW if GPIO.input(self.to_int( - rpi_output['gpioPin'])) == GPIO.HIGH else GPIO.HIGH + rpi_output['gpio_pin'])) == GPIO.HIGH else GPIO.HIGH else: - val = GPIO.LOW if rpi_input['setControlledIO'] == 'low' else GPIO.HIGH + val = GPIO.LOW if rpi_input['controlled_io_set_value'] == 'low' else GPIO.HIGH self.write_gpio(self.to_int( - rpi_output['gpioPin']), val) + rpi_output['gpio_pin']), val) for notification in self.notifications: if notification['gpioAction']: msg = "GPIO control action caused by input " + str(rpi_input['label']) + ". Setting GPIO" + str( - rpi_input['controlledIO']) + " to: " + str(rpi_input['setControlledIO']) + rpi_input['controlled_io']) + " to: " + str(rpi_input['controlled_io_set_value']) self.send_notification(msg) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" @@ -580,26 +675,26 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_printer_action(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.to_int(rpi_input['gpioPin']) and rpi_input['actionType'] == 'printer' and \ - ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpioPin']))): - if rpi_input['printerAction'] == 'resume': + if channel == self.to_int(rpi_input['gpio_pin']) and rpi_input['action_type'] == 'printer_control' and \ + ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpio_pin']))): + if rpi_input['printer_action'] == 'resume': self._logger.info("Printer action resume.") self._printer.resume_print() - elif rpi_input['printerAction'] == 'pause': + elif rpi_input['printer_action'] == 'pause': self._logger.info("Printer action pause.") self._printer.pause_print() - elif rpi_input['printerAction'] == 'cancel': + elif rpi_input['printer_action'] == 'cancel': self._logger.info("Printer action cancel.") self._printer.cancel_print() - elif rpi_input['printerAction'] == 'stopTemperatureControl': + elif rpi_input['printer_action'] == 'stop_temperature_control': self._logger.info( "Printer action stoping temperature control.") self.enclosure_set_temperature = 0 self.handle_temperature_control() for notification in self.notifications: - if notification['printerAction']: + if notification['printer_action']: msg = "Printer action: " + \ - rpi_input['printerAction'] + \ + rpi_input['printer_action'] + \ " caused by input: " + str(rpi_input['label']) self.send_notification(msg) except Exception as ex: @@ -627,7 +722,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for pwm in self.pwm_intances: if gpio in pwm: pwm_object = pwm[gpio] - pwm['dutycycle'] = pwmValue + pwm['duty_cycle'] = pwmValue pwm_object.stop() pwm_object.start(pwmValue) if self._settings.get(["debug"]) is True: @@ -648,16 +743,16 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, result_pwm = [] for rpi_output in self.rpi_outputs: - pin = self.to_int(rpi_output['gpioPin']) - if rpi_output['outputType'] == 'regular': - val = GPIO.input(pin) if not rpi_output['activeLow'] else ( + pin = self.to_int(rpi_output['gpio_pin']) + if rpi_output['output_type'] == 'regular': + val = GPIO.input(pin) if not rpi_output['active_low'] else ( not GPIO.input(pin)) result.append({pin: val}) - if rpi_output['outputType'] == 'pwm': + if rpi_output['output_type'] == 'pwm': for pwm in self.pwm_intances: if pin in pwm: - if 'dutycycle' in pwm: - pwmVal = pwm['dutycycle'] + if 'duty_cycle' in pwm: + pwmVal = pwm['duty_cycle'] val = self.to_int(pwmVal) else: val = 100 @@ -675,15 +770,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def get_output_list(self): result = [] for rpi_output in self.rpi_outputs: - result.append(self.to_int(rpi_output['gpioPin'])) + result.append(self.to_int(rpi_output['gpio_pin'])) return result def send_notification(self, message): try: - provider = self._settings.get(["notificationProvider"]) + provider = self._settings.get(["notification_provider"]) if provider == 'ifttt': - event = self._settings.get(["event_name"]) - api_key = self._settings.get(["apiKEY"]) + event = self._settings.get(["notification_event_name"]) + api_key = self._settings.get(["notification_api_key"]) if self._settings.get(["debug"]) is True: self._logger.info( "Sending notification to: %s with msg: %s with key: %s", provider, message, api_key) @@ -730,25 +825,25 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.start_filament_detection() if event == Events.PRINT_STARTED: - self.cancel_events_on_queue() + self.cancel_events_on_event_queue() self.start_filament_detection() for rpi_output in self.rpi_outputs: - if rpi_output['autoStartup'] and rpi_output['outputType'] == 'regular': - value = False if rpi_output['activeLow'] else True - self.queue.append(threading.Timer(self.to_float(rpi_output['startupTimeDelay']), - self.write_gpio, - args=[self.to_int(rpi_output['gpioPin']), value])) - if rpi_output['autoStartup'] and rpi_output['outputType'] == 'pwm': - value = self.to_int(rpi_output['dutycycle']) - self.queue.append(threading.Timer(self.to_float(rpi_output['startupTimeDelay']), - self.write_pwm, - args=[self.to_int(rpi_output['gpioPin']), value])) - if rpi_output['autoStartup'] and rpi_output['outputType'] == 'neopixel': - gpioPin = rpi_output['gpioPin'] - ledCount = rpi_output['neopixelCount'] - ledBrightness = rpi_output['neopixelBrightness'] - address = rpi_output['microAddress'] - stringColor = rpi_output['color'] + if rpi_output['auto_startup'] and rpi_output['output_type'] == 'regular': + value = False if rpi_output['active_low'] else True + self.event_queue.append(threading.Timer(self.to_float(rpi_output['startup_time']), + self.write_gpio, + args=[self.to_int(rpi_output['gpio_pin']), value])) + if rpi_output['auto_startup'] and rpi_output['output_type'] == 'pwm': + value = self.to_int(rpi_output['duty_cycle']) + self.event_queue.append(threading.Timer(self.to_float(rpi_output['startup_time']), + self.write_pwm, + args=[self.to_int(rpi_output['gpio_pin']), value])) + if rpi_output['auto_startup'] and rpi_output['output_type'] == 'neopixel': + gpio_pin = rpi_output['gpio_pin'] + ledCount = rpi_output['neopixel_count'] + ledBrightness = rpi_output['neopixel_brightness'] + address = rpi_output['microcontroller_address'] + stringColor = rpi_output['neopixel_color'] stringColor = stringColor.replace('rgb(', '') red = stringColor[:stringColor.index(',')] @@ -757,13 +852,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, stringColor = stringColor[stringColor.index(',') + 1:] blue = stringColor[:stringColor.index(')')] - self.queue.append(threading.Timer(self.to_float(rpi_output['startupTimeDelay']), - self.send_neopixel_command, - args=[gpioPin, ledCount, ledBrightness, red, green, blue, address])) - for task in self.queue: + self.event_queue.append(threading.Timer(self.to_float(rpi_output['startup_time']), + self.send_neopixel_command, + args=[gpio_pin, ledCount, ledBrightness, red, green, blue, address])) + for task in self.event_queue: task.start() for control in self.temperature_control: - if control['autoStartup'] is True: + if control['auto_startup'] is True: self.enclosure_set_temperature = self.to_int( control['defaultTemp']) self._plugin_manager.send_plugin_message( @@ -775,25 +870,25 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._plugin_manager.send_plugin_message( self._identifier, dict(enclosureSetTemp=self.enclosure_set_temperature)) for rpi_output in self.rpi_outputs: - if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'regular': - value = True if rpi_output['activeLow'] else False - self.queue.append(threading.Timer(self.to_float(rpi_output['shutdownTimeDelay']), - self.write_gpio, - args=[self.to_int(rpi_output['gpioPin']), value])) - if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'pwm': + if rpi_output['auto_shutdown'] and rpi_output['output_type'] == 'regular': + value = True if rpi_output['active_low'] else False + self.event_queue.append(threading.Timer(self.to_float(rpi_output['shutdown_time']), + self.write_gpio, + args=[self.to_int(rpi_output['gpio_pin']), value])) + if rpi_output['auto_shutdown'] and rpi_output['output_type'] == 'pwm': value = 0 - self.queue.append(threading.Timer(self.to_float(rpi_output['shutdownTimeDelay']), - self.write_pwm, - args=[self.to_int(rpi_output['gpioPin']), value])) - if rpi_output['autoShutdown'] and rpi_output['outputType'] == 'neopixel': - gpioPin = rpi_output['gpioPin'] - ledCount = rpi_output['neopixelCount'] - ledBrightness = rpi_output['neopixelBrightness'] - address = rpi_output['microAddress'] - self.queue.append(threading.Timer(self.to_float(rpi_output['shutdownTimeDelay']), - self.send_neopixel_command, - args=[gpioPin, ledCount, 0, 0, 0, 0, address])) - for task in self.queue: + self.event_queue.append(threading.Timer(self.to_float(rpi_output['shutdown_time']), + self.write_pwm, + args=[self.to_int(rpi_output['gpio_pin']), value])) + if rpi_output['auto_shutdown'] and rpi_output['output_type'] == 'neopixel': + gpio_pin = rpi_output['gpio_pin'] + ledCount = rpi_output['neopixel_count'] + ledBrightness = rpi_output['neopixel_brightness'] + address = rpi_output['microcontroller_address'] + self.event_queue.append(threading.Timer(self.to_float(rpi_output['shutdown_time']), + self.send_neopixel_command, + args=[gpio_pin, ledCount, 0, 0, 0, 0, address])) + for task in self.event_queue: task.start() if event == Events.PRINT_DONE: @@ -814,8 +909,6 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, outputsBeforeSave = self.get_output_list() octoprint.plugin.SettingsPlugin.on_settings_save(self, data) - self.temperature_reading = self._settings.get(["temperature_reading"]) - self.temperature_control = self._settings.get(["temperature_control"]) self.rpi_outputs = self._settings.get(["rpi_outputs"]) self.rpi_inputs = self._settings.get(["rpi_inputs"]) self.notifications = self._settings.get(["notifications"]) @@ -826,28 +919,21 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for pin in (pin for pin in outputsBeforeSave if pin not in commonPins): self.clear_channel(pin) - self.previous_rpi_outputs = commonPins + self.rpi_outputs_not_changed = commonPins self.clear_gpio() if self._settings.get(["debug"]) is True: - self._logger.info("temperature_reading: %s", - self.temperature_reading) - self._logger.info("temperature_control: %s", - self.temperature_control) self._logger.info("rpi_outputs: %s", self.rpi_outputs) self._logger.info("rpi_inputs: %s", self.rpi_inputs) self.start_gpio() self.configure_gpio() + self.generate_temperature_control_status() def get_settings_defaults(self): return dict( - temperature_reading=[{'isEnabled': False, 'gpioPin': 4, - 'useFahrenheit': False, 'sensorType': '', 'sensorAddress': 0}], - temperature_control=[{'isEnabled': False, 'controlType': 'heater', - 'gpioPin': 17, 'activeLow': True, 'autoStartup': False, 'defaultTemp': 0}], rpi_outputs=[], rpi_inputs=[], - filamentSensorGcode="G91 ;Set Relative Mode \n" + + filament_sensor_gcode="G91 ;Set Relative Mode \n" + "G1 E-5.000000 F500 ;Retract 5mm\n" + "G1 Z15 F300 ;move Z up 15mm\n" + "G90 ;Set Absolute Mode\n " + @@ -860,17 +946,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, "G28 X0 Y0 ;Home X Y\n" + "M82 ;Set extruder to Absolute Mode\n" + "G92 E0 ;Set Extruder to 0", - debug=True, - enableTemperatureLog=False, + debug=False, + debug_temperature_log=False, useBoardPinNumber=False, - filamentSensorTimeout=120, - notificationProvider="disabled", - apiKEY="", - event_name="printer_event", - showTempNavbar=False, + notification_provider="disabled", + notification_api_key="", + notification_event_name="printer_event", settingsVersion="", notifications=[{'printFinish': True, 'filamentChange': True, - 'printerAction': True, 'temperatureAction': True, 'gpioAction': True}] + 'printer_action': True, 'temperatureAction': True, 'gpioAction': True}] ) # ~~ TemplatePlugin diff --git a/octoprint_enclosure/static/js/enclosure.js b/octoprint_enclosure/static/js/enclosure.js index ee4935f..7463b6b 100644 --- a/octoprint_enclosure/static/js/enclosure.js +++ b/octoprint_enclosure/static/js/enclosure.js @@ -4,30 +4,37 @@ $(function () { self.pluginName = "enclosure"; - self.global_settings = parameters[0]; - self.connection = parameters[1]; + self.settingsViewModel = parameters[0]; + self.connectionViewModel = parameters[1]; self.printerStateViewModel = parameters[2]; - self.temperature_reading = ko.observableArray(); - self.temperature_control = ko.observableArray(); self.rpi_outputs = ko.observableArray(); self.rpi_inputs = ko.observableArray(); - self.filamentSensorGcode = ko.observable(); - self.enclosureTemp = ko.observable(); - self.enclosureSetTemperature = ko.observable(); - self.enclosureHumidity = ko.observable(); + self.rpi_outputs_regular = ko.pureComputed(function () { + return ko.utils.arrayFilter(self.settingsViewModel.settings.plugins.enclosure.rpi_outputs(), function (item) { + return (item.output_type() === "regular"); + }); + }); - self.previousGpioStatus; - self.previousGpioPWMStatus; - self.navbarTemp = ko.observable(); - self.navbarHum = ko.observable(); + self.rpi_outputs_pwm = ko.pureComputed(function () { + return ko.utils.arrayFilter(self.settingsViewModel.settings.plugins.enclosure.rpi_outputs(), function (item) { + return (item.output_type() === "pwm"); + }); + }); - self.showTempNavbar = ko.observable(); + self.rpi_inputs_temperature_sensors = ko.pureComputed(function () { + return ko.utils.arrayFilter(self.settingsViewModel.settings.plugins.enclosure.rpi_inputs(), function (item) { + return (item.input_type() === "temperature_sensor"); + }); + }); - self.notificationProvider = ko.observable(); - self.event_name = ko.observable(); - self.apiKEY = ko.observable(); + self.debug = ko.observable(); + self.debug_temperature_log = ko.observable(); + self.filament_sensor_gcode = ko.observable(); + self.notification_provider = ko.observable(); + self.notification_event_name = ko.observable(); + self.notification_api_key = ko.observable(); self.notifications = ko.observable(); self.onDataUpdaterPluginMessage = function (plugin, data) { @@ -38,12 +45,11 @@ $(function () { if (data.hasOwnProperty("enclosuretemp")) { self.enclosureTemp(data.enclosuretemp); - self.temperature_reading().forEach(function (element) { - if ("useFahrenheit" in element) { - useFahrenheit = element['useFahrenheit']() + if ("use_fahrenheit" in element) { + use_fahrenheit = element['use_fahrenheit']() - if (useFahrenheit) { + if (use_fahrenheit) { self.navbarTemp(_.sprintf("Enc: %.1f°F", data.enclosuretemp)); } else { self.navbarTemp(_.sprintf("Enc: %.1f°C", data.enclosuretemp)); @@ -51,6 +57,7 @@ $(function () { } }); } + if (data.hasOwnProperty("enclosureHumidity")) { self.enclosureHumidity(data.enclosureHumidity); self.navbarHum(_.sprintf("Hum: %.1f%%", data.enclosureHumidity)); @@ -65,11 +72,11 @@ $(function () { } if (!data.rpi_output) { - data.rpi_output = self.previousGpioStatus; + data.rpi_output = self.previous_gpio_status; } if (!data.rpi_output_pwm) { - data.rpi_output_pwm = self.previousGpioPWMStatus; + data.rpi_output_pwm = self.previous_gpio_pwm_status; } if (data.rpi_output) { @@ -83,7 +90,7 @@ $(function () { $("#btn_on_" + key).removeClass('active'); } }); - self.previousGpioStatus = data.rpi_output; + self.previous_gpio_status = data.rpi_output; } if (data.rpi_output_pwm) { @@ -91,22 +98,26 @@ $(function () { key = Object.keys(gpio)[0]; val = gpio[key]; if (parseFloat(val) != 100) { - $("#dutycycle_" + key).attr("placeholder", val); + $("#duty_cycle_" + key).attr("placeholder", val); } else { - $("#dutycycle_" + key).attr("placeholder", "off"); + $("#duty_cycle_" + key).attr("placeholder", "off"); } }); - self.previousGpioPWMStatus = data.rpi_output_pwm; + self.previous_gpio_pwm_status = data.rpi_output_pwm; } if (data.isMsg) { - new PNotify({ title: "Enclosure", text: data.msg, type: "error" }); + new PNotify({ + title: "Enclosure", + text: data.msg, + type: "error" + }); } }; self.enableBtn = ko.computed(function () { - // return self.connection.loginState.isUser() && self.printerStateViewModel.isOperational(); - return self.connection.loginState.isUser(); + // return self.connectionViewModel.loginState.isUser() && self.printerStateViewModel.isOperational(); + return self.connectionViewModel.loginState.isUser(); }); @@ -118,35 +129,39 @@ $(function () { self.onBeforeBinding = function () { - self.settings = self.global_settings.settings.plugins.enclosure; - self.temperature_reading(self.settings.temperature_reading()); - // self.temperature_control(self.settings.temperature_control.slice(0)); - self.rpi_outputs(self.settings.rpi_outputs()); - self.rpi_inputs(self.settings.rpi_inputs()); - self.filamentSensorGcode(self.settings.filamentSensorGcode()); - self.notificationProvider(self.settings.notificationProvider()); - self.showTempNavbar(self.settings.showTempNavbar()); + self.rpi_outputs(self.settingsViewModel.settings.plugins.enclosure.rpi_outputs()); + self.rpi_inputs(self.settingsViewModel.settings.plugins.enclosure.rpi_inputs()); - self.event_name(self.settings.event_name()); - self.apiKEY(self.settings.apiKEY()); - self.notifications(self.settings.notifications()); + self.debug(self.settingsViewModel.settings.plugins.enclosure.debug()) + self.debug_temperature_log(self.settingsViewModel.settings.plugins.enclosure.debug_temperature_log()) + self.filament_sensor_gcode(self.settingsViewModel.settings.plugins.enclosure.filament_sensor_gcode()) + self.notification_provider(self.settingsViewModel.settings.plugins.enclosure.notification_provider()) + self.notification_event_name(self.settingsViewModel.settings.plugins.enclosure.notification_event_name()) + self.notification_api_key(self.settingsViewModel.settings.plugins.enclosure.notification_api_key()) + self.notifications(self.settingsViewModel.settings.plugins.enclosure.notifications()) + + // self.settings = self.settingsViewModel.settings.plugins.enclosure; + // self.temperature_reading(self.settings.temperature_reading()); + // // self.temperature_control(self.settings.temperature_control.slice(0)); }; self.onStartupComplete = function () { - self.getUpdateBtnStatus(); + // self.getUpdateBtnStatus(); }; self.onDataUpdaterReconnect = function () { - self.getUpdateBtnStatus(); + // self.getUpdateBtnStatus(); }; self.onSettingsShown = function () { - // self.fixUI(); + }; self.showColorPicker = function () { - $('[name=colorpicker]').colorpicker({ format: 'rgb' }); + $('[name=colorpicker]').colorpicker({ + format: 'rgb' + }); } self.onSettingsHidden = function () { @@ -154,8 +169,8 @@ $(function () { }; self.getRegularOutputs = function () { - return self.global_settings.settings.plugins.enclosure.rpi_outputs().filter(function (rpi_outputs) { - return rpi_outputs.outputType == 'regular'; + return self.settingsViewModel.settings.plugins.enclosure.rpi_outputs().filter(function (rpi_outputs) { + return rpi_outputs.output_type == 'regular'; }); }; self.setTemperature = function () { @@ -164,7 +179,9 @@ $(function () { url: self.buildPluginUrl("/setEnclosureTemperature"), type: "GET", dataType: "json", - data: { "enclosureSetTemp": Number($("#enclosureSetTemp").val()) }, + data: { + "enclosureSetTemp": Number($("#enclosureSetTemp").val()) + }, success: function (data) { $("#enclosureSetTemp").val(''); cleanTemperature = self.getCleanTemperature(data.enclosureSetTemperature); @@ -177,31 +194,81 @@ $(function () { }; self.addRpiOutput = function () { - self.global_settings.settings.plugins.enclosure.rpi_outputs.push({ - label: ko.observable("Ouput " + - (self.global_settings.settings.plugins.enclosure.rpi_outputs().length + 1)), - gpioPin: ko.observable(0), activeLow: true, - autoStartup: ko.observable(false), startupTimeDelay: 0, autoShutdown: ko.observable(false), shutdownTimeDelay: 0, - outputType: ko.observable('regular'), frequency: 50, dutycycle: 0, color: "rgb(255,0,0)", - neopixelCount: 0, neopixelBrightness: 255, microAddress: 0 + + var arrRelaysLength = self.settingsViewModel.settings.plugins.enclosure.rpi_outputs().length; + + var nextIndex = arrRelaysLength == 0 ? 1 : self.settingsViewModel.settings.plugins.enclosure.rpi_outputs()[arrRelaysLength - 1].index() + 1; + + self.settingsViewModel.settings.plugins.enclosure.rpi_outputs.push({ + index: ko.observable(nextIndex), + label: ko.observable("Ouput " + nextIndex), + output_type: ko.observable("regular"), + gpio_pin: ko.observable(0), + gpio_status: ko.observable(0), + active_low: ko.observable(true), + auto_startup: ko.observable(false), + controlled_io: ko.observable(0), + controlled_io_set_value: ko.observable("Low"), + startup_time: ko.observable(0), + auto_shutdown: ko.observable(false), + shutdown_time: ko.observable(0), + linked_temperature_sensor: ko.observable(), + alarm_set_temperature: ko.observable(0), + temperature_control_type: ko.observable(""), + temperature_control_set_temperature: ko.observable(0), + temperature_control_deadband: ko.observable(0), + temperature_control_default_temperature: ko.observable(0), + temperature_control_max_temperature: ko.observable(0), + pwm_frequency: ko.observable(50), + pwm_status: ko.observable(50), + duty_cycle: ko.observable(0), + neopixel_color: ko.observable("rgb(255,0,0)"), + neopixel_count: ko.observable(0), + neopixel_brightness: ko.observable(255), + microcontroller_address: ko.observable(0), + gcode: ko.observable("") }); + + // var test = self.settingsViewModel.settings.plugins.enclosure.rpi_outputs(); + + // console.log(self.rpi_outputs_regular()); }; - self.removeRpiOutput = function (definition) { - self.global_settings.settings.plugins.enclosure.rpi_outputs.remove(definition); + self.removeRpiOutput = function (data) { + self.settingsViewModel.settings.plugins.enclosure.rpi_outputs.remove(data); }; self.addRpiInput = function () { - self.global_settings.settings.plugins.enclosure.rpi_inputs.push({ - label: ko.observable("Input " + - (self.global_settings.settings.plugins.enclosure.rpi_inputs().length + 1)), gpioPin: 0, inputPull: "inputPullUp", - actionType: ko.observable("temperature"), setTemp: 100, controlledIO: ko.observable(""), setControlledIO: "low", - edge: "fall", printerAction: "filament" + + var arrRelaysLength = self.settingsViewModel.settings.plugins.enclosure.rpi_inputs().length; + + var nextIndex = arrRelaysLength == 0 ? 1 : self.settingsViewModel.settings.plugins.enclosure.rpi_inputs()[arrRelaysLength - 1].index() + 1; + + self.settingsViewModel.settings.plugins.enclosure.rpi_inputs.push({ + index: ko.observable(nextIndex), + label: ko.observable("Input " + nextIndex), + input_type: ko.observable("gpio"), + gpio_pin: ko.observable(0), + input_pull_resistor: ko.observable("input_pull_up"), + temperature_sensor_type: ko.observable("DS18B20"), + temperature_sensor_address: ko.observable(""), + temperature_sensor_temperature: ko.observable(0), + temperature_sensor_humidity: ko.observable(0), + ds18b20_serial: ko.observable(""), + use_fahrenheit: ko.observable(false), + action_type: ko.observable("gpio_control"), + controlled_io: ko.observable(""), + controlled_io_set_value: ko.observable("low"), + edge: ko.observable("fall"), + printer_action: ko.observable("filament"), + temperature_sensor_navbar: ko.observable(true), + filament_sensor_timeout: ko.observable(120), + filament_sensor_enabled: ko.observable(true) }); }; self.removeRpiInput = function (definition) { - self.global_settings.settings.plugins.enclosure.rpi_inputs.remove(definition); + self.settingsViewModel.settings.plugins.enclosure.rpi_inputs.remove(definition); }; self.turnOffHeater = function () { @@ -209,7 +276,9 @@ $(function () { url: self.buildPluginUrl("/setEnclosureTemperature"), type: "GET", dataType: "json", - data: { "enclosureSetTemp": 0 }, + data: { + "enclosureSetTemp": 0 + }, success: function (data) { $("#enclosureSetTemp").val(''); $("#enclosureSetTemp").attr("placeholder", self.getCleanTemperature(data.enclosureSetTemperature)); @@ -223,7 +292,11 @@ $(function () { type: "GET", dataType: "json", success: function (data) { - new PNotify({ title: "Enclosure", text: "GPIO Mode cleared successfully", type: "success" }); + new PNotify({ + title: "Enclosure", + text: "GPIO Mode cleared successfully", + type: "success" + }); } }); }; @@ -256,7 +329,10 @@ $(function () { $.ajax({ type: "GET", dataType: "json", - data: { "io": data[0], "status": data[1] }, + data: { + "io": data[0], + "status": data[1] + }, url: self.buildPluginUrl("/setIO"), async: false }); @@ -264,18 +340,25 @@ $(function () { self.handlePWM = function (data, event) { io = parseInt(data[0]); - pwmVal = parseInt($("#dutycycle_" + io).val()); + pwmVal = parseInt($("#duty_cycle_" + io).val()); if (pwmVal < 0 || pwmVal > 100 || isNaN(pwmVal)) { - $("#dutycycle_" + io).val('') - new PNotify({ title: "Enclosure", text: "Duty Cycle value needs to be between 0 and 100!", type: "error" }); + $("#duty_cycle_" + io).val('') + new PNotify({ + title: "Enclosure", + text: "Duty Cycle value needs to be between 0 and 100!", + type: "error" + }); } else { // console.log(pwmVal); - $("#dutycycle_" + io).val('') - $("#dutycycle_" + io).attr("placeholder", pwmVal); + $("#duty_cycle_" + io).val('') + $("#duty_cycle_" + io).attr("placeholder", pwmVal); $.ajax({ type: "GET", dataType: "json", - data: { "io": io, "pwmVal": pwmVal }, + data: { + "io": io, + "pwmVal": pwmVal + }, url: self.buildPluginUrl("/setPWM"), }); } @@ -292,37 +375,26 @@ $(function () { b = parseInt(tempStr.substring(0, tempStr.indexOf(")"))); if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || isNaN(r) || isNaN(g) || isNaN(b)) { - new PNotify({ title: "Enclosure", text: "Color needs to follow the format rgb(value_red,value_green,value_blue)!", type: "error" }); + new PNotify({ + title: "Enclosure", + text: "Color needs to follow the format rgb(value_red,value_green,value_blue)!", + type: "error" + }); } else { $.ajax({ type: "GET", dataType: "json", - data: { "io": io, "red": r, "green": g, "blue": b }, + data: { + "io": io, + "red": r, + "green": g, + "blue": b + }, url: self.buildPluginUrl("/setNeopixel"), }); } }; - self.fixUI = function () { - if ($('#enableTemperatureReading').is(':checked')) { - $('#enableHeater').prop('disabled', false); - $('#temperature_reading_content').show("blind"); - // $('#temperature_control_content').show("blind"); - } else { - $('#enableHeater').prop('disabled', true); - $('#enableHeater').prop('checked', false); - $('#temperature_reading_content').hide("blind"); - // $('#temperature_control_content').hide("blind"); - } - - if ($('#enableHeater').is(':checked')) { - $('#temperature_control_content').show("blind"); - } else { - $('#temperature_control_content').hide("blind"); - } - - }; - self.isNumeric = function (n) { return !isNaN(parseFloat(n)) && isFinite(n); }; @@ -332,9 +404,12 @@ $(function () { }; } - OCTOPRINT_VIEWMODELS.push([ - EnclosureViewModel, - ["settingsViewModel", "connectionViewModel", "printerStateViewModel"], - ["#tab_plugin_enclosure", "#settings_plugin_enclosure", "#navbar_plugin_enclosure"] - ]); -}); + OCTOPRINT_VIEWMODELS.push({ + construct: EnclosureViewModel, + // ViewModels your plugin depends on, e.g. loginStateViewModel, settingsViewModel, ... + dependencies: ["settingsViewModel", "connectionViewModel", "printerStateViewModel"], + // Elements to bind to, e.g. #settings_plugin_tasmota-mqtt, #tab_plugin_tasmota-mqtt, ... + elements: ["#tab_plugin_enclosure", "#settings_plugin_enclosure", "#navbar_plugin_enclosure"] + }); + +}); \ No newline at end of file diff --git a/octoprint_enclosure/templates/enclosure_navbar.jinja2 b/octoprint_enclosure/templates/enclosure_navbar.jinja2 index ba43967..e69de29 100644 --- a/octoprint_enclosure/templates/enclosure_navbar.jinja2 +++ b/octoprint_enclosure/templates/enclosure_navbar.jinja2 @@ -1,8 +0,0 @@ - - - diff --git a/octoprint_enclosure/templates/enclosure_settings.jinja2 b/octoprint_enclosure/templates/enclosure_settings.jinja2 index 9963e4e..752348f 100644 --- a/octoprint_enclosure/templates/enclosure_settings.jinja2 +++ b/octoprint_enclosure/templates/enclosure_settings.jinja2 @@ -1,137 +1,13 @@ -
-

{{ _('Temperature Sensor') }}

-
-
- -
-
- - -
- -
- - GPIO pin for temperature sensor, recommended to use 4 as DS18B20 only works on pin 4 -
-
- - -
- -
- - GPIO pin for temperature sensor need to connect the sensor to I2C. SCL Clock to GPIO 3 (SCL) and SDA Data to GPIO - 2 (SDA) -
-
-
- -
- - Sensor address in HEX value, you can find it by runing - i2cdetect -y 1 on your Raspberry Pi -
-
- - -
- -
- - GPIO pin for temperature sensor, recommended to use 4 as DS18B20 only works on pin 4 -
-
- -
- - Choose if you want to work with Celsius or Fahrenheit -
-
-
-
- -
-

{{ _('Temperature Control') }}

-
-
-
- -
-
-
-
- -
- - GPIO pin used to control Heater. -
-
-
-
- - Active low means that the heater will turn on when receive a low signal (ground) from Raspbery PI -
-
-
- -
- -
-
- -
-
-
-
- - Choose if you want to automatically startup temperature control when the print starts -
-
- -
- -
- - Default temperature that temperature control will be set -
-
- -
-
-

{{ _('Raspberry Pi Outputs') }}

+

+ Configure all + outputs. Outputs can be everything that do actions based on UI button presses or automatic events or alarms. +

+

+ Example of possible outputs are gpio pins, neopixel LED's, temperature control or triggered gcode. +

-
+
@@ -139,154 +15,193 @@
-
-
- - - Info: WRITE SOMETHING HERE - Warning - - - - Info: TODO. - - - - Info: TODO - -
-
+
- +
Name displayed on Enclosure Tab
+ +
+ +
+ + Id used for API control +
+
+
- - + + GPIO number that will be controlled. - + Attention Neopixel requires a microcontroler (ex: arduino) connected to I2C bus. This is the pin on the - microcontroler that is connected to the Neopixel. + microcontroler that is connected to the Neopixel. +
-
- -
- - When the event happen, you want control which IO? -
-
+ +
Choose if GPIO should turn on automatomatically when print starts
- -
+ + +
- +
- - Time delay to turn on GPIO when print starts + + Time delay in secconds to turn on GPIO when print starts OR exact time that the event should happen, note that + events will only be scheduled after a print starts, time should be formated as HH:MM on a 24 hours format
+
Choose if GPIO should turn off automatomatically when print finishes
- -
+ + +
- +
- - Time delay to turn off GPIO when print finishes + + Time delay in secconds to turn on GPIO when print starts OR exact time that the event should happen, note that + events will only be scheduled after a print starts, time should be formated as HH:MM on a 24 hours format
- +
Active low means that the GPIO will turn on when receive a low signal (ground) from Raspbery PI
- + +
+ +
+ + Temperature sensor responsible for geting the value to be used. Configured on the input side of the plugin. +
+
+ + +
+ +
+ +
+
+ +
+
+
+ +
+ + Default temperature that temperature control will be set +
+
+
+ +
+ + Allowabe drift on temperature control. +
+
+ +
+ +
+ + Maximun temperature that the enclosure should reach, if this temperature is hit, the heater will be disabled. +
+
+ + +
- + Set temperature that will trigger the event
- When the event happen, you want control which IO?
@@ -294,7 +209,7 @@
- @@ -303,55 +218,65 @@
- +
- +
- + Value is in Hz
- + Value is in percentage, between 0 and 100
- +
- + Microcontroller address in HEX value, you can find it by runing i2cdetect -y 1 on your Raspberry Pi
- +
- + Number of led's on strip
- + Value between 0 and 255
- + Value needs to follow the format rgb(value_red,value_green,value_blue) where values should be between 0 and 255
+ +
+ +
+ + GCODE that will be sent to the printer. You should add + ENTER on the end of every line sent to the printer +
+
+

{{ _('Raspberry Pi Inputs') }}

+

+ Configure all + inputs. Inputs get data from gpio or connected sensors to provide additional functionality. Inputs can control + outputs or influence how they behave. +

+

+ Example of possible inputs are buttons connected to GPIO pins that control outputs or printer events, temperature and humidity + sensors, and filament sensors. +

-
+
- +
Name of Input
-
- {{ _('Printer') }} + {{ _('GPIO Input') }}
- {{ _('GPIO Control') }} + {{ _('Temperature Sensor') }}
- + Info: GPIO will input status of the pin, HIGH / LOW - + Info: Temperature Sensors will input temperature and humidity data. @@ -400,26 +333,100 @@
- + +
+ + +
+ +
+ + GPIO pin for temperature sensor, recommended to use 4 as DS18B20 has default support to pin #4 (BCM) +
+
+
+ +
+ + DS18B20 serial value, needs to be used to have support for multiple sensors, read documentation on github page + for more information +
+
+ + +
+ +
+ + GPIO pin for temperature sensor need to connect the sensor to I2C. SCL Clock to GPIO 3 (SCL) and SDA Data to GPIO + 2 (SDA) + +
+
+
+ +
+ + Sensor address in HEX value, you can find it by runing + i2cdetect -y 1 on your Raspberry Pi +
+
+ + +
+ +
+ + GPIO pin for temperature sensor, recommended to use 4 as DS18B20 only works on pin 4 +
+
+ +
+ + Choose if you want to work with Celsius or Fahrenheit +
+
+ +
- {{ _('Printer') }} + {{ _('GPIO Control') }}
- {{ _('GPIO Control') }} + {{ _('Printer') }}
- + - Info: PRINTER actions when a condition is met, that can be a filament sensor, button, - etc. Actions can be Pause \ Resume \ Cancel a printer job, change the filament or disable Temperature Control. - You can use the "change filament" action and set up the input GPIO acording to your sensor, for example, if your - filament sensor conects to ground when detects the end of the filament, you should choose PULL UP resistors and - detect the event on the falling edge. + Info: PRINTER actions when a condition is met, that can be a filament sensor, button, etc. Actions can + be Pause \ Resume \ Cancel a printer_control job, change the filament or disable Temperature Control. You can + use the "change filament" action and set up the input GPIO acording to your sensor, for example, if your filament + sensor conects to ground when detects the end of the filament, you should choose PULL UP resistors and detect + the event on the falling edge. - + Info: Action will control GPIO outputs when a condition is met, for example detect a press of a button. You can use this to control any previous configured OUTPUTS, basically beeing able to control your lights / fan @@ -430,12 +437,12 @@
- +
- + Input GPIO that will detect the event that should trigger the action. For example if you have a filament sensor you put the GPIO pin that the sensor is connected. This can also be a press of a button or any other signal that you want to detect. You can not use GPIO 4 here if you are using temeprature sensor DS18B20 @@ -444,18 +451,14 @@
- + + Choose what type of pull resistors that you want on the output. If you signal is active low, that means it should run the action when receive a low signal (ground), you should choose PULL UP resistors.
-
- - -
@@ -467,57 +470,74 @@ the action when receive a low signal (ground), you should choose FALLING EDGE.
-
- -
- - When the event happen, you want control which IO? -
-
-
- -
- - When the event happen, you want to turn the controlled IO HIGH or LOW? -
-
- - -
-
- -
- - Do you want thrigger the event on the rise or falling edge? If you signal is active low, that means it should run - the action when receive a low signal (ground), you should choose FALLING EDGE. -
+ +
+ +
+ + When the event happen, you want control which IO?
+
+ +
+ + When the event happen, you want to turn the controlled IO HIGH or LOW? +
+
+ +
- - + You can use filament change on your filament detectors and add buttons to resume and pause the print job.
+ +
+
+ + Enable and disable filament sensors +
+
+
+ +
+ + Time in seconds that filament sensor will be inactive after sensing end of filament. This is to avoid sending multiple + commands to the printer. + +
+
+ + + + +
+
+ + Enable and disable temperature on navbar +
+
- - - - Advanced options - -
-
-
-
- - Log additional information on octoprint log to help trouble shoot the plugin + + + + + Advanced options + +
+ +
+
+ + Log additional information on octoprint log to help trouble shoot the plugin +
-
-
-
- - Display enclosure temperature and humidity on navbar + +
+
+ + Log additional temperature readings on octoprint log to help trouble shoot the plugin +
-
-
-
- - Use BOARD pin numbers instead of BCM pin numbers + +
+
+ + Use BOARD pin numbers instead of BCM pin numbers +
-
-
-
- - This will clear any GPIO configuration that might exist on your system, use with caution, it might break other plugins - that use GPIO +
+
+ + This will clear any GPIO configuration that might exist on your system, use with caution, it might break other + plugins that use GPIO +
-
- -
- - Time that filament sensor will be inactive after sensing end of filament. This is to avoid sending multiple M600 commands - to the printer. -
-
- -
- - GCODE that will be sent to the printer to pause and allow filament to be changed. You should add - ; on the end of every line sent to the printer + +
+ +
+ + GCODE that will be sent to the printer to pause and allow filament to be changed. You should add + ENTER on the end of every line sent to the printer +
-
-
- -
- + +
+ +
+ +
-
- -
- -
- - Event name that was configured on the maker chanel of IFTTT, don't use space between the words + +
+ +
+ + Event name that was configured on the maker chanel of IFTTT, don't use space between the words +
-
-
- -
- +
+ +
+ +
-
-
-
- +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
-
- -
-
- -
-
- -
-
- -
-
- - -
\ No newline at end of file + + +
\ No newline at end of file diff --git a/octoprint_enclosure/templates/enclosure_tab.jinja2 b/octoprint_enclosure/templates/enclosure_tab.jinja2 index 47ae6b7..e69de29 100644 --- a/octoprint_enclosure/templates/enclosure_tab.jinja2 +++ b/octoprint_enclosure/templates/enclosure_tab.jinja2 @@ -1,94 +0,0 @@ -
-
-

{{ _('Enclosure Temperature') }}

- - - - - - - - - - - - - - - - -
{{ _('Actual') }}{{ _('Target') }}
{{ _('Enclosure') }} - - °F - °C - -
-
- - °F - °C -
- - - -
-
- -
-
{{ _('Humidity') }} - - % -
-
-
- - -
- -

- - - - -

- - - - - - -
{{ _('Duty Cycle:') }} - - - -
- - - -

- - - - - -
- - - -
- -
diff --git a/octoprint_enclosure/templates/enclosure_tab_temp.html b/octoprint_enclosure/templates/enclosure_tab_temp.html new file mode 100644 index 0000000..b1dbdeb --- /dev/null +++ b/octoprint_enclosure/templates/enclosure_tab_temp.html @@ -0,0 +1,98 @@ +
+
+

{{ _('Enclosure Temperature') }}

+ + + + + + + + + + + + + + + + +
{{ _('Actual') }}{{ _('Target') }}
{{ _('Enclosure') }} + + °F + °C + +
+
+ + °F + °C +
+ + + +
+
+ +
+
{{ _('Humidity') }} + + % +
+
+
+ + +
+ +

+

+

+ + + + +

+

+

+ + + + + + +
{{ _('Duty Cycle:') }} + + + +
+ + + +

+

+

+ + + + + +
+ + + +
+ +
\ No newline at end of file diff --git a/octoprint_enclosure/templates/navbar_temp.html b/octoprint_enclosure/templates/navbar_temp.html new file mode 100644 index 0000000..e848001 --- /dev/null +++ b/octoprint_enclosure/templates/navbar_temp.html @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/octoprint_enclosure/templates/settings_temp.html b/octoprint_enclosure/templates/settings_temp.html new file mode 100644 index 0000000..e69de29 diff --git a/octoprint_enclosure/templates/temp.html b/octoprint_enclosure/templates/temp.html new file mode 100644 index 0000000..1aa0754 --- /dev/null +++ b/octoprint_enclosure/templates/temp.html @@ -0,0 +1,131 @@ +
+

{{ _('Temperature Sensor') }}

+
+
+ +
+
+
+ +
+ + + Attention You need to install and configure the necessary libraries for the temperature sensor, check + the documentation on + github page +
+
+ +
+ +
+ + GPIO pin for temperature sensor, recommended to use 4 as DS18B20 only works on pin 4 +
+
+ + +
+ +
+ + GPIO pin for temperature sensor need to connect the sensor to I2C. SCL Clock to GPIO 3 (SCL) and SDA Data to GPIO + 2 (SDA) +
+
+
+ +
+ + Sensor address in HEX value, you can find it by runing + i2cdetect -y 1 on your Raspberry Pi +
+
+ + +
+ +
+ + GPIO pin for temperature sensor, recommended to use 4 as DS18B20 only works on pin 4 +
+
+ +
+ + Choose if you want to work with Celsius or Fahrenheit +
+
+
+
+ +
+

{{ _('Temperature Control') }}

+
+
+
+ +
+
+
+
+ +
+ + GPIO pin used to control Heater. +
+
+
+
+ + Active low means that the heater will turn on when receive a low signal (ground) from Raspbery PI +
+
+
+ +
+ +
+
+ +
+
+
+
+ + Choose if you want to automatically startup temperature control when the print starts +
+
+ +
+ +
+ + Default temperature that temperature control will be set +
+
+ +
+
+
\ No newline at end of file -- 2.39.5 From 0aad4ee49cb67c0315efd69d898823ad5c56f471 Mon Sep 17 00:00:00 2001 From: Vitor de Miranda Henrique Date: Wed, 7 Feb 2018 23:17:30 -0600 Subject: [PATCH 08/42] code review to line 888 --- octoprint_enclosure/__init__.py | 175 ++++++++++++++++++-------------- 1 file changed, 98 insertions(+), 77 deletions(-) diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index ccfc897..4499272 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -33,6 +33,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, event_queue = [] temperature_control_status = [] temperature_sensor_data = [] + last_filament_end_detected = [] def start_timer(self): """ @@ -152,7 +153,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, pwm_val = flask.request.values["pwmVal"] for rpi_output in self.rpi_outputs: if self.to_int(gpio_index) == self.to_int(rpi_output['index']): - self.write_pwm(self.to_int(rpi_output['gpio_pin']), self.to_int(pwm_val)) + self.write_pwm(self.to_int( + rpi_output['gpio_pin']), self.to_int(pwm_val)) return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/setNeopixel", methods=["GET"]) @@ -169,7 +171,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, address = rpi_output['microcontroller_address'] if not address: self.send_neopixel_command( - self.to_int(rpi_output['gpio_pin']), + self.to_int(rpi_output['gpio_pin']), led_count, led_brightness, red, green, blue, address) else: self.send_neopixel_command_direct( @@ -457,7 +459,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, temperature_control['gpio_pin']), val) for control_status in self.temperature_control_status: if control_status['index'] == temperature_control['index']: - self.temperature_control_status['status'] = current_status + control_status['status'] = current_status def start_gpio(self): try: @@ -495,19 +497,20 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def clear_gpio(self): try: - for control in self.temperature_control: - if control['isEnabled']: - GPIO.cleanup(self.to_int(control['gpio_pin'])) - for rpi_output in self.rpi_outputs: - if self.to_int(rpi_output['gpio_pin']) not in self.rpi_outputs_not_changed: - GPIO.cleanup(self.to_int(rpi_output['gpio_pin'])) - for rpi_input in self.rpi_inputs: + + for gpio_out in list(filter(lambda item: item['output_type'] == 'regular' or + item['output_type'] == 'pwm' or + item['output_type'] == 'temperature_control' or + item['output_type'] == 'neopixel_direct', self.rpi_outputs)): + GPIO.cleanup(self.to_int(gpio_out['gpio_pin'])) + + for gpio_in in list(filter(lambda item: item['input_type'] == 'gpio', self.rpi_inputs)): try: GPIO.remove_event_detect( - self.to_int(rpi_input['gpio_pin'])) + self.to_int(gpio_in['gpio_pin'])) except: pass - GPIO.cleanup(self.to_int(rpi_input['gpio_pin'])) + GPIO.cleanup(self.to_int(gpio_in['gpio_pin'])) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -535,38 +538,35 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def configure_gpio(self): try: - for control in self.temperature_control: - if control['isEnabled']: - GPIO.setup(self.to_int( - control['gpio_pin']), GPIO.OUT, initial=GPIO.HIGH if control['active_low'] else GPIO.LOW) - for rpi_output in self.rpi_outputs: - pin = self.to_int(rpi_output['gpio_pin']) - if rpi_output['output_type'] == 'regular': - if self.to_int(rpi_output['gpio_pin']) not in self.rpi_outputs_not_changed: - initialValue = GPIO.HIGH if rpi_output['active_low'] else GPIO.LOW - GPIO.setup(pin, GPIO.OUT, initial=initialValue) - if rpi_output['output_type'] == 'pwm': - for pwm in (pwm for pwm in self.pwm_intances if pin in pwm): - self.pwm_intances.remove(pwm) - self.clear_channel(pin) - GPIO.setup(pin, GPIO.OUT) - p = GPIO.PWM(pin, self.to_int(rpi_output['pwm_frequency'])) - self.pwm_intances.append({pin: p}) - if rpi_output['output_type'] == 'neopixel': - self.clear_channel(pin) - for rpi_input in self.rpi_inputs: - pullResistor = GPIO.PUD_UP if rpi_input[ - 'input_pull_resistor'] == 'input_pull_up' else GPIO.PUD_DOWN + + for gpio_out in list(filter(lambda item: item['output_type'] == 'regular' or + item['output_type'] == 'temperature_control', self.rpi_outputs)): + initialValue = GPIO.HIGH if gpio_out['active_low'] else GPIO.LOW + pin = self.to_int(gpio_out['gpio_pin']) + GPIO.setup(pin, GPIO.OUT, initial=initialValue) + for gpio_out_pwm in list(filter(lambda item: item['output_type'] == 'pwm', self.rpi_outputs)): + pin = self.to_int(gpio_out_pwm['gpio_pin']) + index = self.to_int(gpio_out_pwm['index']) + for pwm in (pwm_dict for pwm_dict in self.pwm_intances if index in pwm_dict): + self.pwm_intances.remove(pwm) + self.clear_channel(pin) + GPIO.setup(pin, GPIO.OUT) + pwm_instance = GPIO.PWM(pin, self.to_int( + gpio_out_pwm['pwm_frequency'])) + self.pwm_intances.append({index: pwm_instance}) + for gpio_out_neopixel in list(filter(lambda item: item['output_type'] == 'neopixel_direct', self.rpi_outputs)): + pin = self.to_int(gpio_out_neopixel['gpio_pin']) + self.clear_channel(pin) + + for rpi_input in list(filter(lambda item: item['input_type'] == 'gpio', self.rpi_inputs)): + pullResistor = GPIO.PUD_UP if rpi_input['input_pull_resistor'] == 'input_pull_up' else GPIO.PUD_DOWN GPIO.setup(self.to_int( rpi_input['gpio_pin']), GPIO.IN, pullResistor) - if rpi_input['action_type'] == 'gpio' and self.to_int(rpi_input['gpio_pin']) != 0: - edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING + edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING + if rpi_input['action_type'] == 'gpio_control': GPIO.add_event_detect(self.to_int( rpi_input['gpio_pin']), edge, callback=self.handle_gpio_control, bouncetime=200) - if (rpi_input['action_type'] == 'printer_control' and - rpi_input['printer_action'] != 'filament' and - self.to_int(rpi_input['gpio_pin']) != 0): - edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING + if (rpi_input['action_type'] == 'printer_control' and rpi_input['printer_action'] != 'filament'): GPIO.add_event_detect(self.to_int( rpi_input['gpio_pin']), edge, callback=self.handle_printer_action, bouncetime=200) except Exception as ex: @@ -578,13 +578,18 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_filamment_detection(self, channel): try: - for rpi_input in self.rpi_inputs: - if (channel == self.to_int(rpi_input['gpio_pin']) and rpi_input['action_type'] == 'printer_control' and - rpi_input['printer_action'] == 'filament' and - ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpio_pin'])))): - if time.time() - self.last_filament_end_detected > self._settings.get_int(["filamentSensorTimeout"]): + for filament_sensor in list(filter(lambda item: item['input_type'] == 'gpio' and + item['action_type'] == 'printer_control' and + item['printer_action'] == 'filament', self.rpi_inputs)): + if ((filament_sensor['edge'] == 'fall') ^ (GPIO.input(self.to_int(filament_sensor['gpio_pin']))) and + filament_sensor['filament_sensor_enabled']): + last_detected_time = list(filter(lambda item: item['index'] == filament_sensor['index'], + self.last_filament_end_detected)).pop()['time'] + if time.time() - last_detected_time > self._settings.get_int(["filament_sensor_timeout"]): self._logger.info("Detected end of filament.") - self.last_filament_end_detected = time.time() + for item in self.last_filament_end_detected: + if item['index'] == filament_sensor['index']: + item['time'] = time.time() for line in self._settings.get(["filament_sensor_gcode"]).split('\n'): if line: self._printer.commands(line.strip().upper()) @@ -594,7 +599,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for notification in self.notifications: if notification['filamentChange']: msg = "Filament change action caused by sensor: " + \ - str(rpi_input['label']) + str(filament_sensor['label']) self.send_notification(msg) else: self._logger.info( @@ -609,17 +614,18 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def start_filament_detection(self): self.stop_filament_detection() try: - for rpi_input in self.rpi_inputs: - if (rpi_input['action_type'] == 'printer_control' and - rpi_input['printer_action'] == 'filament' and - self.to_int(rpi_input['gpio_pin']) != 0): - edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING - if GPIO.input(self.to_int(rpi_input['gpio_pin'])) == (edge == GPIO.RISING): - self._printer.pause_print() - self._logger.info("Started printing with no filament.") - else: - GPIO.add_event_detect(self.to_int( - rpi_input['gpio_pin']), edge, callback=self.handle_filamment_detection, bouncetime=200) + for filament_sensor in list(filter(lambda item: item['input_type'] == 'gpio' and + item['action_type'] == 'printer_control' and + item['printer_action'] == 'filament', self.rpi_inputs)): + edge = GPIO.RISING if filament_sensor['edge'] == 'rise' else GPIO.FALLING + if GPIO.input(self.to_int(filament_sensor['gpio_pin'])) == (edge == GPIO.RISING): + self._printer.pause_print() + self._logger.info("Started printing with no filament.") + else: + self.last_filament_end_detected.append( + dict(index=filament_sensor['index'], time=0)) + GPIO.add_event_detect(self.to_int( + filament_sensor['gpio_pin']), edge, callback=self.handle_filamment_detection, bouncetime=200) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -629,10 +635,12 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def stop_filament_detection(self): try: - for rpi_input in self.rpi_inputs: - if rpi_input['action_type'] == 'printer_control' and rpi_input['printer_action'] == 'filament': - GPIO.remove_event_detect( - self.to_int(rpi_input['gpio_pin'])) + self.last_filament_end_detected = [] + for filament_sensor in list(filter(lambda item: item['input_type'] == 'gpio' and + item['action_type'] == 'printer_control' and + item['printer_action'] == 'filament', self.rpi_inputs)): + GPIO.remove_event_detect( + self.to_int(filament_sensor['gpio_pin'])) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -651,7 +659,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, rpi_input['action_type'] == 'gpio' and ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpio_pin'])))): for rpi_output in self.rpi_outputs: - if (self.to_int(rpi_input['controlled_io']) == self.to_int(rpi_output['gpio_pin']) and + if (self.to_int(rpi_input['controlled_io']) == self.to_int(rpi_output['index']) and rpi_output['output_type'] == 'regular'): if rpi_input['controlled_io_set_value'] == 'toggle': val = GPIO.LOW if GPIO.input(self.to_int( @@ -675,8 +683,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_printer_action(self, channel): try: for rpi_input in self.rpi_inputs: - if channel == self.to_int(rpi_input['gpio_pin']) and rpi_input['action_type'] == 'printer_control' and \ - ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpio_pin']))): + if (channel == self.to_int(rpi_input['gpio_pin']) and + rpi_input['action_type'] == 'printer_control' and + ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpio_pin'])))): if rpi_input['printer_action'] == 'resume': self._logger.info("Printer action resume.") self._printer.resume_print() @@ -739,15 +748,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def update_output_ui(self): try: - result = [] - result_pwm = [] + gpio_status = [] + pwm_status = [] for rpi_output in self.rpi_outputs: pin = self.to_int(rpi_output['gpio_pin']) if rpi_output['output_type'] == 'regular': val = GPIO.input(pin) if not rpi_output['active_low'] else ( not GPIO.input(pin)) - result.append({pin: val}) + gpio_status.append({pin: val}) if rpi_output['output_type'] == 'pwm': for pwm in self.pwm_intances: if pin in pwm: @@ -756,10 +765,25 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, val = self.to_int(pwmVal) else: val = 100 - result_pwm.append({pin: val}) + pwm_status.append({pin: val}) # self._logger.info("result_pwm: %s", result_pwm) self._plugin_manager.send_plugin_message( - self._identifier, dict(rpi_output=result, rpi_output_pwm=result_pwm)) + self._identifier, dict(rpi_output=gpio_status, rpi_output_pwm=pwm_status)) + except Exception as ex: + template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) + self._logger.warn(message) + pass + + def update_set_temperature(self): + try: + result = [] + for filament_sensor in list(filter(lambda item: item['output_type'] == 'temperature_control', self.rpi_outputs)): + result.append(dict( + index=filament_sensor['index'], temperature=filament_sensor['temperature_control_set_temperature'])) + self._plugin_manager.send_plugin_message( + self._identifier, dict(set_temperature=result)) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" message = template.format( @@ -855,15 +879,12 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.event_queue.append(threading.Timer(self.to_float(rpi_output['startup_time']), self.send_neopixel_command, args=[gpio_pin, ledCount, ledBrightness, red, green, blue, address])) + + if rpi_output['auto_startup'] and rpi_output['output_type'] == 'temperature_control': + rpi_output['temperature_control_set_temperature'] = rpi_output['temperature_control_default_temperature'] + self.update_set_temperature() for task in self.event_queue: task.start() - for control in self.temperature_control: - if control['auto_startup'] is True: - self.enclosure_set_temperature = self.to_int( - control['defaultTemp']) - self._plugin_manager.send_plugin_message( - self._identifier, dict(enclosureSetTemp=self.enclosure_set_temperature)) - elif event in (Events.PRINT_DONE, Events.PRINT_FAILED, Events.PRINT_CANCELLED): self.stop_filament_detection() self.enclosure_set_temperature = 0 -- 2.39.5 From 4496b32eae24d420065ecd7ebe56d88656e02ffe Mon Sep 17 00:00:00 2001 From: de Miranda Henrique Date: Thu, 15 Feb 2018 09:16:01 -0600 Subject: [PATCH 09/42] temperature setting working --- octoprint_enclosure/__init__.py | 229 +++++++++--------- octoprint_enclosure/static/css/enclosure.css | 42 ++++ octoprint_enclosure/static/js/enclosure.js | 220 ++++++++++------- .../templates/enclosure_settings.jinja2 | 8 +- .../templates/enclosure_tab.jinja2 | 74 ++++++ .../templates/enclosure_tab_temp.html | 3 +- octoprint_enclosure/templates/temp2.html | 64 +++++ 7 files changed, 437 insertions(+), 203 deletions(-) create mode 100644 octoprint_enclosure/static/css/enclosure.css create mode 100644 octoprint_enclosure/templates/temp2.html diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index 4499272..4d47335 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -16,6 +16,8 @@ import requests import inspect import threading +# 28-0000062410dc + class EnclosurePlugin(octoprint.plugin.StartupPlugin, octoprint.plugin.TemplatePlugin, @@ -77,25 +79,23 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.rpi_inputs = self._settings.get(["rpi_inputs"]) self.notifications = self._settings.get(["notifications"]) self.fix_data() + self.generate_temperature_control_status() self.rpi_outputs_not_changed = [] self.start_timer() - self.start_gpio() + self.setup_gpio() self.configure_gpio() self.update_output_ui() # ~~ Blueprintplugin mixin @octoprint.plugin.BlueprintPlugin.route("/setEnclosureTemperature", methods=["GET"]) def set_enclosure_temperature(self): - set_temperature = flask.request.values["set_temperature"] - index = flask.request.values["index"] - for temperature_control in list(filter(lambda item: - item['output_type'] == 'temperature_control' and - item['index'] == index, self.rpi_outputs)): + set_temperature = self.to_float(flask.request.values["set_temperature"]) + index_id = self.to_int(flask.request.values["index_id"]) + + for temperature_control in [item for item in self.rpi_outputs if item['index_id'] == index_id]: temperature_control['temperature_control_set_temperature'] = set_temperature - if self._settings.get(["debug"]) is True: - self._logger.info( - "DEBUG -> Seting output index %s to temperature: %s", index, set_temperature) - self.handle_temperature_control() + + # self.handle_temperature_control() return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/getEnclosureSetTemperature", methods=["GET"]) @@ -139,20 +139,20 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, @octoprint.plugin.BlueprintPlugin.route("/setIO", methods=["GET"]) def set_io(self): - gpio_index = flask.request.values["index"] + gpio_index = flask.request.values["index_id"] value = True if flask.request.values["status"] == "on" else False for rpi_output in self.rpi_outputs: - if self.to_int(gpio_index) == self.to_int(rpi_output['index']): + if self.to_int(gpio_index) == self.to_int(rpi_output['index_id']): val = (not value) if rpi_output['active_low'] else value self.write_gpio(self.to_int(rpi_output['gpio_pin']), val) return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/setPWM", methods=["GET"]) def set_pwm(self): - gpio_index = flask.request.values["index"] + gpio_index = flask.request.values["index_id"] pwm_val = flask.request.values["pwmVal"] for rpi_output in self.rpi_outputs: - if self.to_int(gpio_index) == self.to_int(rpi_output['index']): + if self.to_int(gpio_index) == self.to_int(rpi_output['index_id']): self.write_pwm(self.to_int( rpi_output['gpio_pin']), self.to_int(pwm_val)) return flask.jsonify(success=True) @@ -160,12 +160,12 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, @octoprint.plugin.BlueprintPlugin.route("/setNeopixel", methods=["GET"]) def set_neopixel(self): """ set_neopixel method get request from octoprint and send the comand to arduino or neopixel""" - gpio_index = flask.request.values["index"] + gpio_index = flask.request.values["index_id"] red = flask.request.values["red"] green = flask.request.values["green"] blue = flask.request.values["blue"] for rpi_output in self.rpi_outputs: - if self.to_int(gpio_index) == self.to_int(rpi_output['index']): + if self.to_int(gpio_index) == self.to_int(rpi_output['index_id']): led_count = rpi_output['neopixel_count'] led_brightness = rpi_output['neopixel_brightness'] address = rpi_output['microcontroller_address'] @@ -184,8 +184,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, """ Fix setting dada commin from old releases of the plugin""" if not self._settings.get(["settingsVersion"]) == "3.6": - self._settings.set(["rpi_outputs"], []) - self._settings.set(["rpi_inputs"], []) + # self._settings.set(["rpi_outputs"], []) + # self._settings.set(["rpi_inputs"], []) + # self.rpi_outputs = self._settings.get(["rpi_outputs"]) + # self.rpi_inputs = self._settings.get(["rpi_inputs"]) self._logger.warn("######### settings not compatible #########") def send_neopixel_command(self, led_pin, led_count, led_brightness, red, green, blue, address): @@ -210,7 +212,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("Sending neopixel cmd: %s", cmd) Popen(cmd, shell=True) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -237,7 +239,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("Sending neopixel cmd: %s", cmd) Popen(cmd, shell=True) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -246,21 +248,20 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def check_enclosure_temp(self): try: sensor_data = [] - for sensor in list( - filter(lambda item: item['input_type'] == 'temperature_sensor', self.rpi_inputs)): + for sensor in list(filter(lambda item: item['input_type'] == 'temperature_sensor', self.rpi_inputs)): temp, hum = self.get_sensor_data(sensor) if self._settings.get(["debug"]) is True and self._settings.get(["debug_temperature_log"]) is True: self._logger.info( "Sensor %s Temperature: %s humidity %s", sensor['label'], temp, hum) sensor_data.append( - dict(id=sensor['index'], temperature=temp, humidity=hum)) + dict(index_id=sensor['index_id'], temperature=temp, humidity=hum)) self._plugin_manager.send_plugin_message( self._identifier, dict(sensor_data=sensor_data)) self.temperature_sensor_data = sensor_data self.handle_temperature_control() - self.handle_temperature_events() + # self.handle_temperature_events() except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -273,7 +274,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, temp, hum = self.read_dht_temp( sensor['temperature_sensor_type'], sensor['gpio_pin']) elif sensor['temperature_sensor_type'] == "18b20": - temp = self.read_18b20_temp() + temp = self.read_18b20_temp(sensor['ds18b20_serial']) hum = 0 elif sensor['temperature_sensor_type'] == "bme280": temp, hum = self.read_bme280_temp( @@ -295,23 +296,22 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, hum = round(self.to_float(hum), 1) return temp, hum except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) pass def handle_temperature_events(self): - for temperature_alarm in list(filter(lambda item: item['output_type'] == 'temperature_alarm', self.rpi_outputs)): + for temperature_alarm in [item for item in self.rpi_outputs if item['output_type'] == 'temperature_alarm']: if self.to_float(temperature_alarm['alarm_set_temperature']) == 0: continue - linked_data = list(filter( - lambda sensor: sensor['index'] == temperature_alarm['linked_temperature_sensor'], - self.temperature_sensor_data)).pop() + linked_data = [item for item in self.temperature_sensor_data if item['index_id'] == + temperature_alarm['linked_temperature_sensor']].pop() sensor_temperature = linked_data['temperature'] if self.to_float(temperature_alarm['alarm_set_temperature']) < sensor_temperature: for rpi_controlled_output in self.rpi_outputs: - if self.to_int(temperature_alarm['controlled_io']) == self.to_int(rpi_controlled_output['index']): + if self.to_int(temperature_alarm['controlled_io']) == self.to_int(rpi_controlled_output['index_id']): val = GPIO.LOW if rpi_controlled_output['active_low'] else GPIO.HIGH self.write_gpio(self.to_int( rpi_controlled_output['gpio_pin']), val) @@ -334,7 +334,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, temp, hum = stdout.split("|") return (self.to_float(temp.strip()), self.to_float(hum.strip())) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -353,7 +353,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, temp, hum = stdout.split("|") return (self.to_float(temp.strip()), self.to_float(hum.strip())) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -372,20 +372,20 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, temp, hum = stdout.split("|") return (self.to_float(temp.strip()), self.to_float(hum.strip())) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) return (0, 0) - def read_18b20_temp(self): + def read_18b20_temp(self, serial_number): os.system('modprobe w1-gpio') os.system('modprobe w1-therm') - lines = self.read_raw_18b20_temp() + lines = self.read_raw_18b20_temp(serial_number) while lines[0].strip()[-3:] != 'YES': time.sleep(0.2) - lines = self.read_raw_18b20_temp() + lines = self.read_raw_18b20_temp(serial_number) equals_pos = lines[1].find('t=') if equals_pos != -1: temp_string = lines[1][equals_pos + 2:] @@ -393,9 +393,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, return '{0:0.1f}'.format(temp_c) return 0 - def read_raw_18b20_temp(self): + def read_raw_18b20_temp(self, serial_number): base_dir = '/sys/bus/w1/devices/' - device_folder = glob.glob(base_dir + '28*')[0] + device_folder = glob.glob(base_dir + str(serial_number) + '*')[0] device_file = device_folder + '/w1_slave' device_file_result = open(device_file, 'r') lines = device_file_result.readlines() @@ -414,54 +414,61 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("TMP102 result: %s", stdout) return self.to_float(stdout.strip()) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) return 0 def handle_temperature_control(self): - for temperature_control in list(filter(lambda item: - item['output_type'] == 'temperature_control', self.rpi_outputs)): + try: + for temperature_control in list(filter(lambda item: item['output_type'] == 'temperature_control', self.rpi_outputs)): - set_temperature = self.to_float( - temperature_control['temperature_control_set_temperature']) + set_temperature = self.to_float( + temperature_control['temperature_control_set_temperature']) - if set_temperature == 0: - current_status = False - else: - linked_data = list(filter(lambda sensor: - sensor['index'] == temperature_control['linked_temperature_sensor'], - self.temperature_sensor_data)).pop() - current_temperature = self.to_float(linked_data['temperature']) + linked_id = temperature_control['linked_temperature_sensor'] - current_status = set_temperature < current_temperature - - if temperature_control['temperature_control_type'] is 'cooler': - current_status != current_status - - previous_status = filter( - lambda item: item['index'] == temperature_control['index'], - self.temperature_control_status).pop()['status'] - - if current_status != previous_status: - if current_status: - self._logger.info( - "Turning gpio to control temperature on.") - val = False if temperature_control['active_low'] else True - self.write_gpio(self.to_int( - temperature_control['gpio_pin']), val) + if set_temperature == 0: + current_status = False else: - self._logger.info( - "Turning gpio to control temperature off.") - val = True if temperature_control['active_low'] else False - self.write_gpio(self.to_int( - temperature_control['gpio_pin']), val) - for control_status in self.temperature_control_status: - if control_status['index'] == temperature_control['index']: - control_status['status'] = current_status + linked_data = [ + data for data in self.temperature_sensor_data if data['index_id'] == linked_id].pop() - def start_gpio(self): + current_temperature = self.to_float(linked_data['temperature']) + + current_status = self.to_float(set_temperature) > self.to_float(current_temperature) + + if temperature_control['temperature_control_type'] is 'cooler': + current_status = not current_status + + previous_status = filter( + lambda item: item['index_id'] == temperature_control['index_id'], + self.temperature_control_status).pop()['status'] + + if current_status != previous_status: + if current_status: + self._logger.info( + "Turning gpio to control temperature on.") + val = False if temperature_control['active_low'] else True + self.write_gpio(self.to_int( + temperature_control['gpio_pin']), val) + else: + self._logger.info( + "Turning gpio to control temperature off.") + val = True if temperature_control['active_low'] else False + self.write_gpio(self.to_int( + temperature_control['gpio_pin']), val) + for control_status in self.temperature_control_status: + if control_status['index_id'] == temperature_control['index_id']: + control_status['status'] = current_status + except Exception as ex: + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) + self._logger.warn(message) + + def setup_gpio(self): try: currentMode = GPIO.getmode() setMode = GPIO.BOARD if self._settings.get( @@ -473,7 +480,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, item['output_type'] == 'neopixel_direct', self.rpi_outputs)) gpios.append(list(filter( lambda item: item['input_type'] == 'gpio', self.rpi_inputs))) - if gpios.count() > 0: + if gpios: GPIO.setmode(setMode) tempstr = "BOARD" if setMode == GPIO.BOARD else "BCM" self._logger.info("Setting GPIO mode to %s", tempstr) @@ -489,7 +496,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._identifier, dict(isMsg=True, msg=warn_msg)) GPIO.setwarnings(False) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -512,7 +519,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, pass GPIO.cleanup(self.to_int(gpio_in['gpio_pin'])) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -522,7 +529,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: GPIO.cleanup(self.to_int(channel)) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -533,7 +540,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for temperature_control in list(filter(lambda item: item['output_type'] == 'temperature_control', self.rpi_outputs)): status.append( - dict(index=temperature_control['index'], status=False)) + dict(index_id=temperature_control['index_id'], status=False)) self.temperature_control_status = status def configure_gpio(self): @@ -546,14 +553,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, GPIO.setup(pin, GPIO.OUT, initial=initialValue) for gpio_out_pwm in list(filter(lambda item: item['output_type'] == 'pwm', self.rpi_outputs)): pin = self.to_int(gpio_out_pwm['gpio_pin']) - index = self.to_int(gpio_out_pwm['index']) - for pwm in (pwm_dict for pwm_dict in self.pwm_intances if index in pwm_dict): + index_id = self.to_int(gpio_out_pwm['index_id']) + for pwm in (pwm_dict for pwm_dict in self.pwm_intances if index_id in pwm_dict): self.pwm_intances.remove(pwm) self.clear_channel(pin) GPIO.setup(pin, GPIO.OUT) pwm_instance = GPIO.PWM(pin, self.to_int( gpio_out_pwm['pwm_frequency'])) - self.pwm_intances.append({index: pwm_instance}) + self.pwm_intances.append({index_id: pwm_instance}) for gpio_out_neopixel in list(filter(lambda item: item['output_type'] == 'neopixel_direct', self.rpi_outputs)): pin = self.to_int(gpio_out_neopixel['gpio_pin']) self.clear_channel(pin) @@ -570,7 +577,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, GPIO.add_event_detect(self.to_int( rpi_input['gpio_pin']), edge, callback=self.handle_printer_action, bouncetime=200) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -580,15 +587,16 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, try: for filament_sensor in list(filter(lambda item: item['input_type'] == 'gpio' and item['action_type'] == 'printer_control' and - item['printer_action'] == 'filament', self.rpi_inputs)): + item['printer_action'] == 'filament' and + filament_sensor['gpio_pin'] == channel, self.rpi_inputs)): if ((filament_sensor['edge'] == 'fall') ^ (GPIO.input(self.to_int(filament_sensor['gpio_pin']))) and filament_sensor['filament_sensor_enabled']): - last_detected_time = list(filter(lambda item: item['index'] == filament_sensor['index'], + last_detected_time = list(filter(lambda item: item['index_id'] == filament_sensor['index_id'], self.last_filament_end_detected)).pop()['time'] if time.time() - last_detected_time > self._settings.get_int(["filament_sensor_timeout"]): self._logger.info("Detected end of filament.") for item in self.last_filament_end_detected: - if item['index'] == filament_sensor['index']: + if item['index_id'] == filament_sensor['index_id']: item['time'] = time.time() for line in self._settings.get(["filament_sensor_gcode"]).split('\n'): if line: @@ -605,7 +613,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info( "Prevented end of filament detection, filament sensor timeout not elapsed.") except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -623,11 +631,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("Started printing with no filament.") else: self.last_filament_end_detected.append( - dict(index=filament_sensor['index'], time=0)) + dict(index_id=filament_sensor['index_id'], time=0)) GPIO.add_event_detect(self.to_int( filament_sensor['gpio_pin']), edge, callback=self.handle_filamment_detection, bouncetime=200) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -642,7 +650,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, GPIO.remove_event_detect( self.to_int(filament_sensor['gpio_pin'])) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -659,7 +667,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, rpi_input['action_type'] == 'gpio' and ((rpi_input['edge'] == 'fall') ^ GPIO.input(self.to_int(rpi_input['gpio_pin'])))): for rpi_output in self.rpi_outputs: - if (self.to_int(rpi_input['controlled_io']) == self.to_int(rpi_output['index']) and + if (self.to_int(rpi_input['controlled_io']) == self.to_int(rpi_output['index_id']) and rpi_output['output_type'] == 'regular'): if rpi_input['controlled_io_set_value'] == 'toggle': val = GPIO.LOW if GPIO.input(self.to_int( @@ -674,7 +682,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, rpi_input['controlled_io']) + " to: " + str(rpi_input['controlled_io_set_value']) self.send_notification(msg) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -707,7 +715,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, " caused by input: " + str(rpi_input['label']) self.send_notification(msg) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -720,7 +728,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("Writing on gpio: %s value %s", gpio, value) self.update_output_ui() except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -740,7 +748,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.update_output_ui() break except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -770,7 +778,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._plugin_manager.send_plugin_message( self._identifier, dict(rpi_output=gpio_status, rpi_output_pwm=pwm_status)) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -781,11 +789,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, result = [] for filament_sensor in list(filter(lambda item: item['output_type'] == 'temperature_control', self.rpi_outputs)): result.append(dict( - index=filament_sensor['index'], temperature=filament_sensor['temperature_control_set_temperature'])) + index_id=filament_sensor['index_id'], temperature=filament_sensor['temperature_control_set_temperature'])) self._plugin_manager.send_plugin_message( self._identifier, dict(set_temperature=result)) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -827,7 +835,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for err in j['errors']: self._logger.info('Error: {}'.format(err['message'])) except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{1!r}" + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) self._logger.warn(message) @@ -870,11 +878,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, stringColor = rpi_output['neopixel_color'] stringColor = stringColor.replace('rgb(', '') - red = stringColor[:stringColor.index(',')] - stringColor = stringColor[stringColor.index(',') + 1:] - green = stringColor[:stringColor.index(',')] - stringColor = stringColor[stringColor.index(',') + 1:] - blue = stringColor[:stringColor.index(')')] + red = stringColor[:stringColor.index_id(',')] + stringColor = stringColor[stringColor.index_id(',') + 1:] + green = stringColor[:stringColor.index_id(',')] + stringColor = stringColor[stringColor.index_id(',') + 1:] + blue = stringColor[:stringColor.index_id(')')] self.event_queue.append(threading.Timer(self.to_float(rpi_output['startup_time']), self.send_neopixel_command, @@ -926,7 +934,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # ~~ SettingsPlugin mixin def on_settings_save(self, data): - self._logger.info("data: %s", data) + # self._logger.info("data: %s", data) outputsBeforeSave = self.get_output_list() octoprint.plugin.SettingsPlugin.on_settings_save(self, data) @@ -946,7 +954,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if self._settings.get(["debug"]) is True: self._logger.info("rpi_outputs: %s", self.rpi_outputs) self._logger.info("rpi_inputs: %s", self.rpi_inputs) - self.start_gpio() + self.setup_gpio() self.configure_gpio() self.generate_temperature_control_status() @@ -989,7 +997,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def get_assets(self): return dict( js=["js/enclosure.js", "js/bootstrap-colorpicker.min.js"], - css=["css/bootstrap-colorpicker.css"] + css=["css/bootstrap-colorpicker.css", "css/enclosure.css"], + less=['less/my_styles.less'] ) # ~~ Softwareupdate hook diff --git a/octoprint_enclosure/static/css/enclosure.css b/octoprint_enclosure/static/css/enclosure.css new file mode 100644 index 0000000..a7c0ce4 --- /dev/null +++ b/octoprint_enclosure/static/css/enclosure.css @@ -0,0 +1,42 @@ +#enclosure-table { + table-layout: fixed; + width: 100%; + margin-top: 20px; +} + +#enclosure-table th, +#enclosure-table td { + vertical-align: middle; + text-align: center; +} + + +#enclosure-table th.temperature_sensor, +#enclosure-table td.temperature_sensor { + width: 15%; + text-align: left; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +#enclosure-table th.temperature_actual, +#enclosure-table td.temperature_actual { + width: 20%; +} + +#enclosure-table th.humidity_actual, +#enclosure-table td.humidity_actual { + width: 20%; +} + +#enclosure-table th.temperature_control, +#enclosure-table td.temperature_control { + width: 15%; +} + +#enclosure-table th.temperature_target, +#enclosure-table td.temperature_target { + width: 30%; + overflow: visible; +} diff --git a/octoprint_enclosure/static/js/enclosure.js b/octoprint_enclosure/static/js/enclosure.js index 7463b6b..7a937fc 100644 --- a/octoprint_enclosure/static/js/enclosure.js +++ b/octoprint_enclosure/static/js/enclosure.js @@ -37,74 +37,100 @@ $(function () { self.notification_api_key = ko.observable(); self.notifications = ko.observable(); + self.humidityCapableSensor = function(sensor){ + if (['11', '22'].indexOf(sensor) >= 0){ + return true; + } + return false; + }; + + self.linkedTemperatureControl = function(sensor_index){ + return ko.pureComputed(function () { + return ko.utils.arrayFilter(self.settingsViewModel.settings.plugins.enclosure.rpi_outputs(), function (item) { + return (item.linked_temperature_sensor() == sensor_index); + }); + }); + }; + + self.hasAnySensorWithHumidity = function(){ + self.rpi_inputs_temperature_sensors().forEach(function (sensor) { + if (self.humidityCapableSensor(sensor.temperature_sensor_type())) { + return true; + } + }); + return false; + }; + self.onDataUpdaterPluginMessage = function (plugin, data) { if (plugin != "enclosure") { return; } - if (data.hasOwnProperty("enclosuretemp")) { - self.enclosureTemp(data.enclosuretemp); + if (data.hasOwnProperty("sensor_data")) { + data.sensor_data.forEach(function (sensor_data) { + var linked_temperature_sensor = ko.utils.arrayFilter(self.rpi_inputs(), function (temperature_sensor) { + return (sensor_data['id'] == temperature_sensor.index_id()); + }).pop(); - self.temperature_reading().forEach(function (element) { - if ("use_fahrenheit" in element) { - use_fahrenheit = element['use_fahrenheit']() - - if (use_fahrenheit) { - self.navbarTemp(_.sprintf("Enc: %.1f°F", data.enclosuretemp)); - } else { - self.navbarTemp(_.sprintf("Enc: %.1f°C", data.enclosuretemp)); - } + if (linked_temperature_sensor){ + linked_temperature_sensor.temperature_sensor_temperature(sensor_data['temperature']) + linked_temperature_sensor.temperature_sensor_humidity(sensor_data['humidity']) } - }); - } - - if (data.hasOwnProperty("enclosureHumidity")) { - self.enclosureHumidity(data.enclosureHumidity); - self.navbarHum(_.sprintf("Hum: %.1f%%", data.enclosureHumidity)); - } - if (data.hasOwnProperty("enclosureSetTemp")) { - if (parseFloat(data.enclosureSetTemp) > 0.0) { - $("#enclosureSetTemp").attr("placeholder", data.enclosureSetTemp); - } else { - $("#enclosureSetTemp").attr("placeholder", "off"); - } - } + }) + // linked_item.temperature_sensor_temperature() + }; - if (!data.rpi_output) { - data.rpi_output = self.previous_gpio_status; - } - if (!data.rpi_output_pwm) { - data.rpi_output_pwm = self.previous_gpio_pwm_status; - } - if (data.rpi_output) { - data.rpi_output.forEach(function (gpio) { - key = Object.keys(gpio)[0]; - if (gpio[key]) { - $("#btn_off_" + key).removeClass('active'); - $("#btn_on_" + key).addClass('active'); - } else { - $("#btn_off_" + key).addClass('active'); - $("#btn_on_" + key).removeClass('active'); - } - }); - self.previous_gpio_status = data.rpi_output; - } - if (data.rpi_output_pwm) { - data.rpi_output_pwm.forEach(function (gpio) { - key = Object.keys(gpio)[0]; - val = gpio[key]; - if (parseFloat(val) != 100) { - $("#duty_cycle_" + key).attr("placeholder", val); - } else { - $("#duty_cycle_" + key).attr("placeholder", "off"); - } - }); - self.previous_gpio_pwm_status = data.rpi_output_pwm; - } + // if (data.hasOwnProperty("enclosureHumidity")) { + // self.enclosureHumidity(data.enclosureHumidity); + // self.navbarHum(_.sprintf("Hum: %.1f%%", data.enclosureHumidity)); + // } + + // if (data.hasOwnProperty("enclosureSetTemp")) { + // if (parseFloat(data.enclosureSetTemp) > 0.0) { + // $("#enclosureSetTemp").attr("placeholder", data.enclosureSetTemp); + // } else { + // $("#enclosureSetTemp").attr("placeholder", "off"); + // } + // } + + // if (!data.rpi_output) { + // data.rpi_output = self.previous_gpio_status; + // } + + // if (!data.rpi_output_pwm) { + // data.rpi_output_pwm = self.previous_gpio_pwm_status; + // } + + // if (data.rpi_output) { + // data.rpi_output.forEach(function (gpio) { + // key = Object.keys(gpio)[0]; + // if (gpio[key]) { + // $("#btn_off_" + key).removeClass('active'); + // $("#btn_on_" + key).addClass('active'); + // } else { + // $("#btn_off_" + key).addClass('active'); + // $("#btn_on_" + key).removeClass('active'); + // } + // }); + // self.previous_gpio_status = data.rpi_output; + // } + + // if (data.rpi_output_pwm) { + // data.rpi_output_pwm.forEach(function (gpio) { + // key = Object.keys(gpio)[0]; + // val = gpio[key]; + // if (parseFloat(val) != 100) { + // $("#duty_cycle_" + key).attr("placeholder", val); + // } else { + // $("#duty_cycle_" + key).attr("placeholder", "off"); + // } + // }); + // self.previous_gpio_pwm_status = data.rpi_output_pwm; + // } if (data.isMsg) { new PNotify({ @@ -147,7 +173,8 @@ $(function () { }; self.onStartupComplete = function () { - // self.getUpdateBtnStatus(); + // var test = self.linkedTemperatureControl(1); + // console.log(test()); }; self.onDataUpdaterReconnect = function () { @@ -165,7 +192,7 @@ $(function () { } self.onSettingsHidden = function () { - self.getUpdateBtnStatus(); + // self.getUpdateBtnStatus(); }; self.getRegularOutputs = function () { @@ -173,34 +200,49 @@ $(function () { return rpi_outputs.output_type == 'regular'; }); }; - self.setTemperature = function () { - if (self.isNumeric($("#enclosureSetTemp").val())) { + self.setTemperature = function (item, form) { + + var newSetTemperature = item.temperature_control_new_temperature(); + if (form !== undefined) { + $(form).find("input").blur(); + } + + if(self.isNumeric(newSetTemperature)){ + var request = {set_temperature:newSetTemperature, index_id:item.index_id()}; $.ajax({ url: self.buildPluginUrl("/setEnclosureTemperature"), type: "GET", dataType: "json", - data: { - "enclosureSetTemp": Number($("#enclosureSetTemp").val()) - }, + data: request, success: function (data) { - $("#enclosureSetTemp").val(''); - cleanTemperature = self.getCleanTemperature(data.enclosureSetTemperature); - $("#enclosureSetTemp").attr("placeholder", cleanTemperature); - } + item.temperature_control_new_temperature(""); + item.temperature_control_set_temperature(newSetTemperature); + }, + error: function (textStatus, errorThrown) { + new PNotify({ + title: "Enclosure", + text: "Error setting temperature", + type: "error" + }); + } }); - } else { - alert("Temperature is not a number"); - } + }else{ + new PNotify({ + title: "Enclosure", + text: "Invalid set temperature", + type: "error" + }); + } }; self.addRpiOutput = function () { var arrRelaysLength = self.settingsViewModel.settings.plugins.enclosure.rpi_outputs().length; - var nextIndex = arrRelaysLength == 0 ? 1 : self.settingsViewModel.settings.plugins.enclosure.rpi_outputs()[arrRelaysLength - 1].index() + 1; + var nextIndex = arrRelaysLength == 0 ? 1 : self.settingsViewModel.settings.plugins.enclosure.rpi_outputs()[arrRelaysLength - 1].index_id() + 1; self.settingsViewModel.settings.plugins.enclosure.rpi_outputs.push({ - index: ko.observable(nextIndex), + index_id: ko.observable(nextIndex), label: ko.observable("Ouput " + nextIndex), output_type: ko.observable("regular"), gpio_pin: ko.observable(0), @@ -215,8 +257,9 @@ $(function () { linked_temperature_sensor: ko.observable(), alarm_set_temperature: ko.observable(0), temperature_control_type: ko.observable(""), - temperature_control_set_temperature: ko.observable(0), temperature_control_deadband: ko.observable(0), + temperature_control_set_temperature: ko.observable(0), + temperature_control_new_temperature: ko.observable(""), temperature_control_default_temperature: ko.observable(0), temperature_control_max_temperature: ko.observable(0), pwm_frequency: ko.observable(50), @@ -242,10 +285,10 @@ $(function () { var arrRelaysLength = self.settingsViewModel.settings.plugins.enclosure.rpi_inputs().length; - var nextIndex = arrRelaysLength == 0 ? 1 : self.settingsViewModel.settings.plugins.enclosure.rpi_inputs()[arrRelaysLength - 1].index() + 1; + var nextIndex = arrRelaysLength == 0 ? 1 : self.settingsViewModel.settings.plugins.enclosure.rpi_inputs()[arrRelaysLength - 1].index_id() + 1; self.settingsViewModel.settings.plugins.enclosure.rpi_inputs.push({ - index: ko.observable(nextIndex), + index_id: ko.observable(nextIndex), label: ko.observable("Input " + nextIndex), input_type: ko.observable("gpio"), gpio_pin: ko.observable(0), @@ -271,19 +314,20 @@ $(function () { self.settingsViewModel.settings.plugins.enclosure.rpi_inputs.remove(definition); }; - self.turnOffHeater = function () { - $.ajax({ - url: self.buildPluginUrl("/setEnclosureTemperature"), - type: "GET", - dataType: "json", - data: { - "enclosureSetTemp": 0 - }, - success: function (data) { - $("#enclosureSetTemp").val(''); - $("#enclosureSetTemp").attr("placeholder", self.getCleanTemperature(data.enclosureSetTemperature)); - } - }); + self.turnOffHeater = function (item) { + console.log(item); + // $.ajax({ + // url: self.buildPluginUrl("/setEnclosureTemperature"), + // type: "GET", + // dataType: "json", + // data: { + // "enclosureSetTemp": 0 + // }, + // success: function (data) { + // $("#enclosureSetTemp").val(''); + // $("#enclosureSetTemp").attr("placeholder", self.getCleanTemperature(data.enclosureSetTemperature)); + // } + // }); }; self.clearGPIOMode = function () { diff --git a/octoprint_enclosure/templates/enclosure_settings.jinja2 b/octoprint_enclosure/templates/enclosure_settings.jinja2 index 752348f..bb4a7ac 100644 --- a/octoprint_enclosure/templates/enclosure_settings.jinja2 +++ b/octoprint_enclosure/templates/enclosure_settings.jinja2 @@ -66,7 +66,7 @@
- + Id used for API control
@@ -146,7 +146,7 @@
Temperature sensor responsible for geting the value to be used. Configured on the input side of the plugin.
@@ -201,7 +201,7 @@
When the event happen, you want control which IO?
@@ -476,7 +476,7 @@
When the event happen, you want control which IO?
diff --git a/octoprint_enclosure/templates/enclosure_tab.jinja2 b/octoprint_enclosure/templates/enclosure_tab.jinja2 index e69de29..158e87b 100644 --- a/octoprint_enclosure/templates/enclosure_tab.jinja2 +++ b/octoprint_enclosure/templates/enclosure_tab.jinja2 @@ -0,0 +1,74 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ _('Temperature') }}{{ _('Humidity') }}{{ _('Control') }}{{ _('Target') }}
+ % + +
+
+ + °F + °C +
+
+ + + +
+
+
Set Temp
+ + + +
\ No newline at end of file diff --git a/octoprint_enclosure/templates/enclosure_tab_temp.html b/octoprint_enclosure/templates/enclosure_tab_temp.html index b1dbdeb..4a4196d 100644 --- a/octoprint_enclosure/templates/enclosure_tab_temp.html +++ b/octoprint_enclosure/templates/enclosure_tab_temp.html @@ -95,4 +95,5 @@ -
\ No newline at end of file +
+ diff --git a/octoprint_enclosure/templates/temp2.html b/octoprint_enclosure/templates/temp2.html new file mode 100644 index 0000000..bbba765 --- /dev/null +++ b/octoprint_enclosure/templates/temp2.html @@ -0,0 +1,64 @@ +{% if enableTemperatureGraph %} +
+
+
+{% endif %} + + +
+ + + + + + + + + + + + +
{{ _('Actual') }}{{ _('Target') }}{{ _('Offset') }}
+ + +
-- 2.39.5 From c1047d020c0cd53df6baee5c5bf1fa5fbb8afad5 Mon Sep 17 00:00:00 2001 From: Vitor de Miranda Henrique Date: Thu, 22 Feb 2018 23:05:06 -0600 Subject: [PATCH 10/42] output working --- octoprint_enclosure/__init__.py | 233 ++++----- .../static/css/bootstrap-colorpicker.css | 458 +++++++++--------- .../static/css/bootstrap2-toggle.css | 85 ++++ octoprint_enclosure/static/css/enclosure.css | 96 ++-- .../static/js/bootstrap-colorpicker.min.js | 8 +- .../static/js/bootstrap2-toggle.js | 180 +++++++ octoprint_enclosure/static/js/enclosure.js | 172 ++++--- .../templates/enclosure_settings.jinja2 | 34 +- .../templates/enclosure_tab.jinja2 | 187 ++++--- .../templates/enclosure_tab_temp.html | 62 +-- octoprint_enclosure/templates/temp2.html | 128 ++--- 11 files changed, 989 insertions(+), 654 deletions(-) create mode 100755 octoprint_enclosure/static/css/bootstrap2-toggle.css create mode 100755 octoprint_enclosure/static/js/bootstrap2-toggle.js diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index 4d47335..9d90c6f 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -73,50 +73,45 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # ~~ StartupPlugin mixin def on_after_startup(self): + self.fix_data() self.pwm_intances = [] self.event_queue = [] self.rpi_outputs = self._settings.get(["rpi_outputs"]) self.rpi_inputs = self._settings.get(["rpi_inputs"]) self.notifications = self._settings.get(["notifications"]) - self.fix_data() self.generate_temperature_control_status() self.rpi_outputs_not_changed = [] self.start_timer() self.setup_gpio() self.configure_gpio() - self.update_output_ui() + self.update_ui() # ~~ Blueprintplugin mixin @octoprint.plugin.BlueprintPlugin.route("/setEnclosureTemperature", methods=["GET"]) def set_enclosure_temperature(self): - set_temperature = self.to_float(flask.request.values["set_temperature"]) + set_temperature = self.to_float( + flask.request.values["set_temperature"]) index_id = self.to_int(flask.request.values["index_id"]) for temperature_control in [item for item in self.rpi_outputs if item['index_id'] == index_id]: - temperature_control['temperature_control_set_temperature'] = set_temperature + temperature_control['temp_ctr_set_temp'] = set_temperature - # self.handle_temperature_control() + self.handle_temperature_control() return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/getEnclosureSetTemperature", methods=["GET"]) def get_enclosure_set_temperature(self): - result = [] - for temperature_control_output in list(filter(lambda item: - item['output_type'] == 'temperature_control', - self.rpi_outputs)): - set_temperature = self.to_float( - temperature_control_output['temperature_control_set_temperature']) - result.append(set_temperature) - return flask.jsonify(result) + self.update_ui_set_temperature() + return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/clearGPIOMode", methods=["GET"]) def clear_gpio_mode(self): GPIO.cleanup() return flask.jsonify(success=True) - @octoprint.plugin.BlueprintPlugin.route("/updateBtnStatus", methods=["GET"]) - def get_update_btn_status(self): - self.update_output_ui() + @octoprint.plugin.BlueprintPlugin.route("/updateUI", methods=["GET"]) + def update_ui_requested(self): + self.update_ui() return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/getOutputStatus", methods=["GET"]) @@ -135,12 +130,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, @octoprint.plugin.BlueprintPlugin.route("/getEnclosureTemperature", methods=["GET"]) def get_enclosure_temperature(self): - return flask.jsonify(self.temperature_sensor_data) + self.update_ui_current_temperature() + return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/setIO", methods=["GET"]) def set_io(self): gpio_index = flask.request.values["index_id"] - value = True if flask.request.values["status"] == "on" else False + value = True if flask.request.values["status"] == 'true' else False for rpi_output in self.rpi_outputs: if self.to_int(gpio_index) == self.to_int(rpi_output['index_id']): val = (not value) if rpi_output['active_low'] else value @@ -255,11 +251,61 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, "Sensor %s Temperature: %s humidity %s", sensor['label'], temp, hum) sensor_data.append( dict(index_id=sensor['index_id'], temperature=temp, humidity=hum)) - self._plugin_manager.send_plugin_message( - self._identifier, dict(sensor_data=sensor_data)) self.temperature_sensor_data = sensor_data + self.update_ui() self.handle_temperature_control() - # self.handle_temperature_events() + self.handle_temperature_events() + except Exception as ex: + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) + self._logger.warn(message) + pass + + def update_ui(self): + self.update_ui_outputs() + self.update_ui_current_temperature() + self.update_ui_set_temperature() + + def update_ui_current_temperature(self): + self._plugin_manager.send_plugin_message( + self._identifier, dict(sensor_data=self.temperature_sensor_data)) + + def update_ui_set_temperature(self): + result = [] + for temp_crt_output in list(filter(lambda item: + item['output_type'] == 'temperature_control', + self.rpi_outputs)): + set_temperature = self.to_float( + temp_crt_output['temp_ctr_set_temp']) + result.append( + dict(index_id=temp_crt_output['index_id'], set_temperature=set_temperature)) + result.append(set_temperature) + self._plugin_manager.send_plugin_message( + self._identifier, dict(set_temperature=result)) + + def update_ui_outputs(self): + try: + gpio_status = [] + pwm_status = [] + for rpi_output in self.rpi_outputs: + index = self.to_int(rpi_output['index_id']) + pin = self.to_int(rpi_output['gpio_pin']) + if rpi_output['output_type'] == 'regular': + val = GPIO.input(pin) if not rpi_output['active_low'] else ( + not GPIO.input(pin)) + gpio_status.append(dict(index_id=index, status=val)) + if rpi_output['output_type'] == 'pwm': + for pwm in self.pwm_intances: + if pin in pwm: + if 'duty_cycle' in pwm: + pwmVal = pwm['duty_cycle'] + val = self.to_int(pwmVal) + else: + val = 100 + pwm_status.append(dict(index_id=index, pwm_value=val)) + self._plugin_manager.send_plugin_message( + self._identifier, dict(rpi_output=gpio_status, rpi_output_pwm=pwm_status)) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( @@ -269,25 +315,25 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def get_sensor_data(self, sensor): try: - if sensor['temperature_sensor_type'] in ["11", "22", "2302"]: - self._logger.info("temperature_sensor_type dht") + if sensor['temp_sensor_type'] in ["11", "22", "2302"]: + self._logger.info("temp_sensor_type dht") temp, hum = self.read_dht_temp( - sensor['temperature_sensor_type'], sensor['gpio_pin']) - elif sensor['temperature_sensor_type'] == "18b20": + sensor['temp_sensor_type'], sensor['gpio_pin']) + elif sensor['temp_sensor_type'] == "18b20": temp = self.read_18b20_temp(sensor['ds18b20_serial']) hum = 0 - elif sensor['temperature_sensor_type'] == "bme280": + elif sensor['temp_sensor_type'] == "bme280": temp, hum = self.read_bme280_temp( - sensor['temperature_sensor_address']) - elif sensor['temperature_sensor_type'] == "si7021": + sensor['temp_sensor_address']) + elif sensor['temp_sensor_type'] == "si7021": temp, hum = self.read_si7021_temp( - sensor['temperature_sensor_address']) - elif sensor['temperature_sensor_type'] == "tmp102": + sensor['temp_sensor_address']) + elif sensor['temp_sensor_type'] == "tmp102": temp = self.read_tmp102_temp( - sensor['temperature_sensor_address']) + sensor['temp_sensor_address']) hum = 0 else: - self._logger.info("temperature_sensor_type no match") + self._logger.info("temp_sensor_type no match") temp = 0 hum = 0 if temp != -1 and hum != -1: @@ -304,12 +350,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_temperature_events(self): for temperature_alarm in [item for item in self.rpi_outputs if item['output_type'] == 'temperature_alarm']: - if self.to_float(temperature_alarm['alarm_set_temperature']) == 0: + set_temperature = self.to_float( + temperature_alarm['alarm_set_temp']) + if int(set_temperature) is 0: continue linked_data = [item for item in self.temperature_sensor_data if item['index_id'] == - temperature_alarm['linked_temperature_sensor']].pop() - sensor_temperature = linked_data['temperature'] - if self.to_float(temperature_alarm['alarm_set_temperature']) < sensor_temperature: + temperature_alarm['linked_temp_sensor']].pop() + sensor_temperature = self.to_float(linked_data['temperature']) + if set_temperature < sensor_temperature: for rpi_controlled_output in self.rpi_outputs: if self.to_int(temperature_alarm['controlled_io']) == self.to_int(rpi_controlled_output['index_id']): val = GPIO.LOW if rpi_controlled_output['active_low'] else GPIO.HIGH @@ -425,9 +473,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, for temperature_control in list(filter(lambda item: item['output_type'] == 'temperature_control', self.rpi_outputs)): set_temperature = self.to_float( - temperature_control['temperature_control_set_temperature']) + temperature_control['temp_ctr_set_temp']) + temp_deadband = self.to_float( + temperature_control['temp_ctr_deadband']) + max_temp = self.to_float( + temperature_control['temp_ctr_max_temp']) - linked_id = temperature_control['linked_temperature_sensor'] + linked_id = temperature_control['linked_temp_sensor'] + + previous_status = filter( + lambda item: item['index_id'] == temperature_control['index_id'], + self.temperature_control_status).pop()['status'] if set_temperature == 0: current_status = False @@ -435,17 +491,22 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, linked_data = [ data for data in self.temperature_sensor_data if data['index_id'] == linked_id].pop() - current_temperature = self.to_float(linked_data['temperature']) + current_temperature = self.to_float( + linked_data['temperature']) - current_status = self.to_float(set_temperature) > self.to_float(current_temperature) + if set_temperature - temp_deadband > current_temperature: + current_status = True + elif set_temperature + temp_deadband < current_temperature: + current_status = False + else: + current_status = previous_status - if temperature_control['temperature_control_type'] is 'cooler': + if temperature_control['temp_ctr_type'] is 'cooler': current_status = not current_status - previous_status = filter( - lambda item: item['index_id'] == temperature_control['index_id'], - self.temperature_control_status).pop()['status'] - + if temperature_control['temp_ctr_type'] is 'heater' and int(max_temp) is not 0 and max_temp < current_temperature: + temperature_control['temp_ctr_set_temp'] = 0 + current_status = False if current_status != previous_status: if current_status: self._logger.info( @@ -463,10 +524,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if control_status['index_id'] == temperature_control['index_id']: control_status['status'] = current_status except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" - message = template.format( - type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) - self._logger.warn(message) + template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" + message = template.format( + type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) + self._logger.warn(message) def setup_gpio(self): try: @@ -474,12 +535,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, setMode = GPIO.BOARD if self._settings.get( ["useBoardPinNumber"]) else GPIO.BCM if currentMode is None: - gpios = list(filter(lambda item: item['output_type'] == 'regular' or - item['output_type'] == 'pwm' or - item['output_type'] == 'temperature_control' or - item['output_type'] == 'neopixel_direct', self.rpi_outputs)) - gpios.append(list(filter( - lambda item: item['input_type'] == 'gpio', self.rpi_inputs))) + outputs = list(filter(lambda item: item['output_type'] == 'regular' or + item['output_type'] == 'pwm' or + item['output_type'] == 'temperature_control' or + item['output_type'] == 'neopixel_direct', self.rpi_outputs)) + inputs = list(filter( + lambda item: item['input_type'] == 'gpio', self.rpi_inputs)) + gpios = outputs + inputs if gpios: GPIO.setmode(setMode) tempstr = "BOARD" if setMode == GPIO.BOARD else "BCM" @@ -726,7 +788,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, GPIO.output(gpio, value) if self._settings.get(["debug"]) is True: self._logger.info("Writing on gpio: %s value %s", gpio, value) - self.update_output_ui() + self.update_ui() except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( @@ -745,7 +807,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if self._settings.get(["debug"]) is True: self._logger.info( "Writing PWM on gpio: %s value %s", gpio, pwmValue) - self.update_output_ui() + self.update_ui() break except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" @@ -754,51 +816,6 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def update_output_ui(self): - try: - gpio_status = [] - pwm_status = [] - - for rpi_output in self.rpi_outputs: - pin = self.to_int(rpi_output['gpio_pin']) - if rpi_output['output_type'] == 'regular': - val = GPIO.input(pin) if not rpi_output['active_low'] else ( - not GPIO.input(pin)) - gpio_status.append({pin: val}) - if rpi_output['output_type'] == 'pwm': - for pwm in self.pwm_intances: - if pin in pwm: - if 'duty_cycle' in pwm: - pwmVal = pwm['duty_cycle'] - val = self.to_int(pwmVal) - else: - val = 100 - pwm_status.append({pin: val}) - # self._logger.info("result_pwm: %s", result_pwm) - self._plugin_manager.send_plugin_message( - self._identifier, dict(rpi_output=gpio_status, rpi_output_pwm=pwm_status)) - except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" - message = template.format( - type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) - self._logger.warn(message) - pass - - def update_set_temperature(self): - try: - result = [] - for filament_sensor in list(filter(lambda item: item['output_type'] == 'temperature_control', self.rpi_outputs)): - result.append(dict( - index_id=filament_sensor['index_id'], temperature=filament_sensor['temperature_control_set_temperature'])) - self._plugin_manager.send_plugin_message( - self._identifier, dict(set_temperature=result)) - except Exception as ex: - template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" - message = template.format( - type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) - self._logger.warn(message) - pass - def get_output_list(self): result = [] for rpi_output in self.rpi_outputs: @@ -851,7 +868,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def on_event(self, event, payload): if event == Events.CONNECTED: - self.update_output_ui() + self.update_ui() if event == Events.PRINT_RESUMED: self.start_filament_detection() @@ -889,7 +906,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, args=[gpio_pin, ledCount, ledBrightness, red, green, blue, address])) if rpi_output['auto_startup'] and rpi_output['output_type'] == 'temperature_control': - rpi_output['temperature_control_set_temperature'] = rpi_output['temperature_control_default_temperature'] + rpi_output['temp_ctr_set_temp'] = rpi_output['temp_ctr_default_temp'] self.update_set_temperature() for task in self.event_queue: task.start() @@ -933,9 +950,6 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # ~~ SettingsPlugin mixin def on_settings_save(self, data): - - # self._logger.info("data: %s", data) - outputsBeforeSave = self.get_output_list() octoprint.plugin.SettingsPlugin.on_settings_save(self, data) self.rpi_outputs = self._settings.get(["rpi_outputs"]) @@ -996,9 +1010,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # ~~ AssetPlugin mixin def get_assets(self): return dict( - js=["js/enclosure.js", "js/bootstrap-colorpicker.min.js"], - css=["css/bootstrap-colorpicker.css", "css/enclosure.css"], - less=['less/my_styles.less'] + js=["js/enclosure.js", "js/bootstrap-colorpicker.min.js", "js/bootstrap2-toggle.js"], + css=["css/bootstrap-colorpicker.css", "css/enclosure.css", "css/bootstrap2-toggle.css"] ) # ~~ Softwareupdate hook diff --git a/octoprint_enclosure/static/css/bootstrap-colorpicker.css b/octoprint_enclosure/static/css/bootstrap-colorpicker.css index 2429962..26cb0de 100755 --- a/octoprint_enclosure/static/css/bootstrap-colorpicker.css +++ b/octoprint_enclosure/static/css/bootstrap-colorpicker.css @@ -1,230 +1,230 @@ -/*! - * Bootstrap Colorpicker v2.5.1 - * https://itsjavi.com/bootstrap-colorpicker/ - * - * Originally written by (c) 2012 Stefan Petre - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0.txt - * - */ -.colorpicker-saturation { - width: 100px; - height: 100px; - background-image: url("../img/bootstrap-colorpicker/saturation.png"); - cursor: crosshair; - float: left; -} -.colorpicker-saturation i { - display: block; - height: 5px; - width: 5px; - border: 1px solid #000; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; - position: absolute; - top: 0; - left: 0; - margin: -4px 0 0 -4px; -} -.colorpicker-saturation i b { - display: block; - height: 5px; - width: 5px; - border: 1px solid #fff; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} -.colorpicker-hue, -.colorpicker-alpha { - width: 15px; - height: 100px; - float: left; - cursor: row-resize; - margin-left: 4px; - margin-bottom: 4px; -} -.colorpicker-hue i, -.colorpicker-alpha i { - display: block; - height: 1px; - background: #000; - border-top: 1px solid #fff; - position: absolute; - top: 0; - left: 0; - width: 100%; - margin-top: -1px; -} -.colorpicker-hue { - background-image: url("../img/bootstrap-colorpicker/hue.png"); -} -.colorpicker-alpha { - background-image: url("../img/bootstrap-colorpicker/alpha.png"); - display: none; -} -.colorpicker-saturation, -.colorpicker-hue, -.colorpicker-alpha { - background-size: contain; -} -.colorpicker { - padding: 4px; - min-width: 130px; - margin-top: 1px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - z-index: 2500; -} -.colorpicker:before, -.colorpicker:after { - display: table; - content: ""; - line-height: 0; -} -.colorpicker:after { - clear: both; -} -.colorpicker:before { - content: ''; - display: inline-block; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-bottom-color: rgba(0, 0, 0, 0.2); - position: absolute; - top: -7px; - left: 6px; -} -.colorpicker:after { - content: ''; - display: inline-block; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - position: absolute; - top: -6px; - left: 7px; -} -.colorpicker div { - position: relative; -} -.colorpicker.colorpicker-with-alpha { - min-width: 140px; -} -.colorpicker.colorpicker-with-alpha .colorpicker-alpha { - display: block; -} -.colorpicker-color { - height: 10px; - margin-top: 5px; - clear: both; - background-image: url("../img/bootstrap-colorpicker/alpha.png"); - background-position: 0 100%; -} -.colorpicker-color div { - height: 10px; -} -.colorpicker-selectors { - display: none; - height: 10px; - margin-top: 5px; - clear: both; -} -.colorpicker-selectors i { - cursor: pointer; - float: left; - height: 10px; - width: 10px; -} -.colorpicker-selectors i + i { - margin-left: 3px; -} -.colorpicker-element .input-group-addon i, -.colorpicker-element .add-on i { - display: inline-block; - cursor: pointer; - height: 16px; - vertical-align: text-top; - width: 16px; -} -.colorpicker.colorpicker-inline { - position: relative; - display: inline-block; - float: none; - z-index: auto; -} -.colorpicker.colorpicker-horizontal { - width: 110px; - min-width: 110px; - height: auto; -} -.colorpicker.colorpicker-horizontal .colorpicker-saturation { - margin-bottom: 4px; -} -.colorpicker.colorpicker-horizontal .colorpicker-color { - width: 100px; -} -.colorpicker.colorpicker-horizontal .colorpicker-hue, -.colorpicker.colorpicker-horizontal .colorpicker-alpha { - width: 100px; - height: 15px; - float: left; - cursor: col-resize; - margin-left: 0px; - margin-bottom: 4px; -} -.colorpicker.colorpicker-horizontal .colorpicker-hue i, -.colorpicker.colorpicker-horizontal .colorpicker-alpha i { - display: block; - height: 15px; - background: #ffffff; - position: absolute; - top: 0; - left: 0; - width: 1px; - border: none; - margin-top: 0px; -} -.colorpicker.colorpicker-horizontal .colorpicker-hue { - background-image: url("../img/bootstrap-colorpicker/hue-horizontal.png"); -} -.colorpicker.colorpicker-horizontal .colorpicker-alpha { - background-image: url("../img/bootstrap-colorpicker/alpha-horizontal.png"); -} -.colorpicker-right:before { - left: auto; - right: 6px; -} -.colorpicker-right:after { - left: auto; - right: 7px; -} -.colorpicker-no-arrow:before { - border-right: 0; - border-left: 0; -} -.colorpicker-no-arrow:after { - border-right: 0; - border-left: 0; -} -.colorpicker.colorpicker-visible, -.colorpicker-alpha.colorpicker-visible, -.colorpicker-saturation.colorpicker-visible, -.colorpicker-hue.colorpicker-visible, -.colorpicker-selectors.colorpicker-visible { - display: block; -} -.colorpicker.colorpicker-hidden, -.colorpicker-alpha.colorpicker-hidden, -.colorpicker-saturation.colorpicker-hidden, -.colorpicker-hue.colorpicker-hidden, -.colorpicker-selectors.colorpicker-hidden { - display: none; -} -.colorpicker-inline.colorpicker-visible { - display: inline-block; -} +/*! + * Bootstrap Colorpicker v2.5.1 + * https://itsjavi.com/bootstrap-colorpicker/ + * + * Originally written by (c) 2012 Stefan Petre + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + */ +.colorpicker-saturation { + width: 100px; + height: 100px; + background-image: url("../img/bootstrap-colorpicker/saturation.png"); + cursor: crosshair; + float: left; +} +.colorpicker-saturation i { + display: block; + height: 5px; + width: 5px; + border: 1px solid #000; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + position: absolute; + top: 0; + left: 0; + margin: -4px 0 0 -4px; +} +.colorpicker-saturation i b { + display: block; + height: 5px; + width: 5px; + border: 1px solid #fff; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} +.colorpicker-hue, +.colorpicker-alpha { + width: 15px; + height: 100px; + float: left; + cursor: row-resize; + margin-left: 4px; + margin-bottom: 4px; +} +.colorpicker-hue i, +.colorpicker-alpha i { + display: block; + height: 1px; + background: #000; + border-top: 1px solid #fff; + position: absolute; + top: 0; + left: 0; + width: 100%; + margin-top: -1px; +} +.colorpicker-hue { + background-image: url("../img/bootstrap-colorpicker/hue.png"); +} +.colorpicker-alpha { + background-image: url("../img/bootstrap-colorpicker/alpha.png"); + display: none; +} +.colorpicker-saturation, +.colorpicker-hue, +.colorpicker-alpha { + background-size: contain; +} +.colorpicker { + padding: 4px; + min-width: 130px; + margin-top: 1px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + z-index: 2500; +} +.colorpicker:before, +.colorpicker:after { + display: table; + content: ""; + line-height: 0; +} +.colorpicker:after { + clear: both; +} +.colorpicker:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 6px; +} +.colorpicker:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; + top: -6px; + left: 7px; +} +.colorpicker div { + position: relative; +} +.colorpicker.colorpicker-with-alpha { + min-width: 140px; +} +.colorpicker.colorpicker-with-alpha .colorpicker-alpha { + display: block; +} +.colorpicker-color { + height: 10px; + margin-top: 5px; + clear: both; + background-image: url("../img/bootstrap-colorpicker/alpha.png"); + background-position: 0 100%; +} +.colorpicker-color div { + height: 10px; +} +.colorpicker-selectors { + display: none; + height: 10px; + margin-top: 5px; + clear: both; +} +.colorpicker-selectors i { + cursor: pointer; + float: left; + height: 10px; + width: 10px; +} +.colorpicker-selectors i + i { + margin-left: 3px; +} +.colorpicker-element .input-group-addon i, +.colorpicker-element .add-on i { + display: inline-block; + cursor: pointer; + height: 16px; + vertical-align: text-top; + width: 16px; +} +.colorpicker.colorpicker-inline { + position: relative; + display: inline-block; + float: none; + z-index: auto; +} +.colorpicker.colorpicker-horizontal { + width: 110px; + min-width: 110px; + height: auto; +} +.colorpicker.colorpicker-horizontal .colorpicker-saturation { + margin-bottom: 4px; +} +.colorpicker.colorpicker-horizontal .colorpicker-color { + width: 100px; +} +.colorpicker.colorpicker-horizontal .colorpicker-hue, +.colorpicker.colorpicker-horizontal .colorpicker-alpha { + width: 100px; + height: 15px; + float: left; + cursor: col-resize; + margin-left: 0px; + margin-bottom: 4px; +} +.colorpicker.colorpicker-horizontal .colorpicker-hue i, +.colorpicker.colorpicker-horizontal .colorpicker-alpha i { + display: block; + height: 15px; + background: #ffffff; + position: absolute; + top: 0; + left: 0; + width: 1px; + border: none; + margin-top: 0px; +} +.colorpicker.colorpicker-horizontal .colorpicker-hue { + background-image: url("../img/bootstrap-colorpicker/hue-horizontal.png"); +} +.colorpicker.colorpicker-horizontal .colorpicker-alpha { + background-image: url("../img/bootstrap-colorpicker/alpha-horizontal.png"); +} +.colorpicker-right:before { + left: auto; + right: 6px; +} +.colorpicker-right:after { + left: auto; + right: 7px; +} +.colorpicker-no-arrow:before { + border-right: 0; + border-left: 0; +} +.colorpicker-no-arrow:after { + border-right: 0; + border-left: 0; +} +.colorpicker.colorpicker-visible, +.colorpicker-alpha.colorpicker-visible, +.colorpicker-saturation.colorpicker-visible, +.colorpicker-hue.colorpicker-visible, +.colorpicker-selectors.colorpicker-visible { + display: block; +} +.colorpicker.colorpicker-hidden, +.colorpicker-alpha.colorpicker-hidden, +.colorpicker-saturation.colorpicker-hidden, +.colorpicker-hue.colorpicker-hidden, +.colorpicker-selectors.colorpicker-hidden { + display: none; +} +.colorpicker-inline.colorpicker-visible { + display: inline-block; +} /*# sourceMappingURL=bootstrap-colorpicker.css.map */ \ No newline at end of file diff --git a/octoprint_enclosure/static/css/bootstrap2-toggle.css b/octoprint_enclosure/static/css/bootstrap2-toggle.css new file mode 100755 index 0000000..3f48927 --- /dev/null +++ b/octoprint_enclosure/static/css/bootstrap2-toggle.css @@ -0,0 +1,85 @@ +/*! ======================================================================== + * Bootstrap Toggle: bootstrap2-toggle.css v2.2.0 + * http://www.bootstraptoggle.com + * ======================================================================== + * Copyright 2014 Min Hur, The New York Times Company + * Licensed under MIT + * ======================================================================== */ + + +label.checkbox .toggle, +label.checkbox.inline .toggle { + margin-left: -20px; + margin-right: 5px; +} +.toggle { + min-width: 40px; + height: 20px; + position: relative; + overflow: hidden; +} +.toggle input[type="checkbox"] { + display: none; +} +.toggle-group { + position: absolute; + width: 200%; + top: 0; + bottom: 0; + left: 0; + transition: left 0.35s; + -webkit-transition: left 0.35s; + -moz-user-select: none; + -webkit-user-select: none; +} +.toggle.off .toggle-group { + left: -100%; +} +.toggle-on { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 50%; + margin: 0; + border: 0; + border-radius: 0; +} +.toggle-off { + position: absolute; + top: 0; + bottom: 0; + left: 50%; + right: 0; + margin: 0; + border: 0; + border-radius: 0; +} +.toggle-handle { + position: relative; + margin: 0 auto; + padding-top: 0px; + padding-bottom: 0px; + height: 100%; + width: 0px; + border-width: 0 1px; +} +.toggle-handle.btn-mini { + top: -1px; +} +.toggle.btn { min-width: 30px; } +.toggle-on.btn { padding-right: 24px; } +.toggle-off.btn { padding-left: 24px; } + +.toggle.btn-large { min-width: 40px; } +.toggle-on.btn-large { padding-right: 35px; } +.toggle-off.btn-large { padding-left: 35px; } + +.toggle.btn-small { min-width: 25px; } +.toggle-on.btn-small { padding-right: 20px; } +.toggle-off.btn-small { padding-left: 20px; } + +.toggle.btn-mini { min-width: 20px; } +.toggle-on.btn-mini { padding-right: 12px; } +.toggle-off.btn-mini { padding-left: 12px; } + diff --git a/octoprint_enclosure/static/css/enclosure.css b/octoprint_enclosure/static/css/enclosure.css index a7c0ce4..8e090c4 100644 --- a/octoprint_enclosure/static/css/enclosure.css +++ b/octoprint_enclosure/static/css/enclosure.css @@ -1,42 +1,54 @@ -#enclosure-table { - table-layout: fixed; - width: 100%; - margin-top: 20px; -} - -#enclosure-table th, -#enclosure-table td { - vertical-align: middle; - text-align: center; -} - - -#enclosure-table th.temperature_sensor, -#enclosure-table td.temperature_sensor { - width: 15%; - text-align: left; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -#enclosure-table th.temperature_actual, -#enclosure-table td.temperature_actual { - width: 20%; -} - -#enclosure-table th.humidity_actual, -#enclosure-table td.humidity_actual { - width: 20%; -} - -#enclosure-table th.temperature_control, -#enclosure-table td.temperature_control { - width: 15%; -} - -#enclosure-table th.temperature_target, -#enclosure-table td.temperature_target { - width: 30%; - overflow: visible; -} +#enclosure-table { + table-layout: fixed; + width: 100%; + margin-top: 20px; +} + +#enclosure-table th, +#enclosure-table td { + vertical-align: middle; + text-align: center; +} + + +#enclosure-table th.temperature_sensor, +#enclosure-table td.temperature_sensor { + width: 15%; + text-align: left; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +#enclosure-table th.temperature_actual, +#enclosure-table td.temperature_actual { + width: 20%; +} + +#enclosure-table th.humidity_actual, +#enclosure-table td.humidity_actual { + width: 20%; +} + +#enclosure-table th.temperature_control, +#enclosure-table td.temperature_control { + width: 15%; +} + +#enclosure-table th.temperature_target, +#enclosure-table td.temperature_target { + width: 30%; + overflow: visible; +} + +.glyphs-on { + color: blue; + text-shadow: 4px 4px 15px blue; +} + +.glyphs-off { + color: red; + text-shadow: 4px 4px 15px red; +} + + diff --git a/octoprint_enclosure/static/js/bootstrap-colorpicker.min.js b/octoprint_enclosure/static/js/bootstrap-colorpicker.min.js index 2cec749..7cd35b8 100755 --- a/octoprint_enclosure/static/js/bootstrap-colorpicker.min.js +++ b/octoprint_enclosure/static/js/bootstrap-colorpicker.min.js @@ -1,5 +1,5 @@ -/*! - * Bootstrap Colorpicker v2.5.1 - * https://itsjavi.com/bootstrap-colorpicker/ - */ +/*! + * Bootstrap Colorpicker v2.5.1 + * https://itsjavi.com/bootstrap-colorpicker/ + */ !function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):jQuery&&!jQuery.fn.colorpicker&&b(jQuery)}(this,function(a){"use strict";var b=function(c,d,e,f,g){this.fallbackValue=e?e&&"undefined"!=typeof e.h?e:this.value={h:0,s:0,b:0,a:1}:null,this.fallbackFormat=f?f:"rgba",this.hexNumberSignPrefix=g===!0,this.value=this.fallbackValue,this.origFormat=null,this.predefinedColors=d?d:{},this.colors=a.extend({},b.webColors,this.predefinedColors),c&&("undefined"!=typeof c.h?this.value=c:this.setColor(String(c))),this.value||(this.value={h:0,s:0,b:0,a:1})};b.webColors={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32",transparent:"transparent"},b.prototype={constructor:b,colors:{},predefinedColors:{},getValue:function(){return this.value},setValue:function(a){this.value=a},_sanitizeNumber:function(a){return"number"==typeof a?a:isNaN(a)||null===a||""===a||void 0===a?1:""===a?0:"undefined"!=typeof a.toLowerCase?(a.match(/^\./)&&(a="0"+a),Math.ceil(100*parseFloat(a))/100):1},isTransparent:function(a){return!(!a||!("string"==typeof a||a instanceof String))&&(a=a.toLowerCase().trim(),"transparent"===a||a.match(/#?00000000/)||a.match(/(rgba|hsla)\(0,0,0,0?\.?0\)/))},rgbaIsTransparent:function(a){return 0===a.r&&0===a.g&&0===a.b&&0===a.a},setColor:function(a){if(a=a.toLowerCase().trim()){if(this.isTransparent(a))return this.value={h:0,s:0,b:0,a:0},!0;var b=this.parse(a);b?(this.value=this.value={h:b.h,s:b.s,b:b.b,a:b.a},this.origFormat||(this.origFormat=b.format)):this.fallbackValue&&(this.value=this.fallbackValue)}return!1},setHue:function(a){this.value.h=1-a},setSaturation:function(a){this.value.s=a},setBrightness:function(a){this.value.b=1-a},setAlpha:function(a){this.value.a=Math.round(parseInt(100*(1-a),10)/100*100)/100},toRGB:function(a,b,c,d){0===arguments.length&&(a=this.value.h,b=this.value.s,c=this.value.b,d=this.value.a),a*=360;var e,f,g,h,i;return a=a%360/60,i=c*b,h=i*(1-Math.abs(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a],{r:Math.round(255*e),g:Math.round(255*f),b:Math.round(255*g),a:d}},toHex:function(a,b,c,d){0===arguments.length&&(a=this.value.h,b=this.value.s,c=this.value.b,d=this.value.a);var e=this.toRGB(a,b,c,d);if(this.rgbaIsTransparent(e))return"transparent";var f=(this.hexNumberSignPrefix?"#":"")+((1<<24)+(parseInt(e.r)<<16)+(parseInt(e.g)<<8)+parseInt(e.b)).toString(16).slice(1);return f},toHSL:function(a,b,c,d){0===arguments.length&&(a=this.value.h,b=this.value.s,c=this.value.b,d=this.value.a);var e=a,f=(2-b)*c,g=b*c;return g/=f>0&&f<=1?f:2-f,f/=2,g>1&&(g=1),{h:isNaN(e)?0:e,s:isNaN(g)?0:g,l:isNaN(f)?0:f,a:isNaN(d)?0:d}},toAlias:function(a,b,c,d){var e,f=0===arguments.length?this.toHex():this.toHex(a,b,c,d),g="alias"===this.origFormat?f:this.toString(this.origFormat,!1);for(var h in this.colors)if(e=this.colors[h].toLowerCase().trim(),e===f||e===g)return h;return!1},RGBtoHSB:function(a,b,c,d){a/=255,b/=255,c/=255;var e,f,g,h;return g=Math.max(a,b,c),h=g-Math.min(a,b,c),e=0===h?null:g===a?(b-c)/h:g===b?(c-a)/h+2:(a-b)/h+4,e=(e+360)%6*60/360,f=0===h?0:h/g,{h:this._sanitizeNumber(e),s:f,b:g,a:this._sanitizeNumber(d)}},HueToRGB:function(a,b,c){return c<0?c+=1:c>1&&(c-=1),6*c<1?a+(b-a)*c*6:2*c<1?b:3*c<2?a+(b-a)*(2/3-c)*6:a},HSLtoRGB:function(a,b,c,d){b<0&&(b=0);var e;e=c<=.5?c*(1+b):c+b-c*b;var f=2*c-e,g=a+1/3,h=a,i=a-1/3,j=Math.round(255*this.HueToRGB(f,e,g)),k=Math.round(255*this.HueToRGB(f,e,h)),l=Math.round(255*this.HueToRGB(f,e,i));return[j,k,l,this._sanitizeNumber(d)]},parse:function(b){if(0===arguments.length)return!1;var c,d,e=this,f=!1,g="undefined"!=typeof this.colors[b];return g&&(b=this.colors[b].toLowerCase().trim()),a.each(this.stringParsers,function(a,h){var i=h.re.exec(b);return c=i&&h.parse.apply(e,[i]),!c||(f={},d=g?"alias":h.format?h.format:e.getValidFallbackFormat(),f=d.match(/hsla?/)?e.RGBtoHSB.apply(e,e.HSLtoRGB.apply(e,c)):e.RGBtoHSB.apply(e,c),f instanceof Object&&(f.format=d),!1)}),f},getValidFallbackFormat:function(){var a=["rgba","rgb","hex","hsla","hsl"];return this.origFormat&&a.indexOf(this.origFormat)!==-1?this.origFormat:this.fallbackFormat&&a.indexOf(this.fallbackFormat)!==-1?this.fallbackFormat:"rgba"},toString:function(a,c){a=a||this.origFormat||this.fallbackFormat,c=c||!1;var d=!1;switch(a){case"rgb":return d=this.toRGB(),this.rgbaIsTransparent(d)?"transparent":"rgb("+d.r+","+d.g+","+d.b+")";case"rgba":return d=this.toRGB(),"rgba("+d.r+","+d.g+","+d.b+","+d.a+")";case"hsl":return d=this.toHSL(),"hsl("+Math.round(360*d.h)+","+Math.round(100*d.s)+"%,"+Math.round(100*d.l)+"%)";case"hsla":return d=this.toHSL(),"hsla("+Math.round(360*d.h)+","+Math.round(100*d.s)+"%,"+Math.round(100*d.l)+"%,"+d.a+")";case"hex":return this.toHex();case"alias":return d=this.toAlias(),d===!1?this.toString(this.getValidFallbackFormat()):c&&!(d in b.webColors)&&d in this.predefinedColors?this.predefinedColors[d]:d;default:return d}},stringParsers:[{re:/rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/,format:"rgb",parse:function(a){return[a[1],a[2],a[3],1]}},{re:/rgb\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,format:"rgb",parse:function(a){return[2.55*a[1],2.55*a[2],2.55*a[3],1]}},{re:/rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"rgba",parse:function(a){return[a[1],a[2],a[3],a[4]]}},{re:/rgba\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"rgba",parse:function(a){return[2.55*a[1],2.55*a[2],2.55*a[3],a[4]]}},{re:/hsl\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,format:"hsl",parse:function(a){return[a[1]/360,a[2]/100,a[3]/100,a[4]]}},{re:/hsla\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"hsla",parse:function(a){return[a[1]/360,a[2]/100,a[3]/100,a[4]]}},{re:/#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,format:"hex",parse:function(a){return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16),1]}},{re:/#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,format:"hex",parse:function(a){return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16),1]}}],colorNameToHex:function(a){return"undefined"!=typeof this.colors[a.toLowerCase()]&&this.colors[a.toLowerCase()]}};var c={horizontal:!1,inline:!1,color:!1,format:!1,input:"input",container:!1,component:".add-on, .input-group-addon",fallbackColor:!1,fallbackFormat:"hex",hexNumberSignPrefix:!0,sliders:{saturation:{maxLeft:100,maxTop:100,callLeft:"setSaturation",callTop:"setBrightness"},hue:{maxLeft:0,maxTop:100,callLeft:!1,callTop:"setHue"},alpha:{maxLeft:0,maxTop:100,callLeft:!1,callTop:"setAlpha"}},slidersHorz:{saturation:{maxLeft:100,maxTop:100,callLeft:"setSaturation",callTop:"setBrightness"},hue:{maxLeft:100,maxTop:0,callLeft:"setHue",callTop:!1},alpha:{maxLeft:100,maxTop:0,callLeft:"setAlpha",callTop:!1}},template:'