Skip to content
This repository was archived by the owner on Sep 30, 2019. It is now read-only.

Commit e3b38fa

Browse files
committed
Refactor platform_detect to Platform, add Pi revision detect function, and default I2C bus function.
1 parent 48a6f68 commit e3b38fa

File tree

6 files changed

+162
-73
lines changed

6 files changed

+162
-73
lines changed

Adafruit_GPIO/I2C.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
import smbus
2626

27+
import Adafruit_GPIO.Platform as Platform
28+
2729

2830
logger = logging.getLogger(__name__)
2931

@@ -40,10 +42,22 @@ def reverseByteOrder(data):
4042

4143
def get_default_bus():
4244
"""Return the default bus number based on the device platform. For a
43-
Raspberry Pi either bus 0 or 1 (baed on the Pi revision) will be returned.
45+
Raspberry Pi either bus 0 or 1 (based on the Pi revision) will be returned.
4446
For a Beaglebone Black the first user accessible bus, 1, will be returned.
4547
"""
46-
return 0
48+
plat = Platform.platform_detect()
49+
if plat == Platform.RASPBERRY_PI:
50+
if Platform.pi_revision() == 1:
51+
# Revision 1 Pi uses I2C bus 0.
52+
return 0
53+
else:
54+
# Revision 2 Pi uses I2C bus 1.
55+
return 1
56+
elif plat == Platform.BEAGLEBONE_BLACK:
57+
# Beaglebone Black has multiple I2C buses, default to 1 (P9_19 and P9_20).
58+
return 1
59+
else:
60+
raise RuntimeError('Could not determine default I2C bus for platform.')
4761

4862

4963
class Device(object):

Adafruit_GPIO/platform_detect.py Adafruit_GPIO/Platform.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
# SOFTWARE.
2121
import platform
22+
import re
2223

2324
# Platform identification constants.
2425
UNKNOWN = 0
@@ -47,4 +48,24 @@ def platform_detect():
4748
elif plat.lower().find('armv7l-with-debian') > -1:
4849
return BEAGLEBONE_BLACK
4950
else:
50-
return UNKNOWN
51+
return UNKNOWN
52+
53+
def pi_revision():
54+
"""Detect the revision number of a Raspberry Pi, useful for changing
55+
functionality like default I2C bus based on revision."""
56+
# Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History
57+
with open('/proc/cpuinfo', 'r') as infile:
58+
for line in infile:
59+
# Match a line of the form "Revision : 0002" while ignoring extra
60+
# info in front of the revsion (like 1000 when the Pi was over-volted).
61+
match = re.match('Revision\s+:\s+.*(\w{4})$', line)
62+
if match and match.group(1) in ['0002', '0003']:
63+
# Return revision 1 if revision ends with 0002 or 0003.
64+
return 1
65+
elif match:
66+
# Assume revision 2 if revision ends with any other 4 chars.
67+
return 2
68+
else:
69+
# Couldn't find the revision, throw an exception.
70+
raise RuntimeError('Could not determine Raspberry Pi revision.')
71+

test/test_GPIO.py

+10-17
Original file line numberDiff line numberDiff line change
@@ -107,25 +107,18 @@ def test_input(self):
107107

108108

109109
class TestGetPlatformGPIO(unittest.TestCase):
110+
@patch.dict('sys.modules', {'RPi': Mock(), 'RPi.GPIO': Mock()})
111+
@patch('platform.platform', Mock(return_value='Linux-3.10.25+-armv6l-with-debian-7.4'))
110112
def test_raspberrypi(self):
111-
rpi = Mock()
112-
with patch('platform.platform',
113-
new=Mock(return_value='Linux-3.10.25+-armv6l-with-debian-7.4')):
114-
with patch.dict('sys.modules',
115-
{'RPi': rpi, 'RPi.GPIO': rpi.gpio}):
116-
gpio = GPIO.get_platform_gpio()
117-
self.assertIsInstance(gpio, GPIO.RPiGPIOAdapter)
113+
gpio = GPIO.get_platform_gpio()
114+
self.assertIsInstance(gpio, GPIO.RPiGPIOAdapter)
118115

116+
@patch.dict('sys.modules', {'Adafruit_BBIO': Mock(), 'Adafruit_BBIO.GPIO': Mock()})
117+
@patch('platform.platform', Mock(return_value='Linux-3.8.13-bone47-armv7l-with-debian-7.4'))
119118
def test_beagleboneblack(self):
120-
bbio = Mock()
121-
with patch('platform.platform',
122-
new=Mock(return_value='Linux-3.8.13-bone47-armv7l-with-debian-7.4')):
123-
with patch.dict('sys.modules',
124-
{'Adafruit_BBIO': bbio, 'Adafruit_BBIO.GPIO': bbio.gpio}):
125-
gpio = GPIO.get_platform_gpio()
126-
self.assertIsInstance(gpio, GPIO.AdafruitBBIOAdapter)
119+
gpio = GPIO.get_platform_gpio()
120+
self.assertIsInstance(gpio, GPIO.AdafruitBBIOAdapter)
127121

122+
@patch('platform.platform', Mock(return_value='Darwin-13.2.0-x86_64-i386-64bit'))
128123
def test_otherplatform(self):
129-
with patch('platform.platform',
130-
new=Mock(return_value='Darwin-13.2.0-x86_64-i386-64bit')):
131-
self.assertRaises(RuntimeError, GPIO.get_platform_gpio)
124+
self.assertRaises(RuntimeError, GPIO.get_platform_gpio)

test/test_I2C.py

+44-9
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
from mock import Mock, patch
2626

27+
import Adafruit_GPIO.Platform as Platform
28+
2729

2830
# Enable debug logging to stdout during tests.
2931
logging.basicConfig()
@@ -70,15 +72,23 @@ def read_i2c_block_data(self, address, length):
7072

7173

7274
def create_device(address, busnum):
73-
# Mock the smbus module and inject it into the global namespace so the
74-
# Adafruit_GPIO.I2C module can be imported. Also inject a mock SMBus
75-
# instance to be returned by smbus.SMBus function calls.
76-
smbus = Mock()
77-
mockbus = MockSMBus()
78-
smbus.SMBus.return_value = mockbus
79-
with patch.dict('sys.modules', {'smbus': smbus}):
80-
import Adafruit_GPIO.I2C as I2C
81-
return (I2C.Device(address, busnum), smbus, mockbus)
75+
# Mock the smbus module and inject it into the global namespace so the
76+
# Adafruit_GPIO.I2C module can be imported. Also inject a mock SMBus
77+
# instance to be returned by smbus.SMBus function calls.
78+
smbus = Mock()
79+
mockbus = MockSMBus()
80+
smbus.SMBus.return_value = mockbus
81+
with patch.dict('sys.modules', {'smbus': smbus}):
82+
import Adafruit_GPIO.I2C as I2C
83+
return (I2C.Device(address, busnum), smbus, mockbus)
84+
85+
def safe_import_i2c():
86+
# Mock the smbus module and inject it into the global namespace so the
87+
# Adafruit_GPIO.I2C module can be imported. The imported I2C module is
88+
# returned so global functions can be called on it.
89+
with patch.dict('sys.modules', {'smbus': Mock() }):
90+
import Adafruit_GPIO.I2C as I2C
91+
return I2C
8292

8393

8494
class TestI2CDevice(unittest.TestCase):
@@ -144,3 +154,28 @@ def test_readS16(self):
144154
self.assertEqual(value, -4863)
145155

146156

157+
class TestGetDefaultBus(unittest.TestCase):
158+
@patch('Adafruit_GPIO.Platform.pi_revision', Mock(return_value=1))
159+
@patch('Adafruit_GPIO.Platform.platform_detect', Mock(return_value=Platform.RASPBERRY_PI))
160+
def test_raspberry_pi_rev1(self):
161+
I2C = safe_import_i2c()
162+
bus = I2C.get_default_bus()
163+
self.assertEqual(bus, 0)
164+
165+
@patch('Adafruit_GPIO.Platform.pi_revision', Mock(return_value=2))
166+
@patch('Adafruit_GPIO.Platform.platform_detect', Mock(return_value=Platform.RASPBERRY_PI))
167+
def test_raspberry_pi_rev2(self):
168+
I2C = safe_import_i2c()
169+
bus = I2C.get_default_bus()
170+
self.assertEqual(bus, 1)
171+
172+
@patch('Adafruit_GPIO.Platform.platform_detect', Mock(return_value=Platform.BEAGLEBONE_BLACK))
173+
def test_beaglebone_black(self):
174+
I2C = safe_import_i2c()
175+
bus = I2C.get_default_bus()
176+
self.assertEqual(bus, 1)
177+
178+
@patch('Adafruit_GPIO.Platform.platform_detect', Mock(return_value=Platform.UNKNOWN))
179+
def test_unknown(self):
180+
I2C = safe_import_i2c()
181+
self.assertRaises(RuntimeError, I2C.get_default_bus)

test/test_Platform.py

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright (c) 2014 Adafruit Industries
2+
# Author: Tony DiCola
3+
#
4+
# Permission is hereby granted, free of charge, to any person obtaining a copy
5+
# of this software and associated documentation files (the "Software"), to deal
6+
# in the Software without restriction, including without limitation the rights
7+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
# copies of the Software, and to permit persons to whom the Software is
9+
# furnished to do so, subject to the following conditions:
10+
#
11+
# The above copyright notice and this permission notice shall be included in
12+
# all copies or substantial portions of the Software.
13+
#
14+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
# THE SOFTWARE.
21+
import unittest
22+
23+
from mock import Mock, patch
24+
25+
import Adafruit_GPIO.Platform as Platform
26+
27+
28+
class TestPlatformDetect(unittest.TestCase):
29+
@patch('platform.platform', Mock(return_value='Linux-3.10.25+-armv6l-with-debian-7.4'))
30+
def test_raspberry_pi(self):
31+
result = Platform.platform_detect()
32+
self.assertEquals(result, Platform.RASPBERRY_PI)
33+
34+
@patch('platform.platform', Mock(return_value='Linux-3.8.13-bone47-armv7l-with-debian-7.4'))
35+
def test_beaglebone_black(self):
36+
result = Platform.platform_detect()
37+
self.assertEquals(result, Platform.BEAGLEBONE_BLACK)
38+
39+
@patch('platform.platform', Mock(return_value='Darwin-13.2.0-x86_64-i386-64bit'))
40+
def test_unknown(self):
41+
result = Platform.platform_detect()
42+
self.assertEquals(result, Platform.UNKNOWN)
43+
44+
45+
class TestPiRevision(unittest.TestCase):
46+
def test_revision_1(self):
47+
with patch('__builtin__.open') as mock_open:
48+
handle = mock_open.return_value.__enter__.return_value
49+
handle.__iter__.return_value = iter(['Revision : 0002'])
50+
rev = Platform.pi_revision()
51+
self.assertEquals(rev, 1)
52+
with patch('__builtin__.open') as mock_open:
53+
handle = mock_open.return_value.__enter__.return_value
54+
handle.__iter__.return_value = iter(['Revision : 0003'])
55+
rev = Platform.pi_revision()
56+
self.assertEquals(rev, 1)
57+
58+
def test_revision_2(self):
59+
with patch('__builtin__.open') as mock_open:
60+
handle = mock_open.return_value.__enter__.return_value
61+
handle.__iter__.return_value = iter(['Revision : 000e'])
62+
rev = Platform.pi_revision()
63+
self.assertEquals(rev, 2)
64+
65+
def test_unknown_revision(self):
66+
with patch('__builtin__.open') as mock_open:
67+
handle = mock_open.return_value.__enter__.return_value
68+
handle.__iter__.return_value = iter(['foobar'])
69+
self.assertRaises(RuntimeError, Platform.pi_revision)
70+

test/test_platform_detect.py

-44
This file was deleted.

0 commit comments

Comments
 (0)