Skip to content

Commit

Permalink
Added full support for Adafruit DotStar LED Strips.
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGirderboot committed Nov 16, 2021
1 parent 770e550 commit 9dcc544
Show file tree
Hide file tree
Showing 5 changed files with 327 additions and 5 deletions.
133 changes: 131 additions & 2 deletions octoprint_enclosure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ def on_after_startup(self):
self.generate_temp_hum_control_status()
self.setup_gpio()
self.configure_gpio()
self.update_ui()
self.start_outpus_with_server()
self.update_ui()
self.handle_initial_gpio_control()
self.start_timer()
self.print_complete = False
Expand Down Expand Up @@ -682,6 +682,48 @@ def set_neopixel_old(self):

return jsonify(success=True)

@octoprint.plugin.BlueprintPlugin.route("/setDotstar", methods=["GET"])
def set_dotstar_old(self):
""" set_dotstar method get request from octoprint and send the command to dotstar"""
gpio_index = self.to_int(request.values["index_id"])
action = request.values["action"]

for rpi_output in self.rpi_outputs:
if gpio_index == self.to_int(rpi_output['index_id']):
#self._logger.info("DotStar Output Data: %s", rpi_output)
led_count = rpi_output['dotstar_count']
use_spi = rpi_output['dotstar_use_spi']
if use_spi == True:
data_pin = 0
clock_pin = 0
else:
data_pin =self.to_int(rpi_output['dotstar_data_pin'])
clock_pin = self.to_int(rpi_output['dotstar_clock_pin'])

if action == "setColor" :
active = True
red = request.values["red"]
green = request.values["green"]
blue = request.values["blue"]
led_brightness = request.values["brightness"]
elif action == "setPower":
led_brightness = rpi_output['dotstar_brightness']
#self._logger.info("DotStar Requested Power: %s", request.values["status"])
if request.values["status"] == "true":
active = True
else:
active = False

if rpi_output['dotstar_color'] is None:
red, green, blue = self.get_color_from_rgb(rpi_output['default_dotstar_color'])
else:
red, green, blue = self.get_color_from_rgb(rpi_output['dotstar_color'])


self.send_dotstar_command(gpio_index, active, data_pin, clock_pin, led_count, led_brightness, red, green, blue)

return jsonify(success=True)

@octoprint.plugin.BlueprintPlugin.route("/setLedstripColor", methods=["GET"])
def set_ledstrip_color_old(self):
""" set_ledstrip_color method get request from octoprint and send the command to Open-Smart RGB LED Strip"""
Expand All @@ -695,7 +737,6 @@ def set_ledstrip_color_old(self):

# DEPREACTION END


# GPIO over i2c

def gpio_i2c_input(self, output, active_low=None):
Expand Down Expand Up @@ -754,6 +795,44 @@ def gpio_i2c_write(self, output, state, queue_id=None):
pass


def send_dotstar_command(self, index_id, active, data_pin, clock_pin, led_count, led_brightness, red, green, blue, queue_id=None):
if queue_id is not None:
self._logger.debug("running scheduled queue id %s", queue_id)
self.stop_queue_item(queue_id)

# Import here so we don't rely on this library when no dotstar strip is in use.
try:
import board
import adafruit_dotstar as dotstar

self._logger.info("DotStar Modules Imported")

# Assume SPI if clock or data pin is 0
if ((self.to_int(data_pin) == 0) or (self.to_int(clock_pin) == 0)):
clock_pin = board.SCK
data_pin = board.MOSI

dots = dotstar.DotStar(clock_pin, data_pin, self.to_int(led_count), brightness=self.to_float(led_brightness))
if active:
self._logger.info("Setting DotStar color and brightness")
dots.fill((self.to_int(red),self.to_int(green),self.to_int(blue)))

# Update color, brightness, and power with current values sent to the strip
for rpi_output in self.rpi_outputs:
if self.to_int(index_id) == self.to_int(rpi_output['index_id']):
rpi_output['dotstar_color'] = 'rgb({0!s},{1!s},{2!s})'.format(red, green, blue)
rpi_output['dotstar_brightness'] = led_brightness
rpi_output['dotstar_active'] = True
else:
self._logger.info("Turning off DotStar")
dots.fill(0)
for rpi_output in self.rpi_outputs:
if self.to_int(index_id) == self.to_int(rpi_output['index_id']):
rpi_output['dotstar_active'] = False
self.update_ui_outputs()
except Exception as ex:
self._logger.warn(ex)

def send_neopixel_command(self, led_pin, led_count, led_brightness, red, green, blue, address, neopixel_dirrect,
index_id, queue_id=None):
"""Send neopixel command
Expand Down Expand Up @@ -920,6 +999,7 @@ def update_ui_outputs(self):
regular_status = []
pwm_status = []
neopixel_status = []
dotstar_status = []
temp_control_status = []
for output in self.rpi_outputs:
index = self.to_int(output['index_id'])
Expand All @@ -945,6 +1025,12 @@ def update_ui_outputs(self):
val = output['neopixel_color']
neopixel_status.append(
dict(index_id=index, color=val, auto_startup=startup, auto_shutdown=shutdown))
if output['output_type'] == 'dotstar':
col = output['dotstar_color']
level = output['dotstar_brightness']
pwr = output['dotstar_active']
dotstar_status.append(
dict(index_id=index, color=col, brightness=level, active=pwr, auto_startup=startup, auto_shutdown=shutdown))
if output['output_type'] == 'pwm':
for pwm in self.pwm_instances:
if pin in pwm:
Expand All @@ -958,6 +1044,7 @@ def update_ui_outputs(self):
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_dotstar=dotstar_status,
rpi_output_temp_hum_ctrl=temp_control_status))
except Exception as ex:
self.log_error(ex)
Expand Down Expand Up @@ -1883,6 +1970,9 @@ def schedule_auto_shutdown_outputs(self, rpi_output, shutdown_delay_seconds):
self.schedule_pwm_duty_on_queue(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)
if (rpi_output['output_type'] == 'dotstar'):
active = False
self.add_dotstar_output_to_queue(rpi_output, shutdown_delay_seconds, active, 0, 0, 0, 0, sufix)
if rpi_output['output_type'] == 'temp_hum_control':
value = 0
self.add_temperature_output_temperature_queue(shutdown_delay_seconds, rpi_output, value, sufix)
Expand Down Expand Up @@ -1925,6 +2015,20 @@ def start_outpus_with_server(self):
neopixel_direct = 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_direct, index_id)
if (rpi_output['output_type'] == 'dotstar'):
index_id = self.to_int(rpi_output['index_id'])
red, green, blue = self.get_color_from_rgb(rpi_output['default_dotstar_color'])
brightness = rpi_output['default_dotstar_brightness']
led_count = rpi_output['dotstar_count']
use_spi = rpi_output['dotstar_use_spi']
if use_spi == True:
data_pin = 0
clock_pin = 0
else:
data_pin =self.to_int(rpi_output['dotstar_data_pin'])
clock_pin = self.to_int(rpi_output['dotstar_clock_pin'])
active = True
self.send_dotstar_command(index_id, active, data_pin, clock_pin, led_count, brightness, red, green, blue)
if rpi_output['output_type'] == 'temp_hum_control':
rpi_output['temp_ctr_set_value'] = rpi_output['temp_ctr_default_value']

Expand All @@ -1941,6 +2045,11 @@ def schedule_auto_startup_outputs(self, rpi_output, delay_seconds):
if (rpi_output['output_type'] == 'neopixel_indirect' or rpi_output['output_type'] == 'neopixel_direct'):
red, green, blue = self.get_color_from_rgb(rpi_output['default_neopixel_color'])
self.add_neopixel_output_to_queue(rpi_output, delay_seconds, red, green, blue, sufix)
if (rpi_output['output_type'] == 'dotstar'):
red, green, blue = self.get_color_from_rgb(rpi_output['default_dotstar_color'])
brightness = rpi_output['default_dotstar_brightness']
active = True
self.add_dotstar_output_to_queue(rpi_output, delay_seconds, active, red, green, blue, brightness, sufix)
if rpi_output['output_type'] == 'temp_hum_control':
value = rpi_output['temp_ctr_default_value']
self.add_temperature_output_temperature_queue(delay_seconds, rpi_output, value, sufix)
Expand Down Expand Up @@ -1985,6 +2094,26 @@ def add_neopixel_output_to_queue(self, rpi_output, delay_seconds, red, green, bl

self.event_queue.append(dict(queue_id=queue_id, thread=thread))

def add_dotstar_output_to_queue(self, rpi_output, delay_seconds, active, red, green, blue, brightness, sufix):
led_count = rpi_output['dotstar_count']
use_spi = rpi_output['dotstar_use_spi']
if use_spi == True:
data_pin = 0
clock_pin = 0
else:
data_pin =self.to_int(rpi_output['dotstar_data_pin'])
clock_pin = self.to_int(rpi_output['dotstar_clock_pin'])

index_id = self.to_int(rpi_output['index_id'])
queue_id = '{0!s}_{1!s}'.format(index_id, sufix)

self._logger.debug("Scheduling dotstar output id %s for on %s delay_seconds", queue_id, delay_seconds)

thread = threading.Timer(delay_seconds, self.send_dotstar_command,
args=[index_id, active, data_pin, clock_pin, led_count, brightness, red, green, blue, queue_id])
# (self, index_id, active, data_pin, clock_pin, led_count, led_brightness, red, green, blue
self.event_queue.append(dict(queue_id=queue_id, thread=thread))

def add_pwm_output_to_queue(self, delay_seconds, rpi_output, value, sufix):
queue_id = '{0!s}_{1!s}'.format(rpi_output['index_id'], sufix)

Expand Down
96 changes: 95 additions & 1 deletion octoprint_enclosure/static/js/enclosure.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ $(function () {
self.hasAnyNavbarOutput = function(){
return_value = false;
self.rpi_outputs().forEach(function (output) {
if ((output.output_type()=="regular" || output.output_type()=="gcode_output") && output.show_on_navbar()) {
if ((output.output_type()=="regular" || output.output_type()=="gcode_output" || output.output_type()=="dotstar" ) && output.show_on_navbar()) {
return_value = true;
return false;
}
Expand Down Expand Up @@ -225,6 +225,21 @@ $(function () {
})
}

if (data.hasOwnProperty("rpi_output_dotstar")) {
data.rpi_output_dotstar.forEach(function (output) {
var linked_output = ko.utils.arrayFilter(self.rpi_outputs(), function (item) {
return (output['index_id'] == item.index_id());
}).pop();
if (linked_output) {
linked_output.dotstar_color(output['color'])
linked_output.dotstar_active(output['active'])
linked_output.dotstar_brightness(output['brightness'])
linked_output.auto_shutdown(output['auto_shutdown'])
linked_output.auto_startup(output['auto_startup'])
}
})
}

if (data.hasOwnProperty("rpi_output_ledstrip")) {
data.rpi_output_ledstrip.forEach(function (output) {
var linked_output = ko.utils.arrayFilter(self.rpi_outputs(), function (item) {
Expand Down Expand Up @@ -414,6 +429,18 @@ $(function () {
new_neopixel_color: ko.observable(""),
neopixel_count: ko.observable(0),
neopixel_brightness: ko.observable(255),
dotstar_color: ko.observable("rgb(0,0,0)"),
default_dotstar_color: ko.observable(""),
new_dotstar_color: ko.observable(""),
new_dotstar_brightness: ko.observable(""),
dotstar_count: ko.observable(0),
dotstar_brightness: ko.observable(1),
default_dotstar_brightness: ko.observable(""),
dotstar_use_spi: ko.observable(true),
dotstar_gpio_clk: ko.observable(""),
dotstar_gpio_dat: ko.observable(""),
dotstar_brightness: ko.observable(""),
dotstar_active: ko.observable(false),
ledstrip_color: ko.observable("rgb(0,0,0)"),
default_ledstrip_color: ko.observable(""),
new_ledstrip_color: ko.observable(""),
Expand Down Expand Up @@ -670,6 +697,73 @@ $(function () {
}
};

self.handleDotstarColor = function (item) {
self.handleDotstar(item, item.new_dotstar_color(), item.dotstar_brightness())
}

self.handleDotstarBrightness = function (item) {
self.handleDotstar(item, item.dotstar_color(), item.new_dotstar_brightness())
}

self.handleDotstar = function (item, color, brightness) {

var index = item.index_id() ;
//var or_tempStr = item.new_dotstar_color();
var tempStr = color.replace("rgb(", "");

var r = parseInt(tempStr.substring(0, tempStr.indexOf(",")));
tempStr = tempStr.slice(tempStr.indexOf(",") + 1);
var g = parseInt(tempStr.substring(0, tempStr.indexOf(",")));
tempStr = tempStr.slice(tempStr.indexOf(",") + 1);
var b = parseInt(tempStr.substring(0, tempStr.indexOf(")")));

if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || isNaN(r) || isNaN(g) || isNaN(b)) {
new PNotify({
title: "Enclosure",
text: "Color needs to follow the format rgb(value_red,value_green,value_blue)!",
type: "error"
});
} else {
$.ajax({
type: "GET",
dataType: "json",
data: {
"index_id": index,
"action": "setColor",
"red": r,
"green": g,
"blue": b,
"brightness": brightness
},
url: self.buildPluginUrl("/setDotstar"),
success: function (data) {
item.new_dotstar_color("");
self.getUpdateUI();
}
});
}
};

self.handleDotstarPower = function (item, form) {

var request = {
"status": !item.dotstar_active(),
"index_id": item.index_id(),
"action": "setPower"
};

$.ajax({
type: "GET",
dataType: "json",
data: request,
url: self.buildPluginUrl("/setDotstar"),
success: function (data) {
self.getUpdateUI();
}
});
};


self.handleLedstripColor = function (item) {
var index = item.index_id() ;
var or_tempStr = item.new_ledstrip_color();
Expand Down
14 changes: 14 additions & 0 deletions octoprint_enclosure/templates/enclosure_navbar.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@
</li>
<!-- /ko -->

<!-- ko if: ($data.output_type() == "dotstar") -->
<li>
<a href="javascript:void(0)" data-bind="click: $root.handleDotstarPower">
<span data-bind="html: label"> </span>
<!-- ko if: ($data.dotstar_active()) -->
<span class="badge badge-success help-inline">on</span>
<!-- /ko -->
<!-- ko ifnot: ($data.dotstar_active()) -->
<span class="badge badge-important help-inline">off</span>
<!-- /ko -->
</a>
</li>
<!-- /ko -->

<!-- ko if: ($data.output_type() == "gcode_output") -->
<!-- ko if: ($root.isOperational()) -->
<li>
Expand Down

0 comments on commit 9dcc544

Please sign in to comment.