Skip to content

Commit

Permalink
fix: is_rockpi and is_raspberry_pi should not break outside Balena #69
Browse files Browse the repository at this point in the history
* read model information from /proc/device-tree/model
in the absense of balena env variable
  • Loading branch information
pritamghanghas committed Feb 28, 2022
1 parent 0064137 commit 33c5451
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 51 deletions.
84 changes: 44 additions & 40 deletions hm_pyhelper/hardware_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@
from enum import Enum, auto
from collections import namedtuple
from hm_pyhelper.exceptions import UnknownVariantException, \
UnknownVariantAttributeException
UnknownVariantAttributeException

BALENA_ENV_PI_MODELS = [
'raspberry-pi2',
'raspberrypi3',
'raspberrypi3-64',
'raspberrypi4-64',
'nebra-hnt',
'raspberrypicm4-ioboard'
]

BALENA_ENV_ROCKPI_MODELS = ['rockpi-4b-rk3399']

SBCInfo = namedtuple('SBCInfo', ['vendor_id', 'vendor_name', 'model_name'])


class DeviceVendor(Enum):
"""
Enum for device vendors.
Expand All @@ -15,10 +26,12 @@ class DeviceVendor(Enum):
ROCK_PI = auto()
RASPBERRY_PI = auto()


def device_model():
with open('/proc/device-tree/model', 'r') as f:
return f.readline().strip()


def sbc_info() -> SBCInfo:
sbc_info = SBCInfo(vendor_id=-1, vendor_name='', model_name='')
dev_model = device_model()
Expand All @@ -32,38 +45,29 @@ def sbc_info() -> SBCInfo:
model_name=dev_model)
return sbc_info


def is_rockpi():
result = sbc_info().vendor_id == DeviceVendor.ROCK_PI

# honor env override
env_value = os.getenv('BALENA_DEVICE_TYPE')
if 'rockpi-4b-rk3399' in env_value:
result = True

return result
if env_value in BALENA_ENV_ROCKPI_MODELS:
return True

# use device tree supplied model name
return sbc_info().vendor_id == DeviceVendor.ROCK_PI


def is_raspberry_pi():
"""
Pulled from
https://www.balena.io/docs/reference/base-images/devicetypes/
"""
result = sbc_info().vendor_id == DeviceVendor.RASPBERRY_PI

# honor evn override
# honor env override
device_type = os.getenv('BALENA_DEVICE_TYPE')
device_type_match = [
'raspberry-pi2',
'raspberrypi3',
'raspberrypi3-64',
'raspberrypi4-64',
'nebra-hnt',
'raspberrypicm4-ioboard'
]

if device_type in device_type_match:
result = True
return result
if device_type in BALENA_ENV_PI_MODELS:
return True

return sbc_info().vendor_id == DeviceVendor.RASPBERRY_PI


variant_definitions = {
Expand All @@ -84,7 +88,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': ['2AHRD-EPN8531', '2AB8JCSR40', '2ARPP-GL5712UX'],
'IC_IDS': ['27187-HNTIN'],
'CONTAINS_IC_IDS': []
},
},

# Nebra Indoor Hotspot, Old identifier
'Indoor': {
Expand All @@ -103,7 +107,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': ['2AHRD-EPN8531', '2AB8JCSR40', '2ARPP-GL5712UX'],
'IC_IDS': ['27187-HNTIN'],
'CONTAINS_IC_IDS': []
},
},

# Nebra Outdoor Hotspot Gen1
'NEBHNT-OUT1': {
Expand All @@ -123,7 +127,7 @@ def is_raspberry_pi():
'XMR201903EG25G', '2AZDM-WIFIRP'],
'IC_IDS': ['27187-HNTOUT'],
'CONTAINS_IC_IDS': []
},
},

# Nebra Outdoor Hotspot Old Identifier
'Outdoor': {
Expand All @@ -143,7 +147,7 @@ def is_raspberry_pi():
'XMR201903EG25G', '2AZDM-WIFIRP'],
'IC_IDS': ['27187-HNTOUT'],
'CONTAINS_IC_IDS': []
},
},

# Nebra Pi 0 Light Hotspot SPI Ethernet
'NEBHNT-LGT-ZS': {
Expand All @@ -162,7 +166,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': ['2ABCB-RPI0W', '2ARPP-GL5712UX'],
'IC_IDS': ['27187-HNTLGTMC'],
'CONTAINS_IC_IDS': ['20953-RPI0W']
},
},

# Nebra Pi 0 Light Hotspot USB Ethernet
'NEBHNT-LGT-ZX': {
Expand All @@ -181,7 +185,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# Nebra Beaglebone Light Hotspot
'NEBHNT-BBB': {
Expand All @@ -200,7 +204,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# Nebra Pocket Beagle Light Hotspot
'NEBHNT-PBB': {
Expand All @@ -219,7 +223,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# Nebra Hotspot HAT ROCK Pi 4 Indoor
'NEBHNT-HHRK4': {
Expand All @@ -240,7 +244,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': ['2ARPP-GL5712UX', '2A3PA-ROCKPI4'],
'IC_IDS': ['27187-HHRK4'],
'CONTAINS_IC_IDS': []
},
},

# Nebra Hotspot HAT ROCK Pi 4 Outdoor
'NEBHNT-HHRK4-OUT': {
Expand All @@ -263,7 +267,7 @@ def is_raspberry_pi():
'XMR201903EG25G'],
'IC_IDS': ['27187-HHRK4-OUT'],
'CONTAINS_IC_IDS': []
},
},

# Nebra Hotspot HAT RPi 3/4 Full
'NEBHNT-HHRPI': {
Expand All @@ -282,7 +286,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# Nebra Hotspot HAT RPi Light
'NEBHNT-HHRPL': {
Expand All @@ -301,7 +305,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# Nebra Hotspot HAT Tinkerboard 1
'NEBHNT-HHTK': {
Expand All @@ -320,7 +324,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# Nebra Hotspot HAT Tinkerboard 2
'NEBHNT-HHTK2': {
Expand All @@ -339,7 +343,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# RAKwireless Hotspot Miner
'COMP-RAKHM': {
Expand All @@ -357,7 +361,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# Helium Hotspot
'COMP-HELIUM': {
Expand All @@ -375,7 +379,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# SenseCAP M1 Hotspot
'COMP-SENSECAPM1': {
Expand All @@ -393,7 +397,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# DIY Pi Supply Hotspot HAT
'DIY-PISLGH': {
Expand All @@ -411,7 +415,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
},
},

# Nebra Indoor Hotspot
'DIY-RAK2287': {
Expand All @@ -429,7 +433,7 @@ def is_raspberry_pi():
'CONTAINS_FCC_IDS': [],
'IC_IDS': [],
'CONTAINS_IC_IDS': []
}
}
}


Expand Down
46 changes: 35 additions & 11 deletions hm_pyhelper/tests/test_hardware_definitions.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import os
import pytest
from unittest import TestCase
from unittest.mock import patch, mock_open, MagicMock
import unittest
from hm_pyhelper import hardware_definitions

from hm_pyhelper.exceptions import UnknownVariantException, \
UnknownVariantAttributeException

from hm_pyhelper.hardware_definitions import variant_definitions, \
from hm_pyhelper.hardware_definitions import is_rockpi, variant_definitions, \
get_variant_attribute, \
is_raspberry_pi

Expand Down Expand Up @@ -79,7 +81,7 @@ def test_get_variant_attribute_unknown_attribute(self):
# raspberry pi model names picked from pi kernel sources
# https://github.com/raspberrypi/linux
# grep -ir "raspberry" linux/arch/arm* | grep "model =" | cut -d "=" -f2
mock_known_pi_models = ["Raspberry Pi Model B+",
mock_known_dts_pi_models = ["Raspberry Pi Model B+",
"Raspberry Pi Model B",
"Raspberry Pi Model B",
"Raspberry Pi Compute Module",
Expand Down Expand Up @@ -111,13 +113,35 @@ def test_get_variant_attribute_unknown_attribute(self):


def test_is_raspberry_pi(self):
mm = MagicMock(name='open', spec=open)
mm.return_value = iter(self.mock_known_pi_models)
with unittest.mock.patch('builtins.open', mm):
for model in self.mock_known_pi_models:
print("testing")
for model in self.mock_known_dts_pi_models:
with patch('builtins.open', new_callable=mock_open, read_data=model):
self.assertTrue(is_raspberry_pi())


if __name__ == "__main__":
unittest.main()
with patch('builtins.open', new_callable=mock_open, read_data="Rock something"):
self.assertFalse(is_raspberry_pi())

# test balena env based detection
for model in hardware_definitions.BALENA_ENV_PI_MODELS:
with patch.dict(os.environ, {'BALENA_DEVICE_TYPE': model}):
self.assertTrue(is_raspberry_pi())
# in absense of the env, it should look for /proc/device-tree/model
# which will not exist on test environment.
with self.assertRaises(FileNotFoundError):
self.assertFalse(is_raspberry_pi())

mock_known_rock_dts_models = ["ROCK PI 4B"]

def test_is_rock_pi(self):
for model in self.mock_known_rock_dts_models:
with patch('builtins.open', new_callable=mock_open, read_data=model):
self.assertTrue(is_rockpi())
with patch('builtins.open', new_callable=mock_open, read_data="raspberry something"):
self.assertFalse(is_rockpi())

# test balena env based detection
for model in hardware_definitions.BALENA_ENV_ROCKPI_MODELS:
with patch.dict(os.environ, {'BALENA_DEVICE_TYPE': model}):
self.assertTrue(is_rockpi())
# in absense of the env, it should look for /proc/device-tree/model
# which will not exist on test environment.
with self.assertRaises(FileNotFoundError):
self.assertFalse(is_rockpi())

0 comments on commit 33c5451

Please sign in to comment.