Skip to content

Commit

Permalink
Merge pull request #48 from entrippy/develop
Browse files Browse the repository at this point in the history
Light on on Octoprint Startup
  • Loading branch information
entrippy committed Nov 26, 2023
2 parents 5c3f851 + 3e92b5e commit bf46548
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 115 deletions.
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# OctoPrint-OctoHue Change Log

## Added in 0.5.0
* Added "Light On" on Octoprint startup

## Fixed in 0.4.4
* It is recommended that you remove your existing octohue settings, or at the very least remove statusDict from config.yaml
* Back from the dead after several years of inactivity (thanks covid)
* Fixed bug preventing changes to initial example configuration from being changed. No example events are configured in this version, but they will return in future.
* Changed persistent statusDict settins to a list of dicts instead of a dict of dicts, this was what played hell with the above
* Moved from using the term "status" to "events" in line with octoprint terminology
* Added new Event Add modal with "Event" dropdown populated from native octoprint events.


## Fixed in 0.4.3
* Renamed rgb() to build_state() as it better describes its function
* Fixed brightness not being passed properly to build_state meaning it always defaulted to 255
* Fixed bridge object not being reinitialised on settings save, requiring a restart to pickup bridge and user changes.
* Default brightness now works as planned and sets the brightness when it is not defined for a particular status.

## Added in 0.4.2
* Optional Navbar Icon allowing the user to toggle On/Off
* Reworked settings allows user configurable Statuses and colour/brightness/state configurations.
* Added turning lights off as an option for printer statuses.
* Added debug logging option to allow logging or raw status events to aid configuration

5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

Illuminate your print job and signal its status using a Philips Hue light.

## Added in 0.5.0
* Added option to "Light On" on Octoprint startup by selecting an already configured light event

## Fixed in 0.4.4
* It is recommended that you remove your existing octohue settings, or at the very least remove statusDict from config.yaml
* Back from the dead after several years of inactivity (thanks covid)
Expand Down Expand Up @@ -31,6 +34,8 @@ Illuminate your print job and signal its status using a Philips Hue light.
* Support to switch off lights when OctoPrint quits.
* Customisable default brightness

See the CHANGELOG.md for a full list of historic changes over time

See the TODO list at the end of this page for features on the roadmap

## Setup
Expand Down
98 changes: 52 additions & 46 deletions octoprint_octohue/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,50 +86,19 @@ def toggle_state(self):
else:
self.build_state(illuminate=True, bri=int(self._settings.get(['defaultbri'])))

def get_settings_version(self):
return 2

def on_settings_migrate(self, target, current=None):
if current is None:
self._logger.info("Migrating Settings: Writing example settings")
self._settings.set(["statusDict"], [
{'event': 'Connected',
'colour':'#FFFFFF',
'brightness':255,
'turnoff':False},
{'event': 'Disconnected',
'colour':'',
'brightness':"",
'turnoff':True},
{'event': 'PrintStarted',
'colour':'#FFFFFF',
'brightness':255,
'turnoff':False},
{'event': 'PrintResumed',
'colour':'#FFFFFF',
'brightness':255,
'turnoff':False},
{'event': 'PrintDone',
'colour':'#33FF36',
'brightness':255,
'turnoff':False},
{'event': 'PrintFailed',
'colour':'#FF0000',
'brightness':255,
'turnoff':False}
])
self._settings.save()

if current < self.get_settings_version():
self._logger.info("Migrating Settings: Updating a setting")

def get_configured_events(self):
configuredEvents = [ sub['event'] for sub in self._settings.get(['statusDict']) ]
return configuredEvents

def on_after_startup(self):
self._logger.info("Octohue is alive!")
self._logger.debug("Bridge Address is %s" % self._settings.get(['bridgeaddr']) if self._settings.get(['bridgeaddr']) else "Please set Bridge Address in settings")
self._logger.debug("Hue Username is %s" % self._settings.get(['husername']) if self._settings.get(['husername']) else "Please set Hue Username in settings")
self.pbridge = Bridge(self._settings.get(['bridgeaddr']), self._settings.get(['husername']))
self._logger.debug("Bridge established at: %s" % self.pbridge.url)
#if self._settings.get(['ononstartup']) == True:
# my_statusEvent = next((statusEvent for statusEvent in self._settings.get(['statusDict']) if statusEvent['event'] == self._settings.get(['ononstartupevent'])), None)
# self.build_state(illuminate=True, colour=my_statusEvent['colour'], bri=int(self._settings.get(['defaultbri'])))

def on_shutdown(self):
self._logger.info("Ladies and Gentlemen, thank you and goodnight!")
Expand Down Expand Up @@ -173,6 +142,8 @@ def get_settings_defaults(self):
lampid="",
lampisgroup="",
defaultbri=255,
ononstartup=False,
ononstartupevent="",
offonshutdown=True,
showhuetoggle=True,
statusDict=[]
Expand All @@ -184,14 +155,44 @@ def get_settings_restricted_paths(self):
def get_settings_version(self):
return 1

def on_settings_migrate(self, target, current):
def on_settings_migrate(self, target, current=None):
if current is None:
self._logger.info("Creating Default Settings")

if current is not None and current < self.get_settings_version():
self._logger.info("Updating Settings")

self._settings.save()
self._logger.info("Migrating Settings: Writing example settings")
self._settings.set(["statusDict"], [
{'event': 'Connected',
'colour':'#FFFFFF',
'brightness':255,
'delay':0,
'turnoff':False},
{'event': 'Disconnected',
'colour':'',
'brightness':"",
'delay':0,
'turnoff':True},
{'event': 'PrintStarted',
'colour':'#FFFFFF',
'brightness':255,
'delay':0,
'turnoff':False},
{'event': 'PrintResumed',
'colour':'#FFFFFF',
'brightness':255,
'delay':0,
'turnoff':False},
{'event': 'PrintDone',
'colour':'#33FF36',
'brightness':255,
'delay':0,
'turnoff':False},
{'event': 'PrintFailed',
'colour':'#FF0000',
'brightness':255,
'delay':0,
'turnoff':False}
])
self._settings.save()
elif current < self.get_settings_version():
self._logger.info("Migrating Settings: Updating a setting")

def on_settings_load(self):
my_settings = {
Expand All @@ -202,17 +203,20 @@ def on_settings_load(self):
"lampid": self._settings.get(["lampid"]),
"lampisgroup": self._settings.get(["lampisgroup"]),
"defaultbri": self._settings.get(["defaultbri"]),
"ononstartup": self._settings.get(["ononstartup"]),
"configuredEvents": self.get_configured_events(),
"ononstartupevent": self._settings.get(["ononstartupevent"]),
"offonshutdown": self._settings.get(["offonshutdown"]),
"showhuetoggle": self._settings.get(["showhuetoggle"])
}
return my_settings

def on_settings_save(self, data):
data.pop("availableEvents", None)
self._logger.info("Saving: %s" % data)
self._logger.debug("Saving: %s" % data)
octoprint.plugin.SettingsPlugin.on_settings_save(self, data)
self.pbridge = Bridge(self._settings.get(['bridgeaddr']), self._settings.get(['husername']))
self._logger.debug("New Bridge established at: %s" % self.pbridge.url)
self._logger.info("New Bridge established at: %s" % self.pbridge.url)

def get_template_vars(self):
return dict(
Expand All @@ -222,6 +226,8 @@ def get_template_vars(self):
lampisgroup=self._settings.get(["lampisgroup"]),
defaultbri=self._settings.get(["defaultbri"]),
offonshutdown=self._settings.get(["offonshutdown"]),
ononstartup=self._settings.get(['ononstartup']),
ononstartupevent=self._settings.get(['ononstartupevent']),
showhuetoggle=self._settings.get(["showhuetoggle"]),
statusDict=self._settings.get(["statusDict"])
)
Expand Down
44 changes: 30 additions & 14 deletions octoprint_octohue/static/js/OctoHue.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,31 @@
* License: AGPLv3
*/
$(function() {

ko.extenders.defaultIfNull = function(target, defaultValue) {
var result = ko.computed({
read: target,
write: function(newValue) {
if (!newValue) {
target(defaultValue);
} else {
target(newValue);
}
}
});

result(target());

return result;
};

function OctohueViewModel(parameters) {
var self = this;

self.settingsViewModel = parameters[0];
self.selectedEvent = ko.observable();
self.ownSettings = {}
self.ownSettings = {};
self.statusDict = [];

self.statusDetails = function (data) {
if (data === false) {
Expand All @@ -30,18 +49,15 @@ $(function() {
}
};

self.statusDict = {}

self.addStatus = function () {
self.selectedEvent(self.statusDetails(false));
self.settingsViewModel.settings.plugins.octohue.statusDict.push(
self.selectedEvent()
);
$("#StatusManagerEditor").modal("show");
};

self.editStatus = function (data) {
self.selectedEvent(self.statusDetails(data));
self.addNewStatus = function () {
var statusObj = {
event: ko.observable(''),
colour: ko.observable(''),
brightness: ko.observable('').extend({ defaultIfNull: "255" }),
delay: ko.observable('').extend({ defaultIfNull: "0" }),
turnoff: ko.observable('')
};
self.ownSettings.statusDict.push(statusObj);
};

self.removeStatus = function (data) {
Expand All @@ -61,8 +77,8 @@ $(function() {
self.onBeforeBinding = function () {
self.settings = self.settingsViewModel.settings;
self.ownSettings = self.settings.plugins.octohue;
self.statusDict = self.settingsViewModel.settings.plugins.octohue.statusDict;
}

}

/* view model class, parameters for constructor, container to bind to
Expand Down
65 changes: 12 additions & 53 deletions octoprint_octohue/templates/octohue_settings.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
<input type="checkbox" data-bind="checked: ownSettings.offonshutdown">Lights Off on Server Shutdown
</label>
</div>
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: ownSettings.ononstartup">Lights On on OctoPrint Startup
</label>
<select class="input-block-level" data-bind="value: ownSettings.ononstartupevent, options: $root.settingsViewModel.settings.plugins.octohue.configuredEvents().sort(), optionsCaption: 'Select Event', valueAllowUnset: true"></select>
</div>
<label class="control-label"></label>
<div class="controls">
<label class="checkbox">
Expand Down Expand Up @@ -64,10 +70,10 @@
</th>
</tr>
</thead>
<tbody class="control-group" data-bind="foreach: settingsViewModel.settings.plugins.octohue.statusDict">
<tbody class="control-group" data-bind="foreach: statusDict">
<tr>
<td>
<input type="text" value="Event" data-bind="value: event">
<select class="input-block-level" data-bind="value: event, options: $root.settingsViewModel.settings.plugins.octohue.availableEvents().sort(), optionsCaption: 'Select Event', valueAllowUnset: true"></select>
</td>
<td>
<input type="color" class="input-mini" data-bind="value: colour">
Expand All @@ -76,71 +82,24 @@
<input type="text" class="input-mini" data-bind="value: colour">
</td>
<td>
<input type="number" max="255" class="input-mini" data-bind="value: brightness">
<input type="number" max="255" class="input-mini" data-bind="value: brightness" value="255">
</td>
<td>
<input type="number" class="input-mini" data-bind="value: delay">
<input type="number" class="input-mini" data-bind="value: delay" value="0">
</td>
<td>
<i data-bind="attr: { class: turnoff() ? 'fa fa-check-square-o' : 'fa fa-square-o' }, click: $parent.setSwitchOff"></i>
</td>
<td>
<i class="fa fa-trash-o" data-bind="click: $root.removeStatus"></i>
<i class="fa fa-trash-o" data-bind="click: $parent.removeStatus"></i>
</td>
</tr>
</tbody>
</table>
<div class="control">
<button class="btn" data-bind="click: addStatus">New</button>
<button class="btn" data-bind="click: addNewStatus">New</button>
</div>
</div>
</div>
</form>

<div id="StatusManagerEditor" data-bind="with: selectedEvent" class="modal hide fade-in">
<div class="modal-header">
<a href="#" class="close" data-dismiss="modal" aria-hidden="true">&times;</a>
<h3>{{ _('Event Editor') }}</h3>
</div>
<div class="modal-body">
<div class="control-group">
<label class="control-label">{{ _('Event') }}</label>
<div class="controls">
<select class="input-block-level" data-bind="value: event, options: $root.settingsViewModel.settings.plugins.octohue.availableEvents().sort(), optionsCaption: 'Select Event', valueAllowUnset: true"></select>
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Colour') }}</label>
<div class="controls">
<input type="color" class="input-mini" data-bind="value: colour">
<input type="text" class="input-block-level" data-bind="value: colour" />
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Brightness') }}</label>
<div class="controls">
<input type="number" max="255" class="input-mini" data-bind="value: brightness" value="255">
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Delay') }}</label>
<div class="controls">
<input type="text" class="input-block-level: data-bind="value: delay" />
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Turn Off') }}</label>
<div class="controls">
<input type="checkbox" data-bind="checked: turnoff" />
</div>
</div>
<p><small>
{{ _('Please note that any event handlers you define here will be processed <em>asynchronously</em> to OctoPrint\'s own processing of the event. You cannot stall, block or otherwise influence internal execution with event handlers.') }}
</small></p>
</div>
<div class="modal-footer">
<div class="row-fluid">
{{ _('Do not forget to save in main settings.') }} <button type="button" class="btn" data-dismiss="modal">{{ _('Close') }}</button>
</div>
</div>
</div>
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
plugin_name = "OctoHue"

# The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module
plugin_version = "0.4.4"
plugin_version = "0.5.0"

# The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin
# module
Expand All @@ -33,7 +33,7 @@
plugin_license = "AGPLv3"

# Any additional requirements besides OctoPrint should be listed here
plugin_requires = ["colormath", "qhue"]
plugin_requires = ["colormath", "qhue", "numpy"]

### --------------------------------------------------------------------------------------------------------------------
### More advanced options that you usually shouldn't have to touch follow after this point
Expand Down

0 comments on commit bf46548

Please sign in to comment.