refactor board detection to dependent on chip; simplify getattr checking
Per feedback here and elsewhere: https://forum.armbian.com/topic/8981-adafruit-circuitpython/?tab=comments#comment-67633 There's still plenty to be done here, but this is cleaner than it was. Also makes some names more consistent, and uses uppercase string values for id constants.
This commit is contained in:
parent
672713699e
commit
0c491f95a2
4 changed files with 134 additions and 131 deletions
|
|
@ -34,18 +34,39 @@ class PlatformDetect:
|
|||
self.board = Board(self)
|
||||
self.chip = Chip(self)
|
||||
|
||||
def cpuinfo_field(self, field):
|
||||
def get_cpuinfo_field(self, field):
|
||||
"""
|
||||
Search /proc/cpuinfo for a field and return its value, if found,
|
||||
otherwise None.
|
||||
"""
|
||||
# Match a line like 'Hardware : BCM2709':
|
||||
pattern = r'^' + field + r'\s+:\s+(.*)$'
|
||||
|
||||
with open('/proc/cpuinfo', 'r') as infile:
|
||||
cpuinfo = infile.read().split('\n')
|
||||
for line in cpuinfo:
|
||||
# Match a line like 'Hardware : BCM2709':
|
||||
pattern = r'^' + field + r'\s+:\s+(.*)$'
|
||||
match = re.search(pattern, line, flags=re.IGNORECASE)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
return None
|
||||
|
||||
def get_armbian_release_field(self, field):
|
||||
"""
|
||||
Search /etc/armbian-release, if it exists, for a field and return its
|
||||
value, if found, otherwise None.
|
||||
"""
|
||||
field_value = None
|
||||
pattern = r'^' + field + r'=(.*)'
|
||||
try:
|
||||
with open("/etc/armbian-release", 'r') as f:
|
||||
armbian = f.read().split('\n')
|
||||
for line in armbian:
|
||||
match = re.search(pattern, line)
|
||||
if match:
|
||||
field_value = match.group(1)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
return field_value
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import adafruit_platformdetect.chip as ap_chip
|
||||
import platform
|
||||
import sys
|
||||
import re
|
||||
|
|
@ -5,25 +6,25 @@ import re
|
|||
# Pi revision codes from:
|
||||
# https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
|
||||
|
||||
BEAGLEBONE_BLACK = "beaglebone_black"
|
||||
FEATHER_HUZZAH="feather_huzzah"
|
||||
FEATHER_M0_EXPRESS="feather_m0_express"
|
||||
PYBOARD = "pyboard"
|
||||
NODEMCU = "nodemcu"
|
||||
ORANGEPI_PC = "orangepipc"
|
||||
BEAGLEBONE_BLACK = "BEAGLEBONE_BLACK"
|
||||
FEATHER_HUZZAH = "FEATHER_HUZZAH"
|
||||
FEATHER_M0_EXPRESS="FEATHER_M0_EXPRESS"
|
||||
PYBOARD = "PYBOARD"
|
||||
NODEMCU = "NODEMCU"
|
||||
ORANGE_PI_PC = "ORANGE_PI_PC"
|
||||
|
||||
RASPBERRY_PI_B = "raspberry_pi_b"
|
||||
RASPBERRY_PI_B_PLUS = "raspberry_pi_b_plus"
|
||||
RASPBERRY_PI_A = "raspberry_pi_a"
|
||||
RASPBERRY_PI_A_PLUS = "raspberry_pi_a_plus"
|
||||
RASPBERRY_PI_CM1 = "raspberry_pi_cm1"
|
||||
RASPBERRY_PI_ZERO = "raspberry_pi_zero"
|
||||
RASPBERRY_PI_ZERO_W = "raspberry_pi_zero_w"
|
||||
RASPBERRY_PI_2B = "raspberry_pi_2b"
|
||||
RASPBERRY_PI_3B = "raspberry_pi_3b"
|
||||
RASPBERRY_PI_3B_PLUS = "raspberry_pi_3b_plus"
|
||||
RASPBERRY_PI_CM3 = "raspberry_pi_cm3"
|
||||
RASPBERRY_PI_3A_PLUS = "raspberry_pi_3a_plus"
|
||||
RASPBERRY_PI_B = "RASPBERRY_PI_B"
|
||||
RASPBERRY_PI_B_PLUS = "RASPBERRY_PI_B_PLUS"
|
||||
RASPBERRY_PI_A = "RASPBERRY_PI_A"
|
||||
RASPBERRY_PI_A_PLUS = "RASPBERRY_PI_A_PLUS"
|
||||
RASPBERRY_PI_CM1 = "RASPBERRY_PI_CM1"
|
||||
RASPBERRY_PI_ZERO = "RASPBERRY_PI_ZERO"
|
||||
RASPBERRY_PI_ZERO_W = "RASPBERRY_PI_ZERO_W"
|
||||
RASPBERRY_PI_2B = "RASPBERRY_PI_2B"
|
||||
RASPBERRY_PI_3B = "RASPBERRY_PI_3B"
|
||||
RASPBERRY_PI_3B_PLUS = "RASPBERRY_PI_3B_PLUS"
|
||||
RASPBERRY_PI_CM3 = "RASPBERRY_PI_CM3"
|
||||
RASPBERRY_PI_3A_PLUS = "RASPBERRY_PI_3A_PLUS"
|
||||
|
||||
# TODO: Should this include RASPBERRY_PI_3A_PLUS or any other models?
|
||||
ANY_RASPBERRY_PI_2_OR_3 = (
|
||||
|
|
@ -55,109 +56,81 @@ class Board:
|
|||
self.detect = detect
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return a human-readable name for the detected board, if any."""
|
||||
name = None
|
||||
if sys.platform == "linux":
|
||||
name = self._linux_computer_name()
|
||||
elif sys_platform == "esp8266": # TODO more conservative board-guessing
|
||||
def id(self):
|
||||
"""Return a unique id for the detected board, if any."""
|
||||
|
||||
chip_id = self.detect.chip.id
|
||||
|
||||
if chip_id == ap_chip.BCM2XXX:
|
||||
return self._pi_id()
|
||||
elif chip_id == ap_chip.AM33XX:
|
||||
return BEAGLEBONE_BLACK
|
||||
elif chip_id == ap_chip.SUN8I:
|
||||
return self._armbian_id()
|
||||
elif chip_id == ap_chip.ESP8266:
|
||||
return FEATHER_HUZZAH
|
||||
elif sys_platform == "samd21":
|
||||
elif chip_id == ap_chip.SAMD21:
|
||||
return FEATHER_M0_EXPRESS
|
||||
elif sys_platform == "pyboard":
|
||||
elif chip_id == ap_chip.STM32:
|
||||
return PYBOARD
|
||||
|
||||
return name
|
||||
return None
|
||||
|
||||
def _linux_computer_name(self):
|
||||
"""Try to detect name of a Linux SBC."""
|
||||
def _pi_id(self):
|
||||
"""Try to detect id of a Raspberry Pi."""
|
||||
# Check for Pi boards:
|
||||
pi_rev_code = self.pi_rev_code
|
||||
pi_rev_code = self._pi_rev_code()
|
||||
if pi_rev_code:
|
||||
for model, codes in _PI_REV_CODES.items():
|
||||
if pi_rev_code in codes:
|
||||
return model
|
||||
|
||||
# Check for BBB:
|
||||
if self.beaglebone_black:
|
||||
return BEAGLEBONE_BLACK
|
||||
|
||||
# Check for OrangePiPC
|
||||
if self.orangepi_pc:
|
||||
return ORANGEPI_PC
|
||||
|
||||
return None
|
||||
|
||||
@property
|
||||
def orangepi_pc(self):
|
||||
"""Check whether the current board is an OrangePi PC."""
|
||||
if self.detect.chip.name != "sun8i":
|
||||
return False
|
||||
try:
|
||||
with open("/etc/armbian-release", 'r') as f:
|
||||
armbian = f.read().split('\n')
|
||||
for line in armbian:
|
||||
match = re.search('^BOARD=(.*)', line)
|
||||
if match:
|
||||
return match.group(1) == "orangepipc"
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
return False
|
||||
|
||||
@property
|
||||
def beaglebone_black(self):
|
||||
"""Check whether the current board is a Beaglebone Black."""
|
||||
if sys.platform != "linux" or self.any_raspberry_pi:
|
||||
return False
|
||||
|
||||
# TODO: beaglebone_black detection is too sloppy, needs to be more specific
|
||||
# before we can detect it
|
||||
return False
|
||||
|
||||
|
||||
# TODO: Check the Beaglebone Black /proc/cpuinfo value instead of first
|
||||
# looking for a Raspberry Pi and then falling back to platform.
|
||||
|
||||
plat = platform.platform().lower()
|
||||
if plat.find('armv7l-with-debian') > -1:
|
||||
return True
|
||||
elif plat.find('armv7l-with-ubuntu') > -1:
|
||||
return True
|
||||
elif plat.find('armv7l-with-glibc2.4') > -1:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@property
|
||||
def any_raspberry_pi(self):
|
||||
return self.pi_rev_code is not None
|
||||
|
||||
@property
|
||||
def any_raspberry_pi_2_or_3(self):
|
||||
return self.name in ANY_RASPBERRY_PI_2_OR_3
|
||||
|
||||
@property
|
||||
def pi_rev_code(self):
|
||||
def _pi_rev_code(self):
|
||||
"""Attempt to find a Raspberry Pi revision code for this board."""
|
||||
# 2708 is Pi 1
|
||||
# 2709 is Pi 2
|
||||
# 2835 is Pi 3 (or greater) on 4.9.x kernel
|
||||
# Anything else is not a Pi.
|
||||
|
||||
if self.detect.cpuinfo_field('Hardware') not in ('BCM2708', 'BCM2709', 'BCM2835'):
|
||||
if self.detect.chip.id != ap_chip.BCM2XXX:
|
||||
# Something else, not a Pi.
|
||||
return None
|
||||
return self.detect.cpuinfo_field('Revision')
|
||||
return self.detect.get_cpuinfo_field('Revision')
|
||||
|
||||
@property
|
||||
def _armbian_id(self):
|
||||
"""Check whether the current board is an OrangePi PC."""
|
||||
board_value = self.detect.get_armbian_release_field('BOARD')
|
||||
if board_value == "orangepipc":
|
||||
return ORANGE_PI_PC
|
||||
return None
|
||||
|
||||
@property
|
||||
def beaglebone_black(self):
|
||||
"""Check whether the current board is a Beaglebone Black."""
|
||||
return self.id == BEAGLEBONE_BLACK
|
||||
|
||||
@property
|
||||
def orange_pi_pc(self):
|
||||
"""Check whether the current board is an Orange Pi PC."""
|
||||
return self.id == ORANGE_PI_PC
|
||||
|
||||
@property
|
||||
def any_raspberry_pi(self):
|
||||
"""Check whether the current board is any Raspberry Pi."""
|
||||
return self._pi_rev_code() is not None
|
||||
|
||||
@property
|
||||
def any_raspberry_pi_2_or_3(self):
|
||||
return self.id in ANY_RASPBERRY_PI_2_OR_3
|
||||
|
||||
def __getattr__(self, attr):
|
||||
"""
|
||||
Detect whether the given attribute is the current board. Currently
|
||||
handles Raspberry Pi models.
|
||||
handles Raspberry Pi models; other board properties are handled by
|
||||
individual methods for the time being.
|
||||
"""
|
||||
# Check Raspberry Pi values:
|
||||
if attr in _PI_REV_CODES:
|
||||
if sys.platform != "linux":
|
||||
return False
|
||||
return self.pi_rev_code in _PI_REV_CODES[attr]
|
||||
|
||||
raise AttributeError(attr + " is not a defined board")
|
||||
if self.id == attr:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -1,35 +1,41 @@
|
|||
import sys
|
||||
|
||||
ESP8266 = "esp8266"
|
||||
SAMD21 = "samd21"
|
||||
STM32 = "stm32"
|
||||
SUN8I = "sun8i"
|
||||
AM33XX = "AM33XX"
|
||||
BCM2XXX = "BCM2XXX"
|
||||
ESP8266 = "ESP8266"
|
||||
SAMD21 = "SAMD21"
|
||||
STM32 = "STM32"
|
||||
SUN8I = "SUN8I"
|
||||
|
||||
class Chip:
|
||||
"""Attempt detection of current chip / CPU."""
|
||||
def __init__(self, detect):
|
||||
self.detect = detect
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
name = None
|
||||
|
||||
def id(self):
|
||||
platform = sys.platform
|
||||
if platform is not None:
|
||||
if platform == "esp8266":
|
||||
name = ESP8266
|
||||
elif platform == "samd21":
|
||||
name = SAMD21
|
||||
elif platform == "pyboard":
|
||||
name = STM32
|
||||
elif platform == "linux":
|
||||
# XXX: Here is where some work to detect ARM / x86 stuff for
|
||||
# real needs to happen.
|
||||
hardwarename = self.detect.cpuinfo_field("Hardware")
|
||||
if not hardwarename:
|
||||
return None
|
||||
if "sun8i" in hardwarename:
|
||||
name = SUN8I
|
||||
else:
|
||||
name = hardwarename
|
||||
if platform == "linux":
|
||||
return self._linux_id()
|
||||
elif platform == "esp8266":
|
||||
return ESP8266
|
||||
elif platform == "samd21":
|
||||
return SAMD21
|
||||
elif platform == "pyboard":
|
||||
return STM32
|
||||
else:
|
||||
return None
|
||||
|
||||
return name
|
||||
def _linux_id(self):
|
||||
"""Attempt to detect the CPU on a computer running the Linux kernel."""
|
||||
id = None
|
||||
|
||||
hardware = self.detect.get_cpuinfo_field("Hardware")
|
||||
if hardware in ('BCM2708', 'BCM2708', 'BCM2835'):
|
||||
id = BCM2XXX
|
||||
elif "AM33XX" in hardwarename:
|
||||
id = AM33XX
|
||||
elif "sun8i" in hardwarename:
|
||||
id = SUN8I
|
||||
|
||||
return id
|
||||
|
|
|
|||
|
|
@ -4,13 +4,16 @@ import adafruit_platformdetect
|
|||
|
||||
detect = adafruit_platformdetect.PlatformDetect()
|
||||
|
||||
print("Chip name: ", detect.chip.name)
|
||||
print("Chip id: ", detect.chip.id)
|
||||
|
||||
print("Board name: ", detect.board.name)
|
||||
print("Board id: ", detect.board.id)
|
||||
|
||||
print("Is this a Pi 3B+?", detect.board.RASPBERRY_PI_3B_PLUS)
|
||||
print("Is this a BBB?", detect.board.BEAGLEBONE_BLACK)
|
||||
|
||||
if detect.board.any_raspberry_pi:
|
||||
print("Raspberry Pi detected.")
|
||||
print("Revision code: ", detect.board.pi_rev_code)
|
||||
print("Revision code: ", detect.board._pi_rev_code())
|
||||
|
||||
if detect.board.beaglebone_black:
|
||||
print("BBB detected")
|
||||
|
|
|
|||
Loading…
Reference in a new issue