Skip to content

Commit

Permalink
Improved scene handling and update WebApp state when recall a scene
Browse files Browse the repository at this point in the history
  • Loading branch information
manup committed Sep 18, 2016
1 parent 91862c5 commit 41a7f23
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 172 deletions.
201 changes: 95 additions & 106 deletions de_web_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5792,130 +5792,119 @@ void DeRestPluginPrivate::handleSceneClusterIndication(TaskItem &task, const deC
}
else if (zclFrame.commandId() == 0x05) // Recall scene command
{
if (!ind.srcAddress().hasExt())
{
return;
}

// update Nodes and Groups state if Recall scene Command was send by a switch
Sensor *sensorNode = getSensorNodeForAddressAndEndpoint(ind.srcAddress(), ind.srcEndpoint());

if (sensorNode)
if (sensorNode && sensorNode->deletedState() == Sensor::StateNormal)
{
if (sensorNode->deletedState() != Sensor::StateDeleted)
{
DBG_Assert(zclFrame.payload().size() >= 3);

QDataStream stream(zclFrame.payload());
stream.setByteOrder(QDataStream::LittleEndian);
checkSensorNodeReachable(sensorNode);
}

uint16_t groupId;
uint8_t sceneId;
DBG_Assert(zclFrame.payload().size() >= 3);

//stream >> status;
stream >> groupId;
stream >> sceneId;
QDataStream stream(zclFrame.payload());
stream.setByteOrder(QDataStream::LittleEndian);

// check if scene exists
Scene scene;
TaskItem task2;
bool colorloopDeactivated = false;
Group *group = getGroupForId(groupId);
uint16_t groupId;
uint8_t sceneId;

if (group && group->state() != Group::StateDeleted && group->state() != Group::StateDeleteFromDB)
{
std::vector<Scene>::const_iterator i = group->scenes.begin();
std::vector<Scene>::const_iterator end = group->scenes.end();
stream >> groupId;
stream >> sceneId;

for (; i != end; ++i)
{
if ((i->id == sceneId) && (i->state != Scene::StateDeleted))
{
scene = *i;
// check if scene exists

std::vector<LightState>::const_iterator ls = scene.lights().begin();
std::vector<LightState>::const_iterator lsend = scene.lights().end();
bool colorloopDeactivated = false;
Group *group = getGroupForId(groupId);
Scene *scene = group ? group->getScene(sceneId) : 0;

for (; ls != lsend; ++ls)
{
LightNode *light = getLightNodeForId(ls->lid());
if (light && light->isAvailable() && light->state() != LightNode::StateDeleted)
{
bool changed = false;
if (!ls->colorloopActive() && light->isColorLoopActive() != ls->colorloopActive())
{
//stop colorloop if scene was saved without colorloop (Osram don't stop colorloop if another scene is called)
task2.lightNode = light;
task2.req.dstAddress() = task2.lightNode->address();
task2.req.setTxOptions(deCONZ::ApsTxAcknowledgedTransmission);
task2.req.setDstEndpoint(task2.lightNode->haEndpoint().endpoint());
task2.req.setSrcEndpoint(getSrcEndpoint(task2.lightNode, task2.req));
task2.req.setDstAddressMode(deCONZ::ApsExtAddress);

light->setColorLoopActive(false);
addTaskSetColorLoop(task2, false, 15);

changed = true;
colorloopDeactivated = true;
}
//turn on colorloop if scene was saved with colorloop (FLS don't save colorloop at device)
else if (ls->colorloopActive() && light->isColorLoopActive() != ls->colorloopActive())
{
task2.lightNode = light;
task2.req.dstAddress() = task2.lightNode->address();
task2.req.setTxOptions(deCONZ::ApsTxAcknowledgedTransmission);
task2.req.setDstEndpoint(task2.lightNode->haEndpoint().endpoint());
task2.req.setSrcEndpoint(getSrcEndpoint(task2.lightNode, task2.req));
task2.req.setDstAddressMode(deCONZ::ApsExtAddress);

light->setColorLoopActive(true);
light->setColorLoopSpeed(ls->colorloopTime());
addTaskSetColorLoop(task2, true, ls->colorloopTime());
changed = true;
}
if (ls->on() && !light->isOn())
{
light->setIsOn(true);
changed = true;
}
if (!ls->on() && light->isOn())
{
light->setIsOn(false);
changed = true;
}
if ((uint16_t)ls->bri() != light->level())
{
light->setLevel((uint16_t)ls->bri());
changed = true;
}
if (changed)
{
updateEtag(light->etag);
}
}
}
if (group && (group->state() == Group::StateNormal) && scene)
{
std::vector<LightState>::const_iterator ls = scene->lights().begin();
std::vector<LightState>::const_iterator lsend = scene->lights().end();

//recall scene again
if (colorloopDeactivated)
{
callScene(group, sceneId);
}
break;
for (; ls != lsend; ++ls)
{
LightNode *lightNode = getLightNodeForId(ls->lid());
if (lightNode && lightNode->isAvailable() && lightNode->state() == LightNode::StateNormal)
{
bool changed = false;
if (lightNode->hasColor())
{
if (!ls->colorloopActive() && lightNode->isColorLoopActive() != ls->colorloopActive())
{
//stop colorloop if scene was saved without colorloop (Osram don't stop colorloop if another scene is called)
TaskItem task2;
task2.lightNode = lightNode;
task2.req.dstAddress() = task2.lightNode->address();
task2.req.setTxOptions(deCONZ::ApsTxAcknowledgedTransmission);
task2.req.setDstEndpoint(task2.lightNode->haEndpoint().endpoint());
task2.req.setSrcEndpoint(getSrcEndpoint(task2.lightNode, task2.req));
task2.req.setDstAddressMode(deCONZ::ApsExtAddress);

lightNode->setColorLoopActive(false);
addTaskSetColorLoop(task2, false, 15);

changed = true;
colorloopDeactivated = true;
}
//turn on colorloop if scene was saved with colorloop (FLS don't save colorloop at device)
else if (ls->colorloopActive() && lightNode->isColorLoopActive() != ls->colorloopActive())
{
TaskItem task2;
task2.lightNode = lightNode;
task2.req.dstAddress() = task2.lightNode->address();
task2.req.setTxOptions(deCONZ::ApsTxAcknowledgedTransmission);
task2.req.setDstEndpoint(task2.lightNode->haEndpoint().endpoint());
task2.req.setSrcEndpoint(getSrcEndpoint(task2.lightNode, task2.req));
task2.req.setDstAddressMode(deCONZ::ApsExtAddress);

lightNode->setColorLoopActive(true);
lightNode->setColorLoopSpeed(ls->colorloopTime());
addTaskSetColorLoop(task2, true, ls->colorloopTime());

changed = true;
}
}
if (ls->on() != lightNode->isOn())
{
lightNode->setIsOn(ls->on());
changed = true;
}
if ((uint16_t)ls->bri() != lightNode->level())
{
lightNode->setLevel((uint16_t)ls->bri());
changed = true;
}
if (lightNode->hasColor())
{
if (ls->x() != lightNode->colorX() || ls->y() != lightNode->colorY())
{
lightNode->setColorXY(ls->x(), ls->y());
changed = true;
}
}
if (changed)
{
updateEtag(lightNode->etag);
}
}
// turning 'on' the group is also a assumtion but a very likely one
if (!group->isOn())
{
group->setIsOn(true);
updateEtag(group->etag);
}

updateEtag(gwConfigEtag);
}

processTasks();
//recall scene again
if (colorloopDeactivated)
{
callScene(group, sceneId);
}
}
// turning 'on' the group is also a assumtion but a very likely one
if (!group->isOn())
{
group->setIsOn(true);
updateEtag(group->etag);
}

updateEtag(gwConfigEtag);
processTasks();
}
}

Expand Down
2 changes: 1 addition & 1 deletion group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ Scene *Group::getScene(quint8 sceneId)
std::vector<Scene>::iterator end = scenes.end();
for (; i != end; ++i)
{
if (i->id == sceneId)
if (i->id == sceneId && i->state == Scene::StateNormal)
{
return &*i;
}
Expand Down
Loading

0 comments on commit 41a7f23

Please sign in to comment.