Allow controlling any blind in the house

This commit is contained in:
2024-01-03 11:34:15 +11:00
parent 8b835b6af0
commit ccdbea4283

View File

@@ -28,6 +28,8 @@ EspMQTTClient client(
auto timer = Timer<10, millis, uint16_t>();
void processPacket(const Packet*);
void processSetMessage(const String& topic, const String &payload);
void processSetPositionMessage(const String& topic, const String &payload);
bool sendOpenPacket(uint16_t destination);
bool sendClosePacket(uint16_t destination);
@@ -38,11 +40,34 @@ bool sendPacket(Packet *packet);
bool updatePosition(uint16_t shadeID);
struct Shade {
uint16_t ID;
String name;
};
std::vector<Shade> shades;
void setup() {
Serial.begin(SER_BAUDRATE);
Serial.println("Starting up");
shades.push_back(Shade{0x4EF1, "study_blind"});
shades.push_back(Shade{0xA51F, "studio_blockout_left_blind"});
shades.push_back(Shade{0xDAEF, "studio_blockout_right_blind"});
shades.push_back(Shade{0x7687, "studio_left_blind"});
shades.push_back(Shade{0xB0DE, "studio_right_blind"});
shades.push_back(Shade{0xB451, "bedroom_door_blockout_blind"});
shades.push_back(Shade{0x48A6, "bedroom_window_blockout_blind"});
shades.push_back(Shade{0x9E14, "bedroom_door_blind"});
shades.push_back(Shade{0x061C, "bedroom_window_blind"});
shades.push_back(Shade{0x2959, "bathroom_blind"});
shades.push_back(Shade{0x6FAD, "kitchen_door_blind"});
shades.push_back(Shade{0xFB21, "kitchen_window_blind"});
shades.push_back(Shade{0x8B10, "living_room_big_window_blind"});
shades.push_back(Shade{0x3EB8, "living_room_door_blind"});
shades.push_back(Shade{0x5463, "living_room_window_blind"});
powerView.setPacketCallback(processPacket);
if (!powerView.begin()) {
Serial.println("Failed to start RFPowerView");
@@ -75,11 +100,13 @@ void processPacket(const Packet *packet) {
for (size_t i = 0; i < parameters.fields.size(); i++) {
Field field = parameters.fields[i];
if (field.identifier == 0x50) {
if (packet->source == 0x4EF1) {
uint16_t value = std::get<uint16_t>(field.value);
uint8_t position = (uint8_t)std::round(((float)value / 0xFFFF) * 100);
String payload = String(position);
client.publish("hotdog/test_mqtt_blind/position", payload, true);
for (size_t i = 0; i < shades.size(); i++) {
if (packet->source == shades[i].ID) {
uint16_t value = std::get<uint16_t>(field.value);
uint8_t position = (uint8_t)std::round(((float)value / 0xFFFF) * 100);
String payload = String(position);
client.publish("hotdog/" + shades[i].name + "/position", payload, true);
}
}
}
}
@@ -89,32 +116,10 @@ void processPacket(const Packet *packet) {
void onConnectionEstablished() {
Serial.println("Connection established");
client.subscribe("hotdog/test_mqtt_blind/set", [] (const String &payload) {
uint16_t shadeID = 0x4EF1;
if (payload == "OPEN") {
sendOpenPacket(shadeID);
} else if (payload == "CLOSE") {
sendClosePacket(shadeID);
} else if (payload == "STOP") {
sendStopPacket(shadeID);
// TODO: Schedule fetching position of blind
sendFetchPosition(shadeID);
}
});
client.subscribe("hotdog/test_mqtt_blind/set_position", [] (const String &payload) {
uint16_t shadeID = 0x4EF1;
float percentage = payload.toInt() / 100.0f;
sendSetPosition(shadeID, percentage);
// TODO: Schedule fetching position of blind
timer.in(1000, updatePosition, 0x4EF1);
timer.in(3000, updatePosition, 0x4EF1);
timer.in(5000, updatePosition, 0x4EF1);
timer.in(7000, updatePosition, 0x4EF1);
timer.in(9000, updatePosition, 0x4EF1);
timer.in(15000, updatePosition, 0x4EF1);
timer.in(30000, updatePosition, 0x4EF1);
});
for (int i = 0; i < shades.size(); i++) {
client.subscribe("hotdog/" + shades[i].name + "/set", processSetMessage);
client.subscribe("hotdog/" + shades[i].name + "/set_position", processSetPositionMessage);
}
client.publish("hotdog/availability", "online", true);
}
@@ -200,4 +205,45 @@ bool updatePosition(uint16_t shadeID) {
Serial.println("Triggering position update");
sendFetchPosition(shadeID);
return false;
}
void processSetMessage(const String &topic, const String &payload) {
int startIndex = topic.indexOf("/") + 1;
int endIndex = topic.indexOf("/", startIndex);
String shadeName = topic.substring(startIndex, endIndex);
for (size_t i = 0; i < shades.size(); i++) {
if (shades[i].name == shadeName) {
if (payload == "OPEN") {
sendOpenPacket(shades[i].ID);
} else if (payload == "CLOSE") {
sendClosePacket(shades[i].ID);
} else if (payload == "STOP") {
sendStopPacket(shades[i].ID);
// TODO: Schedule fetching position of blind
sendFetchPosition(shades[i].ID);
}
}
}
}
void processSetPositionMessage(const String& topic, const String &payload) {
int startIndex = topic.indexOf("/") + 1;
int endIndex = topic.indexOf("/", startIndex);
String shadeName = topic.substring(startIndex, endIndex);
for (size_t i = 0; i < shades.size(); i++) {
if (shades[i].name == shadeName) {
float percentage = payload.toInt() / 100.0f;
sendSetPosition(shades[i].ID, percentage);
// TODO: Schedule fetching position of blind
timer.in(1000, updatePosition, shades[i].ID);
timer.in(3000, updatePosition, shades[i].ID);
timer.in(5000, updatePosition, shades[i].ID);
timer.in(7000, updatePosition, shades[i].ID);
timer.in(9000, updatePosition, shades[i].ID);
timer.in(15000, updatePosition, shades[i].ID);
timer.in(30000, updatePosition, shades[i].ID);
}
}
}