--- /dev/null
+#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
--- /dev/null
+#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
# 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
--- /dev/null
+#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
--- /dev/null
+#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
#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;
static ofstream logStream;
static string pidFile = "~/mqttthermostat.lock";
static string configFile = "~/mqttthermostat.conf";
+int32_t gpioHeatingPin = -1;
static bool shuttingDown = false;
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.");
}
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.");
}
else if (key == "clientid") {
clientid = value;
}
+ else if (key == "gpio heating pin") {
+ gpioHeatingPin = stoi(value);
+ }
}
}
}