diff --git a/sonoff/i18n.h b/sonoff/i18n.h
index a90028e8d..4469ae006 100644
--- a/sonoff/i18n.h
+++ b/sonoff/i18n.h
@@ -549,6 +549,7 @@ const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s %s{e}";
const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} =
, {m} = | , {e} = |
const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = | , {e} = |
const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = | , {e} = |
+const char HTTP_SNS_ILLUMINANCE_S[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; // {s} = , {m} = | , {e} = |
#if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798)
const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = | , {e} = |
diff --git a/sonoff/xsns_91_max44009.ino b/sonoff/xsns_91_max44009.ino
new file mode 100644
index 000000000..499a88eb0
--- /dev/null
+++ b/sonoff/xsns_91_max44009.ino
@@ -0,0 +1,166 @@
+/*
+ xsns_91_max44009.ino - MAX44009 ambient light sensor support for Sonoff-Tasmota
+
+ Copyright (C) 2019 Theo Arends
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifdef USE_I2C
+#ifdef USE_MAX44009
+/*********************************************************************************************\
+ * MAX44009 - Ambient Light Intensity
+ *
+ * I2C Address: 0x23 or 0x5C
+\*********************************************************************************************/
+
+#define XSNS_91 91
+
+#define MAX44009_ADDR1 0x4A
+#define MAX44009_ADDR2 0x4B
+#define REG_CONFIG 0x02
+#define REG_LUMINANCE 0x03
+#define MAX44009_CONTINUOUS_AUTO_MODE 0x80 // Start measurement in automatic, continous mode
+
+uint8_t max44009_address;
+uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2 };
+uint8_t max44009_type = 0;
+uint8_t max44009_valid = 0;
+float max44009_illuminance = 0;
+char max44009_types[] = "MAX44009";
+
+bool Max4409Read_lum(void)
+{
+ if (max44009_valid) { max44009_valid--; }
+
+ /* Select luminance start register */
+ Wire.beginTransmission(max44009_address);
+ Wire.write(REG_LUMINANCE);
+ Wire.endTransmission();
+
+ if (2 != Wire.requestFrom(max44009_address, (uint8_t)2)) { return false; }
+ byte msb = Wire.read();
+ byte lsb = Wire.read();
+ int exponent = (msb & 0xF0) >> 4;
+ int mantissa = ((msb & 0x0F) << 4) | (lsb & 0x0F);
+ max44009_illuminance = pow(2, exponent) * mantissa * 0.045;
+
+ max44009_valid = SENSOR_MAX_MISS;
+ return true;
+}
+
+/********************************************************************************************/
+
+void Max4409Detect(void)
+{
+ if (max44009_type) {
+ return;
+ }
+
+ for (byte i = 0; i < sizeof(max44009_addresses); i++) {
+ max44009_address = max44009_addresses[i];
+ Wire.beginTransmission(max44009_address);
+
+ /* select configuration register iand set mode */
+ Wire.write(REG_CONFIG);
+ Wire.write(MAX44009_CONTINUOUS_AUTO_MODE);
+ if (!Wire.endTransmission()) {
+ max44009_type = 1;
+ snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, max44009_types, max44009_address);
+ AddLog(LOG_LEVEL_DEBUG);
+ break;
+ }
+ }
+}
+
+void Max4409EverySecond(void)
+{
+ if (90 == (uptime %100)) {
+ // 1mS
+ Max4409Detect();
+ }
+ else {
+ // 1mS
+ if (max44009_type) {
+ if (!Max4409Read_lum()) {
+ AddLogMissed(max44009_types, max44009_valid);
+// if (!max44009_valid) { max44009_type = 0; }
+ }
+ }
+ }
+}
+
+void Max4409Show(boolean json)
+{
+ char illum_str[8];
+
+ if (max44009_valid) {
+
+ /* convert illuminance to fixed size string */
+ if (max44009_illuminance < 10) {
+ dtostrf(max44009_illuminance, sizeof(illum_str) -1, 3, illum_str);
+ } else if (max44009_illuminance < 100) {
+ dtostrf(max44009_illuminance, sizeof(illum_str) -1, 2, illum_str);
+ } else if (max44009_illuminance < 1000) {
+ dtostrf(max44009_illuminance, sizeof(illum_str) -1, 1, illum_str);
+ } else {
+ dtostrf(max44009_illuminance, sizeof(illum_str) -1, 0, illum_str);
+ }
+
+ if (json) {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), mqtt_data, max44009_types, illum_str);
+#ifdef USE_DOMOTICZ
+ if (0 == tele_period) {
+ DomoticzSensor(DZ_ILLUMINANCE, illum_str);
+ }
+#endif // USE_DOMOTICZ
+#ifdef USE_WEBSERVER
+ } else {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE_S, mqtt_data, max44009_types, illum_str);
+#endif // USE_WEBSERVER
+ }
+ }
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+boolean Xsns91(byte function)
+{
+ boolean result = false;
+
+ if (i2c_flg) {
+ switch (function) {
+ case FUNC_INIT:
+ Max4409Detect();
+ break;
+ case FUNC_EVERY_SECOND:
+ Max4409EverySecond();
+ break;
+ case FUNC_JSON_APPEND:
+ Max4409Show(1);
+ break;
+#ifdef USE_WEBSERVER
+ case FUNC_WEB_APPEND:
+ Max4409Show(0);
+ break;
+#endif // USE_WEBSERVER
+ }
+ }
+ return result;
+}
+
+#endif // USE_MAX44009
+#endif // USE_I2C