Improve logic for fetching position while blind is moving or stopped
This commit is contained in:
174
src/main.cpp
174
src/main.cpp
@@ -39,15 +39,20 @@ bool sendSetPosition(uint16_t destination, float percentage);
|
|||||||
bool sendFetchPosition(uint16_t destination);
|
bool sendFetchPosition(uint16_t destination);
|
||||||
bool sendPacket(Packet *packet);
|
bool sendPacket(Packet *packet);
|
||||||
|
|
||||||
bool updatePosition(uint16_t shadeID);
|
bool checkPosition(uint16_t shadeID);
|
||||||
|
void startFetchingPosition(uint16_t shadeID, int8_t targetPosition);
|
||||||
|
|
||||||
|
void publishPosition(const String& shadeName, const uint8_t position);
|
||||||
|
void publishState(const String& shadeName, const String& state);
|
||||||
|
|
||||||
struct Shade {
|
struct Shade {
|
||||||
uint16_t ID;
|
uint16_t ID;
|
||||||
String name;
|
String name;
|
||||||
uint8_t lastTargetPosition;
|
int8_t lastTargetPosition;
|
||||||
uint8_t lastPosition;
|
int8_t lastPosition;
|
||||||
uint8_t lastPositionCount;
|
uint8_t samePositionCount;
|
||||||
uint8_t positionFetchCount;
|
uint8_t positionFetchCount;
|
||||||
|
void* timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Shade> shades;
|
std::vector<Shade> shades;
|
||||||
@@ -57,21 +62,21 @@ void setup() {
|
|||||||
|
|
||||||
Serial.println("Starting up");
|
Serial.println("Starting up");
|
||||||
|
|
||||||
shades.push_back(Shade{0x4EF1, "study_blind"});
|
shades.push_back(Shade{0x4EF1, "study_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0xA51F, "studio_blockout_left_blind"});
|
shades.push_back(Shade{0xA51F, "studio_blockout_left_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0xDAEF, "studio_blockout_right_blind"});
|
shades.push_back(Shade{0xDAEF, "studio_blockout_right_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x7687, "studio_left_blind"});
|
shades.push_back(Shade{0x7687, "studio_left_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0xB0DE, "studio_right_blind"});
|
shades.push_back(Shade{0xB0DE, "studio_right_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0xB451, "bedroom_door_blockout_blind"});
|
shades.push_back(Shade{0xB451, "bedroom_door_blockout_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x48A6, "bedroom_window_blockout_blind"});
|
shades.push_back(Shade{0x48A6, "bedroom_window_blockout_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x9E14, "bedroom_door_blind"});
|
shades.push_back(Shade{0x9E14, "bedroom_door_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x061C, "bedroom_window_blind"});
|
shades.push_back(Shade{0x061C, "bedroom_window_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x2959, "bathroom_blind"});
|
shades.push_back(Shade{0x2959, "bathroom_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x6FAD, "kitchen_door_blind"});
|
shades.push_back(Shade{0x6FAD, "kitchen_door_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0xFB21, "kitchen_window_blind"});
|
shades.push_back(Shade{0xFB21, "kitchen_window_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x8B10, "living_room_big_window_blind"});
|
shades.push_back(Shade{0x8B10, "living_room_big_window_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x3EB8, "living_room_door_blind"});
|
shades.push_back(Shade{0x3EB8, "living_room_door_blind", -1, -1, 0, 0, nullptr});
|
||||||
shades.push_back(Shade{0x5463, "living_room_window_blind"});
|
shades.push_back(Shade{0x5463, "living_room_window_blind", -1, -1, 0, 0, nullptr});
|
||||||
|
|
||||||
powerView.setPacketCallback(processPacket);
|
powerView.setPacketCallback(processPacket);
|
||||||
if (!powerView.begin()) {
|
if (!powerView.begin()) {
|
||||||
@@ -109,14 +114,15 @@ void processPacket(const Packet *packet) {
|
|||||||
if (packet->source == shades[i].ID) {
|
if (packet->source == shades[i].ID) {
|
||||||
uint16_t value = std::get<uint16_t>(field.value);
|
uint16_t value = std::get<uint16_t>(field.value);
|
||||||
uint8_t position = (uint8_t)std::round(((float)value / 0xFFFF) * 100);
|
uint8_t position = (uint8_t)std::round(((float)value / 0xFFFF) * 100);
|
||||||
|
|
||||||
if (shades[i].lastPosition == position) {
|
if (shades[i].lastPosition == position) {
|
||||||
shades[i].lastPositionCount++;
|
shades[i].samePositionCount++;
|
||||||
} else {
|
} else {
|
||||||
shades[i].lastPositionCount = 0;
|
shades[i].samePositionCount = 1;
|
||||||
}
|
}
|
||||||
shades[i].lastPosition = position;
|
shades[i].lastPosition = position;
|
||||||
String payload = String(position);
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/position", payload, true);
|
publishPosition(shades[i].name, position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,46 +218,6 @@ bool sendPacket(Packet *packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updatePosition(uint16_t shadeID) {
|
|
||||||
for (size_t i = 0; i < shades.size(); i++) {
|
|
||||||
if (shades[i].ID == shadeID) {
|
|
||||||
if (shades[i].lastTargetPosition != shades[i].lastPosition || shades[i].lastPosition == -1) {
|
|
||||||
if (shades[i].positionFetchCount >= MAX_FETCH_COUNT) {
|
|
||||||
// Give up waiting for the blind to reach the target position
|
|
||||||
if (shades[i].lastPosition > 0) {
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "open", true);
|
|
||||||
} else {
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "closed", true);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shades[i].lastPositionCount >= 2) {
|
|
||||||
// Blind hasn't moved after 3 fetches, so give up waiting
|
|
||||||
if (shades[i].lastPosition > 0) {
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "open", true);
|
|
||||||
} else {
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "closed", true);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
shades[i].positionFetchCount++;
|
|
||||||
sendFetchPosition(shadeID);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
if (shades[i].lastPosition > 0) {
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "open", true);
|
|
||||||
} else {
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "closed", true);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void processSetMessage(const String &topic, const String &payload) {
|
void processSetMessage(const String &topic, const String &payload) {
|
||||||
int startIndex = topic.indexOf("/") + 1;
|
int startIndex = topic.indexOf("/") + 1;
|
||||||
int endIndex = topic.indexOf("/", startIndex);
|
int endIndex = topic.indexOf("/", startIndex);
|
||||||
@@ -262,31 +228,20 @@ void processSetMessage(const String &topic, const String &payload) {
|
|||||||
if (payload == "OPEN") {
|
if (payload == "OPEN") {
|
||||||
sendOpenPacket(shades[i].ID);
|
sendOpenPacket(shades[i].ID);
|
||||||
|
|
||||||
shades[i].lastPosition = -1;
|
startFetchingPosition(shades[i].ID, 100);
|
||||||
shades[i].lastTargetPosition = 100;
|
|
||||||
shades[i].positionFetchCount = 0;
|
|
||||||
shades[i].lastPositionCount = 0;
|
|
||||||
timer.every(2000, updatePosition, shades[i].ID);
|
|
||||||
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "opening", true);
|
publishState(shades[i].name, "opening");
|
||||||
} else if (payload == "CLOSE") {
|
} else if (payload == "CLOSE") {
|
||||||
sendClosePacket(shades[i].ID);
|
sendClosePacket(shades[i].ID);
|
||||||
|
|
||||||
shades[i].lastPosition = -1;
|
startFetchingPosition(shades[i].ID, 0);
|
||||||
shades[i].lastTargetPosition = 0;
|
|
||||||
shades[i].positionFetchCount = 0;
|
|
||||||
shades[i].lastPositionCount = 0;
|
|
||||||
timer.every(2000, updatePosition, shades[i].ID);
|
|
||||||
|
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "closing", true);
|
publishState(shades[i].name, "closing");
|
||||||
} else if (payload == "STOP") {
|
} else if (payload == "STOP") {
|
||||||
sendStopPacket(shades[i].ID);
|
sendStopPacket(shades[i].ID);
|
||||||
|
|
||||||
shades[i].lastPosition = -1;
|
startFetchingPosition(shades[i].ID, -1);
|
||||||
shades[i].lastTargetPosition = -1;
|
timer.in(100, sendFetchPosition, shades[i].ID);
|
||||||
shades[i].positionFetchCount = 0;
|
|
||||||
shades[i].lastPositionCount = 0;
|
|
||||||
timer.every(2000, updatePosition, shades[i].ID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -303,16 +258,61 @@ void processSetPositionMessage(const String& topic, const String &payload) {
|
|||||||
sendSetPosition(shades[i].ID, percentage);
|
sendSetPosition(shades[i].ID, percentage);
|
||||||
|
|
||||||
if (payload.toInt() > shades[i].lastPosition) {
|
if (payload.toInt() > shades[i].lastPosition) {
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "opening", true);
|
publishState(shades[i].name, "opening");
|
||||||
} else if (payload.toInt() < shades[i].lastPosition) {
|
} else if (payload.toInt() < shades[i].lastPosition) {
|
||||||
client.publish("hotdog/" + shades[i].name + "/state", "closing", true);
|
publishState(shades[i].name, "closing");
|
||||||
}
|
}
|
||||||
|
|
||||||
shades[i].lastPosition = -1;
|
startFetchingPosition(shades[i].ID, payload.toInt());
|
||||||
shades[i].lastTargetPosition = payload.toInt();
|
|
||||||
shades[i].positionFetchCount = 0;
|
|
||||||
shades[i].lastPositionCount = 0;
|
|
||||||
timer.every(2000, updatePosition, shades[i].ID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkPosition(uint16_t shadeID) {
|
||||||
|
for (size_t i = 0; i < shades.size(); i++) {
|
||||||
|
if (shades[i].ID == shadeID) {
|
||||||
|
// Keep fetching position if:
|
||||||
|
// - the last reported position doesn't match the target position
|
||||||
|
// - a position hasn't been reported yet
|
||||||
|
// - there is no target position
|
||||||
|
if (shades[i].lastTargetPosition != shades[i].lastPosition || shades[i].lastPosition == -1 || shades[i].lastTargetPosition == -1) {
|
||||||
|
// Keep fetching position if the count limits have not been reached
|
||||||
|
if (shades[i].positionFetchCount < MAX_FETCH_COUNT && shades[i].samePositionCount < 2) {
|
||||||
|
shades[i].positionFetchCount++;
|
||||||
|
sendFetchPosition(shadeID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishState(shades[i].name, shades[i].lastPosition > 0 ? "open" : "closed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startFetchingPosition(uint16_t shadeID, int8_t targetPosition) {
|
||||||
|
for (size_t i = 0; i < shades.size(); i++) {
|
||||||
|
if (shades[i].ID == shadeID) {
|
||||||
|
// Cancel any existing timer
|
||||||
|
if (shades[i].timer != nullptr) {
|
||||||
|
timer.cancel(shades[i].timer);
|
||||||
|
shades[i].timer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
shades[i].lastTargetPosition = targetPosition;
|
||||||
|
shades[i].positionFetchCount = 0;
|
||||||
|
shades[i].samePositionCount = 1;
|
||||||
|
|
||||||
|
shades[i].timer = timer.every(2000, checkPosition, shades[i].ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void publishState(const String& shadeName, const String& state) {
|
||||||
|
client.publish("hotdog/" + shadeName + "/state", state, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void publishPosition(const String& shadeName, const uint8_t position) {
|
||||||
|
client.publish("hotdog/" + shadeName + "/position", String(position), true);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user