06 openHAB - KlausMu/esp32-fan-controller GitHub Wiki

OpenHAB is a vendor and technology agnostic open source automation software which runs as a center for your smart home.

Here I only describe how to integrate the ESP32 fan controller into an existing openHAB installation. If you are new to openHAB, please first read here.

Example of how the integration could look like in openHAB:

Requirements

  • working openHAB installation
  • working ESP32 fan controller with MQTT activated
  • running MQTT broker (a standalone one like Mosquitto or the internal one from openHAB)
  • working connection between openHAB and the MQTT broker. Working connection between ESP32 and the MQTT broker.
  • (optional) basic understandig of mqtt. Here is also a good guide on how to integrate Tasmota with openHAB, which is quite similar to integrating the ESP32 fan controller with openHAB
  • (optional) standalone MQTT client to observe and identify messages on the MQTT broker (e.g. MQTT Explorer, MQTT Spy, mosquitto_sub)

MQTTv2 Integration

If not done yet, you first need to install and activate

edit file runtime.cfg (or use openHAB Paper UI)

org.eclipse.smarthome.persistence:default=rrd4j

edit file addons.cfg (or use openHAB Paper UI)

binding = mqtt
persistence = rrd4j
transformation = jsonpath

configuration files

The rest of the configuration is split throughout several openHAB configuration files. Please assure that the topics correspond to the topics defined in the ESP32 (if you change them there).

.things file

Bridge mqtt:broker:mosquitto [ host="IPAddressOfYourBroker", secure=false, username="myUser", password="myPassword", clientID="myOpenHABMQTTClient" ]
{
    Thing topic esp32FanController {
    Channels:
        Type number : tempAct   "esp32FanController_tempAct"   [ stateTopic="esp32_fan_controller/stat/ACTUALTEMP", commandTopic="esp32_fan_controller/cmnd/ACTUALTEMP" ]
        Type number : pres      "esp32FanController_pres"      [ stateTopic="esp32_fan_controller/tele/STATE1",     transformationPattern="JSONPATH:$.pres" ]
        Type number : alt       "esp32FanController_alt"       [ stateTopic="esp32_fan_controller/tele/STATE1",     transformationPattern="JSONPATH:$.alt" ]
        Type number : hum       "esp32FanController_hum"       [ stateTopic="esp32_fan_controller/tele/STATE1",     transformationPattern="JSONPATH:$.hum" ]
        Type number : tempTarg  "esp32FanController_tempTarg"  [ stateTopic="esp32_fan_controller/stat/TARGETTEMP", commandTopic="esp32_fan_controller/cmnd/TARGETTEMP" ]
        Type number : rpm       "esp32FanController_rpm"       [ stateTopic="esp32_fan_controller/tele/STATE2",     transformationPattern="JSONPATH:$.rpm" ]
        Type number : pwm       "esp32FanController_pwm"       [ stateTopic="esp32_fan_controller/stat/FANPWM",     commandTopic="esp32_fan_controller/cmnd/FANPWM" ]
        Type number : wifiRSSI  "esp32FanController_wifiRSSI"  [ stateTopic="esp32_fan_controller/tele/STATE3",     transformationPattern="JSONPATH:$.wifiRSSI" ]
        Type number : wifiChan  "esp32FanController_wifiChan"  [ stateTopic="esp32_fan_controller/tele/STATE3",     transformationPattern="JSONPATH:$.wifiChan" ]
        Type string : wifiSSID  "esp32FanController_wifiSSID"  [ stateTopic="esp32_fan_controller/tele/STATE3",     transformationPattern="JSONPATH:$.wifiSSID" ]
        Type string : wifiBSSID "esp32FanController_wifiBSSID" [ stateTopic="esp32_fan_controller/tele/STATE3",     transformationPattern="JSONPATH:$.wifiBSSID" ]
    }
}

.items file

Group  gEsp32FanController
Group  gEsp32FanControllerChartTemp
Group  gEsp32FanControllerChartPWM
Number gEsp32FanControllerChartPeriod   "Period"

Number esp32_tempAct          "Temperature (actual) [%.1f °C]"   (gEsp32FanController,gEsp32FanControllerChartTemp) { channel = "mqtt:topic:mosquitto:esp32FanController:tempAct" }
Number esp32_pres             "Pressure [%.2f hPa]"              (gEsp32FanController)                              { channel = "mqtt:topic:mosquitto:esp32FanController:pres" }
Number esp32_alt              "Altitude [%.2f m]"                (gEsp32FanController)                              { channel = "mqtt:topic:mosquitto:esp32FanController:alt" }
Number esp32_hum              "Humidity [%.2f%%]"                (gEsp32FanController)                              { channel = "mqtt:topic:mosquitto:esp32FanController:hum" }
Number esp32_tempTarg         "Temperature (target) [%s °C]"     (gEsp32FanController,gEsp32FanControllerChartTemp) { channel = "mqtt:topic:mosquitto:esp32FanController:tempTarg" }

Number esp32_rpm              "Fan rpm [%d]"                     (gEsp32FanController,gEsp32FanControllerChartPWM)  { channel = "mqtt:topic:mosquitto:esp32FanController:rpm" }
Number esp32_pwm              "Fan pwm [%d]"                     (gEsp32FanController,gEsp32FanControllerChartPWM)  { channel = "mqtt:topic:mosquitto:esp32FanController:pwm" }

Number esp32_wifiRSSI         "WiFi signal strength [%d dB]"     (gEsp32FanController)                              { channel = "mqtt:topic:mosquitto:esp32FanController:wifiRSSI" }
Number esp32_wifiChan         "WiFi channel [%d]"                (gEsp32FanController)                              { channel = "mqtt:topic:mosquitto:esp32FanController:wifiChan" }
String esp32_wifiSSID         "WiFi SSID [%s]"                   (gEsp32FanController)                              { channel = "mqtt:topic:mosquitto:esp32FanController:wifiSSID" }
String esp32_wifiBSSID        "WiFi BSSID [%s]"                  (gEsp32FanController)                              { channel = "mqtt:topic:mosquitto:esp32FanController:wifiBSSID" }

String esp32_presAlt          "Pressure [%s]"                    (gEsp32FanController)
String esp32_rpmFrac          "Fan rpm [%s]"                     (gEsp32FanController)
String esp32_pwmFrac          "Fan pwm [%s]"                     (gEsp32FanController)
String esp32_wifiBSSIDclear   "Access Point [%s]"                (gEsp32FanController)

.sitemap file

Group item=gEsp32FanController            label="ESP32 fan controller" {
/*    
    // begin mode 1: pwm mode -----------------------------
    Frame label="Temperature" {
        Text item=esp32_tempAct
        Text item=esp32_presAlt
        Text item=esp32_hum
    }
    Frame label="Fan" {
        Setpoint item=esp32_pwm           step=10 minValue=0 maxValue=255
        Text item=esp32_rpmFrac
        Text item=esp32_pwmFrac
    }
    // end mode 1: pwm mode -------------------------------
*/
    // begin mode 2: temperature controller mode ----------
    Frame label="Temperature" {
        Text item=esp32_tempAct
        Setpoint item=esp32_tempTarg      step=1 minValue=10 maxValue=50
        Text item=esp32_presAlt
        Text item=esp32_hum
    }
    Frame label="Fan" {
        Text item=esp32_rpmFrac
        Text item=esp32_pwmFrac
    }
    // end mode 2: temperature controller mode ------------
    Frame label="WiFi" {
        Text item=esp32_wifiBSSIDclear
        Text item=esp32_wifiRSSI
    }
    Frame label="Statistics" {
        Switch item=gEsp32FanControllerChartPeriod label="Period" icon="line" mappings=[0="hour", 1="day", 2="week", 3="month", 4="year"]
        Chart item=gEsp32FanControllerChartTemp period=h refresh=6000 visibility=[gEsp32FanControllerChartPeriod==0, gEsp32FanControllerChartPeriod=="NULL"]
        Chart item=gEsp32FanControllerChartTemp period=D refresh=30000 visibility=[gEsp32FanControllerChartPeriod==1]
        Chart item=gEsp32FanControllerChartTemp period=W refresh=30000 visibility=[gEsp32FanControllerChartPeriod==2]
        Chart item=gEsp32FanControllerChartTemp period=M refresh=30000 visibility=[gEsp32FanControllerChartPeriod==3]
        Chart item=gEsp32FanControllerChartTemp period=Y refresh=30000 visibility=[gEsp32FanControllerChartPeriod==4]

        Chart item=gEsp32FanControllerChartPWM period=h refresh=6000 visibility=[gEsp32FanControllerChartPeriod==0, gEsp32FanControllerChartPeriod=="NULL"]
        Chart item=gEsp32FanControllerChartPWM period=D refresh=30000 visibility=[gEsp32FanControllerChartPeriod==1]
        Chart item=gEsp32FanControllerChartPWM period=W refresh=30000 visibility=[gEsp32FanControllerChartPeriod==2]
        Chart item=gEsp32FanControllerChartPWM period=M refresh=30000 visibility=[gEsp32FanControllerChartPeriod==3]
        Chart item=gEsp32FanControllerChartPWM period=Y refresh=30000 visibility=[gEsp32FanControllerChartPeriod==4]
    }
}

. rules file

rule "esp32 pressure altitude"
when
    Item esp32_pres changed or
    Item esp32_alt changed
then
    if ((esp32_pres == NULL) || (esp32_alt == NULL)) {
        esp32_presAlt.postUpdate("")
    }
    esp32_presAlt.postUpdate(String::format("%.2f hPa (%.2f m)", (esp32_pres.state as DecimalType).floatValue, (esp32_alt.state as DecimalType).floatValue))
end

rule "esp32 fan rpm"
when
    Item esp32_rpm changed
then
    if ((esp32_rpm == NULL)) {
        esp32_rpmFrac.postUpdate("")
    }
    esp32_rpmFrac.postUpdate(String::format("%d/3300 (%d%%)", (esp32_rpm.state as DecimalType).intValue, 100*(esp32_rpm.state as DecimalType).intValue/3300))
end

rule "esp32 fan pwm"
when
    Item esp32_pwm changed
then
    if ((esp32_pwm == NULL)) {
        esp32_pwmFrac.postUpdate("")
    }
    esp32_pwmFrac.postUpdate(String::format("%d/255 (%d%%)", (esp32_pwm.state as DecimalType).intValue, 100*(esp32_pwm.state as DecimalType).intValue/255))
end

rule "esp32 wifiBSSID realname"
when
    Item esp32_wifiBSSID changed or
    Item esp32_wifiChan changed
then
    if ((esp32_wifiBSSID == NULL) || (esp32_wifiChan == NULL)) {
        esp32_wifiBSSIDclear.postUpdate("")
    }
    var String labelText
    var String macAddressAP = esp32_wifiBSSID.state.toString
    var String macAddressClear = macAddressAP
    if        (macAddressAP == "MacAddressOfFirstAccessPoint, e.g. AA:BB:CC:DD:EE:FF") {
        macAddressClear = "FritzBox 2,4 GHz"
    } else if (macAddressAP == "MacAddressOfSecondAccessPoint, e.g. AA:BB:CC:DD:EE:FF") {
        macAddressClear = "Repeater 2,4 GHz"
    }

    labelText = macAddressClear
    labelText += " (Channel " + (esp32_wifiChan.state as DecimalType).intValue + ")"
    esp32_wifiBSSIDclear.postUpdate(labelText)
end

.persist file

Strategies {
    // for rrd charts, we need a cron strategy
    everyMinute : "0 * * * * ?"
    everyHour : "0 0 * * * ?"
    everyDay : "0 0 0 * * ?"
}

Items {
    esp32_tempAct               : strategy = everyMinute
    esp32_tempTarg              : strategy = everyChange, everyMinute
    esp32_hum                   : strategy = everyMinute
    esp32_rpm,esp32_pwm         : strategy = everyMinute
}
⚠️ **GitHub.com Fallback** ⚠️