forked from upstream-mirrors/OpenTracks
Use antlib.jar to connect to ANT+ sensor.
This commit is contained in:
@@ -7,6 +7,9 @@ Android Support Package:
|
|||||||
android-support-v4-r7-googlemaps.jar
|
android-support-v4-r7-googlemaps.jar
|
||||||
- see https://github.com/petedoyle/android-support-v4-googlemaps
|
- see https://github.com/petedoyle/android-support-v4-googlemaps
|
||||||
|
|
||||||
|
Ant+:
|
||||||
|
antlib.jar - see http://www.thisisant.com/pages/developer-zone/android-api
|
||||||
|
|
||||||
Google APIs Client Library for Java:
|
Google APIs Client Library for Java:
|
||||||
commons-codec-1.3.jar
|
commons-codec-1.3.jar
|
||||||
commons-logging-1.1.1.jar
|
commons-logging-1.1.1.jar
|
||||||
|
|||||||
Binary file not shown.
@@ -161,14 +161,12 @@ limitations under the License.
|
|||||||
<string-array name="sensor_type_all_options">
|
<string-array name="sensor_type_all_options">
|
||||||
<item>@string/settings_sensor_type_none</item>
|
<item>@string/settings_sensor_type_none</item>
|
||||||
<item>@string/settings_sensor_type_ant</item>
|
<item>@string/settings_sensor_type_ant</item>
|
||||||
<item>@string/settings_sensor_type_srm</item>
|
|
||||||
<item>@string/settings_sensor_type_polar</item>
|
<item>@string/settings_sensor_type_polar</item>
|
||||||
<item>@string/settings_sensor_type_zephyr</item>
|
<item>@string/settings_sensor_type_zephyr</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="sensor_type_all_values">
|
<string-array name="sensor_type_all_values">
|
||||||
<item>@string/sensor_type_value_none</item>
|
<item>@string/sensor_type_value_none</item>
|
||||||
<item>@string/sensor_type_value_ant</item>
|
<item>@string/sensor_type_value_ant</item>
|
||||||
<item>@string/sensor_type_value_srm_ant_bridge</item>
|
|
||||||
<item>@string/sensor_type_value_polar</item>
|
<item>@string/sensor_type_value_polar</item>
|
||||||
<item>@string/sensor_type_value_zephyr</item>
|
<item>@string/sensor_type_value_zephyr</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ limitations under the License.
|
|||||||
<string name="sensor_type_value_ant">ANT</string>
|
<string name="sensor_type_value_ant">ANT</string>
|
||||||
<string name="sensor_type_value_none">NONE</string>
|
<string name="sensor_type_value_none">NONE</string>
|
||||||
<string name="sensor_type_value_polar">POLAR</string>
|
<string name="sensor_type_value_polar">POLAR</string>
|
||||||
<string name="sensor_type_value_srm_ant_bridge">SRM_ANT_BRIDGE</string>
|
|
||||||
<string name="sensor_type_value_zephyr">ZEPHYR</string>
|
<string name="sensor_type_value_zephyr">ZEPHYR</string>
|
||||||
<string name="settings_map_track_color_mode_dynamic_value">DYNAMIC</string>
|
<string name="settings_map_track_color_mode_dynamic_value">DYNAMIC</string>
|
||||||
<string name="settings_map_track_color_mode_fixed_value">FIXED</string>
|
<string name="settings_map_track_color_mode_fixed_value">FIXED</string>
|
||||||
|
|||||||
@@ -18,10 +18,8 @@ limitations under the License.
|
|||||||
<!-- Keys for persisted preferences. Sorted alphabetically. DO NOT TRANSLATE. -->
|
<!-- Keys for persisted preferences. Sorted alphabetically. DO NOT TRANSLATE. -->
|
||||||
<string name="allow_access_key">allowAccess</string>
|
<string name="allow_access_key">allowAccess</string>
|
||||||
<string name="announcement_frequency_key">announcementFrequency</string>
|
<string name="announcement_frequency_key">announcementFrequency</string>
|
||||||
<string name="ant_cadence_sensor_id_key">antCadenceSensorId</string>
|
<string name="ant_heart_rate_monitor_id_key">antHeartRateMonitorId</string>
|
||||||
<string name="ant_cadence_speed_sensor_id_key">antCadenceSpeedSensorId</string>
|
<string name="ant_speed_distance_monitor_id_key">antSpeedDistanceMonitorId</string>
|
||||||
<string name="ant_heart_rate_sensor_id_key">antHeartRateSensorId</string>
|
|
||||||
<string name="ant_srm_bridge_sensor_id_key">antSrmBridgeSensorId</string>
|
|
||||||
<string name="auto_resume_track_current_retry_key">autoResumeTrackCurrentRetry</string>
|
<string name="auto_resume_track_current_retry_key">autoResumeTrackCurrentRetry</string>
|
||||||
<string name="auto_resume_track_timeout_key">autoResumeTrackTimeout</string>
|
<string name="auto_resume_track_timeout_key">autoResumeTrackTimeout</string>
|
||||||
<string name="bluetooth_sensor_key">bluetoothSensor</string>
|
<string name="bluetooth_sensor_key">bluetoothSensor</string>
|
||||||
@@ -72,6 +70,8 @@ limitations under the License.
|
|||||||
<string name="settings_reset_key">settingsReset</string>
|
<string name="settings_reset_key">settingsReset</string>
|
||||||
<string name="settings_sensor_key">settingsSensor</string>
|
<string name="settings_sensor_key">settingsSensor</string>
|
||||||
<string name="settings_sensor_ant_key">settingsSensorAnt</string>
|
<string name="settings_sensor_ant_key">settingsSensorAnt</string>
|
||||||
|
<string name="settings_sensor_ant_reset_heart_rate_monitor_key">settingsSensorAntResetHeartRateMonitor</string>
|
||||||
|
<string name="settings_sensor_ant_reset_speed_distance_monitor_key">settingsSensorAntResetSpeedDistanceMonitor</string>
|
||||||
<string name="settings_sensor_bluetooth_key">settingsSensorBluetooth</string>
|
<string name="settings_sensor_bluetooth_key">settingsSensorBluetooth</string>
|
||||||
<string name="settings_sensor_bluetooth_pairing_key">settingsSensorBluetoothPairing</string>
|
<string name="settings_sensor_bluetooth_pairing_key">settingsSensorBluetoothPairing</string>
|
||||||
<string name="settings_sensor_root_key">settingsSensorRoot</string>
|
<string name="settings_sensor_root_key">settingsSensorRoot</string>
|
||||||
|
|||||||
@@ -1726,11 +1726,6 @@ limitations under the License.
|
|||||||
Character limit: ~26 (1 line)">
|
Character limit: ~26 (1 line)">
|
||||||
Sensor
|
Sensor
|
||||||
</string>
|
</string>
|
||||||
<string name="settings_sensor_ant_not_paired"
|
|
||||||
translation_description="In the 'Sensor' settings, the summary for 'Unpair ANT+ heart rate
|
|
||||||
sensor' or 'Unpair SRM ANT+ bridge' when there no ANT+ device paired.">
|
|
||||||
Not paired.
|
|
||||||
</string>
|
|
||||||
<string name="settings_sensor_ant_options"
|
<string name="settings_sensor_ant_options"
|
||||||
translation_description="In the 'Sensor' settings, the section header to configure the ANT+
|
translation_description="In the 'Sensor' settings, the section header to configure the ANT+
|
||||||
options. Note that ANT+ is a radio standard.
|
options. Note that ANT+ is a radio standard.
|
||||||
@@ -1739,17 +1734,25 @@ limitations under the License.
|
|||||||
ANT+ options
|
ANT+ options
|
||||||
</string>
|
</string>
|
||||||
<string name="settings_sensor_ant_paired"
|
<string name="settings_sensor_ant_paired"
|
||||||
translation_description="In the 'Sensor' settings, the summary for 'Unpair ANT+ heart rate
|
translation_description="In the 'Sensor' settings, the summary to indicate the paired ANT+
|
||||||
sensor' or 'Unpair SRM ANT+ bridge' when there is an ANT+ device paired.
|
device. Note that ANT+ is a radio standard.
|
||||||
|
|
||||||
%1$d: sensor id number. E.g., '1'.">
|
%1$d: device id number. E.g., '1'.">
|
||||||
Paired with: %1$d.
|
Paired with: %1$d.
|
||||||
</string>
|
</string>
|
||||||
<string name="settings_sensor_bluetooth_connected"
|
<string name="settings_sensor_ant_reset_heart_rate_monitor"
|
||||||
translation_description="The message when connected to a bluetooth sensor.
|
translation_description="In the 'Sensor' settings, under the 'ANT+ options', the option to reset
|
||||||
|
an ANT+ heart rate monitor. Note that ANT+ is a radio standard.
|
||||||
|
|
||||||
%1$s: sensor name. E.g., 'polar bluetooth'.">
|
Character limit: ~26 (1 line)">
|
||||||
Connected to %1$s
|
Reset heart rate monitor
|
||||||
|
</string>
|
||||||
|
<string name="settings_sensor_ant_reset_speed_distance_monitor"
|
||||||
|
translation_description="In the 'Sensor' settings, under the 'ANT+ options', the option to reset
|
||||||
|
an ANT+ speed distance monitor. Note that ANT+ is a radio standard.
|
||||||
|
|
||||||
|
Character limit: ~26 (1 line)">
|
||||||
|
Reset speed distance monitor
|
||||||
</string>
|
</string>
|
||||||
<string name="settings_sensor_bluetooth_options"
|
<string name="settings_sensor_bluetooth_options"
|
||||||
translation_description="In the 'Sensor' settings, the section header to configure the Bluetooth
|
translation_description="In the 'Sensor' settings, the section header to configure the Bluetooth
|
||||||
@@ -1784,6 +1787,16 @@ limitations under the License.
|
|||||||
sensor to connect to.">
|
sensor to connect to.">
|
||||||
The Bluetooth sensor to connect to.
|
The Bluetooth sensor to connect to.
|
||||||
</string>
|
</string>
|
||||||
|
<string name="settings_sensor_connected"
|
||||||
|
translation_description="The message when connected to a sensor.
|
||||||
|
|
||||||
|
%1$s: sensor name. E.g., 'polar bluetooth'.">
|
||||||
|
Connected to %1$s
|
||||||
|
</string>
|
||||||
|
<string name="settings_sensor_not_connected"
|
||||||
|
translation_description="The message when not connected to a sensor.">
|
||||||
|
Not connected.
|
||||||
|
</string>
|
||||||
<string name="settings_sensor_type"
|
<string name="settings_sensor_type"
|
||||||
translation_description="In the 'Sensor' settings, the dropdown option to choose a sensor type.
|
translation_description="In the 'Sensor' settings, the dropdown option to choose a sensor type.
|
||||||
|
|
||||||
@@ -1792,10 +1805,10 @@ limitations under the License.
|
|||||||
</string>
|
</string>
|
||||||
<string name="settings_sensor_type_ant"
|
<string name="settings_sensor_type_ant"
|
||||||
translation_description="In the 'Sensor' settings, for the 'Sensor type' dropdown, the option to
|
translation_description="In the 'Sensor' settings, for the 'Sensor type' dropdown, the option to
|
||||||
connect to an ANT+ heart rate sensor. Note that ANT+ is a radio standard.
|
connect to an ANT+ sensor. Note that ANT+ is a radio standard.
|
||||||
|
|
||||||
Character limit: ~21 (1 line)">
|
Character limit: ~21 (1 line)">
|
||||||
ANT+ heart rate
|
ANT+
|
||||||
</string>
|
</string>
|
||||||
<string name="settings_sensor_type_none"
|
<string name="settings_sensor_type_none"
|
||||||
translation_description="In the 'Sensor' settings, for the 'Sensor type' dropdown, the option to
|
translation_description="In the 'Sensor' settings, for the 'Sensor type' dropdown, the option to
|
||||||
@@ -1812,14 +1825,6 @@ limitations under the License.
|
|||||||
Character limit: ~21 (1 line)">
|
Character limit: ~21 (1 line)">
|
||||||
Polar Bluetooth
|
Polar Bluetooth
|
||||||
</string>
|
</string>
|
||||||
<string name="settings_sensor_type_srm"
|
|
||||||
translation_description="In the 'Sensor' settings, for the 'Sensor type' dropdown, the option to
|
|
||||||
connect to a SRM ANT+ bridge. Do not translate SRM, the company name, but can translate
|
|
||||||
ANT+, the radio standard, and bridge (network bridge).
|
|
||||||
|
|
||||||
Character limit: ~21 (1 line)">
|
|
||||||
SRM ANT+ bridge
|
|
||||||
</string>
|
|
||||||
<string name="settings_sensor_type_summary"
|
<string name="settings_sensor_type_summary"
|
||||||
translation_description="In the 'Sensor' settings, the summary for the 'Sensor type' option
|
translation_description="In the 'Sensor' settings, the summary for the 'Sensor type' option
|
||||||
explaining that it is to configure the type of sensor to connect to.">
|
explaining that it is to configure the type of sensor to connect to.">
|
||||||
@@ -1833,21 +1838,6 @@ limitations under the License.
|
|||||||
Character limit: ~21 (1 line)">
|
Character limit: ~21 (1 line)">
|
||||||
Zephyr Bluetooth
|
Zephyr Bluetooth
|
||||||
</string>
|
</string>
|
||||||
<string name="settings_sensor_unpair_ant"
|
|
||||||
translation_description="In the 'Sensor' settings, under the 'ANT+ options' configurations, the
|
|
||||||
option to unpair an ANT+ heart rate sensor. Note that ANT+ is a radio standard.
|
|
||||||
|
|
||||||
Character limit: ~26 (1 line)">
|
|
||||||
Unpair ANT+ heart rate
|
|
||||||
</string>
|
|
||||||
<string name="settings_sensor_unpair_srm"
|
|
||||||
translation_description="In the 'Sensor' settings, under the 'ANT+ options' configurations, the
|
|
||||||
option to unpair a SRM ANT+ bridge. Do not translate SRM, the company name, but can translate
|
|
||||||
ANT+, the radio standard, and bridge (network bridge).
|
|
||||||
|
|
||||||
Character limit: ~26 (1 line)">
|
|
||||||
Unpair SRM ANT+ bridge
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<!-- Settings Sharing -->
|
<!-- Settings Sharing -->
|
||||||
<string name="settings_sharing"
|
<string name="settings_sharing"
|
||||||
|
|||||||
@@ -39,13 +39,13 @@ limitations under the License.
|
|||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="@string/settings_sensor_ant_key"
|
android:key="@string/settings_sensor_ant_key"
|
||||||
android:title="@string/settings_sensor_ant_options" >
|
android:title="@string/settings_sensor_ant_options" >
|
||||||
<com.google.android.apps.mytracks.AntPreference
|
<Preference
|
||||||
android:defaultValue="0"
|
android:key="@string/settings_sensor_ant_reset_heart_rate_monitor_key"
|
||||||
android:key="@string/ant_heart_rate_sensor_id_key"
|
android:persistent="false"
|
||||||
android:title="@string/settings_sensor_unpair_ant" />
|
android:title="@string/settings_sensor_ant_reset_heart_rate_monitor" />
|
||||||
<com.google.android.apps.mytracks.AntPreference
|
<Preference
|
||||||
android:defaultValue="0"
|
android:key="@string/settings_sensor_ant_reset_speed_distance_monitor_key"
|
||||||
android:key="@string/ant_srm_bridge_sensor_id_key"
|
android:persistent="false"
|
||||||
android:title="@string/settings_sensor_unpair_srm" />
|
android:title="@string/settings_sensor_ant_reset_speed_distance_monitor" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
@@ -1,268 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 Dynastream Innovations Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.dsi.ant;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Android Ant API is not finalized, and *will* change. Use at your
|
|
||||||
* own risk.
|
|
||||||
*
|
|
||||||
* Public API for controlling the Ant Service.
|
|
||||||
* AntDefines contains definitions commonly used in ANT messaging.
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public class AntDefine {
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Valid Configuration Values
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte MIN_BIN = 0;
|
|
||||||
public static final byte MAX_BIN = 10;
|
|
||||||
|
|
||||||
public static final short MIN_DEVICE_ID = 0;
|
|
||||||
public static final short MAX_DEVICE_ID = (short)65535;
|
|
||||||
|
|
||||||
public static final short MIN_BUFFER_THRESHOLD = 0;
|
|
||||||
public static final short MAX_BUFFER_THRESHOLD = 996;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// ANT Message Payload Size
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte ANT_STANDARD_DATA_PAYLOAD_SIZE =((byte)8);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// ANT LIBRARY Extended Data Message Fields
|
|
||||||
// NOTE: You must check the extended message
|
|
||||||
// bitfield first to find out which fields
|
|
||||||
// are present before accessing them!
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte ANT_EXT_MESG_DEVICE_ID_FIELD_SIZE =((byte)4);
|
|
||||||
//public static final byte ANT_EXT_STRING_SIZE =((byte)19); // this is the additional buffer space required required for setting USB Descriptor strings
|
|
||||||
public static final byte ANT_EXT_STRING_SIZE =((byte)0); // changed to 0 as we will not be dealing with ANT USB parts.
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// ANT Extended Data Message Bifield Definitions
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte ANT_EXT_MESG_BITFIELD_DEVICE_ID =((byte)0x80); // first field after bitfield
|
|
||||||
public static final byte ANT_EXT_MESG_BITFIELD_RSSI =((byte)0x40); // next field after ID, if there is one
|
|
||||||
public static final byte ANT_EXT_MESG_BITFIELD_TIME_STAMP =((byte)0x20); // next field after RSSI, if there is one
|
|
||||||
|
|
||||||
// 4 bits free reserved set to 0
|
|
||||||
public static final byte ANT_EXT_MESG_BIFIELD_EXTENSION =((byte)0x01);
|
|
||||||
|
|
||||||
// extended message input bitfield defines
|
|
||||||
public static final byte ANT_EXT_MESG_BITFIELD_OVERWRITE_SHARED_ADR =((byte)0x10);
|
|
||||||
public static final byte ANT_EXT_MESG_BITFIELD_TRANSMISSION_TYPE =((byte)0x08);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// ID Definitions
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte ANT_ID_SIZE =((byte)4);
|
|
||||||
public static final byte ANT_ID_TRANS_TYPE_OFFSET =((byte)3);
|
|
||||||
public static final byte ANT_ID_DEVICE_TYPE_OFFSET =((byte)2);
|
|
||||||
public static final byte ANT_ID_DEVICE_NUMBER_HIGH_OFFSET =((byte)1);
|
|
||||||
public static final byte ANT_ID_DEVICE_NUMBER_LOW_OFFSET =((byte)0);
|
|
||||||
public static final byte ANT_ID_DEVICE_TYPE_PAIRING_FLAG =((byte)0x80);
|
|
||||||
|
|
||||||
public static final byte ANT_TRANS_TYPE_SHARED_ADDR_MASK =((byte)0x03);
|
|
||||||
public static final byte ANT_TRANS_TYPE_1_BYTE_SHARED_ADDRESS =((byte)0x02);
|
|
||||||
public static final byte ANT_TRANS_TYPE_2_BYTE_SHARED_ADDRESS =((byte)0x03);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Assign Channel Parameters
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte PARAMETER_RX_NOT_TX =((byte)0x00);
|
|
||||||
public static final byte PARAMETER_TX_NOT_RX =((byte)0x10);
|
|
||||||
public static final byte PARAMETER_SHARED_CHANNEL =((byte)0x20);
|
|
||||||
public static final byte PARAMETER_NO_TX_GUARD_BAND =((byte)0x40);
|
|
||||||
public static final byte PARAMETER_ALWAYS_RX_WILD_CARD_SEARCH_ID =((byte)0x40); //Pre-AP2
|
|
||||||
public static final byte PARAMETER_RX_ONLY =((byte)0x40);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Ext. Assign Channel Parameters
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte EXT_PARAM_ALWAYS_SEARCH =((byte)0x01);
|
|
||||||
public static final byte EXT_PARAM_FREQUENCY_AGILITY =((byte)0x04);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Radio TX Power Definitions
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte RADIO_TX_POWER_LVL_MASK =((byte)0x03);
|
|
||||||
|
|
||||||
public static final byte RADIO_TX_POWER_LVL_0 =((byte)0x00); //(formerly: RADIO_TX_POWER_MINUS20DB); lowest
|
|
||||||
public static final byte RADIO_TX_POWER_LVL_1 =((byte)0x01); //(formerly: RADIO_TX_POWER_MINUS10DB);
|
|
||||||
public static final byte RADIO_TX_POWER_LVL_2 =((byte)0x02); //(formerly: RADIO_TX_POWER_MINUS5DB);
|
|
||||||
public static final byte RADIO_TX_POWER_LVL_3 =((byte)0x03); //(formerly: RADIO_TX_POWER_0DB); highest
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Channel Status
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte STATUS_CHANNEL_STATE_MASK =((byte)0x03);
|
|
||||||
public static final byte STATUS_UNASSIGNED_CHANNEL =((byte)0x00);
|
|
||||||
public static final byte STATUS_ASSIGNED_CHANNEL =((byte)0x01);
|
|
||||||
public static final byte STATUS_SEARCHING_CHANNEL =((byte)0x02);
|
|
||||||
public static final byte STATUS_TRACKING_CHANNEL =((byte)0x03);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Standard capabilities defines
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte CAPABILITIES_NO_RX_CHANNELS =((byte)0x01);
|
|
||||||
public static final byte CAPABILITIES_NO_TX_CHANNELS =((byte)0x02);
|
|
||||||
public static final byte CAPABILITIES_NO_RX_MESSAGES =((byte)0x04);
|
|
||||||
public static final byte CAPABILITIES_NO_TX_MESSAGES =((byte)0x08);
|
|
||||||
public static final byte CAPABILITIES_NO_ACKD_MESSAGES =((byte)0x10);
|
|
||||||
public static final byte CAPABILITIES_NO_BURST_TRANSFER =((byte)0x20);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Advanced capabilities defines
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte CAPABILITIES_OVERUN_UNDERRUN =((byte)0x01); // Support for this functionality has been dropped
|
|
||||||
public static final byte CAPABILITIES_NETWORK_ENABLED =((byte)0x02);
|
|
||||||
public static final byte CAPABILITIES_AP1_VERSION_2 =((byte)0x04); // This Version of the AP1 does not support transmit and only had a limited release
|
|
||||||
public static final byte CAPABILITIES_SERIAL_NUMBER_ENABLED =((byte)0x08);
|
|
||||||
public static final byte CAPABILITIES_PER_CHANNEL_TX_POWER_ENABLED =((byte)0x10);
|
|
||||||
public static final byte CAPABILITIES_LOW_PRIORITY_SEARCH_ENABLED =((byte)0x20);
|
|
||||||
public static final byte CAPABILITIES_SCRIPT_ENABLED =((byte)0x40);
|
|
||||||
public static final byte CAPABILITIES_SEARCH_LIST_ENABLED =((byte)0x80);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Advanced capabilities 2 defines
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte CAPABILITIES_LED_ENABLED =((byte)0x01);
|
|
||||||
public static final byte CAPABILITIES_EXT_MESSAGE_ENABLED =((byte)0x02);
|
|
||||||
public static final byte CAPABILITIES_SCAN_MODE_ENABLED =((byte)0x04);
|
|
||||||
public static final byte CAPABILITIES_RESERVED =((byte)0x08);
|
|
||||||
public static final byte CAPABILITIES_PROX_SEARCH_ENABLED =((byte)0x10);
|
|
||||||
public static final byte CAPABILITIES_EXT_ASSIGN_ENABLED =((byte)0x20);
|
|
||||||
public static final byte CAPABILITIES_FREE_1 =((byte)0x40);
|
|
||||||
public static final byte CAPABILITIES_FIT1_ENABLED =((byte)0x80);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Advanced capabilities 3 defines
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte CAPABILITIES_SENSRCORE_ENABLED =((byte)0x01);
|
|
||||||
public static final byte CAPABILITIES_RESERVED_1 =((byte)0x02);
|
|
||||||
public static final byte CAPABILITIES_RESERVED_2 =((byte)0x04);
|
|
||||||
public static final byte CAPABILITIES_RESERVED_3 =((byte)0x08);
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Burst Message Sequence
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte CHANNEL_NUMBER_MASK =((byte)0x1F);
|
|
||||||
public static final byte SEQUENCE_NUMBER_MASK =((byte)0xE0);
|
|
||||||
public static final byte SEQUENCE_NUMBER_ROLLOVER =((byte)0x60);
|
|
||||||
public static final byte SEQUENCE_FIRST_MESSAGE =((byte)0x00);
|
|
||||||
public static final byte SEQUENCE_LAST_MESSAGE =((byte)0x80);
|
|
||||||
public static final byte SEQUENCE_NUMBER_INC =((byte)0x20);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Control Message Flags
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte BROADCAST_CONTROL_BYTE =((byte)0x00);
|
|
||||||
public static final byte ACKNOWLEDGED_CONTROL_BYTE =((byte)0xA0);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Response / Event Codes
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte RESPONSE_NO_ERROR =((byte)0x00);
|
|
||||||
public static final byte NO_EVENT =((byte)0x00);
|
|
||||||
|
|
||||||
public static final byte EVENT_RX_SEARCH_TIMEOUT =((byte)0x01);
|
|
||||||
public static final byte EVENT_RX_FAIL =((byte)0x02);
|
|
||||||
public static final byte EVENT_TX =((byte)0x03);
|
|
||||||
public static final byte EVENT_TRANSFER_RX_FAILED =((byte)0x04);
|
|
||||||
public static final byte EVENT_TRANSFER_TX_COMPLETED =((byte)0x05);
|
|
||||||
public static final byte EVENT_TRANSFER_TX_FAILED =((byte)0x06);
|
|
||||||
public static final byte EVENT_CHANNEL_CLOSED =((byte)0x07);
|
|
||||||
public static final byte EVENT_RX_FAIL_GO_TO_SEARCH =((byte)0x08);
|
|
||||||
public static final byte EVENT_CHANNEL_COLLISION =((byte)0x09);
|
|
||||||
public static final byte EVENT_TRANSFER_TX_START =((byte)0x0A); // a pending transmit transfer has begun
|
|
||||||
|
|
||||||
public static final byte EVENT_CHANNEL_ACTIVE =((byte)0x0F);
|
|
||||||
|
|
||||||
public static final byte EVENT_TRANSFER_TX_NEXT_MESSAGE =((byte)0x11); // only enabled in FIT1
|
|
||||||
|
|
||||||
public static final byte CHANNEL_IN_WRONG_STATE =((byte)0x15); // returned on attempt to perform an action from the wrong channel state
|
|
||||||
public static final byte CHANNEL_NOT_OPENED =((byte)0x16); // returned on attempt to communicate on a channel that is not open
|
|
||||||
public static final byte CHANNEL_ID_NOT_SET =((byte)0x18); // returned on attempt to open a channel without setting the channel ID
|
|
||||||
public static final byte CLOSE_ALL_CHANNELS =((byte)0x19); // returned when attempting to start scanning mode, when channels are still open
|
|
||||||
|
|
||||||
public static final byte TRANSFER_IN_PROGRESS =((byte)0x1F); // returned on attempt to communicate on a channel with a TX transfer in progress
|
|
||||||
public static final byte TRANSFER_SEQUENCE_NUMBER_ERROR =((byte)0x20); // returned when sequence number is out of order on a Burst transfer
|
|
||||||
public static final byte TRANSFER_IN_ERROR =((byte)0x21);
|
|
||||||
public static final byte TRANSFER_BUSY =((byte)0x22);
|
|
||||||
|
|
||||||
public static final byte INVALID_MESSAGE_CRC =((byte)0x26); // returned if there is a framing error on an incomming message
|
|
||||||
public static final byte MESSAGE_SIZE_EXCEEDS_LIMIT =((byte)0x27); // returned if a data message is provided that is too large
|
|
||||||
public static final byte INVALID_MESSAGE =((byte)0x28); // returned when the message has an invalid parameter
|
|
||||||
public static final byte INVALID_NETWORK_NUMBER =((byte)0x29); // returned when an invalid network number is provided
|
|
||||||
public static final byte INVALID_LIST_ID =((byte)0x30); // returned when the provided list ID or size exceeds the limit
|
|
||||||
public static final byte INVALID_SCAN_TX_CHANNEL =((byte)0x31); // returned when attempting to transmit on channel 0 when in scan mode
|
|
||||||
|
|
||||||
public static final byte INVALID_PARAMETER_PROVIDED =((byte)0x33); // returned when an invalid parameter is specified in a configuration message
|
|
||||||
|
|
||||||
public static final byte EVENT_SERIAL_QUE_OVERFLOW =((byte)0x34);
|
|
||||||
public static final byte EVENT_QUE_OVERFLOW =((byte)0x35); // ANT event que has overflowed and lost 1 or more events
|
|
||||||
|
|
||||||
public static final byte EVENT_CLK_ERROR =((byte)0x36); // debug event for XOSC16M on LE1
|
|
||||||
|
|
||||||
public static final byte SCRIPT_FULL_ERROR =((byte)0x40); // error writing to script, memory is full
|
|
||||||
public static final byte SCRIPT_WRITE_ERROR =((byte)0x41); // error writing to script, bytes not written correctly
|
|
||||||
public static final byte SCRIPT_INVALID_PAGE_ERROR =((byte)0x42); // error accessing script page
|
|
||||||
public static final byte SCRIPT_LOCKED_ERROR =((byte)0x43); // the scripts are locked and can't be dumped
|
|
||||||
|
|
||||||
public static final byte NO_RESPONSE_MESSAGE =((byte)0x50); // returned to the Command_SerialMessageProcess function, so no reply message is generated
|
|
||||||
public static final byte RETURN_TO_MFG =((byte)0x51); // default return to any mesg when the module determines that the mfg procedure has not been fully completed
|
|
||||||
|
|
||||||
public static final byte FIT_ACTIVE_SEARCH_TIMEOUT =((byte)0x60); // Fit1 only event added for timeout of the pairing state after the Fit module becomes active
|
|
||||||
public static final byte FIT_WATCH_PAIR =((byte)0x61); // Fit1 only
|
|
||||||
public static final byte FIT_WATCH_UNPAIR =((byte)0x62); // Fit1 only
|
|
||||||
|
|
||||||
public static final byte USB_STRING_WRITE_FAIL =((byte)0x70);
|
|
||||||
|
|
||||||
// Internal only events below this point
|
|
||||||
public static final byte INTERNAL_ONLY_EVENTS =((byte)0x80);
|
|
||||||
public static final byte EVENT_RX =((byte)0x80); // INTERNAL: Event for a receive message
|
|
||||||
public static final byte EVENT_NEW_CHANNEL =((byte)0x81); // INTERNAL: EVENT for a new active channel
|
|
||||||
public static final byte EVENT_PASS_THRU =((byte)0x82); // INTERNAL: Event to allow an upper stack events to pass through lower stacks
|
|
||||||
|
|
||||||
public static final byte EVENT_BLOCKED =((byte)0xFF); // INTERNAL: Event to replace any event we do not wish to go out, will also zero the size of the Tx message
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
// Script Command Codes
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
public static final byte SCRIPT_CMD_FORMAT =((byte)0x00);
|
|
||||||
public static final byte SCRIPT_CMD_DUMP =((byte)0x01);
|
|
||||||
public static final byte SCRIPT_CMD_SET_DEFAULT_SECTOR =((byte)0x02);
|
|
||||||
public static final byte SCRIPT_CMD_END_SECTOR =((byte)0x03);
|
|
||||||
public static final byte SCRIPT_CMD_END_DUMP =((byte)0x04);
|
|
||||||
public static final byte SCRIPT_CMD_LOCK =((byte)0x05);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
// Reset Mesg Codes
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
public static final byte RESET_FLAGS_MASK =((byte)0xE0);
|
|
||||||
public static final byte RESET_SUSPEND =((byte)0x80); // this must follow bitfield def
|
|
||||||
public static final byte RESET_SYNC =((byte)0x40); // this must follow bitfield def
|
|
||||||
public static final byte RESET_CMD =((byte)0x20); // this must follow bitfield def
|
|
||||||
public static final byte RESET_WDT =((byte)0x02);
|
|
||||||
public static final byte RESET_RST =((byte)0x01);
|
|
||||||
public static final byte RESET_POR =((byte)0x00);
|
|
||||||
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 Dynastream Innovations Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.dsi.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages the ANT Interface
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public interface AntInterfaceIntent {
|
|
||||||
|
|
||||||
public static final String STATUS = "com.dsi.ant.rx.intent.STATUS";
|
|
||||||
public static final String ANT_MESSAGE = "com.dsi.ant.intent.ANT_MESSAGE";
|
|
||||||
public static final String ANT_INTERFACE_CLAIMED_PID = "com.dsi.ant.intent.ANT_INTERFACE_CLAIMED_PID";
|
|
||||||
|
|
||||||
public static final String ANT_ENABLED_ACTION = "com.dsi.ant.intent.action.ANT_ENABLED";
|
|
||||||
public static final String ANT_DISABLED_ACTION = "com.dsi.ant.intent.action.ANT_DISABLED";
|
|
||||||
public static final String ANT_RESET_ACTION = "com.dsi.ant.intent.action.ANT_RESET";
|
|
||||||
|
|
||||||
public static final String ANT_INTERFACE_CLAIMED_ACTION = "com.dsi.ant.intent.action.ANT_INTERFACE_CLAIMED_ACTION";
|
|
||||||
|
|
||||||
public static final String ANT_RX_MESSAGE_ACTION = "com.dsi.ant.intent.action.ANT_RX_MESSAGE_ACTION";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,279 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 Dynastream Innovations Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.dsi.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public API for controlling the Ant Service.
|
|
||||||
* AntMesg contains definitions for ANT message IDs
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public class AntMesg {
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// HCI VS Message Format
|
|
||||||
// Messages are in the format:
|
|
||||||
//
|
|
||||||
// Outgoing ANT messages (host -> ANT chip)
|
|
||||||
// 01 D1 FD XX YY YY II JJ ------
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// | HCI framing | | ANT Mesg |
|
|
||||||
//
|
|
||||||
// where: 01 is the 1 byte HCI packet Identifier (HCI Command packet)
|
|
||||||
// D1 FD is the 2 byte HCI op code (0xFDD1 stored in little endian)
|
|
||||||
// XX is the 1 byte Length of all parameters in bytes (number of bytes in the HCI packet after this byte)
|
|
||||||
// YY YY is the 2 byte Parameter describing the length of the entire ANT message (II JJ ------) stored in little endian
|
|
||||||
// II is the 1 byte size of the ANT message (0-249)
|
|
||||||
// JJ is the 1 byte ID of the ANT message (1-255, 0 is invalid)
|
|
||||||
// ------ is the data of the ANT message (0-249 bytes of data)
|
|
||||||
//
|
|
||||||
// Incoming HCI Command Complete for ANT message command (host <- ANT chip)
|
|
||||||
// 04 0E 04 01 D1 FD ZZ
|
|
||||||
//
|
|
||||||
// where: 04 is the 1 byte HCI packet Identifier (HCI Event packet)
|
|
||||||
// 0E is the 1 byte HCI event (Command Complete)
|
|
||||||
// 04 is the 1 byte Length of all parameters in bytes (there are 4 bytes)
|
|
||||||
// 01 is the 1 byte Number of parameters in the packet (there is 1 parameter)
|
|
||||||
// D1 FD is the 2 byte HCI Op code of the command (0xFDD1 stored in little endian)
|
|
||||||
// ZZ is the 1 byte response to the command (0x00 - Command Successful
|
|
||||||
// 0x1F - Returned if the receive message queue of the ANT chip is full, the command should be retried
|
|
||||||
// Other - Any other non-zero response code indicates an error)
|
|
||||||
//
|
|
||||||
// Incoming ANT messages (host <- ANT chip)
|
|
||||||
// 04 FF XX 00 05 YY YY II JJ ------
|
|
||||||
// ^ ^ ^ ^
|
|
||||||
// | HCI framing | | ANT Mesg |
|
|
||||||
//
|
|
||||||
// where: 04 is the 1 byte HCI packet Identifier (HCI Event packet)
|
|
||||||
// FF is the 1 byte HCI event code (0xFF Vendor Specific event)
|
|
||||||
// XX is the 1 byte Length of all parameters in bytes (number of bytes in the HCI packet after this byte)
|
|
||||||
// 00 05 is the 2 byte vendor specific event code for ANT messages (0x0500 stored in little endian)
|
|
||||||
// YY YY is the 2 byte Parameter describing the length of the entire ANT message (II JJ ------) stored in little endian
|
|
||||||
// II is the 1 byte size of the ANT message (0-249)
|
|
||||||
// JJ is the 1 byte ID of the ANT message (1-255, 0 is invalid)
|
|
||||||
// ------ is the data of the ANT message (0-249 bytes of data)
|
|
||||||
//
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public static final byte MESG_SYNC_SIZE =((byte)0); // Ant messages are embedded in HCI messages we do not include a sync byte
|
|
||||||
public static final byte MESG_SIZE_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_ID_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_CHANNEL_NUM_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_EXT_MESG_BF_SIZE =((byte)1); // NOTE: this could increase in the future
|
|
||||||
public static final byte MESG_CHECKSUM_SIZE =((byte)0); // Ant messages are embedded in HCI messages we do not include a checksum
|
|
||||||
public static final byte MESG_DATA_SIZE =((byte)9);
|
|
||||||
|
|
||||||
// The largest serial message is an ANT data message with all of the extended fields
|
|
||||||
public static final byte MESG_ANT_MAX_PAYLOAD_SIZE =AntDefine.ANT_STANDARD_DATA_PAYLOAD_SIZE;
|
|
||||||
|
|
||||||
public static final byte MESG_MAX_EXT_DATA_SIZE =(AntDefine.ANT_EXT_MESG_DEVICE_ID_FIELD_SIZE + AntDefine.ANT_EXT_STRING_SIZE); // ANT device ID (4 bytes) + Padding for ANT EXT string size(19 bytes)
|
|
||||||
|
|
||||||
public static final byte MESG_MAX_DATA_SIZE =(MESG_ANT_MAX_PAYLOAD_SIZE + MESG_EXT_MESG_BF_SIZE + MESG_MAX_EXT_DATA_SIZE); // ANT data payload (8 bytes) + extended bitfield (1 byte) + extended data (10 bytes)
|
|
||||||
public static final byte MESG_MAX_SIZE_VALUE =(MESG_MAX_DATA_SIZE + MESG_CHANNEL_NUM_SIZE); // this is the maximum value that the serial message size value is allowed to be
|
|
||||||
public static final byte MESG_BUFFER_SIZE =(MESG_SIZE_SIZE + MESG_ID_SIZE + MESG_CHANNEL_NUM_SIZE + MESG_MAX_DATA_SIZE + MESG_CHECKSUM_SIZE);
|
|
||||||
public static final byte MESG_FRAMED_SIZE =(MESG_ID_SIZE + MESG_CHANNEL_NUM_SIZE + MESG_MAX_DATA_SIZE);
|
|
||||||
public static final byte MESG_HEADER_SIZE =(MESG_SYNC_SIZE + MESG_SIZE_SIZE + MESG_ID_SIZE);
|
|
||||||
public static final byte MESG_FRAME_SIZE =(MESG_HEADER_SIZE + MESG_CHECKSUM_SIZE);
|
|
||||||
public static final byte MESG_MAX_SIZE =(MESG_MAX_DATA_SIZE + MESG_FRAME_SIZE);
|
|
||||||
|
|
||||||
public static final byte MESG_SIZE_OFFSET =(MESG_SYNC_SIZE);
|
|
||||||
public static final byte MESG_ID_OFFSET =(MESG_SYNC_SIZE + MESG_SIZE_SIZE);
|
|
||||||
public static final byte MESG_DATA_OFFSET =(MESG_HEADER_SIZE);
|
|
||||||
public static final byte MESG_RECOMMENDED_BUFFER_SIZE =((byte) 64); // This is the recommended size for serial message buffers if there are no RAM restrictions on the system
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Message ID's
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte MESG_INVALID_ID =((byte)0x00);
|
|
||||||
public static final byte MESG_EVENT_ID =((byte)0x01);
|
|
||||||
|
|
||||||
public static final byte MESG_VERSION_ID =((byte)0x3E);
|
|
||||||
public static final byte MESG_RESPONSE_EVENT_ID =((byte)0x40);
|
|
||||||
|
|
||||||
public static final byte MESG_UNASSIGN_CHANNEL_ID =((byte)0x41);
|
|
||||||
public static final byte MESG_ASSIGN_CHANNEL_ID =((byte)0x42);
|
|
||||||
public static final byte MESG_CHANNEL_MESG_PERIOD_ID =((byte)0x43);
|
|
||||||
public static final byte MESG_CHANNEL_SEARCH_TIMEOUT_ID =((byte)0x44);
|
|
||||||
public static final byte MESG_CHANNEL_RADIO_FREQ_ID =((byte)0x45);
|
|
||||||
public static final byte MESG_NETWORK_KEY_ID =((byte)0x46);
|
|
||||||
public static final byte MESG_RADIO_TX_POWER_ID =((byte)0x47);
|
|
||||||
public static final byte MESG_RADIO_CW_MODE_ID =((byte)0x48);
|
|
||||||
|
|
||||||
public static final byte MESG_SYSTEM_RESET_ID =((byte)0x4A);
|
|
||||||
public static final byte MESG_OPEN_CHANNEL_ID =((byte)0x4B);
|
|
||||||
public static final byte MESG_CLOSE_CHANNEL_ID =((byte)0x4C);
|
|
||||||
public static final byte MESG_REQUEST_ID =((byte)0x4D);
|
|
||||||
|
|
||||||
public static final byte MESG_BROADCAST_DATA_ID =((byte)0x4E);
|
|
||||||
public static final byte MESG_ACKNOWLEDGED_DATA_ID =((byte)0x4F);
|
|
||||||
public static final byte MESG_BURST_DATA_ID =((byte)0x50);
|
|
||||||
|
|
||||||
public static final byte MESG_CHANNEL_ID_ID =((byte)0x51);
|
|
||||||
public static final byte MESG_CHANNEL_STATUS_ID =((byte)0x52);
|
|
||||||
public static final byte MESG_RADIO_CW_INIT_ID =((byte)0x53);
|
|
||||||
public static final byte MESG_CAPABILITIES_ID =((byte)0x54);
|
|
||||||
|
|
||||||
public static final byte MESG_STACKLIMIT_ID =((byte)0x55);
|
|
||||||
|
|
||||||
public static final byte MESG_SCRIPT_DATA_ID =((byte)0x56);
|
|
||||||
public static final byte MESG_SCRIPT_CMD_ID =((byte)0x57);
|
|
||||||
|
|
||||||
public static final byte MESG_ID_LIST_ADD_ID =((byte)0x59);
|
|
||||||
public static final byte MESG_ID_LIST_CONFIG_ID =((byte)0x5A);
|
|
||||||
public static final byte MESG_OPEN_RX_SCAN_ID =((byte)0x5B);
|
|
||||||
|
|
||||||
public static final byte MESG_EXT_CHANNEL_RADIO_FREQ_ID =((byte)0x5C); // OBSOLETE: (for 905 radio)
|
|
||||||
public static final byte MESG_EXT_BROADCAST_DATA_ID =((byte)0x5D);
|
|
||||||
public static final byte MESG_EXT_ACKNOWLEDGED_DATA_ID =((byte)0x5E);
|
|
||||||
public static final byte MESG_EXT_BURST_DATA_ID =((byte)0x5F);
|
|
||||||
|
|
||||||
public static final byte MESG_CHANNEL_RADIO_TX_POWER_ID =((byte)0x60);
|
|
||||||
public static final byte MESG_GET_SERIAL_NUM_ID =((byte)0x61);
|
|
||||||
public static final byte MESG_GET_TEMP_CAL_ID =((byte)0x62);
|
|
||||||
public static final byte MESG_SET_LP_SEARCH_TIMEOUT_ID =((byte)0x63);
|
|
||||||
public static final byte MESG_SET_TX_SEARCH_ON_NEXT_ID =((byte)0x64);
|
|
||||||
public static final byte MESG_SERIAL_NUM_SET_CHANNEL_ID_ID =((byte)0x65);
|
|
||||||
public static final byte MESG_RX_EXT_MESGS_ENABLE_ID =((byte)0x66);
|
|
||||||
public static final byte MESG_RADIO_CONFIG_ALWAYS_ID =((byte)0x67);
|
|
||||||
public static final byte MESG_ENABLE_LED_FLASH_ID =((byte)0x68);
|
|
||||||
|
|
||||||
public static final byte MESG_XTAL_ENABLE_ID =((byte)0x6D);
|
|
||||||
|
|
||||||
public static final byte MESG_STARTUP_MESG_ID =((byte)0x6F);
|
|
||||||
public static final byte MESG_AUTO_FREQ_CONFIG_ID =((byte)0x70);
|
|
||||||
public static final byte MESG_PROX_SEARCH_CONFIG_ID =((byte)0x71);
|
|
||||||
public static final byte MESG_EVENT_BUFFERING_CONFIG_ID =((byte)0x74);
|
|
||||||
|
|
||||||
|
|
||||||
public static final byte MESG_CUBE_CMD_ID =((byte)0x80);
|
|
||||||
|
|
||||||
public static final byte MESG_GET_PIN_DIODE_CONTROL_ID =((byte)0x8D);
|
|
||||||
public static final byte MESG_PIN_DIODE_CONTROL_ID =((byte)0x8E);
|
|
||||||
public static final byte MESG_FIT1_SET_AGC_ID =((byte)0x8F);
|
|
||||||
|
|
||||||
public static final byte MESG_FIT1_SET_EQUIP_STATE_ID =((byte)0x91); // *** CONFLICT: w/ Sensrcore, Fit1 will never have sensrcore enabled
|
|
||||||
|
|
||||||
// Sensrcore Messages
|
|
||||||
public static final byte MESG_SET_CHANNEL_INPUT_MASK_ID =((byte)0x90);
|
|
||||||
public static final byte MESG_SET_CHANNEL_DATA_TYPE_ID =((byte)0x91);
|
|
||||||
public static final byte MESG_READ_PINS_FOR_SECT_ID =((byte)0x92);
|
|
||||||
public static final byte MESG_TIMER_SELECT_ID =((byte)0x93);
|
|
||||||
public static final byte MESG_ATOD_SETTINGS_ID =((byte)0x94);
|
|
||||||
public static final byte MESG_SET_SHARED_ADDRESS_ID =((byte)0x95);
|
|
||||||
public static final byte MESG_ATOD_EXTERNAL_ENABLE_ID =((byte)0x96);
|
|
||||||
public static final byte MESG_ATOD_PIN_SETUP_ID =((byte)0x97);
|
|
||||||
public static final byte MESG_SETUP_ALARM_ID =((byte)0x98);
|
|
||||||
public static final byte MESG_ALARM_VARIABLE_MODIFY_TEST_ID =((byte)0x99);
|
|
||||||
public static final byte MESG_PARTIAL_RESET_ID =((byte)0x9A);
|
|
||||||
public static final byte MESG_OVERWRITE_TEMP_CAL_ID =((byte)0x9B);
|
|
||||||
public static final byte MESG_SERIAL_PASSTHRU_SETTINGS_ID =((byte)0x9C);
|
|
||||||
|
|
||||||
public static final byte MESG_BIST_ID =((byte)0xAA);
|
|
||||||
|
|
||||||
public static final byte MESG_UNLOCK_INTERFACE_ID =((byte)0xAD);
|
|
||||||
public static final byte MESG_SERIAL_ERROR_ID =((byte)0xAE);
|
|
||||||
public static final byte MESG_SET_ID_STRING_ID =((byte)0xAF);
|
|
||||||
|
|
||||||
public static final byte MESG_PORT_GET_IO_STATE_ID =((byte)0xB4);
|
|
||||||
public static final byte MESG_PORT_SET_IO_STATE_ID =((byte)0xB5);
|
|
||||||
|
|
||||||
public static final byte MESG_SLEEP_ID =((byte)0xC5);
|
|
||||||
public static final byte MESG_GET_GRMN_ESN_ID =((byte)0xC6);
|
|
||||||
public static final byte MESG_SET_USB_INFO_ID =((byte)0xC7);
|
|
||||||
|
|
||||||
public static final byte MESG_COMMAND_COMPLETE_RESPONSE_ID =((byte)0xC8);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Command complete results
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte MESG_COMMAND_COMPLETE_SUCCESS =((byte)0x00);
|
|
||||||
public static final byte MESG_COMMAND_COMPLETE_RETRY =((byte)0x1F);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Message Sizes
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final byte MESG_INVALID_SIZE =((byte)0);
|
|
||||||
|
|
||||||
public static final byte MESG_VERSION_SIZE =((byte)13);
|
|
||||||
public static final byte MESG_RESPONSE_EVENT_SIZE =((byte)3);
|
|
||||||
public static final byte MESG_CHANNEL_STATUS_SIZE =((byte)2);
|
|
||||||
|
|
||||||
public static final byte MESG_UNASSIGN_CHANNEL_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_ASSIGN_CHANNEL_SIZE =((byte)3);
|
|
||||||
public static final byte MESG_CHANNEL_ID_SIZE =((byte)5);
|
|
||||||
public static final byte MESG_CHANNEL_MESG_PERIOD_SIZE =((byte)3);
|
|
||||||
public static final byte MESG_CHANNEL_SEARCH_TIMEOUT_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_CHANNEL_RADIO_FREQ_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_CHANNEL_RADIO_TX_POWER_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_NETWORK_KEY_SIZE =((byte)9);
|
|
||||||
public static final byte MESG_RADIO_TX_POWER_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_RADIO_CW_MODE_SIZE =((byte)3);
|
|
||||||
public static final byte MESG_RADIO_CW_INIT_SIZE =((byte)1);
|
|
||||||
|
|
||||||
public static final byte MESG_SYSTEM_RESET_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_OPEN_CHANNEL_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_CLOSE_CHANNEL_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_REQUEST_SIZE =((byte)2);
|
|
||||||
|
|
||||||
public static final byte MESG_CAPABILITIES_SIZE =((byte)6);
|
|
||||||
public static final byte MESG_STACKLIMIT_SIZE =((byte)2);
|
|
||||||
|
|
||||||
public static final byte MESG_SCRIPT_DATA_SIZE =((byte)10);
|
|
||||||
public static final byte MESG_SCRIPT_CMD_SIZE =((byte)3);
|
|
||||||
|
|
||||||
public static final byte MESG_ID_LIST_ADD_SIZE =((byte)6);
|
|
||||||
public static final byte MESG_ID_LIST_CONFIG_SIZE =((byte)3);
|
|
||||||
public static final byte MESG_OPEN_RX_SCAN_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_EXT_CHANNEL_RADIO_FREQ_SIZE =((byte)3);
|
|
||||||
|
|
||||||
public static final byte MESG_RADIO_CONFIG_ALWAYS_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_RX_EXT_MESGS_ENABLE_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_SET_TX_SEARCH_ON_NEXT_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_SET_LP_SEARCH_TIMEOUT_SIZE =((byte)2);
|
|
||||||
|
|
||||||
public static final byte MESG_SERIAL_NUM_SET_CHANNEL_ID_SIZE =((byte)3);
|
|
||||||
public static final byte MESG_ENABLE_LED_FLASH_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_GET_SERIAL_NUM_SIZE =((byte)4);
|
|
||||||
public static final byte MESG_GET_TEMP_CAL_SIZE =((byte)4);
|
|
||||||
|
|
||||||
public static final byte MESG_XTAL_ENABLE_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_STARTUP_MESG_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_AUTO_FREQ_CONFIG_SIZE =((byte)4);
|
|
||||||
public static final byte MESG_PROX_SEARCH_CONFIG_SIZE =((byte)2);
|
|
||||||
|
|
||||||
public static final byte MESG_GET_PIN_DIODE_CONTROL_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_PIN_DIODE_CONTROL_ID_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_FIT1_SET_EQUIP_STATE_SIZE =((byte)2);
|
|
||||||
public static final byte MESG_FIT1_SET_AGC_SIZE =((byte)3);
|
|
||||||
|
|
||||||
public static final byte MESG_BIST_SIZE =((byte)6);
|
|
||||||
public static final byte MESG_UNLOCK_INTERFACE_SIZE =((byte)1);
|
|
||||||
public static final byte MESG_SET_SHARED_ADDRESS_SIZE =((byte)3);
|
|
||||||
|
|
||||||
public static final byte MESG_GET_GRMN_ESN_SIZE =((byte)5);
|
|
||||||
|
|
||||||
public static final byte MESG_PORT_SET_IO_STATE_SIZE =((byte)5);
|
|
||||||
|
|
||||||
public static final byte MESG_EVENT_BUFFERING_CONFIG_SIZE =((byte)6);
|
|
||||||
|
|
||||||
public static final byte MESG_SLEEP_SIZE =((byte)1);
|
|
||||||
|
|
||||||
|
|
||||||
public static final byte MESG_EXT_DATA_SIZE =((byte)13);
|
|
||||||
|
|
||||||
protected AntMesg()
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 Dynastream Innovations Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.dsi.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Android Ant API is not finalized, and *will* be updated and expanded.
|
|
||||||
* This is the base level ANT messaging API and gives any application full
|
|
||||||
* control over the ANT radio HW. Caution should be exercised when using
|
|
||||||
* this interface.
|
|
||||||
*
|
|
||||||
* Public API for controlling the Ant Service.
|
|
||||||
*
|
|
||||||
* {@hide}
|
|
||||||
*/
|
|
||||||
interface IAnt {
|
|
||||||
// Since version 1 (1.0):
|
|
||||||
boolean enable();
|
|
||||||
boolean disable();
|
|
||||||
boolean isEnabled();
|
|
||||||
|
|
||||||
boolean ANTTxMessage(in byte[] message);
|
|
||||||
|
|
||||||
boolean ANTResetSystem();
|
|
||||||
boolean ANTUnassignChannel(byte channelNumber);
|
|
||||||
boolean ANTAssignChannel(byte channelNumber, byte channelType, byte networkNumber);
|
|
||||||
boolean ANTSetChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType);
|
|
||||||
boolean ANTSetChannelPeriod(byte channelNumber, int channelPeriod);
|
|
||||||
boolean ANTSetChannelRFFreq(byte channelNumber, byte radioFrequency);
|
|
||||||
boolean ANTSetChannelSearchTimeout(byte channelNumber, byte searchTimeout);
|
|
||||||
boolean ANTSetLowPriorityChannelSearchTimeout(byte channelNumber, byte searchTimeout);
|
|
||||||
boolean ANTSetProximitySearch(byte channelNumber, byte searchThreshold);
|
|
||||||
boolean ANTSetChannelTxPower(byte channelNumber, byte txPower);
|
|
||||||
boolean ANTAddChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType, byte listIndex);
|
|
||||||
boolean ANTConfigList(byte channelNumber, byte listSize, byte exclude);
|
|
||||||
|
|
||||||
boolean ANTOpenChannel(byte channelNumber);
|
|
||||||
boolean ANTCloseChannel(byte channelNumber);
|
|
||||||
|
|
||||||
boolean ANTRequestMessage(byte channelNumber, byte messageID);
|
|
||||||
boolean ANTSendBroadcastData(byte channelNumber, in byte[] txBuffer);
|
|
||||||
boolean ANTSendAcknowledgedData(byte channelNumber, in byte[] txBuffer);
|
|
||||||
|
|
||||||
boolean ANTSendBurstTransferPacket(byte control, in byte[] txBuffer);
|
|
||||||
|
|
||||||
int ANTSendBurstTransfer(byte channelNumber, in byte[] txBuffer);
|
|
||||||
int ANTTransmitBurst(byte channelNumber, in byte[] txBuffer, int initialPacket, boolean containsEndOfBurst);
|
|
||||||
|
|
||||||
// Since version 4 (1.3):
|
|
||||||
boolean ANTConfigEventBuffering(int screenOnFlushTimerInterval, int screenOnFlushBufferThreshold, int screenOffFlushTimerInterval, int screenOffFlushBufferThreshold);
|
|
||||||
|
|
||||||
// Since version 2 (1.1):
|
|
||||||
boolean ANTDisableEventBuffering();
|
|
||||||
|
|
||||||
// Since version 3 (1.2):
|
|
||||||
int getServiceLibraryVersionCode();
|
|
||||||
String getServiceLibraryVersionName();
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Dynastream Innovations Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.dsi.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Android Ant API is not finalized, and *will* be updated and expanded.
|
|
||||||
* This is the base level ANT messaging API and gives any application full
|
|
||||||
* control over the ANT radio HW. Caution should be exercised when using
|
|
||||||
* this interface.
|
|
||||||
*
|
|
||||||
* Public API for controlling the Ant Service.
|
|
||||||
*
|
|
||||||
* {@hide}
|
|
||||||
*/
|
|
||||||
interface IAnt_6 {
|
|
||||||
// Since version 1 (1.0):
|
|
||||||
boolean enable();
|
|
||||||
boolean disable();
|
|
||||||
boolean isEnabled();
|
|
||||||
|
|
||||||
boolean ANTTxMessage(in byte[] message);
|
|
||||||
|
|
||||||
boolean ANTResetSystem();
|
|
||||||
boolean ANTUnassignChannel(byte channelNumber);
|
|
||||||
boolean ANTAssignChannel(byte channelNumber, byte channelType, byte networkNumber);
|
|
||||||
boolean ANTSetChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType);
|
|
||||||
boolean ANTSetChannelPeriod(byte channelNumber, int channelPeriod);
|
|
||||||
boolean ANTSetChannelRFFreq(byte channelNumber, byte radioFrequency);
|
|
||||||
boolean ANTSetChannelSearchTimeout(byte channelNumber, byte searchTimeout);
|
|
||||||
boolean ANTSetLowPriorityChannelSearchTimeout(byte channelNumber, byte searchTimeout);
|
|
||||||
boolean ANTSetProximitySearch(byte channelNumber, byte searchThreshold);
|
|
||||||
boolean ANTSetChannelTxPower(byte channelNumber, byte txPower);
|
|
||||||
boolean ANTAddChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType, byte listIndex);
|
|
||||||
boolean ANTConfigList(byte channelNumber, byte listSize, byte exclude);
|
|
||||||
|
|
||||||
boolean ANTOpenChannel(byte channelNumber);
|
|
||||||
boolean ANTCloseChannel(byte channelNumber);
|
|
||||||
|
|
||||||
boolean ANTRequestMessage(byte channelNumber, byte messageID);
|
|
||||||
boolean ANTSendBroadcastData(byte channelNumber, in byte[] txBuffer);
|
|
||||||
boolean ANTSendAcknowledgedData(byte channelNumber, in byte[] txBuffer);
|
|
||||||
|
|
||||||
boolean ANTSendBurstTransferPacket(byte control, in byte[] txBuffer);
|
|
||||||
|
|
||||||
int ANTSendBurstTransfer(byte channelNumber, in byte[] txBuffer);
|
|
||||||
int ANTTransmitBurst(byte channelNumber, in byte[] txBuffer, int initialPacket, boolean containsEndOfBurst);
|
|
||||||
|
|
||||||
// Since version 4 (1.3):
|
|
||||||
boolean ANTConfigEventBuffering(int screenOnFlushTimerInterval, int screenOnFlushBufferThreshold, int screenOffFlushTimerInterval, int screenOffFlushBufferThreshold);
|
|
||||||
|
|
||||||
// Since version 2 (1.1):
|
|
||||||
boolean ANTDisableEventBuffering();
|
|
||||||
|
|
||||||
// Since version 3 (1.2):
|
|
||||||
int getServiceLibraryVersionCode();
|
|
||||||
String getServiceLibraryVersionName();
|
|
||||||
|
|
||||||
// Since version 6 (1.5):
|
|
||||||
boolean claimInterface();
|
|
||||||
boolean requestForceClaimInterface(String appName);
|
|
||||||
boolean stopRequestForceClaimInterface();
|
|
||||||
boolean releaseInterface();
|
|
||||||
boolean hasClaimedInterface();
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 Dynastream Innovations Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.dsi.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* API for configuring the non-ANT components of the ANT Service.
|
|
||||||
*
|
|
||||||
* {@hide}
|
|
||||||
*/
|
|
||||||
interface IServiceSettings {
|
|
||||||
void debugLogging(boolean debug);
|
|
||||||
|
|
||||||
boolean setNumCombinedBurstPackets(int numPackets);
|
|
||||||
int getNumCombinedBurstPackets();
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Dynastream Innovations Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.dsi.ant;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines version numbers
|
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public class Version {
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Library Version Information
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
public static final int ANT_LIBRARY_VERSION_CODE = 6;
|
|
||||||
public static final int ANT_LIBRARY_VERSION_MAJOR = 2;
|
|
||||||
public static final int ANT_LIBRARY_VERSION_MINOR = 0;
|
|
||||||
public static final String ANT_LIBRARY_VERSION_NAME = String.valueOf(ANT_LIBRARY_VERSION_MAJOR) + "." + String.valueOf(ANT_LIBRARY_VERSION_MINOR);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.dsi.ant.exception;
|
|
||||||
|
|
||||||
public class AntInterfaceException extends Exception
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = -7278855366167722274L;
|
|
||||||
|
|
||||||
public AntInterfaceException()
|
|
||||||
{
|
|
||||||
this("Unknown ANT Interface error");
|
|
||||||
}
|
|
||||||
|
|
||||||
public AntInterfaceException(String string)
|
|
||||||
{
|
|
||||||
super(string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.dsi.ant.exception;
|
|
||||||
|
|
||||||
import android.os.RemoteException;
|
|
||||||
|
|
||||||
public class AntRemoteException extends AntInterfaceException
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 8950974759973459561L;
|
|
||||||
|
|
||||||
public AntRemoteException(RemoteException e)
|
|
||||||
{
|
|
||||||
this("ANT Interface error, ANT Radio Service remote error: "+e.toString(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AntRemoteException(String string, RemoteException e)
|
|
||||||
{
|
|
||||||
super(string);
|
|
||||||
|
|
||||||
this.initCause(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.dsi.ant.exception;
|
|
||||||
|
|
||||||
public class AntServiceNotConnectedException extends AntInterfaceException
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = -2085081032170129309L;
|
|
||||||
|
|
||||||
public AntServiceNotConnectedException()
|
|
||||||
{
|
|
||||||
this("ANT Interface error, ANT Radio Service not connected.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public AntServiceNotConnectedException(String string)
|
|
||||||
{
|
|
||||||
super(string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks;
|
|
||||||
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.preference.Preference;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A preference for an ANT device pairing.
|
|
||||||
* Currently this shows the ID and lets the user clear that ID for future pairing.
|
|
||||||
* TODO: Support pairing from this preference.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
*/
|
|
||||||
public class AntPreference extends Preference {
|
|
||||||
|
|
||||||
private final static int DEFAULT_PERSISTEDINT = 0;
|
|
||||||
|
|
||||||
public AntPreference(Context context) {
|
|
||||||
super(context);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AntPreference(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
int sensorId = getPersistedInt(AntPreference.DEFAULT_PERSISTEDINT);
|
|
||||||
if (sensorId == 0) {
|
|
||||||
setSummary(R.string.settings_sensor_ant_not_paired);
|
|
||||||
} else {
|
|
||||||
setSummary(getContext().getString(R.string.settings_sensor_ant_paired, sensorId));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add actions to allow repairing.
|
|
||||||
setOnPreferenceClickListener(
|
|
||||||
new OnPreferenceClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
AntPreference.this.persistInt(0);
|
|
||||||
setSummary(R.string.settings_sensor_ant_not_paired);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-2
@@ -96,8 +96,7 @@ public class BluetoothSensorManager extends SensorManager {
|
|||||||
case BluetoothConnectionManager.MESSAGE_DEVICE_NAME:
|
case BluetoothConnectionManager.MESSAGE_DEVICE_NAME:
|
||||||
String deviceName = message.getData()
|
String deviceName = message.getData()
|
||||||
.getString(BluetoothConnectionManager.KEY_DEVICE_NAME);
|
.getString(BluetoothConnectionManager.KEY_DEVICE_NAME);
|
||||||
Toast.makeText(context,
|
Toast.makeText(context, context.getString(R.string.settings_sensor_connected, deviceName),
|
||||||
context.getString(R.string.settings_sensor_bluetooth_connected, deviceName),
|
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
case BluetoothConnectionManager.MESSAGE_READ:
|
case BluetoothConnectionManager.MESSAGE_READ:
|
||||||
|
|||||||
+2
-5
@@ -16,8 +16,7 @@
|
|||||||
|
|
||||||
package com.google.android.apps.mytracks.services.sensors;
|
package com.google.android.apps.mytracks.services.sensors;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.services.sensors.ant.AntDirectSensorManager;
|
import com.google.android.apps.mytracks.services.sensors.ant.AntSensorManager;
|
||||||
import com.google.android.apps.mytracks.services.sensors.ant.AntSrmBridgeSensorManager;
|
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
@@ -98,9 +97,7 @@ public class SensorManagerFactory {
|
|||||||
context, R.string.sensor_type_key, sensorTypeValueNone);
|
context, R.string.sensor_type_key, sensorTypeValueNone);
|
||||||
|
|
||||||
if (sensorType.equals(context.getString(R.string.sensor_type_value_ant))) {
|
if (sensorType.equals(context.getString(R.string.sensor_type_value_ant))) {
|
||||||
return new AntDirectSensorManager(context);
|
return new AntSensorManager(context);
|
||||||
} else if (sensorType.equals(context.getString(R.string.sensor_type_value_srm_ant_bridge))) {
|
|
||||||
return new AntSrmBridgeSensorManager(context);
|
|
||||||
} else if (sensorType.equals(context.getString(R.string.sensor_type_value_zephyr))) {
|
} else if (sensorType.equals(context.getString(R.string.sensor_type_value_zephyr))) {
|
||||||
return new ZephyrSensorManager(context);
|
return new ZephyrSensorManager(context);
|
||||||
} else if (sensorType.equals(context.getString(R.string.sensor_type_value_polar))) {
|
} else if (sensorType.equals(context.getString(R.string.sensor_type_value_polar))) {
|
||||||
|
|||||||
-56
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class decodes and encapsulates an ANT Channel ID message.
|
|
||||||
* (ANT Message ID 0x51, Protocol & Usage guide v4.2 section 9.5.7.2)
|
|
||||||
*
|
|
||||||
* @author Matthew Simmons
|
|
||||||
*/
|
|
||||||
public class AntChannelIdMessage extends AntMessage {
|
|
||||||
private byte channelNumber;
|
|
||||||
private short deviceNumber;
|
|
||||||
private byte deviceTypeId;
|
|
||||||
private byte transmissionType;
|
|
||||||
|
|
||||||
public AntChannelIdMessage(byte[] messageData) {
|
|
||||||
channelNumber = messageData[0];
|
|
||||||
deviceNumber = decodeShort(messageData[1], messageData[2]);
|
|
||||||
deviceTypeId = messageData[3];
|
|
||||||
transmissionType = messageData[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the channel number */
|
|
||||||
public byte getChannelNumber() {
|
|
||||||
return channelNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the device number */
|
|
||||||
public short getDeviceNumber() {
|
|
||||||
return deviceNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the device type */
|
|
||||||
public byte getDeviceTypeId() {
|
|
||||||
return deviceTypeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the transmission type */
|
|
||||||
public byte getTransmissionType() {
|
|
||||||
return transmissionType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class decodes and encapsulates an ANT Channel Response / Event message.
|
|
||||||
* (ANT Message ID 0x40, Protocol & Usage guide v4.2 section 9.5.6.1)
|
|
||||||
*
|
|
||||||
* @author Matthew Simmons
|
|
||||||
*/
|
|
||||||
public class AntChannelResponseMessage extends AntMessage {
|
|
||||||
private byte channelNumber;
|
|
||||||
private byte messageId;
|
|
||||||
private byte messageCode;
|
|
||||||
|
|
||||||
public AntChannelResponseMessage(byte[] messageData) {
|
|
||||||
channelNumber = messageData[0];
|
|
||||||
messageId = messageData[1];
|
|
||||||
messageCode = messageData[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the channel number */
|
|
||||||
public byte getChannelNumber() {
|
|
||||||
return channelNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the ID of the message being responded to */
|
|
||||||
public byte getMessageId() {
|
|
||||||
return messageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the code for a specific response or event */
|
|
||||||
public byte getMessageCode() {
|
|
||||||
return messageCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-242
@@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
|
||||||
|
|
||||||
import com.dsi.ant.AntDefine;
|
|
||||||
import com.dsi.ant.AntMesg;
|
|
||||||
import com.dsi.ant.exception.AntInterfaceException;
|
|
||||||
import com.google.android.apps.mytracks.content.Sensor;
|
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A sensor manager to connect ANT+ sensors.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
* @author Laszlo Molnar
|
|
||||||
*/
|
|
||||||
public class AntDirectSensorManager extends AntSensorManager
|
|
||||||
implements AntSensorDataCollector {
|
|
||||||
|
|
||||||
// allocating one channel for each sensor type
|
|
||||||
private static final byte HEART_RATE_CHANNEL = 0;
|
|
||||||
private static final byte CADENCE_CHANNEL = 1;
|
|
||||||
private static final byte CADENCE_SPEED_CHANNEL = 2;
|
|
||||||
|
|
||||||
// ids for device number preferences
|
|
||||||
private static final int sensorIdKeys[] = {
|
|
||||||
R.string.ant_heart_rate_sensor_id_key,
|
|
||||||
R.string.ant_cadence_sensor_id_key,
|
|
||||||
R.string.ant_cadence_speed_sensor_id_key,
|
|
||||||
};
|
|
||||||
|
|
||||||
private AntSensorBase sensors[] = null;
|
|
||||||
|
|
||||||
// current data to be sent for SensorDataSet
|
|
||||||
private static final byte HEART_RATE_DATA_INDEX = 0;
|
|
||||||
private static final byte CADENCE_DATA_INDEX = 1;
|
|
||||||
private int currentSensorData[] = { -1, -1 };
|
|
||||||
|
|
||||||
private long lastDataSentMillis = 0;
|
|
||||||
private byte connectingChannelsBitmap = 0;
|
|
||||||
|
|
||||||
public AntDirectSensorManager(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean handleMessage(byte messageId, byte[] messageData) {
|
|
||||||
if (super.handleMessage(messageId, messageData)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int channel = messageData[0] & AntDefine.CHANNEL_NUMBER_MASK;
|
|
||||||
if (sensors == null || channel >= sensors.length) {
|
|
||||||
Log.d(TAG, "Unknown channel in message: " + channel);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AntSensorBase sensor = sensors[channel];
|
|
||||||
switch (messageId) {
|
|
||||||
case AntMesg.MESG_BROADCAST_DATA_ID:
|
|
||||||
if (sensor.getDeviceNumber() == WILDCARD) {
|
|
||||||
resolveWildcardDeviceNumber((byte) channel);
|
|
||||||
}
|
|
||||||
sensor.handleBroadcastData(messageData, this);
|
|
||||||
break;
|
|
||||||
case AntMesg.MESG_RESPONSE_EVENT_ID:
|
|
||||||
handleMessageResponse(messageData);
|
|
||||||
break;
|
|
||||||
case AntMesg.MESG_CHANNEL_ID_ID:
|
|
||||||
sensor.setDeviceNumber(handleChannelId(messageData));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unexpected ANT message id: " + messageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private short handleChannelId(byte[] rawMessage) {
|
|
||||||
AntChannelIdMessage message = new AntChannelIdMessage(rawMessage);
|
|
||||||
short deviceNumber = message.getDeviceNumber();
|
|
||||||
byte channel = message.getChannelNumber();
|
|
||||||
if (channel >= sensors.length) {
|
|
||||||
Log.d(TAG, "Unknown channel in message: " + channel);
|
|
||||||
return WILDCARD;
|
|
||||||
}
|
|
||||||
Log.i(TAG, "Found ANT device id: " + deviceNumber + " on channel: " + channel);
|
|
||||||
|
|
||||||
PreferencesUtils.setInt(context, sensorIdKeys[channel], deviceNumber);
|
|
||||||
return deviceNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void channelOut(byte channel)
|
|
||||||
{
|
|
||||||
if (channel >= sensors.length) {
|
|
||||||
Log.d(TAG, "Unknown channel in message: " + channel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
connectingChannelsBitmap &= ~(1 << channel);
|
|
||||||
Log.i(TAG, "ANT channel " + channel + " disconnected.");
|
|
||||||
|
|
||||||
if (sensors[channel].getDeviceNumber() != WILDCARD) {
|
|
||||||
Log.i(TAG, "Retrying....");
|
|
||||||
if (setupChannel(sensors[channel], channel)) {
|
|
||||||
connectingChannelsBitmap |= 1 << channel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (connectingChannelsBitmap == 0) {
|
|
||||||
setSensorState(Sensor.SensorState.DISCONNECTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleMessageResponse(byte[] rawMessage) {
|
|
||||||
AntChannelResponseMessage message = new AntChannelResponseMessage(rawMessage);
|
|
||||||
byte channel = message.getChannelNumber();
|
|
||||||
switch (message.getMessageId()) {
|
|
||||||
case AntMesg.MESG_EVENT_ID:
|
|
||||||
if (message.getMessageCode() == AntDefine.EVENT_RX_SEARCH_TIMEOUT) {
|
|
||||||
// Search timeout
|
|
||||||
Log.w(TAG, "ANT search timed out. Unassigning channel " + channel);
|
|
||||||
try {
|
|
||||||
getAntReceiver().ANTUnassignChannel(channel);
|
|
||||||
} catch (AntInterfaceException e) {
|
|
||||||
Log.e(TAG, "ANT error unassigning channel", e);
|
|
||||||
channelOut(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AntMesg.MESG_UNASSIGN_CHANNEL_ID:
|
|
||||||
channelOut(channel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resolveWildcardDeviceNumber(byte channel) {
|
|
||||||
try {
|
|
||||||
getAntReceiver().ANTRequestMessage(channel, AntMesg.MESG_CHANNEL_ID_ID);
|
|
||||||
} catch (AntInterfaceException e) {
|
|
||||||
Log.e(TAG, "ANT error handling broadcast data", e);
|
|
||||||
}
|
|
||||||
Log.d(TAG, "Requesting channel id id on channel: " + channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setupAntSensorChannels() {
|
|
||||||
short devIds[] = new short[sensorIdKeys.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < sensorIdKeys.length; ++i) {
|
|
||||||
devIds[i] = (short) PreferencesUtils.getInt(context, sensorIdKeys[i], WILDCARD);
|
|
||||||
}
|
|
||||||
|
|
||||||
sensors = new AntSensorBase[] {
|
|
||||||
new HeartRateSensor(devIds[HEART_RATE_CHANNEL]),
|
|
||||||
new CadenceSensor(devIds[CADENCE_CHANNEL]),
|
|
||||||
new CadenceSpeedSensor(devIds[CADENCE_SPEED_CHANNEL]),
|
|
||||||
};
|
|
||||||
|
|
||||||
connectingChannelsBitmap = 0;
|
|
||||||
for (int i = 0; i < sensors.length; ++i) {
|
|
||||||
if (setupChannel(sensors[i], (byte) i)) {
|
|
||||||
connectingChannelsBitmap |= 1 << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (connectingChannelsBitmap == 0) {
|
|
||||||
setSensorState(Sensor.SensorState.DISCONNECTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean setupChannel(AntSensorBase sensor, byte channel) {
|
|
||||||
Log.i(TAG, "setup channel=" + channel + " deviceType=" + sensor.getDeviceType());
|
|
||||||
|
|
||||||
return setupAntSensorChannel(sensor.getNetworkNumber(),
|
|
||||||
channel,
|
|
||||||
sensor.getDeviceNumber(),
|
|
||||||
sensor.getDeviceType(),
|
|
||||||
(byte) 0x01,
|
|
||||||
sensor.getChannelPeriod(),
|
|
||||||
sensor.getFrequency(),
|
|
||||||
(byte) 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendSensorData(byte index, int value) {
|
|
||||||
if (index >= currentSensorData.length) {
|
|
||||||
Log.w(TAG, "invalid index in sendSensorData:" + index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
currentSensorData[index] = value;
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
// data comes in at ~4Hz rate from the sensors, so after >300 msec
|
|
||||||
// fresh data is here from all the connected sensors
|
|
||||||
if (now < lastDataSentMillis + 300) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lastDataSentMillis = now;
|
|
||||||
setSensorState(Sensor.SensorState.CONNECTED);
|
|
||||||
|
|
||||||
Sensor.SensorDataSet.Builder b = Sensor.SensorDataSet.newBuilder();
|
|
||||||
if (currentSensorData[HEART_RATE_DATA_INDEX] >= 0) {
|
|
||||||
b.setHeartRate(
|
|
||||||
Sensor.SensorData.newBuilder()
|
|
||||||
.setValue(currentSensorData[HEART_RATE_DATA_INDEX])
|
|
||||||
.setState(Sensor.SensorState.SENDING));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentSensorData[CADENCE_DATA_INDEX] >= 0) {
|
|
||||||
b.setCadence(
|
|
||||||
Sensor.SensorData.newBuilder()
|
|
||||||
.setValue(currentSensorData[CADENCE_DATA_INDEX])
|
|
||||||
.setState(Sensor.SensorState.SENDING));
|
|
||||||
}
|
|
||||||
sensorData = b.setCreationTime(now).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCadence(int value) {
|
|
||||||
sendSensorData(CADENCE_DATA_INDEX, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeartRate(int value) {
|
|
||||||
sendSensorData(HEART_RATE_DATA_INDEX, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a common superclass for ANT message subclasses.
|
|
||||||
*
|
|
||||||
* @author Matthew Simmons
|
|
||||||
*/
|
|
||||||
public class AntMessage {
|
|
||||||
protected AntMessage() {}
|
|
||||||
|
|
||||||
/** Build a short value from its constituent bytes */
|
|
||||||
protected static short decodeShort(byte b0, byte b1) {
|
|
||||||
int value = b0 & 0xFF;
|
|
||||||
value |= (b1 & 0xFF) << 8;
|
|
||||||
return (short)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A enum which stores static data about ANT sensors.
|
|
||||||
*
|
|
||||||
* @author Matthew Simmons
|
|
||||||
*/
|
|
||||||
public enum AntSensor {
|
|
||||||
SENSOR_HEART_RATE (Constants.ANT_DEVICE_TYPE_HRM),
|
|
||||||
SENSOR_CADENCE (Constants.ANT_DEVICE_TYPE_CADENCE),
|
|
||||||
SENSOR_SPEED (Constants.ANT_DEVICE_TYPE_SPEED),
|
|
||||||
SENSOR_POWER (Constants.ANT_DEVICE_TYPE_POWER);
|
|
||||||
|
|
||||||
private static class Constants {
|
|
||||||
public static byte ANT_DEVICE_TYPE_POWER = 11;
|
|
||||||
public static byte ANT_DEVICE_TYPE_HRM = 120;
|
|
||||||
public static byte ANT_DEVICE_TYPE_CADENCE = 122;
|
|
||||||
public static byte ANT_DEVICE_TYPE_SPEED = 123;
|
|
||||||
};
|
|
||||||
|
|
||||||
private final byte deviceType;
|
|
||||||
|
|
||||||
private AntSensor(byte deviceType) {
|
|
||||||
this.deviceType = deviceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getDeviceType() {
|
|
||||||
return deviceType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for ANT+ sensors.
|
|
||||||
*
|
|
||||||
* @author Laszlo Molnar
|
|
||||||
*/
|
|
||||||
|
|
||||||
public abstract class AntSensorBase {
|
|
||||||
/*
|
|
||||||
* These constants are defined by the ANT+ spec.
|
|
||||||
*/
|
|
||||||
public static final byte NETWORK_NUMBER = 1;
|
|
||||||
public static final byte RF_FREQUENCY = 57;
|
|
||||||
|
|
||||||
private short deviceNumber;
|
|
||||||
private final byte deviceType;
|
|
||||||
private final short channelPeriod;
|
|
||||||
|
|
||||||
AntSensorBase(short deviceNumber, byte deviceType,
|
|
||||||
String deviceTypeString, short channelPeriod) {
|
|
||||||
this.deviceNumber = deviceNumber;
|
|
||||||
this.deviceType = deviceType;
|
|
||||||
this.channelPeriod = channelPeriod;
|
|
||||||
|
|
||||||
Log.i(TAG, "Will pair with " + deviceTypeString + " device: " + ((int) deviceNumber & 0xFFFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c);
|
|
||||||
|
|
||||||
public void setDeviceNumber(short dn) {
|
|
||||||
deviceNumber = dn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getDeviceNumber() {
|
|
||||||
return deviceNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getNetworkNumber() {
|
|
||||||
return NETWORK_NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getFrequency() {
|
|
||||||
return RF_FREQUENCY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte getDeviceType() {
|
|
||||||
return deviceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getChannelPeriod() {
|
|
||||||
return channelPeriod;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
+622
-288
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009 Google Inc.
|
* Copyright 2012 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
@@ -13,9 +13,8 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
package com.google.android.apps.mytracks.services.sensors.ant;
|
||||||
|
|
||||||
import com.dsi.ant.AntDefine;
|
import com.dsi.ant.AntDefine;
|
||||||
import com.dsi.ant.AntInterface;
|
import com.dsi.ant.AntInterface;
|
||||||
@@ -25,361 +24,696 @@ import com.dsi.ant.exception.AntInterfaceException;
|
|||||||
import com.dsi.ant.exception.AntServiceNotConnectedException;
|
import com.dsi.ant.exception.AntServiceNotConnectedException;
|
||||||
import com.google.android.apps.mytracks.content.Sensor;
|
import com.google.android.apps.mytracks.content.Sensor;
|
||||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||||
|
import com.google.android.apps.mytracks.content.Sensor.SensorState;
|
||||||
import com.google.android.apps.mytracks.services.sensors.SensorManager;
|
import com.google.android.apps.mytracks.services.sensors.SensorManager;
|
||||||
|
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||||
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the common superclass for ANT-based sensors. It handles tasks which
|
* Ant Sensor Manager.
|
||||||
* apply to the ANT framework as a whole, such as framework initialization and
|
|
||||||
* destruction. Subclasses are expected to handle the initialization and
|
|
||||||
* management of individual sensors.
|
|
||||||
*
|
*
|
||||||
* Implementation:
|
* @author Jimmy Shih
|
||||||
*
|
|
||||||
* The initialization process is somewhat complicated. This is due in part to
|
|
||||||
* the asynchronous nature of ANT Radio Service initialization, and in part due
|
|
||||||
* to an apparent bug in that service. The following is an overview of the
|
|
||||||
* initialization process.
|
|
||||||
*
|
|
||||||
* Initialization begins in {@link #setupChannel}, which is invoked by the
|
|
||||||
* {@link SensorManager} when track recording begins. {@link #setupChannel}
|
|
||||||
* asks the ANT Radio Service (via {@link AntInterface}) to start, using a
|
|
||||||
* AntInterface.ServiceListener to indicate when the service has
|
|
||||||
* connected. {@link #serviceConnected} claims and enables the Radio Service,
|
|
||||||
* and then resets it to a known state for our use. Completion of reset is
|
|
||||||
* indicated by receipt of a startup message (see {@link AntStartupMessage}).
|
|
||||||
* Once we've received that message, the ANT service is ready for use, and we
|
|
||||||
* can start sensor-specific initialization using
|
|
||||||
* {@link #setupAntSensorChannels}. The initialization of each sensor will
|
|
||||||
* usually result in a call to {@link #setupAntSensorChannel}.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
*/
|
*/
|
||||||
public abstract class AntSensorManager extends SensorManager {
|
public class AntSensorManager extends SensorManager {
|
||||||
|
|
||||||
// Pairing
|
|
||||||
protected static final short WILDCARD = 0;
|
|
||||||
|
|
||||||
private AntInterface antReceiver;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data from the sensors.
|
* Channel States
|
||||||
*/
|
*/
|
||||||
protected SensorDataSet sensorData;
|
public enum ChannelStates {
|
||||||
|
CLOSED, // Channel is closed
|
||||||
|
PENDING_OPEN, // User has requested opening the channel, waiting for a reset
|
||||||
|
SEARCHING, // Channel is opened, but has not received data
|
||||||
|
TRACKING_STATUS, // Channel is opened and has received status data recently
|
||||||
|
TRACKING_DATA, // Channel is opened and has received measurement data
|
||||||
|
// recently
|
||||||
|
OFFLINE // Channel is closed as the result of a search timeout
|
||||||
|
}
|
||||||
|
|
||||||
protected Context context;
|
private static final String TAG = AntSensorManager.class.getSimpleName();
|
||||||
|
|
||||||
private static final boolean DEBUGGING = false;
|
public static final short WILDCARD = 0;
|
||||||
|
|
||||||
/** Receives and logs all status ANT intents. */
|
private static final int CHANNELS = 2;
|
||||||
private final BroadcastReceiver statusReceiver = new BroadcastReceiver() {
|
private static final byte HRM_CHANNEL = (byte) 0;
|
||||||
@Override
|
private static final byte SDM_CHANNEL = (byte) 1;
|
||||||
public void onReceive(Context ctx, Intent intent) {
|
|
||||||
String antAction = intent.getAction();
|
|
||||||
Log.i(TAG, "enter status onReceive" + antAction);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Receives all data ANT intents. */
|
private static final byte HRM_DEVICE_TYPE = 0x78;
|
||||||
private final BroadcastReceiver dataReceiver = new BroadcastReceiver() {
|
private static final byte SDM_DEVICE_TYPE = 0x7C;
|
||||||
@Override
|
|
||||||
public void onReceive(Context ctx, Intent intent) {
|
|
||||||
String antAction = intent.getAction();
|
|
||||||
Log.i(TAG, "enter data onReceive" + antAction);
|
|
||||||
|
|
||||||
if (antAction != null && antAction.equals(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION)) {
|
private static final short HRM_PERIOD = 8070;
|
||||||
byte[] antMessage = intent.getByteArrayExtra(AntInterfaceIntent.ANT_MESSAGE);
|
private static final short SDM_PERIOD = 8134;
|
||||||
if (DEBUGGING) {
|
|
||||||
Log.d(TAG, "Received RX message " + messageToString(antMessage));
|
private static final byte DEFAULT_PROXIMITY_SEARCH_BIN = 7;
|
||||||
}
|
private static final short SCREEN_ON_BUFFER_THRESHOLD = AntDefine.MIN_BUFFER_THRESHOLD;
|
||||||
if (getAntReceiver() != null) {
|
private static final short SCREEN_OFF_BUFFER_THRESHOLD = AntDefine.MAX_BUFFER_THRESHOLD;
|
||||||
handleMessage(antMessage);
|
|
||||||
}
|
private static final String RADIO_ANT = "ant";
|
||||||
}
|
private static final byte ANT_NETWORK = (byte) 0x01;
|
||||||
}
|
private static final int ANT_FREQUENCY = 57; // 2457Mhz (Ant+ frequency)
|
||||||
};
|
private static final int ANT_TRANSMISSION_TYPE = 0; // 0 for wild card search
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final ChannelConfiguration channelConfig[];
|
||||||
|
private final IntentFilter statusIntentFilter;
|
||||||
|
private final AntInterface antInterface;
|
||||||
|
|
||||||
|
private boolean serviceConnected = false;
|
||||||
|
private boolean hasClaimedInterface = false;
|
||||||
|
private ChannelStates hrmState = ChannelStates.CLOSED;
|
||||||
|
private ChannelStates sdmState = ChannelStates.CLOSED;
|
||||||
|
private short hrmDeviceNumber = WILDCARD;
|
||||||
|
private short sdmDeviceNumber = WILDCARD;
|
||||||
|
|
||||||
|
private SensorDataSet sensorDataSet = null;
|
||||||
|
private int lastHeartRate = -1;
|
||||||
|
private int lastCadence = -1;
|
||||||
|
private long lastSensorDataSetTime = 0;
|
||||||
|
|
||||||
|
private boolean requestedReset = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ANT uses this listener to tell us when it has bound to the ANT Radio
|
* Constructor.
|
||||||
* Service. We can't start sending ANT commands until we've been notified
|
*
|
||||||
* (via this listener) that the Radio Service has connected.
|
* @param context the context
|
||||||
*/
|
*/
|
||||||
private AntInterface.ServiceListener antServiceListener = new AntInterface.ServiceListener() {
|
|
||||||
@Override
|
|
||||||
public void onServiceConnected() {
|
|
||||||
serviceConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onServiceDisconnected() {
|
|
||||||
Log.d(TAG, "ANT interface reports disconnection");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public AntSensorManager(Context context) {
|
public AntSensorManager(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
// We register for ANT intents early because we want to have a record of
|
channelConfig = new ChannelConfiguration[CHANNELS];
|
||||||
// the status intents in the log as we start up.
|
channelConfig[HRM_CHANNEL] = new ChannelConfiguration();
|
||||||
registerForAntIntents();
|
channelConfig[SDM_CHANNEL] = new ChannelConfiguration();
|
||||||
|
|
||||||
|
statusIntentFilter = new IntentFilter();
|
||||||
|
statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLED_ACTION);
|
||||||
|
statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLING_ACTION);
|
||||||
|
statusIntentFilter.addAction(AntInterfaceIntent.ANT_DISABLED_ACTION);
|
||||||
|
statusIntentFilter.addAction(AntInterfaceIntent.ANT_DISABLING_ACTION);
|
||||||
|
statusIntentFilter.addAction(AntInterfaceIntent.ANT_RESET_ACTION);
|
||||||
|
statusIntentFilter.addAction(AntInterfaceIntent.ANT_INTERFACE_CLAIMED_ACTION);
|
||||||
|
statusIntentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||||
|
|
||||||
|
antInterface = new AntInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUpChannel() {
|
||||||
|
if (AntInterface.hasAntSupport(context)) {
|
||||||
|
context.registerReceiver(statusReceiver, statusIntentFilter);
|
||||||
|
if (!antInterface.initService(context, serviceListener)) {
|
||||||
|
AntInterface.goToMarket(context);
|
||||||
|
} else {
|
||||||
|
setSensorState(Sensor.SensorState.CONNECTING);
|
||||||
|
serviceConnected = antInterface.isServiceConnected();
|
||||||
|
if (serviceConnected) {
|
||||||
|
try {
|
||||||
|
hasClaimedInterface = antInterface.hasClaimedInterface();
|
||||||
|
if (hasClaimedInterface) {
|
||||||
|
enableDataMessage(true);
|
||||||
|
}
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tearDownChannel() {
|
protected void tearDownChannel() {
|
||||||
Log.i(TAG, "destroying AntSensorManager");
|
try {
|
||||||
|
context.unregisterReceiver(statusReceiver);
|
||||||
cleanAntInterface();
|
} catch (IllegalArgumentException e) {
|
||||||
unregisterForAntIntents();
|
// Can safely ignore
|
||||||
|
}
|
||||||
|
enableDataMessage(false);
|
||||||
|
if (serviceConnected) {
|
||||||
|
try {
|
||||||
|
if (hasClaimedInterface) {
|
||||||
|
antInterface.releaseInterface();
|
||||||
|
}
|
||||||
|
antInterface.stopRequestForceClaimInterface();
|
||||||
|
} catch (AntServiceNotConnectedException e) {
|
||||||
|
// Can safely ignore
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
Log.w(TAG, "Exception in tearDonwChannel.", e);
|
||||||
|
}
|
||||||
|
antInterface.releaseService();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SensorDataSet getSensorDataSet() {
|
public SensorDataSet getSensorDataSet() {
|
||||||
return sensorData;
|
return sensorDataSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to claim the ant interface.
|
||||||
|
*/
|
||||||
|
public void tryClaimAnt() {
|
||||||
|
try {
|
||||||
|
antInterface.requestForceClaimInterface(context.getString(R.string.my_tracks_app_name));
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AntInterface.ServiceListener serviceListener = new AntInterface.ServiceListener() {
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected() {
|
||||||
|
serviceConnected = true;
|
||||||
|
try {
|
||||||
|
hasClaimedInterface = antInterface.hasClaimedInterface();
|
||||||
|
if (hasClaimedInterface) {
|
||||||
|
enableDataMessage(true);
|
||||||
|
} else {
|
||||||
|
// Need to claim the ant interface if it is available
|
||||||
|
hasClaimedInterface = antInterface.claimInterface();
|
||||||
|
}
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected() {
|
||||||
|
serviceConnected = false;
|
||||||
|
if (hasClaimedInterface) {
|
||||||
|
enableDataMessage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures ant radio.
|
||||||
|
*/
|
||||||
|
private void configureAntRadio() {
|
||||||
|
try {
|
||||||
|
if (serviceConnected && hasClaimedInterface && antInterface.isEnabled()) {
|
||||||
|
try {
|
||||||
|
antInterface.ANTConfigEventBuffering((short) 0xFFFF, SCREEN_ON_BUFFER_THRESHOLD,
|
||||||
|
(short) 0xFFFF, SCREEN_OFF_BUFFER_THRESHOLD);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
Log.e(TAG, "Cannot configure event buffering.", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "Cannot set event buffering now.");
|
||||||
|
}
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
Log.e(TAG, "Unable to check enabled state.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles ant error.
|
||||||
|
*/
|
||||||
|
private void handleAntError() {
|
||||||
|
clearAllChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a channel.
|
||||||
|
*
|
||||||
|
* @param channel the channel
|
||||||
|
*/
|
||||||
|
private void openChannel(byte channel) {
|
||||||
|
channelConfig[channel].deviceNumber = 0;
|
||||||
|
channelConfig[channel].deviceType = 0;
|
||||||
|
channelConfig[channel].TransmissionType = ANT_TRANSMISSION_TYPE;
|
||||||
|
channelConfig[channel].period = 0;
|
||||||
|
channelConfig[channel].freq = ANT_FREQUENCY;
|
||||||
|
channelConfig[channel].proxSearch = DEFAULT_PROXIMITY_SEARCH_BIN;
|
||||||
|
switch (channel) {
|
||||||
|
case HRM_CHANNEL:
|
||||||
|
hrmDeviceNumber = (short) PreferencesUtils.getInt(
|
||||||
|
context, R.string.ant_heart_rate_monitor_id_key, WILDCARD);
|
||||||
|
channelConfig[channel].deviceNumber = hrmDeviceNumber;
|
||||||
|
channelConfig[channel].deviceType = HRM_DEVICE_TYPE;
|
||||||
|
channelConfig[channel].period = HRM_PERIOD;
|
||||||
|
hrmState = ChannelStates.PENDING_OPEN;
|
||||||
|
break;
|
||||||
|
case SDM_CHANNEL:
|
||||||
|
sdmDeviceNumber = (short) PreferencesUtils.getInt(
|
||||||
|
context, R.string.ant_speed_distance_monitor_id_key, WILDCARD);
|
||||||
|
channelConfig[channel].deviceNumber = sdmDeviceNumber;
|
||||||
|
channelConfig[channel].deviceType = SDM_DEVICE_TYPE;
|
||||||
|
channelConfig[channel].period = SDM_PERIOD;
|
||||||
|
sdmState = ChannelStates.PENDING_OPEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setupAntChannel(ANT_NETWORK, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes a channel.
|
||||||
|
*
|
||||||
|
* @param channel the channel
|
||||||
|
*/
|
||||||
|
private void closeChannel(byte channel) {
|
||||||
|
channelConfig[channel].isInitializing = false;
|
||||||
|
channelConfig[channel].isDeinitializing = true;
|
||||||
|
switch (channel) {
|
||||||
|
case HRM_CHANNEL:
|
||||||
|
hrmState = ChannelStates.CLOSED;
|
||||||
|
break;
|
||||||
|
case SDM_CHANNEL:
|
||||||
|
sdmState = ChannelStates.CLOSED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setSensorState(SensorState.DISCONNECTED);
|
||||||
|
try {
|
||||||
|
antInterface.ANTCloseChannel(channel);
|
||||||
|
// Note, unassign channel after getting channel closed event
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
Log.w(TAG, "Unable to close channel: " + channel, e);
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all channels.
|
||||||
|
*/
|
||||||
|
private void clearAllChannels() {
|
||||||
|
hrmState = ChannelStates.CLOSED;
|
||||||
|
sdmState = ChannelStates.CLOSED;
|
||||||
|
setSensorState(SensorState.DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests reset.
|
||||||
|
*/
|
||||||
|
public void requestReset() {
|
||||||
|
try {
|
||||||
|
requestedReset = true;
|
||||||
|
antInterface.ANTResetSystem();
|
||||||
|
configureAntRadio();
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
Log.e(TAG, "Unable to reset ant.", e);
|
||||||
|
requestedReset = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return true;
|
if (antInterface == null || !antInterface.isServiceConnected()) {
|
||||||
}
|
return false;
|
||||||
|
|
||||||
public AntInterface getAntReceiver() {
|
|
||||||
return antReceiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the interface used by the {@link SensorManager} to tell this
|
|
||||||
* class when to start. It handles initialization of the ANT framework,
|
|
||||||
* eventually resulting in sensor-specific initialization via
|
|
||||||
* {@link #setupAntSensorChannels}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void setUpChannel() {
|
|
||||||
setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void setup() {
|
|
||||||
// We handle this unpleasantly because the UI should've checked for ANT
|
|
||||||
// support before it even instantiated this class.
|
|
||||||
if (!AntInterface.hasAntSupport(context)) {
|
|
||||||
throw new IllegalStateException("device does not have ANT support");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanAntInterface();
|
|
||||||
|
|
||||||
antReceiver = AntInterface.getInstance(context, antServiceListener);
|
|
||||||
|
|
||||||
if (antReceiver == null) {
|
|
||||||
Log.e(TAG, "Failed to get ANT Receiver");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setSensorState(Sensor.SensorState.CONNECTING);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleans up the ANT+ receiver interface, by releasing the interface
|
|
||||||
* and destroying it.
|
|
||||||
*/
|
|
||||||
private void cleanAntInterface() {
|
|
||||||
Log.i(TAG, "Destroying AntSensorManager");
|
|
||||||
|
|
||||||
if (antReceiver == null) {
|
|
||||||
Log.e(TAG, "no ANT receiver");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
antReceiver.releaseInterface();
|
return antInterface.isEnabled();
|
||||||
antReceiver.destroy();
|
|
||||||
antReceiver = null;
|
|
||||||
} catch (AntServiceNotConnectedException e) {
|
|
||||||
Log.i(TAG, "ANT service not connected", e);
|
|
||||||
} catch (AntInterfaceException e) {
|
} catch (AntInterfaceException e) {
|
||||||
Log.e(TAG, "failed to release ANT interface", e);
|
Log.w(TAG, "Unable to check enabled.", e);
|
||||||
} catch (RuntimeException e) {
|
return false;
|
||||||
Log.e(TAG, "run-time exception when cleaning the ANT interface", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private final BroadcastReceiver statusReceiver = new BroadcastReceiver() {
|
||||||
* This method is invoked via the ServiceListener when we're connected to
|
public void onReceive(Context c, Intent intent) {
|
||||||
* the ANT service. If we're just starting up, this is our first opportunity
|
String ANTAction = intent.getAction();
|
||||||
* to initiate any ANT commands.
|
if (ANTAction.equals(AntInterfaceIntent.ANT_DISABLED_ACTION)) {
|
||||||
*/
|
clearAllChannels();
|
||||||
private synchronized void serviceConnected() {
|
} else if (ANTAction.equals(AntInterfaceIntent.ANT_RESET_ACTION)) {
|
||||||
Log.d(TAG, "ANT service connected");
|
if (!requestedReset) {
|
||||||
|
// Someone else triggered an ant reset
|
||||||
|
clearAllChannels();
|
||||||
|
} else {
|
||||||
|
requestedReset = false;
|
||||||
|
configureAntRadio();
|
||||||
|
}
|
||||||
|
} else if (ANTAction.equals(AntInterfaceIntent.ANT_INTERFACE_CLAIMED_ACTION)) {
|
||||||
|
boolean wasClaimed = hasClaimedInterface;
|
||||||
|
|
||||||
if (antReceiver == null) {
|
// Could also read ANT_INTERFACE_CLAIMED_PID from intent and see if it
|
||||||
Log.e(TAG, "no ANT receiver");
|
// matches the current process PID.
|
||||||
return;
|
try {
|
||||||
|
hasClaimedInterface = antInterface.hasClaimedInterface();
|
||||||
|
if (hasClaimedInterface) {
|
||||||
|
enableDataMessage(true);
|
||||||
|
} else {
|
||||||
|
if (wasClaimed) {
|
||||||
|
// Claimed by another application
|
||||||
|
enableDataMessage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
} else if (ANTAction.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
|
||||||
|
if (isAirPlaneMode()) {
|
||||||
|
clearAllChannels();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final BroadcastReceiver dataReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context c, Intent intent) {
|
||||||
|
if (intent.getAction().equals(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION)) {
|
||||||
|
byte[] ANTRxMessage = intent.getByteArrayExtra(AntInterfaceIntent.ANT_MESSAGE);
|
||||||
|
switch (ANTRxMessage[AntMesg.MESG_ID_OFFSET]) {
|
||||||
|
case AntMesg.MESG_BROADCAST_DATA_ID:
|
||||||
|
case AntMesg.MESG_ACKNOWLEDGED_DATA_ID:
|
||||||
|
// Switch on channel number
|
||||||
|
switch (ANTRxMessage[AntMesg.MESG_DATA_OFFSET]) {
|
||||||
|
case HRM_CHANNEL:
|
||||||
|
decodeHrmMessage(ANTRxMessage);
|
||||||
|
break;
|
||||||
|
case SDM_CHANNEL:
|
||||||
|
decodeSdmMessage(ANTRxMessage);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_RESPONSE_EVENT_ID:
|
||||||
|
handleResponseEventMessage(ANTRxMessage);
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_CHANNEL_ID_ID:
|
||||||
|
short deviceNum = (short) ((ANTRxMessage[AntMesg.MESG_DATA_OFFSET + 1] & 0xFF
|
||||||
|
| ((ANTRxMessage[AntMesg.MESG_DATA_OFFSET + 2] & 0xFF) << 8)) & 0xFFFF);
|
||||||
|
// Switch on channel number
|
||||||
|
switch (ANTRxMessage[AntMesg.MESG_DATA_OFFSET]) {
|
||||||
|
case HRM_CHANNEL:
|
||||||
|
hrmDeviceNumber = deviceNum;
|
||||||
|
PreferencesUtils.setInt(
|
||||||
|
context, R.string.ant_heart_rate_monitor_id_key, hrmDeviceNumber);
|
||||||
|
Toast.makeText(context,
|
||||||
|
context.getString(R.string.settings_sensor_connected, deviceNum),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
setSensorState(SensorState.CONNECTED);
|
||||||
|
break;
|
||||||
|
case SDM_CHANNEL:
|
||||||
|
sdmDeviceNumber = deviceNum;
|
||||||
|
PreferencesUtils.setInt(
|
||||||
|
context, R.string.ant_speed_distance_monitor_id_key, sdmDeviceNumber);
|
||||||
|
Toast.makeText(context,
|
||||||
|
context.getString(R.string.settings_sensor_connected, deviceNum),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
setSensorState(SensorState.CONNECTED);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
/**
|
||||||
if (!antReceiver.claimInterface()) {
|
* Handles response event message.
|
||||||
Log.e(TAG, "failed to claim ANT interface");
|
*
|
||||||
return;
|
* @param message the message
|
||||||
|
*/
|
||||||
|
private void handleResponseEventMessage(byte[] message) {
|
||||||
|
// For a list of possible message codes see ANT Message Protocol and Usage
|
||||||
|
// section 9.5.6.1 available from thisisant.com
|
||||||
|
byte channelNumber = message[AntMesg.MESG_DATA_OFFSET];
|
||||||
|
if ((message[AntMesg.MESG_DATA_OFFSET + 1] == AntMesg.MESG_EVENT_ID)
|
||||||
|
&& (message[AntMesg.MESG_DATA_OFFSET + 2] == AntDefine.EVENT_RX_SEARCH_TIMEOUT)) {
|
||||||
|
// A channel timed out searching, unassign it
|
||||||
|
channelConfig[channelNumber].isInitializing = false;
|
||||||
|
channelConfig[channelNumber].isDeinitializing = false;
|
||||||
|
switch (channelNumber) {
|
||||||
|
case HRM_CHANNEL:
|
||||||
|
try {
|
||||||
|
hrmState = ChannelStates.OFFLINE;
|
||||||
|
antInterface.ANTUnassignChannel(HRM_CHANNEL);
|
||||||
|
setSensorState(SensorState.DISCONNECTED);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDM_CHANNEL:
|
||||||
|
try {
|
||||||
|
sdmState = ChannelStates.OFFLINE;
|
||||||
|
antInterface.ANTUnassignChannel(SDM_CHANNEL);
|
||||||
|
setSensorState(SensorState.DISCONNECTED);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!antReceiver.isEnabled()) {
|
if (channelConfig[channelNumber].isInitializing) {
|
||||||
// Make sure not to call AntInterface.enable() again, if it has been
|
if (message[AntMesg.MESG_DATA_OFFSET + 2] != 0) {
|
||||||
// already called before
|
// Error response
|
||||||
Log.i(TAG, "Powering on Radio");
|
Log.e(TAG, String.format("Error code(%#02x) on message ID(%#02x) on channel %d",
|
||||||
antReceiver.enable();
|
message[AntMesg.MESG_DATA_OFFSET + 2],
|
||||||
} else {
|
message[AntMesg.MESG_DATA_OFFSET + 1], channelNumber));
|
||||||
Log.i(TAG, "Radio already enabled");
|
} else {
|
||||||
|
// Switch on message id
|
||||||
|
switch (message[AntMesg.MESG_DATA_OFFSET + 1]) {
|
||||||
|
case AntMesg.MESG_ASSIGN_CHANNEL_ID:
|
||||||
|
try {
|
||||||
|
antInterface.ANTSetChannelId(channelNumber,
|
||||||
|
channelConfig[channelNumber].deviceNumber,
|
||||||
|
channelConfig[channelNumber].deviceType,
|
||||||
|
channelConfig[channelNumber].TransmissionType);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_CHANNEL_ID_ID:
|
||||||
|
try {
|
||||||
|
antInterface.ANTSetChannelPeriod(
|
||||||
|
channelNumber, channelConfig[channelNumber].period);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_CHANNEL_MESG_PERIOD_ID:
|
||||||
|
try {
|
||||||
|
antInterface.ANTSetChannelRFFreq(channelNumber, channelConfig[channelNumber].freq);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_CHANNEL_RADIO_FREQ_ID:
|
||||||
|
try {
|
||||||
|
// Disable high priority search
|
||||||
|
antInterface.ANTSetChannelSearchTimeout(channelNumber, (byte) 0);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_CHANNEL_SEARCH_TIMEOUT_ID:
|
||||||
|
try {
|
||||||
|
// Set search timeout to 30 seconds (low priority search)
|
||||||
|
antInterface.ANTSetLowPriorityChannelSearchTimeout(channelNumber, (byte) 12);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_SET_LP_SEARCH_TIMEOUT_ID:
|
||||||
|
if (channelConfig[channelNumber].deviceNumber == WILDCARD) {
|
||||||
|
try {
|
||||||
|
// Configure proximity search, if using wild card search
|
||||||
|
antInterface.ANTSetProximitySearch(
|
||||||
|
channelNumber, channelConfig[channelNumber].proxSearch);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
antInterface.ANTOpenChannel(channelNumber);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_PROX_SEARCH_CONFIG_ID:
|
||||||
|
try {
|
||||||
|
antInterface.ANTOpenChannel(channelNumber);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AntMesg.MESG_OPEN_CHANNEL_ID:
|
||||||
|
channelConfig[channelNumber].isInitializing = false;
|
||||||
|
switch (channelNumber) {
|
||||||
|
case HRM_CHANNEL:
|
||||||
|
hrmState = ChannelStates.SEARCHING;
|
||||||
|
break;
|
||||||
|
case SDM_CHANNEL:
|
||||||
|
sdmState = ChannelStates.SEARCHING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (channelConfig[channelNumber].isDeinitializing) {
|
||||||
|
if ((message[AntMesg.MESG_DATA_OFFSET + 1] == AntMesg.MESG_EVENT_ID)
|
||||||
|
&& (message[AntMesg.MESG_DATA_OFFSET + 2] == AntDefine.EVENT_CHANNEL_CLOSED)) {
|
||||||
|
try {
|
||||||
|
antInterface.ANTUnassignChannel(channelNumber);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
} else if ((message[AntMesg.MESG_DATA_OFFSET + 1] == AntMesg.MESG_UNASSIGN_CHANNEL_ID)
|
||||||
|
&& (message[AntMesg.MESG_DATA_OFFSET + 2] == AntDefine.RESPONSE_NO_ERROR)) {
|
||||||
|
channelConfig[channelNumber].isDeinitializing = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (AntInterfaceException e) {
|
|
||||||
Log.e(TAG, "failed to enable ANT", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
/**
|
||||||
// We expect this call to throw an exception due to a bug in the ANT
|
* Decodes HRM message.
|
||||||
// Radio Service. It won't actually fail, though, as we'll get the
|
*
|
||||||
// startup message (see {@link AntStartupMessage}) one normally expects
|
* @param message the message
|
||||||
// after a reset. Channel initialization can proceed once we receive
|
*/
|
||||||
// that message.
|
private void decodeHrmMessage(byte[] message) {
|
||||||
antReceiver.ANTResetSystem();
|
if (hrmState != ChannelStates.CLOSED) {
|
||||||
} catch (AntInterfaceException e) {
|
hrmState = ChannelStates.TRACKING_DATA;
|
||||||
Log.e(TAG, "failed to reset ANT (expected exception)", e);
|
}
|
||||||
|
|
||||||
|
if (hrmDeviceNumber == WILDCARD) {
|
||||||
|
try {
|
||||||
|
antInterface.ANTRequestMessage(HRM_CHANNEL, AntMesg.MESG_CHANNEL_ID_ID);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastHeartRate = message[10] & 0xFF;
|
||||||
|
setSenorDataSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes SDM message.
|
||||||
|
*
|
||||||
|
* @param message the message
|
||||||
|
*/
|
||||||
|
private void decodeSdmMessage(byte[] message) {
|
||||||
|
if (sdmState != ChannelStates.CLOSED) {
|
||||||
|
sdmState = ChannelStates.TRACKING_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdmDeviceNumber == WILDCARD) {
|
||||||
|
try {
|
||||||
|
antInterface.ANTRequestMessage(SDM_CHANNEL, AntMesg.MESG_CHANNEL_ID_ID);
|
||||||
|
} catch (AntInterfaceException e) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check page 2 data
|
||||||
|
if (message[3] == 0x02) {
|
||||||
|
lastCadence = (int) ((message[6] & 0xFF) + (((message[7] >>> 4) & 0x0F) / 16.0f));
|
||||||
|
setSenorDataSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets sensor data set.
|
||||||
|
*/
|
||||||
|
private void setSenorDataSet() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
// Data comes in at ~4Hz rate from the sensors, so after >300 msec fresh
|
||||||
|
// data is here from all the connected sensors
|
||||||
|
if (now < lastSensorDataSetTime + 300) { return; }
|
||||||
|
lastSensorDataSetTime = now;
|
||||||
|
|
||||||
|
SensorDataSet.Builder builder = Sensor.SensorDataSet.newBuilder();
|
||||||
|
if (lastHeartRate != -1) {
|
||||||
|
builder.setHeartRate(Sensor.SensorData.newBuilder()
|
||||||
|
.setValue(lastHeartRate).setState(Sensor.SensorState.SENDING));
|
||||||
|
}
|
||||||
|
if (lastCadence != -1) {
|
||||||
|
builder.setCadence(Sensor.SensorData.newBuilder()
|
||||||
|
.setValue(lastCadence).setState(Sensor.SensorState.SENDING));
|
||||||
|
}
|
||||||
|
sensorDataSet = builder.setCreationTime(now).build();
|
||||||
|
setSensorState(SensorState.SENDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a raw ANT message.
|
* Sets up ant channel.
|
||||||
* @param antMessage the ANT message, including the size and message ID bytes
|
|
||||||
* @deprecated Use {@link #handleMessage(byte, byte[])} instead.
|
|
||||||
*/
|
|
||||||
protected void handleMessage(byte[] antMessage) {
|
|
||||||
int len = antMessage[0];
|
|
||||||
if (len != antMessage.length - 2 || antMessage.length <= 2) {
|
|
||||||
Log.e(TAG, "Invalid message: " + messageToString(antMessage));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte messageId = antMessage[1];
|
|
||||||
// Arrays#copyOfRange doesn't exist??
|
|
||||||
byte[] messageData = new byte[antMessage.length - 2];
|
|
||||||
System.arraycopy(antMessage, 2, messageData, 0, antMessage.length - 2);
|
|
||||||
handleMessage(messageId, messageData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a raw ANT message.
|
|
||||||
* @param messageId the message ID. See the ANT Message Protocol and Usage
|
|
||||||
* guide, section 9.3.
|
|
||||||
* @param messageData the ANT message, without the size and message ID bytes.
|
|
||||||
* @return true if this method has taken responsibility for the passed
|
|
||||||
* message; false otherwise.
|
|
||||||
*/
|
|
||||||
protected boolean handleMessage(byte messageId, byte[] messageData) {
|
|
||||||
if (messageId == AntMesg.MESG_STARTUP_MESG_ID) {
|
|
||||||
Log.d(TAG, String.format(Locale.US,
|
|
||||||
"Received startup message (reason %02x); initializing channel",
|
|
||||||
new AntStartupMessage(messageData).getMessage()));
|
|
||||||
setupAntSensorChannels();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses define this method to perform sensor-specific initialization.
|
|
||||||
* When this method is called, the ANT framework has been enabled, and is
|
|
||||||
* ready for use.
|
|
||||||
*/
|
|
||||||
protected abstract void setupAntSensorChannels();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by subclasses to set up an ANT channel for a single sensor. A given
|
|
||||||
* subclass may invoke this method multiple times if the subclass is
|
|
||||||
* responsible for more than one sensor.
|
|
||||||
*
|
*
|
||||||
* @return true on success
|
* @param networkNumber the network number
|
||||||
|
* @param channel the channel
|
||||||
*/
|
*/
|
||||||
protected boolean setupAntSensorChannel(byte networkNumber, byte channelNumber,
|
private void setupAntChannel(byte networkNumber, byte channel) {
|
||||||
short deviceNumber, byte deviceType, byte txType, short channelPeriod,
|
|
||||||
byte radioFreq, byte proxSearch) {
|
|
||||||
|
|
||||||
if (antReceiver == null) {
|
|
||||||
Log.e(TAG, "no ANT receiver");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Assign as slave channel on selected network (0 = public, 1 = ANT+, 2 =
|
channelConfig[channel].isInitializing = true;
|
||||||
// ANTFS)
|
channelConfig[channel].isDeinitializing = false;
|
||||||
antReceiver.ANTAssignChannel(channelNumber, AntDefine.PARAMETER_RX_NOT_TX, networkNumber);
|
|
||||||
|
|
||||||
antReceiver.ANTSetChannelId(channelNumber, deviceNumber, deviceType, txType);
|
// Assign as slave channel on selected network
|
||||||
antReceiver.ANTSetChannelPeriod(channelNumber, channelPeriod);
|
antInterface.ANTAssignChannel(channel, AntDefine.PARAMETER_RX_NOT_TX, networkNumber);
|
||||||
antReceiver.ANTSetChannelRFFreq(channelNumber, radioFreq);
|
|
||||||
|
|
||||||
// Disable high priority search
|
// The rest of the channel configuration will occur after the response is
|
||||||
antReceiver.ANTSetChannelSearchTimeout(channelNumber, (byte) 0);
|
// received in handleResponseEventMessage
|
||||||
|
} catch (AntInterfaceException aie) {
|
||||||
|
handleAntError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set search timeout to 10 seconds (low priority search))
|
/**
|
||||||
antReceiver.ANTSetLowPriorityChannelSearchTimeout(channelNumber, (byte) 4);
|
* Enables data message.
|
||||||
|
*
|
||||||
if (deviceNumber == WILDCARD) {
|
* @param enabled true to enable
|
||||||
// Configure proximity search, if using wild card search
|
*/
|
||||||
antReceiver.ANTSetProximitySearch(channelNumber, proxSearch);
|
private void enableDataMessage(boolean enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
context.registerReceiver(
|
||||||
|
dataReceiver, new IntentFilter(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION));
|
||||||
|
openChannel(HRM_CHANNEL);
|
||||||
|
openChannel(SDM_CHANNEL);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
context.unregisterReceiver(dataReceiver);
|
||||||
|
closeChannel(HRM_CHANNEL);
|
||||||
|
closeChannel(SDM_CHANNEL);
|
||||||
|
setSensorState(SensorState.DISCONNECTED);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Can safely ignore
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
antReceiver.ANTOpenChannel(channelNumber);
|
/**
|
||||||
return true;
|
* Returns true if in airplane mode.
|
||||||
|
*/
|
||||||
} catch (AntInterfaceException e) {
|
private boolean isAirPlaneMode() {
|
||||||
Log.e(TAG, "failed to setup ANT channel", e);
|
if (!Settings.System.getString(
|
||||||
|
context.getContentResolver(), Settings.System.AIRPLANE_MODE_RADIOS)
|
||||||
|
.contains(RADIO_ANT)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
if (Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0)
|
||||||
|
== 0) {
|
||||||
private void registerForAntIntents() {
|
return false;
|
||||||
Log.i(TAG, "Registering for ant intents.");
|
|
||||||
// Register for ANT intent broadcasts.
|
|
||||||
IntentFilter statusIntentFilter = new IntentFilter();
|
|
||||||
statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLED_ACTION);
|
|
||||||
statusIntentFilter.addAction(AntInterfaceIntent.ANT_DISABLED_ACTION);
|
|
||||||
statusIntentFilter.addAction(AntInterfaceIntent.ANT_INTERFACE_CLAIMED_ACTION);
|
|
||||||
statusIntentFilter.addAction(AntInterfaceIntent.ANT_RESET_ACTION);
|
|
||||||
context.registerReceiver(statusReceiver, statusIntentFilter);
|
|
||||||
|
|
||||||
IntentFilter dataIntentFilter = new IntentFilter();
|
|
||||||
dataIntentFilter.addAction(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION);
|
|
||||||
context.registerReceiver(dataReceiver, dataIntentFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unregisterForAntIntents()
|
|
||||||
{
|
|
||||||
Log.i(TAG, "Unregistering ANT Intents.");
|
|
||||||
|
|
||||||
try {
|
|
||||||
context.unregisterReceiver(statusReceiver);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
Log.w(TAG, "Failed to unregister ANT status receiver", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
context.unregisterReceiver(dataReceiver);
|
Field field = Settings.System.class.getField("AIRPLANE_MODE_TOGGLEABLE_RADIOS");
|
||||||
} catch (IllegalArgumentException e) {
|
return !Settings.System.getString(context.getContentResolver(), (String) field.get(null))
|
||||||
Log.w(TAG, "Failed to unregister ANT data receiver", e);
|
.contains(RADIO_ANT);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// This is expected if the list does not yet exist, so just return true
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String messageToString(byte[] message) {
|
|
||||||
StringBuilder out = new StringBuilder();
|
|
||||||
for (byte b : message) {
|
|
||||||
out.append(String.format(Locale.US, "%s%02x", (out.length() == 0 ? "" : " "), b));
|
|
||||||
}
|
|
||||||
return out.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-242
@@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
|
||||||
|
|
||||||
import com.dsi.ant.AntDefine;
|
|
||||||
import com.dsi.ant.AntMesg;
|
|
||||||
import com.dsi.ant.exception.AntInterfaceException;
|
|
||||||
import com.google.android.apps.mytracks.content.Sensor;
|
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
|
||||||
import com.google.android.maps.mytracks.BuildConfig;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A sensor manager to the PC7 SRM ANT+ bridge.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
* @author Umran Abdulla
|
|
||||||
*/
|
|
||||||
public class AntSrmBridgeSensorManager extends AntSensorManager {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These constants are defined by the ANT+ spec.
|
|
||||||
*/
|
|
||||||
public static final byte CHANNEL_NUMBER = 0;
|
|
||||||
public static final byte NETWORK_NUMBER = 0;
|
|
||||||
public static final byte DEVICE_TYPE = 12;
|
|
||||||
public static final byte NETWORK_ID = 1;
|
|
||||||
public static final short CHANNEL_PERIOD = 8192;
|
|
||||||
public static final byte RF_FREQUENCY = 50;
|
|
||||||
|
|
||||||
private static final int INDEX_MESSAGE_TYPE = 1;
|
|
||||||
private static final int INDEX_MESSAGE_ID = 2;
|
|
||||||
private static final int INDEX_MESSAGE_POWER = 3;
|
|
||||||
private static final int INDEX_MESSAGE_SPEED = 5;
|
|
||||||
private static final int INDEX_MESSAGE_CADENCE = 7;
|
|
||||||
private static final int INDEX_MESSAGE_BPM = 8;
|
|
||||||
|
|
||||||
private static final int MSG_INITIAL = 5;
|
|
||||||
private static final int MSG_DATA = 6;
|
|
||||||
|
|
||||||
private short deviceNumber;
|
|
||||||
|
|
||||||
public AntSrmBridgeSensorManager(Context context) {
|
|
||||||
super(context);
|
|
||||||
|
|
||||||
Log.i(TAG, "new ANT SRM Bridge Sensor Manager created");
|
|
||||||
|
|
||||||
deviceNumber = WILDCARD;
|
|
||||||
|
|
||||||
// First read the the device id that we will be pairing with.
|
|
||||||
deviceNumber = (short) PreferencesUtils.getInt(
|
|
||||||
context, R.string.ant_srm_bridge_sensor_id_key, WILDCARD);
|
|
||||||
Log.i(TAG, "Will pair with device: " + deviceNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean handleMessage(byte messageId, byte[] messageData) {
|
|
||||||
if (super.handleMessage(messageId, messageData)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(TAG, "Received ANT msg: " + AntUtils.antMessageToString(messageId) + "(" + messageId + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
int channel = messageData[0] & AntDefine.CHANNEL_NUMBER_MASK;
|
|
||||||
switch (channel) {
|
|
||||||
case CHANNEL_NUMBER:
|
|
||||||
decodeChannelMsg(messageId, messageData);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.d(TAG, "Unhandled message: " + channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode an ant device message.
|
|
||||||
* @param messageData The byte array received from the device.
|
|
||||||
*/
|
|
||||||
private void decodeChannelMsg(int messageId, byte[] messageData) {
|
|
||||||
switch (messageId) {
|
|
||||||
case AntMesg.MESG_BROADCAST_DATA_ID:
|
|
||||||
handleBroadcastData(messageData);
|
|
||||||
break;
|
|
||||||
case AntMesg.MESG_RESPONSE_EVENT_ID:
|
|
||||||
handleMessageResponse(messageData);
|
|
||||||
break;
|
|
||||||
case AntMesg.MESG_CHANNEL_ID_ID:
|
|
||||||
handleChannelId(messageData);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unexpected message id: " + messageId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleBroadcastData(byte[] antMessage) {
|
|
||||||
if (deviceNumber == WILDCARD) {
|
|
||||||
try {
|
|
||||||
getAntReceiver().ANTRequestMessage(CHANNEL_NUMBER, AntMesg.MESG_CHANNEL_ID_ID);
|
|
||||||
} catch (AntInterfaceException e) {
|
|
||||||
Log.e(TAG, "ANT error handling broadcast data", e);
|
|
||||||
}
|
|
||||||
Log.d(TAG, "Requesting channel id id.");
|
|
||||||
}
|
|
||||||
|
|
||||||
setSensorState(Sensor.SensorState.CONNECTED);
|
|
||||||
|
|
||||||
int messageType = antMessage[INDEX_MESSAGE_TYPE] & 0xFF;
|
|
||||||
Log.d(TAG, "Received message-type=" + messageType);
|
|
||||||
|
|
||||||
switch (messageType) {
|
|
||||||
case MSG_INITIAL:
|
|
||||||
break;
|
|
||||||
case MSG_DATA:
|
|
||||||
parseDataMsg(antMessage);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseDataMsg(byte[] msg)
|
|
||||||
{
|
|
||||||
int messageId = msg[INDEX_MESSAGE_ID] & 0xFF;
|
|
||||||
Log.d(TAG, "Received message-id=" + messageId);
|
|
||||||
|
|
||||||
int powerVal = (((msg[INDEX_MESSAGE_POWER] & 0xFF) << 8) |
|
|
||||||
(msg[INDEX_MESSAGE_POWER+1] & 0xFF));
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
int speedVal = (((msg[INDEX_MESSAGE_SPEED] & 0xFF) << 8) |
|
|
||||||
(msg[INDEX_MESSAGE_SPEED+1] & 0xFF));
|
|
||||||
int cadenceVal = (msg[INDEX_MESSAGE_CADENCE] & 0xFF);
|
|
||||||
int bpmVal = (msg[INDEX_MESSAGE_BPM] & 0xFF);
|
|
||||||
long time = System.currentTimeMillis();
|
|
||||||
|
|
||||||
Sensor.SensorData.Builder power =
|
|
||||||
Sensor.SensorData.newBuilder()
|
|
||||||
.setValue(powerVal)
|
|
||||||
.setState(Sensor.SensorState.SENDING);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Although speed is available from the SRM Bridge, MyTracks doesn't use the value, and
|
|
||||||
* computes speed from the GPS location data.
|
|
||||||
*/
|
|
||||||
// Sensor.SensorData.Builder speed = Sensor.SensorData.newBuilder().setValue(speedVal).setState(
|
|
||||||
// Sensor.SensorState.SENDING);
|
|
||||||
|
|
||||||
Sensor.SensorData.Builder cadence =
|
|
||||||
Sensor.SensorData.newBuilder()
|
|
||||||
.setValue(cadenceVal)
|
|
||||||
.setState(Sensor.SensorState.SENDING);
|
|
||||||
|
|
||||||
Sensor.SensorData.Builder bpm =
|
|
||||||
Sensor.SensorData.newBuilder()
|
|
||||||
.setValue(bpmVal)
|
|
||||||
.setState(Sensor.SensorState.SENDING);
|
|
||||||
|
|
||||||
sensorData =
|
|
||||||
Sensor.SensorDataSet.newBuilder()
|
|
||||||
.setCreationTime(time)
|
|
||||||
.setPower(power)
|
|
||||||
.setCadence(cadence)
|
|
||||||
.setHeartRate(bpm)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleChannelId(byte[] rawMessage) {
|
|
||||||
AntChannelIdMessage message = new AntChannelIdMessage(rawMessage);
|
|
||||||
deviceNumber = message.getDeviceNumber();
|
|
||||||
Log.d(TAG, "Found device id: " + deviceNumber);
|
|
||||||
PreferencesUtils.setInt(context, R.string.ant_srm_bridge_sensor_id_key, deviceNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleMessageResponse(byte[] rawMessage) {
|
|
||||||
AntChannelResponseMessage message =
|
|
||||||
new AntChannelResponseMessage(rawMessage);
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(TAG, "Received ANT Response: " + AntUtils.antMessageToString(message.getMessageId()) +
|
|
||||||
"(" + message.getMessageId() + ")" +
|
|
||||||
", Code: " + AntUtils.antEventToStr(message.getMessageCode()) +
|
|
||||||
"(" + message.getMessageCode() + ")");
|
|
||||||
}
|
|
||||||
switch (message.getMessageId()) {
|
|
||||||
case AntMesg.MESG_EVENT_ID:
|
|
||||||
if (message.getMessageCode() == AntDefine.EVENT_RX_SEARCH_TIMEOUT) {
|
|
||||||
// Search timeout
|
|
||||||
Log.w(TAG, "Search timed out. Unassigning channel.");
|
|
||||||
try {
|
|
||||||
getAntReceiver().ANTUnassignChannel((byte) 0);
|
|
||||||
} catch (AntInterfaceException e) {
|
|
||||||
Log.e(TAG, "ANT error unassigning channel", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AntMesg.MESG_UNASSIGN_CHANNEL_ID:
|
|
||||||
setSensorState(Sensor.SensorState.DISCONNECTED);
|
|
||||||
Log.i(TAG, "Disconnected from the sensor: " + getSensorState());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected void setupAntSensorChannels() {
|
|
||||||
Log.i(TAG, "Setting up ANT sensor channels");
|
|
||||||
setupAntSensorChannel(
|
|
||||||
NETWORK_NUMBER,
|
|
||||||
CHANNEL_NUMBER,
|
|
||||||
deviceNumber,
|
|
||||||
DEVICE_TYPE,
|
|
||||||
(byte) 0x01,
|
|
||||||
CHANNEL_PERIOD,
|
|
||||||
RF_FREQUENCY,
|
|
||||||
(byte) 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getDeviceNumber() {
|
|
||||||
return deviceNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDeviceNumber(short deviceNumber) {
|
|
||||||
this.deviceNumber = deviceNumber;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class decodes and encapsulates an ANT Startup message.
|
|
||||||
* (ANT Message ID 0x6f, Protocol & Usage guide v4.2 section 9.5.3.1)
|
|
||||||
*
|
|
||||||
* @author Matthew Simmons
|
|
||||||
*/
|
|
||||||
public class AntStartupMessage extends AntMessage {
|
|
||||||
private byte message;
|
|
||||||
|
|
||||||
public AntStartupMessage(byte[] messageData) {
|
|
||||||
message = messageData[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the cause of the startup */
|
|
||||||
public byte getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import com.dsi.ant.AntDefine;
|
|
||||||
import com.dsi.ant.AntInterface;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods for ANT functionality.
|
|
||||||
*
|
|
||||||
* Prefer use of this class to importing DSI ANT classes into code outside of
|
|
||||||
* the sensors package.
|
|
||||||
*/
|
|
||||||
public class AntUtils {
|
|
||||||
private AntUtils() {}
|
|
||||||
|
|
||||||
/** Returns true if this device supports ANT sensors. */
|
|
||||||
public static boolean hasAntSupport(Context context) {
|
|
||||||
return AntInterface.hasAntSupport(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the names of in the messages with the given value
|
|
||||||
*/
|
|
||||||
public static String antMessageToString(byte msg) {
|
|
||||||
return findConstByteInClass(AntDefine.class, msg, "MESG_.*_ID");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the names of in the events with the given value
|
|
||||||
*/
|
|
||||||
public static String antEventToStr(byte event) {
|
|
||||||
return findConstByteInClass(AntDefine.class, event, ".*EVENT.*");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds a set of constant static byte field declarations in the class that have the given value
|
|
||||||
* and whose name match the given pattern
|
|
||||||
* @param cl class to search in
|
|
||||||
* @param value value of constant static byte field declarations to match
|
|
||||||
* @param regexPattern pattern to match against the name of the field
|
|
||||||
* @return a set of the names of fields, expressed as a string
|
|
||||||
*/
|
|
||||||
private static String findConstByteInClass(Class<?> cl, byte value, String regexPattern)
|
|
||||||
{
|
|
||||||
Field[] fields = cl.getDeclaredFields();
|
|
||||||
Set<String> fieldSet = new HashSet<String>();
|
|
||||||
for (Field f : fields) {
|
|
||||||
try {
|
|
||||||
if (f.getType() == Byte.TYPE &&
|
|
||||||
(f.getModifiers() & Modifier.STATIC) != 0 &&
|
|
||||||
f.getName().matches(regexPattern) &&
|
|
||||||
f.getByte(null) == value) {
|
|
||||||
fieldSet.add(f.getName());
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
// ignore
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fieldSet.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ant+ cadence sensor.
|
|
||||||
*
|
|
||||||
* @author Laszlo Molnar
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class CadenceSensor extends AntSensorBase {
|
|
||||||
/*
|
|
||||||
* These constants are defined by the ANT+ bike speed and cadence sensor spec.
|
|
||||||
*/
|
|
||||||
public static final byte CADENCE_DEVICE_TYPE = 122;
|
|
||||||
public static final short CADENCE_CHANNEL_PERIOD = 8102;
|
|
||||||
|
|
||||||
SensorEventCounter dataProcessor = new SensorEventCounter();
|
|
||||||
|
|
||||||
CadenceSensor(short devNum) {
|
|
||||||
super(devNum, CADENCE_DEVICE_TYPE, "cadence sensor", CADENCE_CHANNEL_PERIOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode an ANT+ cadence sensor message.
|
|
||||||
* @param antMessage The byte array received from the cadence sensor.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) {
|
|
||||||
int sensorTime = ((int) antMessage[5] & 0xFF) + ((int) antMessage[6] & 0xFF) * 256;
|
|
||||||
int crankRevs = ((int) antMessage[7] & 0xFF) + ((int) antMessage[8] & 0xFF) * 256;
|
|
||||||
c.setCadence(dataProcessor.getEventsPerMinute(crankRevs, sensorTime));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
-48
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ant+ combined cadence and speed sensor.
|
|
||||||
*
|
|
||||||
* @author Laszlo Molnar
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class CadenceSpeedSensor extends AntSensorBase {
|
|
||||||
/*
|
|
||||||
* These constants are defined by the ANT+ bike speed and cadence sensor spec.
|
|
||||||
*/
|
|
||||||
public static final byte CADENCE_SPEED_DEVICE_TYPE = 121;
|
|
||||||
public static final short CADENCE_SPEED_CHANNEL_PERIOD = 8086;
|
|
||||||
|
|
||||||
SensorEventCounter dataProcessor = new SensorEventCounter();
|
|
||||||
|
|
||||||
CadenceSpeedSensor(short devNum) {
|
|
||||||
super(devNum, CADENCE_SPEED_DEVICE_TYPE, "speed&cadence sensor", CADENCE_SPEED_CHANNEL_PERIOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode an ANT+ cadence&speed sensor message.
|
|
||||||
* @param antMessage The byte array received from the sensor.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) {
|
|
||||||
int sensorTime = ((int) antMessage[1] & 0xFF) + ((int) antMessage[2] & 0xFF) * 256;
|
|
||||||
int crankRevs = ((int) antMessage[3] & 0xFF) + ((int) antMessage[4] & 0xFF) * 256;
|
|
||||||
c.setCadence(dataProcessor.getEventsPerMinute(crankRevs, sensorTime));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
+13
-13
@@ -17,19 +17,19 @@
|
|||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
package com.google.android.apps.mytracks.services.sensors.ant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for collecting data from the sensors.
|
* Ant channel configuration.
|
||||||
* @author Laszlo Molnar
|
*
|
||||||
|
* @author Jimmy Shih
|
||||||
*/
|
*/
|
||||||
|
public class ChannelConfiguration {
|
||||||
|
|
||||||
public interface AntSensorDataCollector {
|
public short deviceNumber;
|
||||||
|
public byte deviceType;
|
||||||
/**
|
public byte TransmissionType;
|
||||||
* Sets the current cadence to the value specified.
|
public short period;
|
||||||
*/
|
public byte freq;
|
||||||
void setCadence(int value);
|
public byte proxSearch;
|
||||||
|
public boolean isInitializing = false;
|
||||||
/**
|
public boolean isDeinitializing = false;
|
||||||
* Sets the current heart rate to the value specified.
|
|
||||||
*/
|
|
||||||
void setHeartRate(int value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ant+ heart reate monitor sensor.
|
|
||||||
*
|
|
||||||
* @author Laszlo Molnar
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class HeartRateSensor extends AntSensorBase {
|
|
||||||
/*
|
|
||||||
* These constants are defined by the ANT+ heart rate monitor spec.
|
|
||||||
*/
|
|
||||||
public static final byte HEART_RATE_DEVICE_TYPE = 120;
|
|
||||||
public static final short HEART_RATE_CHANNEL_PERIOD = 8070;
|
|
||||||
|
|
||||||
HeartRateSensor(short devNum) {
|
|
||||||
super(devNum, HEART_RATE_DEVICE_TYPE, "heart rate monitor", HEART_RATE_CHANNEL_PERIOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode an ANT+ heart rate monitor message.
|
|
||||||
* @param antMessage The byte array received from the heart rate monitor.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) {
|
|
||||||
int bpm = (int) antMessage[8] & 0xFF;
|
|
||||||
Log.d(TAG, "now:" + System.currentTimeMillis() + " heart rate=" + bpm);
|
|
||||||
c.setHeartRate(bpm);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
-185
@@ -1,185 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes an ANT+ sensor data (counter) + timestamp pair,
|
|
||||||
* and returns the instantaneous value of the sensor
|
|
||||||
*
|
|
||||||
* @author Laszlo Molnar
|
|
||||||
*/
|
|
||||||
public class SensorEventCounter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HistoryElement stores a time stamped sensor counter
|
|
||||||
*/
|
|
||||||
private static class HistoryElement {
|
|
||||||
final long systemTime;
|
|
||||||
final int counter;
|
|
||||||
final int sensorTime;
|
|
||||||
|
|
||||||
HistoryElement(long systemTime, int counter, int sensorTime) {
|
|
||||||
this.systemTime = systemTime;
|
|
||||||
this.counter = counter;
|
|
||||||
this.sensorTime = sensorTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The latest counter value reported by the sensor
|
|
||||||
*/
|
|
||||||
private int counter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The calculated instantaneous sensor value to be displayed
|
|
||||||
*/
|
|
||||||
private int eventsPerMinute;
|
|
||||||
|
|
||||||
private static final int ONE_SECOND_MILLIS = 1000;
|
|
||||||
private static final int HISTORY_LENGTH_MILLIS = ONE_SECOND_MILLIS * 5;
|
|
||||||
private static final int HISTORY_MAX_LENGTH = 100;
|
|
||||||
private static final int ONE_MINUTE_MILLIS = ONE_SECOND_MILLIS * 60;
|
|
||||||
private static final int SENSOR_TIME_RESOLUTION = 1024; // in a second
|
|
||||||
private static final int SENSOR_TIME_ONE_MINUTE = SENSOR_TIME_RESOLUTION * 60;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* History of previous sensor data - oldest first
|
|
||||||
* only the latest HISTORY_LENGTH_MILLIS milliseconds of data is stored
|
|
||||||
*/
|
|
||||||
private LinkedList<HistoryElement> history;
|
|
||||||
|
|
||||||
SensorEventCounter() {
|
|
||||||
counter = -1;
|
|
||||||
eventsPerMinute = 0;
|
|
||||||
history = new LinkedList<HistoryElement>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the instantaneous sensor value to be displayed
|
|
||||||
*
|
|
||||||
* @param newCounter sensor reported counter value
|
|
||||||
* @param sensorTime sensor reported timestamp
|
|
||||||
* @return the calculated value
|
|
||||||
*/
|
|
||||||
public int getEventsPerMinute(int newCounter, int sensorTime) {
|
|
||||||
return getEventsPerMinute(newCounter, sensorTime, System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
// VisibleForTesting
|
|
||||||
protected int getEventsPerMinute(int newCounter, int sensorTime, long now) {
|
|
||||||
int counterChange = (newCounter - counter) & 0xFFFF;
|
|
||||||
|
|
||||||
Log.d(TAG, "now=" + now + " counter=" + newCounter + " sensortime=" + sensorTime);
|
|
||||||
|
|
||||||
if (counter < 0) {
|
|
||||||
// store the initial counter value reported by the sensor
|
|
||||||
// the timestamp is probably out of date, so the history is not updated
|
|
||||||
counter = newCounter;
|
|
||||||
return eventsPerMinute = 0;
|
|
||||||
}
|
|
||||||
counter = newCounter;
|
|
||||||
|
|
||||||
if (counterChange != 0) {
|
|
||||||
// if new data has arrived from the sensor ...
|
|
||||||
if (removeOldHistory(now)) {
|
|
||||||
// ... and the history is not empty, then use the latest entry
|
|
||||||
HistoryElement h = history.getLast();
|
|
||||||
int sensorTimeChange = (sensorTime - h.sensorTime) & 0xFFFF;
|
|
||||||
counterChange = (counter - h.counter) & 0xFFFF;
|
|
||||||
eventsPerMinute = counterChange * SENSOR_TIME_ONE_MINUTE / sensorTimeChange;
|
|
||||||
}
|
|
||||||
// the previous removeOldHistory() call makes the length of the history capped
|
|
||||||
history.addLast(new HistoryElement(now, counter, sensorTime));
|
|
||||||
} else if (!history.isEmpty()) {
|
|
||||||
// the sensor has resent an old (counter,timestamp) pair,
|
|
||||||
// but the history is not empty
|
|
||||||
|
|
||||||
HistoryElement h = history.getLast();
|
|
||||||
if (ONE_MINUTE_MILLIS < (now - h.systemTime) * eventsPerMinute) {
|
|
||||||
// Too much time has passed since the last counter change.
|
|
||||||
// This means that a smaller value than eventsPerMinute must be
|
|
||||||
// returned. This value is extrapolated from the history of
|
|
||||||
// HISTORY_LENGTH_MILLIS data.
|
|
||||||
// Note, that eventsPerMinute is NOT updated unless the history
|
|
||||||
// is empty or contains outdated entries. In that case it is zeroed.
|
|
||||||
return getValueFromHistory(now);
|
|
||||||
} // else the current eventsPerMinute is still valid, nothing to do here
|
|
||||||
} else {
|
|
||||||
// no new data from the sensor & the history is empty -> return 0
|
|
||||||
eventsPerMinute = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(TAG, "getEventsPerMinute returns:" + eventsPerMinute);
|
|
||||||
return eventsPerMinute;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the instantaneous sensor value to be displayed
|
|
||||||
* using the history when the sensor only resends the old data
|
|
||||||
*/
|
|
||||||
private int getValueFromHistory(long now) {
|
|
||||||
if (!removeOldHistory(now)) {
|
|
||||||
// there is nothing in the history, return 0
|
|
||||||
return eventsPerMinute = 0;
|
|
||||||
}
|
|
||||||
HistoryElement f = history.getFirst();
|
|
||||||
HistoryElement l = history.getLast();
|
|
||||||
int sensorTimeChange = (l.sensorTime - f.sensorTime) & 0xFFFF;
|
|
||||||
int counterChange = (counter - f.counter) & 0xFFFF;
|
|
||||||
|
|
||||||
// difference between now and systemTime of the oldest history entry
|
|
||||||
// for better precision sensor timestamps are considered between
|
|
||||||
// the first and the last history entry (could be overkill)
|
|
||||||
int systemTimeChange = (int) (now - l.systemTime
|
|
||||||
+ (sensorTimeChange * ONE_SECOND_MILLIS) / SENSOR_TIME_RESOLUTION);
|
|
||||||
|
|
||||||
// eventsPerMinute is not overwritten by this calculated value
|
|
||||||
// because it is still needed when a new sensor event arrives
|
|
||||||
int v = (counterChange * ONE_MINUTE_MILLIS) / systemTimeChange;
|
|
||||||
Log.d(TAG, "getEventsPerMinute returns (2):" + v);
|
|
||||||
|
|
||||||
// do not return larger number than eventsPerMinute, because the reason
|
|
||||||
// this function got called is that more time has passed after the last
|
|
||||||
// sensor counter value change than the current eventsPerMinute
|
|
||||||
// would be valid
|
|
||||||
return v < eventsPerMinute ? v : eventsPerMinute;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes old data from the history.
|
|
||||||
*
|
|
||||||
* @param now the current system time
|
|
||||||
* @return true if the remaining history is not empty
|
|
||||||
*/
|
|
||||||
private boolean removeOldHistory(long now) {
|
|
||||||
HistoryElement h;
|
|
||||||
while ((h = history.peek()) != null) {
|
|
||||||
// if the first element of the list is in our desired time range then return
|
|
||||||
if (now - h.systemTime <= HISTORY_LENGTH_MILLIS && history.size() < HISTORY_MAX_LENGTH) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// otherwise remove the too old element, and look at the next (newer) one
|
|
||||||
history.removeFirst();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+39
-14
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package com.google.android.apps.mytracks.settings;
|
package com.google.android.apps.mytracks.settings;
|
||||||
|
|
||||||
import com.google.android.apps.mytracks.services.sensors.ant.AntUtils;
|
import com.dsi.ant.AntInterface;
|
||||||
|
import com.google.android.apps.mytracks.services.sensors.ant.AntSensorManager;
|
||||||
import com.google.android.apps.mytracks.util.BluetoothDeviceUtils;
|
import com.google.android.apps.mytracks.util.BluetoothDeviceUtils;
|
||||||
|
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
@@ -47,13 +49,14 @@ public class SensorSettingsActivity extends AbstractSettingsActivity {
|
|||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
addPreferencesFromResource(R.xml.sensor_settings);
|
addPreferencesFromResource(R.xml.sensor_settings);
|
||||||
|
|
||||||
|
boolean hasAntSupport = AntInterface.hasAntSupport(this);
|
||||||
ListPreference sensorTypeListPreference = (ListPreference) findPreference(
|
ListPreference sensorTypeListPreference = (ListPreference) findPreference(
|
||||||
getString(R.string.sensor_type_key));
|
getString(R.string.sensor_type_key));
|
||||||
List<String> sensorTypeEntries = Arrays.asList(getResources().getStringArray(
|
List<String> sensorTypeEntries = Arrays.asList(getResources().getStringArray(
|
||||||
AntUtils.hasAntSupport(this) ? R.array.sensor_type_all_options
|
hasAntSupport ? R.array.sensor_type_all_options
|
||||||
: R.array.sensor_type_bluetooth_options));
|
: R.array.sensor_type_bluetooth_options));
|
||||||
List<String> sensorTypeEntryValues = Arrays.asList(getResources().getStringArray(
|
List<String> sensorTypeEntryValues = Arrays.asList(getResources().getStringArray(
|
||||||
AntUtils.hasAntSupport(this) ? R.array.sensor_type_all_values
|
hasAntSupport ? R.array.sensor_type_all_values
|
||||||
: R.array.sensor_type_bluetooth_values));
|
: R.array.sensor_type_bluetooth_values));
|
||||||
sensorTypeListPreference.setEntries(sensorTypeEntries.toArray(
|
sensorTypeListPreference.setEntries(sensorTypeEntries.toArray(
|
||||||
new CharSequence[sensorTypeEntries.size()]));
|
new CharSequence[sensorTypeEntries.size()]));
|
||||||
@@ -78,7 +81,7 @@ public class SensorSettingsActivity extends AbstractSettingsActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!AntUtils.hasAntSupport(this)) {
|
if (!hasAntSupport) {
|
||||||
PreferenceScreen rootPreferenceScreen = (PreferenceScreen) findPreference(
|
PreferenceScreen rootPreferenceScreen = (PreferenceScreen) findPreference(
|
||||||
getString(R.string.settings_sensor_root_key));
|
getString(R.string.settings_sensor_root_key));
|
||||||
rootPreferenceScreen.removePreference(
|
rootPreferenceScreen.removePreference(
|
||||||
@@ -97,17 +100,39 @@ public class SensorSettingsActivity extends AbstractSettingsActivity {
|
|||||||
|| getString(R.string.sensor_type_value_zephyr).equals(sensorType);
|
|| getString(R.string.sensor_type_value_zephyr).equals(sensorType);
|
||||||
findPreference(getString(R.string.settings_sensor_bluetooth_key)).setEnabled(isBluetooth);
|
findPreference(getString(R.string.settings_sensor_bluetooth_key)).setEnabled(isBluetooth);
|
||||||
|
|
||||||
Preference antHeartRateSensorId = findPreference(
|
boolean isAnt = getString(R.string.sensor_type_value_ant).equals(sensorType);
|
||||||
getString(R.string.ant_heart_rate_sensor_id_key));
|
updateAntSensor(R.string.settings_sensor_ant_reset_heart_rate_monitor_key,
|
||||||
if (antHeartRateSensorId != null) {
|
R.string.ant_heart_rate_monitor_id_key, isAnt);
|
||||||
antHeartRateSensorId.setEnabled(getString(R.string.sensor_type_value_ant).equals(sensorType));
|
updateAntSensor(R.string.settings_sensor_ant_reset_speed_distance_monitor_key,
|
||||||
}
|
R.string.ant_speed_distance_monitor_id_key, isAnt);
|
||||||
|
}
|
||||||
|
|
||||||
Preference antSrmBridgetSensorId = findPreference(
|
/**
|
||||||
getString(R.string.ant_srm_bridge_sensor_id_key));
|
* Updates an ant sensor.
|
||||||
if (antSrmBridgetSensorId != null) {
|
*
|
||||||
antSrmBridgetSensorId.setEnabled(
|
* @param preferenceKey the preference key
|
||||||
getString(R.string.sensor_type_value_srm_ant_bridge).equals(sensorType));
|
* @param valueKey the value key
|
||||||
|
* @param enabled true if enabled
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private void updateAntSensor(int preferenceKey, final int valueKey, boolean enabled) {
|
||||||
|
Preference preference = findPreference(getString(preferenceKey));
|
||||||
|
if (preference != null) {
|
||||||
|
preference.setEnabled(enabled);
|
||||||
|
int deviceId = PreferencesUtils.getInt(this, valueKey, AntSensorManager.WILDCARD);
|
||||||
|
if (deviceId == AntSensorManager.WILDCARD) {
|
||||||
|
preference.setSummary(R.string.settings_sensor_not_connected);
|
||||||
|
} else {
|
||||||
|
preference.setSummary(getString(R.string.settings_sensor_ant_paired, deviceId));
|
||||||
|
}
|
||||||
|
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference pref) {
|
||||||
|
PreferencesUtils.setInt(SensorSettingsActivity.this, valueKey, AntSensorManager.WILDCARD);
|
||||||
|
pref.setSummary(R.string.settings_sensor_not_connected);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks;
|
|
||||||
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for the AntPreference.
|
|
||||||
*
|
|
||||||
* @author Youtao Liu
|
|
||||||
*/
|
|
||||||
public class AntPreferenceTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
public void testNotPaired() {
|
|
||||||
|
|
||||||
AntPreference antPreference = new AntPreference(getContext()) {
|
|
||||||
@Override
|
|
||||||
protected int getPersistedInt(int defaultReturnValue) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
assertEquals(getContext().getString(R.string.settings_sensor_ant_not_paired),
|
|
||||||
antPreference.getSummary());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testPaired() {
|
|
||||||
int persistInt = 1;
|
|
||||||
AntPreference antPreference = new AntPreference(getContext()) {
|
|
||||||
@Override
|
|
||||||
protected int getPersistedInt(int defaultReturnValue) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
assertEquals(
|
|
||||||
getContext().getString(R.string.settings_sensor_ant_paired, persistInt),
|
|
||||||
antPreference.getSummary());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
public class AntChannelIdMessageTest extends AndroidTestCase {
|
|
||||||
public void testParse() {
|
|
||||||
byte[] rawMessage = {
|
|
||||||
0, // channel number
|
|
||||||
0x34, 0x12, // device number
|
|
||||||
(byte) 0xaa, // device type id
|
|
||||||
(byte) 0xbb, // transmission type
|
|
||||||
};
|
|
||||||
|
|
||||||
AntChannelIdMessage message = new AntChannelIdMessage(rawMessage);
|
|
||||||
assertEquals(0, message.getChannelNumber());
|
|
||||||
assertEquals(0x1234, message.getDeviceNumber());
|
|
||||||
assertEquals((byte) 0xaa, message.getDeviceTypeId());
|
|
||||||
assertEquals((byte) 0xbb, message.getTransmissionType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import com.dsi.ant.AntDefine;
|
|
||||||
import com.dsi.ant.AntMesg;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
public class AntChannelResponseMessageTest extends AndroidTestCase {
|
|
||||||
public void testParse() {
|
|
||||||
byte[] rawMessage = {
|
|
||||||
0,
|
|
||||||
AntMesg.MESG_EVENT_ID,
|
|
||||||
AntDefine.EVENT_RX_SEARCH_TIMEOUT
|
|
||||||
};
|
|
||||||
AntChannelResponseMessage message = new AntChannelResponseMessage(rawMessage);
|
|
||||||
|
|
||||||
assertEquals(0, message.getChannelNumber());
|
|
||||||
assertEquals(AntMesg.MESG_EVENT_ID, message.getMessageId());
|
|
||||||
assertEquals(AntDefine.EVENT_RX_SEARCH_TIMEOUT, message.getMessageCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-116
@@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import com.dsi.ant.AntMesg;
|
|
||||||
import com.google.android.apps.mytracks.Constants;
|
|
||||||
import com.google.android.apps.mytracks.content.Sensor;
|
|
||||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
|
||||||
import com.google.android.maps.mytracks.R;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
|
||||||
|
|
||||||
public class AntDirectSensorManagerTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
private AntSensorBase heartRateSensor;
|
|
||||||
private static final byte HEART_RATE_CHANNEL = 0;
|
|
||||||
|
|
||||||
private class MockAntDirectSensorManager extends AntDirectSensorManager {
|
|
||||||
public MockAntDirectSensorManager(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected boolean setupChannel(AntSensorBase sensor, byte channel) {
|
|
||||||
if (channel == HEART_RATE_CHANNEL) {
|
|
||||||
heartRateSensor = sensor;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private AntDirectSensorManager manager;
|
|
||||||
|
|
||||||
public void setUp() {
|
|
||||||
SharedPreferences sharedPreferences = getContext().getSharedPreferences(
|
|
||||||
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
|
||||||
// Let's use default values.
|
|
||||||
sharedPreferences.edit().clear().apply();
|
|
||||||
manager = new MockAntDirectSensorManager(getContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testBroadcastData() {
|
|
||||||
manager.setupAntSensorChannels();
|
|
||||||
assertNotNull(heartRateSensor);
|
|
||||||
|
|
||||||
heartRateSensor.setDeviceNumber((short) 42);
|
|
||||||
byte[] buff = new byte[9];
|
|
||||||
buff[0] = HEART_RATE_CHANNEL;
|
|
||||||
buff[8] = (byte) 220;
|
|
||||||
manager.handleMessage(AntMesg.MESG_BROADCAST_DATA_ID, buff);
|
|
||||||
|
|
||||||
Sensor.SensorDataSet sds = manager.getSensorDataSet();
|
|
||||||
assertNotNull(sds);
|
|
||||||
assertTrue(sds.hasHeartRate());
|
|
||||||
assertEquals(Sensor.SensorState.SENDING,
|
|
||||||
sds.getHeartRate().getState());
|
|
||||||
assertEquals(220, sds.getHeartRate().getValue());
|
|
||||||
|
|
||||||
assertFalse(sds.hasCadence());
|
|
||||||
assertFalse(sds.hasPower());
|
|
||||||
assertEquals(Sensor.SensorState.CONNECTED, manager.getSensorState());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testChannelId() {
|
|
||||||
manager.setupAntSensorChannels();
|
|
||||||
assertNotNull(heartRateSensor);
|
|
||||||
|
|
||||||
byte[] buff = new byte[9];
|
|
||||||
buff[1] = 43;
|
|
||||||
manager.handleMessage(AntMesg.MESG_CHANNEL_ID_ID, buff);
|
|
||||||
|
|
||||||
assertEquals(43, heartRateSensor.getDeviceNumber());
|
|
||||||
assertEquals(43, PreferencesUtils.getInt(
|
|
||||||
getContext(), R.string.ant_heart_rate_sensor_id_key, AntSensorManager.WILDCARD));
|
|
||||||
assertNull(manager.getSensorDataSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testResponseEvent() {
|
|
||||||
manager.setupAntSensorChannels();
|
|
||||||
assertNotNull(heartRateSensor);
|
|
||||||
manager.setHeartRate(210);
|
|
||||||
heartRateSensor.setDeviceNumber((short) 42);
|
|
||||||
|
|
||||||
assertEquals(Sensor.SensorState.CONNECTED, manager.getSensorState());
|
|
||||||
byte[] buff = new byte[3];
|
|
||||||
buff[0] = HEART_RATE_CHANNEL;
|
|
||||||
buff[1] = AntMesg.MESG_UNASSIGN_CHANNEL_ID;
|
|
||||||
buff[2] = 0; // code
|
|
||||||
manager.handleMessage(AntMesg.MESG_RESPONSE_EVENT_ID, buff);
|
|
||||||
assertEquals(Sensor.SensorState.CONNECTED, manager.getSensorState());
|
|
||||||
|
|
||||||
heartRateSensor.setDeviceNumber((short) 0);
|
|
||||||
manager.handleMessage(AntMesg.MESG_RESPONSE_EVENT_ID, buff);
|
|
||||||
assertEquals(Sensor.SensorState.DISCONNECTED, manager.getSensorState());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Test timeout too.
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
public class AntMessageTest extends AndroidTestCase {
|
|
||||||
private static class TestAntMessage extends AntMessage {
|
|
||||||
public static short decodeShort(byte low, byte high) {
|
|
||||||
return AntMessage.decodeShort(low, high);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDecode() {
|
|
||||||
assertEquals(0x1234, TestAntMessage.decodeShort((byte) 0x34, (byte) 0x12));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-94
@@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
import android.test.MoreAsserts;
|
|
||||||
|
|
||||||
public class AntSensorManagerTest extends AndroidTestCase {
|
|
||||||
private class TestAntSensorManager extends AntSensorManager {
|
|
||||||
|
|
||||||
public TestAntSensorManager(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte messageId;
|
|
||||||
public byte[] messageData;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setupAntSensorChannels() {}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
public void handleMessage(byte[] rawMessage) {
|
|
||||||
super.handleMessage(rawMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("hiding")
|
|
||||||
@Override
|
|
||||||
public boolean handleMessage(byte messageId, byte[] messageData) {
|
|
||||||
this.messageId = messageId;
|
|
||||||
this.messageData = messageData;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TestAntSensorManager sensorManager;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
sensorManager = new TestAntSensorManager(getContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSimple() {
|
|
||||||
byte[] rawMessage = {
|
|
||||||
0x03, // length
|
|
||||||
0x12, // message id
|
|
||||||
0x11, 0x22, 0x33, // body
|
|
||||||
};
|
|
||||||
|
|
||||||
byte[] expectedBody = { 0x11, 0x22, 0x33 };
|
|
||||||
|
|
||||||
sensorManager.handleMessage(rawMessage);
|
|
||||||
assertEquals((byte) 0x12, sensorManager.messageId);
|
|
||||||
MoreAsserts.assertEquals(expectedBody, sensorManager.messageData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testTooShort() {
|
|
||||||
byte[] rawMessage = {
|
|
||||||
0x53, // length
|
|
||||||
0x12 // message id
|
|
||||||
};
|
|
||||||
|
|
||||||
sensorManager.handleMessage(rawMessage);
|
|
||||||
assertEquals(0, sensorManager.messageId);
|
|
||||||
assertNull(sensorManager.messageData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testLengthWrong() {
|
|
||||||
byte[] rawMessage = {
|
|
||||||
0x53, // length
|
|
||||||
0x12, // message id
|
|
||||||
0x34, // body
|
|
||||||
};
|
|
||||||
|
|
||||||
sensorManager.handleMessage(rawMessage);
|
|
||||||
assertEquals(0, sensorManager.messageId);
|
|
||||||
assertNull(sensorManager.messageData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-29
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
public class AntStartupMessageTest extends AndroidTestCase {
|
|
||||||
public void testParse() {
|
|
||||||
byte[] rawMessage = {
|
|
||||||
0x12,
|
|
||||||
};
|
|
||||||
|
|
||||||
AntStartupMessage message = new AntStartupMessage(rawMessage);
|
|
||||||
assertEquals(0x12, message.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package com.google.android.apps.mytracks.services.sensors.ant;
|
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Laszlo Molnar
|
|
||||||
*/
|
|
||||||
public class SensorEventCounterTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
public void testGetEventsPerMinute() {
|
|
||||||
SensorEventCounter sec = new SensorEventCounter();
|
|
||||||
assertEquals(0, sec.getEventsPerMinute(0, 0, 0));
|
|
||||||
assertEquals(0, sec.getEventsPerMinute(1, 1024, 1000));
|
|
||||||
assertEquals(60, sec.getEventsPerMinute(2, 1024 * 2, 2000));
|
|
||||||
assertEquals(60, sec.getEventsPerMinute(2, 1024 * 2, 2500));
|
|
||||||
assertTrue(60 > sec.getEventsPerMinute(2, 1024 * 2, 4000));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user