Compare commits
No commits in common. "dev" and "master" have entirely different histories.
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,4 +4,4 @@
|
|||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
|
|
||||||
include/config.hpp
|
src/config.h
|
14
.vscode/settings.json
vendored
14
.vscode/settings.json
vendored
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"files.associations": {
|
|
||||||
"array": "cpp",
|
|
||||||
"deque": "cpp",
|
|
||||||
"list": "cpp",
|
|
||||||
"string": "cpp",
|
|
||||||
"unordered_map": "cpp",
|
|
||||||
"vector": "cpp",
|
|
||||||
"string_view": "cpp",
|
|
||||||
"initializer_list": "cpp",
|
|
||||||
"ranges": "cpp"
|
|
||||||
},
|
|
||||||
"clang-tidy.checks": ["readability-*", "modernize-*", "bugprone-*"]
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class DHTSensor {}
|
|
@ -1,52 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ESP8266WiFi.h>
|
|
||||||
#include <IRremoteESP8266.h>
|
|
||||||
#include <IRsend.h>
|
|
||||||
#include <HALightColorTemperatureBrightness.hpp>
|
|
||||||
|
|
||||||
class IRLight: public HALightColorTemperatureBrightnessController {
|
|
||||||
private:
|
|
||||||
bool state;
|
|
||||||
short brightness;
|
|
||||||
byte color_temp;
|
|
||||||
|
|
||||||
IRsend *irsend;
|
|
||||||
|
|
||||||
const uint32_t RDOn = irsend->encodeNEC(0x80, 0x1);
|
|
||||||
|
|
||||||
const uint32_t RDOff = irsend->encodeNEC(0x80, 0x1A);
|
|
||||||
|
|
||||||
const uint32_t RDButtonCenter = irsend->encodeNEC(0x80, 0x5);
|
|
||||||
|
|
||||||
const uint32_t RDBrightnessUp = irsend->encodeNEC(0x80, 0x12);
|
|
||||||
|
|
||||||
const uint32_t RDBrightnessDown = irsend->encodeNEC(0x80, 0x1E);
|
|
||||||
|
|
||||||
const uint32_t RDButtonA = irsend->encodeNEC(0x80, 0x7);
|
|
||||||
|
|
||||||
const uint32_t RDButtonB = irsend->encodeNEC(0x80, 0x8);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit IRLight(int pin);
|
|
||||||
explicit IRLight(IRsend *irsend);
|
|
||||||
|
|
||||||
void setState(bool state);
|
|
||||||
bool getState();
|
|
||||||
void on();
|
|
||||||
void off();
|
|
||||||
|
|
||||||
void setBrightness(int brightness);
|
|
||||||
int getBrightness();
|
|
||||||
|
|
||||||
void setColorTemperature(int color);
|
|
||||||
int getColorTemperature();
|
|
||||||
|
|
||||||
void brightnessUp();
|
|
||||||
void brightnessDown();
|
|
||||||
int getBrightnessScale();
|
|
||||||
|
|
||||||
void begin();
|
|
||||||
|
|
||||||
~IRLight();
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
#ifndef UTILS_H
|
|
||||||
#define UTILS_H
|
|
||||||
|
|
||||||
double round2(double value);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||||||
#include <HAControllableDevice.hpp>
|
|
||||||
|
|
||||||
HAControllableDevice::HAControllableDevice(PubSubClient &client,
|
|
||||||
const char *device_type,
|
|
||||||
const char *name,
|
|
||||||
const char *unique_id)
|
|
||||||
: HADevice(client, device_type, name, unique_id) {
|
|
||||||
setupCommandTopic();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAControllableDevice::setupCommandTopic() {
|
|
||||||
command_topic_size = strlen(device_topic) + 4 + 1;
|
|
||||||
command_topic = (char *)malloc(command_topic_size);
|
|
||||||
|
|
||||||
strcpy(command_topic, device_topic);
|
|
||||||
strcat(command_topic, "/cmd");
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAControllableDevice::subscribeToCommandTopic() {
|
|
||||||
Serial.print("Subscribe to ");
|
|
||||||
Serial.println(command_topic);
|
|
||||||
client.subscribe(command_topic);
|
|
||||||
};
|
|
@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HADevice.hpp>
|
|
||||||
|
|
||||||
class HAControllableDevice : public HADevice {
|
|
||||||
protected:
|
|
||||||
char *command_topic;
|
|
||||||
unsigned int command_topic_size;
|
|
||||||
|
|
||||||
void setupCommandTopic();
|
|
||||||
|
|
||||||
public:
|
|
||||||
HAControllableDevice(PubSubClient &client, const char *device_type,
|
|
||||||
const char *name, const char *unique_id);
|
|
||||||
|
|
||||||
void subscribeToCommandTopic();
|
|
||||||
virtual void handle(char *topic, byte *payload, unsigned int length) = 0;
|
|
||||||
};
|
|
@ -1,40 +0,0 @@
|
|||||||
#include <HADevice.hpp>
|
|
||||||
|
|
||||||
HADevice::HADevice(PubSubClient &client, const char *device_type,
|
|
||||||
const char *name, const char *unique_id)
|
|
||||||
: client(client), device_type(device_type), name(name),
|
|
||||||
unique_id(unique_id) {
|
|
||||||
buffer = (char *)malloc(MQTT_MAX_PACKET_SIZE);
|
|
||||||
|
|
||||||
setupDeviceTopic();
|
|
||||||
setupConfigTopic();
|
|
||||||
setupStateTopic();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HADevice::setupDeviceTopic() {
|
|
||||||
device_topic_size =
|
|
||||||
strlen(base_topic) + 1 + strlen(device_type) + 1 + strlen(unique_id) + 1;
|
|
||||||
device_topic = (char *)malloc(device_topic_size);
|
|
||||||
|
|
||||||
strcpy(device_topic, base_topic);
|
|
||||||
strcat(device_topic, "/");
|
|
||||||
strcat(device_topic, device_type);
|
|
||||||
strcat(device_topic, "/");
|
|
||||||
strcat(device_topic, unique_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HADevice::setupConfigTopic() {
|
|
||||||
config_topic_size = strlen(device_topic) + 7 + 1;
|
|
||||||
config_topic = (char *)malloc(config_topic_size);
|
|
||||||
|
|
||||||
strcpy(config_topic, device_topic);
|
|
||||||
strcat(config_topic, "/config");
|
|
||||||
}
|
|
||||||
|
|
||||||
void HADevice::setupStateTopic() {
|
|
||||||
state_topic_size = strlen(device_topic) + 6 + 1;
|
|
||||||
state_topic = (char *)malloc(state_topic_size);
|
|
||||||
|
|
||||||
strcpy(state_topic, device_topic);
|
|
||||||
strcat(state_topic, "/state");
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <PubSubClient.h>
|
|
||||||
|
|
||||||
class HADevice {
|
|
||||||
protected:
|
|
||||||
PubSubClient &client;
|
|
||||||
const char *name;
|
|
||||||
const char *unique_id;
|
|
||||||
const char *device_type;
|
|
||||||
|
|
||||||
static constexpr const char *base_topic = "homeassistant";
|
|
||||||
|
|
||||||
char *device_topic = nullptr;
|
|
||||||
unsigned int device_topic_size = 0;
|
|
||||||
|
|
||||||
char *config_topic = nullptr;
|
|
||||||
unsigned int config_topic_size = 0;
|
|
||||||
|
|
||||||
char *state_topic = nullptr;
|
|
||||||
unsigned int state_topic_size = 0;
|
|
||||||
|
|
||||||
char *buffer;
|
|
||||||
unsigned int buffer_size = MQTT_MAX_PACKET_SIZE;
|
|
||||||
|
|
||||||
void setupDeviceTopic();
|
|
||||||
void setupConfigTopic();
|
|
||||||
void setupStateTopic();
|
|
||||||
|
|
||||||
public:
|
|
||||||
HADevice(PubSubClient &client, const char *device_type, const char *name,
|
|
||||||
const char *unique_id);
|
|
||||||
virtual void sendConfig() = 0;
|
|
||||||
virtual void sendState() = 0;
|
|
||||||
};
|
|
@ -1,83 +0,0 @@
|
|||||||
#include <HALight.hpp>
|
|
||||||
|
|
||||||
HALight::HALight(PubSubClient &client, const char *name, const char *unique_id)
|
|
||||||
: HAControllableDevice(client, "light", name, unique_id) {}
|
|
||||||
|
|
||||||
HALight::HALight(PubSubClient &client, const char *name, const char *unique_id,
|
|
||||||
HALightController &baseLight)
|
|
||||||
: HAControllableDevice(client, "light", name, unique_id),
|
|
||||||
light(&baseLight) {}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALight::createConfigJSON() {
|
|
||||||
JSON_DOCUMENT_TYPE doc;
|
|
||||||
|
|
||||||
doc["~"] = device_topic;
|
|
||||||
doc["name"] = name;
|
|
||||||
doc["unique_id"] = unique_id;
|
|
||||||
doc["cmd_t"] = "~/cmd";
|
|
||||||
doc["stat_t"] = "~/state";
|
|
||||||
doc["schema"] = "json";
|
|
||||||
|
|
||||||
patchConfigJSON(doc);
|
|
||||||
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALight::patchConfigJSON(JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALight::createStateJSON() {
|
|
||||||
JSON_DOCUMENT_TYPE doc;
|
|
||||||
|
|
||||||
if (light->getState()) {
|
|
||||||
doc["state"] = "ON";
|
|
||||||
} else {
|
|
||||||
doc["state"] = "OFF";
|
|
||||||
}
|
|
||||||
|
|
||||||
patchStateJSON(doc);
|
|
||||||
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALight::patchStateJSON(JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALight::innerHandler(const JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
if (strcmp(doc["state"], "ON") == 0) {
|
|
||||||
light->setState(true);
|
|
||||||
} else {
|
|
||||||
light->setState(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALight::sendState() {
|
|
||||||
JSON_DOCUMENT_TYPE doc = createStateJSON();
|
|
||||||
|
|
||||||
buffer[0] = '\0';
|
|
||||||
serializeJson(doc, buffer, buffer_size);
|
|
||||||
|
|
||||||
Serial.println(state_topic);
|
|
||||||
client.publish(state_topic, buffer, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALight::sendConfig() {
|
|
||||||
JSON_DOCUMENT_TYPE doc = createConfigJSON();
|
|
||||||
buffer[0] = '\0';
|
|
||||||
serializeJson(doc, buffer, buffer_size);
|
|
||||||
client.publish(config_topic, buffer, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALight::handle(char *topic, byte *payload, unsigned int length) {
|
|
||||||
if (strcmp(topic, command_topic) != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE doc;
|
|
||||||
deserializeJson(doc, (const byte *)payload, length);
|
|
||||||
|
|
||||||
innerHandler(doc);
|
|
||||||
|
|
||||||
sendState();
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HAControllableDevice.hpp>
|
|
||||||
|
|
||||||
class HALightController {
|
|
||||||
public:
|
|
||||||
virtual void setState(bool state) = 0;
|
|
||||||
virtual bool getState() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define JSON_DOCUMENT_TYPE StaticJsonDocument<256>
|
|
||||||
|
|
||||||
class HALight : public HAControllableDevice {
|
|
||||||
private:
|
|
||||||
HALightController *light;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual JSON_DOCUMENT_TYPE createConfigJSON();
|
|
||||||
virtual JSON_DOCUMENT_TYPE patchConfigJSON(JSON_DOCUMENT_TYPE &doc);
|
|
||||||
virtual JSON_DOCUMENT_TYPE createStateJSON();
|
|
||||||
virtual JSON_DOCUMENT_TYPE patchStateJSON(JSON_DOCUMENT_TYPE &doc);
|
|
||||||
virtual void innerHandler(const JSON_DOCUMENT_TYPE &doc);
|
|
||||||
HALight(PubSubClient &client, const char *name, const char *unique_id);
|
|
||||||
public:
|
|
||||||
HALight(PubSubClient &client, const char *name, const char *unique_id,
|
|
||||||
HALightController &baseLight);
|
|
||||||
void handle(char *topic, byte *payload, unsigned int length) override;
|
|
||||||
void sendConfig() override;
|
|
||||||
void sendState() override;
|
|
||||||
};
|
|
@ -1,30 +0,0 @@
|
|||||||
#include <HALightBrightness.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
HALightBrightness::HALightBrightness(PubSubClient &client, const char *name, const char *unique_id,
|
|
||||||
HALightBrightnessController &baseLight)
|
|
||||||
: HALight(client, name, unique_id, baseLight), light(&baseLight) {}
|
|
||||||
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALightBrightness::patchConfigJSON(JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
doc["brightness"] = true;
|
|
||||||
doc["brightness_scale"] = light->getBrightnessScale();
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALightBrightness::patchStateJSON(JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
doc["brightness"] = light->getBrightness();
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALightBrightness::handleBrightness(const JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
if (doc.containsKey("brightness")) {
|
|
||||||
light->setBrightness(doc["brightness"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALightBrightness::innerHandler(const JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
handleBrightness(doc);
|
|
||||||
delay(50);
|
|
||||||
HALight::innerHandler(doc);
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HALight.hpp>
|
|
||||||
|
|
||||||
class HALightBrightnessController: public virtual HALightController {
|
|
||||||
public:
|
|
||||||
virtual void setBrightness(int value) = 0;
|
|
||||||
virtual int getBrightness() = 0;
|
|
||||||
|
|
||||||
virtual int getBrightnessScale() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class HALightBrightness : public virtual HALight {
|
|
||||||
private:
|
|
||||||
HALightBrightnessController *light;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual JSON_DOCUMENT_TYPE patchConfigJSON(JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
virtual JSON_DOCUMENT_TYPE patchStateJSON(JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
virtual void innerHandler(const JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
|
|
||||||
void handleBrightness(const JSON_DOCUMENT_TYPE &doc);
|
|
||||||
|
|
||||||
public:
|
|
||||||
HALightBrightness(PubSubClient &client, const char *name, const char *unique_id,
|
|
||||||
HALightBrightnessController &baseLight);
|
|
||||||
};
|
|
@ -1,28 +0,0 @@
|
|||||||
#include <HALightColorTemperature.hpp>
|
|
||||||
|
|
||||||
HALightColorTemperature::HALightColorTemperature(PubSubClient &client, const char *name, const char *unique_id,
|
|
||||||
HALightColorTemperatureController &baseLight)
|
|
||||||
: HALight(client, "light", name, baseLight),
|
|
||||||
light(&baseLight) {}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALightColorTemperature::patchConfigJSON(JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
doc["color_temp"] = true;
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALightColorTemperature::patchStateJSON(JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
doc["color_temp"] = light->getColorTemperature();
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALightColorTemperature::handleColorTemperature(const JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
if (doc.containsKey("color_temp")) {
|
|
||||||
light->setColorTemperature(doc["color_temp"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALightColorTemperature::innerHandler(const JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
handleColorTemperature(doc);
|
|
||||||
delay(50);
|
|
||||||
HALight::innerHandler(doc);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HALight.hpp>
|
|
||||||
|
|
||||||
class HALightColorTemperatureController: public virtual HALightController {
|
|
||||||
public:
|
|
||||||
virtual void setColorTemperature(int value) = 0;
|
|
||||||
virtual int getColorTemperature() = 0;
|
|
||||||
|
|
||||||
virtual int getBrightnessScale() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class HALightColorTemperature : public virtual HALight {
|
|
||||||
private:
|
|
||||||
HALightColorTemperatureController *light;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual JSON_DOCUMENT_TYPE patchConfigJSON(JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
virtual JSON_DOCUMENT_TYPE patchStateJSON(JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
virtual void innerHandler(const JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
|
|
||||||
void handleColorTemperature(const JSON_DOCUMENT_TYPE &doc);
|
|
||||||
public:
|
|
||||||
HALightColorTemperature(PubSubClient &client, const char *name, const char *unique_id,
|
|
||||||
HALightColorTemperatureController &baseLight);
|
|
||||||
};
|
|
@ -1,34 +0,0 @@
|
|||||||
#include <HALightColorTemperatureBrightness.hpp>
|
|
||||||
|
|
||||||
HALightColorTemperatureBrightness::HALightColorTemperatureBrightness(
|
|
||||||
PubSubClient &client,
|
|
||||||
const char *name,
|
|
||||||
const char *unique_id,
|
|
||||||
HALightColorTemperatureBrightnessController &baseLight
|
|
||||||
) :
|
|
||||||
HALightBrightness(client, name, unique_id, baseLight),
|
|
||||||
HALightColorTemperature(client, name, unique_id, baseLight),
|
|
||||||
HALight(client, name, unique_id, baseLight),
|
|
||||||
light(&baseLight)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALightColorTemperatureBrightness::patchConfigJSON(JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
HALightBrightness::patchConfigJSON(doc);
|
|
||||||
HALightColorTemperature::patchConfigJSON(doc);
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_DOCUMENT_TYPE HALightColorTemperatureBrightness::patchStateJSON(JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
HALightBrightness::patchStateJSON(doc);
|
|
||||||
HALightColorTemperature::patchStateJSON(doc);
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HALightColorTemperatureBrightness::innerHandler(const JSON_DOCUMENT_TYPE &doc) {
|
|
||||||
handleBrightness(doc);
|
|
||||||
delay(50);
|
|
||||||
handleColorTemperature(doc);
|
|
||||||
delay(50);
|
|
||||||
HALight::innerHandler(doc);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HALightBrightness.hpp>
|
|
||||||
#include <HALightColorTemperature.hpp>
|
|
||||||
|
|
||||||
class HALightColorTemperatureBrightnessController:
|
|
||||||
public HALightBrightnessController,
|
|
||||||
public HALightColorTemperatureController
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
class HALightColorTemperatureBrightness :
|
|
||||||
public HALightBrightness,
|
|
||||||
public HALightColorTemperature
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
HALightColorTemperatureBrightnessController *light;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
JSON_DOCUMENT_TYPE patchConfigJSON(JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
JSON_DOCUMENT_TYPE patchStateJSON(JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
virtual void innerHandler(const JSON_DOCUMENT_TYPE &doc) override;
|
|
||||||
public:
|
|
||||||
HALightColorTemperatureBrightness(PubSubClient &client, const char *name, const char *unique_id,
|
|
||||||
HALightColorTemperatureBrightnessController &baseLight);
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HALight.hpp>
|
|
||||||
#include <HALightBrightness.hpp>
|
|
||||||
#include <HALightColorTemperature.hpp>
|
|
||||||
#include <HALightColorTemperatureBrightness.hpp>
|
|
@ -14,13 +14,7 @@ board = d1_mini_pro
|
|||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
adafruit/DHT sensor library@^1.4.3
|
adafruit/DHT sensor library@^1.4.3
|
||||||
|
jfturcot/SimpleTimer@0.0.0-alpha+sha.b30890b8f7
|
||||||
adafruit/Adafruit Unified Sensor@^1.1.5
|
adafruit/Adafruit Unified Sensor@^1.1.5
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
bblanchon/ArduinoJson@^6.19.4
|
|
||||||
crankyoldgit/IRremoteESP8266@^2.8.2
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_filters = default, esp8266_exception_decoder
|
|
||||||
check_tool = cppcheck, clangtidy
|
|
||||||
check_flags =
|
|
||||||
cppcheck: -v --suppress=*:*/.pio/*
|
|
||||||
clangtidy: --checks=-*,clang-diagnostic-*,-clang-diagnostic-unused-value,clang-analyzer-*,-*,bugprone-*,performance-*,readability-*,-readability-magic-numbers,-readability-braces-around-statements,-readability-inconsistent-declaration-parameter-name,-readability-named-parameter --fix
|
|
111
src/IRLight.cpp
111
src/IRLight.cpp
@ -1,111 +0,0 @@
|
|||||||
#include <IRLight.h>
|
|
||||||
|
|
||||||
IRLight::IRLight(int pin) {
|
|
||||||
irsend = new IRsend(pin);
|
|
||||||
state = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IRLight::IRLight(IRsend *irsend) {
|
|
||||||
irsend = irsend;
|
|
||||||
state = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLight::setState(bool state) {
|
|
||||||
if (state)
|
|
||||||
on();
|
|
||||||
else
|
|
||||||
off();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLight::on() {
|
|
||||||
state = true;
|
|
||||||
irsend->sendNEC(RDOn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLight::off() {
|
|
||||||
state = false;
|
|
||||||
irsend->sendNEC(RDOff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLight::setBrightness(int newBrightness) {
|
|
||||||
if (newBrightness > brightness) {
|
|
||||||
for (int i = 0; i < newBrightness - brightness; i++) {
|
|
||||||
brightnessUp();
|
|
||||||
delay(250);
|
|
||||||
}
|
|
||||||
} else if (newBrightness < brightness) {
|
|
||||||
for (int i = 0; i < brightness - newBrightness; i++) {
|
|
||||||
brightnessDown();
|
|
||||||
delay(250);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
brightness = newBrightness;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLight::setColorTemperature(int color) {
|
|
||||||
if (color < 208) {
|
|
||||||
color_temp = 2;
|
|
||||||
brightness = 14;
|
|
||||||
irsend->sendNEC(RDButtonB);
|
|
||||||
} else if (color < 294) {
|
|
||||||
color_temp = 1;
|
|
||||||
brightness = 14;
|
|
||||||
irsend->sendNEC(RDButtonCenter);
|
|
||||||
} else {
|
|
||||||
color_temp = 0;
|
|
||||||
brightness = 14;
|
|
||||||
irsend->sendNEC(RDButtonA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int IRLight::getColorTemperature() {
|
|
||||||
switch (color_temp)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return 370;
|
|
||||||
case 1:
|
|
||||||
return 262;
|
|
||||||
case 2:
|
|
||||||
return 154;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLight::brightnessUp() {
|
|
||||||
if (brightness < getBrightnessScale()) {
|
|
||||||
brightness++;
|
|
||||||
irsend->sendNEC(RDBrightnessUp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLight::brightnessDown() {
|
|
||||||
if (brightness > 0) {
|
|
||||||
brightness--;
|
|
||||||
irsend->sendNEC(RDBrightnessDown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLight::begin() {
|
|
||||||
irsend->begin();
|
|
||||||
brightness = 14;
|
|
||||||
color_temp = 1;
|
|
||||||
irsend->sendNEC(RDButtonCenter);
|
|
||||||
delay(500);
|
|
||||||
off();
|
|
||||||
}
|
|
||||||
|
|
||||||
int IRLight::getBrightnessScale() {
|
|
||||||
return 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IRLight::getBrightness() {
|
|
||||||
return brightness;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IRLight::getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
IRLight::~IRLight() {
|
|
||||||
delete irsend;
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
#include <IRLightController.hpp>
|
|
||||||
|
|
||||||
IRLightController::IRLightController(IRLight &irlight) : irlight(irlight) {}
|
|
||||||
|
|
||||||
void IRLightController::begin() { irlight.begin(); };
|
|
||||||
|
|
||||||
void IRLightController::setState(bool state) {
|
|
||||||
if (state) {
|
|
||||||
irlight.on();
|
|
||||||
} else {
|
|
||||||
irlight.off();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IRLightController::getState() {
|
|
||||||
return irlight.getState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRLightController::setBrightness(int value) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
IRLightController::~IRLightController() {}
|
|
@ -1,21 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HomeAssistantDevices.hpp>
|
|
||||||
#include <IRLight.h>
|
|
||||||
|
|
||||||
class IRLightController : public HALightBrightnessController {
|
|
||||||
private:
|
|
||||||
IRLight &irlight;
|
|
||||||
|
|
||||||
public:
|
|
||||||
IRLightController(IRLight &irlight);
|
|
||||||
void begin();
|
|
||||||
void setState(bool state);
|
|
||||||
bool getState();
|
|
||||||
|
|
||||||
void setBrightness(int value);
|
|
||||||
int getBrightness();
|
|
||||||
int getBrightnessScale();
|
|
||||||
|
|
||||||
~IRLightController();
|
|
||||||
};
|
|
@ -1,7 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 Maxim Slipenko
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
// Настройки WiFi
|
// Настройки WiFi
|
||||||
#define WIFI_SSID "SSID_HERE"
|
#define WIFI_SSID "SSID_HERE"
|
||||||
#define WIFI_PASS "PASS_HERE"
|
#define WIFI_PASS "PASS_HERE"
|
||||||
@ -15,4 +11,6 @@
|
|||||||
#define DHTPIN D4 // pin gpio 2 in sensor
|
#define DHTPIN D4 // pin gpio 2 in sensor
|
||||||
#define DHTTYPE DHT22 // DHT 22 Change this if you have a DHT11
|
#define DHTTYPE DHT22 // DHT 22 Change this if you have a DHT11
|
||||||
|
|
||||||
#define HOMEASSISTANT_TOPIC "homeassistant/sensor/sensorDht"
|
#define CLIENT_ID "CLIENT_ID_HERE"
|
||||||
|
#define HUMIDITY_TOPIC "sensor/humidity"
|
||||||
|
#define TEMPERATURE_TOPIC "sensor/temperature"
|
248
src/main.cpp
248
src/main.cpp
@ -1,128 +1,24 @@
|
|||||||
/*
|
#include <Arduino.h>
|
||||||
* Copyright 2023 Maxim Slipenko
|
|
||||||
*/
|
|
||||||
#include <DHT.h>
|
#include <DHT.h>
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <IRLight.h>
|
|
||||||
#include <IRremoteESP8266.h>
|
|
||||||
#include <IRsend.h>
|
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
#include <HomeAssistantDevices.hpp>
|
#include <config.h>
|
||||||
#include <IRLightController.hpp>
|
|
||||||
|
|
||||||
#include <config.hpp>
|
|
||||||
#include <utils.hpp>
|
|
||||||
|
|
||||||
static const char ISR_Root_x1[] PROGMEM = R"EOF(
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
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
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
)EOF";
|
|
||||||
|
|
||||||
BearSSL::X509List certISRG(ISR_Root_x1);
|
|
||||||
BearSSL::WiFiClientSecure espClient;
|
|
||||||
|
|
||||||
|
WiFiClient espClient;
|
||||||
PubSubClient client(espClient);
|
PubSubClient client(espClient);
|
||||||
DHT dht(DHTPIN, DHTTYPE);
|
DHT dht(DHTPIN, DHTTYPE);
|
||||||
|
|
||||||
IRLight irlight(4);
|
void setup_wifi() {
|
||||||
HALightColorTemperatureBrightness halight(client, "light", "l-1", irlight);
|
|
||||||
|
|
||||||
void setup_devices();
|
|
||||||
void setup_wifi();
|
|
||||||
void setup_time();
|
|
||||||
void setup_mqtt();
|
|
||||||
|
|
||||||
void reconnect();
|
|
||||||
|
|
||||||
void mqtt_callback(char *topic, byte *payload, unsigned int length);
|
|
||||||
void mqtt_publish_config();
|
|
||||||
void mqtt_publish_state();
|
|
||||||
void mqtt_subscribe_to_commands();
|
|
||||||
|
|
||||||
float temp;
|
|
||||||
float hum;
|
|
||||||
long lastMsg = 0;
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
Serial.begin(115200);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
setup_devices();
|
|
||||||
setup_wifi();
|
|
||||||
setup_time();
|
|
||||||
setup_mqtt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
if (!client.connected())
|
|
||||||
{
|
|
||||||
reconnect();
|
|
||||||
}
|
|
||||||
client.loop();
|
|
||||||
|
|
||||||
/*
|
|
||||||
long now = millis();
|
|
||||||
|
|
||||||
if (now - lastMsg > 60000) {
|
|
||||||
lastMsg = now;
|
|
||||||
temp = round2(dht.readTemperature());
|
|
||||||
|
|
||||||
hum = round2(dht.readHumidity());
|
|
||||||
mqtt_publish_state();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_devices()
|
|
||||||
{
|
|
||||||
irlight.begin();
|
|
||||||
dht.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_wifi()
|
|
||||||
{
|
|
||||||
delay(10);
|
delay(10);
|
||||||
|
// We start by connecting to a WiFi network
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.print("Connecting to ");
|
Serial.print("Connecting to ");
|
||||||
Serial.println(WIFI_SSID);
|
Serial.println(WIFI_SSID);
|
||||||
|
|
||||||
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED)
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
{
|
|
||||||
delay(500);
|
delay(500);
|
||||||
Serial.print(".");
|
Serial.print(".");
|
||||||
}
|
}
|
||||||
@ -131,57 +27,18 @@ void setup_wifi()
|
|||||||
Serial.println("WiFi connected");
|
Serial.println("WiFi connected");
|
||||||
Serial.println("IP address: ");
|
Serial.println("IP address: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
WiFi.setAutoReconnect(true);
|
|
||||||
WiFi.persistent(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_time()
|
void reconnect() {
|
||||||
{
|
|
||||||
configTime(0, 0, "pool.ntp.org");
|
|
||||||
|
|
||||||
Serial.print(F("Waiting for NTP time sync: "));
|
|
||||||
time_t nowSecs = time(nullptr);
|
|
||||||
while (nowSecs < 8 * 3600 * 2)
|
|
||||||
{
|
|
||||||
delay(500);
|
|
||||||
Serial.print(F("."));
|
|
||||||
yield();
|
|
||||||
nowSecs = time(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.println();
|
|
||||||
struct tm timeinfo;
|
|
||||||
gmtime_r(&nowSecs, &timeinfo);
|
|
||||||
Serial.print(F("Current time: "));
|
|
||||||
Serial.print(asctime(&timeinfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_mqtt()
|
|
||||||
{
|
|
||||||
espClient.setTrustAnchors(&certISRG);
|
|
||||||
|
|
||||||
client.setServer(MQTT_SERVER, MQTT_PORT);
|
|
||||||
client.setCallback(mqtt_callback);
|
|
||||||
|
|
||||||
if (!client.connected())
|
|
||||||
{
|
|
||||||
reconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void reconnect()
|
|
||||||
{
|
|
||||||
// Loop until we're reconnected
|
// Loop until we're reconnected
|
||||||
while (!client.connected())
|
while (!client.connected()) {
|
||||||
{
|
|
||||||
Serial.print("Attempting MQTT connection...");
|
Serial.print("Attempting MQTT connection...");
|
||||||
if (client.connect("ESP8266Client", MQTT_LOGIN, MQTT_PASS))
|
// Attempt to connect
|
||||||
{
|
// If you do not want to use a username and password, change next line to
|
||||||
|
// if (client.connect("ESP8266Client")) {
|
||||||
|
if (client.connect("ESP8266Client", MQTT_LOGIN, MQTT_PASS)) {
|
||||||
Serial.println("connected");
|
Serial.println("connected");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.print("failed, rc=");
|
Serial.print("failed, rc=");
|
||||||
Serial.print(client.state());
|
Serial.print(client.state());
|
||||||
Serial.println(" try again in 5 seconds");
|
Serial.println(" try again in 5 seconds");
|
||||||
@ -189,46 +46,51 @@ void reconnect()
|
|||||||
delay(5000);
|
delay(5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.subscribe("homeassistant/status");
|
|
||||||
mqtt_publish_config();
|
|
||||||
delay(100);
|
|
||||||
mqtt_publish_state();
|
|
||||||
delay(100);
|
|
||||||
mqtt_subscribe_to_commands();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mqtt_callback(char *topic, byte *payload, unsigned int length)
|
bool checkBound(float newValue, float prevValue, float maxDiff) {
|
||||||
{
|
return !isnan(newValue) &&
|
||||||
Serial.print("Message arrived [");
|
(newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
|
||||||
Serial.print(topic);
|
}
|
||||||
Serial.print("] ");
|
|
||||||
Serial.println();
|
|
||||||
|
|
||||||
if (strcmp(topic, "homeassistant/status") == 0)
|
long lastMsg = 0;
|
||||||
{
|
float temp = 0.0;
|
||||||
payload[length] = '\0';
|
float hum = 0.0;
|
||||||
if (strcmp(reinterpret_cast<char *>(payload), "online") == 0)
|
float diff = 1.0;
|
||||||
{
|
|
||||||
Serial.println("Home Assistant is online");
|
void setup() {
|
||||||
mqtt_publish_config();
|
Serial.begin(115200);
|
||||||
|
setup_wifi();
|
||||||
|
client.setServer(MQTT_SERVER, MQTT_PORT);
|
||||||
|
|
||||||
|
dht.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (!client.connected()) {
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
client.loop();
|
||||||
|
|
||||||
|
long now = millis();
|
||||||
|
if (now - lastMsg > 10000) {
|
||||||
|
lastMsg = now;
|
||||||
|
|
||||||
|
float newTemp = dht.readTemperature();
|
||||||
|
float newHum = dht.readHumidity();
|
||||||
|
|
||||||
|
if (checkBound(newTemp, temp, diff)) {
|
||||||
|
temp = newTemp;
|
||||||
|
Serial.print("New temperature:");
|
||||||
|
Serial.println(String(temp).c_str());
|
||||||
|
client.publish(TEMPERATURE_TOPIC, String(temp).c_str(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkBound(newHum, hum, diff)) {
|
||||||
|
hum = newHum;
|
||||||
|
Serial.print("New humidity:");
|
||||||
|
Serial.println(String(hum).c_str());
|
||||||
|
client.publish(HUMIDITY_TOPIC, String(hum).c_str(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
halight.handle(topic, payload, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mqtt_publish_config()
|
|
||||||
{
|
|
||||||
halight.sendConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
void mqtt_publish_state()
|
|
||||||
{
|
|
||||||
halight.sendState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void mqtt_subscribe_to_commands()
|
|
||||||
{
|
|
||||||
halight.subscribeToCommandTopic();
|
|
||||||
}
|
}
|
@ -1 +0,0 @@
|
|||||||
// double round2(double value) { return (int)(value * 100 + 0.5) / 100.0; }
|
|
Loading…
Reference in New Issue
Block a user