diff --git a/epicardium/ble/ble_main.c b/epicardium/ble/ble_main.c
index 36f832ba6a68e430a2646146b515d782b7fc01be..431b4310a59cd2b811d1ec39670d8a08023423f4 100644
--- a/epicardium/ble/ble_main.c
+++ b/epicardium/ble/ble_main.c
@@ -440,18 +440,23 @@ static void bleProcCccState(bleMsg_t *pMsg)
   APP_TRACE_INFO3("ccc state ind value:%d handle:%d idx:%d", pMsg->ccc.value, pMsg->ccc.handle, pMsg->ccc.idx);
 
   /* handle battery level CCC */
-  if (pMsg->ccc.idx == BLE_BATT_LVL_CCC_IDX)
-  {
-    if (pMsg->ccc.value == ATT_CLIENT_CFG_NOTIFY)
-    {
-      BasMeasBattStart((dmConnId_t) pMsg->ccc.hdr.param, BLE_BATT_TIMER_IND, BLE_BATT_LVL_CCC_IDX);
-    }
-    else
-    {
-      BasMeasBattStop((dmConnId_t) pMsg->ccc.hdr.param);
-    }
-    return;
-  }
+  switch(pMsg->ccc.idx) {
+    case BLE_BATT_LVL_CCC_IDX:
+      if (pMsg->ccc.value == ATT_CLIENT_CFG_NOTIFY)
+      {
+        BasMeasBattStart((dmConnId_t) pMsg->ccc.hdr.param, BLE_BATT_TIMER_IND, BLE_BATT_LVL_CCC_IDX);
+      }
+      else
+      {
+        BasMeasBattStop((dmConnId_t) pMsg->ccc.hdr.param);
+      }
+    break;
+    case BLE_ESS_TEMP_CCC_IDX:
+    case BLE_ESS_HUMI_CCC_IDX:
+    case BLE_ESS_PRES_CCC_IDX:
+      bleESS_ccc_update();
+    break;
+  };
 }
 
 /*************************************************************************************************/
@@ -467,6 +472,7 @@ static void bleClose(bleMsg_t *pMsg)
 {
   /* stop battery measurement */
   BasMeasBattStop((dmConnId_t) pMsg->hdr.param);
+  bleESS_ccc_update();
   GapClearDeviceName();
 }
 
@@ -764,6 +770,7 @@ static void bleProcMsg(bleMsg_t *pMsg)
                connOpen->peerAddr[3], connOpen->peerAddr[2],
                connOpen->peerAddr[1], connOpen->peerAddr[0]);
       BasProcMsg(&pMsg->hdr);
+      bleESS_ccc_update();
       break;
 
     case DM_CONN_CLOSE_IND:
diff --git a/epicardium/ble/ess.c b/epicardium/ble/ess.c
index 9a8c8153d50a662d8637db3ed6f477b19c6867a6..a4452e9d5d2a3685515f8bbaba9ad877f0978e64 100644
--- a/epicardium/ble/ess.c
+++ b/epicardium/ble/ess.c
@@ -8,6 +8,11 @@
 #include "app_api.h"
 
 #include "epicardium.h"
+#include "modules/log.h"
+#include "modules/modules.h"
+
+#include "FreeRTOS.h"
+#include "timers.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -173,6 +178,43 @@ WSF_CT_ASSERT(
 	((sizeof(ESSSvcAttrList) / sizeof(ESSSvcAttrList[0])) ==
 	 ESS_END_HDL - ESS_START_HDL + 1));
 
+static TimerHandle_t poll_timer;
+static StaticTimer_t poll_timer_buffer;
+static void bleESS_update(struct bme680_sensor_data *data);
+
+static void workpoll(void *data)
+{
+	struct bme680_sensor_data sensor_data;
+	if (epic_bme680_read_sensors(&sensor_data) == 0) {
+		bleESS_update(&sensor_data);
+	}
+}
+
+static void poll(TimerHandle_t xTimer)
+{
+	workqueue_schedule(workpoll, NULL);
+}
+
+static void periodic(int period)
+{
+	if (poll_timer == NULL) {
+		poll_timer = xTimerCreateStatic(
+			"bme680_poll",
+			1,
+			pdTRUE,
+			NULL,
+			poll,
+			&poll_timer_buffer
+		);
+	}
+
+	if (period < 1) {
+		xTimerStop(poll_timer, 0);
+	} else {
+		xTimerChangePeriod(poll_timer, pdMS_TO_TICKS(period), 0);
+	}
+}
+
 static void
 sendNotification(dmConnId_t connId, uint16_t handle, uint16_t cccidx)
 {
@@ -274,14 +316,9 @@ static attsGroup_t svcESSGroup = {
 	.endHandle   = ESS_END_HDL,
 };
 
-void bleESS_update(void)
+static void bleESS_update(struct bme680_sensor_data *data)
 {
-	struct bme680_sensor_data data;
-	int ret = epic_bme680_read_sensors(&data);
-	if (ret != 0) {
-		return;
-	}
-	setAttrFromBME680(&data);
+	setAttrFromBME680(data);
 
 	/* Send notifications (if enabled) for all characteristics. */
 	dmConnId_t connId = AppConnIsOpen();
@@ -297,3 +334,22 @@ void bleESS_init(void)
 {
 	AttsAddGroup(&svcESSGroup);
 }
+
+/*
+ * Instruct the ESS service to check if any characterstics have
+ * notifications enabled and enable/disable periodic measurements.
+ */
+void bleESS_ccc_update(void)
+{
+	dmConnId_t connId = AppConnIsOpen();
+	if (connId != DM_CONN_ID_NONE &&
+	    (AttsCccEnabled(connId, BLE_ESS_TEMP_CCC_IDX) ||
+	     AttsCccEnabled(connId, BLE_ESS_HUMI_CCC_IDX) ||
+	     AttsCccEnabled(connId, BLE_ESS_PRES_CCC_IDX))) {
+		LOG_INFO("ess", "enable periodic measurement");
+		periodic(3000);
+	} else {
+		LOG_INFO("ess", "disable periodic measurement");
+		periodic(0);
+	}
+}
diff --git a/epicardium/ble/ess.h b/epicardium/ble/ess.h
index 2e0d993aac0858cc56bf317574cb49ca7d9d927c..3f59edf8841eed21d6d57845c2a9d94f485e409d 100644
--- a/epicardium/ble/ess.h
+++ b/epicardium/ble/ess.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "epicardium.h"
+
 /*!< \brief Service start handle. */
 #define ESS_START_HDL 0x1000
 /*!< \brief Service end handle. */
@@ -26,5 +28,4 @@ enum {
 	ESS_MAX_HDL
 };
 
-
-void bleESS_update();
+void bleESS_ccc_update(void);
diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h
index ccc8d0650497133bb193fc162fb112c6f364e82e..687d8db7c5b9408d4ba874cce8acdc3626edc510 100644
--- a/epicardium/modules/modules.h
+++ b/epicardium/modules/modules.h
@@ -120,6 +120,9 @@ void disp_forcelock();
 #define BHI160_MUTEX_WAIT_MS          50
 void vBhi160Task(void *pvParameters);
 
+/* ---------- BME680 ------------------------------------------------------- */
+void bme680_periodic(int period);
+
 /* ---------- MAX86150 ----------------------------------------------------- */
 #define MAX86150_MUTEX_WAIT_MS		50
 void vMAX86150Task(void *pvParameters);