Skip to content

Commit 4fe091a

Browse files
committed
Prep for v0.0.2
1 parent e96d952 commit 4fe091a

File tree

8 files changed

+146
-131
lines changed

8 files changed

+146
-131
lines changed

Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
LIBRARY_VERSION=$(shell grep version library/setup.cfg | awk -F" = " '{print $$2}')
22
LIBRARY_NAME=$(shell grep name library/setup.cfg | awk -F" = " '{print $$2}')
3+
PACKAGE_NAME="sgp30"
34

45
.PHONY: usage install uninstall
56
usage:
@@ -25,13 +26,13 @@ uninstall:
2526

2627
check:
2728
@echo "Checking for trailing whitespace"
28-
@! grep -IUrn --color "[[:blank:]]$$" --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO
29+
@! grep -IlUrn --color "[[:blank:]]$$" --exclude-dir=.vscode --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO
2930
@echo "Checking for DOS line-endings"
30-
@! grep -IUrn --color "" --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile
31+
@! grep -IlUrn --color "" --exclude-dir=.vscode --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile
3132
@echo "Checking library/CHANGELOG.txt"
3233
@cat library/CHANGELOG.txt | grep ^${LIBRARY_VERSION}
33-
@echo "Checking library/${LIBRARY_NAME}/__init__.py"
34-
@cat library/${LIBRARY_NAME}/__init__.py | grep "^__version__ = '${LIBRARY_VERSION}'"
34+
@echo "Checking library/${PACKAGE_NAME}/__init__.py"
35+
@cat library/${PACKAGE_NAME}/__init__.py | grep "^__version__ = '${LIBRARY_VERSION}'"
3536

3637
tag:
3738
git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}"

examples/test.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
from sgp30 import SGP30
2-
import time
3-
import sys
4-
5-
sgp30 = SGP30()
6-
7-
# result = sgp30.command('set_baseline', (0xFECA, 0xBEBA))
8-
# result = sgp30.command('get_baseline')
9-
# print(["{:02x}".format(n) for n in result])
10-
11-
print("Sensor warming up, please wait...")
12-
def crude_progress_bar():
13-
sys.stdout.write('.')
14-
sys.stdout.flush()
15-
16-
sgp30.start_measurement(crude_progress_bar)
17-
sys.stdout.write('\n')
18-
19-
while True:
20-
result = sgp30.get_air_quality()
21-
print(result)
22-
time.sleep(1.0)
1+
from sgp30 import SGP30
2+
import time
3+
import sys
4+
5+
sgp30 = SGP30()
6+
7+
# result = sgp30.command('set_baseline', (0xFECA, 0xBEBA))
8+
# result = sgp30.command('get_baseline')
9+
# print(["{:02x}".format(n) for n in result])
10+
11+
print("Sensor warming up, please wait...")
12+
def crude_progress_bar():
13+
sys.stdout.write('.')
14+
sys.stdout.flush()
15+
16+
sgp30.start_measurement(crude_progress_bar)
17+
sys.stdout.write('\n')
18+
19+
while True:
20+
result = sgp30.get_air_quality()
21+
print(result)
22+
time.sleep(1.0)

library/CHANGELOG.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
0.0.2
2+
-----
3+
4+
* BugFix: avoid infinite loop during start_measurement (thanks @millerdq2038)
5+
* BugFix: corrected parameter order for set_baseline (thanks @phooey)
6+
* Improvement: close i2c file handle to avoid leak (https://github.com/pimoroni/sgp30-python/issues/5)
7+
18
0.0.1
29
-----
310

library/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ Latest/development library from GitHub:
1919

2020

2121
# Changelog
22+
0.0.2
23+
-----
24+
25+
* BugFix: avoid infinite loop during start_measurement (thanks @millerdq2038)
26+
* BugFix: corrected parameter order for set_baseline (thanks @phooey)
27+
* Improvement: close i2c file handle to avoid leak (https://github.com/pimoroni/sgp30-python/issues/5)
28+
2229
0.0.1
2330
-----
2431

library/setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
[metadata]
33
name = pimoroni-sgp30
4-
version = 0.0.1
4+
version = 0.0.2
55
author = Philip Howard
66
author_email = phil@pimoroni.com
77
description = Driver for the SGP30 Gas Sensor

library/sgp30/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import time
33

44

5-
__version__ = '0.0.1'
5+
__version__ = '0.0.2'
66

77
SGP30_I2C_ADDR = 0x58
88

library/tests/test_setup.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
from tools import MockI2CDev, MockI2CMsg
2-
3-
4-
def test_setup():
5-
from sgp30 import SGP30
6-
dev = MockI2CDev()
7-
assert dev._open is True
8-
sgp30 = SGP30(i2c_dev=dev, i2c_msg=MockI2CMsg())
9-
del sgp30
10-
assert dev._open is False
11-
12-
13-
def test_get_unique_id():
14-
from sgp30 import SGP30
15-
sgp30 = SGP30(i2c_dev=MockI2CDev(), i2c_msg=MockI2CMsg())
16-
assert sgp30.get_unique_id() == 0xffffffffffff
17-
18-
19-
def test_get_feature_set_version():
20-
from sgp30 import SGP30
21-
sgp30 = SGP30(i2c_dev=MockI2CDev(), i2c_msg=MockI2CMsg())
22-
assert sgp30.get_feature_set_version() == (0xc, 0xfe)
1+
from tools import MockI2CDev, MockI2CMsg
2+
3+
4+
def test_setup():
5+
from sgp30 import SGP30
6+
dev = MockI2CDev()
7+
assert dev._open is True
8+
sgp30 = SGP30(i2c_dev=dev, i2c_msg=MockI2CMsg())
9+
del sgp30
10+
assert dev._open is False
11+
12+
13+
def test_get_unique_id():
14+
from sgp30 import SGP30
15+
sgp30 = SGP30(i2c_dev=MockI2CDev(), i2c_msg=MockI2CMsg())
16+
assert sgp30.get_unique_id() == 0xffffffffffff
17+
18+
19+
def test_get_feature_set_version():
20+
from sgp30 import SGP30
21+
sgp30 = SGP30(i2c_dev=MockI2CDev(), i2c_msg=MockI2CMsg())
22+
assert sgp30.get_feature_set_version() == (0xc, 0xfe)

library/tests/tools.py

Lines changed: 81 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,81 @@
1-
import struct
2-
3-
4-
class MockI2CDev():
5-
def __init__(self):
6-
self._open = True
7-
self._last_write = None
8-
9-
def i2c_rdwr(self, a, b=None):
10-
if isinstance(a, MockI2CMsgW):
11-
self._last_write = a.process()
12-
if isinstance(a, MockI2CMsgR):
13-
a.process(self._last_write)
14-
if b is not None:
15-
b.process(self._last_write)
16-
17-
def close(self):
18-
self._open = False
19-
20-
21-
class MockI2CMsg():
22-
def write(self, i2c_addr, data):
23-
return MockI2CMsgW(i2c_addr, data)
24-
25-
def read(self, i2c_addr, response_len):
26-
return MockI2CMsgR(i2c_addr, response_len)
27-
28-
29-
class MockI2CMsgR():
30-
def __init__(self, i2c_addr, response_len):
31-
self._num_words = response_len // 3
32-
self.buf = None
33-
34-
def process(self, last_command):
35-
result = [0, 0, 0]
36-
if last_command[0] == 0x3682: # get_serial_id
37-
result = [0xffff, 0xffff, 0xffff]
38-
if last_command[0] == 0x202f: # get_feature_set_version
39-
result = [0xCAFE, 0x0000, 0x0000]
40-
41-
buf = []
42-
43-
for i in range(self._num_words):
44-
word = result[i]
45-
packed = bytearray(struct.pack('>H', word))
46-
buf.append(packed[0])
47-
buf.append(packed[1])
48-
buf.append(self.calculate_crc(word))
49-
50-
self.buf = bytearray(buf)
51-
52-
def calculate_crc(self, data):
53-
"""Calculate an 8-bit CRC from a 16-bit word
54-
55-
Defined in section 6.6 of the SGP30 datasheet.
56-
57-
Polynominal: 0x31 (x8 + x5 + x4 + x1)
58-
Initialization: 0xFF
59-
Reflect input/output: False
60-
Final XOR: 0x00
61-
62-
"""
63-
crc = 0xff # Initialization value
64-
# calculates 8-Bit checksum with given polynomial
65-
for byte in [(data & 0xff00) >> 8, data & 0x00ff]:
66-
crc ^= byte
67-
for _ in range(8):
68-
if crc & 0x80:
69-
crc = (crc << 1) ^ 0x31 # XOR with polynominal
70-
else:
71-
crc <<= 1
72-
return crc & 0xff
73-
74-
75-
class MockI2CMsgW():
76-
def __init__(self, i2c_addr, data):
77-
self._data = data
78-
79-
def process(self):
80-
command_len = (len(self._data) - 2) // 3
81-
return struct.unpack('>H' + ('Hx' * command_len), self._data)
1+
import struct
2+
3+
4+
class MockI2CDev():
5+
def __init__(self):
6+
self._open = True
7+
self._last_write = None
8+
9+
def i2c_rdwr(self, a, b=None):
10+
if isinstance(a, MockI2CMsgW):
11+
self._last_write = a.process()
12+
if isinstance(a, MockI2CMsgR):
13+
a.process(self._last_write)
14+
if b is not None:
15+
b.process(self._last_write)
16+
17+
def close(self):
18+
self._open = False
19+
20+
21+
class MockI2CMsg():
22+
def write(self, i2c_addr, data):
23+
return MockI2CMsgW(i2c_addr, data)
24+
25+
def read(self, i2c_addr, response_len):
26+
return MockI2CMsgR(i2c_addr, response_len)
27+
28+
29+
class MockI2CMsgR():
30+
def __init__(self, i2c_addr, response_len):
31+
self._num_words = response_len // 3
32+
self.buf = None
33+
34+
def process(self, last_command):
35+
result = [0, 0, 0]
36+
if last_command[0] == 0x3682: # get_serial_id
37+
result = [0xffff, 0xffff, 0xffff]
38+
if last_command[0] == 0x202f: # get_feature_set_version
39+
result = [0xCAFE, 0x0000, 0x0000]
40+
41+
buf = []
42+
43+
for i in range(self._num_words):
44+
word = result[i]
45+
packed = bytearray(struct.pack('>H', word))
46+
buf.append(packed[0])
47+
buf.append(packed[1])
48+
buf.append(self.calculate_crc(word))
49+
50+
self.buf = bytearray(buf)
51+
52+
def calculate_crc(self, data):
53+
"""Calculate an 8-bit CRC from a 16-bit word
54+
55+
Defined in section 6.6 of the SGP30 datasheet.
56+
57+
Polynominal: 0x31 (x8 + x5 + x4 + x1)
58+
Initialization: 0xFF
59+
Reflect input/output: False
60+
Final XOR: 0x00
61+
62+
"""
63+
crc = 0xff # Initialization value
64+
# calculates 8-Bit checksum with given polynomial
65+
for byte in [(data & 0xff00) >> 8, data & 0x00ff]:
66+
crc ^= byte
67+
for _ in range(8):
68+
if crc & 0x80:
69+
crc = (crc << 1) ^ 0x31 # XOR with polynominal
70+
else:
71+
crc <<= 1
72+
return crc & 0xff
73+
74+
75+
class MockI2CMsgW():
76+
def __init__(self, i2c_addr, data):
77+
self._data = data
78+
79+
def process(self):
80+
command_len = (len(self._data) - 2) // 3
81+
return struct.unpack('>H' + ('Hx' * command_len), self._data)

0 commit comments

Comments
 (0)