Skip to content

Commit 6c86234

Browse files
IRMQTTServer: SHT-3x Temperature Sensor Support (#1951)
Adds support for connecting a SHT-3x temperature sensor such as this. Will report as part of the climate entity in Home Assistant if using HA discovery, and optionally also create temperature and humidity sensors in HA as well. Adding the temperature to the climate entity makes the HA integration with Apple HomeKit much nicer as well. It's all disabled by default. Co-authored-by: Sillyfrog <[email protected]> Co-authored-by: David Conran <[email protected]>
1 parent e7824c4 commit 6c86234

File tree

3 files changed

+135
-2
lines changed

3 files changed

+135
-2
lines changed

examples/IRMQTTServer/IRMQTTServer.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries.
132132
#define MQTT_CLIMATE "ac" // Sub-topic for the climate topics.
133133
#define MQTT_CLIMATE_CMND "cmnd" // Sub-topic for the climate command topics.
134134
#define MQTT_CLIMATE_STAT "stat" // Sub-topic for the climate stat topics.
135+
// Sub-topic for the temperature/humidity sensor stat topics.
136+
#define MQTT_SENSOR_STAT "sensor"
135137
// Enable sending/receiving climate via JSON. `true` cost ~5k of program space.
136138
#define MQTT_CLIMATE_JSON false
137139

@@ -221,6 +223,25 @@ const uint16_t kMinUnknownSize = 2 * 10;
221223
// actual a/c unit.
222224
#define REPLAY_DECODED_AC_MESSAGE false
223225

226+
// ------------------------ SHT-3x Support -------------------------------------
227+
// To enable SHT-3x sensor support (such as the Lolin SHT30 Shield), connected
228+
// to GPIOs 4 and 5 (D2 and D1), do the following:
229+
// - uncomment the line in platformio.ini to enable the SHT-3x library
230+
// - uncomment the following #define line
231+
// #define SHT3X_SUPPORT true
232+
233+
// Default address for SHT-3x sensor.
234+
#define SHT3X_I2C_ADDRESS 0x44
235+
// Requires MQTT_DISCOVERY_ENABLE to be true as well.
236+
// If set, will send HA MQTT Discovery messages for the SHT-3x sensor.
237+
#define SHT3X_MQTT_DISCOVERY_ENABLE true
238+
// I2C SDA pin for SHT-3x sensor (D2).
239+
#define SHT3X_I2C_SDA 4
240+
// I2C SCL pin for SHT-3x sensor (D1).
241+
#define SHT3X_I2C_SCL 5
242+
// Check frequency for SHT-3x sensor (in seconds).
243+
#define SHT3X_CHECK_FREQ 60
244+
224245
// ------------------------ Advanced Usage Only --------------------------------
225246

226247
// Reports the input voltage to the ESP chip. **NOT** the input voltage
@@ -238,6 +259,7 @@ const uint16_t kMinUnknownSize = 2 * 10;
238259
#define KEY_POWER "power"
239260
#define KEY_MODE "mode"
240261
#define KEY_TEMP "temp"
262+
#define KEY_HUMIDITY "humidity"
241263
#define KEY_FANSPEED "fanspeed"
242264
#define KEY_SWINGV "swingv"
243265
#define KEY_SWINGH "swingh"
@@ -299,7 +321,7 @@ const uint16_t kJsonAcStateMaxSize = 1024; // Bytes
299321
// ----------------- End of User Configuration Section -------------------------
300322

301323
// Constants
302-
#define _MY_VERSION_ "v1.8.1"
324+
#define _MY_VERSION_ "v1.8.2"
303325

304326
const uint8_t kRebootTime = 15; // Seconds
305327
const uint8_t kQuickDisplayTime = 2; // Seconds
@@ -465,6 +487,9 @@ bool parseStringAndSendPronto(IRsend *irsend, const String str,
465487
#if SEND_RAW
466488
bool parseStringAndSendRaw(IRsend *irsend, const String str);
467489
#endif // SEND_RAW
490+
#if SHT3X_SUPPORT
491+
void sendMQTTDiscoverySensor(const char *topic, String type);
492+
#endif // SH3X_SUPPORT
468493
void handleIr(void);
469494
void handleNotFound(void);
470495
void setup_wifi(void);

examples/IRMQTTServer/IRMQTTServer.ino

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,10 @@ using irutils::msToString;
419419
ADC_MODE(ADC_VCC);
420420
#endif // REPORT_VCC
421421

422+
#ifdef SHT3X_SUPPORT
423+
#include <WEMOS_SHT3X.h>
424+
#endif
425+
422426
// Globals
423427
uint8_t _sanity = 0;
424428
#if defined(ESP8266)
@@ -495,9 +499,15 @@ String MqttClimateCmnd; // Sub-topic for the climate command topics.
495499
#if MQTT_DISCOVERY_ENABLE
496500
String MqttDiscovery;
497501
String MqttUniqueId;
502+
#if SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
503+
String MqttDiscoverySensor;
504+
#endif // SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
498505
#endif // MQTT_DISCOVERY_ENABLE
499506
String MqttHAName;
500507
String MqttClientId;
508+
#if SHT3X_SUPPORT
509+
String MqttSensorStat;
510+
#endif // SHT3X_SUPPORT
501511

502512
// Primative lock file for gating MQTT state broadcasts.
503513
bool lockMqttBroadcast = true;
@@ -537,6 +547,11 @@ bool isSerialGpioUsedByIr(void) {
537547
return false; // Not in use as far as we can tell.
538548
}
539549

550+
#if SHT3X_SUPPORT
551+
SHT3X TemperatureSensor(SHT3X_I2C_ADDRESS);
552+
TimerMs statSensorReadTime = TimerMs();
553+
#endif // SHT3X_SUPPORT
554+
540555
// Debug messages get sent to the serial port.
541556
#pragma GCC diagnostic push
542557
#pragma GCC diagnostic ignored "-Wunused-parameter"
@@ -1290,7 +1305,13 @@ void handleAdmin(void) {
12901305
#if MQTT_DISCOVERY_ENABLE
12911306
html += htmlButton(
12921307
kUrlSendDiscovery, F("Send MQTT Discovery"),
1293-
F("Send a Climate MQTT discovery message to Home Assistant.<br><br>"));
1308+
#if SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
1309+
F("Send a Climate and Sensor MQTT"
1310+
#else
1311+
F("Send a Climate MQTT"
1312+
#endif // SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
1313+
" discovery message to Home Assistant.<br><br>"));
1314+
12941315
#endif // MQTT_DISCOVERY_ENABLE
12951316
#if MQTT_CLEAR_ENABLE
12961317
html += htmlButton(
@@ -1492,6 +1513,10 @@ bool clearMqttSavedStates(const String topic_base) {
14921513
#if MQTT_DISCOVERY_ENABLE
14931514
// Clear the HA climate discovery message.
14941515
success &= mqtt_client.publish(MqttDiscovery.c_str(), "", true);
1516+
#if SHT3X_SUPPORT && MQTT_DISCOVERY_ENABLE
1517+
// Clear the HA sensor discovery message.
1518+
success &= mqtt_client.publish(MqttDiscoverySensor.c_str(), "", true);
1519+
#endif // SHT3X_SUPPORT && MQTT_DISCOVERY_ENABLE
14951520
#endif // MQTT_DISCOVERY_ENABLE
14961521
for (size_t channel = 0;
14971522
channel <= kNrOfIrTxGpios;
@@ -2207,12 +2232,19 @@ void init_vars(void) {
22072232
// Sub-topic for the climate stat topics.
22082233
#if MQTT_DISCOVERY_ENABLE
22092234
MqttDiscovery = "homeassistant/climate/" + String(Hostname);
2235+
#if SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
2236+
MqttDiscoverySensor = "homeassistant/sensor/" + String(Hostname);
2237+
#endif // SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
22102238
MqttUniqueId = WiFi.macAddress();
22112239
MqttUniqueId.replace(":", "");
22122240
#endif // MQTT_DISCOVERY_ENABLE
22132241
MqttHAName = String(Hostname) + "_aircon";
22142242
// Create a unique MQTT client id.
22152243
MqttClientId = String(Hostname) + String(kChipId, HEX);
2244+
#if SHT3X_SUPPORT
2245+
// Sub-topic for the climate stat topics.
2246+
MqttSensorStat = String(MqttPrefix) + '/' + MQTT_SENSOR_STAT + '/';
2247+
#endif // SHT3X_SUPPORT
22162248
#endif // MQTT_ENABLE
22172249
}
22182250

@@ -2518,6 +2550,9 @@ void handleSendMqttDiscovery(void) {
25182550
htmlMenu() +
25192551
F("<p>The Home Assistant MQTT Discovery message is being sent to topic: ")
25202552
+ MqttDiscovery +
2553+
#if SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
2554+
F(" and ") + MqttDiscoverySensor +
2555+
#endif // SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
25212556
F(". It will show up in Home Assistant in a few seconds."
25222557
"</p>"
25232558
"<h3>Warning!</h3>"
@@ -2530,6 +2565,10 @@ void handleSendMqttDiscovery(void) {
25302565
if (i > 0) channel_id = "_" + String(i);
25312566
sendMQTTDiscovery(MqttDiscovery.c_str(), channel_id);
25322567
}
2568+
#if SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
2569+
sendMQTTDiscoverySensor(MqttDiscoverySensor.c_str(), KEY_TEMP);
2570+
sendMQTTDiscoverySensor(MqttDiscoverySensor.c_str(), KEY_HUMIDITY);
2571+
#endif // SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
25332572
}
25342573
#endif // MQTT_DISCOVERY_ENABLE
25352574

@@ -2734,6 +2773,9 @@ void sendMQTTDiscovery(const char *topic, String channel_id) {
27342773
"\"swing_modes\":[\"" D_STR_OFF "\",\"" D_STR_AUTO "\",\"" D_STR_HIGHEST
27352774
"\",\"" D_STR_HIGH "\",\"" D_STR_MIDDLE "\",\""
27362775
D_STR_LOW "\",\"" D_STR_LOWEST "\"],"
2776+
#if SHT3X_SUPPORT
2777+
"\"curr_temp_t\":\"") + MqttSensorStat + F(KEY_TEMP "\","
2778+
#endif // SHT3X_SUPPORT
27372779
"\"uniq_id\":\"") + MqttUniqueId + channel_id + F("\","
27382780
"\"device\":{"
27392781
"\"identifiers\":[\"") + MqttUniqueId + channel_id + F("\"],"
@@ -2752,6 +2794,47 @@ void sendMQTTDiscovery(const char *topic, String channel_id) {
27522794
mqttLog(PSTR("MQTT climate discovery FAILED to send."));
27532795
}
27542796
}
2797+
2798+
#if SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
2799+
// Send the MQTT Discovery data for the SHT3X sensor.
2800+
// type must be a String of either KEY_TEMP or KEY_HUMIDITY.
2801+
void sendMQTTDiscoverySensor(const char *topic, String type) {
2802+
String pub_topic = String(topic) + F("_") + type + F("/config");
2803+
String uom = "%";
2804+
String ha_class = type;
2805+
// XXX Update units of measure for temperature.
2806+
if (type == KEY_TEMP) {
2807+
uom = "°C";
2808+
ha_class = "temperature";
2809+
}
2810+
if (mqtt_client.publish(
2811+
pub_topic.c_str(), String(
2812+
F("{"
2813+
"\"name\":\"") + MqttHAName + "_" + type + F("\","
2814+
2815+
"\"stat_t\":\"") + MqttSensorStat + type + F("\","
2816+
"\"dev_cla\":\"") + ha_class + F("\","
2817+
"\"unit_of_meas\":\"") + uom + F("\","
2818+
2819+
"\"uniq_id\":\"") + MqttUniqueId + type + F("\","
2820+
"\"device\":{"
2821+
"\"identifiers\":[\"") + MqttUniqueId + type + F("\"],"
2822+
"\"connections\":[[\"mac\",\"") + WiFi.macAddress() + F("\"]],"
2823+
"\"manufacturer\":\"IRremoteESP8266\","
2824+
"\"model\":\"IRMQTTServer\","
2825+
"\"name\":\"") + Hostname + F("\","
2826+
"\"sw_version\":\"" _MY_VERSION_ "\""
2827+
"}"
2828+
"}")).c_str(), true)) {
2829+
mqttLog(PSTR("MQTT sensor discovery successful sent."));
2830+
hasDiscoveryBeenSent = true;
2831+
lastDiscovery.reset();
2832+
mqttSentCounter++;
2833+
} else {
2834+
mqttLog(PSTR("MQTT sensor discovery FAILED to send."));
2835+
}
2836+
}
2837+
#endif // SHT3X_SUPPORT && SHT3X_MQTT_DISCOVERY_ENABLE
27552838
#endif // MQTT_DISCOVERY_ENABLE
27562839
#endif // MQTT_ENABLE
27572840

@@ -2820,6 +2903,29 @@ void loop(void) {
28202903
}
28212904
// Periodically send all of the climate state via MQTT.
28222905
doBroadcast(&lastBroadcast, kBroadcastPeriodMs, climate, false, false);
2906+
#if SHT3X_SUPPORT
2907+
// Check if it's time to read the SHT3x sensor.
2908+
if (statSensorReadTime.elapsed() > SHT3X_CHECK_FREQ * 1000) {
2909+
byte result = TemperatureSensor.get();
2910+
if (result == 0) {
2911+
// Success
2912+
float temp = TemperatureSensor.cTemp;
2913+
// XXX Convert units
2914+
float humidity = TemperatureSensor.humidity;
2915+
// Publish the temp and humidity to MQTT.
2916+
String mqttTempTopic = MqttSensorStat + KEY_TEMP;
2917+
String mqttHumidityTopic = MqttSensorStat + KEY_HUMIDITY;
2918+
mqtt_client.publish(mqttTempTopic.c_str(), String(temp).c_str());
2919+
mqtt_client.publish(mqttHumidityTopic.c_str(),
2920+
String(humidity).c_str());
2921+
} else {
2922+
// Error
2923+
mqttLog((String(F("SHT3x sensor read error: ")) +
2924+
String(result)).c_str());
2925+
}
2926+
statSensorReadTime.reset();
2927+
}
2928+
#endif // SHT3X_SUPPORT
28232929
}
28242930
#endif // MQTT_ENABLE
28252931
#if IR_RX

examples/IRMQTTServer/platformio.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ lib_deps_builtin =
1515
lib_deps_external =
1616
PubSubClient@>=2.8.0
1717
ArduinoJson@>=6.0
18+
# Uncomment the following to enable SHT-3x support.
19+
# https://github.com/wemos/WEMOS_SHT3x_Arduino_Library.git
1820

1921
[common_esp8266]
2022
lib_deps_external =

0 commit comments

Comments
 (0)