Mqttitem: value type autodetection
This commit is contained in:
parent
7c96b87a11
commit
ff07551a59
6 changed files with 560 additions and 12 deletions
|
|
@ -101,6 +101,7 @@ void MqttItem::onDevicesMessageReceived(const QMqttMessage& message)
|
|||
{
|
||||
loadExposeFromDevice(device);
|
||||
exposeLoaded_ = true;
|
||||
Q_EMIT exposeLoaded();
|
||||
|
||||
// Unsubscribe from devices topic since we found our device
|
||||
std::shared_ptr<MqttClient> workClient = client.lock();
|
||||
|
|
@ -293,6 +294,30 @@ void MqttItem::setFromExpose(const QJsonObject& expose)
|
|||
hashId();
|
||||
}
|
||||
|
||||
void MqttItem::triggerExposeLookup()
|
||||
{
|
||||
if(exposeLoaded_)
|
||||
return;
|
||||
|
||||
std::shared_ptr<MqttClient> workClient = client.lock();
|
||||
if(!workClient)
|
||||
return;
|
||||
|
||||
// Reset expose loaded flag to allow re-detection
|
||||
exposeLoaded_ = false;
|
||||
|
||||
// Subscribe to bridge/devices
|
||||
if(devicesSubscription)
|
||||
{
|
||||
disconnect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived);
|
||||
workClient->unsubscribe(devicesSubscription);
|
||||
devicesSubscription = nullptr;
|
||||
}
|
||||
|
||||
devicesSubscription = workClient->subscribe(workClient->getBaseTopic() + "/bridge/devices");
|
||||
connect(devicesSubscription->subscription, &QMqttSubscription::messageReceived, this, &MqttItem::onDevicesMessageReceived);
|
||||
}
|
||||
|
||||
QString MqttItem::getTopic() const
|
||||
{
|
||||
return topic_;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ class QString;
|
|||
class MqttItem : public Item
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_SIGNALS:
|
||||
void exposeLoaded();
|
||||
|
||||
public:
|
||||
inline static std::weak_ptr<MqttClient> client;
|
||||
|
||||
|
|
@ -51,6 +54,9 @@ public:
|
|||
// Configure from Zigbee2MQTT expose info
|
||||
void setFromExpose(const QJsonObject& expose);
|
||||
|
||||
// Trigger expose lookup from bridge/devices
|
||||
void triggerExposeLookup();
|
||||
|
||||
QString getTopic() const;
|
||||
QString getValueKey() const;
|
||||
QString getValueOn() const;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "mqttitemsettingswidget.h"
|
||||
#include "ui_mqttitemsettingswidget.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QDebug>
|
||||
|
||||
MqttItemSettingsWidget::MqttItemSettingsWidget(std::weak_ptr<MqttItem> item, QWidget *parent) :
|
||||
|
|
@ -12,20 +13,90 @@ MqttItemSettingsWidget::MqttItemSettingsWidget(std::weak_ptr<MqttItem> item, QWi
|
|||
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
suppressUpdates_ = true;
|
||||
ui->lineEdit_topic->setText(workingItem->getTopic());
|
||||
ui->lineEdit_valueKey->setText(workingItem->getValueKey());
|
||||
ui->lineEdit_valueOn->setText(workingItem->getValueOn());
|
||||
ui->lineEdit_valueOff->setText(workingItem->getValueOff());
|
||||
ui->spinBox_min->setValue(workingItem->getValueMin());
|
||||
ui->spinBox_max->setValue(workingItem->getValueMax());
|
||||
ui->spinBox_step->setValue(workingItem->getValueStep());
|
||||
|
||||
// Set value type combo
|
||||
switch(workingItem->getValueType())
|
||||
{
|
||||
case ITEM_VALUE_UINT:
|
||||
ui->comboBox_valueType->setCurrentIndex(1);
|
||||
break;
|
||||
case ITEM_VALUE_ENUM:
|
||||
ui->comboBox_valueType->setCurrentIndex(2);
|
||||
break;
|
||||
default:
|
||||
ui->comboBox_valueType->setCurrentIndex(0);
|
||||
break;
|
||||
}
|
||||
|
||||
updateValueNamesFromItem();
|
||||
suppressUpdates_ = false;
|
||||
updateVisibility();
|
||||
|
||||
// Connect expose loaded signal
|
||||
connect(workingItem.get(), &MqttItem::exposeLoaded, this, [this]() {
|
||||
if(auto item = item_.lock())
|
||||
{
|
||||
suppressUpdates_ = true;
|
||||
ui->label_status->setText("Detected!");
|
||||
|
||||
// Update value type
|
||||
switch(item->getValueType())
|
||||
{
|
||||
case ITEM_VALUE_UINT:
|
||||
ui->comboBox_valueType->setCurrentIndex(1);
|
||||
break;
|
||||
case ITEM_VALUE_ENUM:
|
||||
ui->comboBox_valueType->setCurrentIndex(2);
|
||||
break;
|
||||
default:
|
||||
ui->comboBox_valueType->setCurrentIndex(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Update limits
|
||||
ui->spinBox_min->setValue(item->getValueMin());
|
||||
ui->spinBox_max->setValue(item->getValueMax());
|
||||
ui->spinBox_step->setValue(item->getValueStep());
|
||||
|
||||
// Update value on/off
|
||||
ui->lineEdit_valueOn->setText(item->getValueOn());
|
||||
ui->lineEdit_valueOff->setText(item->getValueOff());
|
||||
|
||||
// Update value names
|
||||
updateValueNamesFromItem();
|
||||
suppressUpdates_ = false;
|
||||
updateVisibility();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Connect signals
|
||||
connect(ui->lineEdit_topic, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setTopic);
|
||||
connect(ui->lineEdit_valueKey, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueKey);
|
||||
connect(ui->lineEdit_valueOn, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueOn);
|
||||
connect(ui->lineEdit_valueOff, &QLineEdit::textChanged, this, &MqttItemSettingsWidget::setValueOff);
|
||||
connect(ui->comboBox_valueType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MqttItemSettingsWidget::setValueType);
|
||||
connect(ui->spinBox_min, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueMin);
|
||||
connect(ui->spinBox_max, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueMax);
|
||||
connect(ui->spinBox_step, &QSpinBox::valueChanged, this, &MqttItemSettingsWidget::setValueStep);
|
||||
connect(ui->pushButton_autoDetect, &QPushButton::clicked, this, &MqttItemSettingsWidget::onAutoDetectClicked);
|
||||
connect(ui->pushButton_addValueName, &QPushButton::clicked, this, &MqttItemSettingsWidget::onAddValueName);
|
||||
connect(ui->pushButton_removeValueName, &QPushButton::clicked, this, &MqttItemSettingsWidget::onRemoveValueName);
|
||||
connect(ui->listWidget_valueNames, &QListWidget::itemChanged, this, &MqttItemSettingsWidget::onValueNamesChanged);
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::setTopic(const QString& topic)
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
workingItem->setTopic(topic);
|
||||
|
|
@ -34,6 +105,8 @@ void MqttItemSettingsWidget::setTopic(const QString& topic)
|
|||
|
||||
void MqttItemSettingsWidget::setValueKey(const QString& valueKey)
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
workingItem->setValueKey(valueKey);
|
||||
|
|
@ -42,6 +115,8 @@ void MqttItemSettingsWidget::setValueKey(const QString& valueKey)
|
|||
|
||||
void MqttItemSettingsWidget::setValueOn(const QString& valueOn)
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
workingItem->setValueOn(valueOn);
|
||||
|
|
@ -50,12 +125,147 @@ void MqttItemSettingsWidget::setValueOn(const QString& valueOn)
|
|||
|
||||
void MqttItemSettingsWidget::setValueOff(const QString& valueOff)
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
workingItem->setValueOff(valueOff);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::setValueType(int index)
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
item_value_type_t type;
|
||||
switch(index)
|
||||
{
|
||||
case 1: type = ITEM_VALUE_UINT; break;
|
||||
case 2: type = ITEM_VALUE_ENUM; break;
|
||||
default: type = ITEM_VALUE_BOOL; break;
|
||||
}
|
||||
workingItem->setValueType(type);
|
||||
updateVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::setValueMin(int min)
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
workingItem->setValueMin(min);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::setValueMax(int max)
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
workingItem->setValueMax(max);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::setValueStep(int step)
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
workingItem->setValueStep(step);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::onAutoDetectClicked()
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
ui->label_status->setText("Detecting...");
|
||||
workingItem->triggerExposeLookup();
|
||||
}
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::onAddValueName()
|
||||
{
|
||||
bool ok;
|
||||
QString name = QInputDialog::getText(this, "Add Value Name", "Enter value name:", QLineEdit::Normal, "", &ok);
|
||||
if(ok && !name.isEmpty())
|
||||
{
|
||||
ui->listWidget_valueNames->addItem(name);
|
||||
syncValueNamesToItem();
|
||||
}
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::onRemoveValueName()
|
||||
{
|
||||
delete ui->listWidget_valueNames->currentItem();
|
||||
syncValueNamesToItem();
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::onValueNamesChanged()
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
syncValueNamesToItem();
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::syncValueNamesToItem()
|
||||
{
|
||||
if(suppressUpdates_)
|
||||
return;
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
std::vector<QString> names;
|
||||
for(int i = 0; i < ui->listWidget_valueNames->count(); ++i)
|
||||
{
|
||||
names.push_back(ui->listWidget_valueNames->item(i)->text());
|
||||
}
|
||||
workingItem->setValueNames(names);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::updateVisibility()
|
||||
{
|
||||
int typeIndex = ui->comboBox_valueType->currentIndex();
|
||||
|
||||
// Bool controls
|
||||
ui->label_valueOn->setVisible(typeIndex == 0);
|
||||
ui->lineEdit_valueOn->setVisible(typeIndex == 0);
|
||||
ui->label_valueOff->setVisible(typeIndex == 0);
|
||||
ui->lineEdit_valueOff->setVisible(typeIndex == 0);
|
||||
|
||||
// UInt controls
|
||||
ui->label_min->setVisible(typeIndex == 1);
|
||||
ui->spinBox_min->setVisible(typeIndex == 1);
|
||||
ui->label_max->setVisible(typeIndex == 1);
|
||||
ui->spinBox_max->setVisible(typeIndex == 1);
|
||||
ui->label_step->setVisible(typeIndex == 1);
|
||||
ui->spinBox_step->setVisible(typeIndex == 1);
|
||||
|
||||
// Enum controls
|
||||
ui->label_valueNames->setVisible(typeIndex == 2);
|
||||
ui->listWidget_valueNames->setVisible(typeIndex == 2);
|
||||
ui->pushButton_addValueName->setVisible(typeIndex == 2);
|
||||
ui->pushButton_removeValueName->setVisible(typeIndex == 2);
|
||||
}
|
||||
|
||||
void MqttItemSettingsWidget::updateValueNamesFromItem()
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
ui->listWidget_valueNames->clear();
|
||||
for(const QString& name : workingItem->getValueNames())
|
||||
{
|
||||
ui->listWidget_valueNames->addItem(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MqttItemSettingsWidget::~MqttItemSettingsWidget()
|
||||
{
|
||||
delete ui;
|
||||
|
|
|
|||
|
|
@ -14,12 +14,21 @@ class MqttItemSettingsWidget : public QWidget
|
|||
{
|
||||
Q_OBJECT
|
||||
std::weak_ptr<MqttItem> item_;
|
||||
bool suppressUpdates_ = false;
|
||||
|
||||
private slots:
|
||||
void setTopic(const QString& topic);
|
||||
void setValueKey(const QString& valueKey);
|
||||
void setValueOn(const QString& valueOn);
|
||||
void setValueOff(const QString& valueOff);
|
||||
void setValueType(int index);
|
||||
void setValueMin(int min);
|
||||
void setValueMax(int max);
|
||||
void setValueStep(int step);
|
||||
void onAutoDetectClicked();
|
||||
void onAddValueName();
|
||||
void onRemoveValueName();
|
||||
void onValueNamesChanged();
|
||||
|
||||
public:
|
||||
explicit MqttItemSettingsWidget(std::weak_ptr<MqttItem> item, QWidget *parent = nullptr);
|
||||
|
|
@ -27,6 +36,9 @@ public:
|
|||
|
||||
private:
|
||||
Ui::MqttItemSettingsWidget *ui;
|
||||
void updateVisibility();
|
||||
void updateValueNamesFromItem();
|
||||
void syncValueNamesToItem();
|
||||
};
|
||||
|
||||
#endif // MQTTITEMSETTINGSWIDGET_H
|
||||
|
|
@ -6,14 +6,15 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>216</height>
|
||||
<width>450</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<!-- Topic -->
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_topic">
|
||||
<property name="topMargin">
|
||||
|
|
@ -29,12 +30,13 @@
|
|||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_topic">
|
||||
<property name="placeholderText">
|
||||
<string>e.g., kitchen/light</string>
|
||||
<string>e.g., 0xa4c138ef510950e3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<!-- Value Key -->
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_valueKey">
|
||||
<property name="topMargin">
|
||||
|
|
@ -53,12 +55,66 @@
|
|||
<string>state</string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>e.g., state, brightness</string>
|
||||
<string>e.g., state, system_mode, brightness</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<!-- Auto-detect Button -->
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_autoDetect">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_autoDetect">
|
||||
<property name="text">
|
||||
<string>Auto-detect from bridge/devices</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_status">
|
||||
<property name="text">
|
||||
<string></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<!-- Value Type -->
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_valueType">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_valueType">
|
||||
<property name="text">
|
||||
<string>Value Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_valueType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bool</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Unsigned Int</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enum</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<!-- Value On/Off (for Bool) -->
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_valueOn">
|
||||
<property name="topMargin">
|
||||
|
|
@ -78,13 +134,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_valueOff">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_valueOff">
|
||||
<property name="text">
|
||||
|
|
@ -101,8 +150,132 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<!-- Min/Max/Step (for UInt) -->
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_limits">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_min">
|
||||
<property name="text">
|
||||
<string>Min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox_min">
|
||||
<property name="minimum">
|
||||
<number>-999999</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_max">
|
||||
<property name="text">
|
||||
<string>Max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox_max">
|
||||
<property name="minimum">
|
||||
<number>-999999</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_step">
|
||||
<property name="text">
|
||||
<string>Step:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox_step">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<!-- Value Names (for Enum) -->
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_valueNames">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_valueNames">
|
||||
<property name="text">
|
||||
<string>Value Names:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listWidget_valueNames">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_valueNamesButtons">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_addValueName">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_removeValueName">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
</ui>
|
||||
Loading…
Add table
Add a link
Reference in a new issue