diff --git a/examples/compensated-temperature.py b/examples/compensated-temperature.py index d3901ca..071bbfb 100755 --- a/examples/compensated-temperature.py +++ b/examples/compensated-temperature.py @@ -4,10 +4,6 @@ import time import bme680 from subprocess import PIPE, Popen -try: - from smbus2 import SMBus -except ImportError: - from smbus import SMBus print("""compensated-temperature.py - Use the CPU temperature to compensate temperature readings from the BME680 sensor. Method adapted from Initial State's Enviro pHAT @@ -31,12 +27,14 @@ sensor.set_pressure_oversample(bme680.OS_4X) sensor.set_temperature_oversample(bme680.OS_8X) sensor.set_filter(bme680.FILTER_SIZE_3) + # Gets the CPU temperature in degrees C def get_cpu_temperature(): process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE) output, _error = process.communicate() return float(output[output.index('=') + 1:output.rindex("'")]) + factor = 1.0 # Smaller numbers adjust temp down, vice versa smooth_size = 10 # Dampens jitter due to rapid CPU temp changes diff --git a/examples/temperature-offset.py b/examples/temperature-offset.py index 7f298cd..c39700e 100755 --- a/examples/temperature-offset.py +++ b/examples/temperature-offset.py @@ -22,6 +22,7 @@ sensor.set_pressure_oversample(bme680.OS_4X) sensor.set_temperature_oversample(bme680.OS_8X) sensor.set_filter(bme680.FILTER_SIZE_3) + def display_data(offset=0): sensor.set_temp_offset(offset) sensor.get_sensor_data() @@ -32,6 +33,7 @@ def display_data(offset=0): print(output) print('') + print('Initial readings') display_data() diff --git a/library/setup.cfg b/library/setup.cfg index 81dc0bf..bdbc6ef 100644 --- a/library/setup.cfg +++ b/library/setup.cfg @@ -12,3 +12,4 @@ ignore = E501 F403 F405 + W504 diff --git a/library/tests/conftest.py b/library/tests/conftest.py new file mode 100644 index 0000000..bbe4939 --- /dev/null +++ b/library/tests/conftest.py @@ -0,0 +1,101 @@ +import sys +import mock +import pytest +import bme680 +from bme680.constants import CalibrationData + + +class MockSMBus: + """Mock a basic non-presence SMBus device to cause BME680 to fail. + + Returns 0 in all cases, so that CHIP_ID will never match. + + """ + + def __init__(self, bus): # noqa D107 + pass + + def read_byte_data(self, addr, register): + """Return 0 for all read attempts.""" + return 0 + + +class MockSMBusPresent: + """Mock enough of the BME680 for the library to initialise and test.""" + + def __init__(self, bus): + """Initialise with test data.""" + self.regs = [0 for _ in range(256)] + self.regs[bme680.CHIP_ID_ADDR] = bme680.CHIP_ID + + def read_byte_data(self, addr, register): + """Read a single byte from fake registers.""" + return self.regs[register] + + def write_byte_data(self, addr, register, value): + """Write a single byte to fake registers.""" + self.regs[register] = value + + def read_i2c_block_data(self, addr, register, length): + """Read up to length bytes from register.""" + return self.regs[register:register + length] + + +@pytest.fixture(scope='function', autouse=False) +def smbus_notpresent(): + """Mock smbus module.""" + smbus = mock.MagicMock() + smbus.SMBus = MockSMBus + sys.modules['smbus'] = smbus + yield smbus + del sys.modules['smbus'] + + +@pytest.fixture(scope='function', autouse=False) +def smbus(): + """Mock smbus module.""" + smbus = mock.MagicMock() + smbus.SMBus = MockSMBusPresent + sys.modules['smbus'] = smbus + yield smbus + del sys.modules['smbus'] + + +@pytest.fixture(scope='function', autouse=False) +def calibration(): + """Mock bme680 calibration.""" + calibration = CalibrationData() + # Dump of calibration data borrowed from: + # https://github.com/pimoroni/bme680-python/issues/11 + data = { + 'par_gh1': -30, + 'par_gh2': -24754, + 'par_gh3': 18, + 'par_h1': 676, + 'par_h2': 1029, + 'par_h3': 0, + 'par_h4': 45, + 'par_h5': 20, + 'par_h6': 120, + 'par_h7': -100, + 'par_p1': 36673, + 'par_p10': 30, + 'par_p2': -10515, + 'par_p3': 88, + 'par_p4': 7310, + 'par_p5': -129, + 'par_p6': 30, + 'par_p7': 46, + 'par_p8': -3177, + 'par_p9': -2379, + 'par_t1': 26041, + 'par_t2': 26469, + 'par_t3': 3, + 'range_sw_err': 0, + 'res_heat_range': 1, + 'res_heat_val': 48, + 't_fine': 136667 + } + for k, v in data.items(): + setattr(calibration, k, v) + return calibration diff --git a/library/tests/test_compensation.py b/library/tests/test_compensation.py new file mode 100644 index 0000000..89b0cd9 --- /dev/null +++ b/library/tests/test_compensation.py @@ -0,0 +1,41 @@ +import bme680 + + +def test_calc_temperature(smbus, calibration): + """Validate temperature calculation against mock calibration data.""" + sensor = bme680.BME680() + sensor.calibration_data = calibration + assert sensor._calc_temperature(501240) == 2669 + assert sensor.calibration_data.t_fine == 136667 + + +def test_calc_pressure(smbus, calibration): + """Validate pressure calculation against mock calibration data.""" + sensor = bme680.BME680() + sensor.calibration_data = calibration + sensor._calc_temperature(501240) + assert sensor._calc_pressure(353485) == 98712 + + +def test_calc_humidity(smbus, calibration): + """Validate humidity calculation against mock calibration data.""" + sensor = bme680.BME680() + sensor.calibration_data = calibration + sensor._calc_temperature(501240) + assert sensor._calc_humidity(19019) == 42402 + + +def test_calc_gas_resistance(smbus, calibration): + """Validate gas calculation against mock calibration data.""" + sensor = bme680.BME680() + sensor.calibration_data = calibration + assert int(sensor._calc_gas_resistance(0, 0)) == 12946860 + + +def test_temp_offset(smbus, calibration): + """Validate temperature calculation with offset against mock calibration data.""" + sensor = bme680.BME680() + sensor.calibration_data = calibration + sensor.set_temp_offset(1.99) + assert sensor._calc_temperature(501240) == 2669 + 199 + assert sensor.calibration_data.t_fine == 146830 diff --git a/library/tests/test_setup.py b/library/tests/test_setup.py index 95b7391..b401d91 100644 --- a/library/tests/test_setup.py +++ b/library/tests/test_setup.py @@ -1,57 +1,13 @@ -import sys -import mock import pytest import bme680 -class MockSMBus: - """Mock a basic non-presence SMBus device to cause BME680 to fail. - - Returns 0 in all cases, so that CHIP_ID will never match. - - """ - - def __init__(self, bus): # noqa D107 - pass - - def read_byte_data(self, addr, register): - """Return 0 for all read attempts.""" - return 0 - - -class MockSMBusPresent: - """Mock enough of the BME680 for the library to initialise and test.""" - - def __init__(self, bus): - """Initialise with test data.""" - self.regs = [0 for _ in range(256)] - self.regs[bme680.CHIP_ID_ADDR] = bme680.CHIP_ID - - def read_byte_data(self, addr, register): - """Read a single byte from fake registers.""" - return self.regs[register] - - def write_byte_data(self, addr, register, value): - """Write a single byte to fake registers.""" - self.regs[register] = value - - def read_i2c_block_data(self, addr, register, length): - """Read up to length bytes from register.""" - return self.regs[register:register + length] - - -def test_setup_not_present(): +def test_setup_not_present(smbus_notpresent): """Mock the adbsence of a BME680 and test initialisation.""" - sys.modules['smbus'] = mock.MagicMock() - sys.modules['smbus'].SMBus = MockSMBus - with pytest.raises(RuntimeError): sensor = bme680.BME680() # noqa F841 -def test_setup_mock_present(): +def test_setup_mock_present(smbus): """Mock the presence of a BME680 and test initialisation.""" - sys.modules['smbus'] = mock.MagicMock() - sys.modules['smbus'].SMBus = MockSMBusPresent - sensor = bme680.BME680() # noqa F841