Skip to content

Commit 18ad1a2

Browse files
committed
RFLink: added initial MiLight support
1 parent 1660d9a commit 18ad1a2

File tree

2 files changed

+170
-49
lines changed

2 files changed

+170
-49
lines changed

hardware/RFLinkBase.cpp

Lines changed: 166 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ const _tRFLinkStringIntHelper rfswitchcommands[] =
119119
{ "UP", blinds_sOpen },
120120
{ "DOWN", blinds_sClose },
121121
{ "STOP", gswitch_sStop },
122+
{ "COLOR", gswitch_sColor },
123+
{ "DISCO+", gswitch_sDiscop },
124+
{ "DISCO-", gswitch_sDiscom },
122125
{ "", -1 }
123126
};
124127

@@ -133,6 +136,7 @@ const _tRFLinkStringIntHelper rfblindcommands[] =
133136
};
134137

135138

139+
136140
int GetGeneralRFLinkFromString(const _tRFLinkStringIntHelper *pTable, const std::string &szType)
137141
{
138142
int ii = 0;
@@ -161,7 +165,6 @@ CRFLinkBase::CRFLinkBase()
161165
{
162166
m_rfbufferpos=0;
163167
memset(&m_rfbuffer,0,sizeof(m_rfbuffer));
164-
165168
/*
166169
ParseLine("20;08;NewKaku;ID=31c42a;SWITCH=2;CMD=OFF;");
167170
ParseLine("20;3A;NewKaku;ID=c142;SWITCH=1;CMD=ALLOFF;");
@@ -226,59 +229,170 @@ bool CRFLinkBase::WriteToHardware(const char *pdata, const unsigned char length)
226229
{
227230
const _tGeneralSwitch *pSwitch = reinterpret_cast<const _tGeneralSwitch*>(pdata);
228231

229-
if (pSwitch->type != pTypeGeneralSwitch)
230-
return false; //only allowed to control switches
232+
if ((pSwitch->type != pTypeGeneralSwitch) && (pSwitch->type != pTypeLimitlessLights))
233+
return false; //only allowed to control regular switches and MiLight
231234

235+
//_log.Log(LOG_ERROR, "RFLink: switch type: %d", pSwitch->subtype);
232236
std::string switchtype = GetGeneralRFLinkFromInt(rfswitches, pSwitch->subtype);
233237
if (switchtype.empty())
234238
{
235239
_log.Log(LOG_ERROR, "RFLink: trying to send unknown switch type: %d", pSwitch->subtype);
236240
return false;
237241
}
238-
std::string switchcmnd = GetGeneralRFLinkFromInt(rfswitchcommands, pSwitch->cmnd);
239-
240-
// check setlevel command
241-
if (pSwitch->cmnd == gswitch_sSetLevel) {
242-
// Get device level to set
243-
float fvalue = (15.0f / 100.0f)*float(pSwitch->level);
244-
if (fvalue > 15.0f)
245-
fvalue = 15.0f; //99 is fully on
246-
int svalue = round(fvalue);
247-
//_log.Log(LOG_ERROR, "RFLink: level: %d", svalue);
248-
char buffer[50] = {0};
249-
sprintf(buffer, "%d", svalue);
250-
switchcmnd = buffer;
251-
}
242+
//_log.Log(LOG_ERROR, "RFLink: subtype: %d", pSwitch->subtype);
243+
244+
if (pSwitch->type == pTypeGeneralSwitch) {
245+
std::string switchcmnd = GetGeneralRFLinkFromInt(rfswitchcommands, pSwitch->cmnd);
246+
247+
// check setlevel command
248+
if (pSwitch->cmnd == gswitch_sSetLevel) {
249+
// Get device level to set
250+
float fvalue = (15.0f / 100.0f)*float(pSwitch->level);
251+
if (fvalue > 15.0f)
252+
fvalue = 15.0f; //99 is fully on
253+
int svalue = round(fvalue);
254+
//_log.Log(LOG_ERROR, "RFLink: level: %d", svalue);
255+
char buffer[50] = {0};
256+
sprintf(buffer, "%d", svalue);
257+
switchcmnd = buffer;
258+
}
252259

253-
if (switchcmnd.empty())
254-
{
255-
_log.Log(LOG_ERROR, "RFLink: trying to send unknown switch command: %d", pSwitch->cmnd);
256-
return false;
257-
}
260+
if (switchcmnd.empty()) {
261+
_log.Log(LOG_ERROR, "RFLink: trying to send unknown switch command: %d", pSwitch->cmnd);
262+
return false;
263+
}
258264

259-
//Build send string
260-
std::stringstream sstr;
261-
//10;NewKaku;00c142;1;ON; => protocol;address;button number;action (ON/OFF/ALLON/ALLOFF/15 -11-15 for dim level)
265+
//Build send string
266+
std::stringstream sstr;
267+
//10;NewKaku;00c142;1;ON; => protocol;address;button number;action (ON/OFF/ALLON/ALLOFF/15 -11-15 for dim level)
262268

263-
sstr << "10;" << switchtype << ";" << std::hex << std::nouppercase << std::setw(6) << std::setfill('0') << pSwitch->id << ";" << std::hex << std::nouppercase << pSwitch->unitcode << ";" << switchcmnd;
269+
sstr << "10;" << switchtype << ";" << std::hex << std::nouppercase << std::setw(6) << std::setfill('0') << pSwitch->id << ";" << std::hex << std::nouppercase << pSwitch->unitcode << ";" << switchcmnd;
264270
//#ifdef _DEBUG
265-
_log.Log(LOG_STATUS, "RFLink Sending: %s", sstr.str().c_str());
271+
_log.Log(LOG_STATUS, "RFLink Sending: %s", sstr.str().c_str());
266272
//#endif
267-
sstr << "\n";
268-
m_bTXokay = false; // clear OK flag
269-
WriteInt(sstr.str());
270-
time_t atime = mytime(NULL);
271-
time_t btime = mytime(NULL);
273+
sstr << "\n";
274+
m_bTXokay = false; // clear OK flag
275+
WriteInt(sstr.str());
276+
time_t atime = mytime(NULL);
277+
time_t btime = mytime(NULL);
272278

273-
// Wait for an OK response from RFLink to make sure the command was executed
274-
while (m_bTXokay == false) {
275-
if (btime-atime > 4) {
276-
_log.Log(LOG_ERROR, "RFLink: TX time out...");
279+
// Wait for an OK response from RFLink to make sure the command was executed
280+
while (m_bTXokay == false) {
281+
if (btime-atime > 4) {
282+
_log.Log(LOG_ERROR, "RFLink: TX time out...");
283+
return false;
284+
}
285+
btime = mytime(NULL);
286+
}
287+
return true;
288+
}
289+
else { // RFLink Milight extension
290+
_tLimitlessLights *pLed = (_tLimitlessLights*)pdata;
291+
292+
//_log.Log(LOG_ERROR, "RFLink: ledtype: %d", pLed->type); // type limitlessled
293+
//_log.Log(LOG_ERROR, "RFLink: subtype: %d", pLed->subtype); // rgbw/rgb/white?
294+
//_log.Log(LOG_ERROR, "RFLink: id: %d", pLed->id); // id
295+
//_log.Log(LOG_ERROR, "RFLink: unit: %d", pLed->dunit); // unit 0=All, 1=Group1,2=Group2,3=Group3,4=Group4
296+
//_log.Log(LOG_ERROR, "RFLink: command: %d", pLed->command); // command
297+
//_log.Log(LOG_ERROR, "RFLink: value: %d", pLed->value); // brightness/color value
298+
299+
const int m_LEDType = pLed->type;
300+
std::string switchtype = GetGeneralRFLinkFromInt(rfswitches, 0x57);
301+
std::string switchcmnd = GetGeneralRFLinkFromInt(rfswitchcommands, pLed->command);
302+
unsigned int m_colorbright = 0;
303+
304+
switch (pLed->command){
305+
case Limitless_LedOn:
306+
switchcmnd = "ON";
307+
break;
308+
case Limitless_LedOff:
309+
switchcmnd = "OFF";
310+
break;
311+
case Limitless_SetRGBColour:
312+
{
313+
//The Hue is inverted/swifted 90 degrees
314+
int iHue = ((255 - pLed->value) + 192) & 0xFF;
315+
//_log.Log(LOG_ERROR, "RFLink: hue: %d", iHue);
316+
//RGBWSetColor[1] = (unsigned char)iHue;
317+
m_colorbright = m_colorbright & 0xff;
318+
m_colorbright = (((unsigned char) iHue) << 8) + m_colorbright;
319+
switchcmnd = "COLOR";
320+
}
321+
break;
322+
case Limitless_DiscoSpeedSlower:
323+
switchcmnd = "DISCO-";
324+
break;
325+
case Limitless_DiscoSpeedFaster:
326+
switchcmnd = "DISCO+";
327+
break;
328+
case Limitless_DiscoMode:
329+
switchcmnd = "MODE";
330+
break;
331+
case Limitless_SetColorToWhite:
332+
switchcmnd = "ALLON";
333+
break;
334+
case Limitless_SetBrightnessLevel:
335+
{
336+
//convert brightness (0-100) to (0-50) to 0-59
337+
double dval = (59.0 / 100.0)*float(pLed->value / 2);
338+
int ival = round(dval);
339+
if (ival<2)
340+
ival = 2;
341+
if (ival>27)
342+
ival = 27;
343+
//_log.Log(LOG_ERROR, "RFLink: brightness: %d", ival);
344+
m_colorbright = m_colorbright & 0xff00;
345+
m_colorbright = m_colorbright + (unsigned char) ival;
346+
switchcmnd = "BRIGHT";
347+
//RGBWSetBrightnessLevel[1] = (unsigned char)ival;
348+
}
349+
break;
350+
351+
// need work:
352+
case Limitless_SetBrightUp:
353+
switchcmnd = "BRIGHT";
354+
break;
355+
case Limitless_SetBrightDown:
356+
switchcmnd = "BRIGHT";
357+
break;
358+
case Limitless_DiscoSpeedFasterLong:
359+
switchcmnd = "DISCO+";
360+
break;
361+
case Limitless_RGBDiscoNext:
362+
switchcmnd = "DISCO+";
363+
break;
364+
case Limitless_RGBDiscoPrevious:
365+
switchcmnd = "DISCO-";
366+
break;
367+
default:
368+
_log.Log(LOG_ERROR, "RFLink: trying to send unknown led switch command: %d", pLed->command);
277369
return false;
278-
}
279-
btime = mytime(NULL);
370+
}
371+
372+
//Build send string
373+
std::stringstream sstr;
374+
//10;MiLightv1;1234;01;5566;ON; => protocol;address;unit number;color&brightness;action (ON/OFF/ALLON/ALLOFF etc)
375+
376+
sstr << "10;" << switchtype << ";" << std::hex << std::nouppercase << std::setw(4) << std::setfill('0') << pLed->id << ";" << std::setw(2) << std::setfill('0') << int(pLed->dunit) << ";" << std::hex << std::nouppercase << std::setw(4) << m_colorbright << ";" << switchcmnd;
377+
//#ifdef _DEBUG
378+
_log.Log(LOG_STATUS, "RFLink Sending: %s", sstr.str().c_str());
379+
//#endif
380+
sstr << "\n";
381+
m_bTXokay = false; // clear OK flag
382+
WriteInt(sstr.str());
383+
time_t atime = mytime(NULL);
384+
time_t btime = mytime(NULL);
385+
386+
// Wait for an OK response from RFLink to make sure the command was executed
387+
while (m_bTXokay == false) {
388+
if (btime - atime > 4) {
389+
_log.Log(LOG_ERROR, "RFLink: TX time out...");
390+
return false;
391+
}
392+
btime = mytime(NULL);
393+
}
394+
return true;
280395
}
281-
return true;
282396
}
283397

284398
bool CRFLinkBase::SendSwitchInt(const int ID, const int switchunit, const int BatteryLevel, const std::string &switchType, const std::string &switchcmd, const int level)
@@ -770,16 +884,6 @@ bool CRFLinkBase::ParseLine(const std::string &sLine)
770884
SendSoundSensor(ID, BatteryLevel, sound, tmp_Name);
771885
}
772886

773-
if (bHaveRGB)
774-
{
775-
//RRGGBB
776-
SendRGBWSwitch(Node_ID, Child_ID, BatteryLevel, rgb, false, tmp_Name);
777-
}
778-
if (bHaveRGBW)
779-
{
780-
//RRGGBBWW
781-
SendRGBWSwitch(Node_ID, Child_ID, BatteryLevel, rgbw, true, tmp_Name);
782-
}
783887
if (bHaveBlind)
784888
{
785889
SendBlindSensor(Node_ID, Child_ID, BatteryLevel, blind, tmp_Name);
@@ -821,6 +925,19 @@ bool CRFLinkBase::ParseLine(const std::string &sLine)
821925
{
822926
SendPercentageSensor(Node_ID, Child_ID, BatteryLevel, impedance, tmp_Name);
823927
}
928+
929+
if (bHaveRGB)
930+
{
931+
//RRGGBB
932+
_log.Log(LOG_STATUS, "RFLink ID,unit: %x , %x", Node_ID, Child_ID);
933+
SendRGBWSwitch(ID, switchunit, BatteryLevel, rgb, false, tmp_Name);
934+
} else
935+
if (bHaveRGBW)
936+
{
937+
//RRGGBBWW
938+
_log.Log(LOG_STATUS, "RFLink ID,unit: %x , %x", Node_ID, Child_ID);
939+
SendRGBWSwitch(ID, switchunit, BatteryLevel, rgbw, true, tmp_Name);
940+
} else
824941
if (bHaveSwitch && bHaveSwitchCmd)
825942
{
826943
std::string switchType = results[2];

hardware/hardwaretypes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@
176176
#define gswitch_sPlayPlaylist 0x16
177177
#define gswitch_sPlayFavorites 0x17
178178
#define gswitch_sExecute 0x18
179+
#define gswitch_sColor 0x19
180+
#define gswitch_sDiscop 0x1a
181+
#define gswitch_sDiscom 0x1b
182+
179183
//--------------
180184

181185
#define pTypeLux 0xF6

0 commit comments

Comments
 (0)