Files
gateway/components/knx_dali_gw/src/knx_dali_channel.cpp
T
Tony 449a3a801a Add KNX DALI Gateway Module and Message Queue Implementation
- Introduced KnxDaliModule class for handling DALI message queuing, commissioning, and KNX group-object dispatch.
- Implemented Message and MessageQueue classes for managing message operations.
- Removed obsolete OpenKNX IDF component files and CMake configurations.
- Updated submodule reference for KNX.

Signed-off-by: Tony <tonylu@tony-cloud.com>
2026-05-15 12:34:13 +08:00

185 lines
5.4 KiB
C++

#include "knx_dali_channel.h"
#include "dali_define.hpp"
#include "knxprod.h"
#include "dali_helper.h"
#include "esp_log.h"
#include "esp_timer.h"
namespace gateway {
namespace knx_dali_gw {
KnxDaliChannel::KnxDaliChannel() = default;
KnxDaliChannel::~KnxDaliChannel() = default;
void KnxDaliChannel::init(uint8_t channel_index, bool is_group, DaliGatewayBridge& bridge) {
index_ = channel_index;
is_group_ = is_group;
dali_ = &bridge;
}
void KnxDaliChannel::setup() {
if (dali_ == nullptr) return;
// Query initial state
DaliTarget target = is_group_ ? DaliTarget{DaliTargetKind::kGroup, static_cast<int>(index_)}
: DaliTarget{DaliTargetKind::kShortAddress, static_cast<int>(index_)};
(void)target; // Will be used in full port
}
void KnxDaliChannel::loop() {
if (dali_ == nullptr) return;
loopDimming();
loopStaircase();
loopQueryLevel();
}
void KnxDaliChannel::processInputKo(GroupObject& ko) {
uint16_t asap = ko.asap();
int slot = static_cast<int>(asap) - (is_group_ ? GRP_KoOffset : ADR_KoOffset) - index_ * (is_group_ ? GRP_KoBlockSize : ADR_KoBlockSize);
// TODO: Full slot-to-handler mapping from DaliChannel.cpp
// For now, delegate to basic handlers
switch (slot) {
case 0: koHandleSwitch(ko); break;
// ... more slots
default: break;
}
}
// ---- Dimming ----
void KnxDaliChannel::loopDimming() {
if (dimm_direction_ == DimmDirection::kNone) return;
uint64_t now = esp_timer_get_time() / 1000ULL;
if (now - dimm_last_ < dimm_interval_) return;
dimm_last_ = now;
DaliTarget target = is_group_ ? DaliTarget{DaliTargetKind::kGroup, static_cast<int>(index_)}
: DaliTarget{DaliTargetKind::kShortAddress, static_cast<int>(index_)};
if (dimm_direction_ == DimmDirection::kUp) {
if (current_step_ < max_) current_step_++;
dali_->setArc(target, current_step_);
} else {
if (current_step_ > min_) current_step_--;
dali_->setArc(target, current_step_);
}
}
// ---- Staircase ----
void KnxDaliChannel::loopStaircase() {
if (interval_ == 0 || !current_state_) return;
uint64_t now = esp_timer_get_time() / 1000ULL;
if (now - start_time_ >= interval_ * 1000ULL) {
current_state_ = false;
interval_ = 0;
DaliTarget target = is_group_ ? DaliTarget{DaliTargetKind::kGroup, static_cast<int>(index_)}
: DaliTarget{DaliTargetKind::kShortAddress, static_cast<int>(index_)};
dali_->off(target);
}
}
// ---- Query Level ----
void KnxDaliChannel::loopQueryLevel() {
// Periodic status query — simplified for now
}
// ---- Switch State ----
void KnxDaliChannel::setSwitchState(bool value, bool is_switch_command) {
if (current_is_locked_) return;
current_state_ = value;
DaliTarget target = is_group_ ? DaliTarget{DaliTargetKind::kGroup, static_cast<int>(index_)}
: DaliTarget{DaliTargetKind::kShortAddress, static_cast<int>(index_)};
if (value) {
dali_->on(target);
} else {
dali_->off(target);
}
if (value) {
start_time_ = esp_timer_get_time() / 1000ULL;
}
}
// ---- Configuration setters ----
void KnxDaliChannel::setOnValue(uint8_t value) {
on_day_ = value;
on_night_ = value / 2;
}
void KnxDaliChannel::setGroups(uint16_t groups) { groups_ = groups; }
void KnxDaliChannel::setGroupState(uint8_t group, bool state) {
if (state) groups_ |= (1 << group); else groups_ &= ~(1 << group);
}
void KnxDaliChannel::setGroupState(uint8_t group, uint8_t) {}
void KnxDaliChannel::setMinMax(uint8_t min, uint8_t max) { min_ = min; max_ = max; }
void KnxDaliChannel::setMinArc(uint8_t min) { min_ = min; }
void KnxDaliChannel::setHcl(uint8_t curve, uint16_t temp, uint8_t) {
hcl_curve_ = curve;
hcl_current_temp_ = temp;
}
// ---- Dimm State ----
void KnxDaliChannel::setDimmState(uint8_t value, bool, bool) {
current_step_ = value;
}
// ---- Color ----
void KnxDaliChannel::sendColor() {
if (dali_ == nullptr) return;
dali_->setColourRGB(static_cast<int>(index_), current_color_[0],
current_color_[1], current_color_[2]);
}
// ---- KO Handlers ----
void KnxDaliChannel::koHandleSwitch(GroupObject& ko) {
bool on = static_cast<bool>(ko.value());
setSwitchState(on);
}
void KnxDaliChannel::koHandleDimmRel(GroupObject& ko) {
int step = static_cast<int>(static_cast<float>(ko.value()));
if (step > 0) {
dimm_direction_ = DimmDirection::kUp;
dimm_step_ = static_cast<uint8_t>(step);
} else if (step < 0) {
dimm_direction_ = DimmDirection::kDown;
dimm_step_ = static_cast<uint8_t>(-step);
} else {
dimm_direction_ = DimmDirection::kNone;
}
dimm_last_ = esp_timer_get_time() / 1000ULL;
}
void KnxDaliChannel::koHandleDimmAbs(GroupObject& ko) {
uint8_t value = static_cast<uint8_t>(static_cast<float>(ko.value()) * 255.0f / 100.0f);
setDimmState(value);
dimm_direction_ = DimmDirection::kNone;
DaliTarget target = is_group_ ? DaliTarget{DaliTargetKind::kGroup, static_cast<int>(index_)}
: DaliTarget{DaliTargetKind::kShortAddress, static_cast<int>(index_)};
dali_->setArc(target, value);
}
void KnxDaliChannel::koHandleLock(GroupObject& ko) {
bool lock = static_cast<bool>(ko.value());
current_is_locked_ = lock;
}
void KnxDaliChannel::koHandleColor(GroupObject& ko) {
KNXValue val = ko.value();
if (true) {
// RGB packed in float or raw bytes
// Simplified: store and send
sendColor();
}
}
} // namespace knx_dali_gw
} // namespace gateway