Lamp dimming & colour using Loxone + MiLight / EasyBulb / Limitless LED Bulbs

2,511 views
Skip to first unread message

TomM

unread,
Dec 14, 2015, 6:26:24 PM12/14/15
to loxone-...@googlegroups.com
I just thought I would raise a quick post about Milight / EasyBulb / Limitless LED bulbs and how they can integrate with Loxone as I've never seen anyone discuss it here and wanted to make people aware of the option.  Firstly, all 3 brands appear to be the same as each other and likely to be interchangeable, I personally have EasyBulb and MiLight bulbs all running off a MiLight controller and fully integrated with Loxone via UDP connection (1-way, Miniserver -> Milight Controller).

MiLight is a simple wireless IP connected LED RGBW bulb.  You can fully control brightness and RGBW levels to produce any effect you need and the bulbs come in most major formats.  At the heart of the system is a wireless network connected controller box (very small) and that communicates with up to four groups of bulbs.  You can group bulbs to act identically and each group can contain an unlimited (i think) number of bulbs.  You can also connect multiple wifi controllers, giving each its own IP.

As far as I can see, this is the only solution to enable full lighting control to a stand alone lamp.  You cannot achieve this with any combo of Loxone equipment, the only competitor is probably Phillips Hue but at at least twice the price.

A very brief guide to setting it up:

1. Connect the wifi controller to your wireless network as per instructions supplied with device
2. Connect each lamp to your desired group on a wifi controller as per instructions supplied with device
3. In Loxone Config add a device to a lighting controller as an RGB output
4. Create a program block which takes the output from the lighting controller as an analogue input (AI1 - AI13)
5. Use the following code within the program block, making sure you update the IP address and port number on line 14

With regards to the code, you could easily expand this to run 3-4 controllers giving you up to 16 groups of lamps, just need to handle more inputs and route to the correct controller box IP.  I also think that this could could actually be converted to logic blocks if necessary (as Loxone limits the number of code blocks you can use in a single miniserver), probably requires someone with a better logic brain that me though!

Hope this helps someone as I remember thinking this type of functionality was something that Loxone was missing when I first started investigating it.

NOTE: I did not write this code, it was taken from a post on the old Loxone forum in the German section.  I cannot currently find the post to credit it, but as soon as I do I will update this post.

int nEvents;
int n;




// Send UDP packet to wifi box,
// This function expect a code and a parameter
// The function tells the box what to do (Change color, on, off ...)
// The param tells gives the function some params
int SendUDP(int function, int param) {


 
int i = 0;
 
// Send every UDP command 3 times with an interval of 100ms
 
// This way we are sure that the command reaches the wifi box
 
do  {
    STREAM
* Socket = stream_create("/dev/udp/192.168.XXX.XXX/[PORT]",0,0);
   
if (Socket == NULL) {
      printf
("Creating UDP socket failed");
      stream_close
(Socket);
   
}


   
// Build the binary string to send
   
char command[3]={function, param, 0x55 };


    stream_write
(Socket,command,sizeof(command));
    stream_flush
(Socket); stream_close(Socket);
    i
= i + 1;
    sleep
(100);
 
} while (i < 3);
 
return 1;
}


// Gets called with the group ID
// This function will parse the RGB values received from the input
// Using the RGB values we convert them to Hue and Brightness, saturation is not needed
// Since our MiLight LEDS only accept a hue value and a brightness
int SetGroup(int group, float f1) {
 
char buffer[4];
 
char sR[4];
 
char sG[4];
 
char sB[4];
 
float red;
 
float green;
 
float blue;
 
float bri;
 
float r,g,b;
 
float X, Y, Z, cx, cy;
 
char input_color[10];
 
float hue;
 
float sat;
 
float milightColorNo;


  sprintf
(input_color, "%d", (int)f1);
  printf
("group: %d \n",group);


 
// The following code parses the RGB color
 
if (strlen(input_color) == 9) {
    sB
[0] = input_color[0]; sB[1] = input_color[1]; sB[2] = input_color[2]; sB[3] = '\0';
    sG
[0] = input_color[3]; sG[1] = input_color[4]; sG[2] = input_color[5]; sG[3] = '\0';
    sR
[0] = input_color[6]; sR[1] = input_color[7]; sR[2] = input_color[8]; sR[3] = '\0';
 
}
 
else if (strlen(input_color) == 8) {
    sB
[0] = '0'; sB[1] = input_color[0]; sB[2] = input_color[1]; sB[3] = '\0';
    sG
[0] = input_color[2]; sG[1] = input_color[3]; sG[2] = input_color[4]; sG[3] = '\0';
    sR
[0] = input_color[5]; sR[1] = input_color[6]; sR[2] = input_color[7]; sR[3] = '\0';
 
}
 
else if (strlen(input_color) == 7) {
    sB
[0] = '0'; sB[1] = '0'; sB[2] = input_color[0]; sB[3] = '\0';
    sG
[0] = input_color[1]; sG[1] = input_color[2]; sG[2] = input_color[3]; sG[3] = '\0';
    sR
[0] = input_color[4]; sR[1] = input_color[5]; sR[2] = input_color[6]; sR[3] = '\0';
 
}
 
else if (strlen(input_color) == 6) {
    sB
[0] = '0'; sB[1] = '0'; sB[2] = '0'; sB[3] = '\0';
    sG
[0] = input_color[0]; sG[1] = input_color[1]; sG[2] = input_color[2]; sG[3] = '\0';
    sR
[0] = input_color[3]; sR[1] = input_color[4]; sR[2] = input_color[5]; sR[3] = '\0';
 
}
 
else if (strlen(input_color) == 5) {
    sB
[0] = '0'; sB[1] = '0'; sB[2] = '0'; sB[3] = '\0';
    sG
[0] = '0'; sG[1] = input_color[0]; sG[2] = input_color[1]; sG[3] = '\0';
    sR
[0] = input_color[2]; sR[1] = input_color[3]; sR[2] = input_color[4]; sR[3] = '\0';
 
}
 
else if (strlen(input_color) == 4) {
    sB
[0] = '0'; sB[1] = '0'; sB[2] = '0'; sB[3] = '\0';
    sG
[0] = '0'; sG[1] = '0'; sG[2] = input_color[0]; sG[3] = '\0';
    sR
[0] = input_color[1]; sR[1] = input_color[2]; sR[2] = input_color[3]; sR[3] = '\0';
 
}
 
else if (strlen(input_color) == 3) {
    sB
[0] = '0'; sB[1] = '0'; sB[2] = '0'; sB[3] = '\0';
    sG
[0] = '0'; sG[1] = '0'; sG[2] = '0'; sG[3] = '\0';
    sR
[0] = input_color[0]; sR[1] = input_color[1]; sR[2] = input_color[2]; sR[3] = '\0';
 
}
 
else if (strlen(input_color) == 2) {
    sB
[0] = '0'; sB[1] = '0'; sB[2] = '0'; sB[3] = '\0';
    sG
[0] = '0'; sG[1] = '0'; sG[2] = '0'; sG[3] = '\0';
    sR
[0] = '0'; sR[1] = input_color[0]; sR[2] = input_color[1]; sR[3] = '\0';
 
}
 
else if (strlen(input_color) == 1) {
    sB
[0] = '0'; sB[1] = '0'; sB[2] = '0'; sB[3] = '\0';
    sG
[0] = '0'; sG[1] = '0'; sG[2] = '0'; sG[3] = '\0';
    sR
[0] = '0'; sR[1] = '0'; sR[2] = input_color[0]; sR[3] = '\0';
 
}


 
// Convert the strings back to int
  red
= atoi(sR);
  green
= atoi(sG);
  blue
= atoi(sB);
  printf
("red: %d \n",red);
  printf
("green: %d \n",green);
  printf
("blue: %d \n",blue);




   
// Clear older hue and sat values
   hue
= 0;
   sat
= 0;


 
// Convert based on RGB levels to HUE and Saturation
 
if ((red >= green) && (green >= blue)) {
    hue
= 60*(green-blue)/(red-blue);
    sat
= (red - blue) / red;
 
} else if ((green > red) && (red >= blue)) {
    hue
= 60*(2 - (red-blue)/(green-blue));
    sat
= (green - blue) / green;
 
} else if ((green >= blue) && (blue > red)) {
    hue
= 60*(2 + (blue-red)/(green-red));
    sat
= (green - red) / green;
 
} else if ((blue > green) && (green > red)) {
    hue
= 60*(4 - (green-red)/(blue-red));
    sat
= (blue - red) / blue;
 
} else if ((blue > red) && (red >= green)) {
    hue
= 60*(4 + (red-green)/(blue-green));
    sat
= (blue - green) / blue;
 
} else if ((red >= blue) && (blue > green)) {
    hue
= 60*(6 - (blue-green)/(red-green));
    sat
= (red - green) / red;
 
}


  sat
= sat * 255;




 
// set for safety again saturated at white
 
if (blue == 0 && green == 0 && red == 0) {
    sat
= 0;
 
}


 
// First map the 360 degrees value to a value of 0-255
  milightColorNo
=(176-(hue/360.0*255.0));
 
if ( milightColorNo < 0 ) {
    milightColorNo
= 256+ milightColorNo;
 
}


 
// Convert the saturation to the brightness
  bri
= sqrt(pow(red, 2) + pow(green, 2) + pow(blue, 2));
  bri
= bri * 2;
 
if (bri > 255) {
    bri
= 255;
 
}
 
// Falls nur 1 Farbe ein Thema, Helligkeit=Farbe
 
if (red == 0 && green == 0) {
    bri
= (blue * 255)/100;
 
}


 
if (blue == 0 && green == 0)
    bri
= (red * 255)/100;


 
if (red == 0 && blue == 0)
    bri
= (green * 255)/100;




 
// Milight only supports brightness levels from 2-27, so scale 0-255 to 0-27
  bri
=bri/255.0*27.0;
 
if ( bri < 3) {
    bri
=2;
 
}


 
// If all colors are the same level we get white, so set de RGB strip into white mode
 
if (red > 0 || green > 0 || blue > 0 ) {
   
if (red == green && green == blue && blue == red ) {
     
if (group == 1) {
       
// Set white mode for group 1
       
SendUDP( 0xC5, 0x00 );
     
}
     
if (group == 2) {
       
// Set white mode for group 2
       
SendUDP( 0xC7, 0x00 );
     
}
     
if (group == 3) {
       
// Set white mode for group 3
       
SendUDP( 0xC9, 0x00 );
     
}
     
if (group == 4) {
       
// Set white mode for group 4
       
SendUDP( 0xCB, 0x00 );
     
}


     
// Set brightness (Will be executed only for the group selected above)
     
SendUDP( 0x4E, (int) bri );


     
} else {
       
if (group == 1) {
         
// Group 1 on and if already on, select it
         
SendUDP( 0x45, 0x00 );
       
}
       
if (group == 2) {
         
// Group 2 on and if already on, select it
         
SendUDP( 0x47, 0x00 );
       
}
       
if (group == 3) {
         
// Group 3 on and if already on, select it
         
SendUDP( 0x49, 0x00 );
       
}
       
if (group == 4) {
         
// Group 4 on and if already on, select it
         
SendUDP( 0x4B, 0x00 );
       
}
       
// Set hue color (Will be executed only for the group selected above)
       
SendUDP( 0x40, milightColorNo );
       
// Set brightness (Will be executed only for the group selected above)
       
SendUDP( 0x4E, (int) bri );
     
}
   
} else {
     
if (group == 1) {
       
// Set group 1 off
       
SendUDP( 0x46, 0x00 );
     
}
     
if (group == 2) {
       
// Set group 2 off
       
SendUDP( 0x48, 0x00 );
     
}
     
if (group == 3) {
       
// Set group 3 off
       
SendUDP( 0x4A, 0x00 );
     
}
     
if (group == 4) {
       
// Set group 4 off
       
SendUDP( 0x4C, 0x00 );
     
}
   
}
   
return 1;
}




// Main Loop
while (1==1) {


  nEvents
= getinputevent();
 
//printf("this event: %d", nEvents);
 
// Test bitwise if input 4 is changed (00001000)
 
if (nEvents & 8) {
   
SetGroup(1, getinput(0));
 
}
 
// Test bitwise if input 5 is changed (00010000)
 
if (nEvents & 16) {
   
SetGroup(2, getinput(1));
 
}


 
// Test bitwise if input AI3 is changed (0x20) = 32
 
if (nEvents & 32) {
   
SetGroup(3, getinput(2));
 
}


 
// Test bitwise if input AI3 is changed (0x20) = 32
 
if (nEvents & 64) {
   
SetGroup(4, getinput(3));
 
}


  sleep
(500);
}



smartbusinesstools.be

unread,
Dec 31, 2015, 10:00:47 AM12/31/15
to Loxone English
Thanks for the info. Having a quick look at the API, I think you can control the lamps one-way using just virtual outputs and no PicoC, similar to what I do with Philips Hue and Osram Lightify lamps.
Can you tell us how well the white bulbs or GU10s can be dimmed down to 0%.
Message has been deleted

Dectro

unread,
Dec 1, 2016, 6:27:28 AM12/1/16
to Loxone English
Hi,

I'm from Belgium, and I'm currently wiring my home and will be using loxone in the future.
I do already have some milight bulbs which i can control with my phone, but I don't know how to get them working with Loxone..

Maybe TomM you could help me and give me a detailed description how to..? Do you make a virtual output in loxone config? Maybe we can pm or chat to give me the instructions? Don't know how i can contact you here in the google groups..?

Regards

Message has been deleted

Byron

unread,
Dec 2, 2016, 3:51:33 AM12/2/16
to Loxone English
Can you give some more info on how you connected Hue by just using virtual outputs?
Thanks

OnWaVo

unread,
Dec 3, 2016, 12:12:08 PM12/3/16
to Loxone English


I also use the Great and Cheap Milight bulbs with loxone.

Like the OP said, you have to update the IP adress on line 14

And you can indeed just use virtual outputs. Just use the command line with the correct code. (you can find them on the limitlessled website) (example: for the color red you have to fill in '\x40\xB0\x55')

If you dont know the ip adress just use the windows app from limitlessled. 

Here is an example in loxone.



Op donderdag 1 december 2016 12:27:28 UTC+1 schreef Dectro:

Nick Brown

unread,
Jan 3, 2017, 4:09:03 AM1/3/17
to Loxone English
Hi All, I have purchased 5 of these bulbs with the new wireless controller and they're great.  However I'm struggling to get this to work with my Loxone system, I've followed the guide and used the code provided (setting my IP and port) but nothing works at all.  To keep it simple I'm just using a virtual input in the app to switch the lights or change colours but nothing works.

What am I missing?

Thanks

Nick

Duncan

unread,
Jan 3, 2017, 6:00:13 AM1/3/17
to Loxone English

different versions of the controller seem to use different udp ports - its probably that part of the config thats the problem

use the windows app above to find and configure the device, then you have to log into its web page to configure the udp port for sending loxone commands to - its not the same port as used for discovery, then set the loxone pico-c to use the correct udp port for commands

Nick Brown

unread,
Jan 4, 2017, 3:15:09 AM1/4/17
to Loxone English
Hi Duncan, thank you for the guidance, yes my port and protocol were different so I changed them to match your screenshot (UDP & 8899) but still no joy.  I also noticed the IP address was a private IP not on my network so changed it to match the IP of the hub but still no luck.  The IP and port on line 14 were changed to match this too.

Is the serial port parameters important as mine are different?  Can you confirm if the IP in the 'other settings' is the same as the IP for the hub/web?

I will try a bit more tonight and see how it goes.

Duncan

unread,
Jan 4, 2017, 4:26:15 AM1/4/17
to Loxone English
i set mine to use the same IP address for web access and udp access, checked the settings in the pico-c and then it all worked fine.

i use a 255.255.252 subnet, and had problems when i used an ip address in the 192.168.2.x range for the mifi controller but it works fine with loxone on 192.168.2.x and the mifi controller on 192.168.0.x as long as the subnet addresses are correct

Nick Brown

unread,
Jan 7, 2017, 5:49:40 AM1/7/17
to Loxone English
I've tried again and still no luck, the limitlessled windows app sees the hub and you can read write settings but none of the commands work for switching bulbs on/off or changing colour.  I think it is down to the fact that the bulbs and hub i bought are made by http://www.milight.com/ not limilessled, what brand is everyone else using?

Duncan

unread,
Jan 9, 2017, 2:58:11 PM1/9/17
to loxone-...@googlegroups.com


mine is the mi-light one and works fine

the only thing i did was to set up the mi-light IP as fixed, the UDP port as above and changed the line of the code to the correct address

Nick Brown

unread,
Jan 10, 2017, 4:35:02 AM1/10/17
to Loxone English
That is what I have done too.  Can you confirm what version of wifi hub you have, mine is the newest one http://www.milight.com/milight-wifi-receiver-bridge-3-0-controller-box/ which is also a lamp?

Also can you control your lamps using the limitlessled V6 windows app, or even the iPhone app they do as I can't?  Only the iPhone Mi-Light app works for me.

Thanks
Message has been deleted

Giuseppe Di Lella

unread,
Feb 12, 2017, 4:10:50 PM2/12/17
to Loxone English
Hello,
can you please tell me, what I need to modify in the program to run rgbw stripe?
I tried it with loxone but only the rgb is working, and not the white lamps.
Do you have a suggestion?
regards,
Giuseppe

Robin Downes

unread,
Feb 13, 2017, 11:10:12 AM2/13/17
to loxone-...@googlegroups.com

On Sunday, February 12, 2017 at 9:10:50 PM UTC, Giuseppe Di Lella wrote: 
Hello,
can you please tell me, what I need to modify in the program to run rgbw stripe?
I tried it with loxone but only the rgb is working, and not the white lamps.
Do you have a suggestion?
regards,
Giuseppe

Unfortunately the Lighting Controller Block only controls RGBW stripe as as two seperate lights:
  1. 3 channel RGB (Colour picker & brightness slider in the App)
  2. 1 channel White (Brightness slider in the App)
I've just started a thread to ask if anyone has any ideas in config to allow the Lighting Controller Block to control the full RGBW, rather than only the RGB.
Reply all
Reply to author
Forward
0 new messages