Smart Bike Lights (Data Field) / Bike Lights Control (Widget)

I've made two open source CIQ applications to control ANT+ lights:

- Smart Bike Lights (data field): https://apps.garmin.com/en-US/apps/0d9fd828-c932-4470-9c37-fd2828881888 

      Configurator: https://maca88.github.io/SmartBikeLights/ 

- Bike Lights Control (widget): https://apps.garmin.com/en-US/apps/fa3c2332-76e3-4ba1-8528-32a0fd617ab1 

     Configurator: https://maca88.github.io/BikeLightsControl/ 

Smart Bike Lights features:
- Automatic light control (Smart mode) based on the configured filters (sunset, sunlight, speed, ...)
- Manual light control (only for Edge devices with a touch screen or devices with CIQ 3.2 and more than 32KB memory)
- Records lights modes that are displayed in Garmin Connect

Bike Lights Control features:
- Manual light control (available to all devices)

Both applications can be installed on the same device, which can be useful for low end devices (e.g. Edge 520) where "Bike Lights Control" can be used to change light modes manually and "Smart Bike Lights" for automatic light control.

Currently registered ANT+ lights:
- Bontrager Ion Pro RT
- Bontrager Ion 200 RT
- Bontrager Flare RT
- Garmin Varia RTL500
- Garmin Varia RTL510
- Garmin Varia RTL515
- Garmin Varia HL500
- Garmin Varia UT800

in case your ANT+ light is not on the list you can help by doing the following:

1. Install Bike Lights Control
2. Pair your bike light with your Garmin device
3. Open the widget:
- Edge with a touch screen: post which numbers are displayed on the buttons and what mode each button represents when pressed
- Other devices: Select the "Light modes" menu and post which numbers are displayed in the menu and what mode each menu item represents when selected

Example for Bontrager Ion Pro RT:


1 -> High steady beam
2 -> Medium steady beam
5 -> Low steady beam
63 -> Day flash
62 -> Night flash

There are some features that could be possible to add in the future, but would require Garmin to add them to the CIQ api. In case you are interested in any of the below features, consider upvoting their feature request thread:

1. Control lights based on the ambient light sensor available on some devices:
https://forums.garmin.com/developer/connect-iq/i/bug-reports/ambient-light-sensor-api-access 

Known issues:

1. Unable to use Tempe Visualizer or TyreWiz Data Field alongside Smart Bike Lights:
https://forums.garmin.com/developer/connect-iq/i/bug-reports/lightnetworklistener-onbikelightupdate-not-called-when-certain-data-fields-are-installed

  • Thanks so much - works perfect now. Funny thing is that it worked ok on my 520 Plus but clearly I entered something wrong for my new 840. I appreciate your help!

  • BirdLight.txt
    using Toybox.Graphics as Gfx;
    using Toybox.WatchUi as Ui;
    using Toybox.Application as App;
    using Toybox.AntPlus;
    
    var xListenr;
    var xNetwork;
    var xNmode;
    var xLight;
    var xLmode;
    
    var xTest=0;
    
    
    class MyLightNetworkListener extends AntPlus.LightNetworkListener
    {
    	var lList;
    	var lLight;
    
    	
        function onLightNetworkStateUpdate(data)
    	{
    		xNmode=data;	// LIGHT_NETWORK_STATE: NOT_FORMED = 0, FORMING = 1, FORMED = 2
    		xTest+=1000000;
    		
            if (data==AntPlus.LIGHT_NETWORK_STATE_FORMED)
    		{
    			lList= xNetwork.getBikeLights();
    			if (lList != null)
    			{
    				// nMode=xNetwork.getNetworkMode();    
    				
    				var i=0, found=0;
    				for (i=0; i<lList.size(); i++)
    				{
    					lLight=lList[i];
    					if (lLight.type==AntPlus.LIGHT_TYPE_TAILLIGHT)
    					// LIGHT_TYPE_HEADLIGHT 0, LIGHT_TYPE_TAILLIGHT 2, LIGHT_TYPE_SIGNAL_CONFIG 3, LIGHT_TYPE_SIGNAL_LEFT 4, LIGHT_TYPE_SIGNAL_RIGHT 5, LIGHT_TYPE_OTHER 7
    					{
    						xLight=lLight;
    						xLmode=lLight.mode;
    						found=1;
    						//xLid=lLight.identifier;
    						//xLman=xNetwork.getManufacturerInfo(xLid).modelNumber; // .manufacturerId;
    						//xLprd=xNetwork.getProductInfo(xLid).serial;
    						//xLbat=xNetwork.getBatteryStatus(xLid).batteryStatus;	// batteryVoltage=-1.000;
    					}
    					if (found==0)
    					{
    						xLight=null;
    					}
    				}   
    			}
    			else
    			{
    				xLight=null;
    			}
    		}
        }
    }
    
    class BirdField extends Ui.DataField
    {
    
    	var aRadar= new[8];
    	var bRadar;
    
    	function initialize()
    	{
            xListenr= new MyLightNetworkListener();
            xNetwork= new AntPlus.LightNetwork(xListenr);
    		bRadar=	  Toybox.AntPlus has :BikeRadar ? new AntPlus.BikeRadar(null) : null;
    		View.initialize();
    	}
    
    	
    	function onLayout(dc) as Void
    	{
    		dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
    		dc.fillRectangle(0, 0, dc.getWidth(), dc.getHeight());
    	}
    
    
    	function onShow() as Void
    	{
    	}
    
    
    	function onUpdate(dc) as Void
    	{
    		var i;
    		var bat;
    		
    		xTest+=1;
    		dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_TRANSPARENT);
            dc.drawText(10,350,Gfx.FONT_TINY,xTest,Gfx.TEXT_JUSTIFY_LEFT);
    		
    		for(i=0; i<8; i++)
    		{
    			dc.drawText(10,i*30,Graphics.FONT_SMALL,aRadar[i],Graphics.TEXT_JUSTIFY_LEFT);
    		}
    	
    		if (xNmode==2)
    		{
                dc.drawText(10,400,Gfx.FONT_TINY,"NETWORK READY",Gfx.TEXT_JUSTIFY_LEFT);
                dc.drawText(10,430,Gfx.FONT_TINY,"LIGHT: "+xLight.identifier,Gfx.TEXT_JUSTIFY_LEFT);
    			if (xLight!=null)
    			{
    				dc.drawText(10,460,Gfx.FONT_TINY,"MODE: "+xLmode+", "+xLight.mode,Gfx.TEXT_JUSTIFY_LEFT);
    				bat=xNetwork.getBatteryStatus(xLight.identifier).batteryStatus;	// batteryVoltage=-1.000;
    				// BATT_STATUS_NEW = 1, BATT_STATUS_GOOD = 2, BATT_STATUS_OK = 3, BATT_STATUS_LOW = 4, BATT_STATUS_CRITICAL = 5 
    				dc.drawText(10,490,Gfx.FONT_TINY,"BATT: "+bat,Gfx.TEXT_JUSTIFY_LEFT);
    			}
    		
    		}
    		else if (xNmode==1)
    		{
                dc.drawText(10,400,Gfx.FONT_TINY,"NETWORK INIT",Gfx.TEXT_JUSTIFY_LEFT);
    		}
    		else
    		{
                dc.drawText(10,400,Gfx.FONT_TINY,"NETWORK DOWN",Gfx.TEXT_JUSTIFY_LEFT);
    		}
    		
    
    	/*
    		var mode=(mode+1)%20;
            if (mode==10)
    		{
    			dc.drawText(10,730,Graphics.FONT_SMALL,"RESET",Graphics.TEXT_JUSTIFY_LEFT);		
    			// xNetwork.restoreTaillightsNetworkModeControl();
            }
            else if (mode==0)
    		{
    			dc.drawText(10,730,Graphics.FONT_SMALL,"PULSE",Graphics.TEXT_JUSTIFY_LEFT);		
    			xNetwork.setTaillightsMode(6);
    			// xLight.setMode(6);
    			// xNetwork.setTaillightsMode(AntPlus.LIGHT_MODE_FAST_FLASH); // 0: off, 4:ein, 5:hell, 6:pulse, 7:blink
    			// xNetwork.restoreTaillightsNetworkModeControl();		
    		}
    	*/
    	
    	}
    
    	function compute(info)
    	{
    		xTest+=1000;
         
    		var radarInfo = bRadar.getRadarInfo();
    		if(radarInfo)
    		{
    			for(var i = 0; i < 8; i++)
    			{
    				aRadar[i] = radarInfo[i].range;
    				// .range (m)		float
    				// .speed (m/s)		float
    				// .threat (level)	0=THREAT_LEVEL_NO_THREAT, 1=THREAT_LEVEL_VEHICLE_APPROACHING, 2=THREAT_LEVEL_VEHICLE_FAST_APPROACHING
    				// .threatside		0=THREAT_SIDE_NO_SIDE, 1=THREAT_SIDE_RIGHT, 2=THREAT_SIDE_LEFT
    			}
    		}
    		
    	}
    
    	function onHide() as Void 
    	{
    	}
    }
    
    class BirdApp extends App.AppBase
    {
        function getInitialView()	{	return [new BirdField()];	}
        function initialize()		{	AppBase.initialize();		}
        function onStart(state)		{								}
        function onStop(state)		{	/*return false;*/			}
    }
    

    Cool... but heavy stuff for beginners Wink

    I'm trying to make a micro version of your wonderful app - which is complicate because of a non working Ant+ dongle, so I need to transfer every new version to my real edge device instead of using the simulator Disappointed

    However, it looks like I can check the actual light mode (which is not shown imediately but when swapping data field pages for a while) and I am also able to change it to another mode. But how to check easily the 'network mode' shown as "N" or "M" in your app? And how to force to switch the device to the mode "N"?.

    Here's my all-in-one source code showing my first steps (sorry, can't add it as source code, tried to attach it as file)...

     

  • which is complicate because of a non working Ant+ dongle, so I need to transfer every new version to my real edge device instead of using the simulator Disappointed

    I had the same issue, you need to buy a newer dongle or switch to an older SDK (4.0.10 or lower). You can check for more info here:
    https://forums.garmin.com/developer/connect-iq/i/bug-reports/regression-bug-ant-genericchannel-does-not-work-in-simulator-with-sdk-4-1-x-anymore

    But how to check easily the 'network mode' shown as "N" or "M" in your app? And how to force to switch the device to the mode "N"?.

    As far as I know, there is no easy check for this. When you change the Garmin network mode by using the native Garmin menu, the LightNetwork instance that you have in your application will not be updated until it is recreated. There is a comment in Smart Bike Lights code for this:

    https://github.com/maca88/SmartBikeLights/blob/master/Source/SmartBikeLights/source-preprocess/BikeLightsView.mc#L1433

    and here:

    https://github.com/maca88/SmartBikeLights/blob/master/Source/SmartBikeLights/source-preprocess/BikeLightsView.mc#L474

    Smart Bike Lights is basically recreating the light network every time onShow is called if the last update time was older than 1.5 seconds. This condition is there to prevent recreating the light network, when you have Smart Bike Lights on two data screens one after another and you scroll back and forth between the two. 

    You can force to switch back to N (Network) mode by calling restoreHeadlightsNetworkModeControl and restoreTaillightsNetworkModeControl methods:

    https://github.com/maca88/SmartBikeLights/blob/master/Source/SmartBikeLights/source-preprocess/BikeLightsView.mc#L2013 

  • Hi guys, please can you help me with this config?

    Edge 1040 Solar, RT510, I want to have rear light turned off until radar "sees" car - if radar detects car, light should start flashing. And night flashing should start before sunset (this works)

    I had this on combo Edge 1030 + RT510 working but now on 1040 it is not working.

    This is my config string: #0,73413136::1:#2,2!Night:1:6:0:0Es-1800,r1800!:1:0:0:0D=1#0,73404416::1:#3,3!DetCar:1:7:0:0I}300}1!Night:1:6:0:0Es-3600,r1800!:1:0:0:0D=1#7,6:Varia 800:0:16777215:-1!2,:-1,Off:0!1,High:2!1,Medium:3!1,Low:4!1,Night Flash:6!1,Day Flash:7#5,4:Varia 510:0:16777215:-1!2,:-1,Off:0!1,Solid:4!1,Day Flash:7!1,Night Flash:6#0::#0:0#123!:123!#0#0#B3843#4#2#0#0

    Thank you for help. 

  • Thank you @maca88 - the network mode is still a problem but not needed for the moment here.

    I made a small program (25K) now including a custom font imitating one Garmin datafield font. I does control my L7 taillight from Cycplus without wasting any space in the datafield. Normally it does show typical activity data - only when tapping onto the datafield it shows a window which allows to set the light mode...

    Standard view

    After the tap onto the datafield

  • Hi, 

    The issue is with the range operator, where it is set to "Greater Than or Equal" 300 meter instead of "Lower Than or Equal". As Varia radar is able to detect vehicles up to 140 meters, the range operator is not needed. Here is the updated configuration, which should work:

    #0,73413136::1:#2,2!Night:1:6:0:0Es-1800,r1800!:1:0:0:0D=1#0,73404416::1:#3,3!DetCar:1:7:0:0I]-1]0!Night:1:6:0:0Es-3600,r1800!:1:0:0:0D=1#7,6:Varia 800:0:16777215:-1!2,:-1,Off:0!1,High:2!1,Medium:3!1,Low:4!1,Night Flash:6!1,Day Flash:7#5,4:Varia 510:0:16777215:-1!2,:-1,Off:0!1,Solid:4!1,Day Flash:7!1,Night Flash:6#0::#0:0#123!:123!#0#0#B3843#4#2#0#0

  • Smart Bike Lights app not installing on new Edge 840 (FW 25.25) – update required error

    Hi everyone,

    I’m having trouble installing the Smart Bike Lights Connect IQ app on my new Edge 840 (firmware 25.25).

    Here’s what I’ve already tried:

    • Updated my Edge 840 to the latest firmware via Garmin Express (no updates available).

    • Joined the Edge 840 Beta Program and installed the latest beta firmware (currently FW 25.25).

    • Updated my Varia RTL516 firmware via Garmin Express.

    • Tried installing the app via Connect IQ Store (both mobile and PC), and directly on the device.

    • Still getting the same error: "Device needs to be updated in Garmin Express" – even though both the Edge and Varia are fully updated.

    Additional context:

    • On my old Edge 840 (before it broke recently), the Smart Bike Lights app worked without problems.

    • After receiving the replacement Edge 840, the installation has never worked.

    • My setup: Edge 840 (FW 25.25) + Varia RTL516.

    • Varia is paired and works fine otherwise.

    Questions:

    • Is there any way to get an older version of the Smart Bike Lights app that’s compatible with my current Edge firmware?

    • Could there be an API change or firmware requirement blocking installation on the new device?

    Any help (or a link to a compatible PRG file) would be greatly appreciated — I’m happy to test and report back so others can benefit too.

    Thanks!

  • Update:
    After joining the Beta Program, the firmware update did not install correctly at first.
    Only after restarting the Edge 840 did the update to firmware 28.17 complete successfully.

    Now the Smart Bike Lights app installs and works as expected.

    For context: device is operated in Germany.

    Hope this helps others with the same issue!

  • Thank you! I will check it right when I will get to my bike as I am a bit sick now.

  • Would it be possible for some kind soul to provide me with a config?

    I have an Edge 1030 Plus and a Varia RTL515 and I looking for the following behaviour:

    Day defaults to OFF

    Gentle braking - SOLID

    Hard braking - DAY FLASH

    Night defaults to PELOTON

    Gentle braking - SOLID

    Hard braking - NIGHT FLASH

    Both day and night should DAY FLASH on approaching vehicles

    Many thanks