From 17b1a96d713b6cc4f98df7a345536bd44914843b Mon Sep 17 00:00:00 2001 From: de Miranda Henrique Date: Wed, 28 Feb 2018 13:57:30 -0600 Subject: [PATCH] beta? --- octoprint_enclosure/__init__.py | 673 +++++++++++++----- octoprint_enclosure/neopixel_direct.py | 31 + .../{neopixel.py => neopixel_indirect.py} | 0 .../static/css/bootstrap-colorpicker.css | 0 .../static/css/bootstrap2-toggle.css | 85 --- octoprint_enclosure/static/css/enclosure.css | 24 +- .../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 .../static/js/bootstrap2-toggle.js | 180 ----- octoprint_enclosure/static/js/enclosure.js | 356 +++++---- .../templates/enclosure_navbar.jinja2 | 41 ++ .../templates/enclosure_navbar_input.jinja2 | 33 + .../templates/enclosure_settings.jinja2 | 111 ++- .../templates/enclosure_tab.jinja2 | 172 ++++- .../templates/enclosure_tab_temp.html | 65 -- .../templates/navbar_temp.html | 10 - .../templates/settings_temp.html | 0 octoprint_enclosure/templates/temp.html | 131 ---- octoprint_enclosure/templates/temp2.html | 64 -- 23 files changed, 1083 insertions(+), 893 deletions(-) create mode 100644 octoprint_enclosure/neopixel_direct.py rename octoprint_enclosure/{neopixel.py => neopixel_indirect.py} (100%) mode change 100755 => 100644 octoprint_enclosure/static/css/bootstrap-colorpicker.css delete mode 100755 octoprint_enclosure/static/css/bootstrap2-toggle.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 delete mode 100755 octoprint_enclosure/static/js/bootstrap2-toggle.js create mode 100644 octoprint_enclosure/templates/enclosure_navbar_input.jinja2 delete mode 100644 octoprint_enclosure/templates/enclosure_tab_temp.html delete mode 100644 octoprint_enclosure/templates/navbar_temp.html delete mode 100644 octoprint_enclosure/templates/settings_temp.html delete mode 100644 octoprint_enclosure/templates/temp.html delete mode 100644 octoprint_enclosure/templates/temp2.html diff --git a/octoprint_enclosure/__init__.py b/octoprint_enclosure/__init__.py index 70b05c0..60dd966 100644 --- a/octoprint_enclosure/__init__.py +++ b/octoprint_enclosure/__init__.py @@ -10,7 +10,8 @@ import time import sys import glob import os -import datetime +from datetime import datetime +from datetime import timedelta import octoprint.util import requests import inspect @@ -19,6 +20,7 @@ import json # 18b20 sensor serial --> 28-0000062410dc +# 18b20 sensor serial --> 28-000006044a8d # SI7021 addrress --> 40 # BTN 22 -> active low | close to the blue thing) # BTN 23 -> active high @@ -37,13 +39,16 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, last_filament_end_detected = 0 rpi_outputs = [] rpi_inputs = [] + waiting_temperature = [] rpi_outputs_not_changed = [] notifications = [] pwm_intances = [] event_queue = [] - temperature_control_status = [] + temp_hum_control_status = [] temperature_sensor_data = [] last_filament_end_detected = [] + print_start_time_date = 0 + print_complete = False def start_timer(self): """ @@ -79,6 +84,36 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, except: return 0 + @staticmethod + def is_hour(value): + try: + datetime.strptime(value, '%H:%M') + return True + except: + return False + + @staticmethod + def create_date(value): + temp_string = self.print_start_time_date.strftime( + '%m/%d/%Y') + " " + value + return datetime.strptime(temp_string, '%m/%d/%Y %H:%M') + + @staticmethod + def constrain(n, minn, maxn): + return max(min(maxn, n), minn) + + @staticmethod + def getGcodeValue(command_string, gcode): + semicolon = command_string.find(';') + if not semicolon == -1: + command_string = command_string[:semicolon] + + for command in command_string.split(' '): + index = command.upper().find(gcode.upper()) + if not index == -1: + return command.replace(gcode, '').upper() + return -1 + # ~~ StartupPlugin mixin def on_after_startup(self): self.fix_data() @@ -88,23 +123,25 @@ 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.generate_temperature_control_status() + self.generate_temp_hum_control_status() self.setup_gpio() self.configure_gpio() self.update_ui() self.start_timer() + self.print_start_time_date = 0 + self.print_complete = False # ~~ Blueprintplugin mixin - @octoprint.plugin.BlueprintPlugin.route("/setEnclosureTemperature", methods=["GET"]) - def set_enclosure_temperature(self): - set_temperature = self.to_float( + @octoprint.plugin.BlueprintPlugin.route("/setEnclosureTempHum", methods=["GET"]) + def set_enclosure_temperature_humidity(self): + set_value = 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['temp_ctr_set_temp'] = set_temperature + for temp_hum_control in [item for item in self.rpi_outputs if item['index_id'] == index_id]: + temp_hum_control['temp_ctr_set_value'] = set_value - self.handle_temperature_control() + self.handle_temp_hum_control() return flask.jsonify(success=True) # @octoprint.plugin.BlueprintPlugin.route("/getEnclosureSetTemperature", methods=["GET"]) @@ -125,7 +162,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, @octoprint.plugin.BlueprintPlugin.route("/getOutputStatus", methods=["GET"]) def get_output_status(self): gpio_status = [] - for rpi_output in self.rpi_outputs: + for rpi_output in self.rpi_outputs: if rpi_output['output_type'] == 'regular': pin = self.to_int(rpi_output['gpio_pin']) val = GPIO.input(pin) if not rpi_output['active_low'] else ( @@ -143,51 +180,90 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, @octoprint.plugin.BlueprintPlugin.route("/setIO", methods=["GET"]) def set_io(self): - gpio_index = flask.request.values["index_id"] + index = flask.request.values["index_id"] 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']): + if self.to_int(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("/setAutoStartUp", methods=["GET"]) + def set_auto_startup(self): + index = flask.request.values["index_id"] + value = True if flask.request.values["status"] == 'true' else False + for output in self.rpi_outputs: + if self.to_int(index) == self.to_int(output['index_id']): + output['auto_startup'] = value + self._logger.info( + "Setting auto startup for output %s to : %s", index, value) + self._settings.set(["rpi_outputs"], self.rpi_outputs) + return flask.jsonify(success=True) + + @octoprint.plugin.BlueprintPlugin.route("/setAutoShutdown", methods=["GET"]) + def set_auto_shutdown(self): + index = flask.request.values["index_id"] + value = True if flask.request.values["status"] == 'true' else False + for output in self.rpi_outputs: + if self.to_int(index) == self.to_int(output['index_id']): + output['auto_shutdown'] = value + self._logger.info( + "Setting auto shutdown for output %s to : %s", index, value) + self._settings.set(["rpi_outputs"], self.rpi_outputs) + return flask.jsonify(success=True) + + @octoprint.plugin.BlueprintPlugin.route("/setFilamentSensor", methods=["GET"]) + def set_filament_sensor(self): + index = flask.request.values["index_id"] + value = True if flask.request.values["status"] == 'true' else False + for sensor in self.rpi_inputs: + if self.to_int(index) == self.to_int(sensor['index_id']): + sensor['filament_sensor_enabled'] = value + self._logger.info( + "Setting filament sensor for input %s to : %s", index, value) + self._settings.set(["rpi_inputs"], self.rpi_inputs) + return flask.jsonify(success=True) + @octoprint.plugin.BlueprintPlugin.route("/setPWM", methods=["GET"]) def set_pwm(self): - 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_id']): - self.write_pwm(self.to_int( - rpi_output['gpio_pin']), self.to_int(pwm_val)) + set_value = self.to_int(flask.request.values["new_duty_cycle"]) + index_id = self.to_int(flask.request.values["index_id"]) + for rpi_output in [item for item in self.rpi_outputs if item['index_id'] == index_id]: + rpi_output['duty_cycle'] = set_value + rpi_output['new_duty_cycle'] = "" + gpio = self.to_int(rpi_output['gpio_pin']) + self.write_pwm(gpio, set_value) return flask.jsonify(success=True) @octoprint.plugin.BlueprintPlugin.route("/sendGcodeCommand", methods=["GET"]) def requested_gcode_command(self): gpio_index = self.to_int(flask.request.values["index_id"]) - rpi_output = [r_out for r_out in self.rpi_outputs if self.to_int(r_out['index_id']) == gpio_index].pop() + rpi_output = [r_out for r_out in self.rpi_outputs if self.to_int( + r_out['index_id']) == gpio_index].pop() self.send_gcode_command(rpi_output['gcode']) 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_index = flask.request.values["index_id"] + gpio_index = self.to_int(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_id']): + if gpio_index == self.to_int(rpi_output['index_id']): + rpi_output['neopixel_color'] = 'rgb({0!s},{1!s},{2!s})'.format( + red, green, blue) 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) + + neopixel_dirrect = rpi_output['output_type'] == 'neopixel_direct' + + self.send_neopixel_command( + self.to_int(rpi_output['gpio_pin']), + led_count, led_brightness, red, green, blue, address, neopixel_dirrect) + return flask.jsonify(success=True) # ~~ Plugin Internal methods @@ -201,7 +277,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, # 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): + def send_neopixel_command(self, led_pin, led_count, led_brightness, red, green, blue, address, neopixel_dirrect): """Send neopixel command Arguments: @@ -215,8 +291,16 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, """ try: - script = os.path.dirname( - os.path.realpath(__file__)) + "/neopixel.py " + + if address == '': + address = 0 + + if neopixel_dirrect: + script = os.path.dirname( + os.path.realpath(__file__)) + "/neopixel_direct.py " + else: + script = os.path.dirname( + os.path.realpath(__file__)) + "/neopixel_indirect.py " 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: @@ -229,33 +313,6 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, 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{2!r}" - message = template.format( - type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args) - self._logger.warn(message) - pass - def check_enclosure_temp(self): try: sensor_data = [] @@ -267,20 +324,84 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, sensor_data.append( dict(index_id=sensor['index_id'], temperature=temp, humidity=hum)) self.temperature_sensor_data = sensor_data - self.update_ui() - self.handle_temperature_control() + self.handle_temp_hum_control() self.handle_temperature_events() + self.update_ui() 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 toggle_output(self, output_index, first_run=False): + for output in [item for item in self.rpi_outputs if item['index_id'] == output_index]: + gpio_pin = self.to_int(output['gpio_pin']) + index_id = self.to_int(output['index_id']) + + if output['output_type'] == 'regular': + if first_run: + current_value = False + else: + current_value = (not GPIO.input( + gpio_pin)) if output['active_low'] else GPIO.input(gpio_pin) + + if(current_value): + time_delay = self.to_int(output['toggle_timer_off']) + else: + time_delay = self.to_int(output['toggle_timer_on']) + + if not self.print_complete: + self.write_gpio(gpio_pin, not current_value) + thread = threading.Timer(time_delay, + self.toggle_output, + args=[index_id]) + thread.start() + else: + off_value = True if output['active_low'] else False + self.write_gpio(gpio_pin, off_value) + self._logger.warn("Print done. no thead to start") + self.update_ui_outputs() + return + + if output['output_type'] == 'pwm': + for pwm in self.pwm_intances: + if gpio_pin in pwm: + if first_run: + current_pwm_value = 0 + else: + if 'duty_cycle' in pwm: + current_pwm_value = pwm['duty_cycle'] + current_pwm_value = self.to_int( + current_pwm_value) + else: + current_pwm_value = 0 + + if not current_pwm_value == 0: + time_delay = self.to_int( + output['toggle_timer_off']) + write_value = 0 + else: + time_delay = self.to_int(output['toggle_timer_on']) + write_value = self.to_int( + output['default_duty_cycle']) + + if not self.print_complete: + self.write_pwm(gpio_pin, write_value) + thread = threading.Timer(time_delay, + self.toggle_output, + args=[index_id]) + thread.start() + else: + self.write_pwm(self.to_int(output['gpio_pin']), 0) + self.update_ui_outputs() + return + def update_ui(self): self.update_ui_outputs() self.update_ui_current_temperature() self.update_ui_set_temperature() + self.update_ui_inputs() def update_ui_current_temperature(self): self._plugin_manager.send_plugin_message( @@ -289,10 +410,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def update_ui_set_temperature(self): result = [] for temp_crt_output in list(filter(lambda item: - item['output_type'] == 'temperature_control', + item['output_type'] == 'temp_hum_control', self.rpi_outputs)): set_temperature = self.to_float( - temp_crt_output['temp_ctr_set_temp']) + temp_crt_output['temp_ctr_set_value']) result.append( dict(index_id=temp_crt_output['index_id'], set_temperature=set_temperature)) result.append(set_temperature) @@ -301,26 +422,60 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def update_ui_outputs(self): try: - gpio_status = [] + regular_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 ( + neopixel_status = [] + temp_control_status = [] + for output in self.rpi_outputs: + index = self.to_int(output['index_id']) + pin = self.to_int(output['gpio_pin']) + startup = output['auto_startup'] + shutdown = output['auto_shutdown'] + + if output['output_type'] == 'regular': + val = GPIO.input(pin) if not output['active_low'] else ( not GPIO.input(pin)) - gpio_status.append(dict(index_id=index, status=val)) - if rpi_output['output_type'] == 'pwm': + regular_status.append( + dict(index_id=index, status=val, auto_startup=startup, auto_shutdown=shutdown)) + if output['output_type'] == 'temp_hum_control': + temp_control_status.append( + dict(index_id=index, auto_startup=startup, auto_shutdown=shutdown)) + if output['output_type'] == 'neopixel_indirect' or output['output_type'] == 'neopixel_direct': + val = output['neopixel_color'] + neopixel_status.append( + dict(index_id=index, color=val, auto_startup=startup, auto_shutdown=shutdown)) + if 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)) + val = 0 + pwm_status.append( + dict(index_id=index, pwm_value=val, auto_startup=startup, auto_shutdown=shutdown)) + self._plugin_manager.send_plugin_message(self._identifier, dict(rpi_output_regular=regular_status, + rpi_output_pwm=pwm_status, + rpi_output_neopixel=neopixel_status, + rpi_output_temp_hum_ctrl=temp_control_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_ui_inputs(self): + try: + sensor_status = [] + for sensor in self.rpi_inputs: + if sensor['input_type'] == 'gpio' and sensor['action_type'] == 'printer_control' and sensor['printer_action'] == 'filament': + index = self.to_int(sensor['index_id']) + value = sensor['filament_sensor_enabled'] + sensor_status.append( + dict(index_id=index, filament_sensor_enabled=value)) self._plugin_manager.send_plugin_message( - self._identifier, dict(rpi_output=gpio_status, rpi_output_pwm=pwm_status)) + self._identifier, dict(filament_sensor_status=sensor_status)) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" message = template.format( @@ -380,8 +535,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, rpi_controlled_output['gpio_pin']), val) for notification in self.notifications: if notification['temperatureAction']: - msg = "Temperature action: enclosure temperature exceed " + \ - temperature_alarm['setTemp'] + msg = ("Temperature action: enclosure temperature exceed " + + temperature_alarm['alarm_set_temp']) self.send_notification(msg) def read_dht_temp(self, sensor, pin): @@ -483,22 +638,22 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) return 0 - def handle_temperature_control(self): + def handle_temp_hum_control(self): try: - for temperature_control in list(filter(lambda item: item['output_type'] == 'temperature_control', self.rpi_outputs)): + for temp_hum_control in list(filter(lambda item: item['output_type'] == 'temp_hum_control', self.rpi_outputs)): set_temperature = self.to_float( - temperature_control['temp_ctr_set_temp']) + temp_hum_control['temp_ctr_set_value']) temp_deadband = self.to_float( - temperature_control['temp_ctr_deadband']) + temp_hum_control['temp_ctr_deadband']) max_temp = self.to_float( - temperature_control['temp_ctr_max_temp']) + temp_hum_control['temp_ctr_max_temp']) - linked_id = temperature_control['linked_temp_sensor'] + linked_id = temp_hum_control['linked_temp_sensor'] previous_status = filter( - lambda item: item['index_id'] == temperature_control['index_id'], - self.temperature_control_status).pop()['status'] + lambda item: item['index_id'] == temp_hum_control['index_id'], + self.temp_hum_control_status).pop()['status'] if set_temperature == 0: current_status = False @@ -506,37 +661,52 @@ 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']) + if str(temp_hum_control['temp_ctr_type']) == 'dehumidifier': + current_value = self.to_float(linked_data['humidity']) + temp_deadband = 0 + else: + current_value = self.to_float( + linked_data['temperature']) - if set_temperature - temp_deadband > current_temperature: + if set_temperature - temp_deadband > current_value: current_status = True - elif set_temperature + temp_deadband < current_temperature: + elif set_temperature + temp_deadband < current_value: current_status = False else: current_status = previous_status - if temperature_control['temp_ctr_type'] is 'cooler': + if str(temp_hum_control['temp_ctr_type']) == 'cooler': current_status = not current_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 + if temp_hum_control['temp_ctr_type'] == 'heater' and max_temp > 0.0 and max_temp < current_value: + if self._settings.get(["debug"]) is True: + self._logger.info( + "Maximun temperature reached for temperature control %s", temp_hum_control['index_id']) + temp_hum_control['temp_ctr_set_value'] = 0 current_status = False + 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 + val = False if temp_hum_control['active_low'] else True self.write_gpio(self.to_int( - temperature_control['gpio_pin']), val) + temp_hum_control['gpio_pin']), val) else: + index_id = temp_hum_control['index_id'] + if index_id in self.waiting_temperature: + self.waiting_temperature.remove(index_id) + + if not self.waiting_temperature and self._printer.is_paused(): + self._printer.resume_print() + self._logger.info( "Turning gpio to control temperature off.") - val = True if temperature_control['active_low'] else False + val = True if temp_hum_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']: + temp_hum_control['gpio_pin']), val) + for control_status in self.temp_hum_control_status: + if control_status['index_id'] == temp_hum_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}" @@ -552,7 +722,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if currentMode is None: outputs = list(filter(lambda item: item['output_type'] == 'regular' or item['output_type'] == 'pwm' or - item['output_type'] == 'temperature_control' or + item['output_type'] == 'temp_hum_control' or item['output_type'] == 'neopixel_direct', self.rpi_outputs)) inputs = list(filter( lambda item: item['input_type'] == 'gpio', self.rpi_inputs)) @@ -584,7 +754,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, 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'] == 'temp_hum_control' or item['output_type'] == 'neopixel_direct', self.rpi_outputs)): gpio_pin = self.to_int(gpio_out['gpio_pin']) if gpio_pin not in self.rpi_outputs_not_changed: @@ -614,37 +784,37 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def generate_temperature_control_status(self): + def generate_temp_hum_control_status(self): status = [] - for temperature_control in list(filter(lambda item: - item['output_type'] == 'temperature_control', self.rpi_outputs)): + for temp_hum_control in list(filter(lambda item: + item['output_type'] == 'temp_hum_control', self.rpi_outputs)): status.append( - dict(index_id=temperature_control['index_id'], status=False)) - self.temperature_control_status = status + dict(index_id=temp_hum_control['index_id'], status=False)) + self.temp_hum_control_status = status def configure_gpio(self): try: for gpio_out in list(filter(lambda item: item['output_type'] == 'regular' or - item['output_type'] == 'temperature_control', self.rpi_outputs)): + item['output_type'] == 'temp_hum_control', self.rpi_outputs)): initialValue = GPIO.HIGH if gpio_out['active_low'] else GPIO.LOW pin = self.to_int(gpio_out['gpio_pin']) if pin not in self.rpi_outputs_not_changed: self._logger.info( - "Setting GPIO pin %s as OUTPUT with initial value: %s", pin, initialValue) + "Setting GPIO pin %s as OUTPUT with initial value: %s", pin, initialValue) 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_id = self.to_int(gpio_out_pwm['index_id']) self._logger.info( - "Setting GPIO pin %s as PWM",pin) - for pwm in (pwm_dict for pwm_dict in self.pwm_intances if index_id in pwm_dict): + "Setting GPIO pin %s as PWM", pin) + for pwm in (pwm_dict for pwm_dict in self.pwm_intances if pin 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_id: pwm_instance}) + self.pwm_intances.append({pin: 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) @@ -657,9 +827,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, if rpi_input['action_type'] == 'output_control': self._logger.info( "Adding GPIO event detect on pin %s with edge: %s", gpio_pin, edge) - GPIO.add_event_detect(gpio_pin, edge, callback=self.handle_gpio_control, bouncetime=200) + GPIO.add_event_detect( + gpio_pin, edge, callback=self.handle_gpio_control, bouncetime=200) if (rpi_input['action_type'] == 'printer_control' and rpi_input['printer_action'] != 'filament'): - GPIO.add_event_detect(gpio_pin, edge, callback=self.handle_printer_action, bouncetime=200) + GPIO.add_event_detect( + gpio_pin, edge, callback=self.handle_printer_action, bouncetime=200) self._logger.info( "Adding PRINTER CONTROL event detect on pin %s with edge: %s", gpio_pin, edge) except Exception as ex: @@ -749,12 +921,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def handle_gpio_control(self, channel): try: if self._settings.get(["debug"]) is True: - self._logger.info("GPIO event triggered on channel %s", channel) - rpi_input = [r_inp for r_inp in self.rpi_inputs if self.to_int(r_inp['gpio_pin']) == self.to_int(channel)].pop() + self._logger.info( + "GPIO event triggered on channel %s", channel) + rpi_input = [r_inp for r_inp in self.rpi_inputs if self.to_int( + r_inp['gpio_pin']) == self.to_int(channel)].pop() gpio_pin = self.to_int(rpi_input['gpio_pin']) controlled_io = self.to_int(rpi_input['controlled_io']) if ((rpi_input['edge'] == 'fall') ^ GPIO.input(gpio_pin)): - rpi_output = [r_out for r_out in self.rpi_outputs if self.to_int(r_out['index_id']) == controlled_io].pop() + rpi_output = [r_out for r_out in self.rpi_outputs if self.to_int( + r_out['index_id']) == controlled_io].pop() if rpi_output['output_type'] == 'regular': if rpi_input['controlled_io_set_value'] == 'toggle': val = GPIO.LOW if GPIO.input(self.to_int( @@ -772,7 +947,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.send_gcode_command(rpi_output['gcode']) for notification in self.notifications: if notification['gpioAction']: - msg = "GPIO control action caused by input " + str(rpi_input['label']) + ". Sending GCODE command" + msg = "GPIO control action caused by input " + \ + str(rpi_input['label']) + \ + ". Sending GCODE command" self.send_notification(msg) except Exception as ex: template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}" @@ -804,13 +981,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, elif rpi_input['printer_action'] == 'cancel': self._logger.info("Printer action cancel.") self._printer.cancel_print() - elif rpi_input['printer_action'] == 'stop_temperature_control': + elif rpi_input['printer_action'] == 'stop_temp_hum_control': self._logger.info( "Printer action stoping temperature control.") for rpi_output in self.rpi_outputs: - if rpi_output['auto_shutdown'] and rpi_output['output_type'] == 'temperature_control': - rpi_output['temp_ctr_set_temp'] = 0 - self.handle_temperature_control() + if rpi_output['auto_shutdown'] and rpi_output['output_type'] == 'temp_hum_control': + rpi_output['temp_ctr_set_value'] = 0 + self.handle_temp_hum_control() for notification in self.notifications: if notification['printer_action']: msg = "Printer action: " + \ @@ -837,17 +1014,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.warn(message) pass - def write_pwm(self, gpio, pwmValue): + def write_pwm(self, gpio, pwm_value): try: for pwm in self.pwm_intances: if gpio in pwm: pwm_object = pwm[gpio] - pwm['duty_cycle'] = pwmValue + pwm['duty_cycle'] = pwm_value pwm_object.stop() - pwm_object.start(pwmValue) + pwm_object.start(pwm_value) if self._settings.get(["debug"]) is True: self._logger.info( - "Writing PWM on gpio: %s value %s", gpio, pwmValue) + "Writing PWM on gpio: %s value %s", gpio, pwm_value) self.update_ui() break except Exception as ex: @@ -916,72 +1093,62 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self.start_filament_detection() if event == Events.PRINT_STARTED: + self.print_complete = False self.cancel_events_on_event_queue() self.start_filament_detection() + self.print_start_time_date = datetime.now() for rpi_output in self.rpi_outputs: - 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(', '') + if rpi_output['auto_startup']: + delay_seconds = self.get_delay_from_output(rpi_output) + if rpi_output['output_type'] == 'regular': + value = False if rpi_output['active_low'] else True + self.add_regular_output_to_queue( + delay_seconds, rpi_output, value) + if rpi_output['output_type'] == 'pwm': + value = self.to_int(rpi_output['default_duty_cycle']) + self.add_pwm_output_to_queue( + delay_seconds, rpi_output, value) + if (rpi_output['output_type'] == 'neopixel_indirect' or rpi_output['output_type'] == 'neopixel_direct'): + red, green, blue = self.get_color_from_rgb(rpi_output) + self.add_neopixel_output_to_queue( + rpi_output, delay_seconds, red, green, blue) + if rpi_output['auto_startup'] and rpi_output['output_type'] == 'temp_hum_control': + rpi_output['temp_ctr_set_value'] = rpi_output['temp_ctr_default_temp'] - 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(')')] + if rpi_output['toggle_timer']: + if rpi_output['output_type'] == 'regular' or rpi_output['output_type'] == 'pwm': + self.toggle_output(rpi_output['index_id'], True) - 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['temp_ctr_set_temp'] = rpi_output['temp_ctr_default_temp'] - self.update_ui() - self._logger.info("Event queue: %s", self.event_queue) - for task in self.event_queue: - task.start() - self.event_queue = [] - elif event in (Events.PRINT_DONE, Events.PRINT_FAILED, Events.PRINT_CANCELLED): - self.stop_filament_detection() - for rpi_output in self.rpi_outputs: - 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.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])) - - if rpi_output['auto_shutdown'] and rpi_output['output_type'] == 'temperature_control': - rpi_output['temp_ctr_set_temp'] = 0 - self.update_ui() for task in self.event_queue: task.start() self.event_queue = [] + self.update_ui() + + elif event in (Events.PRINT_DONE, Events.PRINT_FAILED, Events.PRINT_CANCELLED): + self.stop_filament_detection() + self.print_complete = True + + for rpi_output in self.rpi_outputs: + if rpi_output['auto_shutdown']: + delay_seconds = self.get_shutdown_delay_from_output( + rpi_output) + if rpi_output['output_type'] == 'regular': + value = True if rpi_output['active_low'] else False + self.add_regular_output_to_queue( + delay_seconds, rpi_output, value) + if rpi_output['output_type'] == 'pwm': + value = 0 + self.add_pwm_output_to_queue( + delay_seconds, rpi_output, value) + if (rpi_output['output_type'] == 'neopixel_indirect' or rpi_output['output_type'] == 'neopixel_direct'): + self.add_neopixel_output_to_queue( + rpi_output, delay_seconds, 0, 0, 0) + if rpi_output['output_type'] == 'temp_hum_control': + rpi_output['temp_ctr_set_value'] = 0 + for task in self.event_queue: + task.start() + self.event_queue = [] + self.update_ui() if event == Events.PRINT_DONE: for notification in self.notifications: @@ -989,11 +1156,81 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, 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)) + timedelta(seconds=elapsed_time_in_seconds)) msg = "Print job finished: " + file_name + \ "finished printing in " + file_name, elapsed_time self.send_notification(msg) + def get_color_from_rgb(self, rpi_output): + stringColor = rpi_output['neopixel_color'] + stringColor = stringColor.replace('rgb(', '') + 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(')')] + return red, green, blue + + def get_shutdown_delay_from_output(self, rpi_output): + shutdown_time = rpi_output['shutdown_time'] + start_up_time = rpi_output['startup_time'] + + if self.is_hour(shutdown_time) and self.is_hour(start_up_time): + shut_down_date_time = create_date(shutdown_time) + start_up_date_time = create_date(start_up_time) + if shut_down_date_time < start_up_date_time: + shut_down_date_time = shut_down_date_time + timedelta(days=1) + if shut_down_date_time < datetime.now(): + delay_seconds = 0.0 + else: + delay_seconds = (shut_down_date_time - + datetime.now()).total_seconds() + + elif self.is_hour(shutdown_time) and not self.is_hour(start_up_time): + shut_down_date_time = create_date(shutdown_time) + if shut_down_date_time < datetime.now(): + delay_seconds = 0.0 + else: + delay_seconds = (shut_down_date_time - + datetime.now()).total_seconds() + else: + delay_seconds = self.to_float(rpi_output['shutdown_time']) + return delay_seconds + + def add_neopixel_output_to_queue(self, rpi_output, delay_seconds, red, green, blue): + gpio_pin = rpi_output['gpio_pin'] + ledCount = rpi_output['neopixel_count'] + ledBrightness = rpi_output['neopixel_brightness'] + address = rpi_output['microcontroller_address'] + neopixel_direct = rpi_output['output_type'] == 'neopixel_direct' + self.event_queue.append(threading.Timer(delay_seconds, + self.send_neopixel_command, + args=[gpio_pin, ledCount, ledBrightness, red, green, blue, address, neopixel_direct])) + + def add_pwm_output_to_queue(self, delay_seconds, rpi_output, value): + self.event_queue.append(threading.Timer(delay_seconds, + self.write_pwm, + args=[self.to_int(rpi_output['gpio_pin']), value])) + + def add_regular_output_to_queue(self, delay_seconds, rpi_output, value): + self.event_queue.append(threading.Timer(delay_seconds, + self.write_gpio, + args=[self.to_int(rpi_output['gpio_pin']), value])) + + def get_delay_from_output(self, rpi_output): + start_up_time = rpi_output['startup_time'] + if self.is_hour(start_up_time): + start_up_date_time = create_date(start_up_time) + if start_up_date_time < self.print_start_time_date: + delay_seconds = 0.0 + else: + delay_seconds = ( + start_up_date_time - self.print_start_time_date).total_seconds() + else: + delay_seconds = self.to_float( + rpi_output['startup_time']) + return delay_seconds + # ~~ SettingsPlugin mixin def on_settings_save(self, data): outputsBeforeSave = self.get_output_list() @@ -1018,7 +1255,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, self._logger.info("rpi_inputs: %s", self.rpi_inputs) self.setup_gpio() self.configure_gpio() - self.generate_temperature_control_status() + self.generate_temp_hum_control_status() def get_settings_defaults(self): return dict( @@ -1038,6 +1275,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, "M82 ;Set extruder to Absolute Mode\n" + "G92 E0 ;Set Extruder to 0", debug=False, + gcode_control=False, debug_temperature_log=False, useBoardPinNumber=False, notification_provider="disabled", @@ -1052,14 +1290,18 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, def get_template_configs(self): return [ dict(type="settings", custom_bindings=True), - dict(type="tab", custom_bindings=True) + dict(type="tab", custom_bindings=True), + dict(type="navbar", custom_bindings=True, + suffix="_1", classes=["dropdown"]), + dict(type="navbar", custom_bindings=True, + template="enclosure_navbar_input.jinja2", suffix="_2", classes=["dropdown"]) ] # ~~ AssetPlugin mixin def get_assets(self): return dict( - 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"] + js=["js/enclosure.js", "js/bootstrap-colorpicker.min.js"], + css=["css/bootstrap-colorpicker.css", "css/enclosure.css"] ) # ~~ Softwareupdate hook @@ -1078,6 +1320,62 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin, ) ) + def hook_gcode_queuing(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs): + if self._settings.get(["gcode_control"]) is False: + return + + if cmd.strip().startswith("ENC"): + if self._settings.get(["debug"]) is True: + self._logger.info("Gcode queuing: %s", cmd) + index_id = self.to_int(self.getGcodeValue(cmd, 'O')) + for output in [item for item in self.rpi_outputs if item['index_id'] == index_id]: + if output['output_type'] == 'regular': + set_value = self.to_int(self.getGcodeValue(cmd, 'S')) + set_value = self.constrain(set_value, 0, 1) + value = True if set_value == 1 else False + value = (not value) if output['active_low'] else value + self.write_gpio(self.to_int(output['gpio_pin']), value) + comm_instance._log( + "Setting REGULAR output %s to value %s" % (index_id, value)) + return + if output['output_type'] == 'pwm': + set_value = self.to_int(self.getGcodeValue(cmd, 'S')) + set_value = self.constrain(set_value, 0, 100) + output['duty_cycle'] = set_value + self.write_pwm(self.to_int(output['gpio_pin']), set_value) + comm_instance._log( + "Setting PWM output %s to value %s" % (index_id, set_value)) + return + if output['output_type'] == 'neopixel_indirect' or output['output_type'] == 'neopixel_direct': + red = self.getGcodeValue(cmd, 'R') + green = self.getGcodeValue(cmd, 'G') + blue = self.getGcodeValue(cmd, 'B') + + led_count = output['neopixel_count'] + led_brightness = output['neopixel_brightness'] + address = output['microcontroller_address'] + + neopixel_dirrect = output['output_type'] == 'neopixel_direct' + + self.send_neopixel_command( + self.to_int(output['gpio_pin']), + led_count, led_brightness, red, green, blue, address, neopixel_dirrect) + comm_instance._log( + "Setting NEOPIXEL output %s to red: %s green: %s blue: %s" % (index_id, red, green, blue)) + return + if output['output_type'] == 'temp_hum_control': + set_value = self.to_float(self.getGcodeValue(cmd, 'S')) + should_wait = self.to_int(self.getGcodeValue(cmd, 'W')) + if should_wait == 1 and self._printer.is_printing(): + self._printer.pause_print() + self.waiting_temperature.append(index_id) + output['temp_ctr_set_value'] = set_value + self.update_ui_set_temperature() + self.handle_temp_hum_control() + comm_instance._log( + "Setting TEMP/HUM control output %s to value %s" % (index_id, set_value)) + return + __plugin_name__ = "Enclosure Plugin" @@ -1088,5 +1386,6 @@ def __plugin_load__(): global __plugin_hooks__ __plugin_hooks__ = { + "octoprint.comm.protocol.gcode.queuing": __plugin_implementation__.hook_gcode_queuing, "octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information } diff --git a/octoprint_enclosure/neopixel_direct.py b/octoprint_enclosure/neopixel_direct.py new file mode 100644 index 0000000..cb038b2 --- /dev/null +++ b/octoprint_enclosure/neopixel_direct.py @@ -0,0 +1,31 @@ +from neopixel import * +import sys +import time + +LED_INVERT = False +LED_DMA = 5 +LED_FREQ_HZ = 800000 + +if len(sys.argv) == 8: + LED_PIN = int(sys.argv[1]) + LED_COUNT = int(sys.argv[2]) + LED_BRIGHTNESS = int(sys.argv[3]) + red = int(sys.argv[4]) + green = int(sys.argv[5]) + blue = int(sys.argv[6]) + address = int(sys.argv[7], 16) +else: + print("fail") + sys.exit(1) + +strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT) +strip.begin() + +color = Color(green, red, blue) + +for i in range(LED_COUNT): + strip.setPixelColor(i, color) + +strip.show() + +print("ok") diff --git a/octoprint_enclosure/neopixel.py b/octoprint_enclosure/neopixel_indirect.py similarity index 100% rename from octoprint_enclosure/neopixel.py rename to octoprint_enclosure/neopixel_indirect.py 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/css/bootstrap2-toggle.css b/octoprint_enclosure/static/css/bootstrap2-toggle.css deleted file mode 100755 index 3f48927..0000000 --- a/octoprint_enclosure/static/css/bootstrap2-toggle.css +++ /dev/null @@ -1,85 +0,0 @@ -/*! ======================================================================== - * 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 1836525..781a8e9 100644 --- a/octoprint_enclosure/static/css/enclosure.css +++ b/octoprint_enclosure/static/css/enclosure.css @@ -30,8 +30,8 @@ width: 15%; } -#enclosure-table th.temperature_control, -#enclosure-table td.temperature_control { +#enclosure-table th.temp_hum_control, +#enclosure-table td.temp_hum_control { width: 15%; } @@ -51,4 +51,24 @@ text-shadow: 4px 4px 15px red; } +.enclosure-link{ + text-decoration: none; +} + +.enclosure-link:hover{ + text-decoration: none; +} + +.navbar-enclosure{ + text-shadow: 0 1px 0 #ccc; + color: #333; + float: none; + padding: 10px 15px 10px; + text-decoration: none; +} + +.neopixel-div{ + width: 25%; +} + 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/bootstrap2-toggle.js b/octoprint_enclosure/static/js/bootstrap2-toggle.js deleted file mode 100755 index 93a541c..0000000 --- a/octoprint_enclosure/static/js/bootstrap2-toggle.js +++ /dev/null @@ -1,180 +0,0 @@ -/*! ======================================================================== - * Bootstrap Toggle: bootstrap2-toggle.js v2.2.0 - * http://www.bootstraptoggle.com - * ======================================================================== - * Copyright 2014 Min Hur, The New York Times Company - * Licensed under MIT - * ======================================================================== */ - - - +function ($) { - 'use strict'; - - // TOGGLE PUBLIC CLASS DEFINITION - // ============================== - - var Toggle = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, this.defaults(), options) - this.render() - } - - Toggle.VERSION = '2.2.0' - - Toggle.DEFAULTS = { - on: 'On', - off: 'Off', - onstyle: 'primary', - offstyle: 'default', - size: 'normal', - style: '', - width: null, - height: null - } - - Toggle.prototype.defaults = function() { - return { - on: this.$element.attr('data-on') || Toggle.DEFAULTS.on, - off: this.$element.attr('data-off') || Toggle.DEFAULTS.off, - onstyle: this.$element.attr('data-onstyle') || Toggle.DEFAULTS.onstyle, - offstyle: this.$element.attr('data-offstyle') || Toggle.DEFAULTS.offstyle, - size: this.$element.attr('data-size') || Toggle.DEFAULTS.size, - style: this.$element.attr('data-style') || Toggle.DEFAULTS.style, - width: this.$element.attr('data-width') || Toggle.DEFAULTS.width, - height: this.$element.attr('data-height') || Toggle.DEFAULTS.height - } - } - - Toggle.prototype.render = function () { - this._onstyle = 'btn-' + this.options.onstyle - this._offstyle = 'btn-' + this.options.offstyle - var size = this.options.size === 'large' ? 'btn-large' - : this.options.size === 'small' ? 'btn-small' - : this.options.size === 'mini' ? 'btn-mini' - : '' - var $toggleOn = $('