From 1180e4e27bbe01838eda5fb625adb6a2664676b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?=
Date: Fri, 10 Nov 2017 18:27:52 +0100
Subject: [PATCH] Fix & extend environment detection on Pi
---
.../plugins/octopi_support/__init__.py | 55 ++++++++----
.../templates/octopi_support_about.jinja2 | 3 +-
tests/plugins/test_octopi_support.py | 89 +++++++++++++++++++
3 files changed, 127 insertions(+), 20 deletions(-)
create mode 100644 tests/plugins/test_octopi_support.py
diff --git a/src/octoprint/plugins/octopi_support/__init__.py b/src/octoprint/plugins/octopi_support/__init__.py
index 0ffc6d11..d71eb60f 100644
--- a/src/octoprint/plugins/octopi_support/__init__.py
+++ b/src/octoprint/plugins/octopi_support/__init__.py
@@ -55,18 +55,32 @@ def get_octopi_version():
return version_line.strip()
-def get_pi_revision():
+def get_pi_cpuinfo():
+ fields = dict(revision="Revision",
+ hardware="Hardware",
+ serial="Serial")
+
+ result = dict()
with open(_CPUINFO_PATH) as f:
for line in f:
- if line and line.startswith("Revision:"):
- return line[line.index(":") + 1:].strip()
- return "unknown"
+ if not line:
+ continue
+
+ for key, prefix in fields.items():
+ if line.startswith(prefix):
+ result[key] = line[line.index(":") + 1:].strip()
+
+ return result
-def get_pi_model(revision):
+def get_pi_model(hardware, revision):
+ if hardware not in ("BCM2835",):
+ return "unknown"
+
if revision.startswith("1000"):
# strip flag for over-volted (https://elinux.org/RPi_HardwareHistory#Which_Pi_have_I_got.3F)
revision = revision[4:]
+
return _RPI_REVISION_MAP.get(revision.lower(), "unknown")
@@ -77,22 +91,20 @@ class OctoPiSupportPlugin(octoprint.plugin.EnvironmentDetectionPlugin,
def __init__(self):
self._version = None
- self._revision = None
+ self._cpuinfo = dict()
self._model = None
#~~ EnvironmentDetectionPlugin
def get_additional_environment(self):
return dict(version=self._get_version(),
- revision=self._get_revision(),
+ revision=self._get_cpuinfo().get("revision", "unknown"),
model=self._get_model())
#~~ SimpleApiPlugin
def on_api_get(self, request):
- return flask.jsonify(version=self._get_version(),
- revision=self._get_revision(),
- model=self._get_model())
+ return flask.jsonify(version=self._get_version())
#~~ AssetPlugin
@@ -111,12 +123,12 @@ class OctoPiSupportPlugin(octoprint.plugin.EnvironmentDetectionPlugin,
def get_template_vars(self):
version = self._get_version()
- revision = self._get_revision()
+ cpuinfo = self._get_cpuinfo()
model = self._get_model()
return dict(version=version,
- rpi=(revision is not None and revision != "unknown" and model is not None and model != "unknown"),
- rpi_revision=revision,
+ rpi_revision=cpuinfo.get("revision", "unknown"),
+ rpi_serial=cpuinfo.get("serial", "unknown"),
rpi_model=model)
#~~ Helpers
@@ -127,23 +139,28 @@ class OctoPiSupportPlugin(octoprint.plugin.EnvironmentDetectionPlugin,
self._version = get_octopi_version()
except:
self._logger.exception("Error while reading OctoPi version from file {}".format(_OCTOPI_VERSION_PATH))
+ self._version = "unknown"
return self._version
def _get_model(self):
if self._model is None:
try:
- self._model = get_pi_model(self._get_revision())
+ cpuinfo = self._get_cpuinfo()
+ self._model = get_pi_model(cpuinfo.get("hardware", "unknown"),
+ cpuinfo.get("revision", "unknown"))
except:
self._logger.exception("Error while detecting RPi model")
+ self._model = "unknown"
return self._model
- def _get_revision(self):
- if self._revision is None:
+ def _get_cpuinfo(self):
+ if self._cpuinfo is None:
try:
- self._revision = get_pi_revision()
+ self._cpuinfo = get_pi_cpuinfo()
except:
- self._logger.exception("Error while detecting RPi revision")
- return self._revision
+ self._logger.exception("Error while fetching cpu info")
+ self._cpuinfo = dict()
+ return self._cpuinfo
def __plugin_check__():
from octoprint.util.platform import get_os
diff --git a/src/octoprint/plugins/octopi_support/templates/octopi_support_about.jinja2 b/src/octoprint/plugins/octopi_support/templates/octopi_support_about.jinja2
index 6272b1ab..dcc15c26 100644
--- a/src/octoprint/plugins/octopi_support/templates/octopi_support_about.jinja2
+++ b/src/octoprint/plugins/octopi_support/templates/octopi_support_about.jinja2
@@ -30,12 +30,13 @@
www.gnu.org/licenses/gpl-3.0.en.html.
-{% if plugin_octopi_support_rpi %}
+{% if plugin_octopi_support_rpi_model != "unknown" %}
{{ _('About this Raspberry Pi') }}
- Model: {{ plugin_octopi_support_rpi_model }}
- Revision: {{ plugin_octopi_support_rpi_revision }}
+ - Serial: {{ plugin_octopi_support_rpi_serial }}
{% endif %}
diff --git a/tests/plugins/test_octopi_support.py b/tests/plugins/test_octopi_support.py
new file mode 100644
index 00000000..ad6140a3
--- /dev/null
+++ b/tests/plugins/test_octopi_support.py
@@ -0,0 +1,89 @@
+
+import unittest
+import ddt
+import mock
+
+OCTOPI_VERSION = "0.14.0"
+
+CPUINFO = """
+processor : 0
+model name : ARMv7 Processor rev 4 (v7l)
+BogoMIPS : 38.40
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 4
+
+processor : 1
+model name : ARMv7 Processor rev 4 (v7l)
+BogoMIPS : 38.40
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 4
+
+processor : 2
+model name : ARMv7 Processor rev 4 (v7l)
+BogoMIPS : 38.40
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 4
+
+processor : 3
+model name : ARMv7 Processor rev 4 (v7l)
+BogoMIPS : 38.40
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 4
+
+Hardware : BCM2835
+Revision : a02082
+Serial : 000000000abcdef1
+"""
+
+@ddt.ddt
+class OctoPiSupportTestCase(unittest.TestCase):
+
+ def test_get_octopi_version(self):
+ from octoprint.plugins.octopi_support import get_octopi_version
+
+ with mock.patch("__builtin__.open", mock.mock_open(), create=True) as m:
+ m.return_value.readline.return_value = OCTOPI_VERSION
+ version = get_octopi_version()
+
+ m.assert_called_once_with("/etc/octopi_version", "r")
+ self.assertEqual(version, "0.14.0")
+
+ def test_get_pi_cpuinfo(self):
+ from octoprint.plugins.octopi_support import get_pi_cpuinfo
+
+ with mock.patch("__builtin__.open", mock.mock_open(), create=True) as m:
+ m.return_value.__iter__.return_value = CPUINFO.splitlines()
+ cpuinfo = get_pi_cpuinfo()
+
+ m.assert_called_once_with("/proc/cpuinfo")
+ self.assertDictEqual(cpuinfo, dict(hardware="BCM2835", revision="a02082", serial="000000000abcdef1"))
+
+ @ddt.data(
+ ("BCM2835", "a02082", "3B"),
+ ("BCM2835", "1000a02082", "3B"),
+
+ # failures
+ ("something else", "a02082", "unknown"),
+ ("BCM2835", "aabbccdd", "unknown")
+ )
+ @ddt.unpack
+ def test_get_pi_model(self, hardware, revision, expected):
+ from octoprint.plugins.octopi_support import get_pi_model
+ actual = get_pi_model(hardware, revision)
+ self.assertEqual(actual, expected)