Support recalling next/previous scene of a group
This allows easier rules for switches to cycle through scenes of a group.
@@ -2607,6 +2607,8 @@ int DeRestPluginPrivate::storeScene(const ApiRequest &req, ApiResponse &rsp)
}
/*! PUT /api/<apikey>/groups/<group_id>/scenes/<scene_id>/recall
+ PUT /api/<apikey>/groups/<group_id>/scenes/next/recall
+ PUT /api/<apikey>/groups/<group_id>/scenes/prev/recall
\return REQ_READY_SEND
REQ_NOT_HANDLED
*/
@@ -2640,9 +2642,69 @@ int DeRestPluginPrivate::recallScene(const ApiRequest &req, ApiResponse &rsp)
}
// check if scene exists
+ Scene *scene = 0;
+ uint8_t sceneId = 0;
+ ok = false;
+ if (sid == QLatin1String("next") || sid == QLatin1String("prev"))
+ {
+ ResourceItem *item = group->item(RActionScene);
+ DBG_Assert(item != 0);
+ uint lastSceneId = 0;
+ if (item && !item->toString().isEmpty())
+ {
+ lastSceneId = item->toString().toUInt(&ok);
+ }
- uint8_t sceneId = sid.toUInt(&ok);
- Scene *scene = ok ? group->getScene(sceneId) : 0;
+ int idx = -1;
+ std::vector<quint8> scenes; // available scenes
+
+ for (const Scene &s : group->scenes)
+ {
+ if (s.state != Scene::StateNormal)
+ {
+ continue;
+ }
+
+ if (lastSceneId == s.id)
+ {
+ idx = scenes.size(); // remember current index
+ }
+ scenes.emplace_back(s.id);
+ }
+
+ if (scenes.size() == 1)
+ {
+ ok = true;
+ sceneId = scenes[0];
+ }
+ else if (scenes.size() > 1)
+ {
+ ok = true;
+ if (idx == -1) // not found
+ {
+ idx = 0; // use first
+ }
+ else if (sid[0] == 'p') // prev
+ {
+ if (idx > 0) { idx--; }
+ else { idx = scenes.size() - 1; } // jump to last scene
+ }
+ else // next
+ {
+ if (idx < int(scenes.size() - 1)) { idx++; }
+ else { idx = 0; } // jump to first scene
+ }
+ DBG_Assert(idx >= 0 && idx < int(scenes.size()));
+ sceneId = scenes[idx];
+ }
+ // else ok == false
+ }
+ else
+ {
+ sceneId = sid.toUInt(&ok);
+ }
+
+ scene = ok ? group->getScene(sceneId) : 0;
if (!scene || (scene->state != Scene::StateNormal))
{
@@ -2695,6 +2757,18 @@ int DeRestPluginPrivate::recallScene(const ApiRequest &req, ApiResponse &rsp)
return REQ_READY_SEND;
}
+ {
+ QString scid = QString::number(sceneId);
+ ResourceItem *item = group->item(RActionScene);
+ if (item && item->toString() != scid)
+ {
+ item->setValue(scid);
+ updateGroupEtag(group);
+ Event e(RGroups, RActionScene, group->id(), item);
+ enqueueEvent(e);
+ }
+ }
+
bool groupOnChanged = false;
bool groupBriChanged = false;
bool groupHueSatChanged = false;
