Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
malnvenshorn committed Jan 14, 2018
2 parents d589b12 + 16449b5 commit 69b69ef
Show file tree
Hide file tree
Showing 11 changed files with 388 additions and 99 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# OctoPrint-CostEstimation

This OctoPrint plugin displays the estimated print cost for the loaded model. The print cost includes the price for the used filament and the operating cost for the printer.

**Note:** This Plugin requires the [Filament Manager Plugin](https://github.com/malnvenshorn/OctoPrint-FilamentManager) to work. Make sure it is installed.
This OctoPrint plugin displays the estimated print cost for the loaded model. The print cost includes the price for the used filament the maintenance and operating cost for the printer as well as the depreciation of the printer.

## Features
- Calculation based on the provided filament length
Expand Down
18 changes: 13 additions & 5 deletions octoprint_costestimation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@ class CostEstimationPlugin(octoprint.plugin.SettingsPlugin,

def get_settings_defaults(self):
return dict(
powerConsumption=0.2, # kWh
costOfElectricity=0.25, # €/kWh
weightOfFilament=1000, # g
costOfFilament=20, # €
densityOfFilament=1.32, # g/cm³
diameterOfFilament=1.75, # mm
powerConsumption=0.2, # kWh
costOfElectricity=0.25, # €/kWh
currency="€",
currencyFormat="%v %s", # %v - value, %s - currency symbol
requiresLogin=False
currencyFormat="%v %s", # %v - value, %s - currency symbol
requiresLogin=False,
useFilamentManager=True,
priceOfPrinter=0, # €
lifespanOfPrinter=0, # h
maintenanceCosts=0, # €/h
)

def get_settings_version(self):
Expand Down Expand Up @@ -49,7 +57,7 @@ def on_settings_migrate(self, target, current=None):

def get_template_configs(self):
return [
dict(type="settings", custom_bindings=False)
dict(type="settings")
]

# AssetPlugin
Expand Down
48 changes: 37 additions & 11 deletions octoprint_costestimation/static/js/costestimation.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,68 @@ $(function() {
self.loginState.isUser() : true;
});

self.showFilamentGroup = ko.pureComputed(function() {
return self.filamentManager === null || !self.settings.settings.plugins.costestimation.useFilamentManager();
})

self.estimatedCostString = ko.pureComputed(function() {
if (!self.showEstimatedCost()) return "-";
if (self.printerState.filename() === undefined) return "-";
if (self.printerState.filament().length == 0) return "-";

var pluginSettings = self.settings.settings.plugins.costestimation;
var jobFilament = self.printerState.filament();
var spoolData = self.filamentManager.selectedSpools();
var spoolData = null;

if (self.filamentManager !== null && pluginSettings.useFilamentManager()) {
spoolData = self.filamentManager.selectedSpools();
}

// calculating filament cost
var filamentCost = 0;
for (var i = 0; i < jobFilament.length; ++i) {
var result = /(\d+)/.exec(jobFilament[i].name()); // extract tool id from name
var tool = result === null ? 0 : result[1];

if (spoolData[tool] === undefined) continue; // skip tools with no selected spool
if (spoolData !== null && spoolData[tool] === undefined) continue; // skip tools with no selected spool

var costOfFilament = spoolData[tool].cost;
var weightOfFilament = spoolData[tool].weight;
var densityOfFilament = spoolData[tool].profile.density;
var diameterOfFilament = spoolData[tool].profile.diameter;
var costPerWeight = costOfFilament / weightOfFilament;
var costOfFilament, weightOfFilament, densityOfFilament, diameterOfFilament;

if (spoolData !== null) {
costOfFilament = spoolData[tool].cost;
weightOfFilament = spoolData[tool].weight;
densityOfFilament = spoolData[tool].profile.density;
diameterOfFilament = spoolData[tool].profile.diameter;
} else {
costOfFilament = parseFloat(pluginSettings.costOfFilament());
weightOfFilament = parseFloat(pluginSettings.weightOfFilament());
densityOfFilament = parseFloat(pluginSettings.densityOfFilament());
diameterOfFilament = parseFloat(pluginSettings.diameterOfFilament());
}

var costPerWeight = weightOfFilament > 0 ? costOfFilament / weightOfFilament : 0;
var filamentLength = jobFilament[i].data().length;
var filamentVolume = self.calculateVolume(filamentLength, diameterOfFilament) / 1000;

filamentCost += costPerWeight * filamentVolume * densityOfFilament;
}

// calculating electricity cost
var powerConsumption = pluginSettings.powerConsumption();
var costOfElectricity = pluginSettings.costOfElectricity();
var powerConsumption = parseFloat(pluginSettings.powerConsumption());
var costOfElectricity = parseFloat(pluginSettings.costOfElectricity());
var costPerHour = powerConsumption * costOfElectricity;
var estimatedPrintTime = self.printerState.estimatedPrintTime() / 3600; // h
var electricityCost = costPerHour * estimatedPrintTime;

// calculating printer cost
var purchasePrice = parseFloat(pluginSettings.priceOfPrinter());
var lifespan = parseFloat(pluginSettings.lifespanOfPrinter());
var depreciationPerHour = lifespan > 0 ? purchasePrice / lifespan : 0;
var maintenancePerHour = parseFloat(pluginSettings.maintenanceCosts());
var printerCost = (depreciationPerHour + maintenancePerHour) * estimatedPrintTime;

// assembling string
var estimatedCost = filamentCost + electricityCost;
var estimatedCost = filamentCost + electricityCost + printerCost;
var currencySymbol = pluginSettings.currency();
var currencyFormat = pluginSettings.currencyFormat();
return currencyFormat.replace("%v", estimatedCost.toFixed(2)).replace("%s", currencySymbol);
Expand All @@ -81,6 +106,7 @@ $(function() {
construct: CostEstimationViewModel,
dependencies: ["printerStateViewModel", "settingsViewModel",
"loginStateViewModel", "filamentManagerViewModel"],
elements: ["#costestimation_string"]
optional: ["filamentManagerViewModel"],
elements: ["#costestimation_string", "#settings_plugin_costestimation"]
});
});
105 changes: 98 additions & 7 deletions octoprint_costestimation/templates/costestimation_settings.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,74 @@

<h3>{{ _("Filament") }}</h3>

{{ _("The settings can be found in the") }} <a href="#settings_plugin_filamentmanager" data-toggle="tab" style="" data-bind="click: function() {$('#settings_plugin_filamentmanager_link').addClass('active'); $('#settings_plugin_costestimation_link').removeClass('active');}">Filament Manager</a>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: $root.settings.settings.plugins.costestimation.useFilamentManager">
{{ _('Use <a target="_blank" href="https://github.com/malnvenshorn/OctoPrint-FilamentManager">Filament Manager Plugin</a>') }}
<!-- ko if: $root.filamentManager !== null -->
<span class="text-success">{{ _("(installed)") }}</span>
<!-- /ko -->
<!-- ko if: $root.filamentManager === null -->
<span class="text-error">{{ _("(not installed)") }}</span>
<!-- /ko -->
</label>
</div>
</div>

<div data-bind="visible: $root.showFilamentGroup">
<div class="control-group">
<label class="control-label">{{ _('Price') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="0.01" min="0" class="input-mini text-right"
data-bind="value: $root.settings.settings.plugins.costestimation.costOfFilament">
<span class="add-on">€</span>
</div>
</div>
</div>

<div class="control-group">
<label class="control-label">{{ _('Weight') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="1" min="0" class="input-mini text-right"
data-bind="value: $root.settings.settings.plugins.costestimation.weightOfFilament">
<span class="add-on">g</span>
</div>
</div>
</div>

<div class="control-group">
<label class="control-label">{{ _('Density') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="0.01" min="0" class="input-mini text-right"
data-bind="value: $root.settings.settings.plugins.costestimation.densityOfFilament">
<span class="add-on">g/cm<sup>3</sup></span>
</div>
</div>
</div>

<div class="control-group">
<label class="control-label">{{ _('Diameter') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="0.01" min="0" class="input-mini text-right"
data-bind="value: $root.settings.settings.plugins.costestimation.diameterOfFilament">
<span class="add-on">mm</span>
</div>
</div>
</div>
</div>

<h3>{{ _("Operating Cost") }}</h3>

<div class="control-group">
<label class="control-label">{{ _('Power consumption') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="0.01" min="0" class="input-mini text-right" data-bind="value: settings.plugins.costestimation.powerConsumption">
<input type="number" step="0.01" min="0" class="input-mini text-right" data-bind="value: $root.settings.settings.plugins.costestimation.powerConsumption">
<span class="add-on">kW</span>
</div>
</div>
Expand All @@ -20,8 +79,40 @@
<label class="control-label">{{ _('Electricity cost') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="0.01" min="0" class="input-mini text-right"data-bind="value: settings.plugins.costestimation.costOfElectricity">
<span class="add-on"><span data-bind="text: settings.plugins.costestimation.currency"></span>/kWh</span>
<input type="number" step="0.01" min="0" class="input-mini text-right"data-bind="value: $root.settings.settings.plugins.costestimation.costOfElectricity">
<span class="add-on"><span data-bind="text: $root.settings.settings.plugins.costestimation.currency"></span>/kWh</span>
</div>
</div>
</div>

<h3>{{ _("Printer Cost") }}</h3>

<div class="control-group">
<label class="control-label">{{ _('Purchase price') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="0.01" min="0" class="input-mini text-right" data-bind="value: $root.settings.settings.plugins.costestimation.priceOfPrinter">
<span class="add-on" data-bind="text: $root.settings.settings.plugins.costestimation.currency"></span>
</div>
</div>
</div>

<div class="control-group">
<label class="control-label">{{ _('Estimated lifespan') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="1" min="0" class="input-mini text-right" data-bind="value: $root.settings.settings.plugins.costestimation.lifespanOfPrinter">
<span class="add-on">h</span>
</div>
</div>
</div>

<div class="control-group">
<label class="control-label">{{ _('Maintenance costs') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" step="0.01" min="0" class="input-mini text-right" data-bind="value: $root.settings.settings.plugins.costestimation.maintenanceCosts">
<span class="add-on"><span data-bind="text: $root.settings.settings.plugins.costestimation.currency"></span>/h</span>
</div>
</div>
</div>
Expand All @@ -31,21 +122,21 @@
<div class="control-group">
<label class="control-label">{{ _('Currency symbol') }}</label>
<div class="controls">
<input type="text" class="input-mini text-center" data-bind="value: settings.plugins.costestimation.currency, valueUpdate: 'afterkeydown'">
<input type="text" class="input-mini text-center" data-bind="value: $root.settings.settings.plugins.costestimation.currency, valueUpdate: 'afterkeydown'">
</div>
</div>

<div class="control-group" title="{{ _('Format string that allows control of symbol position (%%v = value, %%s = symbol)') }}">
<label class="control-label">{{ _('String format') }}</label>
<div class="controls">
<input type="text" class="input-mini text-center" data-bind="value: settings.plugins.costestimation.currencyFormat">
<input type="text" class="input-mini text-center" data-bind="value: $root.settings.settings.plugins.costestimation.currencyFormat">
</div>
</div>

<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: settings.plugins.costestimation.requiresLogin">{{ _("Show estimated cost only if logged in") }}
<input type="checkbox" data-bind="checked: $root.settings.settings.plugins.costestimation.requiresLogin">{{ _("Show estimated cost only if logged in") }}
</label>
</div>
</div>
Expand Down
Binary file modified octoprint_costestimation/translations/de/LC_MESSAGES/messages.mo
Binary file not shown.
Loading

0 comments on commit 69b69ef

Please sign in to comment.