feat(gateway): Update SDK configuration and add 485 control bridge
- Changed flash size configuration from 16MB to 4MB and updated partition table filename. - Introduced two gateway channels with UART configurations for communication. - Added support for gateway cache and startup services including BLE and Wi-Fi. - Enabled SPI RAM and configured its parameters for better memory management. - Enhanced the gateway bridge service to handle generated Modbus points more efficiently. - Refactored the gateway Modbus component to improve point management and added new methods for point description and generation. - Implemented a new Gateway485ControlBridge for handling 485 control communication with UART. - Added necessary files for the 485 control bridge including configuration and implementation. Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -257,9 +257,13 @@ bool SnapshotHasDeviceType(const DaliDomainSnapshot& snapshot, int device_type)
|
||||
}
|
||||
|
||||
std::optional<bool> SnapshotBoolValue(const DaliDomainSnapshot& snapshot,
|
||||
const std::string& key) {
|
||||
const auto found = snapshot.bools.find(key);
|
||||
return found == snapshot.bools.end() ? std::nullopt : std::optional<bool>(found->second);
|
||||
std::string_view key) {
|
||||
for (const auto& entry : snapshot.bools) {
|
||||
if (std::string_view(entry.first) == key) {
|
||||
return entry.second;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<int> SnapshotIntValue(const DaliDomainSnapshot& snapshot,
|
||||
@@ -1258,11 +1262,13 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
}
|
||||
|
||||
std::optional<DaliDomainSnapshot> diagnosticSnapshotLocked(int short_address,
|
||||
const std::string& kind) {
|
||||
std::string_view kind) {
|
||||
if (!ValidShortAddress(short_address) || kind.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const std::string key = kind + ":" + std::to_string(short_address);
|
||||
std::string key(kind.data(), kind.size());
|
||||
key += ":";
|
||||
key += std::to_string(short_address);
|
||||
const TickType_t now = xTaskGetTickCount();
|
||||
const auto cached = diagnostic_snapshot_cache.find(key);
|
||||
if (cached != diagnostic_snapshot_cache.end() &&
|
||||
@@ -1291,8 +1297,8 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
std::optional<bool> readSnapshotBoolLocked(int short_address, const std::string& kind,
|
||||
const std::string& bool_key) {
|
||||
std::optional<bool> readSnapshotBoolLocked(int short_address, std::string_view kind,
|
||||
std::string_view bool_key) {
|
||||
const auto snapshot = diagnosticSnapshotLocked(short_address, kind);
|
||||
if (!snapshot.has_value()) {
|
||||
return std::nullopt;
|
||||
@@ -1629,7 +1635,7 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
return point;
|
||||
}
|
||||
|
||||
bool shouldPublishGeneratedBacnetPointLocked(const GatewayModbusPointBinding& point) {
|
||||
bool shouldPublishGeneratedBacnetPointLocked(const GatewayModbusPoint& point) {
|
||||
if (!point.generated || point.space != GatewayModbusSpace::kDiscreteInput ||
|
||||
point.access != GatewayModbusAccess::kReadOnly ||
|
||||
!ValidShortAddress(point.short_address)) {
|
||||
@@ -1651,27 +1657,38 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
if (modbus == nullptr) {
|
||||
return bindings;
|
||||
}
|
||||
for (const auto& point : modbus->describePoints()) {
|
||||
if (!shouldPublishGeneratedBacnetPointLocked(point)) {
|
||||
std::vector<GatewayModbusPoint> generated_points;
|
||||
generated_points.reserve(192);
|
||||
for (const auto& inventory_entry : discovery_inventory) {
|
||||
if (!ValidShortAddress(inventory_entry.first)) {
|
||||
continue;
|
||||
}
|
||||
const auto* discovery = findDiscoveryEntryLocked(point.short_address);
|
||||
const auto object_instance = generatedBacnetBinaryInputInstance(point.address);
|
||||
if (discovery == nullptr || !object_instance.has_value()) {
|
||||
continue;
|
||||
generated_points.clear();
|
||||
modbus->appendGeneratedPointsForShortAddress(
|
||||
static_cast<uint8_t>(inventory_entry.first), &generated_points);
|
||||
for (const auto& point : generated_points) {
|
||||
if (!shouldPublishGeneratedBacnetPointLocked(point)) {
|
||||
continue;
|
||||
}
|
||||
const auto* discovery = findDiscoveryEntryLocked(point.short_address);
|
||||
const auto object_instance = generatedBacnetBinaryInputInstance(point.address);
|
||||
if (discovery == nullptr || !object_instance.has_value()) {
|
||||
continue;
|
||||
}
|
||||
const auto binding = modbus->describePoint(point);
|
||||
const bool out_of_service = !discovery->online;
|
||||
bindings.push_back(GatewayBacnetObjectBinding{channel.gateway_id,
|
||||
binding.id,
|
||||
binding.name,
|
||||
BridgeObjectType::binaryInput,
|
||||
object_instance.value(),
|
||||
"presentValue",
|
||||
out_of_service,
|
||||
out_of_service
|
||||
? kBacnetReliabilityCommunicationFailure
|
||||
: kBacnetReliabilityNoFaultDetected,
|
||||
true});
|
||||
}
|
||||
const bool out_of_service = !discovery->online;
|
||||
bindings.push_back(GatewayBacnetObjectBinding{channel.gateway_id,
|
||||
point.id,
|
||||
point.name,
|
||||
BridgeObjectType::binaryInput,
|
||||
object_instance.value(),
|
||||
"presentValue",
|
||||
out_of_service,
|
||||
out_of_service
|
||||
? kBacnetReliabilityCommunicationFailure
|
||||
: kBacnetReliabilityNoFaultDetected,
|
||||
true});
|
||||
}
|
||||
return bindings;
|
||||
}
|
||||
@@ -2135,47 +2152,59 @@ struct GatewayBridgeService::ChannelRuntime {
|
||||
cJSON_AddItemToArray(bindings, item);
|
||||
}
|
||||
if (modbus != nullptr) {
|
||||
for (const auto& point : modbus->describePoints()) {
|
||||
if (!shouldPublishGeneratedBacnetPointLocked(point)) {
|
||||
std::vector<GatewayModbusPoint> generated_points;
|
||||
generated_points.reserve(192);
|
||||
for (const auto& inventory_entry : discovery_inventory) {
|
||||
if (!ValidShortAddress(inventory_entry.first)) {
|
||||
continue;
|
||||
}
|
||||
const auto object_instance = generatedBacnetBinaryInputInstance(point.address);
|
||||
const auto* discovery = findDiscoveryEntryLocked(point.short_address);
|
||||
if (!object_instance.has_value() || discovery == nullptr) {
|
||||
continue;
|
||||
generated_points.clear();
|
||||
modbus->appendGeneratedPointsForShortAddress(
|
||||
static_cast<uint8_t>(inventory_entry.first), &generated_points);
|
||||
for (const auto& point : generated_points) {
|
||||
if (!shouldPublishGeneratedBacnetPointLocked(point)) {
|
||||
continue;
|
||||
}
|
||||
const auto object_instance = generatedBacnetBinaryInputInstance(point.address);
|
||||
const auto* discovery = findDiscoveryEntryLocked(point.short_address);
|
||||
if (!object_instance.has_value() || discovery == nullptr) {
|
||||
continue;
|
||||
}
|
||||
cJSON* item = cJSON_CreateObject();
|
||||
if (item == nullptr) {
|
||||
continue;
|
||||
}
|
||||
const auto binding = modbus->describePoint(point);
|
||||
cJSON_AddStringToObject(item, "model", binding.id.c_str());
|
||||
cJSON_AddStringToObject(item, "name", binding.name.c_str());
|
||||
cJSON_AddStringToObject(item, "objectType", "binaryInput");
|
||||
cJSON_AddNumberToObject(item, "objectInstance", object_instance.value());
|
||||
cJSON_AddStringToObject(item, "property", "presentValue");
|
||||
cJSON_AddBoolToObject(item, "generated", true);
|
||||
cJSON_AddStringToObject(item, "generatedKind",
|
||||
GatewayModbusGeneratedKindToString(binding.generated_kind));
|
||||
cJSON_AddNumberToObject(item, "shortAddress", binding.short_address);
|
||||
if (!binding.diagnostic_snapshot.empty()) {
|
||||
cJSON_AddStringToObject(item, "diagnosticSnapshot",
|
||||
binding.diagnostic_snapshot.c_str());
|
||||
}
|
||||
if (!binding.diagnostic_bool.empty()) {
|
||||
cJSON_AddStringToObject(item, "diagnosticBool", binding.diagnostic_bool.c_str());
|
||||
}
|
||||
if (binding.diagnostic_device_type >= 0) {
|
||||
cJSON_AddNumberToObject(item, "diagnosticDeviceType",
|
||||
binding.diagnostic_device_type);
|
||||
}
|
||||
const bool out_of_service = !discovery->online;
|
||||
cJSON_AddBoolToObject(item, "outOfService", out_of_service);
|
||||
cJSON_AddStringToObject(item, "reliability",
|
||||
BacnetReliabilityToString(out_of_service
|
||||
? kBacnetReliabilityCommunicationFailure
|
||||
: kBacnetReliabilityNoFaultDetected));
|
||||
cJSON_AddStringToObject(item, "inventoryState",
|
||||
DiscoveryStateString(discovery->online));
|
||||
cJSON_AddItemToArray(bindings, item);
|
||||
}
|
||||
cJSON* item = cJSON_CreateObject();
|
||||
if (item == nullptr) {
|
||||
continue;
|
||||
}
|
||||
cJSON_AddStringToObject(item, "model", point.id.c_str());
|
||||
cJSON_AddStringToObject(item, "name", point.name.c_str());
|
||||
cJSON_AddStringToObject(item, "objectType", "binaryInput");
|
||||
cJSON_AddNumberToObject(item, "objectInstance", object_instance.value());
|
||||
cJSON_AddStringToObject(item, "property", "presentValue");
|
||||
cJSON_AddBoolToObject(item, "generated", true);
|
||||
cJSON_AddStringToObject(item, "generatedKind",
|
||||
GatewayModbusGeneratedKindToString(point.generated_kind));
|
||||
cJSON_AddNumberToObject(item, "shortAddress", point.short_address);
|
||||
if (!point.diagnostic_snapshot.empty()) {
|
||||
cJSON_AddStringToObject(item, "diagnosticSnapshot",
|
||||
point.diagnostic_snapshot.c_str());
|
||||
}
|
||||
if (!point.diagnostic_bool.empty()) {
|
||||
cJSON_AddStringToObject(item, "diagnosticBool", point.diagnostic_bool.c_str());
|
||||
}
|
||||
if (point.diagnostic_device_type >= 0) {
|
||||
cJSON_AddNumberToObject(item, "diagnosticDeviceType",
|
||||
point.diagnostic_device_type);
|
||||
}
|
||||
const bool out_of_service = !discovery->online;
|
||||
cJSON_AddBoolToObject(item, "outOfService", out_of_service);
|
||||
cJSON_AddStringToObject(item, "reliability",
|
||||
BacnetReliabilityToString(out_of_service
|
||||
? kBacnetReliabilityCommunicationFailure
|
||||
: kBacnetReliabilityNoFaultDetected));
|
||||
cJSON_AddStringToObject(item, "inventoryState", DiscoveryStateString(discovery->online));
|
||||
cJSON_AddItemToArray(bindings, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user