Skip to content

Commit

Permalink
Improve support for Eurotronics Spirit SPZB0001 thermostat
Browse files Browse the repository at this point in the history
Issue #1098

* ZCLDB: add manufacturer specific attributes from official documentation
* Only use reporting to update attributes
* Fix state.on shall be true, when heating is active
* Update config.heatsetpoint when it is changed manually on the device
* Remove unsupported schedules attributes for this thermostat
  • Loading branch information
manup committed Feb 1, 2019
1 parent 7be0f15 commit 2e2a389
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 10 deletions.
11 changes: 9 additions & 2 deletions database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3079,9 +3079,16 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c
item = sensor.addItem(DataTypeInt16, RConfigOffset);
item->setValue(0);
sensor.addItem(DataTypeInt16, RConfigHeating); // Heating set point
sensor.addItem(DataTypeBool, RConfigSchedulerOn); // Scheduler state on/off
sensor.addItem(DataTypeBool, RStateOn); // Heating on/off
sensor.addItem(DataTypeString, RConfigScheduler); // Scheduler setting
if (sensor.modelId().startsWith(QLatin1String("SPZB")))
{
// Eurotronic Spirit
}
else
{
sensor.addItem(DataTypeBool, RConfigSchedulerOn); // Scheduler state on/off
sensor.addItem(DataTypeString, RConfigScheduler); // Scheduler setting
}
}

if (sensor.modelId().startsWith(QLatin1String("RWL02"))) // Hue dimmer switch
Expand Down
17 changes: 14 additions & 3 deletions de_web_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4181,9 +4181,16 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const SensorFi
item = sensorNode.addItem(DataTypeInt16, RConfigOffset);
item->setValue(0);
sensorNode.addItem(DataTypeInt16, RConfigHeating); // Heating set point
sensorNode.addItem(DataTypeBool, RConfigSchedulerOn); // Scheduler state on/off
sensorNode.addItem(DataTypeBool, RStateOn); // Heating on/off
sensorNode.addItem(DataTypeString, RConfigScheduler); // Scheduler setting
if (modelId.startsWith(QLatin1String("SPZB")))
{
// Eurotronic Spirit
}
else
{
sensorNode.addItem(DataTypeBool, RConfigSchedulerOn); // Scheduler state on/off
sensorNode.addItem(DataTypeString, RConfigScheduler); // Scheduler setting
}
}

if (node->nodeDescriptor().manufacturerCode() == VENDOR_DDEL)
Expand Down Expand Up @@ -13470,7 +13477,11 @@ void DeRestPlugin::idleTimerFired()
{
val = sensorNode->getZclValue(*ci, 0x0029); // heating state

if (!val.timestamp.isValid() || val.timestamp.secsTo(now) > 600)
if (sensorNode->modelId().startsWith("SPZB")) // Eurotronic Spirit
{
// supports reporting, no need to read attributes
}
else if (!val.timestamp.isValid() || val.timestamp.secsTo(now) > 600)
{
sensorNode->enableRead(READ_THERMOSTAT_STATE);
sensorNode->setLastRead(READ_THERMOSTAT_STATE, d->idleTotalCounter);
Expand Down
25 changes: 23 additions & 2 deletions general.xml
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@
<attribute id="0x0009" name="Unknown 2" type="enum8" access="r" required="o" >
<description>IKEA control outlet specific.</description>
</attribute>
<attribute id="0x000a" name="IKEA type" type="ostring" access="r" required="o" >
<description>IKEA type as printed on the product.</description>
<attribute id="0x000a" name="Product code" type="ostring" access="r" required="o" >
<description>As printed on the product.</description>
</attribute>
<attribute id="0x4000" name="SW Build ID" type="cstring" access="r" required="o" range="0,16"></attribute>
<attribute id="0xff0d" name="Xiaomi Sensitivity" type="u8" access="rw" required="o" mfcode="0x115f"></attribute>
Expand Down Expand Up @@ -1425,6 +1425,27 @@ Note: It does not clear or delete previous weekly schedule programming configura
<value name="Fan 3rd Stage State On" value="6"></value>
</attribute>
</attribute-set>
<!-- Eurotronic manufacturer specific -->
<attribute-set id="0x4000" description="Eurotronic">
<attribute id="0x4000" name="TRV Mode" type="enum8" default="0x02" access="rw" required="m" mfcode="0x1037">
<value name="Unknown 1" value="0"></value>
<value name="Unknown 2" value="1"></value>
<value name="manual" value="2"></value>
</attribute>
<attribute id="0x4001" name="Set Valve Position" type="u8" default="0x00" access="rw" required="m" mfcode="0x1037"></attribute>
<attribute id="0x4002" name="Errors" type="u8" default="0x00" access="r" required="m" mfcode="0x1037">
<value name="Reserved" value="0"></value>
<value name="Reserved" value="1"></value>
<value name="Reserved" value="2"></value>
<value name="Valve Adaption Failed (E1)" value="3"></value>
<value name="Valve Movement too slow (E2)" value="4"></value>
<value name="Valve not Moving (E3)" value="5"></value>
<value name="Reserved" value="6"></value>
<value name="Reserved" value="7"></value>
</attribute>
<attribute id="0x4003" name="Current Temperature Setpoint" type="s16" default="0x07d0" access="rw" required="m" mfcode="0x1037"></attribute>
<attribute id="0x4008" name="Host Flags" type="u24" default="0x000000" showas="hex" access="rw" required="m" mfcode="0x1037"></attribute>
</attribute-set>
<command id="0x00" dir="recv" name="Setpoint Raise/Lower" required="m">
<description>This command increases (or decreases) the setpoint(s) by amount, in steps of 0.1°C.</description>
<payload>
Expand Down
39 changes: 36 additions & 3 deletions thermostat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,17 @@ void DeRestPluginPrivate::handleThermostatClusterIndication(const deCONZ::ApsDat
}
break;

case 0x0008: // Pi Heating Demand
item = sensor->item(RStateOn);
if (item)
{
item->setValue(attr.numericValue().u8 > 0);
Event e(RSensors, RStateOn, sensor->id(), item);
enqueueEvent(e);
sensor->setZclValue(updateType, THERMOSTAT_CLUSTER_ID, 0x0008, attr.numericValue());
}
break;

case 0x0010: // Local Temperature Calibration (offset in 0.1 °C steps, from -2,5 °C to +2,5 °C)
item = sensor->item(RConfigOffset);
if (item)
Expand Down Expand Up @@ -213,9 +224,31 @@ void DeRestPluginPrivate::handleThermostatClusterIndication(const deCONZ::ApsDat
break;

// manufacturerspecific reported by Eurotronic SPZB0001
case 0x4002: // U8 (0x20): value 0x00
case 0x4003: // S16 (0x29): 2300
case 0x4008: // U24 (0x22): 0x000001
// https://eurotronic.org/wp-content/uploads/2019/01/Spirit_ZigBee_BAL_web_DE_view_V9.pdf
case 0x4003: // Current temperature set point
{ // this will be reported when manually changing the temperature
if (sensor->modelId().startsWith(QLatin1String("SPZB")))
{
item = sensor->item(RConfigHeating);
if (item)
{
item->setValue(attr.numericValue().s16);
Event e(RSensors, RConfigHeating, sensor->id(), item);
enqueueEvent(e);

if (item->toNumber() != item->toNumberPrevious())
{
sensor->setNeedSaveDatabase(true);
}
}
}
}
break;

case 0x4000: // enum8 (0x30): value 0x02, TRV mode
case 0x4001: // U8 (0x20): value 0x00, valve position
case 0x4002: // U8 (0x20): value 0x00, errors
case 0x4008: // U24 (0x22): 0x000001, host flags
{
if (zclFrame.manufacturerCode() == VENDOR_JENNIC)
{
Expand Down

0 comments on commit 2e2a389

Please sign in to comment.