regular gpio tested and working

This commit is contained in:
Vitor de Miranda Henrique
2018-02-25 23:55:31 -06:00
parent c1047d020c
commit c3df6eccc3
5 changed files with 147 additions and 103 deletions

View File

@@ -15,8 +15,16 @@ import octoprint.util
import requests
import inspect
import threading
import json
# 28-0000062410dc
# 18b20 sensor serial --> 28-0000062410dc
# SI7021 addrress --> 40
# BTN 22 -> active low | close to the blue thing)
# BTN 23 -> active high
# LED GREEN -> 17 active on high
# LED RED -> 24 active on low
# Neopixel -> pin 18 (needs sudo)
class EnclosurePlugin(octoprint.plugin.StartupPlugin,
@@ -76,15 +84,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
self.fix_data()
self.pwm_intances = []
self.event_queue = []
self.rpi_outputs_not_changed = []
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.rpi_outputs_not_changed = []
self.start_timer()
self.setup_gpio()
self.configure_gpio()
self.update_ui()
self.start_timer()
# ~~ Blueprintplugin mixin
@octoprint.plugin.BlueprintPlugin.route("/setEnclosureTemperature", methods=["GET"])
@@ -99,10 +107,10 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
self.handle_temperature_control()
return flask.jsonify(success=True)
@octoprint.plugin.BlueprintPlugin.route("/getEnclosureSetTemperature", methods=["GET"])
def get_enclosure_set_temperature(self):
self.update_ui_set_temperature()
return flask.jsonify(success=True)
# @octoprint.plugin.BlueprintPlugin.route("/getEnclosureSetTemperature", methods=["GET"])
# def get_enclosure_set_temperature(self):
# self.update_ui_set_temperature()
# return flask.jsonify(success=True)
@octoprint.plugin.BlueprintPlugin.route("/clearGPIOMode", methods=["GET"])
def clear_gpio_mode(self):
@@ -116,22 +124,22 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
@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['gpio_pin'])
gpio_status = []
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 (
not GPIO.input(pin))
if result:
result = result + ', '
result = result + \
'"' + str(pin) + '": ' + str(val).lower()
return '{' + result + '}'
index = self.to_int(rpi_output['index_id'])
# result.append(dict(index_id=rpi_output['index_id'], value=val))
gpio_status.append(dict(index_id=index, status=val))
self._logger.warn("######### gpio_status: %s", gpio_status)
return flask.Response(json.dumps(gpio_status), mimetype='application/json')
@octoprint.plugin.BlueprintPlugin.route("/getEnclosureTemperature", methods=["GET"])
def get_enclosure_temperature(self):
self.update_ui_current_temperature()
return flask.jsonify(success=True)
# @octoprint.plugin.BlueprintPlugin.route("/getEnclosureTemperature", methods=["GET"])
# def get_enclosure_temperature(self):
# self.update_ui_current_temperature()
# return flask.jsonify(success=True)
@octoprint.plugin.BlueprintPlugin.route("/setIO", methods=["GET"])
def set_io(self):
@@ -571,7 +579,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
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']))
gpio_pin = self.to_int(gpio_out['gpio_pin'])
if gpio_pin not in self.rpi_outputs_not_changed:
GPIO.cleanup(gpio_pin)
for gpio_in in list(filter(lambda item: item['input_type'] == 'gpio', self.rpi_inputs)):
try:
@@ -612,10 +622,15 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
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)
if pin not in self.rpi_outputs_not_changed:
self._logger.info(
"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):
self.pwm_intances.remove(pwm)
self.clear_channel(pin)
@@ -629,15 +644,17 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
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)
gpio_pin = self.to_int(rpi_input['gpio_pin'])
GPIO.setup(gpio_pin, GPIO.IN, pullResistor)
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)
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)
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)
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:
template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}"
message = template.format(
@@ -724,25 +741,26 @@ 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['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['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(
rpi_output['gpio_pin'])) == GPIO.HIGH else GPIO.HIGH
else:
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:
if notification['gpioAction']:
msg = "GPIO control action caused by input " + str(rpi_input['label']) + ". Setting GPIO" + str(
rpi_input['controlled_io']) + " to: " + str(rpi_input['controlled_io_set_value'])
self.send_notification(msg)
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()
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_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
self.write_gpio(self.to_int(
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['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{2!r}"
message = template.format(
@@ -768,7 +786,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
elif rpi_input['printer_action'] == 'stop_temperature_control':
self._logger.info(
"Printer action stoping temperature control.")
self.enclosure_set_temperature = 0
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()
for notification in self.notifications:
if notification['printer_action']:
@@ -790,9 +810,9 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
self._logger.info("Writing on gpio: %s value %s", gpio, value)
self.update_ui()
except Exception as ex:
template = "An exception of type {0} occurred on {1}. Arguments:\n{2!r}"
template = "An exception of type {0} occurred on {1} when writing on pin {2}. Arguments:\n{3!r}"
message = template.format(
type(ex).__name__, inspect.currentframe().f_code.co_name, ex.args)
type(ex).__name__, inspect.currentframe().f_code.co_name, gpio, ex.args)
self._logger.warn(message)
pass
@@ -819,7 +839,8 @@ 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['gpio_pin']))
if rpi_output['output_type'] == 'regular':
result.append(self.to_int(rpi_output['gpio_pin']))
return result
def send_notification(self, message):
@@ -907,14 +928,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
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_set_temperature()
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()
self.enclosure_set_temperature = 0
self._plugin_manager.send_plugin_message(
self._identifier, dict(enclosureSetTemp=self.enclosure_set_temperature))
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
@@ -934,8 +954,13 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
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 = []
if event == Events.PRINT_DONE:
for notification in self.notifications:
@@ -962,6 +987,8 @@ class EnclosurePlugin(octoprint.plugin.StartupPlugin,
for pin in (pin for pin in outputsBeforeSave if pin not in commonPins):
self.clear_channel(pin)
self._logger.info("Pins not changed: %s", commonPins)
self.rpi_outputs_not_changed = commonPins
self.clear_gpio()

View File

@@ -27,7 +27,7 @@
#enclosure-table th.humidity_actual,
#enclosure-table td.humidity_actual {
width: 20%;
width: 15%;
}
#enclosure-table th.temperature_control,
@@ -37,7 +37,7 @@
#enclosure-table th.temperature_target,
#enclosure-table td.temperature_target {
width: 30%;
width: 35%;
overflow: visible;
}

View File

@@ -12,19 +12,19 @@ $(function () {
self.rpi_inputs = ko.observableArray();
self.rpi_outputs_regular = ko.pureComputed(function () {
return ko.utils.arrayFilter(self.settingsViewModel.settings.plugins.enclosure.rpi_outputs(), function (item) {
return ko.utils.arrayFilter(self.rpi_outputs(), function (item) {
return (item.output_type() === "regular");
});
});
self.rpi_outputs_pwm = ko.pureComputed(function () {
return ko.utils.arrayFilter(self.settingsViewModel.settings.plugins.enclosure.rpi_outputs(), function (item) {
return ko.utils.arrayFilter(self.rpi_outputs(), function (item) {
return (item.output_type() === "pwm");
});
});
self.rpi_inputs_temperature_sensors = ko.pureComputed(function () {
return ko.utils.arrayFilter(self.settingsViewModel.settings.plugins.enclosure.rpi_inputs(), function (item) {
return ko.utils.arrayFilter(self.rpi_inputs(), function (item) {
return (item.input_type() === "temperature_sensor");
});
});
@@ -48,7 +48,7 @@ $(function () {
return ko.pureComputed(function () {
return ko.utils.arrayFilter(self.settingsViewModel.settings.plugins.enclosure.rpi_outputs(), function (item) {
if (item.linked_temp_sensor){
return (item.linked_temp_sensor() == sensor_index);
return (item.linked_temp_sensor() == sensor_index && item.output_type() == "temperature_control");
}else{
return false;
}
@@ -221,7 +221,7 @@ $(function () {
}
self.onSettingsHidden = function () {
// self.bindSettings();
self.bindSettings();
// self.requestEnclosureTemperature();
};
@@ -230,6 +230,7 @@ $(function () {
return rpi_outputs.output_type == 'regular';
});
};
self.setTemperature = function (item, form) {
var newSetTemperature = item.temp_ctr_new_set_temp();
@@ -239,14 +240,16 @@ $(function () {
if(self.isNumeric(newSetTemperature)){
var request = {set_temperature:newSetTemperature, index_id:item.index_id()};
$.ajax({
url: self.buildPluginUrl("/setEnclosureTemperature"),
type: "GET",
dataType: "json",
data: request,
success: function (data) {
success: function (data) {
item.temp_ctr_new_set_temp("");
item.temp_ctr_set_temp(newSetTemperature);
self.getUpdateUI();
},
error: function (textStatus, errorThrown) {
new PNotify({
@@ -303,12 +306,14 @@ $(function () {
});
// var test = self.settingsViewModel.settings.plugins.enclosure.rpi_outputs();
// console.log(self.rpi_outputs_regular());
self.bindSettings();
};
self.removeRpiOutput = function (data) {
self.settingsViewModel.settings.plugins.enclosure.rpi_outputs.remove(data);
self.bindSettings();
};
self.addRpiInput = function () {
@@ -338,26 +343,26 @@ $(function () {
filament_sensor_timeout: ko.observable(120),
filament_sensor_enabled: ko.observable(true)
});
self.bindSettings();
};
self.removeRpiInput = function (definition) {
self.settingsViewModel.settings.plugins.enclosure.rpi_inputs.remove(definition);
self.bindSettings();
};
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));
// }
// });
var request = { set_temperature: 0, index_id: item.index_id() };
$.ajax({
url: self.buildPluginUrl("/setEnclosureTemperature"),
type: "GET",
dataType: "json",
data: request,
success: function (data) {
self.getUpdateUI();
}
});
};
self.clearGPIOMode = function () {
@@ -382,27 +387,27 @@ $(function () {
});
};
self.requestEnclosureTemperature = function () {
console.log("Requesting enclosure temperature");
return $.ajax({
type: "GET",
url: self.buildPluginUrl("/getEnclosureTemperature"),
async: false
}).responseText;
};
// self.requestEnclosureTemperature = function () {
// console.log("Requesting enclosure temperature");
// return $.ajax({
// type: "GET",
// url: self.buildPluginUrl("/getEnclosureTemperature"),
// async: false
// }).responseText;
// };
self.requestEnclosureSetTemperature = function () {
$.ajax({
url: self.buildPluginUrl("/getEnclosureSetTemperature"),
type: "GET",
error: function (textStatus, errorThrown) {
new PNotify({
title: "Enclosure",
text: "Error geting set temperatures",
type: "error"
});
}});
};
// self.requestEnclosureSetTemperature = function () {
// $.ajax({
// url: self.buildPluginUrl("/getEnclosureSetTemperature"),
// type: "GET",
// error: function (textStatus, errorThrown) {
// new PNotify({
// title: "Enclosure",
// text: "Error geting set temperatures",
// type: "error"
// });
// }});
// };
self.handleIO = function (item, form) {

View File

@@ -475,7 +475,7 @@
<div class="control-group">
<label class="control-label"> Controlled IO</label>
<div class="controls">
<select data-bind="options: $root.settingsViewModel.settings.plugins.enclosure.rpi_outputs, optionsText: 'label',
<select data-bind="options: $root.rpi_outputs_regular, optionsText: 'label',
optionsValue: 'index_id', value: $data.controlled_io">
</select>
<span class="help-inline">When the event happen, you want control which IO?</span>

View File

@@ -21,9 +21,18 @@
<!-- 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="text: temp_sensor_temp, attr: {title: temp_sensor_temp, rowspan: $root.linkedTemperatureControl(index_id())().length}"></td>
<td class="temperature_actual" data-bind="attr: {rowspan: $root.linkedTemperatureControl(index_id())().length}">
<span data-bind="text: temp_sensor_temp, attr: {title: temp_sensor_temp}"> </span>
<!-- ko if: (use_fahrenheit()) -->
<span class="add-on">&deg;F</span>
<!-- /ko -->
<!-- ko ifnot: (use_fahrenheit()) -->
<span class="add-on">&deg;C</span>
<!-- /ko -->
</td>
<!-- ko if: ($root.humidityCapableSensor(temp_sensor_type())) -->
<td class="humidity_actual" data-bind="html: temp_sensor_humidity, attr: {title: temp_sensor_humidity, rowspan: $root.linkedTemperatureControl(index_id())().length}">
<td class="humidity_actual" data-bind="attr: {rowspan: $root.linkedTemperatureControl(index_id())().length}">
<span data-bind="text: temp_sensor_humidity, attr: {title: temp_sensor_humidity}"> </span>
<span class="add-on">%</span>
</td>
<!-- /ko -->
@@ -34,7 +43,6 @@
<!-- /ko -->
<!-- /ko -->
<!-- ko if: ($root.linkedTemperatureControl(index_id())().length > 0 || $root.hasAnyTemperatureControl()) -->
<!-- ko with: $root.linkedTemperatureControl(index_id())()[0] -->
<th class="temperature_control" data-bind="html: label, attr: {title: label}"></th>
@@ -42,8 +50,12 @@
<form class="form-inline" style="margin:0" data-bind="submit: function(element) { $root.setTemperature($data, element) }">
<div class="input-prepend input-append">
<input type="number" min="0" max="999" class="input-mini input-nospin" data-bind="value: temp_ctr_new_set_temp, valueUpdate: 'input', attr: {placeholder:$root.getCleanTemperature(temp_ctr_set_temp()), id: 'temp_control_' + index_id()}">
<span class="add-on" data-bind="visible: $parent.use_fahrenheit">&deg;F</span>
<span class="add-on" data-bind="visible: $parent.use_fahrenheit">&deg;C</span>
<!-- ko if: ($parent.use_fahrenheit()) -->
<span class="add-on">&deg;F</span>
<!-- /ko -->
<!-- ko ifnot: ($parent.use_fahrenheit()) -->
<span class="add-on">&deg;C</span>
<!-- /ko -->
</div>
<div class="btn-group">
<button type="submit" data-bind="enable: $root.enableBtn()" class="btn btn-primary" title="{{ _('Set') }}">
@@ -70,6 +82,7 @@
<!-- /ko -->
<!-- /ko -->
</tr>
<!-- ko if: ($root.hasAnyTemperatureControl()) -->
<!-- ko foreach: $root.linkedTemperatureControl(index_id())-->
<!-- ko ifnot: ($index() == 0) -->
@@ -79,7 +92,6 @@
</tr>
<!-- /ko -->
<!-- /ko -->
<!-- /ko -->
<!-- /ko -->