]> git.basschouten.com Git - mqttthermostat.git/commitdiff
Add support for AHT20 temperature sensor and GPIO pin high/low heating output.
authorBas Schouten <bas@basschouten.com>
Mon, 30 Jan 2023 04:53:46 +0000 (05:53 +0100)
committerBas Schouten <bas@basschouten.com>
Mon, 30 Jan 2023 04:53:46 +0000 (05:53 +0100)
MQTTThermostat/AHTTemperatureSupplier.cpp [new file with mode: 0644]
MQTTThermostat/AHTTemperatureSupplier.h [new file with mode: 0644]
MQTTThermostat/CMakeLists.txt
MQTTThermostat/GPIOHeatingController.cpp [new file with mode: 0644]
MQTTThermostat/GPIOHeatingController.h [new file with mode: 0644]
MQTTThermostat/maindaemon.cpp

diff --git a/MQTTThermostat/AHTTemperatureSupplier.cpp b/MQTTThermostat/AHTTemperatureSupplier.cpp
new file mode 100644 (file)
index 0000000..a9bb709
--- /dev/null
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+extern "C" {
+#include <linux/i2c-dev.h>
+#include <i2c/smbus.h>
+#include <sys/ioctl.h>
+}
+#include <cerrno>
+#include <chrono>
+
+#include "AHTTemperatureSupplier.h"
+
+int i2c_fd;
+
+#define DATA_PENDING_BIT (1 << 7)
+
+using namespace std;
+
+AHTTemperatureSupplier::AHTTemperatureSupplier()
+{
+  int adapter_nr = 11;
+  char filename[20];
+
+  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
+  i2c_fd = open(filename, O_RDWR);
+
+  if (i2c_fd < 0) {
+    printf("Failed to access i2c port.\n");
+    return;
+  }
+  if (ioctl(i2c_fd, I2C_SLAVE, 0x38) < 0) {
+    printf("Failed to find sensor.\n");
+    return;
+  }
+}
+
+float
+AHTTemperatureSupplier::getTemperature()
+{
+  uint8_t byteRead;
+  byteRead = i2c_smbus_read_byte_data(i2c_fd, 0x71);
+
+  i2c_smbus_write_word_data(i2c_fd, 0xAC, 0x0033);
+  byteRead = 0x98;
+
+  auto start_time = chrono::high_resolution_clock::now();
+  while ((byteRead & DATA_PENDING_BIT)) {
+    auto current_time = chrono::high_resolution_clock::now();
+    if (chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count() > 150) {
+      return mLastTemperature;
+    }
+    usleep(10000);
+
+    byteRead = i2c_smbus_read_byte_data(i2c_fd, 0x71);
+  }
+
+  uint8_t data[6];
+  read(i2c_fd, data, 6);
+
+  uint32_t encHumidity = (data[1] << 12) + (data[2] << 4) + (data[3] >> 4);
+  float humidity = (float)encHumidity / 1048576.0;
+
+  uint32_t encTemperature = ((data[3] & 0xF) << 16) + (data[4] << 8) + data[5];
+  float temperature = (float)(encTemperature / 1048576.0) * 200.0 - 50.0;
+
+  mLastHumidity = (uint32_t)(humidity * 100.0);
+  mLastTemperature = temperature;
+
+  return temperature;
+}
+
+uint32_t
+AHTTemperatureSupplier::getHumidity()
+{
+  return mLastHumidity;
+}
\ No newline at end of file
diff --git a/MQTTThermostat/AHTTemperatureSupplier.h b/MQTTThermostat/AHTTemperatureSupplier.h
new file mode 100644 (file)
index 0000000..17f05ae
--- /dev/null
@@ -0,0 +1,14 @@
+#include "TemperatureSupplier.h"\r
+\r
+class AHTTemperatureSupplier : public TemperatureSupplier\r
+{\r
+public:\r
+  AHTTemperatureSupplier();\r
+\r
+  float getTemperature();\r
+  uint32_t getHumidity();\r
+\r
+private:\r
+  uint32_t mLastHumidity = 0;\r
+  float mLastTemperature = 0.0;\r
+};
\ No newline at end of file
index f62271c16bb3ba7f47698ec1af08f09f0d8fe018..a3b9a0995ec82acee53717254e48a738ba143a9c 100644 (file)
@@ -4,15 +4,28 @@
 
 
 # Add source to this project's executable.
+add_executable (mqttthermostat "MQTTThermostat.cpp" "MQTTThermostat.h" "TemperatureSupplier.h"  "HeatingController.h")
 if (WIN32)
-add_executable (mqttthermostat "MQTTThermostat.cpp" "MQTTThermostat.h" "TemperatureSupplier.h"  "HeatingController.h" "maintest.cpp")
+target_sources (mqttthermostat PRIVATE "maintest.cpp")
 target_link_libraries (mqttthermostat PRIVATE paho-mqtt3a-static paho-mqtt3c-static)
 endif (WIN32)
 if (UNIX)
-add_executable (mqttthermostat "MQTTThermostat.cpp" "MQTTThermostat.h" "TemperatureSupplier.h"  "HeatingController.h" "maindaemon.cpp")
+target_sources (mqttthermostat PRIVATE "maindaemon.cpp")
 target_link_libraries (mqttthermostat PRIVATE paho-mqtt3a paho-mqtt3c)
 endif (UNIX)
 
+if (HAS_AHT_SUPPORT)
+target_sources (mqttthermostat PRIVATE "AHTTemperatureSupplier.cpp")
+target_link_libraries (mqttthermostat PRIVATE i2c)
+add_compile_definitions(HAS_AHT_SUPPORT)
+endif (HAS_AHT_SUPPORT)
+
+if (HAS_GPIO_SUPPORT)
+target_sources (mqttthermostat PRIVATE "GPIOHeatingController.cpp")
+target_link_libraries (mqttthermostat PRIVATE wiringPi)
+add_compile_definitions(HAS_GPIO_SUPPORT)
+endif (HAS_GPIO_SUPPORT)
+
 target_include_directories (mqttthermostat PRIVATE ../paho.mqtt.c/src)
 
 install(TARGETS mqttthermostat
diff --git a/MQTTThermostat/GPIOHeatingController.cpp b/MQTTThermostat/GPIOHeatingController.cpp
new file mode 100644 (file)
index 0000000..9eba3f8
--- /dev/null
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include "GPIOHeatingController.h"
+#include "wiringPi.h"
+
+using namespace std;
+
+GPIOHeatingController::GPIOHeatingController(uint32_t aPin)
+  : mPin(aPin)
+{
+  wiringPiSetupGpio();
+  pinMode(mPin, OUTPUT);
+}
+
+void
+GPIOHeatingController::setHeatingActive(bool aActive)
+{
+  if (aActive) {
+    digitalWrite(mPin, HIGH);
+  }
+  else {
+    digitalWrite(mPin, LOW);
+  }
+}
\ No newline at end of file
diff --git a/MQTTThermostat/GPIOHeatingController.h b/MQTTThermostat/GPIOHeatingController.h
new file mode 100644 (file)
index 0000000..f3eab9b
--- /dev/null
@@ -0,0 +1,12 @@
+#include "HeatingController.h"
+
+class GPIOHeatingController : public HeatingController
+{
+public:
+  GPIOHeatingController(uint32_t aPin);
+
+  void setHeatingActive(bool aActive);
+
+private:
+  uint32_t mPin;
+};
\ No newline at end of file
index 2073bb0a769064fe5be6b5b0411995d435df6389..306dad664da18748742b24638f82c45c30b96cad 100644 (file)
 #include <signal.h>
 
 #include "MQTTThermostat.h"
+#ifdef HAS_AHT_SUPPORT
+#include "AHTTemperatureSupplier.h"
+#endif
+#ifdef HAS_GPIO_SUPPORT
+#include "GPIOHeatingController.h"
+#endif
 
 using namespace std;
 
@@ -25,6 +31,7 @@ static int pid_fd;
 static ofstream logStream;
 static string pidFile = "~/mqttthermostat.lock";
 static string configFile = "~/mqttthermostat.conf";
+int32_t gpioHeatingPin = -1;
 
 static bool shuttingDown = false;
 
@@ -79,6 +86,11 @@ void read_config_file()
           if (value.rfind("dummy", 0) == 0) {
             tempSupplier = make_unique<DummyTemperatureSupplier>();
           }
+#ifdef HAS_AHT_SUPPORT
+          else if (value.rfind("AHT", 0) == 0) {
+            tempSupplier = make_unique<AHTTemperatureSupplier>();
+          }
+#endif
           else {
             LOG("Unknown temperature supplier specified.");
           }
@@ -87,6 +99,15 @@ void read_config_file()
           if (value.rfind("dummy", 0) == 0) {
             heatingController = make_unique<DummyHeatingController>();
           }
+#ifdef HAS_GPIO_SUPPORT
+          else if (value.rfind("GPIO", 0) == 0) {
+            if (gpioHeatingPin < 0) {
+              LOG("GPIO heating pin not specified. Add it before selecting the heating controller.");
+              exit(EXIT_FAILURE);
+            }
+            heatingController = make_unique<GPIOHeatingController>(gpioHeatingPin);
+          }
+#endif
           else {
             LOG("Unknown heating controller specified.");
           }
@@ -100,6 +121,9 @@ void read_config_file()
         else if (key == "clientid") {
           clientid = value;
         }
+        else if (key == "gpio heating pin") {
+          gpioHeatingPin = stoi(value);
+        }
       }
     }
   }