Detect device disconnects

When a device is sending any traffic, the device is considered to be connected. If no traffic if being received from the device, a status is requested. If the device fails to report the status back in a timely manner, it is considered to be disconnected.

If the device fails to reply to the status request, it is important to confirm that the device is not applying settings. While the device is applying settings, it will not be sending heartbeats or able to process a status request.
This commit is contained in:
Kyle Schwarz
2020-08-27 13:20:48 -04:00
parent 5db07102aa
commit 044c2bb86f
6 changed files with 53 additions and 0 deletions
+31
View File
@@ -205,6 +205,32 @@ bool Device::open() {
handleInternalMessage(message);
}));
std::atomic<bool> receivedMessage{false};
messageReceivedCallbackID = com->addMessageCallback(MessageCallback(filter, [&](std::shared_ptr<Message> message) {
receivedMessage = true;
}));
heartbeatThread = std::thread([&]() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
while(true) {
// Wait for 110ms for a possible heartbeat
std::this_thread::sleep_for(std::chrono::milliseconds(110));
if(!receivedMessage) {
// No heartbeat received, request a status
com->sendCommand(Command::RequestStatusUpdate);
// The response should come back quickly if the com is quiet
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// Check if we got a message, and if not, if settings are being applied
if(!receivedMessage && !settings->applyingSettings) {
if(!stopHeartbeatThread)
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
return;
}
}
receivedMessage = false;
}
});
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onDeviceOpen(); return true; });
return true;
}
@@ -215,12 +241,17 @@ bool Device::close() {
return false;
}
stopHeartbeatThread = true;
if(isOnline())
goOffline();
if(internalHandlerCallbackID)
com->removeMessageCallback(internalHandlerCallbackID);
if(messageReceivedCallbackID)
com->removeMessageCallback(messageReceivedCallbackID);
internalHandlerCallbackID = 0;
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onDeviceClose(); return true; });
+8
View File
@@ -210,6 +210,8 @@ bool IDeviceSettings::apply(bool temporary) {
bytestream[6] = (uint8_t)(gs_checksum >> 8);
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
// Pause I/O with the device while the settings are applied
applyingSettings = true;
std::shared_ptr<Message> msg = com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream);
@@ -250,6 +252,8 @@ bool IDeviceSettings::apply(bool temporary) {
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000));
}
applyingSettings = false;
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
bool ret = (msg && msg->data[0] == 1); // Device sends 0x01 for success
@@ -270,6 +274,8 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
return false;
}
applyingSettings = true;
std::shared_ptr<Message> msg = com->waitForMessageSync([this]() {
return com->sendCommand(Command::SetDefaultSettings);
}, Main51MessageFilter(Command::SetDefaultSettings), std::chrono::milliseconds(1000));
@@ -317,6 +323,8 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
return com->sendCommand(Command::SaveSettings);
}, Main51MessageFilter(Command::SaveSettings), std::chrono::milliseconds(5000));
}
applyingSettings = false;
refresh(); // Refresh our buffer with what the device has, whether we were successful or not