dev new features
This commit is contained in:
21
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
21
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Additional context**
|
||||
Add screenshots of your settings screen, so I know how to recreate the data. Also enable the debug information under the advanced section of the plugin, reproduce the issue and attach the [octoprint log](https://discourse.octoprint.org/t/where-can-i-find-octoprints-and-octopis-log-files/299) here.
|
||||
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
41
README.md
41
README.md
@@ -1,3 +1,12 @@
|
||||
Find the plugin useful? Buy me a coffee
|
||||
[](https://www.paypal.me/VitorHenrique/2)
|
||||
|
||||
# Before opening an issue...
|
||||
|
||||
Check the [troubleshooting guide](https://github.com/vitormhenrique/OctoPrint-Enclosure/wiki/Troubleshooting-Guide). Issues with no log, no print screen *will be closed* until the necessary documentation is available.
|
||||
|
||||
Also, be aware that upgrading from versions lower than 4.00 will **DELETE** all settings. More information on [release notes](https://github.com/vitormhenrique/OctoPrint-Enclosure/releases/tag/4.00)
|
||||
|
||||
# OctoPrint-Enclosure
|
||||
|
||||
**Control pretty much everything that you might want to do on your raspberry pi / octoprint / enclosure**
|
||||
@@ -17,11 +26,6 @@ Here is a list of possibilities:
|
||||
* Notifications using IFTTT when events happen (temperature trigger / print events / etc)
|
||||
* Add sub-menus on navbar to quick access outputs and temperature sensors
|
||||
|
||||
Find the plugin useful? Buy me a coffee
|
||||
[](https://www.paypal.me/VitorHenrique/2)
|
||||
|
||||
Having problems with the plugin? check the [troubleshooting guide](https://github.com/vitormhenrique/OctoPrint-Enclosure/wiki/Troubleshooting-Guide)
|
||||
|
||||
Check pictures on thingiverse: http://www.thingiverse.com/thing:2245493
|
||||
|
||||
**Software**
|
||||
@@ -47,6 +51,8 @@ sudo apt-get update
|
||||
sudo apt-get install build-essential python-dev python-openssl
|
||||
sudo python setup.py install</code></pre>
|
||||
|
||||
Note: All libraries need to be installed on raspberry pi system python not octoprint virtual environment.
|
||||
|
||||
You can test the library by using:
|
||||
|
||||
<pre><code>cd examples
|
||||
@@ -62,6 +68,11 @@ Start by adding the following line to /boot/config.txt
|
||||
|
||||
<pre><code>dtoverlay=w1-gpio</code></pre>
|
||||
|
||||
After rebooting, you can check if the OneWire device was found properly with
|
||||
<pre><code>dmesg | grep w1-gpip</code></pre>
|
||||
You should see something like
|
||||
<pre><code>[ 3.030368] w1-gpio onewire@0: gpio pin 4, external pullup pin -1, parasitic power 0</code></pre>
|
||||
|
||||
You should be able to test your sensor by rebooting your system with sudo reboot. When the Pi is back up and you're logged in again, type the commands you see below into a terminal window. When you are in the 'devices' directory, the directory starting '28-' may have a different name, so cd to the name of whatever directory is there.
|
||||
|
||||
<pre><code>sudo modprobe w1-gpio
|
||||
@@ -73,7 +84,7 @@ cat w1_slave</code></pre>
|
||||
|
||||
The response will either have YES or NO at the end of the first line. If it is yes, then the temperature will be at the end of the second line, in 1/000 degrees C.
|
||||
|
||||
Copy the serial number, you will need to configure the plugin
|
||||
Copy the serial number, you will need to configure the plugin. Note that for the serial number includes the 28-, for example 28-0000069834ff.
|
||||
|
||||
* For the SI7021, BME280 and TMP102 sensors
|
||||
|
||||
@@ -88,9 +99,9 @@ Use the right arrow to select the button
|
||||
Select yes when it asks to reboot
|
||||
</code></pre>
|
||||
|
||||
Install some packages:
|
||||
Install some packages (on raspberry pi system python not octoprint virtual environment):
|
||||
|
||||
<pre><code>sudo apt-get install i2c-tools python-pip</code></pre>
|
||||
<pre><code>sudo apt-get install i2c-tools python-pip python-smbus</code></pre>
|
||||
|
||||
Find the address of the sensor:
|
||||
|
||||
@@ -106,11 +117,11 @@ You can use relays / mosfets to control you lights, heater, lockers etc... If yo
|
||||
|
||||
* Relay
|
||||
|
||||
The relays module that I used can be found [here](https://www.amazon.com/gp/product/B0057OC6D8?psc=1&redirect=true&ref_=oh_aui_search_detailpage). Those relays are active low, that means that they will turn on when you put LOW on the output of your pin. In order to not fry your Raspberry Pi pay attention on your wiring connection: remove the jumper link and connect 3.3v to VCC, 5V to JD-VCC and Ground to GND.
|
||||
The relays module that I used couple [SainSmart 2-Channel Relay Module](https://www.amazon.com/gp/product/B0057OC6D8?ie=UTF8&tag=3dpstuff-20&camp=1789&linkCode=xm2&creativeASIN=B0057OC6D8). Those relays are active low, that means that they will turn on when you put LOW on the output of your pin. In order to not fry your Raspberry Pi pay attention on your wiring connection: remove the jumper link and connect 3.3v to VCC, 5V to JD-VCC and Ground to GND.
|
||||
|
||||
* Heater
|
||||
|
||||
For heating my enclosure I got a $15 lasko inside my enclosure. I opened it and added a relay to the mains wire. If you’re uncomfortable soldering or dealing with high voltage, please check out the [PowerSwitch Tail II](http://www.powerswitchtail.com/Pages/default.aspx) . The PowerSwitch Tail II is fully enclosed, making it a lot safer.
|
||||
For heating my enclosure I got a $15 lasko inside my enclosure. I opened it and added a relay to the mains wire. If you’re uncomfortable soldering or dealing with high voltage, please check out the [PowerSwitch Tail II](http://www.powerswitchtail.com/) . The PowerSwitch Tail II is fully enclosed, making it a lot safer.
|
||||
|
||||
**CAUTION: VOLTAGE ON MAINS WIRE CAN KILL YOU, ONLY ATTEMPT TO DO THIS IF YOU KNOW WHAT YOU ARE DOING, AND DO AT YOUR OWN RISK**
|
||||
|
||||
@@ -118,7 +129,7 @@ For heating my enclosure I got a $15 lasko inside my enclosure. I opened it and
|
||||
|
||||
* Cooler
|
||||
|
||||
You can get a [5V small fan](https://www.amazon.com/gp/product/B003FO0LG6/ref=oh_aui_search_detailpage?ie=UTF8&psc=1) and control it over a relay.
|
||||
You can get a [USB Mini Desktop Fan](https://www.amazon.com/gp/product/B00WM7TRTY?ie=UTF8&tag=3dpstuff-20&camp=1789&linkCode=xm2&creativeASIN=B00WM7TRTY) and control it over a relay.
|
||||
|
||||
* Filament sensor
|
||||
|
||||
@@ -180,8 +191,8 @@ You can do this by changing the config.yaml file as instructed on [octoprint doc
|
||||
|
||||
You just need to add the following section:
|
||||
|
||||
```
|
||||
appearance:
|
||||
|
||||
<pre><code>appearance:
|
||||
components:
|
||||
order:
|
||||
tab:
|
||||
@@ -189,9 +200,7 @@ appearance:
|
||||
- control
|
||||
- gcodeviewer
|
||||
- terminal
|
||||
- plugin_enclosure
|
||||
- timelapse
|
||||
```
|
||||
- plugin_enclosure<code><pre>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
temperature_sensor_data = []
|
||||
last_filament_end_detected = []
|
||||
print_complete = False
|
||||
development_mode = False
|
||||
dummy_value = 30.0
|
||||
dummy_delta = 0.5
|
||||
|
||||
def start_timer(self):
|
||||
"""
|
||||
@@ -114,22 +117,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
self.configure_gpio()
|
||||
self.update_ui()
|
||||
self.start_outpus_with_server()
|
||||
self.handle_initial_gpio_control()
|
||||
self.start_timer()
|
||||
self.print_complete = False
|
||||
|
||||
def get_settings_version(self):
|
||||
return 6
|
||||
return 5
|
||||
|
||||
def on_settings_migrate(self, target, current=None):
|
||||
def on_settings_migrate(self, target, current):
|
||||
self._logger.warn("######### current settings version %s target settings version %s #########", current, target)
|
||||
|
||||
if current >= 4 and target == 6:
|
||||
self._logger.warn(
|
||||
"######### migrating settings to v6 #########")
|
||||
for rpi_output in old_outputs:
|
||||
if 'shutdown_on_failed' not in rpi_output:
|
||||
rpi_output['shutdown_on_failed'] = False
|
||||
if 'shutdown_on_failed' not in rpi_output:
|
||||
if current == 4 and target == 5:
|
||||
self._logger.warn("######### migrating settings from v4 to v5 #########")
|
||||
old_outputs = self._settings.get(["rpi_outputs"])
|
||||
@@ -335,7 +331,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
sudo_str = ""
|
||||
|
||||
cmd = sudo_str + "python " + script + str(led_pin) + " " + str(led_count) + " " + str(
|
||||
led_brightness) + " " + str(red) + " " + str(green) + " " + str(blue) + " " + str(address)
|
||||
led_brightness) + " " + str(red) + " " + str(green) + " " + str(blue) + " "
|
||||
|
||||
if neopixel_dirrect:
|
||||
dma = self._settings.get(["neopixel_dma"]) or 10
|
||||
cmd = cmd + str(dma)
|
||||
else:
|
||||
cmd = cmd + str(address)
|
||||
|
||||
if self._settings.get(["debug"]) is True:
|
||||
if queue_id is not None:
|
||||
self._logger.info("Runing scheduled queue id %s", queue_id)
|
||||
@@ -357,11 +360,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
if temp is not None and hum is not None:
|
||||
sensor_data.append(
|
||||
dict(index_id=sensor['index_id'], temperature=temp, humidity=hum))
|
||||
self.temperature_sensor_data = sensor_data
|
||||
self.handle_temp_hum_control()
|
||||
self.handle_temperature_events()
|
||||
self.handle_pwm_linked_temperature()
|
||||
self.update_ui()
|
||||
self.temperature_sensor_data = sensor_data
|
||||
self.handle_temp_hum_control()
|
||||
self.handle_temperature_events()
|
||||
self.handle_pwm_linked_temperature()
|
||||
self.update_ui()
|
||||
except Exception as ex:
|
||||
self.log_error(ex)
|
||||
|
||||
@@ -461,7 +464,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
task['thread'].cancel()
|
||||
self.event_queue.remove(task)
|
||||
if self._settings.get(["debug"]) is True:
|
||||
self._logger.info("Queue id stoped and removed from list...")
|
||||
self._logger.info(
|
||||
"Queue id stoped and removed from list...")
|
||||
self._logger.info("Old queue list: %s", old_list)
|
||||
self._logger.info("New queue list: %s", self.event_queue)
|
||||
|
||||
@@ -483,8 +487,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
regular_status.append(
|
||||
dict(index_id=index, status=val, auto_startup=startup, auto_shutdown=shutdown))
|
||||
if output['output_type'] == 'temp_hum_control':
|
||||
val = GPIO.input(pin) if not output['active_low'] else (
|
||||
not GPIO.input(pin))
|
||||
temp_control_status.append(
|
||||
dict(index_id=index, auto_startup=startup, auto_shutdown=shutdown))
|
||||
dict(index_id=index, status=val, 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(
|
||||
@@ -522,27 +528,29 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
|
||||
def get_sensor_data(self, sensor):
|
||||
try:
|
||||
if sensor['temp_sensor_type'] in ["11", "22", "2302"]:
|
||||
self._logger.info("temp_sensor_type dht")
|
||||
temp, hum = self.read_dht_temp(
|
||||
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['temp_sensor_type'] == "bme280":
|
||||
temp, hum = self.read_bme280_temp(
|
||||
sensor['temp_sensor_address'])
|
||||
elif sensor['temp_sensor_type'] == "si7021":
|
||||
temp, hum = self.read_si7021_temp(
|
||||
sensor['temp_sensor_address'])
|
||||
elif sensor['temp_sensor_type'] == "tmp102":
|
||||
temp = self.read_tmp102_temp(
|
||||
sensor['temp_sensor_address'])
|
||||
hum = 0
|
||||
if self.development_mode:
|
||||
temp, hum = self.read_dummy_temp()
|
||||
else:
|
||||
self._logger.info("temp_sensor_type no match")
|
||||
temp = None
|
||||
hum = None
|
||||
if sensor['temp_sensor_type'] in ["11", "22", "2302"]:
|
||||
temp, hum = self.read_dht_temp(
|
||||
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['temp_sensor_type'] == "bme280":
|
||||
temp, hum = self.read_bme280_temp(
|
||||
sensor['temp_sensor_address'])
|
||||
elif sensor['temp_sensor_type'] == "si7021":
|
||||
temp, hum = self.read_si7021_temp(
|
||||
sensor['temp_sensor_address'])
|
||||
elif sensor['temp_sensor_type'] == "tmp102":
|
||||
temp = self.read_tmp102_temp(
|
||||
sensor['temp_sensor_address'])
|
||||
hum = 0
|
||||
else:
|
||||
self._logger.info("temp_sensor_type no match")
|
||||
temp = None
|
||||
hum = None
|
||||
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)
|
||||
@@ -573,6 +581,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
temperature_alarm['alarm_set_temp'])
|
||||
self.send_notification(msg)
|
||||
|
||||
def read_dummy_temp(self):
|
||||
current_value = self.dummy_value
|
||||
if current_value > 40 or current_value < 30:
|
||||
self.dummy_delta = - self.dummy_delta
|
||||
|
||||
return_value = current_value + self.dummy_delta
|
||||
|
||||
self.dummy_value = return_value
|
||||
|
||||
return return_value, return_value
|
||||
|
||||
def read_dht_temp(self, sensor, pin):
|
||||
try:
|
||||
script = os.path.dirname(
|
||||
@@ -590,6 +609,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:
|
||||
self._logger.info("Failed to excecute python scripts, try disabling use SUDO on advanced section of the plugin.")
|
||||
self.log_error(ex)
|
||||
return (0, 0)
|
||||
|
||||
@@ -610,6 +630,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:
|
||||
self._logger.info("Failed to excecute python scripts, try disabling use SUDO on advanced section of the plugin.")
|
||||
self.log_error(ex)
|
||||
return (0, 0)
|
||||
|
||||
@@ -630,6 +651,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:
|
||||
self._logger.info("Failed to excecute python scripts, try disabling use SUDO on advanced section of the plugin.")
|
||||
self.log_error(ex)
|
||||
return (0, 0)
|
||||
|
||||
@@ -671,6 +693,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
self._logger.info("TMP102 result: %s", stdout)
|
||||
return self.to_float(stdout.strip())
|
||||
except Exception as ex:
|
||||
self._logger.info("Failed to excecute python scripts, try disabling use SUDO on advanced section.")
|
||||
self.log_error(ex)
|
||||
return 0
|
||||
|
||||
@@ -744,24 +767,31 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
linked_data = self.get_linked_temp_sensor_data(
|
||||
linked_id)
|
||||
|
||||
if str(temp_hum_control['temp_ctr_type']) == 'dehumidifier':
|
||||
control_type = str(temp_hum_control['temp_ctr_type'])
|
||||
|
||||
if control_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_value:
|
||||
current_status = True
|
||||
elif set_temperature + temp_deadband < current_value:
|
||||
current_status = False
|
||||
if control_type == 'cooler' or control_type == 'dehumidifier':
|
||||
if current_value <= set_temperature and current_value >= (set_temperature - temp_deadband):
|
||||
current_status = previous_status
|
||||
elif current_value < set_temperature:
|
||||
current_status = False
|
||||
else:
|
||||
current_status = True
|
||||
else:
|
||||
current_status = previous_status
|
||||
if current_value <= set_temperature and current_value >= (set_temperature - temp_deadband):
|
||||
current_status = previous_status
|
||||
elif current_value > set_temperature:
|
||||
current_status = False
|
||||
else:
|
||||
current_status = True
|
||||
|
||||
if str(temp_hum_control['temp_ctr_type']) == 'cooler' or str(temp_hum_control['temp_ctr_type']) == 'dehumidifier':
|
||||
current_status = not current_status
|
||||
|
||||
if temp_hum_control['temp_ctr_type'] == 'heater' and max_temp > 0.0 and max_temp < current_value:
|
||||
if control_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'])
|
||||
@@ -804,7 +834,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
try:
|
||||
current_mode = GPIO.getmode()
|
||||
set_mode = GPIO.BOARD if self._settings.get(
|
||||
["useBoardPinNumber"]) else GPIO.BCM
|
||||
["use_board_pin_number"]) else GPIO.BCM
|
||||
if current_mode is None:
|
||||
outputs = list(filter(lambda item: item['output_type'] == 'regular' or
|
||||
item['output_type'] == 'pwm' or
|
||||
@@ -820,7 +850,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
elif current_mode != set_mode:
|
||||
GPIO.setmode(current_mode)
|
||||
tempstr = "BOARD" if current_mode == GPIO.BOARD else "BCM"
|
||||
self._settings.set(["useBoardPinNumber"],
|
||||
self._settings.set(["use_board_pin_number"],
|
||||
True if current_mode == 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!"
|
||||
@@ -887,16 +917,27 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
GPIO.setup(pin, GPIO.OUT)
|
||||
pwm_instance = GPIO.PWM(pin, self.to_int(
|
||||
gpio_out_pwm['pwm_frequency']))
|
||||
pwm_instance.start(0)
|
||||
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)
|
||||
|
||||
for rpi_input in list(filter(lambda item: item['input_type'] == 'gpio', self.rpi_inputs)):
|
||||
pull_resistor = GPIO.PUD_UP if rpi_input['input_pull_resistor'] == 'input_pull_up' else GPIO.PUD_DOWN
|
||||
gpio_pin = self.to_int(rpi_input['gpio_pin'])
|
||||
pull_resistor = GPIO.PUD_UP if rpi_input['input_pull_resistor'] == 'input_pull_up' else GPIO.PUD_DOWN
|
||||
GPIO.setup(gpio_pin, GPIO.IN, pull_resistor)
|
||||
edge = GPIO.RISING if rpi_input['edge'] == 'rise' else GPIO.FALLING
|
||||
|
||||
inputs_same_gpio = list(
|
||||
[r_inp for r_inp in self.rpi_inputs if self.to_int(r_inp['gpio_pin']) == gpio_pin])
|
||||
|
||||
if len(inputs_same_gpio) > 1:
|
||||
GPIO.remove_event_detect(gpio_pin)
|
||||
for other_input in inputs_same_gpio:
|
||||
if other_input['edge'] is not edge:
|
||||
edge = GPIO.BOTH
|
||||
|
||||
if rpi_input['action_type'] == 'output_control':
|
||||
self._logger.info(
|
||||
"Adding GPIO event detect on pin %s with edge: %s", gpio_pin, edge)
|
||||
@@ -920,11 +961,14 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
filament_sensor['filament_sensor_enabled']):
|
||||
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"]):
|
||||
time_now = time.time()
|
||||
time_difference = self.to_int(time_now - last_detected_time)
|
||||
time_out_value = self.to_int(filament_sensor['filament_sensor_timeout'])
|
||||
if time_difference > time_out_value:
|
||||
self._logger.info("Detected end of filament.")
|
||||
for item in self.last_filament_end_detected:
|
||||
if item['index_id'] == filament_sensor['index_id']:
|
||||
item['time'] = time.time()
|
||||
item['time'] = time_now
|
||||
for line in self._settings.get(["filament_sensor_gcode"]).split('\n'):
|
||||
if line:
|
||||
self._printer.commands(line.strip().upper())
|
||||
@@ -981,24 +1025,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
self._logger.warn("Failed to stop task %s.", task)
|
||||
pass
|
||||
|
||||
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()
|
||||
def handle_initial_gpio_control(self):
|
||||
for rpi_input in [r_inp for r_inp in self.rpi_inputs if r_inp['action_type'] == 'output_control']:
|
||||
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()
|
||||
if rpi_output['output_type'] == 'regular':
|
||||
if rpi_input['controlled_io_set_value'] == 'toggle':
|
||||
val = GPIO.LOW if GPIO.input(self.to_int(
|
||||
rpi_output['gpio_pin'])) == GPIO.HIGH else GPIO.HIGH
|
||||
else:
|
||||
val = GPIO.LOW if rpi_input['controlled_io_set_value'] == '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['gpio_pin']), val)
|
||||
for notification in self.notifications:
|
||||
@@ -1017,7 +1052,6 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
if rpi_output['output_type'] == 'shell_output':
|
||||
command = rpi_output['shell_script']
|
||||
self.shell_command(command)
|
||||
except Exception as ex:
|
||||
self.log_error(ex)
|
||||
pass
|
||||
|
||||
@@ -1104,8 +1138,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
old_pwm_value = pwm['duty_cycle'] if 'duty_cycle' in pwm else -1
|
||||
if not self.to_int(old_pwm_value) == self.to_int(pwm_value):
|
||||
pwm['duty_cycle'] = pwm_value
|
||||
pwm_object.stop()
|
||||
pwm_object.start(pwm_value)
|
||||
pwm_object.ChangeDutyCycle(pwm_value)
|
||||
if self._settings.get(["debug"]) is True:
|
||||
self._logger.info(
|
||||
"Writing PWM on gpio: %s value %s", gpio, pwm_value)
|
||||
@@ -1174,6 +1207,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
if event == Events.PRINT_STARTED:
|
||||
self.print_complete = False
|
||||
self.cancel_all_events_on_queue()
|
||||
self.event_queue = []
|
||||
self.start_filament_detection()
|
||||
for rpi_output in self.rpi_outputs:
|
||||
if rpi_output['auto_startup']:
|
||||
@@ -1209,6 +1243,19 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
elif event in (Events.PRINT_CANCELLED, Events.PRINT_FAILED):
|
||||
self.stop_filament_detection()
|
||||
self.cancel_all_events_on_queue()
|
||||
self.event_queue = []
|
||||
for rpi_output in self.rpi_outputs:
|
||||
if rpi_output['shutdown_on_failed']:
|
||||
shutdown_time = rpi_output['shutdown_time']
|
||||
if rpi_output['output_type'] == 'pwm' and rpi_output['pwm_temperature_linked']:
|
||||
rpi_output['duty_cycle'] = rpi_output['default_duty_cycle']
|
||||
if rpi_output['auto_shutdown'] and not self.is_hour(shutdown_time):
|
||||
delay_seconds = self.to_float(shutdown_time)
|
||||
self.schedule_auto_shutdown_outputs(
|
||||
rpi_output, delay_seconds)
|
||||
if rpi_output['output_type'] == 'temp_hum_control':
|
||||
rpi_output['temp_ctr_set_value'] = 0
|
||||
self.run_tasks()
|
||||
|
||||
if event == Events.PRINT_DONE:
|
||||
for notification in self.notifications:
|
||||
@@ -1238,7 +1285,7 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
shutdown_delay_seconds, rpi_output, value, sufix)
|
||||
if rpi_output['output_type'] == 'pwm' and rpi_output['pwm_temperature_linked']:
|
||||
self.schedule_pwm_duty_on_queue(
|
||||
shutdown_delay_seconds, rpi_output, 0)
|
||||
shutdown_delay_seconds, rpi_output, 0, sufix)
|
||||
if (rpi_output['output_type'] == 'neopixel_indirect' or rpi_output['output_type'] == 'neopixel_direct'):
|
||||
self.add_neopixel_output_to_queue(
|
||||
rpi_output, shutdown_delay_seconds, 0, 0, 0, sufix)
|
||||
@@ -1345,9 +1392,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
|
||||
self.event_queue.append(dict(queue_id=queue_id, thread=thread))
|
||||
|
||||
def schedule_pwm_duty_on_queue(self, delay_seconds, rpi_output, value):
|
||||
queue_id = '{0!s}_{1!s}'.format(
|
||||
rpi_output['index_id'], "pwm_linked_temp")
|
||||
def schedule_pwm_duty_on_queue(self, delay_seconds, rpi_output, value, sufix):
|
||||
queue_id = '{0!s}_{1!s}_{2!s}'.format(
|
||||
rpi_output['index_id'], "pwm_linked_temp", sufix)
|
||||
thread = threading.Timer(delay_seconds,
|
||||
self.set_pwm_duty_cycle,
|
||||
args=[rpi_output, value, queue_id])
|
||||
@@ -1466,10 +1513,11 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
|
||||
"M82 ;Set extruder to Absolute Mode\n" +
|
||||
"G92 E0 ;Set Extruder to 0",
|
||||
use_sudo=True,
|
||||
neopixel_dma=10,
|
||||
debug=False,
|
||||
gcode_control=False,
|
||||
debug_temperature_log=False,
|
||||
useBoardPinNumber=False,
|
||||
use_board_pin_number=False,
|
||||
notification_provider="disabled",
|
||||
notification_api_key="",
|
||||
notification_event_name="printer_event",
|
||||
|
||||
@@ -3,7 +3,6 @@ import sys
|
||||
import time
|
||||
|
||||
LED_INVERT = False
|
||||
LED_DMA = 5
|
||||
LED_FREQ_HZ = 800000
|
||||
|
||||
if len(sys.argv) == 8:
|
||||
@@ -13,7 +12,7 @@ if len(sys.argv) == 8:
|
||||
red = int(sys.argv[4])
|
||||
green = int(sys.argv[5])
|
||||
blue = int(sys.argv[6])
|
||||
address = int(sys.argv[7], 16)
|
||||
LED_DMA = int(sys.argv[7], 16)
|
||||
else:
|
||||
print("fail")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -43,13 +43,17 @@ $(function () {
|
||||
});
|
||||
});
|
||||
|
||||
self.use_sudo = ko.observable();
|
||||
self.gcode_control = ko.observable();
|
||||
self.neopixel_dma = ko.observable();
|
||||
self.debug = ko.observable();
|
||||
self.debug_temperature_log = ko.observable();
|
||||
self.use_board_pin_number = 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.notifications = ko.observableArray([]);
|
||||
|
||||
self.humidityCapableSensor = function(sensor){
|
||||
if (['11', '22', '2302', 'bme280', 'si7021'].indexOf(sensor) >= 0){
|
||||
@@ -83,6 +87,11 @@ $(function () {
|
||||
});
|
||||
};
|
||||
|
||||
self.calculateRowSpan = function(index_id){
|
||||
span = self.linkedTemperatureControl(index_id())().length
|
||||
return span == 0 ? 1 : span;
|
||||
};
|
||||
|
||||
self.hasAnySensorWithHumidity = function(){
|
||||
return_value = false;
|
||||
self.rpi_inputs_temperature_sensors().forEach(function (sensor) {
|
||||
@@ -183,6 +192,7 @@ $(function () {
|
||||
return (output['index_id'] == item.index_id());
|
||||
}).pop();
|
||||
if (linked_output) {
|
||||
linked_output.gpio_status(output['status'])
|
||||
linked_output.auto_shutdown(output['auto_shutdown'])
|
||||
linked_output.auto_startup(output['auto_startup'])
|
||||
}
|
||||
@@ -256,24 +266,28 @@ $(function () {
|
||||
return duty_cycle;
|
||||
}
|
||||
|
||||
self.bindSettings = function(){
|
||||
self.bindFromSettings = function(){
|
||||
self.rpi_outputs(self.settingsViewModel.settings.plugins.enclosure.rpi_outputs());
|
||||
self.rpi_inputs(self.settingsViewModel.settings.plugins.enclosure.rpi_inputs());
|
||||
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.use_sudo(self.settingsViewModel.settings.plugins.enclosure.use_sudo());
|
||||
self.gcode_control(self.settingsViewModel.settings.plugins.enclosure.gcode_control());
|
||||
self.neopixel_dma(self.settingsViewModel.settings.plugins.enclosure.neopixel_dma());
|
||||
self.debug(self.settingsViewModel.settings.plugins.enclosure.debug());
|
||||
self.debug_temperature_log(self.settingsViewModel.settings.plugins.enclosure.debug_temperature_log());
|
||||
self.use_board_pin_number(self.settingsViewModel.settings.plugins.enclosure.use_board_pin_number());
|
||||
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.onBeforeBinding = function () {
|
||||
self.bindSettings();
|
||||
self.bindFromSettings();
|
||||
};
|
||||
|
||||
self.onSettingsBeforeSave = function() {
|
||||
self.bindSettings();
|
||||
self.bindFromSettings();
|
||||
};
|
||||
|
||||
self.onStartupComplete = function () {
|
||||
@@ -363,6 +377,7 @@ $(function () {
|
||||
controlled_io_set_value: ko.observable("Low"),
|
||||
startup_time: ko.observable(0),
|
||||
auto_shutdown: ko.observable(false),
|
||||
shutdown_on_failed: ko.observable(false),
|
||||
shutdown_time: ko.observable(0),
|
||||
linked_temp_sensor: ko.observable(""),
|
||||
alarm_set_temp: ko.observable(0),
|
||||
|
||||
@@ -219,6 +219,15 @@
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: $data.auto_shutdown -->
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" data-bind="checked: shutdown_on_failed"> {{ _('Shutdown on Failed or Canceled') }}
|
||||
</label>
|
||||
<span class="help-inline">Choose if output should turn off automatomatically when print is canceled or fails</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-bind="attr: {id: 'auto_shutdownField_' + $index() }">
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Shutdown Delay / Hour') }}</label>
|
||||
@@ -310,13 +319,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ko if: $data.auto_startup || $data.startup_with_server -->
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Default Value') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: temp_ctr_default_value">
|
||||
<span class="help-inline">Default temperature / humidity that temperature control will be set when the print starts.</span>
|
||||
<span class="help-inline">Default temperature / humidity that temperature control will be set when the print starts or the server starts.</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Value Deadband') }}</label>
|
||||
<div class="controls">
|
||||
@@ -516,7 +528,7 @@
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: ds18b20_serial" value="">
|
||||
<span class="help-inline">DS18B20 serial value, needs to be used to have support for multiple sensors, read documentation on github page
|
||||
for more information</span>
|
||||
for more information. The serial is typically in the form of 28-0123456789ab.</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
@@ -732,6 +744,13 @@
|
||||
<a href=" https://github.com/vitormhenrique/OctoPrint-Enclosure">github</a> page</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Neopixel DMA Channel') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: settingsViewModel.settings.plugins.enclosure.neopixel_dma">
|
||||
<span class="help-inline">DMA channel used on direct control of neopixel.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
@@ -740,7 +759,7 @@
|
||||
<span class="help-inline">Log additional information on octoprint log to help trouble shoot the plugin</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ko if: ($root.settingsViewModel.settings.plugins.enclosure.debug()) -->
|
||||
<!-- ko if: ($root.debug()) -->
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
@@ -753,7 +772,7 @@
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" data-bind="checked: settingsViewModel.settings.plugins.enclosure.useBoardPinNumber"> {{ _('Use Board Pin #') }}
|
||||
<input type="checkbox" data-bind="checked: settingsViewModel.settings.plugins.enclosure.use_board_pin_number"> {{ _('Use Board Pin #') }}
|
||||
</label>
|
||||
<span class="help-inline">Use BOARD pin numbers instead of BCM pin numbers</span>
|
||||
</div>
|
||||
@@ -767,7 +786,7 @@
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="settings-enclosure-filament-sensor">{{ _('Filament Change Gcode') }}</label>
|
||||
<label class="control-label">{{ _('Filament Change Gcode') }}</label>
|
||||
<div class="controls">
|
||||
<textarea rows="4" class="block" data-bind="value: settingsViewModel.settings.plugins.enclosure.filament_sensor_gcode"></textarea>
|
||||
<span class="help-inline">GCODE that will be sent to the printer to pause and allow filament to be changed. You should add
|
||||
@@ -788,17 +807,17 @@
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Event Name') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value: settingsViewModel.settings.plugins.enclosure.notification_event_name">
|
||||
<input type="text" class="input-block-level" data-bind="value: notification_event_name">
|
||||
<span class="help-inline">Event name that was configured on the maker chanel of IFTTT, don't use space between the words</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('IFTTT API KEY') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" data-bind="value:settingsViewModel.settings.plugins.enclosure.notification_api_key">
|
||||
<input type="text" class="input-block-level" data-bind="value: notification_api_key">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="foreach: settingsViewModel.settings.plugins.enclosure.notifications">
|
||||
<div class="control-group" data-bind="foreach: notifications">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" data-bind="checked: temperatureAction"> {{ _('Notify temperature actions') }}
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
<!-- ko foreach: $root.rpi_inputs_temperature_sensors() -->
|
||||
<tr>
|
||||
<th class="temperature_sensor" data-bind="text: label, attr: {title: label, rowspan: $root.linkedTemperatureControl(index_id())().length}"></th>
|
||||
<td class="temperature_actual" data-bind="attr: {rowspan: $root.linkedTemperatureControl(index_id())().length}">
|
||||
<th class="temperature_sensor" data-bind="text: label, attr: {title: label, rowspan: $root.calculateRowSpan(index_id)}"></th>
|
||||
<td class="temperature_actual" data-bind="attr: {rowspan: $root.calculateRowSpan(index_id)}">
|
||||
<span data-bind="text: temp_sensor_temp, attr: {title: temp_sensor_temp}"> </span>
|
||||
<!-- ko if: (use_fahrenheit()) -->
|
||||
<span class="add-on">°F</span>
|
||||
@@ -31,7 +31,7 @@
|
||||
<!-- /ko -->
|
||||
</td>
|
||||
<!-- ko if: ($root.humidityCapableSensor(temp_sensor_type())) -->
|
||||
<td class="humidity_actual" data-bind="attr: {rowspan: $root.linkedTemperatureControl(index_id())().length}">
|
||||
<td class="humidity_actual" data-bind="attr: {rowspan: $root.calculateRowSpan(index_id)}">
|
||||
<span data-bind="text: temp_sensor_humidity, attr: {title: temp_sensor_humidity}"> </span>
|
||||
<span class="add-on">%</span>
|
||||
</td>
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
<!-- ko if: ($root.hasAnySensorWithHumidity()) -->
|
||||
<!-- ko ifnot: ($root.humidityCapableSensor(temp_sensor_type())) -->
|
||||
<td class="humidity_actual" data-bind="attr: {rowspan: $root.linkedTemperatureControl(index_id())().length}">N/A</td>
|
||||
<td class="humidity_actual" data-bind="attr: {rowspan: $root.calculateRowSpan(index_id)}">N/A</td>
|
||||
<!-- /ko -->
|
||||
<!-- /ko -->
|
||||
|
||||
@@ -216,6 +216,12 @@
|
||||
<!-- ko if: ($data.temp_ctr_type() == "dehumidifier") -->
|
||||
<span class="badge badge-warning">Dehumidifier</span>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: ($data.gpio_status()) -->
|
||||
<span class="badge badge-success help-inline">on</span>
|
||||
<!-- /ko -->
|
||||
<!-- ko ifnot: ($data.gpio_status()) -->
|
||||
<span class="badge badge-important help-inline">off</span>
|
||||
<!-- /ko -->
|
||||
</h4>
|
||||
<!-- /ko -->
|
||||
|
||||
@@ -286,4 +292,4 @@
|
||||
<!-- /ko -->
|
||||
</h4>
|
||||
<!-- /ko -->
|
||||
<!-- /ko -->
|
||||
<!-- /ko -->
|
||||
|
||||
@@ -42,7 +42,7 @@ def main():
|
||||
# Divide by 16 to get value in celsius
|
||||
temp /= 16.0
|
||||
|
||||
print temp
|
||||
print('{0:0.1f}'.format(temp))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
2
setup.py
2
setup.py
@@ -14,7 +14,7 @@ plugin_package = "octoprint_enclosure"
|
||||
plugin_name = "OctoPrint-Enclosure"
|
||||
|
||||
# The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module
|
||||
plugin_version = "3.51"
|
||||
plugin_version = "4.09"
|
||||
|
||||
# The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin
|
||||
# module
|
||||
|
||||
Reference in New Issue
Block a user