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

  • Here is the example of hangs & slow response. Garmin 1040:
    1drv.ms/.../EdqcwEBQQVFHknHP4uojxoQByQ5w11Q8jT0JC_bCcXKHLA

    T
    hese failure to set mode and slow response are quite frequent

  • Does it only work with Bluetooth settings?

    The light should be connected with ANT by using Garmin Sensors menu. As far as I know, it is not possible to pair a light via Bluetooth

  • CIQ widget were removed with newer Edges (840/1040+), so a "widget" in Edge 850 is a normal application, which you can open in the menu by going to "Connect IQ" -> LightTester (as least in Edge 1040) 

  • All these configs fails with: Error 3

    I see the problem, the additional modes are missing, which are not changed for existing configurations. You need to add "267911168,0" after "2147483647:1":

    #16384,90382865:1,2147483647:1:267911168,0#7,4!Speed:2:3:20:0C]6.66667Es0,r0!Night:2:5:60:0Es0,r0H]2!Day:2:0:60:0Er0,s0H]2!:1:0:0:0D=1#6291461,1409482753:0,889104606:1:#11,5!BreakD:3:1:5:0Er0,s0H]2A[-20!BreakN:3:5:5:0Es0,r0H]2A[-20!Day:2:8:60:0Er0,s0H]2!Night:2:63:60:0Es0,r0H]2!:1:0:0:0D=1#11,10:AT 1600:0:16777215:0!2,:-1,Off:0!1,Very High  \n1600lm-1.5h:1!1,High  \n1200lm-2h:2!1,Medium  \n800lm-3h:3!1,Medium-Low  \n600lm-4.5h:4!1,Low  \n400lm-6h:5!1,Very Low \n200lm-12h:59!1,Pulse \n 300/50lm-13.5h:60!1,Slow Flash:6!1,Fast Flash:7#8,7:Flare RT:0:16777215:0!2,:-1,Off:0!1,Day Steady  \n25lm-4.5h:1!1,Night Steady  \n5lm-13.5h:5!1,Day Flash  \n90lm-6h:7!1,All-Day Flash  \n45lm-12h:8!1,Night Flash  \n5lm-15h:63!1,:-2#0::#0:0#123!:123!#0#0#B3843#14#1#0#0

    It seems that AT1200/1600 lights are emitting capable modes differently, AT1200 does emit also mode 59 based on the image from Kamil (https://github.com/maca88/SmartBikeLights/discussions/104#discussioncomment-14675854), but AT1600 does not based on the video that you shared:

    I had to update the configurator to include it in the additional modes for AT1600 as previously 59 was not there.

     

    Here is Video with Error 3, slow response & fail to set mode

    Regarding the slow response and failure to set the light mode, there is unfortunately not much we can do when using the Garmin Light Network. With the Garmin Light Network, the more lights you connect, the slower and more error-prone the system becomes due to how ANT+ lights must operate to comply with the ANT+ Lights Profile specification.

    When more than one light is paired with the Edge or a watch, a special light network is formed. In this network, one light is designated as the main light, while the others become secondary lights. The main light is the only one directly connected to the Edge or watch, and the secondary lights communicate only with the main light. This approach saves ANT channels but comes at the cost of slower responsiveness and reduced reliability.

    From my previous testing, I noticed that when the Flare RT is promoted as the main light, the network tends to become unstable and unresponsive, similar to what you’re experiencing.


    Try disabling the Flare RT and check whether the lights respond better to mode changes. If they do, the best option is to use an Individual Light Network for the Flare RT by using Smart Bike Lights #2. Unfortunately, it is not possible to manually select which light will be promoted as the main light.

     > When I clear config, I see that your app combine multiple Taillights:
    FlareRT + Varia 515 = and now I see only  ID:5 & ID:7 modes (which match on both lights). Not sure if that is a problem or not? 

    This is expected and also documented here: https://github.com/maca88/SmartBikeLights?tab=readme-ov-file#grouping-them-into-one-virtual-light 

    > Just "Low Garmin" - seems only one left with Garmin

    Good catch! Now it is fixed.

  • You need to add "267911168,0" after "2147483647:1"

    This fixed the issue. What is this: 267911168,0 ?

    #16384,90382865:1,2147483647:1:267911168,0#5,3!Night:2:51:60:0Es0,r0H]2!Day:2:0:60:0Er0,s0H]2!:1:0:0:0D=1#6291461,1409482753:0,889104606:1:#11,5!BreakD:3:1:5:0Er0,s0H]2A[-20!BreakN:3:5:5:0Es0,r0H]2A[-20!Day:2:8:60:0Er0,s0H]2!Night:2:63:60:0Es0,r0H]2!:1:0:0:0D=1#6,5:AT 1600:0:16777215:0!2,:-1,Off:0!1,Low  \n200lm-12h:51!1,Medium  \n 600lm-4h:52!1,High  \n1200lm-2h:53!1,:-2#6,5:Flare RT:0:16777215:0!2,:-1,Off:0!1,Night Flash  \n5lm-15h:63!1,Day Flash  \n45lm-12h:8!1,Night Steady  \n5lm-13.5h:5!1,Day Steady  \n25lm-4.5h:1#0::#0:0#123!:123!#0#0#B3843#14#1#0#0

    This config fails - if only At1600 is connected - I get: Error 1

    FlareRT & Varia 515 I removed from sensors - just to test the speed.
    Why it fails? I expect that when one light is down (battery dead, or etc.) other should be working, or I miss something? 

    Also I found interesting BUG:
    I removed all Lights (Varia 515, FlareRT), just left AT1600, wanted to see if it respond faster. But I found bug, where it time to time just crash and I get: Error 1.
    I can recovery from crash - disable /enable Lights, and I can crash again - just if I open sensors page (no need to do anything)

    Here is Video:
    https://1drv.ms/v/c/4ccaa19b4a2ea98d/ETxEPyXqYgpNqk5EtncbjgoBVYk1uuKgoLecnIPZSU3-Sg?e=0jSUDk

    It seems that AT1200/1600 lights are emitting capable modes differently, AT1200 does emit also mode 59 based on the image from Kamil


    My guess is that AT1200 and AT1600 - have the same FW. But I have only AT1600, can't check.
    I think if I do not configure some Presets on Magene App - it will not show these ID's.
    For example, now I removed all Presets - and left only 3. And ID:59 is Preset 9, so my guess it was not available because I didn't created Preset 9.

    AT1600 does not based on the video that you shared

    That's why I guess you saw different list of ID's.

     

  • In this network, one light is designated as the main light, while the others become secondary lights.

    Very interesting.

    I noticed that when the Flare RT is promoted as the main light, the network tends to become unstable and unresponsive

    Is there a way to mark - which Light is main? (then I could try to find pattern - when it get slow)

    And this is example with both lights (AT1600 & FlareRT), when it works quite good:
    https://1drv.ms/v/c/4ccaa19b4a2ea98d/EaCqPRlF92BGgYRLXaLOdYsB8rK5WQF4MCzxd_YdeJqA-A?e=HCR02y

    I hope you will find some magic, how to make it always stable, like in this video  Slight smile
     
    What I notice - Garmin Light widget buttons (or remote buttons) - they always fast and do not hang, even when your app start slow response. Maybe because they broadcast the same ID to all lights, and your app need to select specific light - my wild guess Slight smile

  • Is there a way to mark - which Light is main?

    Unfortunately no (as least to my knowledge). The Edge firmware will automatically select which will be the main light when forming the light network and I do not know what are the parameters used to determine the main light. I tried to pair lights in different order, but that does not affect the logic for selecting the main light.
    This was also one of the main reasons why I then added the "Individual Light Network", where each light is directly connected to Edge/watch without forming the light network.

    What I notice - Garmin Light widget buttons (or remote buttons) - they always fast and do not hang, even when your app start slow response.

    I am assuming that the Garmin light widget buttons do not wait for the light to send back a confirmation that the light mode has changed. In Smart Bike Lights, when you tap a button, it turns black to indicate that the command to change the light mode has been sent. Once the light responds with the new mode, the button switches from black to blue.

  • What is this: 267911168,0 ?

    It is a bit technical, but let me try to explain:
    Smart Bike Lights uses a 64bit number to append the missing light modes to the capable modes emitted by the light.
    Because toLong (https://developer.garmin.com/connect-iq/api-docs/Toybox/Lang/String.html#toLong-instance_function) method was introduced only is SDK 3.1.0, I couldn't use it to parse a 64bit number from the configuration as it would not work on older devices (e.g. Edge 1000/520). The solution was to split the 64bit number into two 32bit numbers, one would represent the first 32 bits (267911168) and the second one the last 32bit (0). When you combine the two you get the following 64bit number:

    1150669704793161728

    If you put this number in the calculator, which is able to display bits, like the Windows one, you will see this:

    The bit position where a one is set represents the missing light mode that will be added to the supported modes. In this case, the modes range from 51 to 59.

    if only At1600 is connected - I get: Error 1

    Hmm that is not good. Error 1 means that the LightNetwork API from CIQ SDK does return an unexpected value for light type. Smart Bike Lights does support only headlights (0) and taillights (2) and for others:
    https://developer.garmin.com/connect-iq/api-docs/Toybox/AntPlus.html#LightType-module

    it will show Error 1. In the past I do remember I got value 7 (Other - Undefined light type) for See.Sense ICON2 light in certain cases and that was due to incomplete implementation of the ANT+ Lights Profile specification in the ICON2 firmware. In my case, I also saw "Other" instead of "Headlight/Taillight" in the Sensors -> Lights menu. In order to understand what kind of light type is provided by the SDK, could you sideload the LightTester application (https://github.com/maca88/SmartBikeLights/blob/master/Source/LightTester/build/edge1040/LightTester.prg) and open it when you get Error 1 to check what number you see for TY (light type)?

  • Hi
    I can do it on EDGE840, but i can't find LightTester.prg for 840, only for 1040 and 850.
    Can you create 840 version please? 
    It will be awesome, to get Ravemen FR300 ANT running on your app.

  • I am assuming that the Garmin light widget buttons do not wait for the light to send back a confirmation that the light mode has changed. In Smart Bike Lights, when you tap a button, it turns black to indicate that the command to change the light mode has been sent. Once the light responds with the new mode, the button switches from black to blue.

    Maybe Garmin do not wait status - and it's using "send & forget" protocol (one way), but interesting that I never noticed that it would not set light. (maybe they send multiple times, in case Ant+ lost packet in transition?)

    Edit: I see Garmin already have onBikeLightUpdate(), no need to create your own thread Slight smile
    Then I guess it should work retry with a short backoff until onBikeLightUpdate() confirms the change (or we hit the retry limit).
    Not sure, maybe you already doing this Slight smile
    But, I still see sometimes - when I press button - it will not set my selected Mode, I just need repeat again and again (and because it wait status back - it feels slow response, or that something failing). For some reason when it fails to set Mode (hang ANT+ network?), but after a few clicks on other buttons - it start working, that's why I'm think if retry logic could help to make this more stable?

    Video:
    https://1drv.ms/v/c/4ccaa19b4a2ea98d/EWlQ8DjftgJHpikM5NLSFSEBmCdu27btqcnumflCh1_J2Q?e=xsic5V
    This is opposite example when status is never got returned - I press button "Off", light went Off, but status is not changed - it stuck. I need to swipe forth and back page to update the status.
    And this is again, I guess because of ANT+ "send & forget" protocol, 
    If the light does not rebroadcast its new state immediately (or the Edge misses that message - RF interference, collisions, etc.), your listener never sees it. So the light can change state, but your app won’t know until the next broadcast cycle (which might be missed too).
    Edit: hmmm... I'm not sure about that - because after I swipe forth and back page - it set correct status... so it's not ANT+ packet was lost, right? 


    Well, if we can't relay on ANT+ protocol - setMode() & onBikeLightUpdate(), both can be lost in transition and we never can get back response (due to throttling, competing background services, or RF timing)
    What if we send setMode() in loop (with retry timer), until onBikeLightUpdate() status will confirm and only then switch off loop. And Button state do not change (visual) - it do not care about state, and I can press other buttons instantly or the same button instantly - it would feel much faster I guess. And this loop make sure mode will be set eventually, even it can be lost a few attempts.
    What do you think?