In the esp-idf-lib the adps9930 driver uses a device descriptor structure instead of just i2c_dev_t. Fixed a linking issue. Added APDS9930 task. Added getLightValues function. Added wifi quality value to the MQTT payload. The payload is complete and will be published.

Mon, 03 Apr 2023 16:07:34 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 03 Apr 2023 16:07:34 +0200
changeset 12
bb72d448e282
parent 11
bdc123ae7b49
child 13
c3b29a1dcf1e

In the esp-idf-lib the adps9930 driver uses a device descriptor structure instead of just i2c_dev_t. Fixed a linking issue. Added APDS9930 task. Added getLightValues function. Added wifi quality value to the MQTT payload. The payload is complete and will be published.

esp-idf-lib/components/apds9930/apds9930.c file | annotate | diff | comparison | revisions
esp-idf-lib/components/apds9930/apds9930.h file | annotate | diff | comparison | revisions
main/CMakeLists.txt file | annotate | diff | comparison | revisions
main/config.c file | annotate | diff | comparison | revisions
main/config.h file | annotate | diff | comparison | revisions
main/iotbalkon.c file | annotate | diff | comparison | revisions
main/task_apds9930.c file | annotate | diff | comparison | revisions
main/task_apds9930.h file | annotate | diff | comparison | revisions
main/task_mqtt.c file | annotate | diff | comparison | revisions
--- a/esp-idf-lib/components/apds9930/apds9930.c	Mon Apr 03 11:08:09 2023 +0200
+++ b/esp-idf-lib/components/apds9930/apds9930.c	Mon Apr 03 16:07:34 2023 +0200
@@ -117,7 +117,7 @@
 #define CHECK_LOGE(dev, x, msg, ...) do { \
         esp_err_t __; \
         if ((__ = x) != ESP_OK) { \
-            I2C_DEV_GIVE_MUTEX(dev); \
+            I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); \
             ESP_LOGE(TAG, msg, ## __VA_ARGS__); \
             return __; \
         } \
@@ -130,45 +130,48 @@
 }
 
 
-esp_err_t apds9930_init_desc(i2c_dev_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio)
+esp_err_t apds9930_init_desc(apds9930_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio)
 {
     CHECK_ARG(dev);
-    CHECK_ARG(addr & 0x20);
+
+    if (addr != 0x39) {
+	ESP_LOGE(TAG, "Invalid I2C address");
+	return ESP_ERR_INVALID_ARG;
+    }
 
-    dev->port = port;
-    dev->addr = addr;
-    dev->cfg.sda_io_num = sda_gpio;
-    dev->cfg.scl_io_num = scl_gpio;
+    dev->i2c_dev.port = port;
+    dev->i2c_dev.addr = addr;
+    dev->i2c_dev.cfg.sda_io_num = sda_gpio;
+    dev->i2c_dev.cfg.scl_io_num = scl_gpio;
 #if HELPER_TARGET_IS_ESP32
-    dev->cfg.master.clk_speed = I2C_FREQ_HZ;
+    dev->i2c_dev.cfg.master.clk_speed = I2C_FREQ_HZ;
 #endif
 
-    return i2c_dev_create_mutex(dev);
+    return i2c_dev_create_mutex(&dev->i2c_dev);
 }
 
 
-esp_err_t apds9930_free_desc(i2c_dev_t *dev)
+esp_err_t apds9930_free_desc(apds9930_t *dev)
 {
     CHECK_ARG(dev);
 
-    return i2c_dev_delete_mutex(dev);
+    return i2c_dev_delete_mutex(&dev->i2c_dev);
 }
 
 
-esp_err_t apds9930_init(i2c_dev_t *dev)
+esp_err_t apds9930_init(apds9930_t *dev)
 {
     esp_err_t	err = ESP_OK;
-    uint8_t id;
 
     CHECK_ARG(dev);
-    I2C_DEV_TAKE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
 
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_ID, &id, 1), "Sensor not found");
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ID, &dev->id, 1), "Sensor not found");
 
-    if (id != APDS9930_ID_1 && id != APDS9930_ID_2 && id != APDS9930_ID_3) {
+    if (dev->id != APDS9930_ID_1 && dev->id != APDS9930_ID_2 && dev->id != APDS9930_ID_3) {
 	CHECK_LOGE(dev, ESP_ERR_INVALID_VERSION,
 			"Invalid chip ID: expected: 0x%x or 0x%x or 0x%x got: 0x%x",
-			APDS9930_ID_1, APDS9930_ID_2, APDS9930_ID_3, id);
+			APDS9930_ID_1, APDS9930_ID_2, APDS9930_ID_3, dev->id);
     }
 
     /* Set ENABLE register to 0 (disable all features) */
@@ -178,11 +181,11 @@
     }
 
     /* Set default values for ambient light and proximity registers */
-    CHECK_LOGE(dev, write_register8(dev, APDS9930_ATIME, APDS9930_DEFAULT_ATIME), "Default atime");
-    CHECK_LOGE(dev, write_register8(dev, APDS9930_WTIME, APDS9930_DEFAULT_WTIME), "Default wtime");
-    CHECK_LOGE(dev, write_register8(dev, APDS9930_PPULSE, APDS9930_DEFAULT_PPULSE), "Default ppulse");
-    CHECK_LOGE(dev, write_register8(dev, APDS9930_POFFSET, APDS9930_DEFAULT_POFFSET), "Default poffset");
-    CHECK_LOGE(dev, write_register8(dev, APDS9930_CONFIG, APDS9930_DEFAULT_CONFIG), "Default config");
+    CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_ATIME, APDS9930_DEFAULT_ATIME), "Default atime");
+    CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_WTIME, APDS9930_DEFAULT_WTIME), "Default wtime");
+    CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_PPULSE, APDS9930_DEFAULT_PPULSE), "Default ppulse");
+    CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_POFFSET, APDS9930_DEFAULT_POFFSET), "Default poffset");
+    CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_CONFIG, APDS9930_DEFAULT_CONFIG), "Default config");
     CHECK_LOGE(dev, apds9930_setLEDDrive(dev, APDS9930_DEFAULT_PDRIVE), "Default pdrive");
     CHECK_LOGE(dev, apds9930_setProximityGain(dev, APDS9930_DEFAULT_PGAIN), "Default pgain");
     CHECK_LOGE(dev, apds9930_setAmbientLightGain(dev, APDS9930_DEFAULT_AGAIN), "Default again");
@@ -191,9 +194,9 @@
     CHECK_LOGE(dev, apds9930_setProximityIntHighThreshold(dev, APDS9930_DEFAULT_PIHT), "Default PIHT");
     CHECK_LOGE(dev, apds9930_setLightIntLowThreshold(dev, APDS9930_DEFAULT_AILT), "Default ailt");
     CHECK_LOGE(dev, apds9930_setLightIntHighThreshold(dev, APDS9930_DEFAULT_AIHT), "Default aiht");
-    CHECK_LOGE(dev, write_register8(dev, APDS9930_PERS, APDS9930_DEFAULT_PERS), "Default pers");
+    CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_PERS, APDS9930_DEFAULT_PERS), "Default pers");
 
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
     return err;
 }
 
@@ -201,23 +204,23 @@
  * Public methods for controlling the APDS-9930
  ******************************************************************************/
 
-uint8_t apds9930_getMode(i2c_dev_t *dev)
+uint8_t apds9930_getMode(apds9930_t *dev)
 {
     uint8_t enable_value;
 
-    I2C_DEV_TAKE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
     /* Read current ENABLE register */
-    if (i2c_dev_read_reg(dev, APDS9930_ENABLE, &enable_value, 1) != ESP_OK) {
-	I2C_DEV_GIVE_MUTEX(dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE, &enable_value, 1) != ESP_OK) {
+	I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
         return APDS9930_ERROR;
     }
 
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
     return enable_value;
 }
 
 
-esp_err_t apds9930_setMode(i2c_dev_t *dev, uint8_t mode, uint8_t enable)
+esp_err_t apds9930_setMode(apds9930_t *dev, uint8_t mode, uint8_t enable)
 {
     uint8_t reg_val;
 
@@ -245,15 +248,15 @@
     }
 
     /* Write value back to ENABLE register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, write_register8(dev, APDS9930_ENABLE, reg_val), "Enable register");
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_ENABLE, reg_val), "Enable register");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-esp_err_t apds9930_enableLightSensor(i2c_dev_t *dev, bool interrupts)
+esp_err_t apds9930_enableLightSensor(apds9930_t *dev, bool interrupts)
 {
     CHECK_ARG(dev);
 
@@ -271,7 +274,7 @@
 }
 
 
-esp_err_t apds9930_disableLightSensor(i2c_dev_t *dev)
+esp_err_t apds9930_disableLightSensor(apds9930_t *dev)
 {
     CHECK_ARG(dev);
 
@@ -282,7 +285,7 @@
 }
 
 
-esp_err_t apds9930_enableProximitySensor(i2c_dev_t *dev, bool interrupts)
+esp_err_t apds9930_enableProximitySensor(apds9930_t *dev, bool interrupts)
 {
     CHECK_ARG(dev);
 
@@ -301,7 +304,7 @@
 }
 
 
-esp_err_t apds9930_disableProximitySensor(i2c_dev_t *dev)
+esp_err_t apds9930_disableProximitySensor(apds9930_t *dev)
 {
     CHECK_ARG(dev);
 
@@ -312,13 +315,13 @@
 }
 
 
-esp_err_t apds9930_enablePower(i2c_dev_t *dev)
+esp_err_t apds9930_enablePower(apds9930_t *dev)
 {
     return apds9930_setMode(dev, APDS9930_MODE_POWER, 1);
 }
 
 
-esp_err_t apds9930_disablePower(i2c_dev_t *dev)
+esp_err_t apds9930_disablePower(apds9930_t *dev)
 {
     return apds9930_setMode(dev, APDS9930_MODE_POWER, 0);
 }
@@ -328,7 +331,7 @@
  * Ambient light sensor controls
  ******************************************************************************/
 
-esp_err_t apds9930_readAmbientLightLux(i2c_dev_t *dev, float *val)
+esp_err_t apds9930_readAmbientLightLux(apds9930_t *dev, float *val)
 {
     uint16_t Ch0, Ch1;
 
@@ -341,7 +344,7 @@
 }
 
 
-esp_err_t apds9930_readulAmbientLightLux(i2c_dev_t *dev, unsigned long *val)
+esp_err_t apds9930_readulAmbientLightLux(apds9930_t *dev, unsigned long *val)
 {
     uint16_t Ch0, Ch1;
 
@@ -354,7 +357,7 @@
 }
 
 
-float apds9930_floatAmbientToLux(i2c_dev_t *dev, uint16_t Ch0, uint16_t Ch1)
+float apds9930_floatAmbientToLux(apds9930_t *dev, uint16_t Ch0, uint16_t Ch1)
 {
     uint8_t	x[4] = {1,8,16,120};
     float	iac;
@@ -372,7 +375,7 @@
 }
 
 
-unsigned long apds9930_ulongAmbientToLux(i2c_dev_t *dev, uint16_t Ch0, uint16_t Ch1)
+unsigned long apds9930_ulongAmbientToLux(apds9930_t *dev, uint16_t Ch0, uint16_t Ch1)
 {
     uint8_t	x[4] = {1,8,16,120};
     unsigned long	iac;
@@ -389,37 +392,37 @@
 }
 
 
-esp_err_t apds9930_readCh0Light(i2c_dev_t *dev, uint16_t *val)
+esp_err_t apds9930_readCh0Light(apds9930_t *dev, uint16_t *val)
 {
     uint8_t val_byte;
     *val = 0;
 
     CHECK_ARG(dev);
 
-    I2C_DEV_TAKE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
     /* Read value from channel 0 */
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_Ch0DATAL, &val_byte, 1), "Read ch0 low");
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_Ch0DATAL, &val_byte, 1), "Read ch0 low");
     *val = val_byte;
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_Ch0DATAH, &val_byte, 1), "Read ch0 high");
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_Ch0DATAH, &val_byte, 1), "Read ch0 high");
     *val += ((uint16_t)val_byte << 8);
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-esp_err_t apds9930_readCh1Light(i2c_dev_t *dev, uint16_t *val)
+esp_err_t apds9930_readCh1Light(apds9930_t *dev, uint16_t *val)
 {
     uint8_t val_byte;
     *val = 0;
 
-    I2C_DEV_TAKE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
     /* Read value from channel 1 */
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_Ch1DATAL, &val_byte, 1), "Read ch1 low");
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_Ch1DATAL, &val_byte, 1), "Read ch1 low");
     *val = val_byte;
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_Ch1DATAH, &val_byte, 1), "Read ch1 high");
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_Ch1DATAH, &val_byte, 1), "Read ch1 high");
     *val += ((uint16_t)val_byte << 8);
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
@@ -428,18 +431,18 @@
  * Proximity sensor controls
  ******************************************************************************/
 
-esp_err_t apds9930_readProximity(i2c_dev_t *dev, uint16_t *val)
+esp_err_t apds9930_readProximity(apds9930_t *dev, uint16_t *val)
 {
     *val = 0;
     uint8_t val_byte;
 
-    I2C_DEV_TAKE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
     /* Read value from proximity data register */
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_PDATAL, &val_byte, 1), "Read proximity low");
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PDATAL, &val_byte, 1), "Read proximity low");
     *val = val_byte;
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_PDATAH, &val_byte, 1), "Read proximity high");
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PDATAH, &val_byte, 1), "Read proximity high");
     *val += ((uint16_t)val_byte << 8);
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
@@ -448,91 +451,91 @@
  * Getters and setters for register values
  ******************************************************************************/
 
-uint16_t apds9930_getProximityIntLowThreshold(i2c_dev_t *dev)
+uint16_t apds9930_getProximityIntLowThreshold(apds9930_t *dev)
 {
     uint16_t val;
     uint8_t val_byte;
 
     /* Read value from PILT register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_PILTL, &val_byte, 1) != ESP_OK) {
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PILTL, &val_byte, 1) != ESP_OK) {
         val = 0;
     }
     val = val_byte;
-    if (i2c_dev_read_reg(dev, APDS9930_PILTH, &val_byte, 1) != ESP_OK) {
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PILTH, &val_byte, 1) != ESP_OK) {
         val = 0;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
     val |= ((uint16_t)val_byte << 8);
 
     return val;
 }
 
 
-esp_err_t apdsi9930_setProximityIntLowThreshold(i2c_dev_t *dev, uint16_t threshold)
+esp_err_t apds9930_setProximityIntLowThreshold(apds9930_t *dev, uint16_t threshold)
 {
     uint8_t lo;
     uint8_t hi;
     hi = threshold >> 8;
     lo = threshold & 0x00FF;
 
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_PILTL, &lo, 1), "Write PILTL");
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_PILTH, &hi, 1), "Write PILTH");
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_PILTL, &lo, 1), "Write PILTL");
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_PILTH, &hi, 1), "Write PILTH");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-uint16_t apds9930_getProximityIntHighThreshold(i2c_dev_t *dev)
+uint16_t apds9930_getProximityIntHighThreshold(apds9930_t *dev)
 {
     uint16_t val;
     uint8_t val_byte;
 
     /* Read value from PIHT register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_PIHTL, &val_byte, 1) != ESP_OK) {
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PIHTL, &val_byte, 1) != ESP_OK) {
         val = 0;
     }
     val = val_byte;
-    if (i2c_dev_read_reg(dev, APDS9930_PIHTH, &val_byte, 1) != ESP_OK) {
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PIHTH, &val_byte, 1) != ESP_OK) {
         val = 0;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
     val |= ((uint16_t)val_byte << 8);
 
     return val;
 }
 
 
-esp_err_t apds9930_setProximityIntHighThreshold(i2c_dev_t *dev, uint16_t threshold)
+esp_err_t apds9930_setProximityIntHighThreshold(apds9930_t *dev, uint16_t threshold)
 {
     uint8_t lo;
     uint8_t hi;
     hi = threshold >> 8;
     lo = threshold & 0x00FF;
 
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_PIHTL, &lo, 1), "Write PIHTL");
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_PIHTH, &hi, 1), "Write PIHTH");
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_PIHTL, &lo, 1), "Write PIHTL");
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_PIHTH, &hi, 1), "Write PIHTH");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-uint8_t apds9930_getLEDDrive(i2c_dev_t *dev)
+uint8_t apds9930_getLEDDrive(apds9930_t *dev)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
-	I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
+	I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
         return APDS9930_ERROR;;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     /* Shift and mask out LED drive bits */
     val = (val >> 6) & 0b00000011;
@@ -541,13 +544,13 @@
 }
 
 
-esp_err_t apds9930_setLEDDrive(i2c_dev_t *dev, uint8_t drive)
+esp_err_t apds9930_setLEDDrive(apds9930_t *dev, uint8_t drive)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1), "Read control");
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Read control");
 
     /* Set bits in register to given value */
     drive &= 0b00000011;
@@ -556,24 +559,24 @@
     val |= drive;
 
     /* Write register value back into CONTROL register */
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_CONTROL, &val, 1), "Write control");
-    I2C_DEV_GIVE_MUTEX(dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Write control");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-uint8_t apds9930_getProximityGain(i2c_dev_t *dev)
+uint8_t apds9930_getProximityGain(apds9930_t *dev)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
-        I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
+        I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
         return APDS9930_ERROR;;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     /* Shift and mask out PDRIVE bits */
     val = (val >> 2) & 0b00000011;
@@ -582,13 +585,13 @@
 }
 
 
-esp_err_t apds9930_setProximityGain(i2c_dev_t *dev, uint8_t drive)
+esp_err_t apds9930_setProximityGain(apds9930_t *dev, uint8_t drive)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1), "Read control");
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Read control");
 
     /* Set bits in register to given value */
     drive &= 0b00000011;
@@ -597,24 +600,24 @@
     val |= drive;
 
     /* Write register value back into CONTROL register */
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_CONTROL, &val, 1), "Write control");
-    I2C_DEV_GIVE_MUTEX(dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Write control");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-uint8_t apds9930_getProximityDiode(i2c_dev_t *dev)
+uint8_t apds9930_getProximityDiode(apds9930_t *dev)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
-        I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
+        I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
         return APDS9930_ERROR;;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     /* Shift and mask out PDRIVE bits */
     val = (val >> 4) & 0b00000011;
@@ -623,13 +626,13 @@
 }
 
 
-esp_err_t apds9930_setProximityDiode(i2c_dev_t *dev, uint8_t drive)
+esp_err_t apds9930_setProximityDiode(apds9930_t *dev, uint8_t drive)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1), "Read control");
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Read control");
 
     /* Set bits in register to given value */
     drive &= 0b00000011;
@@ -638,24 +641,24 @@
     val |= drive;
 
     /* Write register value back into CONTROL register */
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_CONTROL, &val, 1), "Write control");
-    I2C_DEV_GIVE_MUTEX(dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Write control");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-uint8_t apds9930_getAmbientLightGain(i2c_dev_t *dev)
+uint8_t apds9930_getAmbientLightGain(apds9930_t *dev)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
-        I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
+        I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
         return APDS9930_ERROR;;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     /* Shift and mask out ADRIVE bits */
     val &= 0b00000011;
@@ -664,13 +667,13 @@
 }
 
 
-esp_err_t apds9930_setAmbientLightGain(i2c_dev_t *dev, uint8_t drive)
+esp_err_t apds9930_setAmbientLightGain(apds9930_t *dev, uint8_t drive)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1), "Read control");
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Read control");
 
     /* Set bits in register to given value */
     drive &= 0b00000011;
@@ -678,24 +681,24 @@
     val |= drive;
 
     /* Write register value back into CONTROL register */
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_CONTROL, &val, 1), "Write control");
-    I2C_DEV_GIVE_MUTEX(dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Write control");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return true;
 }
 
 
-uint8_t apds9930_getAmbientGainLevel(i2c_dev_t *dev)
+uint8_t apds9930_getAmbientGainLevel(apds9930_t *dev)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
-        I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1) != ESP_OK) {
+        I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
         return APDS9930_ERROR;;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     /* Shift and mask out AGL bit */
     val = (val >> 2) & 0b00000001;
@@ -704,13 +707,13 @@
 }
 
 
-esp_err_t apds9930_setAmbientGainLevel(i2c_dev_t *dev, uint8_t enable)
+esp_err_t apds9930_setAmbientGainLevel(apds9930_t *dev, uint8_t enable)
 {
     uint8_t val;
 
     /* Read value from CONTROL register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_CONTROL, &val, 1), "Read control");
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Read control");
 
     /* Set bits in register to given value */
     enable &= 0b00000001;
@@ -719,35 +722,35 @@
     val |= enable;
 
     /* Write register value back into CONTROL register */
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_CONTROL, &val, 1), "Write control");
-    I2C_DEV_GIVE_MUTEX(dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL, &val, 1), "Write control");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-esp_err_t apds9930_getLightIntLowThreshold(i2c_dev_t *dev, uint16_t *threshold)
+esp_err_t apds9930_getLightIntLowThreshold(apds9930_t *dev, uint16_t *threshold)
 {
     uint8_t val_byte;
     *threshold = 0;
 
     /* Read value from ambient light low threshold, low byte register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_AILTL, &val_byte, 1) != ESP_OK) {
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_AILTL, &val_byte, 1) != ESP_OK) {
         *threshold = 0;
     }
     *threshold = val_byte;
-    if (i2c_dev_read_reg(dev, APDS9930_AILTH, &val_byte, 1) != ESP_OK) {
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_AILTH, &val_byte, 1) != ESP_OK) {
         *threshold = 0;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
     *threshold = *threshold + ((uint16_t)val_byte << 8);
 
     return ESP_OK;
 }
 
 
-esp_err_t apds9930_setLightIntLowThreshold(i2c_dev_t *dev, uint16_t threshold)
+esp_err_t apds9930_setLightIntLowThreshold(apds9930_t *dev, uint16_t threshold)
 {
     uint8_t val_low;
     uint8_t val_high;
@@ -756,37 +759,37 @@
     val_low = threshold & 0x00FF;
     val_high = (threshold & 0xFF00) >> 8;
 
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_AILTL, &val_low, 1), "Write AILTL");
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_AILTH, &val_high, 1), "Write AILTH");
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_AILTL, &val_low, 1), "Write AILTL");
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_AILTH, &val_high, 1), "Write AILTH");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-esp_err_t apds9930_getLightIntHighThreshold(i2c_dev_t *dev, uint16_t *threshold)
+esp_err_t apds9930_getLightIntHighThreshold(apds9930_t *dev, uint16_t *threshold)
 {
     uint8_t val_byte;
     *threshold = 0;
 
     /* Read value from ambient light high threshold, low byte register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_AIHTL, &val_byte, 1) != ESP_OK) {
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_AIHTL, &val_byte, 1) != ESP_OK) {
         *threshold = 0;
     }
     *threshold = val_byte;
-    if (i2c_dev_read_reg(dev, APDS9930_AIHTH, &val_byte, 1) != ESP_OK) {
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_AIHTH, &val_byte, 1) != ESP_OK) {
         *threshold = 0;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
     *threshold = *threshold + ((uint16_t)val_byte << 8);
 
     return ESP_OK;
 }
 
 
-esp_err_t apds9930_setLightIntHighThreshold(i2c_dev_t *dev, uint16_t threshold)
+esp_err_t apds9930_setLightIntHighThreshold(apds9930_t *dev, uint16_t threshold)
 {
     uint8_t val_low;
     uint8_t val_high;
@@ -795,26 +798,26 @@
     val_low = threshold & 0x00FF;
     val_high = (threshold & 0xFF00) >> 8;
 
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_AIHTL, &val_low, 1), "Write AIHTL");
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_AIHTH, &val_high, 1), "Write AIHTH");
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_AIHTL, &val_low, 1), "Write AIHTL");
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_AIHTH, &val_high, 1), "Write AIHTH");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-uint8_t apds9930_getAmbientLightIntEnable(i2c_dev_t *dev)
+uint8_t apds9930_getAmbientLightIntEnable(apds9930_t *dev)
 {
     uint8_t val;
 
     /* Read value from ENABLE register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_ENABLE, &val, 1) != ESP_OK) {
-        I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE, &val, 1) != ESP_OK) {
+        I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
         return APDS9930_ERROR;;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     /* Shift and mask out AIEN bit */
     val = (val >> 4) & 0b00000001;
@@ -823,13 +826,13 @@
 }
 
 
-esp_err_t apds9930_setAmbientLightIntEnable(i2c_dev_t *dev, uint8_t enable)
+esp_err_t apds9930_setAmbientLightIntEnable(apds9930_t *dev, uint8_t enable)
 {
     uint8_t val;
 
     /* Read value from ENABLE register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_ENABLE, &val, 1), "Read enable");
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE, &val, 1), "Read enable");
 
     /* Set bits in register to given value */
     enable &= 0b00000001;
@@ -838,24 +841,24 @@
     val |= enable;
 
     /* Write register value back into ENABLE register */
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_ENABLE, &val, 1), "Write enable");
-    I2C_DEV_GIVE_MUTEX(dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_ENABLE, &val, 1), "Write enable");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-uint8_t apds9930_getProximityIntEnable(i2c_dev_t *dev)
+uint8_t apds9930_getProximityIntEnable(apds9930_t *dev)
 {
     uint8_t val;
 
     /* Read value from ENABLE register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    if (i2c_dev_read_reg(dev, APDS9930_ENABLE, &val, 1) != ESP_OK) {
-        I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE, &val, 1) != ESP_OK) {
+        I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
         return APDS9930_ERROR;;
     }
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     /* Shift and mask out PIEN bit */
     val = (val >> 5) & 0b00000001;
@@ -864,13 +867,13 @@
 }
 
 
-esp_err_t apds9930_setProximityIntEnable(i2c_dev_t *dev, uint8_t enable)
+esp_err_t apds9930_setProximityIntEnable(apds9930_t *dev, uint8_t enable)
 {
     uint8_t val;
 
     /* Read value from ENABLE register */
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_read_reg(dev, APDS9930_ENABLE, &val, 1), "Read enable");
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE, &val, 1), "Read enable");
 
     /* Set bits in register to given value */
     enable &= 0b00000001;
@@ -879,21 +882,21 @@
     val |= enable;
 
     /* Write register value back into ENABLE register */
-    CHECK_LOGE(dev, i2c_dev_write_reg(dev, APDS9930_ENABLE, &val, 1), "Write enable");
-    I2C_DEV_GIVE_MUTEX(dev);
+    CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_ENABLE, &val, 1), "Write enable");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-esp_err_t apds9930_clearAmbientLightInt(i2c_dev_t *dev)
+esp_err_t apds9930_clearAmbientLightInt(apds9930_t *dev)
 {
     uint8_t	val = APDS9930_CLEAR_ALS_INT;
 
-    I2C_DEV_TAKE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
     /* This should write to the chip without register address */
-    CHECK_LOGE(dev, i2c_dev_write(dev, NULL, 0, &val, 1), "Clear ALS_INT");
-    I2C_DEV_GIVE_MUTEX(dev);
+    CHECK_LOGE(dev, i2c_dev_write(&dev->i2c_dev, NULL, 0, &val, 1), "Clear ALS_INT");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
 //    if( !wireWriteByte(CLEAR_ALS_INT) ) {
 //      return false;
@@ -903,25 +906,25 @@
 }
 
 
-esp_err_t apds9930_clearProximityInt(i2c_dev_t *dev)
+esp_err_t apds9930_clearProximityInt(apds9930_t *dev)
 {
     uint8_t	val = APDS9930_CLEAR_PROX_INT;
 
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_write(dev, NULL, 0, &val, 1), "Clear PROX_INT");
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_write(&dev->i2c_dev, NULL, 0, &val, 1), "Clear PROX_INT");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
 
 
-esp_err_t apds9930_clearAllInts(i2c_dev_t *dev)
+esp_err_t apds9930_clearAllInts(apds9930_t *dev)
 {
     uint8_t	val = APDS9930_CLEAR_ALL_INTS;
 
-    I2C_DEV_TAKE_MUTEX(dev);
-    CHECK_LOGE(dev, i2c_dev_write(dev, NULL, 0, &val, 1), "Clear ALL_INTS");
-    I2C_DEV_GIVE_MUTEX(dev);
+    I2C_DEV_TAKE_MUTEX(&dev->i2c_dev);
+    CHECK_LOGE(dev, i2c_dev_write(&dev->i2c_dev, NULL, 0, &val, 1), "Clear ALL_INTS");
+    I2C_DEV_GIVE_MUTEX(&dev->i2c_dev);
 
     return ESP_OK;
 }
--- a/esp-idf-lib/components/apds9930/apds9930.h	Mon Apr 03 11:08:09 2023 +0200
+++ b/esp-idf-lib/components/apds9930/apds9930.h	Mon Apr 03 16:07:34 2023 +0200
@@ -47,6 +47,13 @@
 #define APDS9930_AGAIN_16X		2
 #define APDS9930_AGAIN_120X		3
 
+/**
+ * Device descriptor
+ */
+typedef struct {
+    i2c_dev_t	i2c_dev;
+    uint8_t	id;
+} apds9930_t;
 
 
 /**
@@ -61,39 +68,28 @@
  * @param scl_gpio SCL GPIO
  * @return `ESP_OK` on success
  */
-esp_err_t apds9930_init_desc(i2c_dev_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio);
+esp_err_t apds9930_init_desc(apds9930_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio);
 
 /**
  * @brief Free device descriptor
  * @param dev Pointer to I2C device descriptor
  * @return `ESP_OK` on success
  */
-esp_err_t apds9930_free_desc(i2c_dev_t *dev);
-
-
-
-/* APDS9930 Class */
-//class APDS9930 {
-//public:
-
-
-    /* Initialization methods */
-//    APDS9930();
-//    ~APDS9930();
+esp_err_t apds9930_free_desc(apds9930_t *dev);
 
 /**
  * @brief Setup APDS9930 and initializes registers to defaults
  * @param dev Pointer to I2C device descriptor
  * @return `ESP_OK` on success
  */
-esp_err_t apds9930_init(i2c_dev_t *dev);
+esp_err_t apds9930_init(apds9930_t *dev);
 
 /**
  * @brief Reads and returns the contents of the ENABLE register
  * @param dev Pointer to I2C device descriptor
  * @return Contents of the ENABLE register. 0xFF if error.
  */
-uint8_t apds9930_getMode(i2c_dev_t *dev);
+uint8_t apds9930_getMode(apds9930_t *dev);
 
 /**
  * @brief Enables or disables a feature in the APDS-9930
@@ -102,21 +98,21 @@
  * @param enable ON (1) or OFF (0)
  * @return `ESP_OK` on success
  */
-esp_err_t apds9930_setMode(i2c_dev_t *dev, uint8_t mode, uint8_t enable);
+esp_err_t apds9930_setMode(apds9930_t *dev, uint8_t mode, uint8_t enable);
 
 /**
  * @brief Turn the APDS-9930 on
  * @param dev Pointer to I2C device descriptor
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_enablePower(i2c_dev_t *dev);
+esp_err_t apds9930_enablePower(apds9930_t *dev);
 
 /**
  * @brief Turn the APDS-9930 off
  * @param dev Pointer to I2C device descriptor
  * @return ESP_OK if operation successful. False otherwise.
  */
-esp_err_t apds9930_disablePower(i2c_dev_t *dev);
+esp_err_t apds9930_disablePower(apds9930_t *dev);
 
 /**
  * @brief Starts the light (Ambient/IR) sensor on the APDS-9930
@@ -124,14 +120,14 @@
  * @param interrupts true to enable hardware interrupt on high or low light
  * @return ESP_OK if sensor enabled correctly.
  */
-esp_err_t apds9930_enableLightSensor(i2c_dev_t *dev, bool interrupts);
+esp_err_t apds9930_enableLightSensor(apds9930_t *dev, bool interrupts);
 
 /**
  * @brief Ends the light sensor on the APDS-9930
  * @param dev Pointer to I2C device descriptor
  * @return ESP_OK if sensor disabled correctly.
  */
-esp_err_t apds9930_disableLightSensor(i2c_dev_t *dev);
+esp_err_t apds9930_disableLightSensor(apds9930_t *dev);
 
 /**
  * @brief Starts the proximity sensor on the APDS-9930
@@ -139,14 +135,14 @@
  * @param interrupts true to enable hardware external interrupt on proximity
  * @return ESP_OK if sensor enabled correctly.
  */
-esp_err_t apds9930_enableProximitySensor(i2c_dev_t *dev, bool interrupts);
+esp_err_t apds9930_enableProximitySensor(apds9930_t *dev, bool interrupts);
 
 /**
  * @brief Ends the proximity sensor on the APDS-9930
  * @param dev Pointer to I2C device descriptor
  * @return ESP_OK if sensor disabled correctly.
  */
-esp_err_t apds9930_disableProximitySensor(i2c_dev_t *dev);
+esp_err_t apds9930_disableProximitySensor(apds9930_t *dev);
 
 
 /**
@@ -161,7 +157,7 @@
  *
  * @return the value of the LED drive strength. 0xFF on failure.
  */
-uint8_t APDS9930_getLEDDrive(i2c_dev_t *dev);
+uint8_t APDS9930_getLEDDrive(apds9930_t *dev);
 
 /**
  * @brief Sets the LED drive strength for proximity and ALS
@@ -176,7 +172,7 @@
  * @param drive the value (0-3) for the LED drive strength
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_setLEDDrive(i2c_dev_t *dev, uint8_t drive);
+esp_err_t apds9930_setLEDDrive(apds9930_t *dev, uint8_t drive);
 
 /**
  * @brief Gets the receiver ALS gain level for the ambient light sensor.
@@ -184,7 +180,7 @@
  * @param dev Pointer to I2C device descriptor
  * @return 1 if extra ALS gain level is enabled, 0 if not. 0xFF on error.
  */
-uint8_t apds9930_getAmbientGainLevel(i2c_dev_t *dev);
+uint8_t apds9930_getAmbientGainLevel(apds9930_t *dev);
 
 /**
  * @brief Sets the receiver ALS gain level for the ambient light sensor
@@ -194,7 +190,7 @@
  * @param enable the value (0-1) for the gain level.
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_setAmbientGainLevel(i2c_dev_t *dev, uint8_t enable);
+esp_err_t apds9930_setAmbientGainLevel(apds9930_t *dev, uint8_t enable);
 
 /**
  * @brief Returns receiver gain for the ambient light sensor (ALS)
@@ -208,7 +204,7 @@
  *
  * @return the value of the ALS gain. 0xFF on failure.
  */
-uint8_t apds9930_getAmbientLightGain(i2c_dev_t *dev);
+uint8_t apds9930_getAmbientLightGain(apds9930_t *dev);
 
 /**
  * @brief Sets the receiver gain for the ambient light sensor (ALS)
@@ -223,7 +219,7 @@
  * @param drive the value (0-3) for the gain
  * @return ESP_OK if operation successful. False otherwise.
  */
-esp_err_t apds9930_setAmbientLightGain(i2c_dev_t *dev, uint8_t gain);
+esp_err_t apds9930_setAmbientLightGain(apds9930_t *dev, uint8_t gain);
 
 /**
  * @brief Returns receiver gain for proximity detection
@@ -237,7 +233,7 @@
  *
  * @return the value of the proximity gain. 0xFF on failure.
  */
-uint8_t apds9930_getProximityGain(i2c_dev_t *dev);
+uint8_t apds9930_getProximityGain(apds9930_t *dev);
 
 /**
  * @brief Sets the receiver gain for proximity detection
@@ -252,7 +248,7 @@
  * @param drive the value (0-3) for the gain
  * @return True if operation successful. False otherwise.
  */
-esp_err_t apds9930_setProximityGain(i2c_dev_t *dev, uint8_t gain);
+esp_err_t apds9930_setProximityGain(apds9930_t *dev, uint8_t gain);
 
 /**
  * @brief Selects the proximity diode
@@ -267,7 +263,7 @@
  * @param[in] drive the value (0-3) for the diode
  * @return True if operation successful. False otherwise.
  */
-esp_err_t apds9930_setProximityDiode(i2c_dev_t *dev, uint8_t drive);
+esp_err_t apds9930_setProximityDiode(apds9930_t *dev, uint8_t drive);
 
 /**
  * @brief Returns the proximity diode
@@ -281,7 +277,7 @@
  *
  * @return the selected diode. 0xFF on failure.
  */
-uint8_t apds9930_getProximityDiode(i2c_dev_t *dev);
+uint8_t apds9930_getProximityDiode(apds9930_t *dev);
 
 /**
  * @brief Gets the low threshold for ambient light interrupts
@@ -289,7 +285,7 @@
  * @param threshold current low threshold stored on the APDS-9930
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_getLightIntLowThreshold(i2c_dev_t *dev, uint16_t *threshold);
+esp_err_t apds9930_getLightIntLowThreshold(apds9930_t *dev, uint16_t *threshold);
 
 /**
  * @brief Sets the low threshold for ambient light interrupts
@@ -297,7 +293,7 @@
  * @param threshold low threshold value for interrupt to trigger
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_setLightIntLowThreshold(i2c_dev_t *dev, uint16_t threshold);
+esp_err_t apds9930_setLightIntLowThreshold(apds9930_t *dev, uint16_t threshold);
 
 /**
  * @brief Gets the high threshold for ambient light interrupts
@@ -305,7 +301,7 @@
  * @param threshold current low threshold stored on the APDS-9930
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_getLightIntHighThreshold(i2c_dev_t *dev, uint16_t *threshold);
+esp_err_t apds9930_getLightIntHighThreshold(apds9930_t *dev, uint16_t *threshold);
 
 /**
  * @brief Sets the high threshold for ambient light interrupts
@@ -313,14 +309,14 @@
  * @param threshold low threshold value for interrupt to trigger
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_setLightIntHighThreshold(i2c_dev_t *dev, uint16_t threshold);
+esp_err_t apds9930_setLightIntHighThreshold(apds9930_t *dev, uint16_t threshold);
 
 /**
  * @brief Gets if ambient light interrupts are enabled or not
  * @param dev Pointer to I2C device descriptor
  * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
  */
-uint8_t apds9930_getAmbientLightIntEnable(i2c_dev_t *dev);
+uint8_t apds9930_getAmbientLightIntEnable(apds9930_t *dev);
 
 /**
  * @brief Turns ambient light interrupts on or off
@@ -328,14 +324,14 @@
  * @param[in] enable 1 to enable interrupts, 0 to turn them off
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_setAmbientLightIntEnable(i2c_dev_t *dev, uint8_t enable);
+esp_err_t apds9930_setAmbientLightIntEnable(apds9930_t *dev, uint8_t enable);
 
 /**
  * @brief Gets if proximity interrupts are enabled or not
  * @param dev Pointer to I2C device descriptor
  * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
  */
-uint8_t apds9930_getProximityIntEnable(i2c_dev_t *dev);
+uint8_t apds9930_getProximityIntEnable(apds9930_t *dev);
 
 /**
  * @brief Turns proximity interrupts on or off
@@ -343,28 +339,28 @@
  * @param[in] enable 1 to enable interrupts, 0 to turn them off
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_setProximityIntEnable(i2c_dev_t *dev, uint8_t enable);
+esp_err_t apds9930_setProximityIntEnable(apds9930_t *dev, uint8_t enable);
 
 /**
  * @brief Clears the ambient light interrupt
  * @param dev Pointer to I2C device descriptor
  * @return ESP_OK if operation completed successfully.
  */
-esp_err_t apds9930_clearAmbientLightInt(i2c_dev_t *dev);
+esp_err_t apds9930_clearAmbientLightInt(apds9930_t *dev);
 
 /**
  * @brief Clears the proximity interrupt
  * @param dev Pointer to I2C device descriptor
  * @return ESP_OK if operation completed successfully.
  */
-esp_err_t apds9930_clearProximityInt(i2c_dev_t *dev);
+esp_err_t apds9930_clearProximityInt(apds9930_t *dev);
 
 /**
  * @brief Clears all interrupts
  * @param dev Pointer to I2C device descriptor
  * @return ESP_OK if operation completed successfully.
  */
-esp_err_t apds9930_clearAllInts(i2c_dev_t *dev);
+esp_err_t apds9930_clearAllInts(apds9930_t *dev);
 
 /**
  * @brief Reads the proximity level as an 16-bit value
@@ -372,7 +368,7 @@
  * @param val value of the proximity sensor.
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_readProximity(i2c_dev_t *dev, uint16_t *val);
+esp_err_t apds9930_readProximity(apds9930_t *dev, uint16_t *val);
 
 /**
  * @brief Reads the ambient (clear) light level as a float value
@@ -380,7 +376,7 @@
  * @param val value of the light sensor.
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_readAmbientLightLux(i2c_dev_t *dev, float *val);
+esp_err_t apds9930_readAmbientLightLux(apds9930_t *dev, float *val);
 
 /**
  * @brief Reads the ambient (clear) light level as a unsigned long value
@@ -388,11 +384,11 @@
  * @param val value of the light sensor.
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_readulAmbientLightLux(i2c_dev_t *dev, unsigned long *val);
+esp_err_t apds9930_readulAmbientLightLux(apds9930_t *dev, unsigned long *val);
 
-float apds9930_floatAmbientToLux(i2c_dev_t *dev, uint16_t Ch0, uint16_t Ch1);
+float apds9930_floatAmbientToLux(apds9930_t *dev, uint16_t Ch0, uint16_t Ch1);
 
-unsigned long apds9930_ulongAmbientToLux(i2c_dev_t *dev, uint16_t Ch0, uint16_t Ch1);
+unsigned long apds9930_ulongAmbientToLux(apds9930_t *dev, uint16_t Ch0, uint16_t Ch1);
 
 /**
  * @brief Read the channel 0 light value from the APDS-9930
@@ -400,7 +396,7 @@
  * @param val The value read.
  * @return ESP_OK if read is correctly.
  */
-esp_err_t apds9930_readCh0Light(i2c_dev_t *dev, uint16_t *val);
+esp_err_t apds9930_readCh0Light(apds9930_t *dev, uint16_t *val);
 
 /**
  * @brief Read the channel 1 light value from the APDS-9930
@@ -408,14 +404,14 @@
  * @param val The value read.
  * @return ESP_OK if read is correctly.
  */
-esp_err_t apds9930_readCh1Light(i2c_dev_t *dev, uint16_t *val);
+esp_err_t apds9930_readCh1Light(apds9930_t *dev, uint16_t *val);
 
 /**
  * @brief Returns the lower threshold for proximity detection
  * @param dev Pointer to I2C device descriptor
  * @return lower threshold
  */
-uint16_t apds9930_getProximityIntLowThreshold(i2c_dev_t *dev);
+uint16_t apds9930_getProximityIntLowThreshold(apds9930_t *dev);
 
 /**
  * @brief Sets the lower threshold for proximity detection
@@ -423,14 +419,14 @@
  * @param threshold the lower proximity threshold
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_setProximityIntLowThreshold(i2c_dev_t *dev, uint16_t threshold);
+esp_err_t apds9930_setProximityIntLowThreshold(apds9930_t *dev, uint16_t threshold);
 
 /**
  * @brief Returns the high threshold for proximity detection
  * @param dev Pointer to I2C device descriptor
  * @return high threshold
  */
-uint16_t apds9930_getProximityIntHighThreshold(i2c_dev_t *dev);
+uint16_t apds9930_getProximityIntHighThreshold(apds9930_t *dev);
 
 /**
  * @brief Sets the high threshold for proximity detection
@@ -438,7 +434,7 @@
  * @param threshold the high proximity threshold
  * @return ESP_OK if operation successful.
  */
-esp_err_t apds9930_setProximityIntHighThreshold(i2c_dev_t *dev, uint16_t threshold);
+esp_err_t apds9930_setProximityIntHighThreshold(apds9930_t *dev, uint16_t threshold);
 
 
 #ifdef __cplusplus
--- a/main/CMakeLists.txt	Mon Apr 03 11:08:09 2023 +0200
+++ b/main/CMakeLists.txt	Mon Apr 03 16:07:34 2023 +0200
@@ -1,2 +1,2 @@
-idf_component_register(SRCS config.c iotbalkon.c task_bmp280.c task_ina219.c task_wifi.c task_mqtt.c task_out.c xutil.c
+idf_component_register(SRCS config.c iotbalkon.c task_bmp280.c task_ina219.c task_apds9930.c task_wifi.c task_mqtt.c task_out.c xutil.c
                     INCLUDE_DIRS ".")
--- a/main/config.c	Mon Apr 03 11:08:09 2023 +0200
+++ b/main/config.c	Mon Apr 03 16:07:34 2023 +0200
@@ -10,3 +10,5 @@
 ina219_t		ina219_b_dev;
 ina219_t		ina219_s_dev;
 
+apds9930_t		apds9930_dev;
+
--- a/main/config.h	Mon Apr 03 11:08:09 2023 +0200
+++ b/main/config.h	Mon Apr 03 16:07:34 2023 +0200
@@ -44,13 +44,14 @@
 #include <i2cdev.h>
 #include <bmp280.h>
 #include <ina219.h>
-//#include <apds9930.h>
+#include <apds9930.h>
 
 /*
  * Application sources
  */
 #include "task_bmp280.h"
 #include "task_ina219.h"
+#include "task_apds9930.h"
 #include "task_wifi.h"
 #include "task_mqtt.h"
 #include "task_out.h"
--- a/main/iotbalkon.c	Mon Apr 03 11:08:09 2023 +0200
+++ b/main/iotbalkon.c	Mon Apr 03 16:07:34 2023 +0200
@@ -19,6 +19,7 @@
 
 static TaskHandle_t			xTaskBMP280 = NULL;
 static TaskHandle_t			xTaskINA219 = NULL;
+static TaskHandle_t			xTaskAPDS9930 = NULL;
 static TaskHandle_t			xTaskMQTT = NULL;
 static TaskHandle_t			xTaskWifi = NULL;
 static TaskHandle_t			xTaskOUT = NULL;
@@ -55,6 +56,9 @@
 extern ina219_t				ina219_b_dev;
 extern ina219_t				ina219_s_dev;
 extern INA219_State			*ina219_state;
+extern SemaphoreHandle_t		xSemaphoreAPDS9930;
+extern apds9930_t			apds9930_dev;
+extern APDS9930_State			*apds9930_state;
 extern SemaphoreHandle_t		xSemaphoreWiFi;
 extern WIFI_State			*wifi_state;			///< WiFi state
 
@@ -272,6 +276,16 @@
 
 
 
+void getLightValues() {
+
+    request_apds9930();
+
+    while (! ready_apds9930()) {
+        vTaskDelay(10 / portTICK_PERIOD_MS);
+    }
+}
+
+
 void app_main(void)
 {
     uint64_t	totalTime, gTimeInMillis;
@@ -345,6 +359,7 @@
     memset(&bmp280_dev, 0, sizeof(bmp280_t));
     memset(&ina219_b_dev, 0, sizeof(ina219_t));
     memset(&ina219_s_dev, 0, sizeof(ina219_t));
+    memset(&apds9930_dev, 0, sizeof(i2c_dev_t));
 
     i2c_dev_t dev = { 0 };
     dev.cfg.sda_io_num = CONFIG_I2C_MASTER_SDA;
@@ -354,6 +369,9 @@
     dev.addr = 0x39;
     if (i2c_dev_probe(&dev, I2C_DEV_WRITE) == 0) {
         ESP_LOGI(TAG, "Found ADPS-9930");
+	ESP_ERROR_CHECK(apds9930_init_desc(&apds9930_dev, 0x39, 0, CONFIG_I2C_MASTER_SDA, CONFIG_I2C_MASTER_SCL));
+	ESP_ERROR_CHECK(apds9930_init(&apds9930_dev));
+	ESP_LOGI(TAG, "Found APDS-9930 id: 0x%02x", apds9930_dev.id);
     }
     dev.addr = 0x40;
     if (i2c_dev_probe(&dev, I2C_DEV_WRITE) == 0) {
@@ -386,15 +404,17 @@
      */
     xSemaphoreBMP280 = xSemaphoreCreateMutex();
     xSemaphoreINA219 = xSemaphoreCreateMutex();
+    xSemaphoreAPDS9930 = xSemaphoreCreateMutex();
 
 
-    xTaskCreate(&task_bmp280,  "task_bmp280",      2560, NULL, 8, &xTaskBMP280);
-    xTaskCreate(&task_ina219,  "task_ina219",      2560, NULL, 8, &xTaskINA219);
-    xTaskCreate(&task_out,     "task_out",         2560, NULL, 9, &xTaskOUT);
+    xTaskCreate(&task_bmp280,   "task_bmp280",      2560, NULL, 8, &xTaskBMP280);
+    xTaskCreate(&task_ina219,   "task_ina219",      2560, NULL, 8, &xTaskINA219);
+    xTaskCreate(&task_apds9930, "task_apds9930",    2560, NULL, 8, &xTaskAPDS9930);
+    xTaskCreate(&task_out,      "task_out",         2560, NULL, 9, &xTaskOUT);
     // esp_log_level_set("MQTT_CLIENT", ESP_LOG_ERROR);
-    xTaskCreate(&task_mqtt,    "task_mqtt",        4096, NULL, 5, &xTaskMQTT);
+    xTaskCreate(&task_mqtt,     "task_mqtt",        4096, NULL, 5, &xTaskMQTT);
     // esp_log_level_set("wifi", ESP_LOG_ERROR);
-    xTaskCreate(&task_wifi,    "task_wifi",        4096, NULL, 3, &xTaskWifi);
+    xTaskCreate(&task_wifi,     "task_wifi",        4096, NULL, 3, &xTaskWifi);
 
     vTaskDelay(10 / portTICK_PERIOD_MS);
 
@@ -414,7 +434,7 @@
 
 	switch (State) {
 	    case State_Init:		getTempBaro();
-					// getLightValues();
+					getLightValues();
 					getVoltsCurrent();
 					State = State_Connect;
 					DisCounter = 0;
@@ -587,7 +607,7 @@
 					gTimeNext = millis() + ST_INTERVAL;
 					if (loopno >= ST_LOOPS) {
 					    ESP_LOGI(TAG, "Enough loops, do connect");
-        				//    getLightValues();
+        				    getLightValues();
 					    State = State_Connect;
 					    DisCounter = 0;
 					    request_WiFi(true);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/task_apds9930.c	Mon Apr 03 16:07:34 2023 +0200
@@ -0,0 +1,186 @@
+/**
+ * @file task_apds9930.c
+ * @brief The FreeRTOS task to query the APDS9930 sensor.
+ */
+
+
+#include "config.h"
+
+
+static const char		*TAG = "task_apds9930";
+
+SemaphoreHandle_t		xSemaphoreAPDS9930 = NULL;	///< Semaphore APDS9930 task
+EventGroupHandle_t		xEventGroupAPDS9930;		///< Events APDS9930 task
+APDS9930_State			*apds9930_state;		///< Public state for other tasks
+
+float				ambient_light;
+uint16_t			ch0 = 0;
+uint16_t			ch1 = 1;
+uint16_t			ALS_maxcount;			///< Maximum ADC value
+uint16_t			ALS_mincount;			///< Threshold to increase gain
+
+
+extern apds9930_t		apds9930_dev;
+
+const int TASK_APDS9930_REQUEST_DONE = BIT0;			///< All requests are done.
+const int TASK_APDS9930_REQUEST_LIGHT = BIT1;			///< Request Ambient Light
+
+
+
+void request_apds9930(void)
+{
+    xEventGroupClearBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_DONE);
+    xEventGroupSetBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT);
+}
+
+
+
+bool ready_apds9930(void)
+{
+    if (xEventGroupGetBits(xEventGroupAPDS9930) & TASK_APDS9930_REQUEST_DONE)
+	return true;
+    return false;
+}
+
+
+
+/*
+ * Task to read APDS9930 sensor on request.
+ */
+void task_apds9930(void *pvParameter)
+{
+    int		tries;
+    esp_err_t	err = ESP_OK;
+    uint8_t	l_gain = 0, l_aglbit = 0;
+
+    ESP_LOGI(TAG, "Starting task APDS9930 sda=%d scl=%d", CONFIG_I2C_MASTER_SDA, CONFIG_I2C_MASTER_SCL);
+    apds9930_state = malloc(sizeof(APDS9930_State));
+
+    apds9930_state->valid = false;
+    apds9930_state->fake = (apds9930_dev.i2c_dev.addr == 0) ? true:false;
+    apds9930_state->address = apds9930_dev.i2c_dev.addr;
+    apds9930_state->error = APDS9930_ERR_NONE;
+
+    /* event handler and event group for this task */
+    xEventGroupAPDS9930 = xEventGroupCreate();
+    EventBits_t uxBits;
+
+    /*
+     * Task loop forever.
+     */
+    ESP_LOGI(TAG, "Starting loop APDS9930 sensor 0x%02x %d", apds9930_state->address, apds9930_state->fake);
+    while (1) {
+
+	uxBits = xEventGroupWaitBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT, pdFALSE, pdFALSE, portMAX_DELAY );
+
+	if (uxBits & TASK_APDS9930_REQUEST_LIGHT) {
+
+	    if (! apds9930_state->fake) {
+		/* Real sensor is present */
+		apds9930_enablePower(&apds9930_dev);
+		apds9930_enableLightSensor(&apds9930_dev, false);
+		apds9930_disableProximitySensor(&apds9930_dev);
+		if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) {
+		    l_gain = apds9930_state->gain;
+		    l_aglbit = apds9930_state->aglbit;
+		    xSemaphoreGive(xSemaphoreAPDS9930);
+		}
+		if (l_gain > 3)
+		    l_gain = 0;
+		apds9930_setAmbientLightGain(&apds9930_dev, l_gain);
+		apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit);
+		vTaskDelay(200 / portTICK_PERIOD_MS);
+		tries = 6;
+		err = ESP_OK;
+
+		while (tries) {
+		    err = apds9930_readAmbientLightLux(&apds9930_dev, &ambient_light);
+		    if (err == ESP_OK) {
+			err = apds9930_readCh0Light(&apds9930_dev, &ch0);
+			if (err == ESP_OK) {
+			    err = apds9930_readCh1Light(&apds9930_dev, &ch1);
+			}
+		    }
+		    if (err != ESP_OK) {
+			ESP_LOGE(TAG, "read APDS-9930 values error '%s'", esp_err_to_name(err));
+			break;
+		    }
+
+		    /*
+		     * Check ranges
+		     */
+		    if (((ch0 == ALS_maxcount) || (ch1 == ALS_maxcount)) && ((l_gain > 0) || (l_aglbit == 0))) {
+			/* Looks like an internal overflow */
+			if (l_gain > 0) {
+			    l_gain--;
+			} else {
+			    l_aglbit = 1;
+			}
+			apds9930_setAmbientLightGain(&apds9930_dev, l_gain);
+			apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit);
+			vTaskDelay(200 / portTICK_PERIOD_MS);
+			ESP_LOGI(TAG, "Gain decreased to %d  AGL: %d", l_gain, l_aglbit);
+		    } else if ((ch0 < ALS_mincount) && (ch1 < ALS_mincount) && (l_gain < 3)) {
+			/* Looks like low resolution of the ADC. */
+			if ((l_gain == 0) && l_aglbit) {
+			    l_aglbit = 0;
+			} else {
+			    l_gain++;
+			}
+			apds9930_setAmbientLightGain(&apds9930_dev, l_gain);
+                        apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit);
+                        vTaskDelay(200 / portTICK_PERIOD_MS);
+                        ESP_LOGI(TAG, "Gain increased to %d  AGL: %d", l_gain, l_aglbit);
+		    } else {
+			if ((ch0 == ALS_maxcount) || (ch1 == ALS_maxcount)) {
+			    ambient_light = -1;
+			} else if (l_aglbit) {
+			    ambient_light = ambient_light / 0.1666;
+			}
+			ESP_LOGI(TAG, "Ambient: %.3f  Ch0: %d  Ch1: %d  Gain: %d  AGL: %d", ambient_light, ch0, ch1, l_gain, l_aglbit);
+			break;
+		    }
+		    tries--;
+		}
+		if (tries == 0) {
+		    ESP_LOGW(TAG, "tries = 0");
+		}
+		apds9930_disableLightSensor(&apds9930_dev);
+		apds9930_disablePower(&apds9930_dev);
+
+		if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) {
+		    if (err == ESP_OK) {
+			apds9930_state->error = APDS9930_ERR_NONE;
+			apds9930_state->valid = true;
+			apds9930_state->ambient_light = ambient_light;
+			apds9930_state->gain = l_gain;
+			apds9930_state->aglbit = l_aglbit;
+		    } else {
+			apds9930_state->error = APDS9930_ERR_READ;
+			apds9930_state->valid = false;
+			apds9930_state->ambient_light = 12.34;
+			apds9930_state->gain = 2;
+			apds9930_state->aglbit = 0;
+		    }
+		    xSemaphoreGive(xSemaphoreAPDS9930);
+		}
+	    } else {
+		/* Use fake values */
+		if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) {
+		    apds9930_state->error = APDS9930_ERR_NONE;
+                    apds9930_state->valid = true;
+		    apds9930_state->ambient_light = 12.34;
+		    apds9930_state->gain = 2;
+		    apds9930_state->aglbit = 0;
+		    xSemaphoreGive(xSemaphoreAPDS9930);
+		}
+	    }
+
+	    xEventGroupClearBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT);
+	    xEventGroupSetBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_DONE);
+#if 1
+	    ESP_LOGI(TAG, "  Light: %.2f, gain: %d, error: %d", apds9930_state->ambient_light, apds9930_state->gain, apds9930_state->error);
+#endif
+	}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/task_apds9930.h	Mon Apr 03 16:07:34 2023 +0200
@@ -0,0 +1,55 @@
+/**
+ * @file task_apds9930.h
+ * @brief The FreeRTOS task to query the APDS9930 sensor connected to
+ *        the I2C bus.
+ *        The task will update the sensor state structures.
+ */
+
+#ifndef	_TASK_APDS9930_H
+#define	_TASK_APDS9930_H
+
+/*
+ * Error codes in this task
+ */
+#define	APDS9930_ERR_NONE			0	///< No errors
+#define APDS9930_ERR_READ			1
+
+
+
+/**
+ * @brief Structure containing the variables for the APDS9930 task.
+ */
+typedef struct {
+    bool		valid;			///< Valid measurement
+    bool		fake;			///< Fake measurement
+    uint8_t		address;		///< Device i2c address
+    float		ambient_light;		///< Kind of Lux.
+    uint8_t		gain;			///< APDS9930 last gain setting
+    uint8_t		aglbit;			///< APDS9930 ALS Gain Level bit
+    int			error;			///< Error result
+} APDS9930_State;
+
+
+
+/**
+ * @brief Request a new measurement from the APDS9930.
+ */
+void request_apds9930(void);
+
+
+/**
+ * @brief Check if results are ready
+ * @return true of results are ready, else false.
+ */
+bool ready_apds9930(void);
+
+
+/**
+ * @brief The FreeRTOS task to update the APDS9930 on request.
+ * @param pvParameters Parameters for the task.
+ */
+void task_apds9930(void *pvParameters);
+
+
+#endif
+
--- a/main/task_mqtt.c	Mon Apr 03 11:08:09 2023 +0200
+++ b/main/task_mqtt.c	Mon Apr 03 16:07:34 2023 +0200
@@ -26,12 +26,14 @@
 extern SemaphoreHandle_t        xSemaphoreBMP280;	///< BMP280 lock semaphore
 extern INA219_State		*ina219_state;		///< INA219 state
 extern SemaphoreHandle_t	xSemaphoreINA219;	///< INA219 lock semaphore
+extern APDS9930_State		*apds9930_state;	///< APDS9930 state
+extern SemaphoreHandle_t	xSemaphoreAPDS9930;	///< APDS9930 lock semaphore
 extern WIFI_State		*wifi_state;		///< WiFi state
 extern SemaphoreHandle_t	xSemaphoreWiFi;		///< WiFi lock semaphore
 extern const esp_app_desc_t	*app_desc;
 
 extern uint32_t			Alarm;
-extern float			batteryState;
+extern int			batteryState;
 extern float			batteryVolts;
 extern float			batteryCurrent;
 extern float			batteryPower;
@@ -133,11 +135,11 @@
 {
     char        		*topic = NULL, *payload = NULL, buf[64];
     const esp_app_desc_t	*app_desc = esp_app_get_description();
+    int				Quality = 0;
 
-    // {"system":{"battery":70,"alarm":0,"version":"0.2.6","rssi":-56,"wifi":88,"light":{"lux":12.34,"gain":2}},"solar":{"voltage":13.98,"current":234.1,"power":3.272718},"battery":{"voltage":13.21,"current":4.942289,"power":0.065288},"real":{"current":229.1577},"TH":{"temperature":20.2,"humidity":48.3},"output":{"relay1":0,"relay2":0,"dimmer3":0,"dimmer4":0}}
     // {"system":{"battery":40,"alarm":0,"version":"0.3.1","rssi":-77,"wifi":46,"light":{"lux":0.1,"gain":3,"agl":0}},"solar":{"voltage":0.31,"current":0,"power":0},"battery":{"voltage":12.27,"current":53.5,"power":0.657},"real":{"current":-53.5},"TH":{"temperature":8.88,"humidity":0},"output":{"relay1":0,"relay2":0,"dimmer3":90,"dimmer4":80}}
     payload = xstrcpy((char *)"{\"system\":{\"battery\":");
-    sprintf(buf, "%.0f", batteryState);
+    sprintf(buf, "%d", batteryState);
     payload = xstrcat(payload, buf);
     payload = xstrcat(payload, (char *)",\"alarm\":");
     sprintf(buf, "%ld", Alarm);
@@ -148,12 +150,30 @@
     if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) {
 	sprintf(buf, "%d", wifi_state->STA_rssi);
 	payload = xstrcat(payload, buf);
+	payload = xstrcat(payload, (char *)",\"wifi\":");
+	if (wifi_state->STA_rssi <= -100) {
+	    Quality = 0;
+	} else if (wifi_state->STA_rssi >= -50) {
+	    Quality = 100;
+	} else {
+	    Quality = 2 * (wifi_state->STA_rssi + 100);
+	}
+	sprintf(buf, "%d", Quality);
+	payload = xstrcat(payload, buf);
 	xSemaphoreGive(xSemaphoreWiFi);
     }
     payload = xstrcat(payload, (char *)",\"light\":{\"lux\":");
-
-    payload = xstrcat(payload, (char *)",\"gain\":");
-
+    if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) {
+	sprintf(buf, "%.1f", apds9930_state->ambient_light);
+	payload = xstrcat(payload, buf);
+	payload = xstrcat(payload, (char *)",\"gain\":");
+	sprintf(buf, "%d", apds9930_state->gain);
+	payload = xstrcat(payload, buf);
+	payload = xstrcat(payload, (char *)",\"agl\":");
+	sprintf(buf, "%d", apds9930_state->aglbit);
+	payload = xstrcat(payload, buf);
+	xSemaphoreGive(xSemaphoreAPDS9930);
+    }
     payload = xstrcat(payload, (char *)"}},\"solar\":{\"voltage\":");
     sprintf(buf, "%.2f", solarVolts);
     payload = xstrcat(payload, buf);
@@ -200,7 +220,7 @@
     topic = topic_base();
     topic = xstrcat(topic, (char *)"status");
     ESP_LOGI(TAG, "%s %s", topic, payload);
-//    publisher(topic, payload);
+    publisher(topic, payload);
     free(topic);
     topic = NULL;
     free(payload);

mercurial