Extensions: Offer an opportunity to communicate with a dead device

pull/35/head
Paul Hollinsky 2021-04-23 22:32:42 -04:00
parent 4cd7bafca7
commit 218648ae5a
3 changed files with 65 additions and 26 deletions

View File

@ -174,34 +174,36 @@ bool Device::open() {
return false;
}
if(!afterCommunicationOpen()) {
// Very unlikely, at the time of writing this only fails if rawWrite does.
// If you're looking for this error, you're probably looking for if(!serial) below.
report(APIEvent::Type::NoSerialNumber, APIEvent::Severity::Error); // Communication could not be established with the device. Perhaps it is not powered with 12 volts?
com->close();
return false;
APIEvent::Type attemptErr = attemptToBeginCommunication();
if(attemptErr != APIEvent::Type::NoErrorFound) {
// We could not communicate with the device, let's see if an extension can
bool tryAgain = false;
forEachExtension([&tryAgain](const std::shared_ptr<DeviceExtension>& ext) -> bool {
if(ext->onDeviceCommunicationDead())
tryAgain = true;
return true;
});
if(!tryAgain) {
report(attemptErr, APIEvent::Severity::Error);
return false; // Extensions couldn't save us
}
attemptErr = attemptToBeginCommunication();
if(attemptErr != APIEvent::Type::NoErrorFound) {
report(attemptErr, APIEvent::Severity::Error);
return false;
}
}
auto serial = com->getSerialNumberSync();
int i = 0;
while(!serial) {
serial = com->getSerialNumberSync();
if(i++ > 5)
break;
}
if(!serial) {
report(APIEvent::Type::NoSerialNumber, APIEvent::Severity::Error); // Communication could not be established with the device. Perhaps it is not powered with 12 volts?
com->close();
bool block = false;
forEachExtension([&block](const std::shared_ptr<DeviceExtension>& ext) {
if(ext->onDeviceOpen())
return true;
block = true;
return false;
}
std::string currentSerial = getNeoDevice().serial;
if(currentSerial != serial->deviceSerial) {
report(APIEvent::Type::IncorrectSerialNumber, APIEvent::Severity::Error);
com->close();
});
if(block) // Extensions say no
return false;
}
if(!settings->disabled) {
// Since we will not fail the open if a settings read fails,
// downgrade any errors to warnings. Otherwise the error will
@ -258,10 +260,40 @@ bool Device::open() {
com->removeMessageCallback(messageReceivedCallbackID);
});
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onDeviceOpen(); return true; });
return true;
}
APIEvent::Type Device::attemptToBeginCommunication() {
if(!afterCommunicationOpen()) {
// Very unlikely, at the time of writing this only fails if rawWrite does.
// If you're looking for this error, you're probably looking for if(!serial) below.
com->close();
// "Communication could not be established with the device. Perhaps it is not powered with 12 volts?"
return APIEvent::Type::NoSerialNumber;
}
auto serial = com->getSerialNumberSync();
int i = 0;
while(!serial) {
serial = com->getSerialNumberSync();
if(i++ > 5)
break;
}
if(!serial) {
com->close();
// "Communication could not be established with the device. Perhaps it is not powered with 12 volts?"
return APIEvent::Type::NoSerialNumber;
}
std::string currentSerial = getNeoDevice().serial;
if(currentSerial != serial->deviceSerial) {
com->close();
return APIEvent::Type::IncorrectSerialNumber;
}
return APIEvent::Type::NoErrorFound;
}
bool Device::close() {
if(!com) {
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);

View File

@ -283,6 +283,8 @@ private:
std::vector<Network> supportedTXNetworks;
std::vector<Network> supportedRXNetworks;
APIEvent::Type attemptToBeginCommunication();
// Use heartbeatSuppressed instead when reading
std::atomic<int> heartbeatSuppressedByUser{0};
bool heartbeatSuppressed() const { return heartbeatSuppressedByUser > 0 || (settings && settings->applyingSettings); }

View File

@ -17,7 +17,12 @@ public:
virtual ~DeviceExtension() = default;
virtual const char* getName() const = 0;
virtual void onDeviceOpen() {}
// Return false to block opening
virtual bool onDeviceOpen() { return true; }
// Return true to indicate that communication should now be back
virtual bool onDeviceCommunicationDead() { return false; }
virtual void onGoOnline() {}
virtual void onGoOffline() {}
virtual void onDeviceClose() {}