Parsing sensors from Tasmota to InfluxDB

Tasmota is more popular than Espurna, ESPHome, and Homie. However, it doesn't update InfluxDB. I hoped to find ready code or method... Seems I searched bad.

var GAS_WORST_VALID = 50; // kOhm. Empirical... maybe wrong
var GAS_BEST_VALID = 250; // kOhm. Empirical... maybe wrong
var HUM_BASE = 40;  // %rH, considered as optimal indoor
var HUM_WEIGHT = 25; // % of total value. The rest is from GAS.
var obj = {};
/* Set station name here */
obj.station = "bw_mod1";

keys = Object.keys(msg.payload);

// Return first match key by RegEx. If no mach found, return "" 
function getKey(expression) {
    var regex = new RegExp(expression, 'gi');
    for (var i in keys) if (regex.test(keys[i])) return keys[i];
    return "";
} 

/* Normally, air quality sensor requires calibration. Using Tasmota makes this very hard.
Not to be implemented: https://github.com/arendst/Sonoff-Tasmota/issues/5024
Implemented by the book in Homie-based project: https://github.com/igrowing/esp8266_smart_home_ready/blob/master/modules/room%20sensor%20v2/src/room_sensor.ino
This is coarse workaround, based on some expirience. 

Step 1: Calculate proportional value from resistance
(kohm - worst)*100/(best-worst)
Step 2: Put the result on logarithmic scale: low kohm values make significant change on the result
50*log10(step1)*(100-HUM_WEIGHT)/100 
Step 3: Calculate quality of humidity: how far is it from the optimal base, farer -> worse, 
lesser addition to the result
HUM_WEIGHT-ABS(HUM_WEIGHT*(rh%-base)/base/1.5)
Step 4: Compose air quality
step2 - step3
Step 5: filter improper results:
if step4 < 0 don't report quality. If step4 > 100 limit to 100.
*/
var air_k = getKey("BME680")
if (air_k) {
    var air = (msg.payload[air_k].Gas - GAS_WORST_VALID) * 100 / (GAS_BEST_VALID - GAS_WORST_VALID);
    if (air > 0) {
        air = 50*Math.log10(air) * (100-HUM_WEIGHT) / 100 ;
        var hum = HUM_WEIGHT - Math.abs(HUM_WEIGHT * (msg.payload[air_k].Humidity - HUM_BASE)) / HUM_BASE / 1.5;
        obj.quality = Number((Math.min(air + hum, 100)).toFixed(1)); 
    }
}

var env_k = getKey("BME|HTU2|SHT3");
if (env_k) {
    obj.temperature = msg.payload[env_k].Temperature;
    obj.humidity = msg.payload[env_k].Humidity;
}

var bmp = getKey("BM.[0-9]+");
if (bmp) obj.pressure = msg.payload[bmp].Pressure;

var lx_k = getKey("TSL2561|MAX44|BH1750");
if (lx_k) obj.lux = msg.payload[lx_k].Illuminance;

msg.payload = obj;
node.status({text: JSON.stringify(obj)});
msg.topic = "";
return msg;

This function receives a msg object from Tasmota via MQTT, and parses known sensors into InfluxDB acceptable format: {station:"stationname",param:"value",...param:"value"}

Pretty easy to expand the function with additional sensors.
The calculation of air quality isn't precise. Ideas how to improve it without building the entire factory are welcome.

1 Like