Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions octoprint_mrbeam/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def __init__(self):
self.slicing_progress_last = -1
self._logger = mrb_logger("octoprint.plugins.mrbeam")

self._device_info = deviceInfo(use_dummy_values=IS_X86)
self._device_info = deviceInfo(self, use_dummy_values=IS_X86)
self._hostname = None # see self.getHosetname()
self._serial_num = None
self._mac_addrs = dict()
Expand All @@ -183,6 +183,8 @@ def __init__(self):

self._gcode_deletion_thread = None

self._plugins_versions = None

# MrBeam Events needs to be registered in OctoPrint in order to be send to the frontend later on
MrBeamEvents.register_with_octoprint()

Expand Down Expand Up @@ -435,6 +437,7 @@ def get_settings_defaults(self):
)

def on_settings_load(self):
self._plugins_versions = self._device_info.get_software_versions()
return dict(
svgDPI=self._settings.get(["svgDPI"]),
dxfScale=self._settings.get(["dxfScale"]),
Expand Down Expand Up @@ -477,6 +480,7 @@ def on_settings_load(self):
),
software_update_branches=self.get_update_branch_info(),
_version=self._plugin_version,
plugins_versions=self._plugins_versions,
review=dict(
given=self.review_handler.is_review_already_given(),
ask=self._settings.get(["review", "ask"]),
Expand Down Expand Up @@ -792,6 +796,7 @@ def on_ui_render(self, now, request, render_kwargs):
init_ts_ms=time.time() * 1000,
language=language,
beamosVersionNumber=self._plugin_version,
plugins_versions=json.dumps(self._plugins_versions),
beamosVersionBranch=self._branch,
beamosVersionDisplayVersion=display_version_string,
beamosVersionImage=self._octopi_info,
Expand Down Expand Up @@ -2489,9 +2494,9 @@ def on_event(self, event, payload):
payload.get("remoteAddress", None)
)
self.fire_event(
MrBeamEvents.MRB_PLUGIN_VERSION,
MrBeamEvents.MRB_PLUGINS_VERSIONS,
payload=dict(
version=self._plugin_version, is_first_run=self.isFirstRun()
plugins_versions=self._plugins_versions, is_first_run=self.isFirstRun(),
),
)

Expand Down
41 changes: 3 additions & 38 deletions octoprint_mrbeam/analytics/timer_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from analytics_keys import AnalyticsKeys as ak
from octoprint_mrbeam.mrb_logger import mrb_logger
from octoprint_mrbeam.util.cmd_exec import exec_cmd, exec_cmd_output
from octoprint_mrbeam.util.device_info import deviceInfo


class TimerHandler:
Expand Down Expand Up @@ -215,7 +216,7 @@ def _software_versions(self):
I do not se any reason any more to run this as a timed and threaded task.
it made sens when we did a filesystem checksum calculation... _software_versions_and_checksums()
"""
sw_versions = self._get_software_versions()
sw_versions = deviceInfo(self).get_software_versions()
self._logger.debug("Software Version info: \n{}".format(sw_versions))
self._plugin.analytics_handler.add_software_versions(sw_versions)

Expand Down Expand Up @@ -260,7 +261,7 @@ def _software_versions_and_checksums(self):
"src_path": "/home/pi/site-packages/",
},
}
sw_versions = self._get_software_versions()
sw_versions = deviceInfo(self).get_software_versions()

if self._analytics_handler.is_analytics_enabled():
for name, conf in folders.iteritems():
Expand All @@ -278,42 +279,6 @@ def _software_versions_and_checksums(self):
except:
self._logger.exception("Exception in _software_versions_and_checksums(): ")

def _get_software_versions(self):
result = dict()
software_info = None

try:
plugin_info = self._plugin._plugin_manager.get_plugin_info("softwareupdate")
impl = plugin_info.implementation
# using the method get_current_versions() is OK as it is threadsafe
software_info, _, _ = impl.get_current_versions()
self._logger.debug("Software_info: \n {}".format(software_info))
except Exception as e:
self._logger.exception(
"Exception while reading software_info from softwareupdate plugin. Error:{} ".format(e)
)
return result

if isinstance(software_info, dict) is False:
self._logger.warn(
"get_current_versions() Can't read software version from softwareupdate plugin."
)
return result

# Reaching this section means we are OK so far
for name, info in software_info.iteritems():
commit_hash = info["information"]["local"].get("name", None)
if commit_hash is not None:
# regex: "Commit 89nhfbffnf7f8fbfgfndhf" --> "89nhfbffnf7f8fbfgfndhf"
regex_match = re.match(r"Commit (\S+)", commit_hash)
if regex_match is not None:
commit_hash = regex_match.group(1)
result[name] = dict(
version=info.get("displayVersion", None),
commit_hash=commit_hash,
)
return result

def _num_files(self):
try:
all_files = self._plugin._file_manager.list_files(path="", recursive=True)[
Expand Down
2 changes: 1 addition & 1 deletion octoprint_mrbeam/camera/label_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class LabelPrinter(object):
def __init__(self, plugin, use_dummy_values=False):
self._plugin = plugin
self._logger = mrb_logger("octoprint.plugins.mrbeam.camera.label_printer")
self._device_info = deviceInfo(use_dummy_values=use_dummy_values)
self._device_info = deviceInfo(plugin, use_dummy_values=use_dummy_values)

def print_label(self, request):
valid_commands = {"print_label": ["labelType"]}
Expand Down
2 changes: 1 addition & 1 deletion octoprint_mrbeam/mrbeam_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class MrBeamEvents(object):
DUSTING_MODE_START = "DustingModeStart"

ANALYTICS_DATA = "MrbAnalyticsData"
MRB_PLUGIN_VERSION = "MrbPluginVersion"
MRB_PLUGINS_VERSIONS = "MrbPluginsVersions"
JOB_TIME_ESTIMATED = "JobTimeEstimated"

HARDWARE_MALFUNCTION = "HardwareMalfunction"
Expand Down
6 changes: 3 additions & 3 deletions octoprint_mrbeam/printing/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
)
from octoprint.settings import settings
from octoprint_mrbeam.mrb_logger import mrb_logger
from octoprint_mrbeam.util import dict_get, device_info
from octoprint_mrbeam.util import dict_get
from octoprint_mrbeam.util.log import logme


Expand Down Expand Up @@ -199,7 +199,7 @@ def get(self, identifier):
return dict_merge(hard_coded, file_based_result)
else:
if identifier is None:
identifier = device_info.deviceInfo().get_type()
identifier = deviceInfo(self).get_type()
else:
default["id"] = identifier
default["model"] = identifier[-1]
Expand Down Expand Up @@ -258,7 +258,7 @@ def exists(self, identifier):
def _load_all(self):
"""Extend the file based ``PrinterProfileManager._load_all`` with the few hardcoded ones we have."""
file_based_profiles = PrinterProfileManager._load_all(self)
device_type = deviceInfo().get_type()
device_type = deviceInfo(self).get_type()
mrbeam_generated_profiles = {device_type: self.get(device_type)}
mrbeam_profiles = dict_merge(LASER_PROFILE_MAP, mrbeam_generated_profiles)
return dict_merge(mrbeam_profiles, file_based_profiles)
Expand Down
53 changes: 38 additions & 15 deletions octoprint_mrbeam/static/js/mother_viewmodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,14 +402,14 @@ $(function () {
self.removeLoadingOverlay();
};

self.onEventMrbPluginVersion = function (payload) {
self.onEventMrbPluginsVersions = function (payload) {
if (
payload?.version ||
payload?.plugins_versions ||
payload?.is_first_run ||
payload?.mrb_state?.laser_model
) {
self.force_reload_if_required(
payload["version"],
payload["plugins_versions"],
payload["is_first_run"],
payload["mrb_state"]["laser_model"]
);
Expand Down Expand Up @@ -442,25 +442,25 @@ $(function () {
};

/**
* Reloads the frontend bypassing any cache if backend version of mr beam plugin is different from the frontend version
* Reloads the frontend bypassing any cache if backend version of any plugin is different from the frontend version
* or id the firstRunFlag is different.
* This happens sometimes after a software update or if the user used a reset stick
* @private
* @param backend_version (optional) If no version is given the function reads it from self.settings
* @param backend_versions (optional) If versions are not given the function reads it from self.settings
* @param isFirstRun (optional) If no firstRun flag is given the function reads it from self.settings
* @param laserHeadModel (optional) If no laserHeadModel flag is given the function reads it from self.settings
*/
self.force_reload_if_required = function (
backend_version,
backend_versions,
isFirstRun,
laserHeadModel
) {
laserHeadModel = laserHeadModel?.toString();
if (self.settings.settings?.plugins?.mrbeam) {
let mrb_settings = self.settings.settings.plugins.mrbeam;
backend_version = backend_version
? backend_version
: mrb_settings._version();
backend_versions = backend_versions
? backend_versions
: self.parsePluginsVersions(mrb_settings.plugins_versions);
isFirstRun = isFirstRun
? isFirstRun
: mrb_settings.isFirstRun();
Expand All @@ -471,16 +471,17 @@ $(function () {
}
}
if (
backend_version !== BEAMOS_VERSION ||
(backend_versions &&
!self.areAllVersionsEqual(backend_versions, JSON.parse(PLUGINS_VERSIONS))) ||
isFirstRun !== CONFIG_FIRST_RUN ||
(laserHeadModel !== undefined &&
laserHeadModel !== MRBEAM_LASER_HEAD_MODEL)
) {
console.log(
"Frontend reload check: RELOAD! (version: frontend=" +
BEAMOS_VERSION +
"Frontend reload check: RELOAD! (versions: frontend=" +
PLUGINS_VERSIONS +
", backend=" +
backend_version +
JSON.stringify(backend_versions) +
", isFirstRun: frontend=" +
CONFIG_FIRST_RUN +
", backend=" +
Expand All @@ -495,8 +496,8 @@ $(function () {
window.location.href = "/?ts=" + Date.now();
} else {
console.log(
"Frontend reload check: OK (version: " +
BEAMOS_VERSION +
"Frontend reload check: OK (versions: " +
PLUGINS_VERSIONS +
", isFirstRun: " +
CONFIG_FIRST_RUN +
", laserheadModel: " +
Expand All @@ -506,6 +507,28 @@ $(function () {
}
};

self.parsePluginsVersions = function (plugins_versions) {
let result = {};
for (let key of Object.keys(plugins_versions)) {
result[key] = {
version: plugins_versions[key].version(),
commit_hash: plugins_versions[key].commit_hash()
};
}
return result;
}

self.areAllVersionsEqual = function (backend_versions, frontend_versions) {
// if backend_versions was an empty object due to backend failure,
// then this will return true and the page will not keep reloading
for (let key of Object.keys(backend_versions)) {
if(frontend_versions[key]["version"] !== backend_versions[key]["version"]){
return false;
}
}
return true;
}

/**
* controls fullscreen functionality unsing on screenfull.js
*/
Expand Down
2 changes: 1 addition & 1 deletion octoprint_mrbeam/static/js/ready_to_laser_viewmodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ $(function () {
self._fromData(payload);
};

self.onEventMrbPluginVersion = function (payload) {
self.onEventMrbPluginsVersions = function (payload) {
self._fromData(payload);
};

Expand Down
2 changes: 2 additions & 0 deletions octoprint_mrbeam/templates/mrbeam_initscript.jinja2
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script lang="javascript">
var BEAMOS_VERSION = "{{ beamosVersionNumber }}";
// PLUGINS_VERSIONS is set by single quotes since "pluginVersions" is returning a JSON dump which will break with double quotes
var PLUGINS_VERSIONS = '{{ plugins_versions }}';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using quotes you could try to use some of flask filters to make it easier. They seem to be pretty powerful.
Here is an example that would match this needs using tojson and safe https://stackoverflow.com/questions/24719592/sending-data-as-json-object-from-python-to-javascript-with-jinja
You would also need to remove the json.dumps call on the initialisation.

var BEAMOS_BRANCH = "{{ beamosVersionBranch }}";
var BEAMOS_DISPLAY_VERSION = "{{ beamosVersionDisplayVersion }}";
var BEAMOS_IMAGE = "{{ beamosVersionImage }}";
Expand Down
43 changes: 40 additions & 3 deletions octoprint_mrbeam/util/device_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
_instance = None


def deviceInfo(use_dummy_values=False):
def deviceInfo(plugin, use_dummy_values=False):
global _instance
if _instance is None:
_instance = DeviceInfo(use_dummy_values=use_dummy_values)
_instance = DeviceInfo(plugin, use_dummy_values=use_dummy_values)
return _instance


Expand Down Expand Up @@ -48,8 +48,9 @@ class DeviceInfo(object):
KEY_PRODUCTION_DATE = "production_date"
KEY_MODEL = "model"

def __init__(self, use_dummy_values=False):
def __init__(self, plugin, use_dummy_values=False):
self._logger = mrb_logger("octoprint.plugins.mrbeam.util.device_info")
self._plugin = plugin
self._device_data = (
self._read_file() if not use_dummy_values else self._get_dummy_values()
)
Expand Down Expand Up @@ -137,6 +138,42 @@ def get_beamos_version_number(self):
self._logger.debug("beamos_version invalid: " + beamos_version)
return None

def get_software_versions(self):
result = dict()
software_info = None

try:
plugin_info = self._plugin._plugin_manager.get_plugin_info("softwareupdate")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is softwareupdate_plugin_info right?

This is also the only place where we need the plugin... I don't think we need to store a reference to the plugin from the DeviceInfo. It seems like to initialise this class we need to pass any plugin to it... Doesn't feel like it belongs here... If we need the softwareupdate info I think we should directly pass it in the constructor.
Another flag that shows that this is smelly is that we are directly calling the _plugin_manager which is a private variable which means it shouldn't be used outside of its own class.

impl = plugin_info.implementation
# using the method get_current_versions() is OK as it is threadsafe
software_info, _, _ = impl.get_current_versions()
self._logger.debug("Software_info: \n {}".format(software_info))
except Exception as e:
self._logger.exception(
"Exception while reading software_info from softwareupdate plugin. Error:{} ".format(e)
)
return result

if isinstance(software_info, dict) is False:
self._logger.warn(
"get_current_versions() Can't read software version from softwareupdate plugin."
)
return result

# Reaching this section means we are OK so far
for name, info in software_info.iteritems():
commit_hash = info["information"]["local"].get("name", None)
if commit_hash is not None:
# regex: "Commit 89nhfbffnf7f8fbfgfndhf" --> "89nhfbffnf7f8fbfgfndhf"
regex_match = re.match(r"Commit (\S+)", commit_hash)
if regex_match is not None:
commit_hash = regex_match.group(1)
result[name] = dict(
version=info.get("displayVersion", None),
commit_hash=commit_hash,
)
return result

def _read_file(self):
try:
# See configparser for a better solution
Expand Down