Acknowledged
over 1 year ago

Bug report: ANT GenericChannel.release causes issues with other channels

In our app we have 3 ANT generic channels.  One is a master, two are slaves.

I am trying to change one of the channels to a BackgroundScan channel.  

To do that I have to firstly switch it to a "Ant.CHANNEL_TYPE_RX_ONLY" type.  To do that I have to reinitialise the channel, i.e.:

channel = new Ant.ChannelAssignment
            (
                Ant.CHANNEL_TYPE_RX_ONLY,
                Ant.NETWORK_PUBLIC
            );
I believe we cannot change it on the fly.  Since this channel is already assigned I have to release it first, using GenericChannel.release().
When changing back to standard master channel, we do GenericChannel.close() then GenericChannel.release().  On this GenericChannel.release() command the first channel I assigned stops working - I have isolated this line as being the problem. The first channel is still transmitting data but the onMessage event stops getting called.
So in short "releasing" an rx only background scanning channel causes the first assigned channel in my app to stop working.
Any ideas of a workaround?
 
  • I forgot to mention you in reply above, in case you don't get notification..

  • Hi Brandon,

    Ok, I have the issue working in a demo app. Here is what happens:
    - I open 3 speed sensor channels and 1 power meter channel.  I am using SimulANT to create multiple speed and power meters to listen to.

    - I can toggle the power meter from standard mode to scan mode.  When I hit the "GenericChannel.release();" line the first time (on "switchToScan") the first speed  sensor channel closes.  When I switch back from scan ("switchBackFromScan") again the "GenericChannel.release()" line causes the second speed sensor channel to close.

    Here are the speed and power sensor channel codes.  Let me know if you want the full app.

    using Toybox.Ant as Ant;
    using Toybox.System as Sys;
    
    class SpdSensor extends Ant.GenericChannel
    {
    	const DEVICE_TYPE = 123;
    	const PERIOD = 8118;
    	const DEVICE_NUMBER = 0;
    	var device_cfg;
    	var msgCount = 0;
    	hidden var m_channel;
    
    	function initialize()
    	{
    		m_channel = new Ant.ChannelAssignment
    		(
    			Ant.CHANNEL_TYPE_RX_NOT_TX,
    			Ant.NETWORK_PLUS
    		);
    		GenericChannel.initialize(method(:onMessage), m_channel);
    		
    		device_cfg = new Ant.DeviceConfig
    		({
    			:deviceNumber => DEVICE_NUMBER,
    			:deviceType => DEVICE_TYPE,
    			:messagePeriod => PERIOD,
    			:transmissionType =>0,
    			:radioFrequency => 57,
    			:searchTimeoutLowPriority => 10,
    			:searchThreshold => 0
    		});
    		GenericChannel.setDeviceConfig(device_cfg);		
    		GenericChannel.open();
    	}
    
    	function close()
    	{
    		GenericChannel.close();
    	}
    
    	function onMessage(msg)
    	{
    		var payload = msg.getPayload();
    		if (Ant.MSG_ID_BROADCAST_DATA == msg.messageId)
    		{
    			msgCount++;
    		}
    	}
    }
    
    class PwrSensor extends Ant.GenericChannel
    {
    	const DEVICE_TYPE = 11;
    	const PERIOD = 8182;
    	const DEVICE_NUMBER = 0;
    	var device_cfg;
    	var msgCount = 0;
    	hidden var m_channel;
    	hidden var m_scanning = false;
    
    	function initialize()
    	{
    		m_channel = new Ant.ChannelAssignment
    		(
    			Ant.CHANNEL_TYPE_RX_NOT_TX,
    			Ant.NETWORK_PLUS
    		);
    		GenericChannel.initialize(method(:onMessage), m_channel);
    		
    		device_cfg = new Ant.DeviceConfig
    		({
    			:deviceNumber => DEVICE_NUMBER,
    			:deviceType => DEVICE_TYPE,
    			:messagePeriod => PERIOD,
    			:transmissionType =>0,
    			:radioFrequency => 57,
    			:searchTimeoutLowPriority => 10,
    			:searchThreshold => 0
    		});
    		GenericChannel.setDeviceConfig(device_cfg);		
    		GenericChannel.open();
    	}
    
    	function close()
    	{
    		GenericChannel.close();
    	}
    
    	function switchToScan()
    	{
    		GenericChannel.close();
    		GenericChannel.release();
    		m_channel = new Ant.ChannelAssignment
    		(
    			Ant.CHANNEL_TYPE_RX_ONLY,
    			Ant.NETWORK_PLUS
    		);
    		m_channel.setBackgroundScan(true);
    		GenericChannel.initialize(method(:onMessage), m_channel);
    		device_cfg = new Ant.DeviceConfig
    		({
    			:deviceNumber => 0,
    			:deviceType => DEVICE_TYPE,
    			:messagePeriod => PERIOD,
    			:transmissionType =>0,
    			:radioFrequency => 57,
    			:searchTimeoutLowPriority => 10,
    			:searchThreshold => 0
    		});
    		GenericChannel.setDeviceConfig(device_cfg);		
    		GenericChannel.open();
    	}
    
    	function getText()
    	{
    		if (m_scanning)
    		{
    			return "Click Menu to stop pwr scan";
    		}
    		else
    		{
    			return "Click Menu to switch pwr to scan";
    		}
    	}
    
    	function toggleScan()
    	{
    		if (m_scanning)
    		{
    			switchBackFromScan();
    			m_scanning = false;
    		}
    		else
    		{
    			switchToScan();
    			m_scanning = true;
    		}
    	}
    
    	function switchBackFromScan()
    	{
    		GenericChannel.close();
    		GenericChannel.release();
    		m_channel = new Ant.ChannelAssignment
    		(
    			Ant.CHANNEL_TYPE_RX_NOT_TX,
    			Ant.NETWORK_PLUS
    		);
    		m_channel.setBackgroundScan(false);
    		GenericChannel.initialize(method(:onMessage), m_channel);
    		device_cfg = new Ant.DeviceConfig
    		({
    			:deviceNumber => 0,
    			:deviceType => DEVICE_TYPE,
    			:messagePeriod => PERIOD,
    			:transmissionType =>0,
    			:radioFrequency => 57,
    			:searchTimeoutLowPriority => 10,
    			:searchThreshold => 0
    		});
    		GenericChannel.setDeviceConfig(device_cfg);		
    		GenericChannel.open();
    	}
    
    	function onMessage(msg)
    	{
    		var payload = msg.getPayload();
    		if (Ant.MSG_ID_BROADCAST_DATA == msg.messageId)
    		{
    			msgCount++;
    		}
    	}
    }

  • Hi I am on vacation right now and will need to spend a bit of time putting something together to demonstrate.  I'll do that next week.

  • Do you have any additional code from your implementation you can share? We would like to try reproducing using your app and/or code.