Skip to content

Commit dbfad91

Browse files
authored
Merge pull request #38 from Cosik/feature/armbian-support
[Feature] Support for platforms compatible with Armbian
2 parents 8fcc435 + dc1e862 commit dbfad91

File tree

10 files changed

+315
-143
lines changed

10 files changed

+315
-143
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,13 @@ For Raspberry Pi users it's possible to display internal temperature (configurab
88
## Setup
99

1010
Install the plugin using Plugin Manager from Settings
11+
12+
## Need new platform support?
13+
If you need support for additional platform, please inform us and add such information:
14+
* How to read temperature
15+
* How to define platform type
16+
17+
And be ready for testing.
18+
19+
## Change notes:
20+
v 1.0 - added support for all platforms running under Armbian

octoprint_navbartemp/__init__.py

Lines changed: 42 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,83 +10,56 @@
1010
import sys
1111
import re
1212

13+
from .libs.sbc import SBCFactory
14+
15+
1316
class NavBarPlugin(octoprint.plugin.StartupPlugin,
1417
octoprint.plugin.TemplatePlugin,
1518
octoprint.plugin.AssetPlugin,
1619
octoprint.plugin.SettingsPlugin):
1720

1821
def __init__(self):
19-
self.isRaspi = False
20-
self.debugMode = False # to simulate temp on Win/Mac
22+
self.piSocTypes = (["BCM2708", "BCM2709",
23+
"BCM2835"]) # Array of raspberry pi SoC's to check against, saves having a large if/then statement later
24+
self.debugMode = False # to simulate temp on Win/Mac
2125
self.displayRaspiTemp = True
2226
self._checkTempTimer = None
27+
self.sbc = None
2328

2429
def on_after_startup(self):
2530
self.displayRaspiTemp = self._settings.get(["displayRaspiTemp"])
31+
self.piSocTypes = self._settings.get(["piSocTypes"])
2632
self._logger.debug("displayRaspiTemp: %s" % self.displayRaspiTemp)
2733

2834
if sys.platform == "linux2":
29-
with open('/proc/cpuinfo', 'r') as infile:
30-
cpuinfo = infile.read()
31-
# Match a line like 'Hardware : BCM2709'
32-
match = re.search('^Hardware\s+:\s+(\w+)$', cpuinfo, flags=re.MULTILINE | re.IGNORECASE)
33-
34-
if match is None:
35-
# Couldn't find the hardware, assume it isn't a pi.
36-
self.isRaspi = False
37-
elif match.group(1) == 'BCM2708':
38-
self._logger.debug("Pi 1")
39-
self.isRaspi = True
40-
elif match.group(1) == 'BCM2709':
41-
self._logger.debug("Pi 2")
42-
self.isRaspi = True
43-
elif match.group(1) == 'BCM2835':
44-
self._logger.debug("Pi 3")
45-
self.isRaspi = True
46-
47-
if self.isRaspi and self.displayRaspiTemp:
35+
self.sbc = SBCFactory().factory(self._logger)
36+
37+
if self.sbc.is_supported and self.displayRaspiTemp:
4838
self._logger.debug("Let's start RepeatedTimer!")
4939
self.startTimer(30.0)
40+
# debug mode doesn't work if the OS is linux on a regular pc
5041
elif self.debugMode:
51-
self.isRaspi = True
42+
self.sbc.is_supported = True
5243
if self.displayRaspiTemp:
5344
self.startTimer(5.0)
5445

55-
self._logger.debug("is Raspberry Pi? - %s" % self.isRaspi)
46+
self._logger.debug("is supported? - %s" % self.sbc.is_supported)
5647

5748
def startTimer(self, interval):
58-
self._checkTempTimer = RepeatedTimer(interval, self.checkRaspiTemp, None, None, True)
49+
self._checkTempTimer = RepeatedTimer(interval, self.updateSoCTemp, None, None, True)
5950
self._checkTempTimer.start()
6051

61-
def checkRaspiTemp(self):
62-
from sarge import run, Capture
63-
64-
self._logger.debug("Checking Raspberry Pi internal temperature")
65-
66-
if sys.platform == "linux2":
67-
p = run("/opt/vc/bin/vcgencmd measure_temp", stdout=Capture())
68-
p = p.stdout.text
69-
70-
elif self.debugMode:
71-
import random
72-
def randrange_float(start, stop, step):
73-
return random.randint(0, int((stop - start) / step)) * step + start
74-
p = "temp=%s'C" % randrange_float(5, 60, 0.1)
52+
def updateSoCTemp(self):
53+
temp = self.sbc.checkSoCTemp()
54+
self._logger.debug("match: %s" % temp)
55+
self._plugin_manager.send_plugin_message(self._identifier,
56+
dict(isSupported=self.sbc.is_supported,
57+
soctemp=temp))
7558

76-
self._logger.debug("response from sarge: %s" % p)
77-
78-
match = re.search('=(.*)\'', p)
79-
if not match:
80-
self.isRaspi = False
81-
else:
82-
temp = match.group(1)
83-
self._logger.debug("match: %s" % temp)
84-
self._plugin_manager.send_plugin_message(self._identifier, dict(israspi=self.isRaspi, raspitemp=temp))
85-
86-
87-
##~~ SettingsPlugin
59+
##~~ SettingsPlugin
8860
def get_settings_defaults(self):
89-
return dict(displayRaspiTemp = self.displayRaspiTemp)
61+
return dict(displayRaspiTemp=self.displayRaspiTemp,
62+
piSocTypes=self.piSocTypes)
9063

9164
def on_settings_save(self, data):
9265
octoprint.plugin.SettingsPlugin.on_settings_save(self, data)
@@ -104,9 +77,9 @@ def on_settings_save(self, data):
10477
pass
10578
self._plugin_manager.send_plugin_message(self._identifier, dict())
10679

107-
##~~ TemplatePlugin API
80+
##~~ TemplatePlugin API
10881
def get_template_configs(self):
109-
if self.isRaspi:
82+
if self.sbc.is_supported:
11083
return [
11184
dict(type="settings", template="navbartemp_settings_raspi.jinja2")
11285
]
@@ -119,9 +92,10 @@ def get_assets(self):
11992
"js": ["js/navbartemp.js"],
12093
"css": ["css/navbartemp.css"],
12194
"less": ["less/navbartemp.less"]
122-
}
95+
}
96+
97+
##~~ Softwareupdate hook
12398

124-
##~~ Softwareupdate hook
12599
def get_update_information(self):
126100
return dict(
127101
navbartemp=dict(
@@ -130,22 +104,26 @@ def get_update_information(self):
130104

131105
# version check: github repository
132106
type="github_release",
133-
user="imrahil",
107+
user="ntoff",
134108
repo="OctoPrint-NavbarTemp",
135109
current=self._plugin_version,
136110

137111
# update method: pip w/ dependency links
138-
pip="https://github.com/imrahil/OctoPrint-NavbarTemp/archive/{target_version}.zip"
112+
pip="https://github.com/ntoff/OctoPrint-NavbarTemp/archive/{target_version}.zip"
139113
)
140114
)
141115

142-
__plugin_name__ = "Navbar Temperature Plugin"
116+
117+
__plugin_name__ = "Navbar Temperature Plugin (ntoff mod)"
118+
__plugin_author__ = "Jarek Szczepanski (modified by ntoff)"
119+
__plugin_url__ = "https://github.com/ntoff/OctoPrint-NavbarTemp"
120+
143121

144122
def __plugin_load__():
145-
global __plugin_implementation__
146-
__plugin_implementation__ = NavBarPlugin()
123+
global __plugin_implementation__
124+
__plugin_implementation__ = NavBarPlugin()
147125

148-
global __plugin_hooks__
149-
__plugin_hooks__ = {
150-
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
151-
}
126+
global __plugin_hooks__
127+
__plugin_hooks__ = {
128+
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
129+
}

octoprint_navbartemp/libs/__init__.py

Whitespace-only changes.

octoprint_navbartemp/libs/sbc.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
'''
2+
3+
This module contain factory patter for different hardware platforms. Adding new platform is simple, first you need
4+
add class with inheriting from SBC. Inside you have to define differences between parent class and child. You can easily
5+
overwrite methods and parameters. For reference please look at Armbiand and RPi classes.
6+
7+
Last step is to define way of detecting platform type. It could be very different depending on OS.
8+
9+
'''
10+
11+
import os
12+
import re
13+
14+
15+
class SBCFactory(object):
16+
17+
piSocTypes = (["BCM2708", "BCM2709",
18+
"BCM2835"]) # Array of raspberry pi SoC's to check against, saves having a large if/then statement later
19+
20+
# Create based on class name:
21+
def factory(self, logger):
22+
"""
23+
Method is returning handler to object based on defined criteria
24+
:param logger: global logger
25+
:return: handler to proper object
26+
"""
27+
if self._is_armbian():
28+
return Armbian(logger)
29+
elif self._is_rpi(logger):
30+
return RPi(logger)
31+
32+
return SBC()
33+
34+
def _is_rpi(self, logger):
35+
"""
36+
Detecting if is RPi - based on original code
37+
:param logger:
38+
:return:
39+
"""
40+
with open('/proc/cpuinfo', 'r') as infile:
41+
cpuinfo = infile.read()
42+
# Match a line like 'Hardware : BCM2709'
43+
match = re.search('Hardware\s+:\s+(\w+)', cpuinfo, flags=re.MULTILINE | re.IGNORECASE)
44+
45+
if match.group(1) in self.piSocTypes:
46+
logger.info("Broadcom detected")
47+
return True
48+
49+
def _is_armbian(self):
50+
"""
51+
Detecting armbian - checking if armbian monitor exist
52+
:return:
53+
"""
54+
return os.path.exists("/etc/armbianmonitor")
55+
56+
57+
class SBC(object):
58+
59+
temp_cmd = ''
60+
is_supported = False
61+
debugMode = False
62+
parse_pattern = ''
63+
64+
65+
def checkSoCTemp(self):
66+
if self.is_supported:
67+
from sarge import run, Capture
68+
69+
self._logger.info("Checking SoC internal temperature")
70+
p = run(self.temp_cmd, stdout=Capture())
71+
if p.returncode == 1:
72+
self.is_supported = False
73+
self._logger.info("SoC temperature not found.")
74+
else:
75+
p = p.stdout.text
76+
77+
# elif self.debugMode: # doesn't work on linux
78+
# import random
79+
# def randrange_float(start, stop, step):
80+
# return random.randint(0, int((stop - start) / step)) * step + start
81+
#
82+
# p = "temp=%s'C" % randrange_float(5, 60, 0.1)
83+
84+
self._logger.debug("response from sarge: %s" % p)
85+
self._logger.debug("used pattern: %r" % self.parse_pattern)
86+
match = re.search(self.parse_pattern, p)
87+
temp = 0
88+
if not match:
89+
self._logger.debug("match: not found")
90+
self.is_supported = False
91+
else:
92+
temp = self.parse_tepmerature(match)
93+
self._logger.debug("match: %s" % str(temp))
94+
95+
return temp
96+
return 0
97+
98+
def parse_tepmerature(self, re_output):
99+
return re_output.group(1)
100+
101+
102+
class RPi(SBC):
103+
104+
def __init__(self, logger):
105+
self.is_supported = True
106+
self.temp_cmd = '/opt/vc/bin/vcgencmd measure_temp'
107+
self.parse_pattern = '=(.*)\''
108+
self._logger = logger
109+
110+
111+
class Armbian(SBC):
112+
113+
def __init__(self, logger):
114+
self.is_supported = True
115+
self.temp_cmd = 'cat /etc/armbianmonitor/datasources/soctemp'
116+
self.parse_pattern = '(\d+)'
117+
self._logger = logger
118+
119+
def parse_tepmerature(self, re_output):
120+
"""
121+
We are expecting that temp of SoC will be no more that 3 digit int. Armbian on Odroid is returning ex 44000 but
122+
on orangePi 26
123+
:param re_output:
124+
:return:
125+
"""
126+
# TODO: depending on situation in the future maybe it will be necessary to split it.
127+
temp = re_output.group(1)
128+
if len(temp) == 2 or len(temp) == 3:
129+
return float(temp)
130+
elif len(temp) >= 4:
131+
return float(re_output.group(1)) / 1000
132+
133+
return float(re_output.group(1))
Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,40 @@
1-
#navbar .navbar-inner .nav>li>div>p,#navbar .navbar-inner .nav>li>p{color:#333}#navbar .navbar-inner.orange .nav>li>div>p,#navbar .navbar-inner.orange .nav>li>p,#navbar .navbar-inner.red .nav>li>div>p,#navbar .navbar-inner.red .nav>li>p{color:#f2f2f2}#navbar .navbar-inner.green .nav>li>div>p,#navbar .navbar-inner.green .nav>li>p,#navbar .navbar-inner.yellow .nav>li>div>p,#navbar .navbar-inner.yellow .nav>li>p{color:#333}#navbar .navbar-inner.black .nav>li>div>p,#navbar .navbar-inner.black .nav>li>p,#navbar .navbar-inner.blue .nav>li>div>p,#navbar .navbar-inner.blue .nav>li>p,#navbar .navbar-inner.violet .nav>li>div>p,#navbar .navbar-inner.violet .nav>li>p{color:#f2f2f2}
1+
.navbar-inner .navbar-text {
2+
color: #333;
3+
text-shadow: 0 1px 0 #c8c8c8;
4+
cursor: default;
5+
}
6+
.navbar-inner.blue .navbar-text,
7+
.navbar-inner.red .navbar-text,
8+
.navbar-inner.orange .navbar-text,
9+
.navbar-inner.yellow .navbar-text,
10+
.navbar-inner.violet .navbar-text,
11+
.navbar-inner.black .navbar-text {
12+
color: #f2f2f2;
13+
}
14+
.navbar-inner.white .navbar-text {
15+
color: #333;
16+
}
17+
.navbar-inner.black .navbar-text {
18+
text-shadow: 0 1px 0 #5e5e5e;
19+
}
20+
.navbar-inner.white .navbar-text {
21+
text-shadow: 0 1px 0 #c8c8c8;
22+
}
23+
.navbar-inner.red .navbar-text {
24+
text-shadow: 0 1px 0 #d86761;
25+
}
26+
.navbar-inner.blue .navbar-text {
27+
text-shadow: 0 1px 0 #1a66ff;
28+
}
29+
.navbar-inner.green .navbar-text {
30+
text-shadow: 0 1px 0 #50da00;
31+
}
32+
.navbar-inner.yellow .navbar-text {
33+
text-shadow: 0 1px 0 #c2b00c;
34+
}
35+
.navbar-inner.orange .navbar-text {
36+
text-shadow: 0 1px 0 #f6a570;
37+
}
38+
.navbar-inner.violet .navbar-text {
39+
text-shadow: 0 1px 0 #a774ff;
40+
}

0 commit comments

Comments
 (0)