112 lines
3.7 KiB
C++
112 lines
3.7 KiB
C++
#pragma once
|
|
|
|
#include <exception>
|
|
#include <functional>
|
|
#include <optional>
|
|
#include <string>
|
|
|
|
class DaliQueryException : public std::exception {
|
|
public:
|
|
enum class Code {
|
|
busUnavailable,
|
|
gatewayTimeout,
|
|
deviceNoResponse,
|
|
invalidFrame,
|
|
invalidGatewayFrame,
|
|
unknown,
|
|
};
|
|
|
|
DaliQueryException(Code code,
|
|
std::string message,
|
|
std::optional<int> addr = std::nullopt,
|
|
std::optional<int> cmd = std::nullopt)
|
|
: code_(code), message_(std::move(message)), addr_(addr), cmd_(cmd) {}
|
|
|
|
const char* what() const noexcept override { return message_.c_str(); }
|
|
Code code() const { return code_; }
|
|
const std::optional<int>& addr() const { return addr_; }
|
|
const std::optional<int>& cmd() const { return cmd_; }
|
|
|
|
private:
|
|
Code code_ = Code::unknown;
|
|
std::string message_;
|
|
std::optional<int> addr_;
|
|
std::optional<int> cmd_;
|
|
};
|
|
|
|
class DaliBusUnavailableException : public DaliQueryException {
|
|
public:
|
|
explicit DaliBusUnavailableException(std::optional<int> addr = std::nullopt,
|
|
std::optional<int> cmd = std::nullopt)
|
|
: DaliQueryException(Code::busUnavailable, "Bus unavailable", addr, cmd) {}
|
|
};
|
|
|
|
class DaliGatewayTimeoutException : public DaliQueryException {
|
|
public:
|
|
explicit DaliGatewayTimeoutException(std::optional<int> addr = std::nullopt,
|
|
std::optional<int> cmd = std::nullopt)
|
|
: DaliQueryException(Code::gatewayTimeout, "Gateway no response", addr, cmd) {}
|
|
};
|
|
|
|
class DaliDeviceNoResponseException : public DaliQueryException {
|
|
public:
|
|
explicit DaliDeviceNoResponseException(std::optional<int> addr = std::nullopt,
|
|
std::optional<int> cmd = std::nullopt)
|
|
: DaliQueryException(Code::deviceNoResponse, "Device no response", addr, cmd) {}
|
|
};
|
|
|
|
class DaliInvalidFrameException : public DaliQueryException {
|
|
public:
|
|
explicit DaliInvalidFrameException(std::optional<int> addr = std::nullopt,
|
|
std::optional<int> cmd = std::nullopt)
|
|
: DaliQueryException(Code::invalidFrame, "Invalid frame", addr, cmd) {}
|
|
};
|
|
|
|
class DaliInvalidGatewayFrameException : public DaliQueryException {
|
|
public:
|
|
explicit DaliInvalidGatewayFrameException(std::optional<int> addr = std::nullopt,
|
|
std::optional<int> cmd = std::nullopt)
|
|
: DaliQueryException(Code::invalidGatewayFrame, "Invalid gateway frame", addr, cmd) {}
|
|
};
|
|
|
|
inline std::string mapDaliErrorToMessage(const DaliQueryException& e) {
|
|
switch (e.code()) {
|
|
case DaliQueryException::Code::busUnavailable:
|
|
return "dali.error.bus_unavailable";
|
|
case DaliQueryException::Code::gatewayTimeout:
|
|
return "dali.error.gateway_timeout";
|
|
case DaliQueryException::Code::deviceNoResponse:
|
|
return "dali.error.device_no_response";
|
|
case DaliQueryException::Code::invalidFrame:
|
|
return "dali.error.invalid_frame";
|
|
case DaliQueryException::Code::invalidGatewayFrame:
|
|
return "dali.error.invalid_gateway_frame";
|
|
case DaliQueryException::Code::unknown:
|
|
default:
|
|
break;
|
|
}
|
|
return "dali.error.unknown";
|
|
}
|
|
|
|
template <typename T>
|
|
std::optional<T> daliSafe(const std::function<T()>& action,
|
|
const std::function<void(const std::string&)>& onError = nullptr,
|
|
bool rethrowOthers = false) {
|
|
#if defined(__cpp_exceptions)
|
|
try {
|
|
return action();
|
|
} catch (const DaliQueryException& e) {
|
|
if (onError) onError(mapDaliErrorToMessage(e));
|
|
return std::nullopt;
|
|
} catch (...) {
|
|
if (rethrowOthers) throw;
|
|
if (onError) onError("Unexpected error");
|
|
return std::nullopt;
|
|
}
|
|
#else
|
|
(void)onError;
|
|
(void)rethrowOthers;
|
|
return action();
|
|
#endif
|
|
}
|