From 9cc9c188a4c031aebd1451a7ed9368622c8a1717 Mon Sep 17 00:00:00 2001 From: Pierrick C Date: Sun, 30 Jun 2019 20:57:20 +0200 Subject: [PATCH] Init commit : send data from bme280 to adafruit IO --- .gitignore | 1 + code/lib/bme280_i2c.py | 559 +++++++++++++++++++++++++++++++++++++++++ code/lib/mqtt.py | 199 +++++++++++++++ code/main.py | 61 +++++ 4 files changed, 820 insertions(+) create mode 100644 .gitignore create mode 100644 code/lib/bme280_i2c.py create mode 100644 code/lib/mqtt.py create mode 100644 code/main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4acd06b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.py diff --git a/code/lib/bme280_i2c.py b/code/lib/bme280_i2c.py new file mode 100644 index 0000000..72e0fba --- /dev/null +++ b/code/lib/bme280_i2c.py @@ -0,0 +1,559 @@ +# Author(s): Jonathan Hanson 2018 +# +# This is more or less a straight read of the Bosch data sheet at: +# https://www.bosch-sensortec.com/bst/products/all_products/bme280 +# and specifically: +# https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-12.pdf +# +# Modeled on the reference library Bosch Sensortec C library at: +# https://github.com/BoschSensortec/BME280_driver +# +# The development of this module was heavily guided by the prior work done +# by Peter Dahlberg et al at: +# https://github.com/catdog2/mpy_bme280_esp8266 + +from micropython import const +from ustruct import unpack, unpack_from +from utime import sleep_ms + + +# BME280 default address +BME280_I2C_ADDR_PRIM = const(0x76) +BME280_I2C_ADDR_SEC = const(0x77) + +# Sensor Power Mode Options +BME280_SLEEP_MODE = const(0x00) +BME280_FORCED_MODE = const(0x01) +BME280_NORMAL_MODE = const(0x03) + +# Oversampling Options +BME280_NO_OVERSAMPLING = const(0x00) +BME280_OVERSAMPLING_1X = const(0x01) +BME280_OVERSAMPLING_2X = const(0x02) +BME280_OVERSAMPLING_4X = const(0x03) +BME280_OVERSAMPLING_8X = const(0x04) +BME280_OVERSAMPLING_16X = const(0x05) + +# Standby Duration Options +BME280_STANDBY_TIME_500_US = const(0x00) # Note this is microseconds, so 0.5 ms +BME280_STANDBY_TIME_62_5_MS = const(0x01) +BME280_STANDBY_TIME_125_MS = const(0x02) +BME280_STANDBY_TIME_250_MS = const(0x03) +BME280_STANDBY_TIME_500_MS = const(0x04) +BME280_STANDBY_TIME_1000_MS = const(0x05) +BME280_STANDBY_TIME_10_MS = const(0x06) +BME280_STANDBY_TIME_20_MS = const(0x07) + +# Filter Coefficient Options +BME280_FILTER_COEFF_OFF = const(0x00) +BME280_FILTER_COEFF_2 = const(0x01) +BME280_FILTER_COEFF_4 = const(0x02) +BME280_FILTER_COEFF_8 = const(0x03) +BME280_FILTER_COEFF_16 = const(0x04) + +# BME280 Chip ID +_BME280_CHIP_ID = const(0x60) + +# Register Addresses +_BME280_CHIP_ID_ADDR = const(0xD0) +_BME280_RESET_ADDR = const(0xE0) +_BME280_TEMP_PRESS_CALIB_DATA_ADDR = const(0x88) +_BME280_HUMIDITY_CALIB_DATA_ADDR = const(0xE1) +_BME280_PWR_CTRL_ADDR = const(0xF4) +_BME280_CTRL_HUM_ADDR = const(0xF2) +_BME280_CTRL_MEAS_ADDR = const(0xF4) +_BME280_CONFIG_ADDR = const(0xF5) +_BME280_DATA_ADDR = const(0xF7) + +# Register range sizes +_BME280_TEMP_PRESS_CALIB_DATA_LEN = const(26) +_BME280_HUMIDITY_CALIB_DATA_LEN = const(7) +_BME280_P_T_H_DATA_LEN = const(8) + + +class BME280_I2C: + def __init__(self, address: int = BME280_I2C_ADDR_PRIM, i2c=None): + """ + Ensure I2C communication with the sensor is working, reset the sensor, + and load its calibration data into memory. + """ + self.address = address + + if i2c is None: + raise ValueError('A configured I2C object is required.') + self.i2c = i2c + + self._read_chip_id() + self._soft_reset() + self._load_calibration_data() + + def _read_chip_id(self): + """ + Read the chip ID from the sensor and verify it's correct. + If the value isn't correct, wait 1ms and try again. + If 5 tries don't work, raise an exception. + """ + for x in range(5): + mem = self.i2c.readfrom_mem(self.address, _BME280_CHIP_ID_ADDR, 1) + if mem[0] == _BME280_CHIP_ID: + return + sleep_ms(1) + raise Exception("Couldn't read BME280 chip ID after 5 attempts.") + + def _soft_reset(self): + """ + Write the reset command to the sensor's reset address. + Wait 2ms, per the reference library's example. + """ + self.i2c.writeto_mem(self.address, _BME280_RESET_ADDR, bytearray([0xB6])) + sleep_ms(2) + + def _load_calibration_data(self): + """ + Load the read-only calibration values out of the sensor's memory, to be + used later in calibrating the raw reads. These get stored in various + self.cal_dig_* object properties. + + See https://github.com/BoschSensortec/BME280_driver/blob/bme280_v3.3.4/bme280.c#L1192 + See https://github.com/BoschSensortec/BME280_driver/blob/bme280_v3.3.4/bme280.c#L1216 + See https://github.com/catdog2/mpy_bme280_esp8266/blob/master/bme280.py#L73 + """ + # Load the temperature and pressure calibration data + # (note that the first value of the humidity data is stuffed in here) + tp_cal_mem = self.i2c.readfrom_mem(self.address, + _BME280_TEMP_PRESS_CALIB_DATA_ADDR, + _BME280_TEMP_PRESS_CALIB_DATA_LEN) + + (self.cal_dig_T1, self.cal_dig_T2, self.cal_dig_T3, + self.cal_dig_P1, self.cal_dig_P2, self.cal_dig_P3, + self.cal_dig_P4, self.cal_dig_P5, self.cal_dig_P6, + self.cal_dig_P7, self.cal_dig_P8, self.cal_dig_P9, + _, + self.cal_dig_H1) = unpack("> 4) + + self.cal_dig_H6 = unpack_from("> 2) & 0b00000111, + "osr_t": (ctrl_meas >> 5) & 0b00000111, + "filter": (config >> 2) & 0b00000111, + "standby_time": (config >> 5) & 0b00000111, + } + + def set_measurement_settings(self, settings: dict): + """ + Set the sensor's settings for each measurement's oversampling, + the pressure IIR filter coefficient, and standby duration + during normal power mode. + + The settings dict can have keys osr_h, osr_p, osr_t, filter, and + standby_time. All values are optional, and omitting any will retain + the pre-existing value. + + See the data sheet, section 3 and 5 + """ + self._validate_settings(settings) + self._ensure_sensor_is_asleep() + self._write_measurement_settings(settings) + + def _validate_settings(self, settings: dict): + oversampling_options = [ + BME280_NO_OVERSAMPLING, BME280_OVERSAMPLING_1X, + BME280_OVERSAMPLING_2X, BME280_OVERSAMPLING_4X, + BME280_OVERSAMPLING_8X, BME280_OVERSAMPLING_16X] + + filter_options = [ + BME280_FILTER_COEFF_OFF, BME280_FILTER_COEFF_2, + BME280_FILTER_COEFF_4, BME280_FILTER_COEFF_8, + BME280_FILTER_COEFF_16] + + standby_time_options = [ + BME280_STANDBY_TIME_500_US, + BME280_STANDBY_TIME_62_5_MS, BME280_STANDBY_TIME_125_MS, + BME280_STANDBY_TIME_250_MS, BME280_STANDBY_TIME_500_MS, + BME280_STANDBY_TIME_1000_MS, BME280_STANDBY_TIME_10_MS, + BME280_STANDBY_TIME_20_MS] + + if 'osr_h' in settings: + if settings['osr_h'] not in oversampling_options: + raise ValueError("osr_h must be one of the oversampling defines") + if 'osr_p' in settings: + if settings['osr_h'] not in oversampling_options: + raise ValueError("osr_p must be one of the oversampling defines") + if 'osr_t' in settings: + if settings['osr_h'] not in oversampling_options: + raise ValueError("osr_t must be one of the oversampling defines") + if 'filter' in settings: + if settings['filter'] not in filter_options: + raise ValueError("filter filter coefficient defines") + if 'standby_time' in settings: + if settings['standby_time'] not in standby_time_options: + raise ValueError("standby_time must be one of the standby time duration defines") + + def _write_measurement_settings(self, settings: dict): + # Read in the existing configuration, to modify + mem = self.i2c.readfrom_mem(self.address, _BME280_CTRL_HUM_ADDR, 4) + ctrl_hum, _, ctrl_meas, config = unpack("> 4), + "pressure": (press_msb << 12) | (press_lsb << 4) | (press_xlsb >> 4), + "humidity": (hum_msb << 8) | (hum_lsb), + } + + ## + # Float Implementations + ## + + # def _compensate_temperature(self, adc_T: int) -> float: + # """ + # Output value of “25.0” equals 25.0 DegC. + # + # See the floating-point implementation in the reference library: + # https://github.com/BoschSensortec/BME280_driver/blob/bme280_v3.3.4/bme280.c#L884 + # """ + # temperature_min = -40 + # temperature_max = 85 + # + # var1 = (adc_T / 16384.0) - (self.cal_dig_T1 / 1024.0) + # var1 = var1 * self.cal_dig_T2 + # + # var2 = (adc_T / 131072.0) - (self.cal_dig_T1 / 8192.0) + # var2 = var2 * var2 * self.cal_dig_T3 + # + # self.cal_t_fine = int(var1 + var2) + # + # temperature = (var1 + var2) / 5120.0 + # + # if temperature < temperature_min: + # temperature = temperature_min + # elif temperature > temperature_max: + # temperature = temperature_max + # + # return temperature + + # def _compensate_pressure(self, adc_P: int) -> float: + # """ + # Output value of “96386.0” equals 96386 Pa = 963.86 hPa + # + # See the floating-point implementation in the reference library: + # https://github.com/BoschSensortec/BME280_driver/blob/bme280_v3.3.4/bme280.c#L912 + # """ + # pressure_min = 30000.0 + # pressure_max = 110000.0 + # + # var1 = (self.cal_t_fine / 2.0) - 64000.0 + # + # var2 = var1 * var1 * self.cal_dig_P6 / 32768.0 + # var2 = var2 + (var1 * self.cal_dig_P5 * 2.0) + # var2 = (var2 / 4.0) + (self.cal_dig_P4 * 65536.0) + # + # var3 = self.cal_dig_P3 * var1 * var1 / 524288.0 + # + # var1 = (var3 + self.cal_dig_P2 * var1) / 524288.0 + # var1 = (1.0 + var1 / 32768.0) * self.cal_dig_P1 + # + # # avoid exception caused by division by zero + # if var1: + # pressure = 1048576.0 - adc_P + # pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1 + # var1 = self.cal_dig_P9 * pressure * pressure / 2147483648.0 + # var2 = pressure * self.cal_dig_P8 / 32768.0 + # pressure = pressure + (var1 + var2 + self.cal_dig_P7) / 16.0 + # + # if pressure < pressure_min: + # pressure = pressure_min + # elif pressure > pressure_max: + # pressure = pressure_max + # + # else: + # # Invalid case + # pressure = pressure_min + # + # return pressure + + # def _compensate_humidity(self, adc_H: int) -> float: + # """ + # Output value between 0.0 and 100.0, where 100.0 is 100%RH + # + # See the floating-point implementation in the reference library: + # https://github.com/BoschSensortec/BME280_driver/blob/bme280_v3.3.4/bme280.c#L952 + # """ + # humidity_min = 0.0 + # humidity_max = 100.0 + # + # var1 = self.cal_t_fine - 76800.0 + # + # var2 = self.cal_dig_H4 * 64.0 + (self.cal_dig_H5 / 16384.0) * var1 + # + # var3 = adc_H - var2 + # + # var4 = self.cal_dig_H2 / 65536.0 + # + # var5 = 1.0 + (self.cal_dig_H3 / 67108864.0) * var1 + # + # var6 = 1.0 + (self.cal_dig_H6 / 67108864.0) * var1 * var5 + # var6 = var3 * var4 * (var5 * var6) + # + # humidity = var6 * (1.0 - self.cal_dig_H1 * var6 / 524288.0) + # + # if humidity > humidity_max: + # humidity = humidity_max + # elif humidity < humidity_min: + # humidity = humidity_min + # + # return humidity + + ## + # 32-Bit Integer Implementations + ## + + def _compensate_temperature(self, adc_T: int) -> float: + """ + Output value of “25.0” equals 25.0 DegC. + + See the integer implementation in the data sheet, section 4.2.3 + And the reference library: + https://github.com/BoschSensortec/BME280_driver/blob/bme280_v3.3.4/bme280.c#L987 + """ + temperature_min = -4000 + temperature_max = 8500 + + var1 = (((adc_T // 8) - (self.cal_dig_T1 * 2)) * self.cal_dig_T2) // 2048 + + var2 = (((((adc_T // 16) - self.cal_dig_T1) * ((adc_T // 16) - self.cal_dig_T1)) // 4096) * self.cal_dig_T3) // 16384 + + self.cal_t_fine = var1 + var2 + + temperature = (self.cal_t_fine * 5 + 128) // 256 + + if temperature < temperature_min: + temperature = temperature_min + elif temperature > temperature_max: + temperature = temperature_max + + return temperature / 100 + + def _compensate_pressure(self, adc_P: int) -> float: + """ + Output value of “96386.0” equals 96386 Pa = 963.86 hPa + + See the 32-bit integer implementation in the data sheet, section 4.2.3 + And the reference library: + https://github.com/BoschSensortec/BME280_driver/blob/bme280_v3.3.4/bme280.c#L1059 + + Note that there's a 64-bit version of this function in the reference + library on line 1016 that we're leaving unimplemented. + """ + pressure_min = 30000 + pressure_max = 110000 + + var1 = (self.cal_t_fine // 2) - 64000 + + var2 = (((var1 // 4) * (var1 // 4)) // 2048) * self.cal_dig_P6 + var2 = var2 + ((var1 * self.cal_dig_P5) * 2) + var2 = (var2 // 4) + (self.cal_dig_P4 * 65536) + + var3 = (self.cal_dig_P3 * (((var1 // 4) * (var1 // 4)) // 8192)) // 8 + + var4 = (self.cal_dig_P2 * var1) // 2 + + var1 = (var3 + var4) // 262144 + var1 = ((32768 + var1) * self.cal_dig_P1) // 32768 + + # avoid exception caused by division by zero + if var1: + var5 = 1048576 - adc_P + + pressure = (var5 - (var2 // 4096)) * 3125 + + if pressure < 0x80000000: + pressure = (pressure << 1) // var1 + else: + pressure = (pressure // var1) * 2 + + var1 = (self.cal_dig_P9 * (((pressure // 8) * (pressure // 8)) // 8192)) // 4096 + + var2 = (((pressure // 4)) * self.cal_dig_P8) // 8192 + + pressure = pressure + ((var1 + var2 + self.cal_dig_P7) // 16) + + if pressure < pressure_min: + pressure = pressure_min + elif pressure > pressure_max: + pressure = pressure_max + + else: + # Invalid case + pressure = pressure_min + + return pressure + + def _compensate_humidity(self, adc_H: int) -> float: + """ + Output value between 0.0 and 100.0, where 100.0 is 100%RH + + See the floating-point implementation in the reference library: + https://github.com/BoschSensortec/BME280_driver/blob/bme280_v3.3.4/bme280.c#1108 + """ + + humidity_max = 102400 + + var1 = self.cal_t_fine - 76800 + + var2 = adc_H * 16384 + + var3 = self.cal_dig_H4 * 1048576 + + var4 = self.cal_dig_H5 * var1 + + var5 = (((var2 - var3) - var4) + 16384) // 32768 + + var2 = (var1 * self.cal_dig_H6) // 1024 + + var3 = (var1 * self.cal_dig_H3) // 2048 + + var4 = ((var2 * (var3 + 32768)) // 1024) + 2097152 + + var2 = ((var4 * self.cal_dig_H2) + 8192) // 16384 + + var3 = var5 * var2 + + var4 = ((var3 // 32768) * (var3 // 32768)) // 128 + + var5 = var3 - ((var4 * self.cal_dig_H1) // 16) + if var5 < 0: + var5 = 0 + if var5 > 419430400: + var5 = 419430400 + + humidity = var5 // 4096 + + if (humidity > humidity_max): + humidity = humidity_max + + return humidity / 1024 diff --git a/code/lib/mqtt.py b/code/lib/mqtt.py new file mode 100644 index 0000000..d6e5102 --- /dev/null +++ b/code/lib/mqtt.py @@ -0,0 +1,199 @@ +# Copyright (c) 2019, Pycom Limited. +# +# This software is licensed under the GNU GPL version 3 or any +# later version, with permitted additional terms. For more information +# see the Pycom Licence v1.0 document supplied with this file, or +# available at https://www.pycom.io/opensource/licensing +# + +import usocket as socket +import ustruct as struct +from ubinascii import hexlify + +class MQTTException(Exception): + pass + +class MQTTClient: + + def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0, + ssl=False, ssl_params={}): + if port == 0: + port = 8883 if ssl else 1883 + self.client_id = client_id + self.sock = None + self.addr = socket.getaddrinfo(server, port)[0][-1] + self.ssl = ssl + self.ssl_params = ssl_params + self.pid = 0 + self.cb = None + self.user = user + self.pswd = password + self.keepalive = keepalive + self.lw_topic = None + self.lw_msg = None + self.lw_qos = 0 + self.lw_retain = False + + def _send_str(self, s): + self.sock.write(struct.pack("!H", len(s))) + self.sock.write(s) + + def _recv_len(self): + n = 0 + sh = 0 + while 1: + b = self.sock.read(1)[0] + n |= (b & 0x7f) << sh + if not b & 0x80: + return n + sh += 7 + + def set_callback(self, f): + self.cb = f + + def set_last_will(self, topic, msg, retain=False, qos=0): + assert 0 <= qos <= 2 + assert topic + self.lw_topic = topic + self.lw_msg = msg + self.lw_qos = qos + self.lw_retain = retain + + def connect(self, clean_session=True): + self.sock = socket.socket() + self.sock.connect(self.addr) + if self.ssl: + import ussl + self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) + msg = bytearray(b"\x10\0\0\x04MQTT\x04\x02\0\0") + msg[1] = 10 + 2 + len(self.client_id) + msg[9] = clean_session << 1 + if self.user is not None: + msg[1] += 2 + len(self.user) + 2 + len(self.pswd) + msg[9] |= 0xC0 + if self.keepalive: + assert self.keepalive < 65536 + msg[10] |= self.keepalive >> 8 + msg[11] |= self.keepalive & 0x00FF + if self.lw_topic: + msg[1] += 2 + len(self.lw_topic) + 2 + len(self.lw_msg) + msg[9] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3 + msg[9] |= self.lw_retain << 5 + self.sock.write(msg) + #print(hex(len(msg)), hexlify(msg, ":")) + self._send_str(self.client_id) + if self.lw_topic: + self._send_str(self.lw_topic) + self._send_str(self.lw_msg) + if self.user is not None: + self._send_str(self.user) + self._send_str(self.pswd) + resp = self.sock.read(4) + assert resp[0] == 0x20 and resp[1] == 0x02 + if resp[3] != 0: + raise MQTTException(resp[3]) + return resp[2] & 1 + + def disconnect(self): + self.sock.write(b"\xe0\0") + self.sock.close() + + def ping(self): + self.sock.write(b"\xc0\0") + + def publish(self, topic, msg, retain=False, qos=0): + pkt = bytearray(b"\x30\0\0\0") + pkt[0] |= qos << 1 | retain + sz = 2 + len(topic) + len(msg) + if qos > 0: + sz += 2 + assert sz < 2097152 + i = 1 + while sz > 0x7f: + pkt[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + pkt[i] = sz + #print(hex(len(pkt)), hexlify(pkt, ":")) + self.sock.write(pkt, i + 1) + self._send_str(topic) + if qos > 0: + self.pid += 1 + pid = self.pid + struct.pack_into("!H", pkt, 0, pid) + self.sock.write(pkt, 2) + self.sock.write(msg) + if qos == 1: + while 1: + op = self.wait_msg() + if op == 0x40: + sz = self.sock.read(1) + assert sz == b"\x02" + rcv_pid = self.sock.read(2) + rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid == rcv_pid: + return + elif qos == 2: + assert 0 + + def subscribe(self, topic, qos=0): + assert self.cb is not None, "Subscribe callback is not set" + pkt = bytearray(b"\x82\0\0\0") + self.pid += 1 + struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid) + #print(hex(len(pkt)), hexlify(pkt, ":")) + self.sock.write(pkt) + self._send_str(topic) + self.sock.write(qos.to_bytes(1, "little")) + while 1: + op = self.wait_msg() + if op == 0x90: + resp = self.sock.read(4) + #print(resp) + assert resp[1] == pkt[2] and resp[2] == pkt[3] + if resp[3] == 0x80: + raise MQTTException(resp[3]) + return + + # Wait for a single incoming MQTT message and process it. + # Subscribed messages are delivered to a callback previously + # set by .set_callback() method. Other (internal) MQTT + # messages processed internally. + def wait_msg(self): + res = self.sock.read(1) + self.sock.setblocking(True) + if res is None: + return None + if res == b"": + raise OSError(-1) + if res == b"\xd0": # PINGRESP + sz = self.sock.read(1)[0] + assert sz == 0 + return None + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len) + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz) + self.cb(topic, msg) + if op & 6 == 2: + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + self.sock.write(pkt) + elif op & 6 == 4: + assert 0 + + # Checks whether a pending message from server is available. + # If not, returns immediately with None. Otherwise, does + # the same processing as wait_msg. + def check_msg(self): + self.sock.setblocking(False) + return self.wait_msg() diff --git a/code/main.py b/code/main.py new file mode 100644 index 0000000..b72e9b5 --- /dev/null +++ b/code/main.py @@ -0,0 +1,61 @@ +"""Station météo connectée au service Adafruit IO +""" + + +import time +import machine +import network +import bme280_i2c +from mqtt import MQTTClient +import config + +# connect to WLAN +wlan = network.WLAN(network.STA_IF) +nets = wlan.scan() +for net in nets: + net_ssid = net[0].decode() + if net_ssid == config.WIFI_SSID: + print('Network found!') + wlan.connect(net_ssid, config.WIFI_PSK) + while not wlan.isconnected(): + machine.idle() # save power while waiting + print('WLAN connection succeeded!') + break +if not wlan.isconnected(): + print("WLAN not found/not connected") + +# Create a micropython I2C object with the appropriate device pins +i2c = machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4)) + +# Create a sensor object to represent the BME280 +# Note that this will error if the device can't be reached over I2C. +bme = bme280_i2c.BME280_I2C(address=bme280_i2c.BME280_I2C_ADDR_SEC, i2c=i2c) + +# Configure the sensor for the application in question. +bme.set_measurement_settings({ + 'filter': bme280_i2c.BME280_FILTER_COEFF_16, + 'standby_time': bme280_i2c.BME280_STANDBY_TIME_500_US, + 'osr_h': bme280_i2c.BME280_OVERSAMPLING_1X, + 'osr_p': bme280_i2c.BME280_OVERSAMPLING_16X, + 'osr_t': bme280_i2c.BME280_OVERSAMPLING_2X}) + +# Start the sensor automatically sensing +bme.set_power_mode(bme280_i2c.BME280_NORMAL_MODE) + + +client = MQTTClient(client_id="int_weather_station", + server="io.adafruit.com", + user=config.ADAFRUIT_IO_USERNAME, + password=config.ADAFRUIT_IO_KEY, + port=1883) +client.connect() + +while 1: + bme_data = bme.get_measurement() + print(bme_data) + client.publish("{}/feeds/weather.interior-hum".format(config.ADAFRUIT_IO_USERNAME), "{:.0f}".format(bme_data["humidity"])) + time.sleep_ms(2000) + client.publish("{}/feeds/weather.interior-press".format(config.ADAFRUIT_IO_USERNAME), "{:.2f}".format(bme_data["pressure"]/100)) + time.sleep_ms(2000) + client.publish("{}/feeds/weather.interior-temp2".format(config.ADAFRUIT_IO_USERNAME), "{:.1f}".format(bme_data["temperature"])) + time.sleep_ms(16000)