using UnityEngine; using System.Collections; using System.Collections.Generic; using ANT_Managed_Library; using System; /* Frequencies such as 4.06 Hz (ANT+ Heart Rate) and 4.005 Hz (ANT+ Bike Power) will periodically “drift” into each other, or into other channel periods that may be present in the vicinity. During this overlap, channel collisions may occur as the radio can only service channel at a time. */ public class PowerMeterReceiver { private int deviceID = 0; //set this to connect to a specific device ID private bool connected = false; //will be set to true once connected private List scanResult; private int instantaneousPower; // the instantaneous power in watt private int instantaneousCadence; // crank cadence in RPM if available ( 255 indicates invalid) private float crankTorque; private AntChannel backgroundScanChannel; private AntChannel deviceChannel; public int DeviceID => deviceID; public bool Connected => connected; public List ScanResult => scanResult; public int InstantaneousPower => instantaneousPower; public int InstantaneousCadence => instantaneousCadence; public float CrankTorque => crankTorque; private byte[] pageToSend; public PowerMeterReceiver() { } public PowerMeterReceiver(int deviceID) => this.deviceID = deviceID; public void StartScan() { Debug.Log("Looking for ANT + power meter sensor"); AntManager.Instance.Init(); scanResult = new List(); backgroundScanChannel = AntManager.Instance.OpenBackgroundScanChannel(0); backgroundScanChannel.onReceiveData += ReceivedBackgroundScanData; } void ReceivedBackgroundScanData(Byte[] data) { byte deviceType = (data[12]); // extended info Device Type byte switch (deviceType) { case AntplusDeviceType.BikePower: { int deviceNumber = (data[10]) | data[11] << 8; byte transType = data[13]; foreach (AntDevice d in scanResult) { if (d.deviceNumber == deviceNumber && d.transType == transType) //device already found return; } AntDevice foundDevice = new AntDevice(); foundDevice.deviceType = deviceType; foundDevice.deviceNumber = deviceNumber; foundDevice.transType = transType; foundDevice.period = 8182; foundDevice.radiofreq = 57; foundDevice.name = "Powermeter(" + foundDevice.deviceNumber + ")"; scanResult.Add(foundDevice); if (deviceNumber == deviceID) { Debug.Log($"Desired Power Sensor with id {deviceNumber} found!"); ConnectToDevice(foundDevice); } else { Debug.Log($"Power sensor ({deviceNumber}) found and added to ScanResult"); } break; } } } void ConnectToDevice(AntDevice device) { AntManager.Instance.CloseBackgroundScanChannel(); byte channelID = AntManager.Instance.GetFreeChannelID(); deviceChannel = AntManager.Instance.OpenChannel(ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00, channelID, (ushort) device.deviceNumber, device.deviceType, device.transType, (byte) device.radiofreq, (ushort) device.period, false); connected = true; deviceChannel.onReceiveData += Data; deviceChannel.onChannelResponse += ChannelResponse; deviceChannel.hideRXFAIL = true; } private readonly Dictionary updateEventCount = new Dictionary {{0x10, 0}, {0x12, 0}}; private readonly Dictionary sameEventCounter = new Dictionary {{0x10, 0}, {0x12, 0}}; private int previousAccumulatedTorqueValue = 0; private int previousTorqueEventCount = 0; //Deal with the received Data private void Data(Byte[] data) { if (data[0] == 0x10) // Standard Power-Only Main Data Page { if (data[1] == updateEventCount[0x10]) sameEventCounter[0x10]++; else sameEventCounter[0x10] = 0; updateEventCount[0x10] = data[1]; if (sameEventCounter[0x10] > 3) { instantaneousPower = 0; instantaneousCadence = 0; } else { instantaneousPower = data[6] | data[7] << 8; instantaneousCadence = data[3]; } } if (data[0] == 0x12) // Standard Crank Torque Main Data Page { Debug.Log($"Torque Data {data}"); if (data[1] == updateEventCount[0x12]) sameEventCounter[0x12]++; else sameEventCounter[0x12] = 0; updateEventCount[0x12] = data[1]; if (sameEventCounter[0x12] > 3) { crankTorque = 0; } else { int accumulatedTorque = data[6] | data[7] << 8; float divisor = (32 * (updateEventCount[0x12] - previousTorqueEventCount)); if (divisor > 0) { crankTorque = (accumulatedTorque - previousAccumulatedTorqueValue) / divisor; } Debug.Log($"instantaneousCrankTorque = {crankTorque}"); previousAccumulatedTorqueValue = accumulatedTorque; previousTorqueEventCount = updateEventCount[0x12]; } } } public void Calibrate() { Debug.Log("Sending : Manual Zero Calibration request"); pageToSend = new byte[8] {0x01, 0xAA, 0x0FF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; deviceChannel.sendAcknowledgedData(pageToSend); } void ChannelResponse(ANT_Response response) { if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_FAILED_0x06) { deviceChannel.sendAcknowledgedData(pageToSend); //send the page again if the transfer failed } } }