Skip to content

Commit

Permalink
Thermostat Cluster - moved writable settings from state to config
Browse files Browse the repository at this point in the history
  • Loading branch information
ma-ca committed Dec 5, 2018
1 parent 09551b8 commit fe255c3
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 82 deletions.
4 changes: 2 additions & 2 deletions database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2979,8 +2979,8 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c
item->setValue(0);
item = sensor.addItem(DataTypeInt16, RConfigOffset);
item->setValue(0);
sensor.addItem(DataTypeInt16, RStateHeating); // Heating set point
sensor.addItem(DataTypeBool, RStateSchedulerOn); // Scheduler state on/off
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
}
Expand Down
4 changes: 2 additions & 2 deletions de_web_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3978,8 +3978,8 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const SensorFi
sensorNode.addItem(DataTypeInt16, RStateTemperature);
item = sensorNode.addItem(DataTypeInt16, RConfigOffset);
item->setValue(0);
sensorNode.addItem(DataTypeInt16, RStateHeating); // Heating set point
sensorNode.addItem(DataTypeBool, RStateSchedulerOn); // Scheduler state on/off
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
}
Expand Down
8 changes: 4 additions & 4 deletions resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ const char *RStateDaylight = "state/daylight";
const char *RStateEffect = "state/effect";
const char *RStateFire = "state/fire";
const char *RStateFlag = "state/flag";
const char *RStateHeating = "state/heatsetpoint";
const char *RStateHue = "state/hue";
const char *RStateHumidity = "state/humidity";
const char *RStateLastUpdated = "state/lastupdated";
Expand All @@ -64,7 +63,6 @@ const char *RStatePressure = "state/pressure";
const char *RStatePower = "state/power";
const char *RStateReachable = "state/reachable";
const char *RStateSat = "state/sat";
const char *RStateSchedulerOn = "state/scheduleron";
const char *RStateStatus = "state/status";
const char *RStateTampered = "state/tampered";
const char *RStateTemperature = "state/temperature";
Expand All @@ -89,6 +87,7 @@ const char *RConfigLedIndication = "config/ledindication";
const char *RConfigLocalTime = "config/localtime";
const char *RConfigLong = "config/long";
const char *RConfigLevelMin = "config/levelmin";
const char *RConfigHeating = "config/heatsetpoint";
const char *RConfigMode = "config/mode";
const char *RConfigOffset = "config/offset";
const char *RConfigOn = "config/on";
Expand All @@ -98,6 +97,7 @@ const char *RConfigPowerOnCt = "config/poweronct";
const char *RConfigPowerOnLevel = "config/poweronlevel";
const char *RConfigReachable = "config/reachable";
const char *RConfigScheduler = "config/scheduler";
const char *RConfigSchedulerOn = "config/scheduleron";
const char *RConfigSensitivity = "config/sensitivity";
const char *RConfigSensitivityMax = "config/sensitivitymax";
const char *RConfigSunriseOffset = "config/sunriseoffset";
Expand Down Expand Up @@ -156,7 +156,6 @@ void initResourceDescriptors()
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, RStateEffect));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RStateFire));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RStateFlag));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeInt16, RStateHeating));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, RStateHue));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, RStateHumidity, 0, 10000));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeTime, RStateLastUpdated));
Expand All @@ -170,7 +169,6 @@ void initResourceDescriptors()
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeInt16, RStatePower));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RStateReachable));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt8, RStateSat));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RStateSchedulerOn));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, RActionScene));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeInt32, RStateStatus));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RStateTampered));
Expand All @@ -190,6 +188,7 @@ void initResourceDescriptors()
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, RConfigDelay));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, RConfigDuration));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, RConfigGroup));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeInt16, RConfigHeating));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt32, RConfigId));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, RConfigLat));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RConfigLedIndication));
Expand All @@ -205,6 +204,7 @@ void initResourceDescriptors()
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt16, RConfigPowerOnCt));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RConfigReachable));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeString, RConfigScheduler));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeBool, RConfigSchedulerOn));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt8, RConfigSensitivity));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeUInt8, RConfigSensitivityMax));
rItemDescriptors.emplace_back(ResourceItemDescriptor(DataTypeInt8, RConfigSunriseOffset, -120, 120));
Expand Down
4 changes: 2 additions & 2 deletions resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ extern const char *RStateDaylight;
extern const char *RStateEffect;
extern const char *RStateFire;
extern const char *RStateFlag;
extern const char *RStateHeating;
extern const char *RStateHue;
extern const char *RStateHumidity;
extern const char *RStateLastUpdated;
Expand All @@ -79,7 +78,6 @@ extern const char *RStatePressure;
extern const char *RStatePower;
extern const char *RStateReachable;
extern const char *RStateSat;
extern const char *RStateSchedulerOn;
extern const char *RStateStatus;
extern const char *RStateTampered;
extern const char *RStateTemperature;
Expand All @@ -98,6 +96,7 @@ extern const char *RConfigConfigured;
extern const char *RConfigDelay;
extern const char *RConfigDuration;
extern const char *RConfigGroup;
extern const char *RConfigHeating;
extern const char *RConfigId;
extern const char *RConfigLat;
extern const char *RConfigLedIndication;
Expand All @@ -113,6 +112,7 @@ extern const char *RConfigPowerOnCt;
extern const char *RConfigPowerOnLevel;
extern const char *RConfigReachable;
extern const char *RConfigScheduler;
extern const char *RConfigSchedulerOn;
extern const char *RConfigSensitivity;
extern const char *RConfigSensitivityMax;
extern const char *RConfigSunriseOffset;
Expand Down
91 changes: 34 additions & 57 deletions rest_sensors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,6 +1340,40 @@ int DeRestPluginPrivate::changeSensorConfig(const ApiRequest &req, ApiResponse &
return REQ_READY_SEND;
}
}
if (rid.suffix == RConfigSchedulerOn)
{
bool onoff = map[pi.key()].toBool();
uint8_t onoffAttr = onoff ? 0x01 : 0x00;

if (addTaskThermostatReadWriteAttribute(task, deCONZ::ZclWriteAttributesId, 0x0025, deCONZ::Zcl8BitBitMap, onoffAttr))
{
updated = true;
}
else
{
rsp.list.append(errorToMap(ERR_INVALID_VALUE, QString("/sensors/%1/%2").arg(id).arg(rid.suffix), QString("could not set attribute")));
rsp.httpStatus = HttpStatusBadRequest;
return REQ_READY_SEND;
}
}
else if (rid.suffix == RConfigHeating)
{
bool ok;
int16_t heatsetpoint =map[pi.key()].toUInt(&ok);

if (ok && addTaskThermostatReadWriteAttribute(task, deCONZ::ZclWriteAttributesId, 0x0012, deCONZ::Zcl16BitInt, heatsetpoint))
{
updated = true;
}
else
{
rsp.list.append(errorToMap(ERR_INVALID_VALUE,
QString("/sensors/%1/%2").arg(id).arg(rid.suffix),
QString("could not set attribute value=%1").arg(map[pi.key()].toString())));
rsp.httpStatus = HttpStatusBadRequest;
return REQ_READY_SEND;
}
}
}
}

Expand Down Expand Up @@ -1487,11 +1521,6 @@ int DeRestPluginPrivate::changeSensorState(const ApiRequest &req, ApiResponse &r

bool isClip = sensor->type().startsWith(QLatin1String("CLIP"));

if (sensor->type() == "ZHAThermostat")
{
isClip = true; // ZHAThermostat allow PUT on state
}

if (req.sock)
{
userActivity();
Expand Down Expand Up @@ -1622,58 +1651,6 @@ int DeRestPluginPrivate::changeSensorState(const ApiRequest &req, ApiResponse &r
sensor->durationDue = QDateTime::currentDateTime().addSecs(item2->toNumber()).addMSecs(-500);
}
}
else if (sensor->type() == "ZHAThermostat")
{
TaskItem task;
// set destination parameters
task.req.dstAddress() = sensor->address();
task.req.setTxOptions(deCONZ::ApsTxAcknowledgedTransmission);
task.req.setDstEndpoint(sensor->fingerPrint().endpoint);
task.req.setSrcEndpoint(getSrcEndpoint(sensor, task.req));
task.req.setDstAddressMode(deCONZ::ApsExtAddress);

if (rid.suffix == RStateSchedulerOn)
{
bool onoff = val.toBool();
uint8_t onoffAttr = onoff ? 0x01 : 0x00;

if (addTaskThermostatReadWriteAttribute(task, deCONZ::ZclWriteAttributesId, 0x0025, deCONZ::Zcl8BitBitMap, onoffAttr))
{
updated = true;
}
else
{
rsp.list.append(errorToMap(ERR_INVALID_VALUE, QString("/sensors/%1/%2").arg(id).arg(rid.suffix), QString("could not set attribute")));
rsp.httpStatus = HttpStatusBadRequest;

}
}
else if (rid.suffix == RStateHeating)
{
bool ok;
int16_t heatsetpoint =val.toUInt(&ok);

if (ok && addTaskThermostatReadWriteAttribute(task, deCONZ::ZclWriteAttributesId, 0x0012, deCONZ::Zcl16BitInt, heatsetpoint))
{
updated = true;
}
else
{
rsp.list.append(errorToMap(ERR_INVALID_VALUE,
QString("/sensors/%1/%2").arg(id).arg(rid.suffix),
QString("could not set attribute value=%1").arg(val.toString())));
rsp.httpStatus = HttpStatusBadRequest;
}
}
else
{
rsp.list.append(errorToMap(ERR_INVALID_VALUE,
QString("/sensors/%1/state/%2").arg(id).arg(pi.key()),
QString("thermostat invalid value, %1, for parameter %2").arg(rid.suffix).arg(pi.key())));
rsp.httpStatus = HttpStatusBadRequest;
return REQ_READY_SEND;
}
}
}
else // invalid
{
Expand Down
30 changes: 15 additions & 15 deletions thermostat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@
* option | read/write | attribute | description
* -------------------|------------|-----------|---------------------
* state.on | read only | 0x0029 | running state on/off
* state.heatsetpoint | read write | 0x0012 | heating setpoint
* state.scheduleron | read write | 0x0025 | scheduler on/off
* state.temperature | read only | 0x0000 | meassured temperature
* state.temperature | read only | 0x0000 | measured temperature
* config.heatsetpoint| read write | 0x0012 | heating setpoint
* config.scheduleron | read write | 0x0025 | scheduler on/off
* config.offset | read write | 0x0010 | temperature offset
* config.scheduler | read write | (command) | scheduled setpoints
*
*
* Example sensor:
*
* /api/<apike<>/sensors/<id>/
* /api/<apikey>/sensors/<id>/
* {
* config: {
* "heatsetpoint": 2200,
* "offset": 0,
* "scheduler": "Monday,Tuesday,Wednesday,Thursday,Friday 05:00 2200 19:00 1800;Saturday,Sunday 06:00 2100 19:00 1800;"
* "scheduler": "Monday,Tuesday,Wednesday,Thursday,Friday 05:00 2200 19:00 1800;Saturday,Sunday 06:00 2100 19:00 1800;"
* "scheduleron": true
* },
* state: {
* "heatsetpoint": 1800,
* "on": false,
* "scheduleron": true,
* "temperature": 2190
* "on": true,
* "temperature": 2150
* },
* "ep": 1,
* "manufacturername": "Bitron Home",
Expand All @@ -37,8 +37,8 @@
* }
*
* Rest API example commands:
* -X PUT /api/<apikey>/sensors/<id>/state -d '{ "heatsetpoint": 1800 }'
* -X PUT /api/<apikey>/sensors/<id>/state -d '{ "scheduleron": true }'
* -X PUT /api/<apikey>/sensors/<id>/config -d '{ "heatsetpoint": 1800 }'
* -X PUT /api/<apikey>/sensors/<id>/config -d '{ "scheduleron": true }'
* -X PUT /api/<apikey>/sensors/<id>/config -d '{ "offset": 0 }'
* -X PUT /api/<apikey>/sensors/<id>/config -d '{ "scheduler": "Monday 05:00 2200 19:00 1800;" }'
* -d '{ "scheduler": "" }' (send get scheduler command)
Expand Down Expand Up @@ -207,22 +207,22 @@ void DeRestPluginPrivate::handleThermostatClusterIndication(const deCONZ::ApsDat
break;

case 0x0012: // Occupied Heating Setpoint
item = sensor->item(RStateHeating);
item = sensor->item(RConfigHeating);
if (item)
{
item->setValue(attrValue);
Event e(RSensors, RStateHeating, sensor->id(), item);
Event e(RSensors, RConfigHeating, sensor->id(), item);
enqueueEvent(e);
}
break;

case 0x0025: // Thermostat Programming Operation Mode, default 0 (bit#0 = disable/enable Scheduler)
item = sensor->item(RStateSchedulerOn);
item = sensor->item(RConfigSchedulerOn);
if (item)
{
bool onoff = attrValue & 0x01 ? true : false;
item->setValue(onoff);
Event e(RSensors, RStateSchedulerOn, sensor->id(), item);
Event e(RSensors, RConfigSchedulerOn, sensor->id(), item);
enqueueEvent(e);
}
break;
Expand Down

0 comments on commit fe255c3

Please sign in to comment.