Skip to content

Commit

Permalink
merged main into master for 1.5 release
Browse files Browse the repository at this point in the history
  • Loading branch information
EricHigdon committed Sep 7, 2019
2 parents 0df238a + 021ef48 commit 57b944f
Show file tree
Hide file tree
Showing 7 changed files with 459 additions and 20 deletions.
160 changes: 153 additions & 7 deletions octoprint_rgb_status/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,114 @@
'Theater Chase': theater_chase,
'Rainbow': rainbow,
'Rainbow Cycle': rainbow_cycle,
'Theater Chase Rainbow': theater_chase_rainbow
'Theater Chase Rainbow': theater_chase_rainbow,
'Pulse': pulse,
'Knight Rider': knight_rider,
}


class RGBStatusPlugin(
plugin.RestartNeedingPlugin,
plugin.AssetPlugin,
plugin.StartupPlugin,
plugin.ProgressPlugin,
plugin.EventHandlerPlugin,
plugin.SettingsPlugin,
plugin.TemplatePlugin,
plugin.ShutdownPlugin):
plugin.ShutdownPlugin,
plugin.SimpleApiPlugin,
plugin.WizardPlugin):

api_errors = []

def is_wizard_required(self):
return any([not value for key, value in self.get_wizard_details().items()])

def get_wizard_version(self):
return 3

def get_wizard_details(self):
return {
'adduser_done': self.adduser_done(),
'spi_enabled': self.spi_enabled(),
'buffer_increased': self.buffer_increased(),
'frequency_set': self.frequency_set(),
}

def get_api_commands(self):
return {
'adduser': ['password'],
'enable_spi': ['password'],
'increase_buffer': ['password'],
'set_frequency': ['password'],
}

def run_command(self, command, password=None):
from subprocess import Popen, PIPE
if not isinstance(command, list):
command = command.split()
proc = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
if password is not None:
stdout, stderr = proc.communicate('{}\n'.format(password).encode())
else:
stdout, stderr = proc.communicate()
if stderr and 'incorrect password attempt' in stderr:
self.api_errors.append('Incorrect password attempt')
self._logger.error(stderr)
else:
return stdout

def adduser_done(self):
user_groups = self.run_command('groups pi').split()
return 'gpio' in user_groups

def spi_enabled(self):
with open('/boot/config.txt') as file:
for line in file:
if line.startswith('dtparam=spi=on'):
return True
return False

def buffer_increased(self):
with open('/boot/cmdline.txt') as file:
for line in file:
if 'spidev.bufsiz=' in line:
return True
return False

def frequency_set(self):
with open('/boot/config.txt') as file:
for line in file:
if line.startswith('core_freq=250'):
return True
return False

def build_response(self):
import flask
details = self.get_wizard_details()
details.update({'errors': self.api_errors})
self.api_errors = []
return flask.jsonify(details)

def on_api_command(self, command, data):
output = ''
self._logger.info('{} command called'.format(command))
password = data.get('password', None)
cmd = ''
if command == 'adduser':
cmd = 'sudo -S adduser pi gpio'
elif command == 'enable_spi' and not self.spi_enabled():
cmd = ['sudo', '-S', 'bash', '-c', 'echo dtparam=spi=on >> /boot/config.txt']
elif command == 'increase_buffer' and not self.buffer_increased():
cmd = ['sudo', '-S', 'sed', '-i', '$ s/$/ spidev.bufsiz=32768/', '/boot/cmdline.txt']
elif command == 'set_frequency' and not self.frequency_set():
cmd = ['sudo', '-S', 'bash', '-c', 'echo core_freq=250 >> /boot/config.txt']
if cmd:
stdout = self.run_command(cmd, password=password)

return self.build_response()

def on_api_get(self, request):
return self.build_response()

def get_settings_defaults(self):
return {
Expand All @@ -68,6 +164,18 @@ def get_settings_defaults(self):
'idle_effect': 'Solid Color',
'idle_effect_color': '#00ff00',
'idle_effect_delay': 10,

'pause_effect': 'Solid Color',
'pause_effect_color': '#f89406',
'pause_effect_delay': 10,

'fail_effect': 'Pulse',
'fail_effect_color': '#ff0000',
'fail_effect_delay': 10,

'done_effect': 'Pulse',
'done_effect_color': '#00ff00',
'done_effect_delay': 10,
}

def on_settings_save(self, data):
Expand All @@ -92,12 +200,19 @@ def on_settings_save(self, data):

def get_template_configs(self):
return [
{'type': 'settings', 'custom_bindings':False}
{'type': 'settings', 'custom_bindings':False},
{'type': 'wizard', 'mandatory': True}
]

def get_template_vars(self):
return {'effects': EFFECTS, 'strip_types': STRIP_TYPES}

def get_assets(self):
return {
'js': ['js/rgb_status.js'],
'css': ['css/rgb_status.css']
}

def init_strip(self):
settings = []
for setting in STRIP_SETTINGS:
Expand Down Expand Up @@ -131,14 +246,43 @@ def run_idle_effect(self):
self._settings.get_int(['idle_effect_delay']),
)

def run_pause_effect(self):
self._logger.info('Starting Pause Effect')
self.run_effect(
self._settings.get(['pause_effect']),
hex_to_rgb(self._settings.get(['pause_effect_color'])),
self._settings.get_int(['pause_effect_delay']),
)

def run_fail_effect(self):
self._logger.info('Starting Fail Effect')
self.run_effect(
self._settings.get(['fail_effect']),
hex_to_rgb(self._settings.get(['fail_effect_color'])),
self._settings.get_int(['fail_effect_delay']),
)

def run_done_effect(self):
self._logger.info('Starting Done Effect')
self.run_effect(
self._settings.get(['done_effect']),
hex_to_rgb(self._settings.get(['done_effect_color'])),
self._settings.get_int(['done_effect_delay']),
)

def on_event(self, event, payload):
if event == 'PrintStarted':
progress_base_color = hex_to_rgb(self._settings.get(['progress_base_color']))
self.run_effect('Solid Color', progress_base_color, delay=10)
elif event in ['PrintDone', 'PrintCancelled']:
elif event == 'PrintFailed':
self.run_fail_effect()
elif event == 'PrintPaused':
self.run_pause_effect()
elif event == 'PrintDone':
self.run_done_effect()
elif event == 'PrintCancelled':
self.run_idle_effect()


def on_print_progress(self, storage, path, progress):
if progress == 100 and hasattr(self, '_effect') and self._effect.is_alive():
self._logger.info('Progress was set to 100, but the idle effect was already running. Ignoring progress update')
Expand Down Expand Up @@ -204,4 +348,6 @@ def get_update_information(self, *args, **kwargs):
__plugin_name__ = 'RGB Status'
__plugin_pythoncompat__ = ">=2.7,<4"
__plugin_implementation__ = RGBStatusPlugin()
__plugin_hooks__ = {"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information}
__plugin_hooks__ = {
'octoprint.plugin.softwareupdate.check_config': __plugin_implementation__.get_update_information,
}
38 changes: 36 additions & 2 deletions octoprint_rgb_status/basic_effects.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from rpi_ws281x import *
from .utils import blend_colors
import time


Expand All @@ -25,11 +26,11 @@ def color_wipe(strip, color, delay=50, iterations=1):
for p in range(strip.numPixels()):
strip.setPixelColorRGB(p, *color)
strip.show()
time.sleep(delay/1000.0)
time.sleep(delay/100.0)
for p in range(strip.numPixels()):
strip.setPixelColorRGB(p, 0, 0, 0)
strip.show()
time.sleep(delay/1000.0)
time.sleep(delay/100.0)


def theater_chase(strip, color, delay=50, iterations=10):
Expand Down Expand Up @@ -84,3 +85,36 @@ def theater_chase_rainbow(strip, color=None, delay=50, iterations=1):
time.sleep(delay/1000.0)
for p in range(0, strip.numPixels(), 3):
strip.setPixelColor(p+r, 0)


def pulse(strip, color, delay, iterations=1):
for p in range(strip.numPixels()):
strip.setPixelColorRGB(p, *color)
for i in range(255):
strip.setBrightness(i)
strip.show()
time.sleep(delay/1000.0)
for i in reversed(range(255)):
strip.setBrightness(i)
strip.show()
time.sleep(delay/1000.0)


def knight_rider(strip, color, delay, iterations=1):
for active_pixel in range(strip.numPixels()):
for i in range(strip.numPixels()):
if i == active_pixel or i+1 == active_pixel or i-1 == active_pixel:
strip.setPixelColorRGB(i, *color)
else:
strip.setPixelColorRGB(i, *(0,0,0))
strip.show()
time.sleep(delay/100.0)
for active_pixel in reversed(range(strip.numPixels())):
for i in range(strip.numPixels()):
if i == active_pixel or i+1 == active_pixel or i-1 == active_pixel:
strip.setPixelColorRGB(i, *color)
else:
strip.setPixelColorRGB(i, *(0,0,0))
strip.show()
time.sleep(delay/100.0)

53 changes: 53 additions & 0 deletions octoprint_rgb_status/static/css/rgb_status.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#wizard_plugin_rgb_status ol li {
width: 100%;
border-bottom: 1px solid #ccc;
display: block;
padding: 5px;
padding-bottom: 20px;
}
#wizard_plugin_rgb_status ol li.complete * {
display: none;
}
#wizard_plugin_rgb_status ol li.complete h3 {
display: initial;
}
#wizard_plugin_rgb_status ol li:before {
float: left;
margin-left: -30px;
font-size: 25pt;
color: #dc0c0c;
margin-top: 20px;
}
#wizard_plugin_rgb_status ol li:first-of-type:before {
content: "1";
}
#wizard_plugin_rgb_status ol li:nth-of-type(2):before {
content: "2";
}
#wizard_plugin_rgb_status ol li:nth-of-type(3):before {
content: "3";
}
#wizard_plugin_rgb_status ol li:nth-of-type(4):before {
content: "4";
}
#wizard_plugin_rgb_status ol li.complete:before {
content: "✓" !important;
color: #47b347;
margin-top: 10px;
}
#wizard_plugin_rgb_status .code {
font-family: monospace;
background: #ddd;
padding: 1px 5px;
}
#wizard_plugin_rgb_status .helpText {
color: #888;
font-size: 9pt;
line-height: 10pt;
margin-top: -5px;
margin-bottom: 15px;
}
#wizard_plugin_rgb_status .errors {
color: #f33;
font-weight: bold;
}
Loading

0 comments on commit 57b944f

Please sign in to comment.