diff --git a/database.cpp b/database.cpp index 8085e30abf..f416ed677e 100644 --- a/database.cpp +++ b/database.cpp @@ -3669,6 +3669,7 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c // Supported with Danfoss firmware version 1.08 sensor.addItem(DataTypeBool, RConfigScheduleOn)->setValue(false); sensor.addItem(DataTypeString, RConfigSchedule); + sensor.addItem(DataTypeInt16, RConfigExternalTemperatureSensor); } else if (sensor.modelId() == QLatin1String("AC201")) // OWON AC201 Thermostat { diff --git a/de_web_plugin.cpp b/de_web_plugin.cpp index 3d394a9e3f..8f45a341da 100644 --- a/de_web_plugin.cpp +++ b/de_web_plugin.cpp @@ -6606,6 +6606,7 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const SensorFi // Supported with Danfoss firmware version 1.08 sensorNode.addItem(DataTypeBool, RConfigScheduleOn)->setValue(false); sensorNode.addItem(DataTypeString, RConfigSchedule); + sensorNode.addItem(DataTypeInt16, RConfigExternalTemperatureSensor); } else if (modelId == QLatin1String("AC201")) // OWON AC201 Thermostat { diff --git a/general.xml b/general.xml index 003c8b7912..f798863b61 100644 --- a/general.xml +++ b/general.xml @@ -1874,7 +1874,7 @@ Note: It does not clear or delete previous weekly schedule programming configura - + diff --git a/resource.cpp b/resource.cpp index 0d9e16784f..27b08516a7 100644 --- a/resource.cpp +++ b/resource.cpp @@ -143,6 +143,7 @@ const char *RConfigLevelMin = "config/levelmin"; const char *RConfigMode = "config/mode"; const char *RConfigSetValve = "config/setvalve"; const char *RConfigMountingMode = "config/mountingmode"; +const char *RConfigExternalTemperatureSensor = "config/externalsensortemp"; const char *RConfigOffset = "config/offset"; const char *RConfigOn = "config/on"; const char *RConfigPending = "config/pending"; @@ -329,6 +330,7 @@ void initResourceDescriptors() rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RConfigUsertest)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt8, RConfigWindowCoveringType)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RConfigWindowOpen)); + rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeInt16, RConfigExternalTemperatureSensor)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt8, RConfigUbisysJ1Mode)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt8, RConfigUbisysJ1WindowCoveringType)); rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt8, RConfigUbisysJ1ConfigurationAndStatus)); diff --git a/resource.h b/resource.h index 31e730695d..471ff271c5 100644 --- a/resource.h +++ b/resource.h @@ -173,6 +173,7 @@ extern const char *RConfigUrl; extern const char *RConfigUsertest; extern const char *RConfigWindowCoveringType; extern const char *RConfigWindowOpen; +extern const char *RConfigExternalTemperatureSensor; extern const char *RConfigUbisysJ1Mode; extern const char *RConfigUbisysJ1WindowCoveringType; extern const char *RConfigUbisysJ1ConfigurationAndStatus; diff --git a/rest_sensors.cpp b/rest_sensors.cpp index b606d06d33..fa4dbdff5f 100644 --- a/rest_sensors.cpp +++ b/rest_sensors.cpp @@ -1625,6 +1625,35 @@ int DeRestPluginPrivate::changeSensorConfig(const ApiRequest &req, ApiResponse & return REQ_READY_SEND; } } + else if (rid.suffix == RConfigExternalTemperatureSensor) + { + if (map[pi.key()].type() == QVariant::Double) + { + if (sensor->modelId() == QLatin1String("eTRV0100") || sensor->modelId() == QLatin1String("TRV001")) + { + qint16 externalMeasurement = map[pi.key()].toInt(&ok); + + if (addTaskThermostatReadWriteAttribute(task, deCONZ::ZclWriteAttributesId, VENDOR_DANFOSS, 0x4015, deCONZ::Zcl16BitInt, externalMeasurement)) + { + updated = true; + } + else + { + rsp.list.append(errorToMap(ERR_ACTION_ERROR, QString("/sensors/%1/config/%2").arg(id).arg(pi.key()).toHtmlEscaped(), + QString("Could not set attribute"))); + rsp.httpStatus = HttpStatusBadRequest; + return REQ_READY_SEND; + } + } + } + else + { + rsp.list.append(errorToMap(ERR_INVALID_VALUE, QString("/sensors/%1/config/%2").arg(id).arg(pi.key()).toHtmlEscaped(), + QString("invalid value, %1, for parameter %2").arg(map[pi.key()].toString()).arg(pi.key()).toHtmlEscaped())); + rsp.httpStatus = HttpStatusBadRequest; + return REQ_READY_SEND; + } + } else if (rid.suffix == RConfigSetValve) { if (map[pi.key()].type() == QVariant::Bool) diff --git a/thermostat.cpp b/thermostat.cpp index c92b6ebabc..c9289a432b 100644 --- a/thermostat.cpp +++ b/thermostat.cpp @@ -900,6 +900,31 @@ void DeRestPluginPrivate::handleThermostatClusterIndication(const deCONZ::ApsDat } break; + case 0x4015: // External Measured Room Sensor + { + if (zclFrame.manufacturerCode() == VENDOR_DANFOSS && (sensor->modelId() == QLatin1String("eTRV0100") || + sensor->modelId() == QLatin1String("TRV001"))) + { + qint16 externalMeasurement = attr.numericValue().s16; + item = sensor->item(RConfigExternalTemperatureSensor); + if (item) + { + if (updateType == NodeValue::UpdateByZclReport) + { + configUpdated = true; + } + if (item->toNumber() != externalMeasurement) + { + item->setValue(externalMeasurement); + enqueueEvent(Event(RSensors, RConfigExternalTemperatureSensor, sensor->id(), item)); + configUpdated = true; + } + } + } + sensor->setZclValue(updateType, ind.srcEndpoint(), THERMOSTAT_CLUSTER_ID, attrId, attr.numericValue()); + } + break; + default: break; }