Add step size to StateType and ParamType

This commit is contained in:
Simon Stürz 2026-01-07 16:52:35 +01:00
parent 6a84144d66
commit f760f85c98
14 changed files with 76 additions and 39 deletions

View File

@ -832,6 +832,7 @@ ParamType *ThingManager::unpackParamType(const QVariantMap &paramTypeMap, QObjec
paramType->setDefaultValue(paramTypeMap.value("defaultValue")); paramType->setDefaultValue(paramTypeMap.value("defaultValue"));
paramType->setMinValue(paramTypeMap.value("minValue")); paramType->setMinValue(paramTypeMap.value("minValue"));
paramType->setMaxValue(paramTypeMap.value("maxValue")); paramType->setMaxValue(paramTypeMap.value("maxValue"));
paramType->setStepSize(paramTypeMap.value("stepSize").toDouble());
paramType->setAllowedValues(paramTypeMap.value("allowedValues").toList()); paramType->setAllowedValues(paramTypeMap.value("allowedValues").toList());
paramType->setInputType(stringToInputType(paramTypeMap.value("inputType").toString())); paramType->setInputType(stringToInputType(paramTypeMap.value("inputType").toString()));
paramType->setReadOnly(paramTypeMap.value("readOnly").toBool()); paramType->setReadOnly(paramTypeMap.value("readOnly").toBool());
@ -858,6 +859,7 @@ StateType *ThingManager::unpackStateType(const QVariantMap &stateTypeMap, QObjec
stateType->setType(stateTypeMap.value("type").toString()); stateType->setType(stateTypeMap.value("type").toString());
stateType->setMinValue(stateTypeMap.value("minValue")); stateType->setMinValue(stateTypeMap.value("minValue"));
stateType->setMaxValue(stateTypeMap.value("maxValue")); stateType->setMaxValue(stateTypeMap.value("maxValue"));
stateType->setStepSize(stateTypeMap.value("stepSize").toDouble());
stateType->setUnit(stringToUnit(stateTypeMap.value("unit").toString())); stateType->setUnit(stringToUnit(stateTypeMap.value("unit").toString()));
QMetaEnum metaEnum = QMetaEnum::fromType<Types::IOType>(); QMetaEnum metaEnum = QMetaEnum::fromType<Types::IOType>();

View File

@ -24,20 +24,19 @@
#include "paramtype.h" #include "paramtype.h"
ParamType::ParamType(QObject *parent) : ParamType::ParamType(QObject *parent)
QObject(parent) : QObject(parent)
{ {
m_readOnly = false; m_readOnly = false;
} }
ParamType::ParamType(const QString &name, const QVariant::Type type, const QVariant &defaultValue, QObject *parent) : ParamType::ParamType(const QString &name, const QVariant::Type type, const QVariant &defaultValue, QObject *parent)
QObject(parent), : QObject(parent)
m_name(name), , m_name(name)
m_type(QVariant::typeToName(type)), , m_type(QVariant::typeToName(type))
m_defaultValue(defaultValue), , m_defaultValue(defaultValue)
m_readOnly(false) , m_readOnly(false)
{ {}
}
QUuid ParamType::id() const QUuid ParamType::id() const
{ {
@ -119,6 +118,16 @@ void ParamType::setMaxValue(const QVariant &maxValue)
m_maxValue = maxValue; m_maxValue = maxValue;
} }
double ParamType::stepSize() const
{
return m_stepSize;
}
void ParamType::setStepSize(double stepSize)
{
m_stepSize = stepSize;
}
Types::InputType ParamType::inputType() const Types::InputType ParamType::inputType() const
{ {
return m_inputType; return m_inputType;

View File

@ -25,10 +25,10 @@
#ifndef PARAMTYPE_H #ifndef PARAMTYPE_H
#define PARAMTYPE_H #define PARAMTYPE_H
#include <QVariant>
#include <QObject>
#include <QDebug> #include <QDebug>
#include <QObject>
#include <QUuid> #include <QUuid>
#include <QVariant>
#include "types.h" #include "types.h"
@ -43,6 +43,7 @@ class ParamType : public QObject
Q_PROPERTY(QVariant defaultValue READ defaultValue CONSTANT) Q_PROPERTY(QVariant defaultValue READ defaultValue CONSTANT)
Q_PROPERTY(QVariant minValue READ minValue CONSTANT) Q_PROPERTY(QVariant minValue READ minValue CONSTANT)
Q_PROPERTY(QVariant maxValue READ maxValue CONSTANT) Q_PROPERTY(QVariant maxValue READ maxValue CONSTANT)
Q_PROPERTY(double stepSize READ stepSize CONSTANT)
Q_PROPERTY(Types::InputType inputType READ inputType CONSTANT) Q_PROPERTY(Types::InputType inputType READ inputType CONSTANT)
Q_PROPERTY(Types::Unit unit READ unit CONSTANT) Q_PROPERTY(Types::Unit unit READ unit CONSTANT)
Q_PROPERTY(QVariantList allowedValues READ allowedValues CONSTANT) Q_PROPERTY(QVariantList allowedValues READ allowedValues CONSTANT)
@ -76,6 +77,9 @@ public:
QVariant maxValue() const; QVariant maxValue() const;
void setMaxValue(const QVariant &maxValue); void setMaxValue(const QVariant &maxValue);
double stepSize() const;
void setStepSize(double stepSize);
Types::InputType inputType() const; Types::InputType inputType() const;
void setInputType(const Types::InputType &inputType); void setInputType(const Types::InputType &inputType);
@ -97,6 +101,7 @@ private:
QVariant m_defaultValue; QVariant m_defaultValue;
QVariant m_minValue; QVariant m_minValue;
QVariant m_maxValue; QVariant m_maxValue;
double m_stepSize = 0;
Types::InputType m_inputType; Types::InputType m_inputType;
Types::Unit m_unit; Types::Unit m_unit;
QVariantList m_allowedValues; QVariantList m_allowedValues;

View File

@ -24,10 +24,9 @@
#include "statetype.h" #include "statetype.h"
StateType::StateType(QObject *parent) : StateType::StateType(QObject *parent)
QObject(parent) : QObject(parent)
{ {}
}
QUuid StateType::id() const QUuid StateType::id() const
{ {
@ -147,6 +146,16 @@ void StateType::setMaxValue(const QVariant &maxValue)
m_maxValue = maxValue; m_maxValue = maxValue;
} }
double StateType::stepSize() const
{
return m_stepSize;
}
void StateType::setStepSize(double stepSize)
{
m_stepSize = stepSize;
}
Types::IOType StateType::ioType() const Types::IOType StateType::ioType() const
{ {
return m_ioType; return m_ioType;

View File

@ -25,9 +25,9 @@
#ifndef STATETYPE_H #ifndef STATETYPE_H
#define STATETYPE_H #define STATETYPE_H
#include <QVariant>
#include <QObject> #include <QObject>
#include <QUuid> #include <QUuid>
#include <QVariant>
#include "types.h" #include "types.h"
@ -47,6 +47,7 @@ class StateType : public QObject
Q_PROPERTY(Types::IOType ioType READ ioType CONSTANT) Q_PROPERTY(Types::IOType ioType READ ioType CONSTANT)
Q_PROPERTY(QVariant minValue READ minValue CONSTANT) Q_PROPERTY(QVariant minValue READ minValue CONSTANT)
Q_PROPERTY(QVariant maxValue READ maxValue CONSTANT) Q_PROPERTY(QVariant maxValue READ maxValue CONSTANT)
Q_PROPERTY(double stepSize READ stepSize CONSTANT)
public: public:
StateType(QObject *parent = nullptr); StateType(QObject *parent = nullptr);
@ -87,6 +88,9 @@ public:
QVariant maxValue() const; QVariant maxValue() const;
void setMaxValue(const QVariant &maxValue); void setMaxValue(const QVariant &maxValue);
double stepSize() const;
void setStepSize(double stepSize);
private: private:
QUuid m_id; QUuid m_id;
QString m_name; QString m_name;
@ -100,6 +104,7 @@ private:
Types::IOType m_ioType = Types::IOTypeNone; Types::IOType m_ioType = Types::IOTypeNone;
QVariant m_minValue; QVariant m_minValue;
QVariant m_maxValue; QVariant m_maxValue;
double m_stepSize = 0;
}; };
#endif // STATETYPE_H #endif // STATETYPE_H

View File

@ -73,8 +73,8 @@ Item {
Connections { Connections {
target: engine.thingManager target: engine.thingManager
onExecuteActionReply: { onExecuteActionReply: (commandId, thingError, displayMessage) => {
if (commandId == d.pendingCallId) { if (commandId === d.pendingCallId) {
if (thingError !== Thing.ThingErrorNoError) { if (thingError !== Thing.ThingErrorNoError) {
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml")); var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
var dialogParams = {} var dialogParams = {}

View File

@ -38,7 +38,8 @@ Item {
property color color: Style.accentColor property color color: Style.accentColor
property bool on: true property bool on: true
property int precision: 1 property real precision: 1
property real linePrecision: 1
readonly property State progressState: thing ? thing.states.getState(stateType.id) : null readonly property State progressState: thing ? thing.states.getState(stateType.id) : null
readonly property State powerState: thing ? thing.stateByName("power") : null readonly property State powerState: thing ? thing.stateByName("power") : null
@ -46,8 +47,10 @@ Item {
property int startAngle: 135 property int startAngle: 135
property int maxAngle: 270 property int maxAngle: 270
readonly property int steps: canvas.roundToPrecision(root.progressState.maxValue - root.progressState.minValue) / root.precision + 1 readonly property int steps: canvas.roundToPrecision(root.progressState.maxValue - root.progressState.minValue) / root.precision + 1
readonly property int lineSteps: canvas.roundToPrecision(root.progressState.maxValue - root.progressState.minValue, root.linePrecision) / root.linePrecision + 1
readonly property double stepSize: (root.progressState.maxValue - root.progressState.minValue) / steps readonly property double stepSize: (root.progressState.maxValue - root.progressState.minValue) / steps
readonly property double anglePerStep: maxAngle / steps readonly property double anglePerStep: maxAngle / steps
readonly property double lineAnglePerStep: maxAngle / lineSteps
ActionQueue { ActionQueue {
@ -81,8 +84,9 @@ Item {
Behavior on effectColor { ColorAnimation { duration: Style.animationDuration } } Behavior on effectColor { ColorAnimation { duration: Style.animationDuration } }
onEffectColorChanged: requestPaint() onEffectColorChanged: requestPaint()
function roundToPrecision(value) { function roundToPrecision(value, precision) {
var tmp = Math.round(value / root.precision) * root.precision; var effectivePrecision = precision === undefined ? root.precision : precision;
var tmp = Math.round(value / effectivePrecision) * effectivePrecision;
return tmp; return tmp;
} }
@ -94,19 +98,20 @@ Item {
// Step lines // Step lines
var currentValue = actionQueue.pendingValue || root.progressState.value var currentValue = actionQueue.pendingValue || root.progressState.value
var currentStep; var currentStepValue;
if (root.progressState) { if (root.progressState) {
currentStep = roundToPrecision(currentValue - root.progressState.minValue) / root.precision currentStepValue = roundToPrecision(currentValue - root.progressState.minValue, root.linePrecision)
} }
// print("* current step", currentStep, root.steps, currentValue) // print("* current step", currentStepValue, root.lineSteps, currentValue)
for(var step = 0; step < steps; step += root.precision) { for (var step = 0; step < lineSteps; step += 1) {
var angle = step * anglePerStep + startAngle; var stepValue = step * root.linePrecision
var angle = step * lineAnglePerStep + startAngle;
var innerRadius = canvas.width * 0.4 var innerRadius = canvas.width * 0.4
var outerRadius = canvas.width * 0.5 var outerRadius = canvas.width * 0.5
if (step <= currentStep) { if (stepValue <= currentStepValue) {
ctx.strokeStyle = canvas.effectColor ctx.strokeStyle = canvas.effectColor
innerRadius = canvas.width * 0.38 innerRadius = canvas.width * 0.38
ctx.lineWidth = 4; ctx.lineWidth = 4;

View File

@ -106,7 +106,7 @@ InfoPaneBase {
} }
Connections { Connections {
target: engine.thingManager target: engine.thingManager
onExecuteActionReply: { onExecuteActionReply: (commandId, thingError, displayMessage) => {
if (commandId === childLockIcon.pendingAction) { if (commandId === childLockIcon.pendingAction) {
childLockIcon.pendingAction = -1 childLockIcon.pendingAction = -1
} }

View File

@ -27,8 +27,8 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Nymea import Nymea
import "../components" import "qrc:/ui/components"
import "../utils" import "qrc:/ui/utils"
ThingPageBase { ThingPageBase {
id: root id: root
@ -36,6 +36,7 @@ ThingPageBase {
readonly property State powerState: thing.stateByName("power") readonly property State powerState: thing.stateByName("power")
readonly property State maxChargingCurrentState: thing.stateByName("maxChargingCurrent") readonly property State maxChargingCurrentState: thing.stateByName("maxChargingCurrent")
readonly property StateType maxChargingCurrentStateType: thing.thingClass.stateTypes.findByName("maxChargingCurrent") readonly property StateType maxChargingCurrentStateType: thing.thingClass.stateTypes.findByName("maxChargingCurrent")
readonly property real precision: maxChargingCurrentStateType.stepSize !== 0 ? maxChargingCurrentStateType.stepSize : 0.1
readonly property State currentPowerState: thing.stateByName("currentPower") readonly property State currentPowerState: thing.stateByName("currentPower")
readonly property State pluggedInState: thing.stateByName("pluggedIn") readonly property State pluggedInState: thing.stateByName("pluggedIn")
@ -94,6 +95,7 @@ ThingPageBase {
thing: root.thing thing: root.thing
stateName: "maxChargingCurrent" stateName: "maxChargingCurrent"
color: app.interfaceToColor("evcharger") color: app.interfaceToColor("evcharger")
precision: root.precision
on: (actionQueue.pendingValue || powerState.value) === true on: (actionQueue.pendingValue || powerState.value) === true
} }
} }

View File

@ -184,7 +184,7 @@ ThingPageBase {
Connections { Connections {
target: engine.thingManager target: engine.thingManager
onExecuteActionReply: { onExecuteActionReply: (commandId, thingError, displayMessage) => {
addUserPage.error = thingError !== Thing.ThingErrorNoError addUserPage.error = thingError !== Thing.ThingErrorNoError
var masks =[] var masks =[]
masks.push({x: 0, y: 0, width: 1, height: 1}); masks.push({x: 0, y: 0, width: 1, height: 1});

View File

@ -359,7 +359,7 @@ ThingPageBase {
} }
Connections { Connections {
target: engine.thingManager target: engine.thingManager
onExecuteActionReply: { onExecuteActionReply: (commandId, thingError, displayMessage) => {
if (stateDelegate.pendingActionId === commandId) { if (stateDelegate.pendingActionId === commandId) {
stateDelegate.pendingActionId = -1 stateDelegate.pendingActionId = -1
if (stateDelegate.valueCacheDirty) { if (stateDelegate.valueCacheDirty) {
@ -384,7 +384,7 @@ ThingPageBase {
Connections { Connections {
target: engine.thingManager target: engine.thingManager
onExecuteActionReply: { onExecuteActionReply: (commandId, thingError, displayMessage) => {
if (commandId === actionDelegate.pendingActionId) { if (commandId === actionDelegate.pendingActionId) {
pendingTimer.start(); pendingTimer.start();
actionDelegate.lastSuccess = thingError === Thing.ThingErrorNoError actionDelegate.lastSuccess = thingError === Thing.ThingErrorNoError

View File

@ -40,8 +40,8 @@ ThingPageBase {
Connections { Connections {
target: engine.thingManager target: engine.thingManager
onExecuteActionReply: { onExecuteActionReply: (commandId, thingError, displayMessage) => {
if (commandId == d.pendingAction) { if (commandId === d.pendingAction) {
d.pendingAction = -1 d.pendingAction = -1
} }
} }

View File

@ -113,7 +113,7 @@ Item {
Connections { Connections {
target: engine.thingManager target: engine.thingManager
onExecuteActionReply: { onExecuteActionReply: (commandId, thingError, displayMessage) => {
print("executeActionReply:", commandId) print("executeActionReply:", commandId)
if (commandId === d.pendingCallId) { if (commandId === d.pendingCallId) {
d.pendingCallId = -1; d.pendingCallId = -1;

View File

@ -68,8 +68,8 @@ Item {
Connections { Connections {
target: root.thing target: root.thing
onExecuteActionReply: { onExecuteActionReply: (commandId, thingError, displayMessage) => {
if (d.pendingCommand == commandId) { if (d.pendingCommand === commandId) {
// print("command finished") // print("command finished")
d.pendingCommand = -1; d.pendingCommand = -1;
if (d.queuedValue != null) { if (d.queuedValue != null) {