package org.cowboycoders.ant.sensors;
import org.cowboycoders.ant.Channel;
import org.cowboycoders.ant.NetworkKeys;
import org.cowboycoders.ant.Node;
import org.cowboycoders.ant.events.BroadcastListener;
import org.cowboycoders.ant.messages.ChannelType;
import org.cowboycoders.ant.messages.SlaveChannelType;
import org.cowboycoders.ant.messages.data.BroadcastDataMessage;
import java.util.ArrayList;
import java.util.List;
/**
* TODO: pairing with a specific device id
* Created by fluxoid on 22/12/15.
*/
public class HeartRateMonitor {
private final Node node;
private boolean running = false;
private List<HeartRateListener> listeners = new ArrayList<>();
private Channel channel;
private class AntListener implements BroadcastListener<BroadcastDataMessage> {
/*
* Once an instance of this class is registered with a channel,
* this is called every time a broadcast message is received
* on that channel.
*
* (non-Javadoc)
* @see org.cowboycoders.ant.events.BroadcastListener#receiveMessage(java.lang.Object)
*/
@Override
public void receiveMessage(BroadcastDataMessage message) {
/*
* getData() returns the 8 byte payload. The current heart rate
* is contained in the last byte.
*
* Note: remember the lack of unsigned bytes in java, so unsigned values
* should be converted to ints for any arithmetic / display - getUnsignedData()
* is a utility method to do this.
*/
synchronized (HeartRateMonitor.this) {
for (HeartRateListener hrl : listeners) {
hrl.onValueChange(message.getUnsignedData()[7]);
}
}
}
}
/*
* See ANT+ data sheet for explanation
*/
private static final int HRM_CHANNEL_PERIOD = 8070;
/*
* See ANT+ data sheet for explanation
*/
private static final int HRM_CHANNEL_FREQ = 57;
/*
* This should match the device you are connecting with.
* Some devices are put into pairing mode (which sets this bit).
*
* Note: Many ANT+ sport devices do not set this bit (eg. HRM strap).
*
* See ANT+ docs.
*/
private static final boolean HRM_PAIRING_FLAG = false;
/*
* Should match device transmission id (0-255). Special rules
* apply for shared channels. See ANT+ protocol.
*
* 0: wildcard, matches any value (slave only)
*/
private static final int HRM_TRANSMISSION_TYPE = 0;
/*
* device type for ANT+ heart rate monitor
*/
private static final int HRM_DEVICE_TYPE = 120;
/*
* You should make a note of the device id and use it in preference to the wild card
* to pair to a specific device.
*
* 0: wild card, matches all device ids
* any other number: match specific device id
*/
private static final int HRM_DEVICE_ID = 0;
public HeartRateMonitor(Node node) {
this.node = node;
}
public void start() {
if (running) return;
this.running = true;
/* must be called before any configuration takes place */
node.start();
channel = node.getFreeChannel();
// Arbitrary name : useful for identifying channel
channel.setName("C:HRM");
// choose slave or master type. Constructors exist to set two-way/one-way and
// shared/non-shared variants.
ChannelType channelType = new SlaveChannelType();
// use ant network key "N:ANT+"
channel.assign(NetworkKeys.ANT_SPORT, channelType);
// registers an instance of our callback with the channel
channel.registerRxListener(new AntListener(), BroadcastDataMessage.class);
/******* start device specific configuration ******/
channel.setId(HRM_DEVICE_ID, HRM_DEVICE_TYPE, HRM_TRANSMISSION_TYPE, HRM_PAIRING_FLAG);
channel.setFrequency(HRM_CHANNEL_FREQ);
channel.setPeriod(HRM_CHANNEL_PERIOD);
/******* end device specific configuration ******/
// timeout before we give up looking for device
channel.setSearchTimeout(Channel.SEARCH_TIMEOUT_NEVER);
// start listening
channel.open();
}
public void stop() {
if (!running) return;
// stop listening
channel.close();
// resets channel configuration
channel.unassign();
//return the channel to the pool of available channels
node.freeChannel(channel);
}
public synchronized void registerListener(HeartRateListener hrl) {
listeners.add(hrl);
}
}