Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tint remote control by Müller Light; Refactor setting light state #2849

Merged
merged 42 commits into from Jun 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c39df29
Update rest_lights.cpp
ebaauw May 30, 2020
3425d47
Add `state.angle`.
ebaauw May 30, 2020
7543489
Update bindings.cpp
ebaauw May 30, 2020
bf13a4b
Update sensor.cpp
ebaauw May 30, 2020
c2ce0bb
Update database.cpp
ebaauw May 30, 2020
5ef2042
Update sensor.h
ebaauw May 30, 2020
2e3e944
Update rest_sensors.cpp
ebaauw May 30, 2020
caaf67c
Update de_web_plugin.cpp
ebaauw May 30, 2020
6165414
Update de_web_plugin.cpp
ebaauw May 30, 2020
0ee7cd6
Update de_web_plugin.cpp
ebaauw May 31, 2020
6b290aa
Update general.xml
ebaauw Jun 1, 2020
5a06f2b
Update light_node.cpp
ebaauw Jun 1, 2020
5b0bf0c
Update rest_lights.cpp
ebaauw Jun 1, 2020
30536e0
Merge remote-tracking branch 'upstream/master'
ebaauw Jun 4, 2020
1460b6d
Update rest_configuration.cpp
ebaauw Jun 6, 2020
e7c7f0d
Update de_web_plugin_private.h
ebaauw Jun 6, 2020
ff2ef67
Update de_web_plugin.cpp
ebaauw Jun 6, 2020
acd3e48
Update event.cpp
ebaauw Jun 6, 2020
b15004c
Update general.xml
ebaauw Jun 6, 2020
d02441b
Update light_node.h
ebaauw Jun 6, 2020
2adab02
Update light_node.cpp
ebaauw Jun 6, 2020
a2bf7d0
Update resource.cpp
ebaauw Jun 6, 2020
b59a726
Update resource.h
ebaauw Jun 6, 2020
12fa2ec
Update rest_lights.cpp
ebaauw Jun 6, 2020
3f19b57
Update bindings.cpp
ebaauw Jun 7, 2020
551d6ec
Update resource.h
ebaauw Jun 7, 2020
c570902
Update resource.cpp
ebaauw Jun 7, 2020
8f4285d
Update light_node.h
ebaauw Jun 7, 2020
07af3ed
Update light_node.cpp
ebaauw Jun 7, 2020
5dc23b8
Update rest_groups.cpp
ebaauw Jun 7, 2020
4d3905e
Update rest_lights.cpp
ebaauw Jun 7, 2020
9fa3b2e
Update window_covering.cpp
ebaauw Jun 7, 2020
8ed5488
Update de_web_plugin.cpp
ebaauw Jun 7, 2020
8a95e13
Update zcl_tasks.cpp
ebaauw Jun 7, 2020
e746a71
Update rest_lights.cpp
ebaauw Jun 7, 2020
6d36eff
Update resource.cpp
ebaauw Jun 7, 2020
0fa4fe0
Update light_node.cpp
ebaauw Jun 8, 2020
670950b
Update resource.cpp
ebaauw Jun 8, 2020
00dbacb
Update rest_lights.cpp
ebaauw Jun 10, 2020
b56d4be
Update rest_rules.cpp
ebaauw Jun 12, 2020
f04edde
Merge remote-tracking branch 'upstream/master'
ebaauw Jun 12, 2020
0705338
Update rest_rules.cpp
ebaauw Jun 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 15 additions & 1 deletion bindings.cpp
Expand Up @@ -1567,6 +1567,17 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)

return sendConfigureReportingRequest(bt, {rq});
}
else if (bt.binding.clusterId == BASIC_CLUSTER_ID && manufacturerCode == VENDOR_MUELLER && lightNode)
{
rq.dataType = deCONZ::Zcl8BitUint;
rq.attributeId = 0x4005; // Mueller special scene
rq.minInterval = 1;
rq.maxInterval = 300;
rq.reportableChange8bit = 1;
rq.manufacturerCode = VENDOR_MUELLER;

return sendConfigureReportingRequest(bt, {rq});
}
else if (bt.binding.clusterId == VENDOR_CLUSTER_ID)
{
Sensor *sensor = dynamic_cast<Sensor *>(bt.restNode);
Expand Down Expand Up @@ -1672,6 +1683,9 @@ void DeRestPluginPrivate::checkLightBindingsForAttributeReporting(LightNode *lig
else if (lightNode->manufacturerCode() == VENDOR_LGE)
{
}
else if (lightNode->manufacturerCode() == VENDOR_MUELLER)
{
}
else if (lightNode->manufacturerCode() == VENDOR_KEEN_HOME)
{
}
Expand Down Expand Up @@ -2881,7 +2895,7 @@ void DeRestPluginPrivate::checkOldSensorGroups(Sensor *sensor)
i->removeDeviceMembership(sensor->id());
}

if (i->state() == Group::StateNormal && !i->hasDeviceMembers())
if (i->address() != 0 && i->state() == Group::StateNormal && !i->hasDeviceMembers())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i->address() != 0 may we should use some constants here to get more meaning and make it easier to search for places where group 0x0000 is used.

GROUP_0 / GROUP_ZERO or something similar.

Copy link
Collaborator Author

@ebaauw ebaauw Jun 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's several things going wrong with /groups/0. Events are issued on /groups/65520 instead of on /groups/0. A GET of /groups/65520 returns the same as a GET of /groups/0. The entire code handling this should be reviewed. I think we might need to decouple the REST resource ID from the group address for all groups, similar to the Hue bridge.

{
DBG_Printf(DBG_INFO, "delete old group %u of sensor %s\n", i->address(), qPrintable(sensor->name()));
i->setState(Group::StateDeleted);
Expand Down
6 changes: 6 additions & 0 deletions database.cpp
Expand Up @@ -2943,6 +2943,12 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c
{
sensor.addItem(DataTypeUInt16, RStateEventDuration);
}
else if (sensor.modelId().startsWith(QLatin1String("ZBT-Remote-ALL-RGBW")))
{
sensor.addItem(DataTypeUInt16, RStateX);
sensor.addItem(DataTypeUInt16, RStateY);
sensor.addItem(DataTypeUInt16, RStateAngle);
}
}
else if (sensor.type().endsWith(QLatin1String("LightLevel")))
{
Expand Down
425 changes: 238 additions & 187 deletions de_web_plugin.cpp

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions de_web_plugin_private.h
Expand Up @@ -1894,4 +1894,6 @@ public Q_SLOTS:

};

extern DeRestPluginPrivate *plugin;

#endif // DE_WEB_PLUGIN_PRIVATE_H
1 change: 0 additions & 1 deletion event.cpp
Expand Up @@ -51,4 +51,3 @@ Event::Event(const char *resource, const char *what, int num) :
m_id = QString::number(num);
}
}

33 changes: 30 additions & 3 deletions general.xml
Expand Up @@ -201,6 +201,9 @@
<attribute id="0x4001" name="128-Bit security key" type="seckey" access="r" required="m" mfcode="0x1166"></attribute>
<attribute id="0x4002" name="IEEE address" type="uid" access="rw" required="m" mfcode="0x1166"></attribute>
</attribute-set>
<attribute-set id="0x4000" description="Müller Licht specific" mfcode="0x121b">
<attribute id="0x4005" name="Scene" type="u8" access="rw" required="o" mfcode="0x121b"></attribute>
</attribute-set>
<attribute-set id="0x8000" description="Develco Specific" mfcode="0x1015">
<attribute id="0x8000" name="Primary SW Version" type="ostring" access="r" required="m" mfcode="0x1015"></attribute>
<attribute id="0x8010" name="Primary Bootloader SW Version" type="ostring" access="r" required="m" mfcode="0x1015"></attribute>
Expand Down Expand Up @@ -1822,7 +1825,7 @@ controller device, that supports a keypad and LCD screen.</description>
<attribute id="0x0002" name="Remaining time" type="u16" access="r" range="0x0000,0xfffe" default="0x0000" required="o"></attribute>
<attribute id="0x0003" name="Current x" type="u16" access="r" range="0x0000,0xfeff" default="0x61eb" required="m"></attribute>
<attribute id="0x0004" name="Current y" type="u16" access="r" range="0x0000,0xfeff" default="0x607b" required="m"></attribute>
<attribute id="0x0007" name="Color temperature" type="u16" access="r" range="0x0000,0xffff" default="0" required="m"></attribute>
<attribute id="0x0007" name="Color temperature" type="u16" access="r" range="0x0000,0xfeff" default="0" required="m"></attribute>
<!-- TODO -->
<attribute id="0x0008" name="Color Mode" type="enum8" access="r" range="0x00,0x02" default="0x01" required="o">
<value name="Current hue and current saturation" value="0x00"></value>
Expand All @@ -1841,6 +1844,30 @@ controller device, that supports a keypad and LCD screen.</description>
<attribute id="0x0019" name="Primary3 x" type="u16" access="r" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x001a" name="Primary3 y" type="u16" access="r" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x001b" name="Primary3 intensity" type="u8" access="r" range="0x00,0xff" required="o"></attribute>
</attribute-set>
<attribute-set id="0x002" description="Additional Defined Primaries Information">
<attribute id="0x0020" name="Primary4 x" type="u16" access="r" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0021" name="Primary4 y" type="u16" access="r" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0022" name="Primary4 intensity" type="u8" access="r" range="0x00,0xff" required="o"></attribute>
<attribute id="0x0024" name="Primary5 x" type="u16" access="r" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0025" name="Primary5 y" type="u16" access="r" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0026" name="Primary5 intensity" type="u8" access="r" range="0x00,0xff" required="o"></attribute>
<attribute id="0x0028" name="Primary6 x" type="u16" access="r" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0029" name="Primary6 y" type="u16" access="r" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x002a" name="Primary6 intensity" type="u8" access="r" range="0x00,0xff" required="o"></attribute>
</attribute-set>
<attribute-set id="0x003" description="Defined Color Points Settings">
<attribute id="0x0030" name="WhitePoint x" type="u16" access="rw" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0031" name="WhitePoint y" type="u16" access="rw" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0032" name="ColorPoint r x" type="u16" access="rw" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0033" name="ColorPoint r y" type="u16" access="rw" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0034" name="ColorPoint r intensity" type="u8" access="rw" range="0x00,0xff" required="o"></attribute>
<attribute id="0x0036" name="ColorPoint g x" type="u16" access="rw" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0037" name="ColorPoint g y" type="u16" access="rw" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x0038" name="ColorPoint g intensity" type="u8" access="rw" range="0x00,0xff" required="o"></attribute>
<attribute id="0x003a" name="ColorPoint b x" type="u16" access="rw" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x003b" name="ColorPoint b y" type="u16" access="rw" range="0x0000,0xfeff" required="o"></attribute>
<attribute id="0x003c" name="ColorPoint b intensity" type="u8" access="rw" range="0x00,0xff" required="o"></attribute>
</attribute-set>
<attribute-set id="0x4000" description="ZLL extensions">
<attribute id="0x4000" name="Enhanced current hue" type="u16" access="r" range="0x0000,0xffff" default="0x0000" required="m"></attribute>
Expand All @@ -1862,8 +1889,8 @@ controller device, that supports a keypad and LCD screen.</description>
<value name="CIE 1931 XY" value="3"></value>
<value name="Color temperature" value="4"></value>
</attribute>
<attribute id="0x400b" name="Color temperature min" type="u16" access="r" range="0x0000,0xffff" default="0" required="m"></attribute>
<attribute id="0x400c" name="Color temperature max" type="u16" access="r" range="0x0000,0xffff" default="0xffff" required="m"></attribute>
<attribute id="0x400b" name="Color temperature min" type="u16" access="r" range="0x0000,0xfeff" default="0" required="m"></attribute>
<attribute id="0x400c" name="Color temperature max" type="u16" access="r" range="0x0000,0xfeff" default="0xfeff" required="m"></attribute>
<attribute id="0x4010" name="PowerOn Color Temperature" type="u16" access="rw" range="0x0000,0xffff" default="0xffff" required="o"></attribute>
<!--
<attribute id="0x0003" mfcode="0x100b" name="PowerOn X" type="u16" access="rw" range="0x0000,0xffff" default="0xffff" required="o"></attribute>
Expand Down
210 changes: 138 additions & 72 deletions light_node.cpp
Expand Up @@ -14,18 +14,22 @@
*/
LightNode::LightNode() :
Resource(RLights),
m_state(StateNormal),
m_resetRetryCount(0),
m_zdpResetSeq(0),
m_groupCapacity(0),
m_manufacturerCode(0),
m_otauClusterId(0), // unknown
m_colorLoopActive(false),
m_colorLoopSpeed(0),
m_groupCount(0),
m_sceneCapacity(16)
m_state(StateNormal),
m_resetRetryCount(0),
m_zdpResetSeq(0),
m_groupCapacity(0),
m_manufacturerCode(0),
m_otauClusterId(0), // unknown
m_colorLoopActive(false),
m_colorLoopSpeed(0),
m_groupCount(0),
m_sceneCapacity(16)

{
QDateTime now = QDateTime::currentDateTime();
lastStatePush = now;
lastAttrPush = now;

{
// add common items
addItem(DataTypeBool, RStateOn);
addItem(DataTypeString, RStateAlert);
Expand All @@ -35,6 +39,8 @@ LightNode::LightNode() :
addItem(DataTypeString, RAttrModelId);
addItem(DataTypeString, RAttrType);
addItem(DataTypeString, RAttrSwVersion);
addItem(DataTypeTime, RAttrLastAnnounced);
addItem(DataTypeTime, RAttrLastSeen);

setManufacturerName(QLatin1String("Unknown"));
}
Expand Down Expand Up @@ -214,66 +220,6 @@ bool LightNode::hasColor() const
return item(RStateColorMode) != nullptr;
}

/*! Sets the lights CIE color coordinates.
\param x the x coordinate (0..65279)
\param y the y coordinate (0..65279)
*/
void LightNode::setColorXY(uint16_t x, uint16_t y)
{
DBG_Assert(x <= 65279);
DBG_Assert(y <= 65279);

if (x > 65279)
{
x = 65279;
}

if (y > 65279)
{
y = 65279;
}

ResourceItem *i = item(RStateX);
if (i)
{
i->setValue(x);
}

i = item(RStateY);
if (i)
{
i->setValue(y);
}
}

/*! Returns the current colormode.
*/
const QString &LightNode::colorMode() const
{
static QString foo;
const ResourceItem *i = item(RStateColorMode);
DBG_Assert(i != nullptr);
if (i)
{
return i->toString();
}
return foo;
}

/*! Sets the current colormode.
\param colorMode the colormode ("hs", "xy", "ct")
*/
void LightNode::setColorMode(const QString &colorMode)
{
DBG_Assert((colorMode == QLatin1String("hs")) || (colorMode == QLatin1String("xy")) || (colorMode == QLatin1String("ct")));

ResourceItem *i = item(RStateColorMode);
if (i && i->toString() != colorMode)
{
i->setValue(colorMode);
}
}

/*! Sets the nodes color loop active state.
\param colorLoopActive whereever the color loop is active
*/
Expand Down Expand Up @@ -302,6 +248,102 @@ uint8_t LightNode::colorLoopSpeed() const
return m_colorLoopSpeed;
}

/*! Handles admin when ResourceItem value has been set.
* \param i ResourceItem
*/
void LightNode::didSetValue(ResourceItem *i)
{
plugin->enqueueEvent(Event(RLights, i->descriptor().suffix, id(), i));
plugin->updateLightEtag(this);
setNeedSaveDatabase(true);
plugin->saveDatabaseItems |= DB_LIGHTS;
plugin->queSaveDb(DB_LIGHTS, DB_SHORT_SAVE_DELAY);
}

/*! Set ResourceItem value.
* \param suffix ResourceItem suffix
* \param val ResourceIetm value
*/
bool LightNode::setValue(const char *suffix, qint64 val, bool forceUpdate)
{
ResourceItem *i = item(suffix);
if (!i)
{
return false;
}
if (forceUpdate || i->toNumber() != val)
{
if (!(i->setValue(val)))
{
return false;
}
didSetValue(i);
return true;
}
return false;
}

/*! Set ResourceItem value.
* \param suffix ResourceItem suffix
* \param val ResourceIetm value
*/
bool LightNode::setValue(const char *suffix, const QString &val, bool forceUpdate)
{
ResourceItem *i = item(suffix);
if (!i)
{
return false;
}
if (forceUpdate || i->toString() != val)
{
if (!(i->setValue(val)))
{
return false;
}
didSetValue(i);
return true;
}
return false;
}

/*! Set ResourceItem value.
* \param suffix ResourceItem suffix
* \param val ResourceIetm value
*/
bool LightNode::setValue(const char *suffix, const QVariant &val, bool forceUpdate)
{
ResourceItem *i = item(suffix);
if (!i)
{
return false;
}
if (forceUpdate || i->toVariant() != val)
{
if (!(i->setValue(val)))
{
return false;
}
didSetValue(i);
return true;
}
return false;
}

/*! Mark received command and update lastseen. */
void LightNode::rx()
{
RestNodeBase *b = static_cast<RestNodeBase *>(this);
b->rx();
if (lastRx() >= item(RAttrLastSeen)->lastChanged().addSecs(1))
{
setValue(RAttrLastSeen, lastRx().toUTC());
}
else
{
item(RAttrLastSeen)->setValue(lastRx().toUTC());
}
}

/*! Returns the lights HA endpoint descriptor.
*/
const deCONZ::SimpleDescriptor &LightNode::haEndpoint() const
Expand Down Expand Up @@ -400,7 +442,7 @@ void LightNode::setHaEndpoint(const deCONZ::SimpleDescriptor &endpoint)
{
addItem(DataTypeUInt16, RConfigColorCapabilities);
addItem(DataTypeUInt16, RConfigCtMin);
addItem(DataTypeUInt16, RConfigCtMax)->setValue(65535);
addItem(DataTypeUInt16, RConfigCtMax)->setValue(0xFEFF);
addItem(DataTypeUInt16, RStateCt);

if (deviceId == DEV_ID_Z30_COLOR_TEMPERATURE_LIGHT ||
Expand All @@ -424,6 +466,7 @@ void LightNode::setHaEndpoint(const deCONZ::SimpleDescriptor &endpoint)
{
addItem(DataTypeUInt16, RStateX);
addItem(DataTypeUInt16, RStateY);
addItem(DataTypeUInt8, RStateEffect);
addItem(DataTypeUInt16, RStateHue);
addItem(DataTypeUInt8, RStateSat);
}
Expand Down Expand Up @@ -468,6 +511,7 @@ void LightNode::setHaEndpoint(const deCONZ::SimpleDescriptor &endpoint)
}
}
}
removeItem(RStateAlert);
addItem(DataTypeBool, RStateOpen);
// FIXME: removeItem(RStateOn);
if (hasLift)
Expand Down Expand Up @@ -686,6 +730,28 @@ void LightNode::jsonToResourceItems(const QString &json)
QVariantMap map = var.toMap();
QDateTime dt = QDateTime::currentDateTime().addSecs(-120);

if (map.contains(RAttrLastAnnounced))
{
QString lastannounced = map[RAttrLastAnnounced].toString();
QString format = QLatin1String("yyyy-MM-ddTHH:mm:ssZ");
QDateTime la = QDateTime::fromString(lastannounced, format);
la.setTimeSpec(Qt::UTC);
map[RAttrLastAnnounced] = la;
}

if (map.contains(RAttrLastSeen))
{
QString lastseen = map[RAttrLastSeen].toString();
QString format = QLatin1String("yyyy-MM-ddTHH:mm:ssZ");
QDateTime ls = QDateTime::fromString(lastseen, format);
ls.setTimeSpec(Qt::UTC);
map[RAttrLastSeen] = ls;
if (ls < dt)
{
dt = ls;
}
}

for (int i = 0; i < itemCount(); i++)
{
ResourceItem *item = itemForIndex(i);
Expand Down