From 75017d7ac643b0efafd00f2d3ea7a5a89b0eff9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?=
Date: Mon, 8 Sep 2014 18:05:25 +0200
Subject: [PATCH] Integrated netconnectd plugin with netconnectd service
---
src/octoprint/plugins/netconnectd/__init__.py | 102 ++++++++++++--
.../netconnectd/static/js/netconnectd.js | 127 +++++++++++++-----
.../netconnectd_settings_dialog.jinja2 | 28 ++--
src/octoprint/server/api/settings.py | 5 +-
src/octoprint/static/js/app/dataupdater.js | 14 +-
src/octoprint/static/js/app/main.js | 18 ++-
.../static/js/app/viewmodels/files.js | 10 ++
7 files changed, 244 insertions(+), 60 deletions(-)
diff --git a/src/octoprint/plugins/netconnectd/__init__.py b/src/octoprint/plugins/netconnectd/__init__.py
index b3b4f641..a7c473c2 100644
--- a/src/octoprint/plugins/netconnectd/__init__.py
+++ b/src/octoprint/plugins/netconnectd/__init__.py
@@ -21,10 +21,14 @@ default_settings = {
s = octoprint.plugin.plugin_settings("netconnectd", defaults=default_settings)
-class NetconnectdSettingsPlugin(octoprint.plugin.SettingsPlugin, octoprint.plugin.SimpleApiPlugin, octoprint.plugin.AssetPlugin):
+class NetconnectdSettingsPlugin(octoprint.plugin.SettingsPlugin,
+ octoprint.plugin.TemplatePlugin,
+ octoprint.plugin.SimpleApiPlugin,
+ octoprint.plugin.AssetPlugin):
def __init__(self):
- self.logger = logging.getLogger(__name__)
+ self.logger = logging.getLogger("plugins.netconnectd." + __name__)
+ self.address = s.get(["socket"])
##~~ SettingsPlugin
@@ -37,6 +41,8 @@ class NetconnectdSettingsPlugin(octoprint.plugin.SettingsPlugin, octoprint.plugi
if "socket" in data and data["socket"]:
s.set(["socket"], data["socket"])
+ self.address = s.get(["socket"])
+
##~~ TemplatePlugin API (part of SettingsPlugin)
def get_template_vars(self):
@@ -79,6 +85,8 @@ class NetconnectdSettingsPlugin(octoprint.plugin.SettingsPlugin, octoprint.plugi
else:
self.logger.info("Configuring wifi {ssid}...".format(**data))
+ self._configure_and_select_wifi(data["ssid"], data["psk"], force=data["force"] if "force" in data else False)
+
elif command == "start_ap":
self.logger.info("Starting ap...")
@@ -100,20 +108,92 @@ class NetconnectdSettingsPlugin(octoprint.plugin.SettingsPlugin, octoprint.plugi
##~~ Private helpers
def _get_wifi_list(self, force=False):
+ payload = dict()
if force:
self.logger.info("Forcing wifi refresh...")
- return [
- {"name": "A Test Wifi", "quality": 59, "encrypted": True},
- {"name": "TyrionDiesOnPage24", "quality": 90, "encrypted": True},
- {"name": "Giraffenhaus", "quality": 78, "encrypted": False},
- ]
+ payload["force"] = True
+
+ flag, content = self._send_message("list_wifi", payload)
+ if not flag:
+ raise RuntimeError("Error while listing wifi: " + content)
+
+ result = []
+ for wifi in content:
+ result.append(dict(ssid=wifi["ssid"], address=wifi["address"], quality=wifi["signal"], encrypted=wifi["encrypted"]))
+ return result
def _get_status(self):
- return {
- "ap": False,
- "connectedToWifi": True
- }
+ payload = dict()
+ flag, content = self._send_message("status", payload)
+ if not flag:
+ raise RuntimeError("Error while querying status: " + content)
+
+ return dict(
+ ap=content["ap"],
+ link=content["link"],
+ wifi_available=content["wifi_available"]
+ )
+
+ def _configure_and_select_wifi(self, ssid, psk, force=False):
+ payload = dict(
+ ssid=ssid,
+ psk=psk,
+ force=force
+ )
+
+ flag, content = self._send_message("config_wifi", payload)
+ if not flag:
+ raise RuntimeError("Error while configuring wifi: " + content)
+
+ flag, content = self._send_message("start_wifi", dict())
+ if not flag:
+ raise RuntimeError("Error while selecting wifi: " + content)
+
+ def _send_message(self, message, data):
+ obj = dict()
+ obj[message] = data
+
+ import json
+ js = json.dumps(obj, encoding="utf8", separators=(",", ":"))
+
+ import socket
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ try:
+ sock.connect(self.address)
+ sock.sendall(js + '\x00')
+
+ buffer = []
+ while True:
+ chunk = sock.recv(16)
+ if chunk:
+ buffer.append(chunk)
+ if chunk.endswith('\x00'):
+ break
+
+ data = ''.join(buffer).strip()[:-1]
+
+ response = json.loads(data.strip())
+ if "result" in response:
+ return True, response["result"]
+
+ elif "error" in response:
+ # something went wrong
+ self.logger.warn("Request to netconnectd went wrong: " + response["error"])
+ return False, response["error"]
+
+ else:
+ output = "Unknown response from netconnectd: {response!r}".format(response=response)
+ self.logger.warn(output)
+ return False, output
+
+ except Exception as e:
+ output = "Error while talking to netconnectd: {}".format(e.message)
+ self.logger.warn(output)
+ return False, output
+
+ finally:
+ sock.close()
__plugin_name__ = "netconnectd client"
__plugin_version__ = "0.1"
diff --git a/src/octoprint/plugins/netconnectd/static/js/netconnectd.js b/src/octoprint/plugins/netconnectd/static/js/netconnectd.js
index 93bcdab7..3ec652bf 100644
--- a/src/octoprint/plugins/netconnectd/static/js/netconnectd.js
+++ b/src/octoprint/plugins/netconnectd/static/js/netconnectd.js
@@ -5,42 +5,49 @@ $(function() {
self.loginState = parameters[0];
self.settingsViewModel = parameters[1];
- self.settings = undefined;
+ self.pollingEnabled = false;
+ self.pollingTimeoutId = undefined;
- self.data = {
- wifis: ko.observableArray([]),
- status: {
- ap: ko.observable(),
- connectedToWifi: ko.observable()
- }
- };
+ self.enableQualitySorting = ko.observable(false);
+ self.statusAp = ko.observable();
+ self.statusLink = ko.observable();
+ self.statusWifiAvailable = ko.observable();
+
+ self.editorWifi = undefined;
self.editorWifiSsid = ko.observable();
self.editorWifiPassphrase1 = ko.observable();
self.editorWifiPassphrase2 = ko.observable();
+ self.working = ko.observable(false);
+
self.editorWifiPassphraseMismatch = ko.computed(function() {
return self.editorWifiPassphrase1() != self.editorWifiPassphrase2();
});
+ self.error = ko.observable(false);
self.connectionStateText = ko.computed(function() {
- if (self.data.status.ap()) {
- return gettext("Access Point is active");
- } else if (self.data.status.connectedToWifi()) {
- return gettext("Connected to configured Wifi");
- } else {
- return gettext("Connected")
+ if (self.error()) {
+ return gettext("Error while talking to netconnectd, is the service running?")
+ } else if (self.statusAp() && !self.statusWifiAvailable()) {
+ return gettext("Access Point is active, wifi configured but not available");
+ } else if (self.statusAp() && self.statusWifiAvailable()) {
+ return gettext("Access Point is active, wifi configured");
+ } else if (self.statusLink()) {
+ return gettext("Connected");
}
+
+ return gettext("Unknown connection state");
});
// initialize list helper
self.listHelper = new ItemListHelper(
"wifis",
{
- "name": function (a, b) {
+ "ssid": function (a, b) {
// sorts ascending
- if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1;
- if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1;
+ if (a["ssid"].toLocaleLowerCase() < b["ssid"].toLocaleLowerCase()) return -1;
+ if (a["ssid"].toLocaleLowerCase() > b["ssid"].toLocaleLowerCase()) return 1;
return 0;
},
"quality": function (a, b) {
@@ -58,19 +65,52 @@ $(function() {
10
);
+ self.getEntryId = function(ssid) {
+ return "settings_plugin_netconnectd_connectbutton_" + md5(data.ssid);
+ };
+
+ self.refresh = function() {
+ self.requestData();
+ };
+
self.fromResponse = function (response) {
if (response.error !== undefined) {
+ self.error(true);
return;
+ } else {
+ self.error(false);
}
- ko.mapping.fromJS(response, self.data);
+
+ self.statusAp(response.status.ap);
+ self.statusLink(response.status.link);
+ self.statusWifiAvailable(response.status.wifi_available);
+
+ var enableQualitySorting = false;
+ _.each(response.wifis, function(wifi) {
+ if (wifi.quality != undefined) {
+ enableQualitySorting = true;
+ }
+ });
+ self.enableQualitySorting(enableQualitySorting);
+
self.listHelper.updateItems(response.wifis);
+ if (!enableQualitySorting) {
+ self.listHelper.changeSorting("ssid");
+ }
+
+ if (self.pollingEnabled) {
+ self.pollingTimeoutId = setTimeout(function() {
+ self.requestData();
+ }, 30000)
+ }
};
self.configureWifi = function(data) {
+ self.editorWifi = data;
+ self.editorWifiSsid(data.ssid);
+ self.editorWifiPassphrase1(undefined);
+ self.editorWifiPassphrase2(undefined);
if (data.encrypted) {
- self.editorWifiSsid(data.ssid);
- self.editorWifiPassphrase1(undefined);
- self.editorWifiPassphrase2(undefined);
$("#settings_plugin_netconnectd_wificonfig").modal("show");
} else {
self.confirmWifiConfiguration();
@@ -79,11 +119,12 @@ $(function() {
self.confirmWifiConfiguration = function() {
self.sendWifiConfig(self.editorWifiSsid(), self.editorWifiPassphrase1(), function() {
+ self.editorWifi = undefined;
self.editorWifiSsid(undefined);
self.editorWifiPassphrase1(undefined);
self.editorWifiPassphrase2(undefined);
$("#settings_plugin_netconnectd_wificonfig").modal("hide");
- })
+ });
};
self.sendStartAp = function() {
@@ -101,28 +142,40 @@ $(function() {
});
};
- self.sendWifiConfig = function(ssid, psk, callback) {
- self._postCommand("configure_wifi", {ssid: ssid, psk: psk});
+ self.sendWifiConfig = function(ssid, psk, successCallback, failureCallback) {
+ self.working(true);
+ self._postCommand("configure_wifi", {ssid: ssid, psk: psk}, successCallback, failureCallback, function() {
+ self.working(false);
+ });
};
- self._postCommand = function (command, data, successCallback, failureCallback) {
+ self._postCommand = function (command, data, successCallback, failureCallback, alwaysCallback) {
var payload = _.extend(data, {command: command});
$.ajax({
url: API_BASEURL + "plugin/netconnectd",
type: "POST",
dataType: "json",
- data: payload,
+ data: JSON.stringify(payload),
+ contentType: "application/json; charset=UTF-8",
success: function(response) {
if (successCallback) successCallback(response);
},
- fail: function() {
+ error: function() {
if (failureCallback) failureCallback();
+ },
+ complete: function() {
+ if (alwaysCallback) alwaysCallback();
}
});
};
self.requestData = function () {
+ if (self.pollingTimeoutId != undefined) {
+ clearTimeout(self.pollingTimeoutId);
+ self.pollingTimeoutId = undefined;
+ }
+
$.ajax({
url: API_BASEURL + "plugin/netconnectd",
type: "GET",
@@ -133,11 +186,25 @@ $(function() {
self.onBeforeBinding = function() {
self.settings = self.settingsViewModel.settings;
- };
-
- self.onStartup = function() {
self.requestData();
};
+
+ self.onDataUpdaterReconnect = function() {
+ self.requestData();
+ };
+
+ self.onSettingsShown = function() {
+ self.pollingEnabled = true;
+ self.requestData();
+ };
+
+ self.onSettingsHidden = function() {
+ if (self.pollingTimeoutId != undefined) {
+ self.pollingTimeoutId = undefined;
+ }
+ self.pollingEnabled = false;
+ }
+
}
// view model class, parameters for constructor, container to bind to
diff --git a/src/octoprint/plugins/netconnectd/templates/netconnectd_settings_dialog.jinja2 b/src/octoprint/plugins/netconnectd/templates/netconnectd_settings_dialog.jinja2
index 3c61f393..3d30315b 100644
--- a/src/octoprint/plugins/netconnectd/templates/netconnectd_settings_dialog.jinja2
+++ b/src/octoprint/plugins/netconnectd/templates/netconnectd_settings_dialog.jinja2
@@ -3,27 +3,27 @@
{{ _('Connection state') }}:
-
+
- | {{ _('Name') }} |
- {{ _('Quality') }} |
+ {{ _('SSID') }} |
+ {{ _('Quality') }} |
{{ _('Action') }} |
-
- | |
- |
-
-
- |
-
+
+ | |
+ |
+
+
+ |
+
+
+
{{ _('netconnectd socket') }}:
@@ -71,8 +73,8 @@
diff --git a/src/octoprint/server/api/settings.py b/src/octoprint/server/api/settings.py
index 93c9b567..e01df927 100644
--- a/src/octoprint/server/api/settings.py
+++ b/src/octoprint/server/api/settings.py
@@ -220,9 +220,8 @@ def setSettings():
enabled = cura.get("enabled")
s.setBoolean(["cura", "enabled"], enabled)
- octoprint.plugin.call_plugin(octoprint.plugin.SettingsPlugin,
- "on_settings_save",
- args=(data["plugins"][name]))
+ for name, plugin in octoprint.plugin.plugin_manager().get_implementations(octoprint.plugin.SettingsPlugin).items():
+ plugin.on_settings_save(data["plugins"][name])
s.save()
diff --git a/src/octoprint/static/js/app/dataupdater.js b/src/octoprint/static/js/app/dataupdater.js
index cd637261..177cef78 100644
--- a/src/octoprint/static/js/app/dataupdater.js
+++ b/src/octoprint/static/js/app/dataupdater.js
@@ -108,8 +108,18 @@ function DataUpdater(allViewModels) {
var gcodeUploadProgress = $("#gcode_upload_progress");
var gcodeUploadProgressBar = $(".bar", gcodeUploadProgress);
- if ((type == "UpdatedFiles" && payload.type == "gcode") || type == "MetadataAnalysisFinished") {
- gcodeFilesViewModel.requestData();
+ if (type == "UpdatedFiles") {
+ _.each(self.allViewModels, function(viewModel) {
+ if (viewModel.hasOwnProperty("onUpdatedFiles")) {
+ viewModel.onUpdatedFiles(payload);
+ }
+ });
+ } else if (type == "MetadataAnalysisFinished") {
+ _.each(self.allViewModels, function(viewModel) {
+ if (viewModel.hasOwnProperty("onMetadataAnalysisFinished")) {
+ viewModel.onMetadataAnalysisFinished(payload);
+ }
+ });
} else if (type == "MovieRendering") {
new PNotify({title: gettext("Rendering timelapse"), text: _.sprintf(gettext("Now rendering timelapse %(movie_basename)s"), payload)});
} else if (type == "MovieDone") {
diff --git a/src/octoprint/static/js/app/main.js b/src/octoprint/static/js/app/main.js
index 5e0d6172..d81cd623 100644
--- a/src/octoprint/static/js/app/main.js
+++ b/src/octoprint/static/js/app/main.js
@@ -40,12 +40,28 @@ $(function() {
});
//~~ Show settings - to ensure centered
+ var settingsDialog = $('#settings_dialog');
+ settingsDialog.on('show', function() {
+ _.each(allViewModels, function(viewModel) {
+ if (viewModel.hasOwnProperty("onSettingsShown")) {
+ viewModel.onSettingsShown();
+ }
+ });
+ });
+ settingsDialog.on('hidden', function() {
+ _.each(allViewModels, function(viewModel) {
+ if (viewModel.hasOwnProperty("onSettingsHidden")) {
+ viewModel.onSettingsHidden();
+ }
+ });
+ });
$('#navbar_show_settings').click(function() {
- $('#settings_dialog').modal()
+ settingsDialog.modal()
.css({
width: 'auto',
'margin-left': function() { return -($(this).width() /2); }
});
+
return false;
});
diff --git a/src/octoprint/static/js/app/viewmodels/files.js b/src/octoprint/static/js/app/viewmodels/files.js
index 217e96f0..ed28e9c7 100644
--- a/src/octoprint/static/js/app/viewmodels/files.js
+++ b/src/octoprint/static/js/app/viewmodels/files.js
@@ -311,5 +311,15 @@ function GcodeFilesViewModel(printerStateViewModel, loginStateViewModel) {
self.onStartup = function() {
self.requestData();
};
+
+ self.onUpdatedFiles = function(payload) {
+ if (payload.type == "gcode") {
+ self.requestData();
+ }
+ };
+
+ self.onMetadataAnalysisFinished = function(payload) {
+ self.requestData();
+ }
}