diff --git a/data/airqmon.css b/data/airqmon.css
index 9d23b2cd06ab3c598f3c8aa6552f5156a30a4c37..1921c8c6e22df26cc238f02ef7f6f06aced53449 100644
--- a/data/airqmon.css
+++ b/data/airqmon.css
@@ -1,3 +1,7 @@
+body {
+  background-color:  rgba(0, 0, 0, .1);
+}
+
 h1 {
     font-weight: bolder;
     letter-spacing: 3px;
diff --git a/data/airqmon.js b/data/airqmon.js
index 336f8f104eb5de1deeaffdd520f713a1f9a379c3..9d3a889e3dc59b442ca2002db1d998bf3b7ba884 100644
--- a/data/airqmon.js
+++ b/data/airqmon.js
@@ -81,7 +81,7 @@ var chartOptions = {
     responsive: true,
     millisPerPixel: 100,
     grid: {
-        fillStyle:'rgba(255,255,255, 0.75)',
+        fillStyle:'rgba(255,255,255, 1)',
         strokeStyle:'rgba(128,128,128, 0.10)',
         verticalSections: 5
     },
@@ -124,7 +124,9 @@ function startWebsocket() {
     websock.onmessage = function(evt) {
         data = JSON.parse(evt.data);
         //console.log(data);
-        handleWebsocketMessage(data);
+        if (data !== null) {
+            handleWebsocketMessage(data);
+        }
     };
 }
 
@@ -156,7 +158,7 @@ function updateMetric(name, value, accuracy) {
         timeseries[name] = new TimeSeries();
         timeseries[name].append(new Date().getTime(), numericValue);
         var metric = $('<li class="list-group-item list-group-item-action" id="metric_'+name+'">'+
-            '<div class="row my-2 rowMetric">'+
+            '<div class="row rowMetric">'+
                 '<div class="d-flex w-100 justify-content-between">'+
                     '<div class="sensorName">'+metrics[name].name+'</div>'+
                     '<div class="sensorValue">'+value+'</div>'+
@@ -178,7 +180,7 @@ function toggleChart(name) {
         charts[name] = new SmoothieChart(chartOptions);
         charts[name].addTimeSeries(timeseries[name], lineOptions);
         $('#metric_'+name).append($('<div class="row rowChart">'+
-            '<div class="chart my-2"><canvas id="chart_'+name+'"></canvas></div>'+
+            '<div class="chart mt-2"><canvas id="chart_'+name+'"></canvas></div>'+
         '</div>'));
         charts[name].streamTo(document.getElementById("chart_"+name), 1000);
     } else {
diff --git a/data/index.html b/data/index.html
index 2b9f250d683c211a14f6b72806662c1c198d7493..8ff16e14d1a559c36dda01679db1f252563424b8 100644
--- a/data/index.html
+++ b/data/index.html
@@ -23,16 +23,15 @@
   
 <main class="container flex-column justify-content-center align-items-center">
 
-    <div class="mb-3 text-center my-4">
+    <div class="row my-3 py-3 g-0 col-12 col-lg-6 offset-lg-3 bg-white text-center shadow shadow-sm rounded">
         <h1>Air Quality Monitor</h1>
+        <div class="mt-2">
+          <canvas id="gauge"></canvas>
+      </div>
     </div>
 
-    <div class="d-flex flex-row justify-content-center mb-3">
-        <canvas id="gauge"></canvas>
-    </div>
-
-    <div class="row mx-1 mb-3">
-      <div class="list-group col-12 col-lg-6 offset-lg-3" id="metrics"></div>
+    <div class="row mb-3 g-0">
+      <div class="list-group col-12 col-lg-6 offset-lg-3 shadow shadow-sm" id="metrics"></div>
     </div>
     
     <div class="spinner-border" role="status" id="wsSpinner">
diff --git a/src/main.cpp b/src/main.cpp
index 7ccd1d0dfde271324f7a5dae8fd76aa510f255f0..669a81715293438a2b9c9acacb97f56b90c08242 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,8 +1,8 @@
 #include "config.h"
 #include <Arduino.h>
+#include <EEPROM.h>
 #include <SoftwareSerial.h>
 #include <ESP8266WiFi.h>
-#include <FS.h>
 #include <LittleFS.h>
 #include <ArduinoOTA.h>
 #include <ESP8266mDNS.h>
@@ -17,6 +17,7 @@
 
 #define PMS_TX D3
 #define PMS_RX D4
+#define STATE_SAVE_PERIOD	UINT32_C(360 * 60 * 1000) // 360 minutes - 4 times a day
 
 SoftwareSerial swSerial;
 WiFiClient wifiClient;
@@ -27,9 +28,14 @@ SerialPM pms(PMS5003, PMS_RX, PMS_TX);
 Bsec iaqSensor;
 PubSubClient mqttClient(wifiClient);
 IPAddress mqttServer;
-
 SimpleMap<String, double> *sensorData;
 
+const uint8_t bsec_config_iaq[] = {
+#include "config/generic_33v_3s_4d/bsec_iaq.txt"
+};
+uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0};
+uint16_t stateUpdateCounter = 0;
+
 void logLine(String line, bool newline = true)
 {
   Serial.print(line);
@@ -280,11 +286,72 @@ void checkIaqSensorStatus(void)
   }
 }
 
+void loadBmeState(void)
+{
+  if (EEPROM.read(0) == BSEC_MAX_STATE_BLOB_SIZE) {
+    // Existing state in EEPROM
+    Serial.println("Reading state from EEPROM");
+
+    for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++) {
+      bsecState[i] = EEPROM.read(i + 1);
+      Serial.println(bsecState[i], HEX);
+    }
+
+    iaqSensor.setState(bsecState);
+    checkIaqSensorStatus();
+  } else {
+    // Erase the EEPROM with zeroes
+    Serial.println("Erasing EEPROM");
+
+    for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE + 1; i++)
+      EEPROM.write(i, 0);
+
+    EEPROM.commit();
+  }
+}
+
+void updateBmeState(void)
+{
+  bool update = false;
+  /* Set a trigger to save the state. Here, the state is saved every STATE_SAVE_PERIOD with the first state being saved once the algorithm achieves full calibration, i.e. iaqAccuracy = 3 */
+  if (stateUpdateCounter == 0) {
+    if (iaqSensor.iaqAccuracy >= 3) {
+      update = true;
+      stateUpdateCounter++;
+    }
+  } else {
+    /* Update every STATE_SAVE_PERIOD milliseconds */
+    if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) {
+      update = true;
+      stateUpdateCounter++;
+    }
+  }
+
+  if (update) {
+    iaqSensor.getState(bsecState);
+    checkIaqSensorStatus();
+
+    Serial.println("Writing state to EEPROM");
+
+    for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE ; i++) {
+      EEPROM.write(i + 1, bsecState[i]);
+      Serial.println(bsecState[i], HEX);
+    }
+
+    EEPROM.write(0, BSEC_MAX_STATE_BLOB_SIZE);
+    EEPROM.commit();
+  }
+}
+
 void setupBme()
 {
+  EEPROM.begin(BSEC_MAX_STATE_BLOB_SIZE + 1);
   Wire.begin();
   iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, Wire);
   checkIaqSensorStatus();
+  iaqSensor.setConfig(bsec_config_iaq);
+  checkIaqSensorStatus();
+  loadBmeState();
   bsec_virtual_sensor_t sensorList[10] = {
       BSEC_OUTPUT_RAW_TEMPERATURE,
       BSEC_OUTPUT_RAW_PRESSURE,
@@ -401,6 +468,7 @@ void readBme()
     sensorData->put("eco2_acc", (int)iaqSensor.co2Accuracy);
     sensorData->put("bvoc", iaqSensor.breathVocEquivalent);
     sensorData->put("bvoc_acc", (int)iaqSensor.breathVocAccuracy);
+    updateBmeState();
   }
   else
   {