@@ -574,11 +574,7 @@ int DeRestPluginPrivate::setLightState(const ApiRequest &req, ApiResponse &rsp)
574
574
}
575
575
576
576
// FIXME temporary workaround to support window_covering
577
- bool isWindowCoveringDevice = false ;
578
- if (taskRef.lightNode ->type () == QLatin1String (" Window covering device" ))
579
- {
580
- isWindowCoveringDevice = true ;
581
- }
577
+ bool isWindowCoveringDevice = taskRef.lightNode ->type () == QLatin1String (" Window covering device" );
582
578
583
579
// on/off
584
580
if (hasOn)
@@ -598,6 +594,7 @@ int DeRestPluginPrivate::setLightState(const ApiRequest &req, ApiResponse &rsp)
598
594
TaskItem task;
599
595
copyTaskReq (taskRef, task);
600
596
// FIXME workaround window_convering
597
+ // FIXME handle lumi.curtain.hagl04
601
598
if (isWindowCoveringDevice
602
599
&& addTaskWindowCovering (task, isOn ? 0x01 /* down*/ : 0x00 /* up*/ , 0 , 0 ))
603
600
{
@@ -682,60 +679,103 @@ int DeRestPluginPrivate::setLightState(const ApiRequest &req, ApiResponse &rsp)
682
679
// FIXME workaround window_covering
683
680
if (isWindowCoveringDevice)
684
681
{
685
- if ((map[" bri" ].type () == QVariant::String) && map[" bri" ].toString () == " stop" )
686
- {
687
- TaskItem task;
688
- copyTaskReq (taskRef, task);
689
- if (addTaskWindowCovering (task, 0x02 /* stop motion*/ , 0 , 0 ))
690
- {
691
- QVariantMap rspItem;
692
- QVariantMap rspItemState;
693
- rspItemState[QString (" /groups/%1/action/bri" ).arg (id)] = map[" bri" ];
694
- rspItem[" success" ] = rspItemState;
695
- rsp.list .append (rspItem);
696
- taskToLocalData (task);
697
- }
698
- else
699
- {
700
- rsp.list .append (errorToMap (ERR_INTERNAL_ERROR, QString (" /lights/%1" ).arg (id), QString (" Internal error, %1" ).arg (ERR_BRIDGE_BUSY)));
701
- }
702
- }
703
- else if (ok && (map[" bri" ].type () == QVariant::Double) && (bri < 256 ))
704
- {
705
- TaskItem task;
706
- copyTaskReq (taskRef, task);
707
- uint8_t moveToPct = 0x00 ;
708
- moveToPct = bri * 100 / 254 ; // Percent 0 - 100 (0x00 - 0x64)
682
+ if ((map[" bri" ].type () == QVariant::String) && map[" bri" ].toString () == " stop" )
683
+ {
684
+ TaskItem task;
685
+ copyTaskReq (taskRef, task);
686
+ if (addTaskWindowCovering (task, 0x02 /* stop motion*/ , 0 , 0 ))
687
+ {
688
+ QVariantMap rspItem;
689
+ QVariantMap rspItemState;
690
+ rspItemState[QString (" /groups/%1/action/bri" ).arg (id)] = map[" bri" ];
691
+ rspItem[" success" ] = rspItemState;
692
+ rsp.list .append (rspItem);
693
+ taskToLocalData (task);
694
+ }
695
+ else
696
+ {
697
+ rsp.list .append (errorToMap (ERR_INTERNAL_ERROR, QString (" /lights/%1" ).arg (id), QString (" Internal error, %1" ).arg (ERR_BRIDGE_BUSY)));
698
+ }
699
+ }
700
+ else if (ok && (map[" bri" ].type () == QVariant::Double) && (bri < 256 ))
701
+ {
702
+ bool ok = false ;
703
+ TaskItem task;
704
+ copyTaskReq (taskRef, task);
705
+ uint8_t moveToPct = 0x00 ;
706
+ moveToPct = bri * 100 / 254 ; // Percent 0 - 100 (0x00 - 0x64)
709
707
if (taskRef.lightNode ->modelId ().startsWith (QLatin1String (" lumi.curtain" )) )
710
708
{
711
709
moveToPct = 100 - moveToPct;
712
710
}
713
- // Legrand invert bri and don't support other value than 0
714
711
if (taskRef.lightNode ->modelId () == QLatin1String (" Shutter switch with neutral" ))
715
712
{
716
- if (bri == 0 )
717
- {
718
- moveToPct = 254 ;
713
+ // Legrand invert bri and don't support other value than 0
714
+ moveToPct = (bri == 0 ) ? 254 : 0 ;
715
+ }
716
+ if (taskRef.lightNode ->modelId ().startsWith (QLatin1String (" lumi.curtain" ))) // FIXME - used for testing.
717
+ // if (taskRef.lightNode->modelId().startsWith(QLatin1String("lumi.curtain.hagl04")))
718
+ {
719
+ float value = moveToPct;
720
+ TaskItem task;
721
+ copyTaskReq (taskRef, task);
722
+
723
+ // FIXME: The following low-level code is needed because ZclAttribute is broken for ZclSingleFloat.
724
+
725
+ task.taskType = TaskWriteAttribute;
726
+
727
+ task.req .setClusterId (ANALOG_OUTPUT_CLUSTER_ID);
728
+ task.req .setProfileId (HA_PROFILE_ID);
729
+ task.zclFrame .setSequenceNumber (zclSeq++);
730
+ task.zclFrame .setCommandId (deCONZ::ZclWriteAttributesId);
731
+ task.zclFrame .setFrameControl (deCONZ::ZclFCProfileCommand |
732
+ deCONZ::ZclFCDirectionClientToServer |
733
+ deCONZ::ZclFCDisableDefaultResponse);
734
+
735
+ DBG_Printf (DBG_INFO, " write attribute of 0x%016llX ep: 0x%02X cluster: 0x%04X: 0x%04X\n " , taskRef.lightNode ->address ().ext (), taskRef.lightNode ->haEndpoint ().endpoint (), ANALOG_OUTPUT_CLUSTER_ID, 0x0055 );
736
+
737
+ { // payload
738
+ QDataStream stream (&task.zclFrame .payload (), QIODevice::WriteOnly);
739
+ stream.setByteOrder (QDataStream::LittleEndian);
740
+ stream.setFloatingPointPrecision (QDataStream::SinglePrecision);
741
+
742
+ stream << (quint16) 0x0055 ;
743
+ stream << (quint8) deCONZ::ZclSingleFloat;
744
+ stream << value;
719
745
}
720
- else
721
- {
722
- moveToPct = 0 ;
746
+
747
+ { // ZCL frame
748
+ QDataStream stream (&task.req .asdu (), QIODevice::WriteOnly);
749
+ stream.setByteOrder (QDataStream::LittleEndian);
750
+ task.zclFrame .writeToStream (stream);
723
751
}
752
+
753
+ ok = addTask (task);
754
+
755
+ // FIXME: Use following code once ZclAttribute has been fixed.
756
+
757
+ // deCONZ::ZclAttribute attr(0x0055, deCONZ::ZclSingleFloat, "value", deCONZ::ZclReadWrite, true);
758
+ // attr.setValue(QVariant(value));
759
+ // ok = writeAttribute(taskRef.lightNode, taskRef.lightNode->haEndpoint().endpoint(), ANALOG_OUTPUT_CLUSTER_ID, attr);
724
760
}
725
- if (addTaskWindowCovering (task, 0x05 /* move to Lift Percent*/ , 0 , moveToPct))
726
- {
727
- QVariantMap rspItem;
728
- QVariantMap rspItemState;
729
- rspItemState[QString (" /lights/%1/state/bri" ).arg (id)] = map[" bri" ];
730
- rspItem[" success" ] = rspItemState;
731
- rsp.list .append (rspItem);
732
- taskToLocalData (task);
733
- }
734
- else
735
- {
736
- rsp.list .append (errorToMap (ERR_INTERNAL_ERROR, QString (" /lights/%1" ).arg (id), QString (" Internal error, %1" ).arg (ERR_BRIDGE_BUSY)));
737
- }
738
- }
761
+ else
762
+ {
763
+ ok = addTaskWindowCovering (task, 0x05 /* move to Lift Percent*/ , 0 , moveToPct);
764
+ }
765
+ if (ok)
766
+ {
767
+ QVariantMap rspItem;
768
+ QVariantMap rspItemState;
769
+ rspItemState[QString (" /lights/%1/state/bri" ).arg (id)] = map[" bri" ];
770
+ rspItem[" success" ] = rspItemState;
771
+ rsp.list .append (rspItem);
772
+ taskToLocalData (task);
773
+ }
774
+ else
775
+ {
776
+ rsp.list .append (errorToMap (ERR_INTERNAL_ERROR, QString (" /lights/%1" ).arg (id), QString (" Internal error, %1" ).arg (ERR_BRIDGE_BUSY)));
777
+ }
778
+ }
739
779
} // FIXME end workaround window_covering
740
780
else if (!isOn && !hasOn)
741
781
{
0 commit comments