Implement DALI Bridge Engine and Model Management
- Added `bridge.cpp` to handle DALI bridge operations including model management, command execution, and response formatting. - Introduced `bridge_model.cpp` for defining bridge models, value transformations, and JSON serialization/deserialization. - Created `bridge_provisioning.cpp` for managing bridge configuration storage and retrieval using NVS on ESP platform. - Enhanced `gateway_cloud.cpp` to integrate DALI bridge requests and responses with cloud communication. - Introduced `modbus_bridge.cpp` to handle Modbus-specific operations and register management. - Implemented utility functions for converting between DaliValue and cJSON formats. - Added error handling and metadata management in bridge responses.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "bridge.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct BacnetBridgeConfig {
|
||||
uint32_t deviceInstance = 4194303;
|
||||
std::string localAddress;
|
||||
uint16_t udpPort = 47808;
|
||||
};
|
||||
|
||||
struct BacnetObjectBinding {
|
||||
std::string modelID;
|
||||
BridgeObjectType objectType = BridgeObjectType::unknown;
|
||||
int objectInstance = -1;
|
||||
std::string property;
|
||||
};
|
||||
|
||||
class DaliBacnetBridge {
|
||||
public:
|
||||
explicit DaliBacnetBridge(DaliBridgeEngine& engine);
|
||||
|
||||
void setConfig(const BacnetBridgeConfig& config);
|
||||
const BacnetBridgeConfig& config() const;
|
||||
|
||||
DaliBridgeResult handlePropertyWrite(BridgeObjectType objectType,
|
||||
int objectInstance,
|
||||
const std::string& property,
|
||||
const DaliValue& value) const;
|
||||
std::optional<BacnetObjectBinding> findObject(BridgeObjectType objectType,
|
||||
int objectInstance,
|
||||
const std::string& property) const;
|
||||
std::vector<BacnetObjectBinding> describeObjects() const;
|
||||
|
||||
private:
|
||||
DaliBridgeEngine& engine_;
|
||||
BacnetBridgeConfig config_;
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.hpp"
|
||||
#include "bridge_model.hpp"
|
||||
#include "dali_comm.hpp"
|
||||
#include "dt1.hpp"
|
||||
#include "dt8.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct DaliBridgeRequest {
|
||||
std::string sequence;
|
||||
std::string modelID;
|
||||
std::optional<BridgeOperation> operation;
|
||||
std::optional<int> rawAddress;
|
||||
std::optional<int> rawCommand;
|
||||
std::optional<int> shortAddress;
|
||||
DaliValue value;
|
||||
DaliValue::Object metadata;
|
||||
};
|
||||
|
||||
struct DaliBridgeResult {
|
||||
std::string sequence;
|
||||
std::string modelID;
|
||||
BridgeOperation operation = BridgeOperation::unknown;
|
||||
bool ok = false;
|
||||
std::optional<int> data;
|
||||
std::string error;
|
||||
DaliValue::Object metadata;
|
||||
|
||||
DaliValue::Object toJson() const;
|
||||
};
|
||||
|
||||
class DaliBridgeEngine {
|
||||
public:
|
||||
explicit DaliBridgeEngine(DaliComm& comm);
|
||||
|
||||
bool upsertModel(const BridgeModel& model);
|
||||
bool removeModel(const std::string& modelID);
|
||||
const BridgeModel* findModel(const std::string& modelID) const;
|
||||
std::vector<BridgeModel> listModels() const;
|
||||
|
||||
DaliBridgeResult execute(const DaliBridgeRequest& request);
|
||||
|
||||
private:
|
||||
DaliComm& comm_;
|
||||
DaliBase base_;
|
||||
DaliDT1 dt1_;
|
||||
DaliDT8 dt8_;
|
||||
std::map<std::string, BridgeModel> models_;
|
||||
|
||||
DaliBridgeResult executeResolved(const DaliBridgeRequest& request,
|
||||
const BridgeModel* model,
|
||||
BridgeOperation operation);
|
||||
std::optional<int> resolveShortAddress(const DaliBridgeRequest& request,
|
||||
const BridgeModel* model) const;
|
||||
std::optional<int> resolveRawAddress(const DaliBridgeRequest& request,
|
||||
const BridgeModel* model) const;
|
||||
std::optional<int> resolveRawCommand(const DaliBridgeRequest& request,
|
||||
const BridgeModel* model) const;
|
||||
std::optional<int> resolveIntValue(const DaliBridgeRequest& request, const BridgeModel* model) const;
|
||||
std::optional<double> resolveDoubleValue(const DaliBridgeRequest& request) const;
|
||||
};
|
||||
@@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include "model_value.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
enum class BridgeProtocolKind {
|
||||
unknown = 0,
|
||||
mqtt = 1,
|
||||
modbus = 2,
|
||||
bacnet = 3,
|
||||
};
|
||||
|
||||
enum class BridgeObjectType {
|
||||
unknown = 0,
|
||||
holdingRegister = 1,
|
||||
inputRegister = 2,
|
||||
coil = 3,
|
||||
discreteInput = 4,
|
||||
analogValue = 5,
|
||||
analogOutput = 6,
|
||||
binaryValue = 7,
|
||||
binaryOutput = 8,
|
||||
multiStateValue = 9,
|
||||
};
|
||||
|
||||
enum class BridgeOperation {
|
||||
unknown = 0,
|
||||
send = 1,
|
||||
sendExt = 2,
|
||||
query = 3,
|
||||
setBrightness = 4,
|
||||
setBrightnessPercent = 5,
|
||||
on = 6,
|
||||
off = 7,
|
||||
recallMaxLevel = 8,
|
||||
recallMinLevel = 9,
|
||||
setColorTemperature = 10,
|
||||
getBrightness = 11,
|
||||
getStatus = 12,
|
||||
getColorTemperature = 13,
|
||||
getColorStatus = 14,
|
||||
getEmergencyLevel = 15,
|
||||
getEmergencyStatus = 16,
|
||||
getEmergencyFailureStatus = 17,
|
||||
startEmergencyFunctionTest = 18,
|
||||
stopEmergencyTest = 19,
|
||||
};
|
||||
|
||||
enum class BridgeValueEncoding {
|
||||
none = 0,
|
||||
integer = 1,
|
||||
percentage = 2,
|
||||
kelvin = 3,
|
||||
};
|
||||
|
||||
struct BridgeValueTransform {
|
||||
double scale = 1.0;
|
||||
double offset = 0.0;
|
||||
std::optional<int> clampMin;
|
||||
std::optional<int> clampMax;
|
||||
|
||||
static BridgeValueTransform fromJson(const DaliValue::Object* json);
|
||||
DaliValue::Object toJson() const;
|
||||
int apply(double raw) const;
|
||||
};
|
||||
|
||||
struct BridgeExternalPoint {
|
||||
std::string network;
|
||||
std::string device;
|
||||
BridgeObjectType objectType = BridgeObjectType::unknown;
|
||||
std::optional<int> objectInstance;
|
||||
std::optional<int> registerAddress;
|
||||
std::optional<int> bitIndex;
|
||||
std::string property;
|
||||
|
||||
static BridgeExternalPoint fromJson(const DaliValue::Object* json);
|
||||
DaliValue::Object toJson() const;
|
||||
};
|
||||
|
||||
struct BridgeDaliTarget {
|
||||
std::optional<int> shortAddress;
|
||||
std::optional<int> rawAddress;
|
||||
std::optional<int> rawCommand;
|
||||
|
||||
static BridgeDaliTarget fromJson(const DaliValue::Object* json);
|
||||
DaliValue::Object toJson() const;
|
||||
};
|
||||
|
||||
struct BridgeModel {
|
||||
std::string id;
|
||||
std::string name;
|
||||
BridgeProtocolKind protocol = BridgeProtocolKind::unknown;
|
||||
BridgeExternalPoint external;
|
||||
BridgeDaliTarget dali;
|
||||
BridgeOperation operation = BridgeOperation::unknown;
|
||||
BridgeValueEncoding valueEncoding = BridgeValueEncoding::integer;
|
||||
BridgeValueTransform valueTransform;
|
||||
DaliValue::Object metadata;
|
||||
|
||||
static BridgeModel fromJson(const DaliValue::Object& json);
|
||||
DaliValue::Object toJson() const;
|
||||
std::string displayName() const;
|
||||
};
|
||||
|
||||
const char* bridgeProtocolKindToString(BridgeProtocolKind kind);
|
||||
BridgeProtocolKind bridgeProtocolKindFromString(const std::string& value);
|
||||
|
||||
const char* bridgeObjectTypeToString(BridgeObjectType type);
|
||||
BridgeObjectType bridgeObjectTypeFromString(const std::string& value);
|
||||
|
||||
const char* bridgeOperationToString(BridgeOperation operation);
|
||||
BridgeOperation bridgeOperationFromString(const std::string& value);
|
||||
|
||||
const char* bridgeValueEncodingToString(BridgeValueEncoding encoding);
|
||||
BridgeValueEncoding bridgeValueEncodingFromString(const std::string& value);
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "bacnet_bridge.hpp"
|
||||
#include "bridge_model.hpp"
|
||||
#include "modbus_bridge.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
extern "C" {
|
||||
#include "esp_err.h"
|
||||
}
|
||||
#else
|
||||
using esp_err_t = int;
|
||||
#endif
|
||||
|
||||
struct BridgeRuntimeConfig {
|
||||
std::vector<BridgeModel> models;
|
||||
std::optional<ModbusBridgeConfig> modbus;
|
||||
std::optional<BacnetBridgeConfig> bacnet;
|
||||
DaliValue::Object metadata;
|
||||
|
||||
static BridgeRuntimeConfig fromJson(const DaliValue::Object& json);
|
||||
DaliValue::Object toJson() const;
|
||||
};
|
||||
|
||||
class BridgeProvisioningStore {
|
||||
public:
|
||||
explicit BridgeProvisioningStore(std::string nvsNamespace = "dali_bridge")
|
||||
: nvsNamespace_(std::move(nvsNamespace)) {}
|
||||
|
||||
esp_err_t save(const BridgeRuntimeConfig& config) const;
|
||||
esp_err_t load(BridgeRuntimeConfig* config) const;
|
||||
esp_err_t clear() const;
|
||||
|
||||
private:
|
||||
std::string nvsNamespace_;
|
||||
};
|
||||
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.hpp"
|
||||
#include "bacnet_bridge.hpp"
|
||||
#include "bridge.hpp"
|
||||
#include "bridge_model.hpp"
|
||||
#include "bridge_provisioning.hpp"
|
||||
#include "bus_monitor.hpp"
|
||||
#include "comm.hpp"
|
||||
#include "dali_comm.hpp"
|
||||
@@ -14,6 +18,7 @@
|
||||
#include "color.hpp"
|
||||
#include "errors.hpp"
|
||||
#include "log.hpp"
|
||||
#include "modbus_bridge.hpp"
|
||||
#include "query_scheduler.hpp"
|
||||
#include "sequence.hpp"
|
||||
#include "sequence_store.hpp"
|
||||
|
||||
@@ -11,6 +11,7 @@ class ColorStatus {
|
||||
public:
|
||||
explicit ColorStatus(int status) : status_(status) {}
|
||||
|
||||
int raw() const { return status_; }
|
||||
bool xyOutOfRange() const { return (status_ & 0x01) != 0; }
|
||||
bool ctOutOfRange() const { return (status_ & 0x02) != 0; }
|
||||
bool autoCalibrationActive() const { return (status_ & 0x04) != 0; }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "bridge.hpp"
|
||||
#include "dali_comm.hpp"
|
||||
|
||||
#include <atomic>
|
||||
@@ -27,6 +28,8 @@ class DaliCloudBridge {
|
||||
bool start(const GatewayCloudConfig& config);
|
||||
void stop();
|
||||
bool isConnected() const;
|
||||
DaliBridgeEngine& bridge() { return bridge_; }
|
||||
const DaliBridgeEngine& bridge() const { return bridge_; }
|
||||
|
||||
bool publishStatus(const std::string& status);
|
||||
bool publishRegister(const std::string& payloadJson);
|
||||
@@ -49,6 +52,7 @@ class DaliCloudBridge {
|
||||
std::string topicRegister() const;
|
||||
|
||||
DaliComm& comm_;
|
||||
DaliBridgeEngine bridge_;
|
||||
GatewayCloudConfig config_;
|
||||
std::atomic<bool> connected_{false};
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "bridge.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct ModbusBridgeConfig {
|
||||
std::string transport = "tcp";
|
||||
std::string host;
|
||||
uint16_t port = 502;
|
||||
uint8_t unitID = 1;
|
||||
};
|
||||
|
||||
struct ModbusRegisterBinding {
|
||||
std::string modelID;
|
||||
int registerAddress = -1;
|
||||
};
|
||||
|
||||
class DaliModbusBridge {
|
||||
public:
|
||||
explicit DaliModbusBridge(DaliBridgeEngine& engine);
|
||||
|
||||
void setConfig(const ModbusBridgeConfig& config);
|
||||
const ModbusBridgeConfig& config() const;
|
||||
|
||||
DaliBridgeResult handleHoldingRegisterWrite(int registerAddress, int value) const;
|
||||
std::optional<ModbusRegisterBinding> findHoldingRegister(int registerAddress) const;
|
||||
std::vector<ModbusRegisterBinding> describeHoldingRegisters() const;
|
||||
|
||||
private:
|
||||
DaliBridgeEngine& engine_;
|
||||
ModbusBridgeConfig config_;
|
||||
};
|
||||
Reference in New Issue
Block a user