Skip to content

Commit

Permalink
Bitron Remote, Hue smart button
Browse files Browse the repository at this point in the history
- Add support for Bitron Remote, see #2392;
- Add support (untested!) for Hue smart button, see #2077.
  • Loading branch information
ebaauw authored and manup committed Feb 29, 2020
1 parent b979ab2 commit 6d9c609
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 30 deletions.
25 changes: 20 additions & 5 deletions bindings.cpp
Expand Up @@ -1112,7 +1112,8 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
rq.maxInterval = 7200; // value used by Hue bridge
rq.reportableChange8bit = 0; // value used by Hue bridge
}
else if (sensor && sensor->modelId().startsWith(QLatin1String("RWL02"))) // Hue dimmer switch
else if (sensor && (sensor->modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("ROM00")))) // Hue smart button
{
rq.minInterval = 300; // value used by Hue bridge
rq.maxInterval = 300; // value used by Hue bridge
Expand All @@ -1124,7 +1125,8 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
rq.maxInterval = 900; // value used by Hue bridge
rq.reportableChange8bit = 4; // value used by Hue bridge
}
else if (sensor && sensor->manufacturer().startsWith(QLatin1String("Climax")))
else if (sensor && (sensor->manufacturer().startsWith(QLatin1String("Climax")) ||
sensor->modelId().startsWith(QLatin1String("902010/23"))))
{
rq.attributeId = 0x0035; // battery alarm mask
rq.dataType = deCONZ::Zcl8BitBitMap;
Expand Down Expand Up @@ -1533,6 +1535,7 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
Sensor *sensor = dynamic_cast<Sensor *>(bt.restNode);

if (sensor && (sensor->modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("ROM00")) || // Hue smart button
sensor->modelId().startsWith(QLatin1String("Z3-1BRL")))) // Lutron Aurora Friends-of-Hue dimmer switch
{
deCONZ::NumericUnion val;
Expand Down Expand Up @@ -1854,6 +1857,7 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso
// Philips
sensor->modelId().startsWith(QLatin1String("SML00")) ||
sensor->modelId().startsWith(QLatin1String("RWL02")) ||
sensor->modelId().startsWith(QLatin1String("ROM00")) ||
// Lutron Aurora Friends-of-Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("Z3-1BRL")) ||
// ubisys
Expand Down Expand Up @@ -2057,7 +2061,8 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso
//This device don't support report attribute
continue;
}
if (sensor->manufacturer().startsWith(QLatin1String("Climax")))
if (sensor->manufacturer().startsWith(QLatin1String("Climax")) ||
sensor->modelId().startsWith(QLatin1String("902010/23")))
{
val = sensor->getZclValue(*i, 0x0035); // battery alarm mask
}
Expand Down Expand Up @@ -2116,6 +2121,7 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso
else if (*i == VENDOR_CLUSTER_ID)
{
if (sensor->modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("ROM00")) || // Hue smart button
sensor->modelId().startsWith(QLatin1String("Z3-1BRL"))) // Lutron Aurora Friends-of-Hue dimmer switch
{
val = sensor->getZclValue(*i, 0x0000); // button event
Expand Down Expand Up @@ -2325,7 +2331,8 @@ bool DeRestPluginPrivate::checkSensorBindingsForClientClusters(Sensor *sensor)
//quint8 srcEndpoint = sensor->fingerPrint().endpoint;
std::vector<quint16> clusters;

if (sensor->modelId().startsWith(QLatin1String("RWL02"))) // Hue dimmer switch
if (sensor->modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("ROM00"))) // Hue smart button
{
srcEndpoints.push_back(0x01);
clusters.push_back(ONOFF_CLUSTER_ID);
Expand Down Expand Up @@ -2480,6 +2487,13 @@ bool DeRestPluginPrivate::checkSensorBindingsForClientClusters(Sensor *sensor)
clusters.push_back(COLOR_CLUSTER_ID);
srcEndpoints.push_back(sensor->fingerPrint().endpoint);
}
// Bitron remote control
else if (sensor->modelId().startsWith(QLatin1String("902010/23")))
{
clusters.push_back(ONOFF_CLUSTER_ID);
clusters.push_back(LEVEL_CLUSTER_ID);
srcEndpoints.push_back(sensor->fingerPrint().endpoint);
}
else
{
return false;
Expand Down Expand Up @@ -2593,7 +2607,8 @@ void DeRestPluginPrivate::checkSensorGroup(Sensor *sensor)
}
}

if (sensor->modelId().startsWith(QLatin1String("RWL02"))) // Hue dimmer switch
if (sensor->modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("ROM00"))) // Hue smart button
{
if (!group)
{
Expand Down
24 changes: 22 additions & 2 deletions database.cpp
Expand Up @@ -2930,7 +2930,9 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c
{
sensor.addItem(DataTypeInt32, RStateGesture);
}
else if (sensor.modelId().startsWith(QLatin1String("RWL02"))) // || sensor.modelId().startsWith(QLatin1String("Z3-1BRL")))
else if (sensor.modelId().startsWith(QLatin1String("RWL02")) ||
// sensor.modelId().startsWith(QLatin1String("Z3-1BRL")) ||
sensor.modelId().startsWith(QLatin1String("ROM00")))
{
sensor.addItem(DataTypeUInt16, RStateEventDuration);
}
Expand Down Expand Up @@ -3289,6 +3291,23 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c
sensor.setNeedSaveDatabase(true);
}
}
else if (sensor.modelId().startsWith(QLatin1String("ROM00"))) // Hue smart button
{
clusterId = VENDOR_CLUSTER_ID;
endpoint = 1;

if (!sensor.fingerPrint().hasInCluster(POWER_CONFIGURATION_CLUSTER_ID))
{
sensor.fingerPrint().inClusters.push_back(POWER_CONFIGURATION_CLUSTER_ID);
sensor.setNeedSaveDatabase(true);
}

if (!sensor.fingerPrint().hasInCluster(VENDOR_CLUSTER_ID)) // for realtime button feedback
{
sensor.fingerPrint().inClusters.push_back(VENDOR_CLUSTER_ID);
sensor.setNeedSaveDatabase(true);
}
}
else if (sensor.modelId().startsWith(QLatin1String("SML00"))) // Hue motion sensor
{
if (!sensor.fingerPrint().hasInCluster(BASIC_CLUSTER_ID))
Expand Down Expand Up @@ -3377,7 +3396,8 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c

if (sensor.fingerPrint().hasInCluster(POWER_CONFIGURATION_CLUSTER_ID))
{
if (sensor.manufacturer().startsWith(QLatin1String("Climax")))
if (sensor.manufacturer().startsWith(QLatin1String("Climax")) ||
sensor.modelId().startsWith(QLatin1String("902010/23")))
{
// climax non IAS reports state/lowbattery via battery alarm mask attribute
item = sensor.addItem(DataTypeBool, RStateLowBattery);
Expand Down
78 changes: 57 additions & 21 deletions de_web_plugin.cpp
Expand Up @@ -127,6 +127,7 @@ static const SupportedDevice supportedDevices[] = {
{ VENDOR_NONE, "OJB-IR715-Z", tiMacPrefix },
{ VENDOR_NONE, "902010/21", tiMacPrefix }, // Bitron: door/window sensor
{ VENDOR_NONE, "902010/22", tiMacPrefix }, // Bitron: motion sensor
{ VENDOR_NONE, "902010/23", tiMacPrefix }, // Bitron: remote control
{ VENDOR_NONE, "902010/24", tiMacPrefix }, // Bitron: smoke detector
{ VENDOR_NONE, "902010/25", tiMacPrefix }, // Bitron: smart plug
{ VENDOR_BITRON, "902010/32", emberMacPrefix }, // Bitron: thermostat
Expand All @@ -151,8 +152,8 @@ static const SupportedDevice supportedDevices[] = {
{ VENDOR_NYCE, "3011", emberMacPrefix }, // NYCE door/window sensor
{ VENDOR_NYCE, "3014", emberMacPrefix }, // NYCE garage door/tilt sensor
{ VENDOR_NYCE, "3043", emberMacPrefix }, // NYCE ceiling motion sensor
{ VENDOR_PHILIPS, "RWL020", philipsMacPrefix }, // Hue dimmer switch
{ VENDOR_PHILIPS, "RWL021", philipsMacPrefix }, // Hue dimmer switch
{ VENDOR_PHILIPS, "RWL02", philipsMacPrefix }, // Hue dimmer switch
{ VENDOR_PHILIPS, "ROM00", philipsMacPrefix }, // Hue smart button
{ VENDOR_PHILIPS, "SML00", philipsMacPrefix }, // Hue motion sensor
{ VENDOR_SAMJIN, "motion", samjinMacPrefix }, // Smarthings GP-U999SJVLBAA (Samjin) Motion Sensor
{ VENDOR_SAMJIN, "multi", samjinMacPrefix }, // Smarthings (Samjin) Multipurpose Sensor
Expand Down Expand Up @@ -3238,6 +3239,7 @@ void DeRestPluginPrivate::checkSensorButtonEvent(Sensor *sensor, const deCONZ::A
checkClientCluster = true;
}
else if (sensor->modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("ROM00")) || // Hue smart button
sensor->modelId().startsWith(QLatin1String("Z3-1BRL"))) // Lutron Aurora Friends-of-Hue dimmer switch
{
checkReporting = true;
Expand Down Expand Up @@ -3653,6 +3655,7 @@ void DeRestPluginPrivate::checkSensorButtonEvent(Sensor *sensor, const deCONZ::A
#if 0
// check if hue dimmer switch is configured
if (sensor->modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("ROM00")) || // Hue smart button
sensor->modelId().startsWith(QLatin1String("Z3-1BRL"))) // Lutron Aurora Friends-of-Hue dimmer switch
{
bool ok = true;
Expand Down Expand Up @@ -4717,7 +4720,8 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const SensorFi

if (sensorNode.fingerPrint().hasInCluster(POWER_CONFIGURATION_CLUSTER_ID))
{
if (manufacturer.startsWith(QLatin1String("Climax")))
if (manufacturer.startsWith(QLatin1String("Climax")) ||
sensorNode.modelId().startsWith(QLatin1String("902010/23")))
{
// climax non IAS reports state/lowbattery via battery alarm mask attribute
sensorNode.addItem(DataTypeBool, RStateLowBattery);
Expand Down Expand Up @@ -4767,7 +4771,9 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const SensorFi
{
sensorNode.addItem(DataTypeInt32, RStateGesture);
}
else if (modelId.startsWith(QLatin1String("RWL02"))) // || modelId.startsWith(QLatin1String("Z3-1BRL")))
else if (modelId.startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
// modelId.startsWith(QLatin1String("Z3-1BRL")) || // Lutron Aurora Firends-of-Hue dimmer switch
modelId.startsWith(QLatin1String("ROM00"))) // Hue smart button
{
sensorNode.addItem(DataTypeUInt16, RStateEventDuration);
}
Expand Down Expand Up @@ -5112,6 +5118,10 @@ void DeRestPluginPrivate::addSensorNode(const deCONZ::Node *node, const SensorFi
sensorNode.fingerPrint().inClusters.push_back(VENDOR_CLUSTER_ID);
}
}
else if (modelId.startsWith(QLatin1String("ROM00"))) // Hue smart button)
{
clusterId = VENDOR_CLUSTER_ID;
}
else if (modelId.startsWith(QLatin1String("SML00"))) // Hue motion sensor
{
if (type == QLatin1String("ZHASwitch"))
Expand Down Expand Up @@ -12597,6 +12607,7 @@ void DeRestPluginPrivate::handleCommissioningClusterIndication(TaskItem &task, c
(ind.srcAddress().hasNwk() && ind.srcAddress().nwk() == s.address().nwk()))
{
if (s.modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
s.modelId().startsWith(QLatin1String("ROM00")) || // Hue smart button
s.modelId().startsWith(QLatin1String("Z3-1BRL"))) // Lutron Aurora Friends-of-Hue dimmer switch
{
sensorNode = &s;
Expand Down Expand Up @@ -14131,6 +14142,7 @@ void DeRestPluginPrivate::delayedFastEnddeviceProbe(const deCONZ::NodeEvent *eve
}
}
else if (sensor->modelId().startsWith(QLatin1String("RWL02")) || // Hue dimmer switch
sensor->modelId().startsWith(QLatin1String("ROM00")) || // Hue smart button
sensor->modelId().startsWith(QLatin1String("Z3-1BRL"))) // Lutron Aurora Friends-of-Hue dimmer switch

{
Expand Down Expand Up @@ -14262,30 +14274,54 @@ void DeRestPluginPrivate::delayedFastEnddeviceProbe(const deCONZ::NodeEvent *eve
}
}
}
else if (sensor->modelId().startsWith(QLatin1String("ICZB-RM"))) // icasa remote
{
checkSensorGroup(sensor);
checkSensorBindingsForClientClusters(sensor);
}
else if (sensor->modelId().startsWith(QLatin1String("RC 110"))) // innr Remote
{
checkSensorGroup(sensor);
checkSensorBindingsForClientClusters(sensor);
}
else if (sensor->modelId() == QLatin1String("Remote switch"))// Legrand switch
else if (sensor->modelId().startsWith(QLatin1String("ICZB-RM")) || // icasa remote
sensor->modelId().startsWith(QLatin1String("RC 110")) || // innr Remote
sensor->modelId() == QLatin1String("Remote switch") || // Legrand switch
sensor->modelId().contains(QLatin1String("86opcn01")) || // Aqara Opple
sensor->modelId() == QLatin1String("Shutters central remote switch")) // Legrand switch
{
checkSensorGroup(sensor);
checkSensorBindingsForClientClusters(sensor);
}
else if (sensor->modelId().contains(QLatin1String("86opcn01"))) // Aqara Opple
{
checkSensorGroup(sensor);
checkSensorBindingsForClientClusters(sensor);
}
else if (sensor->modelId() == QLatin1String("Shutters central remote switch"))// Legrand switch
else if (sensor->modelId().startsWith(QLatin1String("902010/23"))) // Bitron remote control
{
checkSensorGroup(sensor);
checkSensorBindingsForClientClusters(sensor);

ResourceItem *item = sensor->item(RStateButtonEvent);

if (!item || !item->lastSet().isValid())
{
BindingTask bindingTask, bindingTask2;

bindingTask.state = BindingTask::StateIdle;
bindingTask.action = BindingTask::ActionBind;
bindingTask.restNode = sensor;
Binding &bnd = bindingTask.binding;
bnd.srcAddress = sensor->address().ext();
bnd.dstAddrMode = deCONZ::ApsExtAddress;
bnd.srcEndpoint = sensor->fingerPrint().endpoint;
bnd.clusterId = ONOFF_CLUSTER_ID;
bnd.dstAddress.ext = apsCtrl->getParameter(deCONZ::ParamMacAddress);
bnd.dstEndpoint = endpoint();

bindingTask2.state = BindingTask::StateIdle;
bindingTask2.action = BindingTask::ActionBind;
bindingTask2.restNode = sensor;
Binding &bnd2 = bindingTask2.binding;
bnd2.srcAddress = sensor->address().ext();
bnd2.dstAddrMode = deCONZ::ApsExtAddress;
bnd2.srcEndpoint = sensor->fingerPrint().endpoint;
bnd2.clusterId = LEVEL_CLUSTER_ID;
bnd2.dstAddress.ext = apsCtrl->getParameter(deCONZ::ParamMacAddress);
bnd2.dstEndpoint = endpoint();

if (bnd.dstEndpoint > 0) // valid gateway endpoint?
{
queueBindingTask(bindingTask);
queueBindingTask(bindingTask2);
}
}
}

for (auto &s : sensors)
Expand Down
18 changes: 16 additions & 2 deletions sensor.cpp
Expand Up @@ -682,6 +682,16 @@ static const Sensor::ButtonMap legrandShutterSwitchRemote[] = {
{ Sensor::ModeNone, 0x00, 0x0000, 0x00, 0, 0, nullptr }
};

static const Sensor::ButtonMap bitronRemoteMap[] = {
// mode ep cluster cmd param button name
{ Sensor::ModeScenes, 0x01, 0x0008, 0x06, 0, S_BUTTON_1 + S_BUTTON_ACTION_SHORT_RELEASED, "Step up (with on/off)" },
{ Sensor::ModeScenes, 0x01, 0x0006, 0x01, 0, S_BUTTON_2 + S_BUTTON_ACTION_SHORT_RELEASED, "On" },
{ Sensor::ModeScenes, 0x01, 0x0006, 0x00, 0, S_BUTTON_3 + S_BUTTON_ACTION_SHORT_RELEASED, "Off" },
{ Sensor::ModeScenes, 0x01, 0x0008, 0x06, 1, S_BUTTON_4 + S_BUTTON_ACTION_SHORT_RELEASED, "Step down (with on/off)" },
// end
{ Sensor::ModeNone, 0x00, 0x0000, 0x00, 0, 0, nullptr }
};


/*! Returns a fingerprint as JSON string. */
QString SensorFingerprint::toString() const
Expand Down Expand Up @@ -1241,14 +1251,18 @@ const Sensor::ButtonMap *Sensor::buttonMap()
}
else if (manufacturer == QLatin1String("Legrand"))
{
if (modelid == QLatin1String("Remote switch")) { m_buttonMap = legrandSwitchRemote; }
else if (modelid == QLatin1String("Shutters central remote switch")) { m_buttonMap = legrandShutterSwitchRemote; }
if (modelid == QLatin1String("Remote switch")) { m_buttonMap = legrandSwitchRemote; }
else if (modelid == QLatin1String("Shutters central remote switch")) { m_buttonMap = legrandShutterSwitchRemote; }
}
else if (manufacturer == QLatin1String("Sunricher"))
{
if (modelid.startsWith(QLatin1String("ZGRC-KEY"))) { m_buttonMap = sunricherCCTMap; }
else if (modelid.startsWith(QLatin1String("ZG2833K"))) { m_buttonMap = sunricherMap; }
}
else if (manufacturer == QLatin1String("Bitron Home"))
{
if (modelid.startsWith(QLatin1String("902010/23"))) { m_buttonMap = bitronRemoteMap; }
}
}

return m_buttonMap;
Expand Down

0 comments on commit 6d9c609

Please sign in to comment.