├── DebugApp ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ └── styles.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ ├── values-v21 │ │ │ └── styles.xml │ │ └── layout │ │ │ └── activity_debug.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── cl │ │ └── felipebarriga │ │ └── android │ │ └── sony │ │ └── smartband │ │ └── api │ │ └── demo │ │ └── DebugActivity.java ├── proguard-rules.pro ├── build.gradle └── DebugApp.iml ├── .idea ├── .name ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── vcs.xml ├── runConfigurations.xml ├── modules.xml ├── compiler.xml ├── gradle.xml └── misc.xml ├── RawBandLogger ├── .gitignore ├── src │ └── main │ │ ├── ic_log-web.png │ │ ├── ic_lauasd-web.png │ │ ├── ic_record-web.png │ │ ├── ic_steps-web.png │ │ ├── ic_battery-web.png │ │ ├── ic_bluetooth-web.png │ │ ├── ic_stopwatch-web.png │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ ├── ic_log.png │ │ │ ├── ic_record.png │ │ │ ├── ic_steps.png │ │ │ ├── ic_battery.png │ │ │ ├── ic_bluetooth.png │ │ │ ├── ic_launcher.png │ │ │ └── ic_stopwatch.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_log.png │ │ │ ├── ic_record.png │ │ │ ├── ic_steps.png │ │ │ ├── ic_battery.png │ │ │ ├── ic_bluetooth.png │ │ │ ├── ic_launcher.png │ │ │ └── ic_stopwatch.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_log.png │ │ │ ├── ic_steps.png │ │ │ ├── ic_battery.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_record.png │ │ │ ├── ic_bluetooth.png │ │ │ └── ic_stopwatch.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_log.png │ │ │ ├── ic_battery.png │ │ │ ├── ic_record.png │ │ │ ├── ic_steps.png │ │ │ ├── ic_bluetooth.png │ │ │ ├── ic_launcher.png │ │ │ └── ic_stopwatch.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_log.png │ │ │ ├── ic_record.png │ │ │ ├── ic_steps.png │ │ │ ├── ic_battery.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_bluetooth.png │ │ │ └── ic_stopwatch.png │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ └── styles.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ ├── values-v21 │ │ │ └── styles.xml │ │ └── layout │ │ │ └── activity_rawband.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── cl │ │ └── felipebarriga │ │ └── android │ │ └── sony │ │ └── smartband │ │ └── api │ │ └── rawband │ │ └── RawBandActivity.java ├── proguard-rules.pro ├── build.gradle └── RawBandLogger.iml ├── SonySmartBandOpenAPI ├── .gitignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── cl │ │ └── felipebarriga │ │ └── android │ │ └── sony │ │ └── smartband │ │ └── api │ │ └── bluetooth │ │ ├── CharacteristicInfo.java │ │ ├── profiles │ │ ├── BaseProfile.java │ │ ├── GenericAccessProfile.java │ │ ├── BleConstants.java │ │ ├── BatteryProfile.java │ │ ├── DeviceInformationProfile.java │ │ ├── AADeviceServiceProfile.java │ │ └── AHServiceProfile.java │ │ ├── DescriptorInfo.java │ │ ├── BtBridgeListener.java │ │ ├── BtBandListener.java │ │ ├── Profiles.java │ │ ├── BandMode.java │ │ ├── BtBandEvent.java │ │ ├── BtAction.java │ │ ├── BtBridge.java │ │ └── BtBand.java ├── build.gradle ├── proguard-rules.pro └── SonySmartBandOpenAPI.iml ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── README.md ├── .gitignore ├── gradle.properties ├── sony-smartband-open-api.iml ├── LICENSE ├── gradlew.bat └── gradlew /DebugApp/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | sony-smartband-open-api -------------------------------------------------------------------------------- /RawBandLogger/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':SonySmartBandOpenAPI' 2 | include ':DebugApp' 3 | include ':RawBandLogger' 4 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /RawBandLogger/src/main/ic_log-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/ic_log-web.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sony-smartband-open-api 2 | Open API of Sony SmartBand SWR-10 3 | 4 | # build instructions 5 | 6 | ``` 7 | ./gradlew build 8 | ``` 9 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/ic_lauasd-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/ic_lauasd-web.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/ic_record-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/ic_record-web.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/ic_steps-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/ic_steps-web.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/ic_battery-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/ic_battery-web.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/ic_bluetooth-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/ic_bluetooth-web.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/ic_stopwatch-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/ic_stopwatch-web.png -------------------------------------------------------------------------------- /DebugApp/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/DebugApp/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /DebugApp/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/DebugApp/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /DebugApp/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/DebugApp/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-hdpi/ic_log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-hdpi/ic_log.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-mdpi/ic_log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-mdpi/ic_log.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xhdpi/ic_log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xhdpi/ic_log.png -------------------------------------------------------------------------------- /DebugApp/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/DebugApp/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /DebugApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/DebugApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-hdpi/ic_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-hdpi/ic_record.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-hdpi/ic_steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-hdpi/ic_steps.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-mdpi/ic_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-mdpi/ic_record.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-mdpi/ic_steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-mdpi/ic_steps.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xhdpi/ic_steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xhdpi/ic_steps.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxhdpi/ic_log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxhdpi/ic_log.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_log.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-hdpi/ic_battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-hdpi/ic_battery.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-hdpi/ic_bluetooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-hdpi/ic_bluetooth.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-hdpi/ic_stopwatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-hdpi/ic_stopwatch.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-mdpi/ic_battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-mdpi/ic_battery.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-mdpi/ic_bluetooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-mdpi/ic_bluetooth.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-mdpi/ic_stopwatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-mdpi/ic_stopwatch.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xhdpi/ic_battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xhdpi/ic_battery.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xhdpi/ic_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xhdpi/ic_record.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxhdpi/ic_battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxhdpi/ic_battery.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxhdpi/ic_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxhdpi/ic_record.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxhdpi/ic_steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxhdpi/ic_steps.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_record.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_steps.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xhdpi/ic_bluetooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xhdpi/ic_bluetooth.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xhdpi/ic_stopwatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xhdpi/ic_stopwatch.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxhdpi/ic_bluetooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxhdpi/ic_bluetooth.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxhdpi/ic_stopwatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxhdpi/ic_stopwatch.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_battery.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_bluetooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_bluetooth.png -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_stopwatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarriga/sony-smartband-open-api/HEAD/RawBandLogger/src/main/res/mipmap-xxxhdpi/ic_stopwatch.png -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DebugApp/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Sony SmartBand API Demo 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Sony SmartBand API Demo 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DebugApp/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Oct 21 11:34:03 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip 7 | -------------------------------------------------------------------------------- /DebugApp/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/workspace.xml 2 | /.idea/libraries 3 | /.idea/tasks.xml 4 | 5 | /local.properties 6 | .DS_Store 7 | /build 8 | .gradle 9 | 10 | # Ignore Gradle GUI config 11 | gradle-app.setting 12 | 13 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 14 | !gradle-wrapper.jar 15 | 16 | # Cache of project 17 | .gradletasknamecache 18 | -------------------------------------------------------------------------------- /DebugApp/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /DebugApp/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | buildscript { 3 | repositories { 4 | // maven { url 'http://repo1.maven.org/maven2' } 5 | } 6 | dependencies { 7 | // classpath 'com.android.tools.build:gradle:0.4' 8 | } 9 | } 10 | */ 11 | 12 | apply plugin: 'android-library' 13 | 14 | dependencies { 15 | compile files('libs/android-support-v4.jar') 16 | } 17 | 18 | android { 19 | compileSdkVersion 23 20 | buildToolsVersion "23.0.2" 21 | 22 | defaultConfig { 23 | minSdkVersion 18 24 | targetSdkVersion 23 25 | } 26 | 27 | lintOptions { 28 | abortOnError false 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/CharacteristicInfo.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | /** 4 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 5 | */ 6 | public class CharacteristicInfo { 7 | final String mServiceName; 8 | final String mCharacteristicName; 9 | 10 | CharacteristicInfo( String serviceName, String characteristicName ) { 11 | mServiceName = serviceName; 12 | mCharacteristicName = characteristicName; 13 | } 14 | 15 | public String toString() { 16 | return "service=" + mServiceName + " name=" + mCharacteristicName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DebugApp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/fbarriga/software/AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /RawBandLogger/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/fbarriga/software/AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /DebugApp/src/main/res/layout/activity_debug.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/fbarriga/software/AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/profiles/BaseProfile.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles; 2 | 3 | import java.util.HashMap; 4 | import java.util.UUID; 5 | 6 | /** 7 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 8 | */ 9 | public abstract class BaseProfile { 10 | protected final static HashMap sUUIDNameMap; 11 | 12 | static { 13 | sUUIDNameMap = new HashMap<>( ); 14 | } 15 | 16 | public final HashMap getsUUIDNameMap() { 17 | return sUUIDNameMap; 18 | } 19 | 20 | public final String getUuidName( UUID uuid ) { 21 | return sUUIDNameMap.get( uuid ); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/DescriptorInfo.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | /** 4 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 5 | */ 6 | public class DescriptorInfo { 7 | final String mServiceName; 8 | final String mCharacteristicName; 9 | final String mDescriptorName; 10 | 11 | DescriptorInfo( String serviceName, String characteristicName, String descriptorName ) { 12 | mServiceName = serviceName; 13 | mCharacteristicName = characteristicName; 14 | mDescriptorName = descriptorName; 15 | } 16 | 17 | public String toString() { 18 | return "service=" + mServiceName + " name=" + mCharacteristicName + " descriptor=" + mDescriptorName; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DebugApp/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion '23.0.2' 6 | defaultConfig { 7 | applicationId 'cl.felipebarriga.android.sony.smartband.api.demo' 8 | minSdkVersion 18 9 | targetSdkVersion 23 10 | versionCode 1001 11 | versionName '1.0.0' 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | productFlavors { 20 | } 21 | } 22 | 23 | dependencies { 24 | compile fileTree(include: ['*.jar'], dir: 'libs') 25 | testCompile 'junit:junit:4.12' 26 | compile 'com.android.support:appcompat-v7:23.1.1' 27 | compile 'com.android.support:design:23.1.1' 28 | compile project(':SonySmartBandOpenAPI') 29 | } 30 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/profiles/GenericAccessProfile.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 7 | */ 8 | public class GenericAccessProfile extends BaseProfile { 9 | public static final String CLASS = "GenericAccessProfile"; 10 | 11 | public static final UUID SERVICE_UUID; 12 | public static final UUID DEVICE_NAME_UUID; 13 | 14 | static { 15 | SERVICE_UUID = UUID.fromString( "00001800-0000-1000-8000-00805F9B34FB" ); 16 | DEVICE_NAME_UUID = UUID.fromString( "00002A00-0000-1000-8000-00805F9B34FB" ); 17 | 18 | sUUIDNameMap.put( SERVICE_UUID, CLASS ); 19 | sUUIDNameMap.put( DEVICE_NAME_UUID, "DEVICE_NAME_UUID" ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/profiles/BleConstants.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles; 2 | 3 | import java.util.HashMap; 4 | import java.util.UUID; 5 | 6 | /** 7 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 8 | */ 9 | public class BleConstants { 10 | public static final UUID CLIENT_CHARACTERISTIC_CONFIGURATION; 11 | 12 | private static HashMap sUUIDNameMap; 13 | 14 | static { 15 | CLIENT_CHARACTERISTIC_CONFIGURATION = UUID.fromString( "00002902-0000-1000-8000-00805F9B34FB" ); 16 | 17 | sUUIDNameMap = new HashMap(); 18 | sUUIDNameMap.put( CLIENT_CHARACTERISTIC_CONFIGURATION, "CLIENT_CHARACTERISTIC_CONFIGURATION" ); 19 | } 20 | 21 | public static String getUuidName( UUID uuid ) { 22 | return sUUIDNameMap.get( uuid ); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /RawBandLogger/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion '23.0.2' 6 | defaultConfig { 7 | applicationId 'cl.felipebarriga.android.sony.smartband.api.rawband' 8 | minSdkVersion 18 9 | targetSdkVersion 23 10 | versionCode 1001 11 | versionName '1.0.0' 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | productFlavors { 20 | } 21 | } 22 | 23 | dependencies { 24 | compile fileTree(include: ['*.jar'], dir: 'libs') 25 | testCompile 'junit:junit:4.12' 26 | compile 'com.android.support:appcompat-v7:23.1.1' 27 | compile 'com.android.support:design:23.1.1' 28 | compile 'com.androidplot:androidplot-core:0.6.1' 29 | compile project(':SonySmartBandOpenAPI') 30 | } 31 | -------------------------------------------------------------------------------- /sony-smartband-open-api.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /DebugApp/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/BtBridgeListener.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | import android.bluetooth.BluetoothGattCharacteristic; 4 | import android.bluetooth.BluetoothGattDescriptor; 5 | import android.bluetooth.BluetoothGattService; 6 | 7 | import java.util.List; 8 | 9 | 10 | /** 11 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 12 | */ 13 | public interface BtBridgeListener { 14 | void onCharacteristicRead( BluetoothGattCharacteristic characteristic ); 15 | void onConnectionStateChange( BtBridge.Status status ); 16 | void onCharacteristicChanged( BluetoothGattCharacteristic characteristic ); 17 | void onCharacteristicWrite( BluetoothGattCharacteristic characteristic ); 18 | void onDescriptorRead( BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor ); 19 | void onDescriptorWrite( BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor ); 20 | void onServicesDiscovered( List services ); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/profiles/BatteryProfile.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles; 2 | 3 | import android.bluetooth.BluetoothGattCharacteristic; 4 | import java.util.UUID; 5 | 6 | /** 7 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 8 | */ 9 | public class BatteryProfile extends BaseProfile { 10 | public static final String CLASS = "BatteryProfile"; 11 | 12 | public static final UUID SERVICE_UUID; 13 | public static final UUID BATTERY_LEVEL_UUID; 14 | 15 | static { 16 | SERVICE_UUID = UUID.fromString( "0000180F-0000-1000-8000-00805F9B34FB" ); 17 | BATTERY_LEVEL_UUID = UUID.fromString( "00002A19-0000-1000-8000-00805F9B34FB" ); 18 | 19 | sUUIDNameMap.put( SERVICE_UUID, CLASS ); 20 | sUUIDNameMap.put( BATTERY_LEVEL_UUID, "BATTERY_LEVEL_UUID" ); 21 | } 22 | 23 | public static int readBatteryLevel( BluetoothGattCharacteristic characteristic ) { 24 | return characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT8, 0 ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Felipe Barriga Richards 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /DebugApp/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 1.8 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/BtBandListener.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | import java.util.Date; 4 | 5 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.AHServiceProfile; 6 | 7 | /** 8 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 9 | */ 10 | public interface BtBandListener { 11 | 12 | void onAHServiceReadAccData( int[] data ); 13 | void onAHServiceReadCurrentTime( int bandSeconds, Date deviceDate, long deltaMs ); 14 | void onAHServiceReadData( ); 15 | void onAHServiceReadEvent( BtBandEvent event ); 16 | void onAHServiceReadMode( BandMode.AccessoryMode mode ); 17 | void onAHServiceReadProtocolVersion( int version ); 18 | void onAHServiceReadUptime( int uptime, Date started ); 19 | 20 | void onBatteryLevel( int level ); 21 | 22 | void onFirmwareRevision( String rev ); 23 | void onSoftwareRevision( String rev ); 24 | void onHardwareRevision( String rev ); 25 | void onManufacturerName( String name ); 26 | 27 | void onAASDeviceVersion( int version ); 28 | void onAASDeviceSmartLink( int version ); 29 | void onAASDeviceProductId( String productId ); 30 | void onAASDeviceData( String data ); 31 | 32 | void onGADeviceName( String data ); 33 | 34 | void onConnectionStateChange( BtBridge.Status status ); 35 | void onServicesDiscovered(); 36 | } 37 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/profiles/DeviceInformationProfile.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 7 | */ 8 | public class DeviceInformationProfile extends BaseProfile { 9 | public static final String CLASS = "DeviceInformationProfile"; 10 | 11 | public static final UUID SERVICE_UUID; 12 | public static final UUID FIRMWARE_REVISION_UUID; 13 | public static final UUID HARDWARE_REVISION_UUID; 14 | public static final UUID SOFTWARE_REVISION_UUID; 15 | public static final UUID MANUFACTURER_NAME_UUID; 16 | 17 | static { 18 | SERVICE_UUID = UUID.fromString( "0000180A-0000-1000-8000-00805F9B34FB" ); 19 | FIRMWARE_REVISION_UUID = UUID.fromString( "00002A26-0000-1000-8000-00805F9B34FB" ); 20 | HARDWARE_REVISION_UUID = UUID.fromString( "00002A27-0000-1000-8000-00805F9B34FB" ); 21 | SOFTWARE_REVISION_UUID = UUID.fromString( "00002A28-0000-1000-8000-00805F9B34FB" ); 22 | MANUFACTURER_NAME_UUID = UUID.fromString( "00002A29-0000-1000-8000-00805F9B34FB" ); 23 | 24 | sUUIDNameMap.put( SERVICE_UUID , CLASS ); 25 | sUUIDNameMap.put( FIRMWARE_REVISION_UUID, "FIRMWARE_REVISION_UUID" ); 26 | sUUIDNameMap.put( HARDWARE_REVISION_UUID, "HARDWARE_REVISION_UUID" ); 27 | sUUIDNameMap.put( SOFTWARE_REVISION_UUID, "SOFTWARE_REVISION_UUID" ); 28 | sUUIDNameMap.put( MANUFACTURER_NAME_UUID, "MANUFACTURER_NAME_UUID" ); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/Profiles.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | import android.util.Log; 4 | 5 | import java.util.HashMap; 6 | import java.util.UUID; 7 | 8 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.AADeviceServiceProfile; 9 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.AHServiceProfile; 10 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.BaseProfile; 11 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.BatteryProfile; 12 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.DeviceInformationProfile; 13 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.GenericAccessProfile; 14 | 15 | /** 16 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 17 | */ 18 | public class Profiles { 19 | private static final String CLASS = "Profiles"; 20 | private static HashMap sUUIDProfileMap; 21 | 22 | static { 23 | sUUIDProfileMap = new HashMap(); 24 | sUUIDProfileMap.put( BatteryProfile.SERVICE_UUID , new BatteryProfile() ); 25 | sUUIDProfileMap.put( AHServiceProfile.SERVICE_UUID , new AHServiceProfile() ); 26 | sUUIDProfileMap.put( AADeviceServiceProfile.SERVICE_UUID , new AADeviceServiceProfile() ); 27 | sUUIDProfileMap.put( DeviceInformationProfile.SERVICE_UUID, new DeviceInformationProfile() ); 28 | sUUIDProfileMap.put( GenericAccessProfile.SERVICE_UUID , new GenericAccessProfile() ); 29 | } 30 | 31 | public static BaseProfile getService( UUID uuid ) { 32 | Log.v( CLASS, "getService: uuid=" + uuid.toString() ); 33 | Object profile = sUUIDProfileMap.get( uuid ); 34 | if( profile == null ) { 35 | Log.w( CLASS, "getService: Profile not found for uuid=" + uuid.toString() ); 36 | return null; 37 | } 38 | 39 | return ( BaseProfile ) profile; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/profiles/AADeviceServiceProfile.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles; 2 | 3 | import android.bluetooth.BluetoothGattCharacteristic; 4 | import java.util.UUID; 5 | 6 | /** 7 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 8 | */ 9 | public class AADeviceServiceProfile extends BaseProfile { 10 | public static final String CLASS = "AADeviceServiceProfile"; 11 | 12 | public static final UUID SERVICE_UUID; 13 | public static final UUID VERSION_UUID; 14 | public static final UUID DATA_UUID; 15 | public static final UUID PRODUCT_ID_UUID; 16 | public static final UUID SMART_LINK_SERVICE_UUID; 17 | 18 | static { 19 | SERVICE_UUID = UUID.fromString( "00000101-37cb-11e3-8682-0002a5d5c51b" ); 20 | VERSION_UUID = UUID.fromString( "00000110-37cb-11e3-8682-0002a5d5c51b" ); 21 | SMART_LINK_SERVICE_UUID = UUID.fromString( "00000111-37cb-11e3-8682-0002a5d5c51b" ); 22 | PRODUCT_ID_UUID = UUID.fromString( "00000112-37cb-11e3-8682-0002a5d5c51b" ); 23 | DATA_UUID = UUID.fromString( "00000113-37cb-11e3-8682-0002a5d5c51b" ); 24 | 25 | sUUIDNameMap.put( SERVICE_UUID , CLASS ); 26 | sUUIDNameMap.put( VERSION_UUID , "VERSION_UUID" ); 27 | sUUIDNameMap.put( SMART_LINK_SERVICE_UUID, "SMART_LINK_SERVICE_UUID" ); 28 | sUUIDNameMap.put( PRODUCT_ID_UUID , "PRODUCT_ID_UUID" ); 29 | sUUIDNameMap.put( DATA_UUID , "DATA_UUID" ); 30 | } 31 | 32 | public static int readDeviceAASVersion( BluetoothGattCharacteristic characteristic ) { 33 | return characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT16, 0 ); 34 | } 35 | 36 | public static int readDeviceSmartLinkService( BluetoothGattCharacteristic characteristic ) { 37 | return characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT8, 0 ); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/BandMode.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 7 | */ 8 | public class BandMode { 9 | public final static String CLASS = "BandMode"; 10 | 11 | public enum AccessoryMode { 12 | DAY, 13 | NIGHT, 14 | MEDIA, 15 | FIRMWARE_UPDATE, 16 | UNKNOWN 17 | } 18 | 19 | private interface ACCESSORY_MODE { 20 | int DAY = 0; 21 | int NIGHT = 1; 22 | int MEDIA = 2; 23 | int FIRMWARE_UPDATE = 3; 24 | } 25 | 26 | private final AccessoryMode mMode; 27 | public BandMode( int mode ) { 28 | mMode = getMode( mode ); 29 | } 30 | 31 | public static AccessoryMode getMode( int _mode ) { 32 | AccessoryMode mode; 33 | if( _mode == ACCESSORY_MODE.DAY ) { 34 | mode = AccessoryMode.DAY; 35 | } else if( _mode == ACCESSORY_MODE.NIGHT ) { 36 | mode = AccessoryMode.NIGHT; 37 | } else if( _mode == ACCESSORY_MODE.MEDIA ) { 38 | mode = AccessoryMode.MEDIA; 39 | } else if ( _mode == ACCESSORY_MODE.FIRMWARE_UPDATE ) { 40 | mode = AccessoryMode.FIRMWARE_UPDATE; 41 | } else { 42 | mode = AccessoryMode.UNKNOWN; 43 | Log.e( CLASS, "getMode: unknown mode: mode=" + _mode ); 44 | } 45 | return mode; 46 | } 47 | 48 | public AccessoryMode getMode() { 49 | return mMode; 50 | } 51 | 52 | static public int getInt( AccessoryMode mode ) { 53 | if( AccessoryMode.DAY.equals( mode ) ) { 54 | return ACCESSORY_MODE.DAY; 55 | } else if( AccessoryMode.NIGHT.equals( mode ) ) { 56 | return ACCESSORY_MODE.NIGHT; 57 | } else if( AccessoryMode.MEDIA.equals( mode ) ) { 58 | return ACCESSORY_MODE.MEDIA; 59 | } else if( AccessoryMode.FIRMWARE_UPDATE.equals( mode ) ) { 60 | return ACCESSORY_MODE.FIRMWARE_UPDATE; 61 | } 62 | 63 | Log.e( CLASS, "getInt: unknown mode: mode=" + mode ); 64 | return -1; 65 | } 66 | 67 | public int getInt() { 68 | return getInt( mMode ); 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/BtBandEvent.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | import android.util.Log; 4 | 5 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.AHServiceProfile; 6 | 7 | /** 8 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 9 | */ 10 | 11 | public class BtBandEvent { 12 | public static final String CLASS = "BtBandEvent"; 13 | 14 | private interface EVENT_TYPE_CODE { 15 | int TAP = 0; 16 | int BUTTON = 1; 17 | int LIFE_BOOKMARK = 2; 18 | int MODE_SWITCH = 3; 19 | int HARDWARE_EVENT = 4; 20 | int UPDATE_TIME = 5; 21 | } 22 | 23 | enum EventType { 24 | UNKNOWN, 25 | TAP, 26 | BUTTON, 27 | LIFE_BOOKMARK, 28 | MODE_SWITCH, 29 | HARDWARE_EVENT, 30 | UPDATE_TIME 31 | } 32 | 33 | enum Event { 34 | UNKNOWN, 35 | LOW_MEMORY, 36 | LOW_BATTERY, 37 | TAP_SINGLE, 38 | TAP_DOUBLE, 39 | TAP_TRIPLE, 40 | BUTTON, 41 | LIFE_BOOKMARK, 42 | MODE_SWITCH_DAY, 43 | MODE_SWITCH_NIGHT, 44 | MODE_SWITCH_MEDIA, 45 | MODE_SWITCH_FIRMWARE, 46 | UPDATE_TIME 47 | } 48 | 49 | private final EventType mType; 50 | private final Event mEvent; 51 | private final long mTimestamp; 52 | 53 | public EventType getType() { 54 | return mType; 55 | } 56 | 57 | public Event getEvent() { 58 | return mEvent; 59 | } 60 | 61 | public long getTimestamp() { 62 | return mTimestamp; 63 | } 64 | 65 | public BtBandEvent( int code, int value, int payload ) { 66 | 67 | if( code == EVENT_TYPE_CODE.LIFE_BOOKMARK ) { 68 | mType = EventType.LIFE_BOOKMARK; 69 | mEvent = Event.LIFE_BOOKMARK; 70 | mTimestamp = AHServiceProfile.convertBandSecondsToTimestamp( payload ); 71 | return; 72 | } 73 | 74 | mTimestamp = 0; 75 | 76 | // Button + TAP will enable media mode 77 | // On media mode taps are detected without problems 78 | if( code == EVENT_TYPE_CODE.TAP ) { 79 | mType = EventType.TAP; 80 | if( value == AHServiceProfile.TAP_EVENT_TYPE.SINGLE ) { 81 | mEvent = Event.TAP_SINGLE; 82 | } else if( value == AHServiceProfile.TAP_EVENT_TYPE.DOUBLE ) { 83 | mEvent = Event.TAP_DOUBLE; 84 | } else if( value == AHServiceProfile.TAP_EVENT_TYPE.TRIPLE ) { 85 | mEvent = Event.TAP_TRIPLE; 86 | } else { 87 | mEvent = Event.UNKNOWN; 88 | Log.e( CLASS, "BtBandEvent: Unknown kind of TAP. value: " + value ); 89 | } 90 | 91 | return; 92 | } 93 | 94 | if( code == EVENT_TYPE_CODE.BUTTON ) { 95 | mType = EventType.BUTTON; 96 | mEvent = Event.BUTTON; 97 | return; 98 | } 99 | 100 | if( code == EVENT_TYPE_CODE.MODE_SWITCH ) { 101 | mType = EventType.MODE_SWITCH; 102 | BandMode.AccessoryMode mode = new BandMode( value ).getMode(); 103 | switch( mode ) { 104 | case DAY: 105 | mEvent = Event.MODE_SWITCH_DAY; 106 | break; 107 | 108 | case NIGHT: 109 | mEvent = Event.MODE_SWITCH_NIGHT; 110 | break; 111 | 112 | case MEDIA: 113 | mEvent = Event.MODE_SWITCH_MEDIA; 114 | break; 115 | 116 | case FIRMWARE_UPDATE: 117 | mEvent = Event.MODE_SWITCH_FIRMWARE; 118 | break; 119 | 120 | case UNKNOWN: 121 | default: 122 | Log.e( CLASS, "BtBandEvent: Switched to unknown mode: " + value ); 123 | mEvent = Event.UNKNOWN; 124 | break; 125 | } 126 | return; 127 | } 128 | 129 | byte LOW_MEMORY_MASK = 0b00000001; 130 | byte LOW_BATTERY_MASK = 0b00000010; 131 | if( code == EVENT_TYPE_CODE.HARDWARE_EVENT ) { 132 | mType = EventType.HARDWARE_EVENT; 133 | if( ( value & LOW_BATTERY_MASK ) > 0 ) { 134 | mEvent = Event.LOW_BATTERY; 135 | } else if( ( value & LOW_MEMORY_MASK ) <= 0 ) { 136 | mEvent = Event.LOW_MEMORY; 137 | } else { 138 | mEvent = Event.UNKNOWN; 139 | Log.e( CLASS, "BtBandEvent: Unknown hardware event: " + value ); 140 | } 141 | return; 142 | } 143 | 144 | if( code == EVENT_TYPE_CODE.UPDATE_TIME ) { 145 | mType = EventType.UPDATE_TIME; 146 | mEvent = Event.UPDATE_TIME; 147 | Log.d( CLASS, "readEvent: The device is requesting that we send a time update" ); 148 | return; 149 | } 150 | 151 | mType = EventType.UNKNOWN; 152 | mEvent = Event.UNKNOWN; 153 | 154 | Log.e( CLASS, "BtBandEvent: Unknown mode: " + code ); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/java/cl/felipebarriga/android/sony/smartband/api/rawband/RawBandActivity.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.rawband; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.util.Log; 7 | 8 | import java.util.Date; 9 | 10 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BandMode; 11 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBand; 12 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBandEvent; 13 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBandListener; 14 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBridge; 15 | 16 | /** 17 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 18 | */ 19 | public class RawBandActivity extends Activity implements BtBandListener { 20 | private final String CLASS = getClass().getSimpleName(); 21 | 22 | @Override 23 | public void onAHServiceReadAccData( int[] data ) { 24 | Log.d( CLASS, "onAHServiceReadAccData: data=[" + data[0] + "," + data[1] + "," + data[2] + "]" ); 25 | } 26 | 27 | @Override 28 | public void onAHServiceReadEvent( BtBandEvent event ) { 29 | Log.d( CLASS, "onAHServiceReadEvent: event=" + event ); 30 | } 31 | 32 | @Override 33 | public void onAHServiceReadCurrentTime( int bandSeconds, Date deviceDate, long deltaMs ) { 34 | Log.d( CLASS, "onAHServiceReadCurrentTime: bandSeconds=" + bandSeconds 35 | +" deviceDate=" + deviceDate + " deltaMs=" + deltaMs ); 36 | 37 | // SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); 38 | // updateUILabel( RowId.CURRENT_TIME, sdf.format( deviceDate ) ); 39 | } 40 | 41 | @Override 42 | public void onAHServiceReadProtocolVersion( int version ) { 43 | Log.d( CLASS, "onAHServiceReadProtocolVersion: version=" + version ); 44 | // updateUILabel( RowId.PROTOCOL_VERSION, String.valueOf( version ) ); 45 | } 46 | 47 | @Override 48 | public void onAHServiceReadData( ) { 49 | Log.d( CLASS, "onAHServiceReadData: called." ); 50 | } 51 | 52 | @Override 53 | public void onAHServiceReadMode( BandMode.AccessoryMode mode ) { 54 | Log.d( CLASS, "onAHServiceReadMode: mode=" + mode.name() ); 55 | // updateUILabel( RowId.CURRENT_MODE, mode.name() ); 56 | } 57 | 58 | @Override 59 | public void onAHServiceReadUptime( int uptime, Date started ) { 60 | Log.d( CLASS, "onAHServiceReadUptime: started=" + started + " uptime=" + uptime ); 61 | // updateUILabel( RowId.UPTIME, String.valueOf( uptime ) ); 62 | } 63 | 64 | @Override 65 | public void onBatteryLevel( int level ) { 66 | Log.d( CLASS, "onBatteryLevel: level=" + level ); 67 | // updateUILabel( RowId.BATTERY_LEVEL, String.valueOf( level ) ); 68 | } 69 | 70 | @Override 71 | public void onFirmwareRevision( String rev ) { 72 | // updateUILabel( RowId.FIRMWARE_REVISION, rev ); 73 | } 74 | 75 | @Override 76 | public void onSoftwareRevision( String rev ) { 77 | // updateUILabel( RowId.SOFTWARE_REVISION, rev ); 78 | } 79 | 80 | @Override 81 | public void onHardwareRevision( String rev ) { 82 | // updateUILabel( RowId.HARDWARE_REVISION, rev ); 83 | } 84 | 85 | @Override 86 | public void onManufacturerName( String name ) { 87 | // updateUILabel( RowId.MANUFACTURER_NAME, name ); 88 | } 89 | 90 | @Override 91 | public void onAASDeviceVersion( int version ) { 92 | // updateUILabel( RowId.AAS_VERSION, String.valueOf( version ) ); 93 | } 94 | 95 | @Override 96 | public void onAASDeviceSmartLink( int smartLink ) { 97 | // updateUILabel( RowId.AAS_SMART_LINK, String.valueOf( smartLink ) ); 98 | } 99 | 100 | @Override 101 | public void onAASDeviceProductId( String productId ) { 102 | // updateUILabel( RowId.AAS_PRODUCT_ID, productId ); 103 | } 104 | 105 | @Override 106 | public void onAASDeviceData( String data ) { 107 | // updateUILabel( RowId.AAS_DATA, data ); 108 | } 109 | 110 | @Override 111 | public void onGADeviceName( String name ) { 112 | // updateUILabel( RowId.GA_DEVICE_NAME, name ); 113 | } 114 | 115 | @Override 116 | public void onConnectionStateChange( final BtBridge.Status status ) { 117 | Log.i( CLASS, "onConnectionStateChange: status=" + status.name() ); 118 | if( status == BtBridge.Status.CONNECTED ) { 119 | // updateUIButton( RowId.STATUS, true, "Disconnect" ); 120 | } else if( status == BtBridge.Status.DISCONNECTED ) { 121 | // updateUIButton( RowId.STATUS, true, "Connect" ); 122 | } else { 123 | // updateUIButton( RowId.STATUS, false, "Disconnect" ); 124 | } 125 | } 126 | 127 | @Override 128 | public void onServicesDiscovered() { 129 | Log.i( CLASS, "onServicesDiscovered: called" ); 130 | } 131 | 132 | private BtBand mBtBand; 133 | private Handler mHandler; 134 | 135 | @Override 136 | protected void onCreate( Bundle savedInstanceState ) { 137 | super.onCreate( savedInstanceState ); 138 | Log.v( CLASS, "onCreate: called." ); 139 | 140 | // mHandler = new Handler( ); 141 | // mBtBand = new BtBand( this ); 142 | // mBtBand.addListener( this ); 143 | setContentView( R.layout.activity_rawband ); 144 | } 145 | 146 | @Override 147 | protected void onStart() { 148 | super.onStart(); 149 | Log.v( CLASS, "onStart: called." ); 150 | } 151 | 152 | @Override 153 | protected void onResume() { 154 | super.onResume(); 155 | Log.v( CLASS, "onResume: called." ); 156 | } 157 | 158 | @Override 159 | protected void onPause() { 160 | super.onPause(); 161 | Log.v( CLASS, "onPause: called." ); 162 | } 163 | 164 | @Override 165 | protected void onRestart() { 166 | super.onRestart(); 167 | Log.v( CLASS, "onRestart: called." ); 168 | } 169 | 170 | @Override 171 | protected void onStop() { 172 | super.onStop(); 173 | Log.v( CLASS, "onStop: called." ); 174 | } 175 | 176 | @Override 177 | protected void onDestroy() { 178 | super.onDestroy(); 179 | Log.v( CLASS, "onDestroy: called." ); 180 | mBtBand.disconnect(); 181 | } 182 | 183 | 184 | } 185 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/SonySmartBandOpenAPI.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/profiles/AHServiceProfile.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles; 2 | 3 | import android.bluetooth.BluetoothGattCharacteristic; 4 | import android.util.Log; 5 | 6 | import java.util.Calendar; 7 | import java.util.Date; 8 | import java.util.UUID; 9 | 10 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BandMode; 11 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBandEvent; 12 | 13 | /** 14 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 15 | */ 16 | public class AHServiceProfile extends BaseProfile { 17 | public static final String CLASS = "AHServiceProfile"; 18 | 19 | public static final UUID SERVICE_UUID; 20 | public static final UUID ACCEL_DATA_UUID; 21 | public static final UUID AUTO_NIGHT_MODE_UUID; 22 | public static final UUID CONTROL_POINT_UUID; 23 | public static final UUID ALARM_UUID; 24 | public static final UUID CURRENT_TIME_UUID; 25 | public static final UUID DATA_UUID; 26 | public static final UUID DEBUG_UUID; 27 | public static final UUID MODE_UUID; 28 | public static final UUID EVENT_UUID; 29 | public static final UUID NOTIFICATION_UUID; 30 | public static final UUID PROTOCOL_VERSION_UUID; 31 | public static final UUID USER_TARGET_UUID; 32 | 33 | public static final long TIMESTAMP_OF_2013 = 1356998400000L; 34 | 35 | public interface TAP_EVENT_TYPE { 36 | int SINGLE = 0; 37 | int DOUBLE = 1; 38 | int TRIPLE = 2; 39 | } 40 | 41 | static { 42 | SERVICE_UUID = UUID.fromString( "00000200-37cb-11e3-8682-0002a5d5c51b" ); 43 | PROTOCOL_VERSION_UUID = UUID.fromString( "00000201-37cb-11e3-8682-0002a5d5c51b" ); 44 | MODE_UUID = UUID.fromString( "00000202-37cb-11e3-8682-0002a5d5c51b" ); 45 | DATA_UUID = UUID.fromString( "00000203-37cb-11e3-8682-0002a5d5c51b" ); 46 | NOTIFICATION_UUID = UUID.fromString( "00000204-37cb-11e3-8682-0002a5d5c51b" ); 47 | USER_TARGET_UUID = UUID.fromString( "00000205-37cb-11e3-8682-0002a5d5c51b" ); 48 | ALARM_UUID = UUID.fromString( "00000206-37cb-11e3-8682-0002a5d5c51b" ); 49 | ACCEL_DATA_UUID = UUID.fromString( "00000207-37cb-11e3-8682-0002a5d5c51b" ); 50 | CURRENT_TIME_UUID = UUID.fromString( "00000208-37cb-11e3-8682-0002a5d5c51b" ); 51 | EVENT_UUID = UUID.fromString( "00000209-37cb-11e3-8682-0002a5d5c51b" ); 52 | CONTROL_POINT_UUID = UUID.fromString( "00000210-37cb-11e3-8682-0002a5d5c51b" ); 53 | DEBUG_UUID = UUID.fromString( "00000211-37cb-11e3-8682-0002a5d5c51b" ); 54 | AUTO_NIGHT_MODE_UUID = UUID.fromString( "00000212-37cb-11e3-8682-0002a5d5c51b" ); 55 | 56 | sUUIDNameMap.put( SERVICE_UUID , CLASS ); 57 | sUUIDNameMap.put( PROTOCOL_VERSION_UUID, "PROTOCOL_VERSION_UUID" ); 58 | sUUIDNameMap.put( MODE_UUID , "MODE_UUID" ); 59 | sUUIDNameMap.put( DATA_UUID , "DATA_UUID" ); 60 | sUUIDNameMap.put( NOTIFICATION_UUID , "NOTIFICATION_UUID" ); 61 | sUUIDNameMap.put( USER_TARGET_UUID , "USER_TARGET_UUID" ); 62 | sUUIDNameMap.put( ALARM_UUID , "ALARM_UUID" ); 63 | sUUIDNameMap.put( ACCEL_DATA_UUID , "ACCEL_DATA_UUID" ); 64 | sUUIDNameMap.put( CURRENT_TIME_UUID , "CURRENT_TIME_UUID" ); 65 | sUUIDNameMap.put( EVENT_UUID , "EVENT_UUID" ); 66 | sUUIDNameMap.put( CONTROL_POINT_UUID , "CONTROL_POINT_UUID" ); 67 | sUUIDNameMap.put( DEBUG_UUID , "DEBUG_UUID" ); 68 | sUUIDNameMap.put( AUTO_NIGHT_MODE_UUID , "AUTO_NIGHT_MODE_UUID" ); 69 | } 70 | 71 | public static int readProtocolVersion( BluetoothGattCharacteristic characteristic ) { 72 | return characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT8, 0 ); 73 | } 74 | 75 | // return uptime in seconds 76 | public static int readUptime( BluetoothGattCharacteristic characteristic ) { 77 | return characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT32, 0 ); 78 | } 79 | 80 | 81 | 82 | public static BandMode.AccessoryMode readMode( BluetoothGattCharacteristic characteristic ) { 83 | int mode = characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT8, 0 ); 84 | return new BandMode( mode ).getMode(); 85 | } 86 | 87 | public static long convertBandSecondsToTimestamp( int seconds ) { 88 | return TIMESTAMP_OF_2013 + ( (long) seconds ) * 1000; 89 | } 90 | 91 | public static Date convertBandSecondsToDate( int seconds ) { 92 | long utcTime = convertBandSecondsToTimestamp( seconds ); 93 | Calendar calendar = Calendar.getInstance(); 94 | calendar.setTimeInMillis( utcTime ); 95 | return calendar.getTime(); 96 | } 97 | 98 | public static int convertTimestampToBandSeconds( long timestamp ) { 99 | long bandMilliseconds = timestamp - TIMESTAMP_OF_2013; 100 | int bandSeconds = (int) (bandMilliseconds / 1000); 101 | 102 | return bandSeconds; 103 | } 104 | 105 | public static void readData( BluetoothGattCharacteristic characteristic ) { 106 | // TODO 107 | } 108 | 109 | public static BtBandEvent readEvent( BluetoothGattCharacteristic characteristic ) { 110 | int PAYLOAD_SIZE = 4; 111 | int payload = 0; 112 | int offset = 0; 113 | 114 | if( characteristic.getValue().length > PAYLOAD_SIZE ) { 115 | payload = characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT32, 0 ); 116 | offset = PAYLOAD_SIZE; 117 | } 118 | int eventData = characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT32, offset ); 119 | 120 | int code = ( 0b11111111000000000000000000000000 & eventData ) >> 24; 121 | int value = ( 0b00000000111111111111111111111111 & eventData ); 122 | Log.v( CLASS, "readEvent: code=" + code + " value=" + value + " payload=" + payload ); 123 | 124 | return new BtBandEvent( code, value, payload ); 125 | } 126 | 127 | /** 128 | * Retrieve acceleration data from characteristic with 10bits of resolution 129 | * @param characteristic 130 | * @return int[] array with raw values 131 | */ 132 | public static int[] readAccData( BluetoothGattCharacteristic characteristic ) { 133 | int accData = characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT32, 0 ); 134 | int x = ( 0b111111111100000000000000000000 & accData ) >> 20; 135 | int y = ( 0b000000000011111111110000000000 & accData ) >> 10; 136 | int z = ( 0b000000000000000000001111111111 & accData ); 137 | 138 | return new int[]{ x, y, z }; 139 | } 140 | 141 | public static int readCurrentTime( BluetoothGattCharacteristic characteristic ) { 142 | return characteristic.getIntValue( BluetoothGattCharacteristic.FORMAT_UINT32, 0 ); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /DebugApp/DebugApp.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /RawBandLogger/RawBandLogger.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /RawBandLogger/src/main/res/layout/activity_rawband.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 19 | 20 | 23 | 24 | 29 | 30 | 31 | 42 | 43 | 52 | 53 | 54 | 55 | 56 | 59 | 60 | 65 | 66 | 67 | 78 | 79 | 88 | 89 | 90 | 91 | 94 | 95 | 100 | 101 | 110 | 111 | 120 | 121 | 122 | 125 | 126 | 131 | 132 | 141 | 142 | 151 | 152 | 153 | 156 | 157 | 162 | 163 | 172 | 173 | 182 | 183 | 184 | 185 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/BtAction.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | import android.bluetooth.BluetoothGattCharacteristic; 4 | 5 | import java.util.HashMap; 6 | import java.util.UUID; 7 | 8 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.AADeviceServiceProfile; 9 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.AHServiceProfile; 10 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.BatteryProfile; 11 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.BleConstants; 12 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.DeviceInformationProfile; 13 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.GenericAccessProfile; 14 | 15 | /** 16 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 17 | */ 18 | public class BtAction { 19 | public static class ActionDetails { 20 | public final Action mAction; 21 | 22 | public final int mFormat; 23 | public final Type mType; 24 | 25 | public final UUID mService; 26 | public final UUID mCharacteristic; 27 | public final UUID mDescriptor; 28 | 29 | public ActionDetails( Action action, Type type, UUID service, UUID characteristic, UUID descriptor, int format ) { 30 | mAction = action; 31 | mType = type; 32 | mService = service; 33 | mCharacteristic = characteristic; 34 | mDescriptor = descriptor; 35 | mFormat = format; 36 | } 37 | 38 | public ActionDetails( Action action, Type type, UUID service, UUID characteristic, UUID descriptor ) { 39 | this( action, type, service, characteristic, descriptor, 0 ); 40 | } 41 | 42 | public ActionDetails( Action action, Type type, UUID service, UUID characteristic, int format ) { 43 | this( action, type, service, characteristic, null, format ); 44 | } 45 | 46 | public ActionDetails( Action action, Type type, UUID service, UUID characteristic ) { 47 | this( action, type, service, characteristic, null, 0 ); 48 | } 49 | } 50 | 51 | enum Type { 52 | READ_CHAR, 53 | WRITE_CHAR, 54 | ENABLE_NOTIFICATION, 55 | DISABLE_NOTIFICATION 56 | } 57 | 58 | public enum Action { 59 | REQUEST_BATTERY_LEVEL, 60 | REQUEST_PROTOCOL_VERSION, 61 | REQUEST_CURRENT_TIME, 62 | REQUEST_UPTIME, 63 | REQUEST_MODE, 64 | REQUEST_FIRMWARE_REVISION, 65 | REQUEST_HARDWARE_REVISION, 66 | REQUEST_SOFTWARE_REVISION, 67 | REQUEST_MANUFACTURER_NAME, 68 | REQUEST_AAS_VERSION, 69 | REQUEST_AAS_SMART_LINK, 70 | REQUEST_AAS_PRODUCT_ID, 71 | REQUEST_AAS_DEVICE_DATA, 72 | REQUEST_GA_DEVICE_NAME, 73 | SET_MODE, 74 | SET_ACC_INTERVAL, 75 | SET_CURRENT_TIME, 76 | ENABLE_DEBUG_NOTIFICATIONS, 77 | DISABLE_DEBUG_NOTIFICATIONS, 78 | ENABLE_EVENT_NOTIFICATIONS, 79 | DISABLE_EVENT_NOTIFICATIONS, 80 | ENABLE_DATA_NOTIFICATIONS, 81 | DISABLE_DATA_NOTIFICATIONS, 82 | ENABLE_ACC_NOTIFICATIONS, 83 | DISABLE_ACC_NOTIFICATIONS, 84 | 85 | } 86 | 87 | private final static HashMap ACTION_MAP = new HashMap<>( ); 88 | 89 | private static void mapAction( Action action, Type type, UUID service, UUID characteristic ) { 90 | ACTION_MAP.put( action, new ActionDetails( action, type, service, characteristic ) ); 91 | } 92 | 93 | private static void mapAction( Action action, Type type, UUID service, UUID characteristic, int format ) { 94 | ACTION_MAP.put( action, new ActionDetails( action, type, service, characteristic, format ) ); 95 | } 96 | 97 | private static void mapAction( Action action, Type type, UUID service, UUID characteristic, UUID descriptor ) { 98 | ACTION_MAP.put( action, new ActionDetails( action, type, service, characteristic, descriptor ) ); 99 | } 100 | 101 | static { 102 | mapAction( Action.REQUEST_BATTERY_LEVEL , Type.READ_CHAR, BatteryProfile.SERVICE_UUID , BatteryProfile.BATTERY_LEVEL_UUID ); 103 | 104 | mapAction( Action.REQUEST_PROTOCOL_VERSION , Type.READ_CHAR, AHServiceProfile.SERVICE_UUID , AHServiceProfile.PROTOCOL_VERSION_UUID ); 105 | mapAction( Action.REQUEST_CURRENT_TIME , Type.READ_CHAR, AHServiceProfile.SERVICE_UUID , AHServiceProfile.CURRENT_TIME_UUID ); 106 | mapAction( Action.REQUEST_MODE , Type.READ_CHAR, AHServiceProfile.SERVICE_UUID , AHServiceProfile.MODE_UUID ); 107 | mapAction( Action.REQUEST_UPTIME , Type.READ_CHAR, AHServiceProfile.SERVICE_UUID , AHServiceProfile.DEBUG_UUID ); 108 | 109 | mapAction( Action.REQUEST_FIRMWARE_REVISION , Type.READ_CHAR, DeviceInformationProfile.SERVICE_UUID, DeviceInformationProfile.FIRMWARE_REVISION_UUID ); 110 | mapAction( Action.REQUEST_HARDWARE_REVISION , Type.READ_CHAR, DeviceInformationProfile.SERVICE_UUID, DeviceInformationProfile.HARDWARE_REVISION_UUID ); 111 | mapAction( Action.REQUEST_SOFTWARE_REVISION , Type.READ_CHAR, DeviceInformationProfile.SERVICE_UUID, DeviceInformationProfile.SOFTWARE_REVISION_UUID ); 112 | mapAction( Action.REQUEST_MANUFACTURER_NAME , Type.READ_CHAR, DeviceInformationProfile.SERVICE_UUID, DeviceInformationProfile.MANUFACTURER_NAME_UUID ); 113 | 114 | mapAction( Action.REQUEST_AAS_VERSION , Type.READ_CHAR, AADeviceServiceProfile.SERVICE_UUID , AADeviceServiceProfile.VERSION_UUID ); 115 | mapAction( Action.REQUEST_AAS_SMART_LINK , Type.READ_CHAR, AADeviceServiceProfile.SERVICE_UUID , AADeviceServiceProfile.SMART_LINK_SERVICE_UUID ); 116 | mapAction( Action.REQUEST_AAS_PRODUCT_ID , Type.READ_CHAR, AADeviceServiceProfile.SERVICE_UUID , AADeviceServiceProfile.PRODUCT_ID_UUID ); 117 | mapAction( Action.REQUEST_AAS_DEVICE_DATA , Type.READ_CHAR, AADeviceServiceProfile.SERVICE_UUID , AADeviceServiceProfile.DATA_UUID ); 118 | 119 | mapAction( Action.REQUEST_GA_DEVICE_NAME , Type.READ_CHAR, GenericAccessProfile.SERVICE_UUID , GenericAccessProfile.DEVICE_NAME_UUID ); 120 | 121 | mapAction( Action.SET_CURRENT_TIME, Type.WRITE_CHAR, AHServiceProfile.SERVICE_UUID, AHServiceProfile.CURRENT_TIME_UUID, BluetoothGattCharacteristic.FORMAT_UINT32 ); 122 | mapAction( Action.SET_MODE , Type.WRITE_CHAR, AHServiceProfile.SERVICE_UUID, AHServiceProfile.MODE_UUID , BluetoothGattCharacteristic.FORMAT_UINT8 ); 123 | mapAction( Action.SET_ACC_INTERVAL, Type.WRITE_CHAR, AHServiceProfile.SERVICE_UUID, AHServiceProfile.ACCEL_DATA_UUID , BluetoothGattCharacteristic.FORMAT_UINT32 ); 124 | 125 | mapAction( Action.ENABLE_EVENT_NOTIFICATIONS , Type.ENABLE_NOTIFICATION , AHServiceProfile.SERVICE_UUID, AHServiceProfile.EVENT_UUID, BleConstants.CLIENT_CHARACTERISTIC_CONFIGURATION ); 126 | mapAction( Action.DISABLE_EVENT_NOTIFICATIONS, Type.DISABLE_NOTIFICATION, AHServiceProfile.SERVICE_UUID, AHServiceProfile.EVENT_UUID, BleConstants.CLIENT_CHARACTERISTIC_CONFIGURATION ); 127 | mapAction( Action.ENABLE_DATA_NOTIFICATIONS , Type.ENABLE_NOTIFICATION , AHServiceProfile.SERVICE_UUID, AHServiceProfile.DATA_UUID, BleConstants.CLIENT_CHARACTERISTIC_CONFIGURATION ); 128 | mapAction( Action.DISABLE_DATA_NOTIFICATIONS , Type.DISABLE_NOTIFICATION, AHServiceProfile.SERVICE_UUID, AHServiceProfile.DATA_UUID, BleConstants.CLIENT_CHARACTERISTIC_CONFIGURATION ); 129 | mapAction( Action.ENABLE_ACC_NOTIFICATIONS , Type.ENABLE_NOTIFICATION , AHServiceProfile.SERVICE_UUID, AHServiceProfile.ACCEL_DATA_UUID, BleConstants.CLIENT_CHARACTERISTIC_CONFIGURATION ); 130 | mapAction( Action.DISABLE_ACC_NOTIFICATIONS , Type.DISABLE_NOTIFICATION, AHServiceProfile.SERVICE_UUID, AHServiceProfile.ACCEL_DATA_UUID, BleConstants.CLIENT_CHARACTERISTIC_CONFIGURATION ); 131 | mapAction( Action.ENABLE_DEBUG_NOTIFICATIONS , Type.ENABLE_NOTIFICATION , AHServiceProfile.SERVICE_UUID, AHServiceProfile.DEBUG_UUID, BleConstants.CLIENT_CHARACTERISTIC_CONFIGURATION ); 132 | mapAction( Action.DISABLE_DEBUG_NOTIFICATIONS, Type.DISABLE_NOTIFICATION, AHServiceProfile.SERVICE_UUID, AHServiceProfile.DEBUG_UUID, BleConstants.CLIENT_CHARACTERISTIC_CONFIGURATION ); 133 | } 134 | 135 | public int mParam; 136 | 137 | public final Action mAction; 138 | BtAction( Action action ) { 139 | mAction = action; 140 | } 141 | 142 | public BtAction setParameter( int param ) { 143 | mParam = param; 144 | return this; 145 | } 146 | 147 | public UUID getServiceUUID() { 148 | ActionDetails details = ACTION_MAP.get( mAction ); 149 | return details.mService; 150 | } 151 | 152 | public UUID getCharacteristicUUID() { 153 | ActionDetails details = ACTION_MAP.get( mAction ); 154 | return details.mCharacteristic; 155 | } 156 | 157 | public UUID getDescriptorUUID() { 158 | ActionDetails details = ACTION_MAP.get( mAction ); 159 | return details.mDescriptor; 160 | } 161 | 162 | public Type getType() { 163 | ActionDetails details = ACTION_MAP.get( mAction ); 164 | return details.mType; 165 | } 166 | 167 | public int getFormat() { 168 | ActionDetails details = ACTION_MAP.get( mAction ); 169 | return details.mFormat; 170 | } 171 | 172 | 173 | } 174 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/BtBridge.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | import android.bluetooth.BluetoothAdapter; 4 | import android.bluetooth.BluetoothDevice; 5 | import android.bluetooth.BluetoothGatt; 6 | import android.bluetooth.BluetoothGattCallback; 7 | import android.bluetooth.BluetoothGattCharacteristic; 8 | import android.bluetooth.BluetoothGattDescriptor; 9 | import android.bluetooth.BluetoothGattService; 10 | import android.bluetooth.BluetoothManager; 11 | import android.bluetooth.BluetoothProfile; 12 | import android.content.Context; 13 | import android.util.Log; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Set; 18 | import java.util.UUID; 19 | 20 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.BaseProfile; 21 | 22 | /** 23 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 24 | */ 25 | 26 | // TODO: how to handle when status != BluetoothGatt.GATT_SUCCESS 27 | public class BtBridge extends BluetoothGattCallback { 28 | public final static String[] COMPATIBLE_DEVICES = { "SWR10" }; 29 | public final String CLASS = getClass().getSimpleName(); 30 | 31 | public enum Status { 32 | CONNECTED, 33 | DISCONNECTED, 34 | CONNECTING 35 | } 36 | 37 | private Context mContext; 38 | ArrayList mListeners = new ArrayList<>(); 39 | 40 | private BluetoothAdapter mBluetoothAdapter; 41 | private BluetoothGatt mGatt; 42 | 43 | private Status mStatus; 44 | 45 | private ArrayList mDevices = new ArrayList<>(); 46 | 47 | BtBridge( Context context ) { 48 | mContext = context; 49 | BluetoothManager btManager = ( BluetoothManager ) mContext.getSystemService( Context.BLUETOOTH_SERVICE ); 50 | mBluetoothAdapter = btManager.getAdapter(); 51 | mStatus = Status.DISCONNECTED; 52 | } 53 | 54 | public Status getStatus() { 55 | return mStatus; 56 | } 57 | 58 | public void addListener( BtBridgeListener listener ) { 59 | if( mListeners.contains( listener ) ) { 60 | Log.w( CLASS, "addListener: Listener already registered" ); 61 | } else { 62 | mListeners.add( listener ); 63 | } 64 | } 65 | 66 | public boolean isDeviceCompatible( String deviceName ) { 67 | for( String device : COMPATIBLE_DEVICES ) { 68 | if( device.equals( deviceName ) ) { 69 | return true; 70 | } 71 | } 72 | return false; 73 | } 74 | 75 | public boolean connect() { 76 | Log.d( CLASS, "connect: called." ); 77 | 78 | if( !mStatus.equals( Status.DISCONNECTED ) ) { 79 | Log.e( CLASS, "connect: Invalid status=" + mStatus.name() ); 80 | return false; 81 | } 82 | 83 | populatePairedDevices(); 84 | BluetoothDevice btDevice = getDevice(); 85 | if( btDevice == null ) { 86 | Log.e( CLASS, "connect: Device not found." ); 87 | return false; 88 | } 89 | 90 | mStatus = Status.CONNECTING; 91 | btDevice.connectGatt( mContext, true, this ); 92 | return true; 93 | } 94 | 95 | 96 | public boolean disconnect() { 97 | Log.d( CLASS, "disconnect: called." ); 98 | if( !mStatus.equals( Status.CONNECTED ) ) { 99 | Log.e( CLASS, "disconnect: Not connected: status=" + mStatus.name() ); 100 | return false; 101 | } 102 | 103 | if( mGatt == null ) { 104 | Log.e( CLASS, "disconnect: mGatt not found" ); 105 | return false; 106 | } 107 | 108 | Log.i( CLASS, "disconnect: disconnected." ); 109 | mGatt.disconnect(); 110 | return true; 111 | } 112 | 113 | public boolean isGattReady() { 114 | if( !mStatus.equals( Status.CONNECTED ) ) { 115 | Log.e( CLASS, "isGattReady: Not connected: status=" + mStatus.name() ); 116 | return false; 117 | } 118 | 119 | if( mGatt == null ) { 120 | Log.e( CLASS, "isGattReady: mGatt not found" ); 121 | return false; 122 | } 123 | 124 | return true; 125 | } 126 | 127 | public boolean discoverServices() { 128 | Log.d( CLASS, "discoverServices: called." ); 129 | if( !isGattReady() ) { 130 | Log.e( CLASS, "discoverServices: Gatt not ready" ); 131 | return false; 132 | } 133 | 134 | return true; 135 | } 136 | 137 | private BluetoothDevice getDevice() { 138 | for( BluetoothDevice btdev : mDevices ) { 139 | if( isDeviceCompatible( btdev.getName() ) ) { 140 | Log.d( CLASS, "getDevice: Device found: addr=" + btdev.getAddress() ); 141 | return btdev; 142 | } 143 | } 144 | 145 | Log.w( CLASS, "getDevice: device not found." ); 146 | return null; 147 | } 148 | 149 | private void populatePairedDevices() { 150 | Log.d( CLASS, "populatePairedDevices: called." ); 151 | Set pairedDevices = mBluetoothAdapter.getBondedDevices(); 152 | 153 | mDevices.clear(); 154 | if( pairedDevices != null && pairedDevices.size() > 0 ) { 155 | mDevices.addAll( pairedDevices ); 156 | } 157 | printPairedDevices(); 158 | } 159 | 160 | private void printPairedDevices() { 161 | Log.i( CLASS, "printPairedDevices: mDevices=" + mDevices.size() ); 162 | for( BluetoothDevice btdev : mDevices ) { 163 | Log.i( CLASS, "printPairedDevices: addr=" + btdev.getAddress() + " name=" + btdev.getName() ); 164 | } 165 | } 166 | 167 | public BluetoothGattCharacteristic getCharacteristic( UUID serviceUuid, UUID characteristicUuid ) { 168 | if( !isGattReady() ) { 169 | Log.e( CLASS, "getCharacteristic: Gatt not ready" ); 170 | return null; 171 | } 172 | 173 | BaseProfile serviceProfile = Profiles.getService( serviceUuid ); 174 | if( serviceProfile == null ) { 175 | Log.e( CLASS, "getCharacteristic: serviceProfile not found. serviceUuid=" + serviceUuid ); 176 | } 177 | 178 | BluetoothGattService service = mGatt.getService( serviceUuid ); 179 | if( service == null ) { 180 | Log.e( CLASS, "getCharacteristic: service not found (on gatt). serviceUuid=" + serviceUuid ); 181 | return null; 182 | } 183 | 184 | BluetoothGattCharacteristic characteristic = service.getCharacteristic( characteristicUuid ); 185 | if( characteristic == null ) { 186 | Log.e( CLASS, "getCharacteristic: characteristic not found. uuid=" + characteristicUuid ); 187 | return null; 188 | } 189 | 190 | return characteristic; 191 | } 192 | 193 | public boolean readCharacteristic( BluetoothGattCharacteristic characteristic ) { 194 | if( characteristic == null ) { 195 | Log.e( CLASS, "readCharacteristic: characteristic=null" ); 196 | return false; 197 | } 198 | 199 | if( !isGattReady() ) { 200 | Log.e( CLASS, "readCharacteristic: Gatt not ready" ); 201 | return false; 202 | } 203 | 204 | return mGatt.readCharacteristic( characteristic ); 205 | } 206 | 207 | public boolean writeCharacteristic( BluetoothGattCharacteristic characteristic ) { 208 | if( !isGattReady() ) { 209 | Log.e( CLASS, "writeCharacteristic: Gatt not ready" ); 210 | return false; 211 | } 212 | 213 | return mGatt.writeCharacteristic( characteristic ); 214 | } 215 | 216 | public boolean writeDescriptor( BluetoothGattDescriptor descriptor ) { 217 | if( !isGattReady() ) { 218 | Log.e( CLASS, "writeDescriptor: Gatt not ready" ); 219 | return false; 220 | } 221 | 222 | return mGatt.writeDescriptor( descriptor ); 223 | } 224 | 225 | public boolean setCharacteristicNotification( BluetoothGattCharacteristic characteristic, boolean enabled ) { 226 | if( !isGattReady() ) { 227 | Log.e( CLASS, "setCharacteristicNotification: Gatt not ready" ); 228 | return false; 229 | } 230 | 231 | return mGatt.setCharacteristicNotification( characteristic, enabled ); 232 | } 233 | 234 | @Override 235 | public void onConnectionStateChange( BluetoothGatt gatt, int status, int newState ) { 236 | if( status != BluetoothGatt.GATT_SUCCESS ) { 237 | Log.e( CLASS, "onConnectionStateChange: Status != SUCCESS: status=" + status ); 238 | return; 239 | } 240 | 241 | Log.d( CLASS, "onConnectionStateChange: Status=" + status ); 242 | 243 | switch( newState ) { 244 | case BluetoothProfile.STATE_CONNECTED: 245 | mStatus = Status.CONNECTED; 246 | mGatt = gatt; 247 | Log.d( CLASS, "onConnectionStateChange: newState=STATE_CONNECTED" ); 248 | mGatt.discoverServices(); 249 | break; 250 | case BluetoothProfile.STATE_DISCONNECTED: 251 | mStatus = Status.DISCONNECTED; 252 | Log.d( CLASS, "onConnectionStateChange: newState=STATE_DISCONNECTED" ); 253 | Log.e( "gattCallback", "STATE_DISCONNECTED" ); 254 | break; 255 | default: 256 | Log.w( CLASS, "onConnectionStateChange: newState=" + newState ); 257 | } 258 | 259 | for( BtBridgeListener listener : mListeners ) { 260 | listener.onConnectionStateChange( mStatus ); 261 | } 262 | } 263 | 264 | @Override 265 | // TODO: maybe here we should set status == CONNECTED 266 | public void onServicesDiscovered( BluetoothGatt gatt, int status ) { 267 | if( status != BluetoothGatt.GATT_SUCCESS ) { 268 | Log.e( CLASS, "onServicesDiscovered: Status != SUCCESS: status=" + status ); 269 | return; 270 | } 271 | mGatt = gatt; 272 | 273 | List services = gatt.getServices(); 274 | Log.d( CLASS, "onServicesDiscovered: services=" + services.size() ); 275 | 276 | for( BtBridgeListener listener : mListeners ) { 277 | listener.onServicesDiscovered( services ); 278 | } 279 | } 280 | 281 | @Override 282 | public void onCharacteristicRead( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status ) { 283 | if( status != BluetoothGatt.GATT_SUCCESS ) { 284 | Log.e( CLASS, "onCharacteristicRead: Status != SUCCESS: status=" + status ); 285 | return; 286 | } 287 | mGatt = gatt; 288 | 289 | if( characteristic == null ) { 290 | Log.e( CLASS, "onCharacteristicRead: null characteristic" ); 291 | return; 292 | } 293 | 294 | for( BtBridgeListener listener : mListeners ) { 295 | listener.onCharacteristicRead( characteristic ); 296 | } 297 | } 298 | 299 | @Override 300 | public void onCharacteristicChanged( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic ) { 301 | if( characteristic == null ) { 302 | Log.e( CLASS, "onCharacteristicChanged: null characteristic" ); 303 | return; 304 | } 305 | mGatt = gatt; 306 | 307 | for( BtBridgeListener listener : mListeners ) { 308 | listener.onCharacteristicChanged( characteristic ); 309 | } 310 | } 311 | 312 | @Override 313 | public void onCharacteristicWrite( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status ) { 314 | if( status != BluetoothGatt.GATT_SUCCESS ) { 315 | Log.e( CLASS, "onCharacteristicWrite: Status != SUCCESS: status=" + status ); 316 | return; 317 | } 318 | mGatt = gatt; 319 | 320 | if( characteristic == null ) { 321 | Log.e( CLASS, "onCharacteristicWrite: null characteristic" ); 322 | return; 323 | } 324 | 325 | for( BtBridgeListener listener : mListeners ) { 326 | listener.onCharacteristicWrite( characteristic ); 327 | } 328 | } 329 | 330 | 331 | @Override 332 | public void onDescriptorRead( BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status ) { 333 | if( status != BluetoothGatt.GATT_SUCCESS ) { 334 | Log.e( CLASS, "onDescriptorRead: Status != SUCCESS: status=" + status ); 335 | return; 336 | } 337 | mGatt = gatt; 338 | 339 | if( descriptor == null ) { 340 | Log.e( CLASS, "onDescriptorRead: null descriptor" ); 341 | return; 342 | } 343 | 344 | BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); 345 | for( BtBridgeListener listener : mListeners ) { 346 | listener.onDescriptorRead( characteristic, descriptor ); 347 | } 348 | } 349 | 350 | @Override 351 | public void onDescriptorWrite( BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status ) { 352 | if( status != BluetoothGatt.GATT_SUCCESS ) { 353 | Log.e( CLASS, "onDescriptorWrite: Status != SUCCESS: status=" + status ); 354 | return; 355 | } 356 | mGatt = gatt; 357 | 358 | if( descriptor == null ) { 359 | Log.e( CLASS, "onDescriptorWrite: null descriptor" ); 360 | return; 361 | } 362 | 363 | BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); 364 | for( BtBridgeListener listener : mListeners ) { 365 | listener.onDescriptorWrite( characteristic, descriptor ); 366 | } 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /DebugApp/src/main/java/cl/felipebarriga/android/sony/smartband/api/demo/DebugActivity.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.demo; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.TableLayout; 10 | import android.widget.TableRow; 11 | import android.widget.TextView; 12 | 13 | import java.text.SimpleDateFormat; 14 | import java.util.Date; 15 | import java.util.HashMap; 16 | 17 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BandMode; 18 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtAction; 19 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBand; 20 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBandEvent; 21 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBandListener; 22 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.BtBridge; 23 | 24 | /** 25 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 26 | */ 27 | public class DebugActivity extends Activity implements BtBandListener { 28 | private final String CLASS = getClass().getSimpleName(); 29 | 30 | @Override 31 | public void onAHServiceReadAccData( int[] data ) { 32 | Log.d( CLASS, "onAHServiceReadAccData: data=[" + data[0] + "," + data[1] + "," + data[2] + "]" ); 33 | } 34 | 35 | @Override 36 | public void onAHServiceReadEvent( BtBandEvent event ) { 37 | Log.d( CLASS, "onAHServiceReadEvent: event=" + event ); 38 | } 39 | 40 | @Override 41 | public void onAHServiceReadCurrentTime( int bandSeconds, Date deviceDate, long deltaMs ) { 42 | Log.d( CLASS, "onAHServiceReadCurrentTime: bandSeconds=" + bandSeconds 43 | +" deviceDate=" + deviceDate + " deltaMs=" + deltaMs ); 44 | 45 | SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); 46 | updateUILabel( RowId.CURRENT_TIME, sdf.format( deviceDate ) ); 47 | } 48 | 49 | @Override 50 | public void onAHServiceReadProtocolVersion( int version ) { 51 | Log.d( CLASS, "onAHServiceReadProtocolVersion: version=" + version ); 52 | updateUILabel( RowId.PROTOCOL_VERSION, String.valueOf( version ) ); 53 | } 54 | 55 | @Override 56 | public void onAHServiceReadData( ) { 57 | Log.d( CLASS, "onAHServiceReadData: called." ); 58 | } 59 | 60 | @Override 61 | public void onAHServiceReadMode( BandMode.AccessoryMode mode ) { 62 | Log.d( CLASS, "onAHServiceReadMode: mode=" + mode.name() ); 63 | updateUILabel( RowId.CURRENT_MODE, mode.name() ); 64 | } 65 | 66 | @Override 67 | public void onAHServiceReadUptime( int uptime, Date started ) { 68 | Log.d( CLASS, "onAHServiceReadUptime: started=" + started + " uptime=" + uptime ); 69 | updateUILabel( RowId.UPTIME, String.valueOf( uptime ) ); 70 | } 71 | 72 | @Override 73 | public void onBatteryLevel( int level ) { 74 | Log.d( CLASS, "onBatteryLevel: level=" + level ); 75 | updateUILabel( RowId.BATTERY_LEVEL, String.valueOf( level ) ); 76 | } 77 | 78 | @Override 79 | public void onFirmwareRevision( String rev ) { 80 | updateUILabel( RowId.FIRMWARE_REVISION, rev ); 81 | } 82 | 83 | @Override 84 | public void onSoftwareRevision( String rev ) { 85 | updateUILabel( RowId.SOFTWARE_REVISION, rev ); 86 | } 87 | 88 | @Override 89 | public void onHardwareRevision( String rev ) { 90 | updateUILabel( RowId.HARDWARE_REVISION, rev ); 91 | } 92 | 93 | @Override 94 | public void onManufacturerName( String name ) { 95 | updateUILabel( RowId.MANUFACTURER_NAME, name ); 96 | } 97 | 98 | @Override 99 | public void onAASDeviceVersion( int version ) { 100 | updateUILabel( RowId.AAS_VERSION, String.valueOf( version ) ); 101 | } 102 | 103 | @Override 104 | public void onAASDeviceSmartLink( int smartLink ) { 105 | updateUILabel( RowId.AAS_SMART_LINK, String.valueOf( smartLink ) ); 106 | } 107 | 108 | @Override 109 | public void onAASDeviceProductId( String productId ) { 110 | updateUILabel( RowId.AAS_PRODUCT_ID, productId ); 111 | } 112 | 113 | @Override 114 | public void onAASDeviceData( String data ) { 115 | updateUILabel( RowId.AAS_DATA, data ); 116 | } 117 | 118 | @Override 119 | public void onGADeviceName( String name ) { 120 | updateUILabel( RowId.GA_DEVICE_NAME, name ); 121 | } 122 | 123 | @Override 124 | public void onConnectionStateChange( final BtBridge.Status status ) { 125 | Log.i( CLASS, "onConnectionStateChange: status=" + status.name() ); 126 | updateUILabel( RowId.STATUS, status.name() ); 127 | if( status == BtBridge.Status.CONNECTED ) { 128 | updateUIButton( RowId.STATUS, true, "Disconnect" ); 129 | } else if( status == BtBridge.Status.DISCONNECTED ) { 130 | updateUIButton( RowId.STATUS, true, "Connect" ); 131 | } else { 132 | updateUIButton( RowId.STATUS, false, "Disconnect" ); 133 | } 134 | } 135 | 136 | @Override 137 | public void onServicesDiscovered() { 138 | Log.i( CLASS, "onServicesDiscovered: called" ); 139 | } 140 | 141 | public enum RowId { 142 | ENABLE_EVENT_NOTIFICATIONS, 143 | ENABLE_DATA_NOTIFICATIONS, 144 | ENABLE_ACC_NOTIFICATIONS, 145 | ENABLE_DEBUG_NOTIFICATIONS, 146 | SEND_CURRENT_TIME, 147 | STATUS, 148 | UPTIME, 149 | CURRENT_MODE, 150 | BATTERY_LEVEL, 151 | CURRENT_TIME, 152 | PROTOCOL_VERSION, 153 | FIRMWARE_REVISION, 154 | SOFTWARE_REVISION, 155 | HARDWARE_REVISION, 156 | MANUFACTURER_NAME, 157 | AAS_VERSION, 158 | AAS_SMART_LINK, 159 | AAS_PRODUCT_ID, 160 | AAS_DATA, 161 | GA_DEVICE_NAME 162 | } 163 | 164 | public static final HashMap mRowActionMap = new HashMap<>( ); 165 | 166 | static { 167 | mRowActionMap.put( RowId.BATTERY_LEVEL , BtAction.Action.REQUEST_BATTERY_LEVEL ); 168 | 169 | mRowActionMap.put( RowId.UPTIME , BtAction.Action.REQUEST_UPTIME ); 170 | mRowActionMap.put( RowId.CURRENT_MODE , BtAction.Action.REQUEST_MODE ); 171 | mRowActionMap.put( RowId.CURRENT_TIME , BtAction.Action.REQUEST_CURRENT_TIME ); 172 | mRowActionMap.put( RowId.PROTOCOL_VERSION , BtAction.Action.REQUEST_PROTOCOL_VERSION ); 173 | 174 | mRowActionMap.put( RowId.FIRMWARE_REVISION, BtAction.Action.REQUEST_FIRMWARE_REVISION ); 175 | mRowActionMap.put( RowId.SOFTWARE_REVISION, BtAction.Action.REQUEST_SOFTWARE_REVISION ); 176 | mRowActionMap.put( RowId.HARDWARE_REVISION, BtAction.Action.REQUEST_HARDWARE_REVISION ); 177 | mRowActionMap.put( RowId.MANUFACTURER_NAME, BtAction.Action.REQUEST_MANUFACTURER_NAME ); 178 | 179 | mRowActionMap.put( RowId.AAS_VERSION , BtAction.Action.REQUEST_AAS_VERSION ); 180 | mRowActionMap.put( RowId.AAS_SMART_LINK , BtAction.Action.REQUEST_AAS_SMART_LINK ); 181 | mRowActionMap.put( RowId.AAS_PRODUCT_ID , BtAction.Action.REQUEST_AAS_PRODUCT_ID ); 182 | mRowActionMap.put( RowId.AAS_DATA , BtAction.Action.REQUEST_AAS_DEVICE_DATA ); 183 | 184 | mRowActionMap.put( RowId.GA_DEVICE_NAME , BtAction.Action.REQUEST_GA_DEVICE_NAME ); 185 | } 186 | 187 | private void updateUILabel( final RowId rowId, final String textValue ) { 188 | mHandler.post(new Runnable() { 189 | @Override 190 | public void run() { 191 | TextView textView = mRowIdValueTextViewMap.get( rowId ); 192 | if( textView == null ) { 193 | Log.e( CLASS, "updateUILabel: Error, view not found. rowId=" + rowId.name() ); 194 | return; 195 | } 196 | 197 | textView.setText( textValue ); 198 | } 199 | }); 200 | } 201 | 202 | private void updateUIButton( final RowId rowId, final boolean enabled, final String textValue ) { 203 | mHandler.post(new Runnable() { 204 | @Override 205 | public void run() { 206 | Button btn = mRowIdButtonMap.get( rowId ); 207 | if( btn == null ) { 208 | Log.e( CLASS, "updateUIButton: Error, btn not found. rowId=" + rowId.name() ); 209 | return; 210 | } 211 | btn.setEnabled( enabled ); 212 | btn.setText( textValue ); 213 | } 214 | }); 215 | } 216 | 217 | private static HashMap mRowIdButtonMap = new HashMap<>( ); 218 | private static HashMap mRowIdValueTextViewMap = new HashMap<>( ); 219 | private static HashMap mViewRowIdMap = new HashMap<>( ); 220 | 221 | private TableRow createRow( RowId rowId, String label, String defaultValue, 222 | String btnText, View.OnClickListener btnListener ) { 223 | 224 | TableRow tb = new TableRow( this ); 225 | TextView labelText = new TextView( this ); 226 | TextView valueText = new TextView( this ); 227 | Button btn = new Button( this ); 228 | 229 | labelText.setText( label ); 230 | valueText.setText( defaultValue ); 231 | btn.setText( btnText ); 232 | 233 | btn.setOnClickListener( btnListener ); 234 | 235 | tb.addView( labelText ); 236 | tb.addView( valueText ); 237 | tb.addView( btn ); 238 | 239 | mRowIdButtonMap.put( rowId, btn ); 240 | mRowIdValueTextViewMap.put( rowId, valueText ); 241 | mViewRowIdMap.put( btn, rowId ); 242 | 243 | return tb; 244 | } 245 | 246 | private View.OnClickListener mClickListener = new View.OnClickListener() { 247 | @Override 248 | public void onClick( View v ) { 249 | RowId rowId = mViewRowIdMap.get( v ); 250 | TextView valueTextView = mRowIdValueTextViewMap.get( rowId ); 251 | if( rowId == RowId.STATUS ) { 252 | switch( mBtBand.getStatus() ) { 253 | case DISCONNECTED: 254 | try { 255 | mBtBand.connect(); 256 | } catch( Exception e ) { 257 | e.printStackTrace(); 258 | } 259 | break; 260 | 261 | case CONNECTED: 262 | mBtBand.disconnect(); 263 | break; 264 | 265 | case CONNECTING: 266 | break; 267 | } 268 | valueTextView.setText( mBtBand.getStatus().name() ); 269 | return; 270 | } 271 | 272 | if( !mBtBand.getStatus().equals( BtBridge.Status.CONNECTED ) ) { 273 | Log.e( CLASS, "onClick: " + rowId.name() + " not connected" ); 274 | return; 275 | } 276 | 277 | if( rowId == RowId.SEND_CURRENT_TIME ) { 278 | mBtBand.syncDeviceTime(); 279 | return; 280 | } 281 | 282 | if( rowId == RowId.ENABLE_EVENT_NOTIFICATIONS ) { 283 | if( mBtBand.isEventNotificationsEnabled() ) { 284 | mBtBand.addRequest( BtAction.Action.DISABLE_EVENT_NOTIFICATIONS ); 285 | valueTextView.setText( "Disable" ); 286 | } else { 287 | mBtBand.addRequest( BtAction.Action.ENABLE_EVENT_NOTIFICATIONS ); 288 | valueTextView.setText( "Enable" ); 289 | } 290 | return; 291 | } 292 | 293 | if( rowId == RowId.ENABLE_DATA_NOTIFICATIONS ) { 294 | if( mBtBand.isDataNotificationsEnabled() ) { 295 | mBtBand.addRequest( BtAction.Action.DISABLE_DATA_NOTIFICATIONS ); 296 | valueTextView.setText( "Disable" ); 297 | } else { 298 | mBtBand.addRequest( BtAction.Action.ENABLE_DATA_NOTIFICATIONS ); 299 | valueTextView.setText( "Enable" ); 300 | } 301 | return; 302 | } 303 | 304 | if( rowId == RowId.ENABLE_ACC_NOTIFICATIONS ) { 305 | if( mBtBand.isAccNotificationsEnabled() ) { 306 | mBtBand.addRequest( BtAction.Action.DISABLE_ACC_NOTIFICATIONS ); 307 | valueTextView.setText( "Disable" ); 308 | } else { 309 | mBtBand.addRequest( BtAction.Action.ENABLE_ACC_NOTIFICATIONS ); 310 | valueTextView.setText( "Enable" ); 311 | } 312 | return; 313 | } 314 | 315 | if( rowId == RowId.ENABLE_DEBUG_NOTIFICATIONS ) { 316 | if( mBtBand.isDebugNotificationsEnabled() ) { 317 | mBtBand.addRequest( BtAction.Action.DISABLE_DEBUG_NOTIFICATIONS ); 318 | valueTextView.setText( "Disable" ); 319 | } else { 320 | mBtBand.addRequest( BtAction.Action.ENABLE_DEBUG_NOTIFICATIONS ); 321 | valueTextView.setText( "Enable" ); 322 | } 323 | return; 324 | } 325 | 326 | BtAction.Action action = mRowActionMap.get( rowId ); 327 | if( rowId != null ) { 328 | mBtBand.addRequest( action ); 329 | return; 330 | } 331 | 332 | switch( rowId ) { 333 | 334 | default: 335 | Log.e( CLASS, "onClick: unknown rowId: " + rowId.name() ); 336 | break; 337 | } 338 | 339 | } 340 | }; 341 | 342 | private BtBand mBtBand; 343 | private Handler mHandler; 344 | 345 | private void uiPopulateRows( TableLayout tl ) { 346 | tl.addView( createRow( RowId.STATUS , "Status:" , "-", "Connect", mClickListener ) ); 347 | tl.addView( createRow( RowId.UPTIME , "Uptime:" , "-", "Update" , mClickListener ) ); 348 | tl.addView( createRow( RowId.CURRENT_MODE , "Current Mode:" , "-", "Update" , mClickListener ) ); 349 | tl.addView( createRow( RowId.PROTOCOL_VERSION, "Protocol Version:", "-", "Update" , mClickListener ) ); 350 | tl.addView( createRow( RowId.CURRENT_TIME , "Current Time:" , "-", "Update" , mClickListener ) ); 351 | 352 | tl.addView( createRow( RowId.BATTERY_LEVEL, "Battery Level:", "-", "Update" , mClickListener ) ); 353 | 354 | tl.addView( createRow( RowId.FIRMWARE_REVISION, "Firmware Rev.:", "-", "Update", mClickListener ) ); 355 | tl.addView( createRow( RowId.HARDWARE_REVISION, "Hardware Rev.:", "-", "Update", mClickListener ) ); 356 | tl.addView( createRow( RowId.SOFTWARE_REVISION, "Software Rev.:", "-", "Update", mClickListener ) ); 357 | tl.addView( createRow( RowId.MANUFACTURER_NAME, "Manufacturer:" , "-", "Update", mClickListener ) ); 358 | 359 | tl.addView( createRow( RowId.AAS_VERSION , "AAS Version:" , "-", "Update", mClickListener ) ); 360 | tl.addView( createRow( RowId.AAS_SMART_LINK, "AAS SmartLink:", "-", "Update", mClickListener ) ); 361 | tl.addView( createRow( RowId.AAS_PRODUCT_ID, "AAS ProductId:", "-", "Update", mClickListener ) ); 362 | tl.addView( createRow( RowId.AAS_DATA , "AAS Data:" , "-", "Update", mClickListener ) ); 363 | 364 | tl.addView( createRow( RowId.GA_DEVICE_NAME, "GA Device Name:", "-", "Update", mClickListener ) ); 365 | 366 | tl.addView( createRow( RowId.SEND_CURRENT_TIME, "Send Current Time:", "-", "Update", mClickListener ) ); 367 | 368 | tl.addView( createRow( RowId.ENABLE_EVENT_NOTIFICATIONS, "Event Notifications:" , "-", "Enable", mClickListener ) ); 369 | tl.addView( createRow( RowId.ENABLE_DATA_NOTIFICATIONS , "Data Notifications:" , "-", "Enable", mClickListener ) ); 370 | tl.addView( createRow( RowId.ENABLE_ACC_NOTIFICATIONS , "Accelerometer Notif.:", "-", "Enable", mClickListener ) ); 371 | tl.addView( createRow( RowId.ENABLE_DEBUG_NOTIFICATIONS, "Debug Notifications:" , "-", "Enable", mClickListener ) ); 372 | } 373 | 374 | private void uiAddModeRow(TableLayout tl ) { 375 | TableRow tb = new TableRow( this ); 376 | TextView labelText = new TextView( this ); 377 | 378 | Button btnDay = new Button( this ); 379 | Button btnNight = new Button( this ); 380 | Button btnMedia = new Button( this ); 381 | Button btnFirmware = new Button( this ); 382 | 383 | labelText.setText( "Mode:" ); 384 | 385 | btnDay.setText( "Day" ); 386 | btnNight.setText( "Night" ); 387 | btnMedia.setText( "Media" ); 388 | btnFirmware.setText( "Firmware" ); 389 | 390 | btnDay.setOnClickListener( new View.OnClickListener() { 391 | @Override 392 | public void onClick( View v ) { 393 | mBtBand.addRequest( BtAction.Action.SET_MODE, BandMode.getInt( BandMode.AccessoryMode.DAY ) ); 394 | } 395 | } ); 396 | 397 | btnNight.setOnClickListener( new View.OnClickListener() { 398 | @Override 399 | public void onClick( View v ) { 400 | mBtBand.addRequest( BtAction.Action.SET_MODE, BandMode.getInt( BandMode.AccessoryMode.NIGHT ) ); 401 | } 402 | } ); 403 | 404 | btnMedia.setOnClickListener( new View.OnClickListener() { 405 | @Override 406 | public void onClick( View v ) { 407 | mBtBand.addRequest( BtAction.Action.SET_MODE, BandMode.getInt( BandMode.AccessoryMode.MEDIA ) ); 408 | } 409 | } ); 410 | 411 | btnFirmware.setOnClickListener( new View.OnClickListener() { 412 | @Override 413 | public void onClick( View v ) { 414 | mBtBand.addRequest( BtAction.Action.SET_MODE, BandMode.getInt( BandMode.AccessoryMode.FIRMWARE_UPDATE ) ); 415 | } 416 | } ); 417 | 418 | tb.addView( labelText ); 419 | tb.addView( btnDay ); 420 | tb.addView( btnNight ); 421 | tb.addView( btnMedia ); 422 | tb.addView( btnFirmware ); 423 | tl.addView( tb ); 424 | } 425 | 426 | @Override 427 | protected void onCreate( Bundle savedInstanceState ) { 428 | super.onCreate( savedInstanceState ); 429 | Log.v( CLASS, "onCreate: called." ); 430 | 431 | mHandler = new Handler( ); 432 | mBtBand = new BtBand( this ); 433 | mBtBand.addListener( this ); 434 | setContentView( R.layout.activity_debug ); 435 | 436 | TableLayout tl = ( TableLayout ) findViewById( R.id.debug_table_layout ); 437 | uiPopulateRows( tl ); 438 | uiAddModeRow( tl ); 439 | } 440 | 441 | @Override 442 | protected void onStart() { 443 | super.onStart(); 444 | Log.v( CLASS, "onStart: called." ); 445 | } 446 | 447 | @Override 448 | protected void onResume() { 449 | super.onResume(); 450 | Log.v( CLASS, "onResume: called." ); 451 | } 452 | 453 | @Override 454 | protected void onPause() { 455 | super.onPause(); 456 | Log.v( CLASS, "onPause: called." ); 457 | } 458 | 459 | @Override 460 | protected void onRestart() { 461 | super.onRestart(); 462 | Log.v( CLASS, "onRestart: called." ); 463 | } 464 | 465 | @Override 466 | protected void onStop() { 467 | super.onStop(); 468 | Log.v( CLASS, "onStop: called." ); 469 | } 470 | 471 | @Override 472 | protected void onDestroy() { 473 | super.onDestroy(); 474 | Log.v( CLASS, "onDestroy: called." ); 475 | mBtBand.disconnect(); 476 | } 477 | 478 | 479 | } 480 | -------------------------------------------------------------------------------- /SonySmartBandOpenAPI/src/main/java/cl/felipebarriga/android/sony/smartband/api/bluetooth/BtBand.java: -------------------------------------------------------------------------------- 1 | package cl.felipebarriga.android.sony.smartband.api.bluetooth; 2 | 3 | import android.bluetooth.BluetoothGattCharacteristic; 4 | import android.bluetooth.BluetoothGattDescriptor; 5 | import android.bluetooth.BluetoothGattService; 6 | import android.content.Context; 7 | import android.util.Log; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Calendar; 11 | import java.util.Date; 12 | import java.util.List; 13 | import java.util.Queue; 14 | import java.util.UUID; 15 | import java.util.concurrent.LinkedBlockingQueue; 16 | 17 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.AADeviceServiceProfile; 18 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.AHServiceProfile; 19 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.BaseProfile; 20 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.BatteryProfile; 21 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.BleConstants; 22 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.DeviceInformationProfile; 23 | import cl.felipebarriga.android.sony.smartband.api.bluetooth.profiles.GenericAccessProfile; 24 | 25 | /** 26 | * Copyright (c) 2015 Felipe Barriga Richards. See Copyright Notice in LICENSE file. 27 | */ 28 | public class BtBand implements BtBridgeListener { 29 | 30 | private final String CLASS = getClass().getSimpleName(); 31 | 32 | private BtBridge mBtBridge; 33 | private Context mContext; 34 | 35 | ArrayList mListeners = new ArrayList<>(); 36 | 37 | private boolean mEventNotificationsEnabled; 38 | private boolean mDataNotificationsEnabled; 39 | private boolean mDebugNotificationsEnabled; 40 | private boolean mAccNotificationsEnabled; 41 | 42 | public boolean isEventNotificationsEnabled() { 43 | return mEventNotificationsEnabled; 44 | } 45 | 46 | public boolean isDataNotificationsEnabled() { 47 | return mDataNotificationsEnabled; 48 | } 49 | 50 | public boolean isDebugNotificationsEnabled() { 51 | return mDebugNotificationsEnabled; 52 | } 53 | 54 | public boolean isAccNotificationsEnabled() { 55 | return mAccNotificationsEnabled; 56 | } 57 | 58 | public BtBridge.Status getStatus() { 59 | return mBtBridge.getStatus(); 60 | } 61 | 62 | public void addListener( BtBandListener listener ) { 63 | if( mListeners.contains( listener ) ) { 64 | Log.w( CLASS, "setOnBtBandListener: Listener already registered" ); 65 | } else { 66 | mListeners.add( listener ); 67 | } 68 | } 69 | 70 | public BtBand( Context context ) { 71 | mEventNotificationsEnabled = false; 72 | mDataNotificationsEnabled = false; 73 | mDebugNotificationsEnabled = false; 74 | mAccNotificationsEnabled = false; 75 | 76 | mContext = context; 77 | mBtBridge = new BtBridge( mContext ); 78 | mBtBridge.addListener( this ); 79 | } 80 | 81 | private DescriptorInfo getDescriptorInfo( BluetoothGattDescriptor descriptor ) { 82 | BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); 83 | return getDescriptorInfo( characteristic.getService().getUuid(), characteristic.getUuid(), descriptor.getUuid() ); 84 | } 85 | 86 | private DescriptorInfo getDescriptorInfo( UUID serviceUuid, UUID characteristicUuid, UUID descriptorUuid ) { 87 | BaseProfile serviceProfile = Profiles.getService( serviceUuid ); 88 | return new DescriptorInfo( 89 | serviceProfile.getClass().getSimpleName(), 90 | serviceProfile.getUuidName( characteristicUuid ), 91 | BleConstants.getUuidName( descriptorUuid ) 92 | ); 93 | } 94 | 95 | private CharacteristicInfo getCharacteristicInfo( BluetoothGattCharacteristic characteristic ) { 96 | return getCharacteristicInfo( characteristic.getService().getUuid(), characteristic.getUuid() ); 97 | } 98 | 99 | private CharacteristicInfo getCharacteristicInfo( UUID serviceUuid, UUID characteristicUuid ) { 100 | BaseProfile serviceProfile = Profiles.getService( serviceUuid ); 101 | if( serviceProfile == null ) { 102 | Log.e( CLASS, "getCharacteristicInfo: service not found. serviceUuid=" + serviceUuid ); 103 | return null; 104 | } 105 | 106 | return new CharacteristicInfo( serviceProfile.getClass().getSimpleName(), serviceProfile.getUuidName( characteristicUuid ) ); 107 | } 108 | 109 | private BluetoothGattCharacteristic readGatt( UUID serviceUuid, UUID characteristicUuid ) { 110 | Log.d( CLASS, "readGatt: " + getCharacteristicInfo( serviceUuid, characteristicUuid ) ); 111 | 112 | BluetoothGattCharacteristic characteristic = mBtBridge.getCharacteristic( serviceUuid, characteristicUuid ); 113 | if( characteristic == null ) { 114 | Log.e( CLASS, "readGatt: characteristic not found" ); 115 | return null; 116 | } 117 | return characteristic; 118 | } 119 | 120 | private void updateNotification( BtAction action, boolean enable ) { 121 | UUID serviceUuid = action.getServiceUUID(); 122 | UUID characteristicUuid = action.getCharacteristicUUID(); 123 | UUID descriptorUuid = action.getDescriptorUUID(); 124 | Log.d( CLASS, "updateNotification: enable=" + enable + " " + getCharacteristicInfo( serviceUuid, characteristicUuid ) ); 125 | 126 | BluetoothGattCharacteristic characteristic = mBtBridge.getCharacteristic( serviceUuid, characteristicUuid ); 127 | if( characteristic == null ) { 128 | Log.e( CLASS, "updateNotification: characteristic not found" ); 129 | return; 130 | } 131 | 132 | BluetoothGattDescriptor descriptor = characteristic.getDescriptor( descriptorUuid ); 133 | if( descriptor == null ) { 134 | Log.e( CLASS, "updateNotification: descriptor not found" ); 135 | return; 136 | } 137 | 138 | mBtBridge.setCharacteristicNotification( characteristic, enable ); 139 | if( enable ) { 140 | descriptor.setValue( BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE ); 141 | } else { 142 | descriptor.setValue( BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE ); 143 | } 144 | Log.d( CLASS, "updateNotification: " + getDescriptorInfo( descriptor ) ); 145 | 146 | if( !mBtBridge.writeDescriptor( descriptor ) ) { 147 | Log.e( CLASS, "updateNotification: success = false " + getDescriptorInfo( descriptor ) ); 148 | } 149 | } 150 | 151 | private BluetoothGattCharacteristic setValue( UUID serviceUuid, UUID characteristicUuid, int value, int format, int offset ) { 152 | BluetoothGattCharacteristic characteristic = mBtBridge.getCharacteristic( serviceUuid, characteristicUuid ); 153 | if( characteristic == null ) { 154 | Log.e( CLASS, "setValue: characteristic not found" ); 155 | return null; 156 | } 157 | 158 | if( !characteristic.setValue( value, format, offset ) ) { 159 | Log.e( CLASS, "setValue: error setting value" ); 160 | return null; 161 | } 162 | 163 | return characteristic; 164 | } 165 | 166 | private Queue mRequestQueue = new LinkedBlockingQueue<>(); 167 | 168 | public void addRequest( BtAction.Action action ) { 169 | mRequestQueue.add( new BtAction( action ) ); 170 | processQueue(); 171 | } 172 | 173 | public void addRequest( BtAction.Action action, int parameter ) { 174 | mRequestQueue.add( new BtAction( action ).setParameter( parameter ) ); 175 | processQueue(); 176 | } 177 | 178 | public void syncDeviceTime() { 179 | long now = Calendar.getInstance().getTimeInMillis(); 180 | setDeviceTime( AHServiceProfile.convertTimestampToBandSeconds( now ) ); 181 | } 182 | 183 | /** 184 | * Set the device time. 185 | * @param bandTimestamp Number of seconds since 2013 186 | */ 187 | public void setDeviceTime( int bandTimestamp ) { 188 | Date date = AHServiceProfile.convertBandSecondsToDate( bandTimestamp ); 189 | Log.d( CLASS, "sendCurrentTime: called. bandTimestamp=" + bandTimestamp + " date=" + date ); 190 | mRequestQueue.add( new BtAction( BtAction.Action.SET_CURRENT_TIME ).setParameter( bandTimestamp ) ); 191 | } 192 | 193 | private void processQueue() { 194 | Log.d( CLASS, "processQueue: called." ); 195 | BtAction action = mRequestQueue.poll(); 196 | if( action == null ) { 197 | Log.d( CLASS, "processQueue: the queue is empty" ); 198 | return; 199 | } 200 | 201 | executeAction( action ); 202 | } 203 | 204 | private void executeAction( BtAction action ) { 205 | BtAction.Type type = action.getType(); 206 | Log.i( CLASS, "executeAction: action=" + action.mAction.name() + " type=" + type.name() ); 207 | 208 | if( type.equals( BtAction.Type.READ_CHAR ) ) { 209 | mBtBridge.readCharacteristic( readGatt( action.getServiceUUID(), action.getCharacteristicUUID() ) ); 210 | } else if( type.equals( BtAction.Type.WRITE_CHAR ) ) { 211 | mBtBridge.writeCharacteristic( 212 | setValue( 213 | action.getServiceUUID(), 214 | action.getCharacteristicUUID(), 215 | action.mParam, 216 | action.getFormat(), 217 | 0 218 | ) 219 | ); 220 | } else if( type.equals( BtAction.Type.ENABLE_NOTIFICATION ) ) { 221 | updateNotification( action, true ); 222 | } else if( type.equals( BtAction.Type.DISABLE_NOTIFICATION ) ) { 223 | updateNotification( action, false ); 224 | } else { 225 | Log.e( CLASS, "executeAction: don't know how to handle: action=" + action.mAction.name() ); 226 | } 227 | } 228 | 229 | public void onConnectionStateChange( BtBridge.Status newStatus ) { 230 | if( newStatus.equals( BtBridge.Status.CONNECTED ) ) { 231 | mBtBridge.discoverServices(); 232 | } 233 | 234 | for( BtBandListener listener : mListeners ) { 235 | listener.onConnectionStateChange( newStatus ); 236 | } 237 | } 238 | 239 | public void onServicesDiscovered( List services ) { 240 | Log.d( CLASS, "onServicesDiscovered: services=" + services.size() ); 241 | 242 | for( BluetoothGattService service : services ) { 243 | BaseProfile serviceProfile = Profiles.getService( service.getUuid() ); 244 | if( serviceProfile == null ) { 245 | Log.w( CLASS, "- service=unknown uuid=" + service.getUuid() ); 246 | continue; 247 | } 248 | Log.d( CLASS, "-> service name=" + serviceProfile.getClass().getSimpleName() + " (" + service.getUuid() + ")" ); 249 | List chars = service.getCharacteristics(); 250 | for( BluetoothGattCharacteristic c : chars ) { 251 | Log.d( CLASS, "--> characteristic name=" + serviceProfile.getUuidName( c.getUuid() ) + " (" + c.getUuid() + ")" ); 252 | List descriptors = c.getDescriptors(); 253 | for( BluetoothGattDescriptor d : descriptors ) { 254 | Log.d( CLASS, "---> descriptor name=" + BleConstants.getUuidName( d.getUuid() ) + " (" + d.getUuid() + ")" ); 255 | } 256 | } 257 | } 258 | 259 | for( BtBandListener listener : mListeners ) { 260 | listener.onServicesDiscovered( ); 261 | } 262 | } 263 | 264 | private void handleDeviceInfoFirmwareRevision( BluetoothGattCharacteristic characteristic ) { 265 | String revision = characteristic.getStringValue( 0 ); 266 | for( BtBandListener listener : mListeners ) { 267 | listener.onFirmwareRevision( revision ); 268 | } 269 | } 270 | 271 | private void handleDeviceInfoSoftwareRevision( BluetoothGattCharacteristic characteristic ) { 272 | String revision = characteristic.getStringValue( 0 ); 273 | for( BtBandListener listener : mListeners ) { 274 | listener.onSoftwareRevision( revision ); 275 | } 276 | } 277 | 278 | private void handleDeviceInfoHardwareRevision( BluetoothGattCharacteristic characteristic ) { 279 | String revision = characteristic.getStringValue( 0 ); 280 | for( BtBandListener listener : mListeners ) { 281 | listener.onHardwareRevision( revision ); 282 | } 283 | } 284 | 285 | private void handleDeviceInfoManufacturerName( BluetoothGattCharacteristic characteristic ) { 286 | String name = characteristic.getStringValue( 0 ); 287 | for( BtBandListener listener : mListeners ) { 288 | listener.onManufacturerName( name ); 289 | } 290 | } 291 | 292 | private void handleDeviceInfoCallback( BluetoothGattCharacteristic characteristic ) { 293 | UUID uuid = characteristic.getUuid(); 294 | 295 | if( uuid.equals( DeviceInformationProfile.FIRMWARE_REVISION_UUID ) ) { 296 | handleDeviceInfoFirmwareRevision( characteristic ); 297 | } else if( uuid.equals( DeviceInformationProfile.SOFTWARE_REVISION_UUID) ) { 298 | handleDeviceInfoSoftwareRevision( characteristic ); 299 | } else if( uuid.equals( DeviceInformationProfile.HARDWARE_REVISION_UUID) ) { 300 | handleDeviceInfoHardwareRevision( characteristic ); 301 | } else if( uuid.equals( DeviceInformationProfile.MANUFACTURER_NAME_UUID) ) { 302 | handleDeviceInfoManufacturerName( characteristic ); 303 | } else { 304 | Log.e( CLASS, "handleDeviceInfoCallback: unknown response" ); 305 | } 306 | } 307 | 308 | private void handleAASDeviceVersion( BluetoothGattCharacteristic characteristic ) { 309 | int version = AADeviceServiceProfile.readDeviceAASVersion( characteristic ); 310 | for( BtBandListener listener : mListeners ) { 311 | listener.onAASDeviceVersion( version ); 312 | } 313 | } 314 | 315 | private void handleAASDeviceSmartLink( BluetoothGattCharacteristic characteristic ) { 316 | int smartLink = AADeviceServiceProfile.readDeviceSmartLinkService( characteristic ); 317 | for( BtBandListener listener : mListeners ) { 318 | listener.onAASDeviceSmartLink( smartLink ); 319 | } 320 | } 321 | 322 | private void handleAASDeviceProductId( BluetoothGattCharacteristic characteristic ) { 323 | String productId = characteristic.getStringValue( 0 ); 324 | for( BtBandListener listener : mListeners ) { 325 | listener.onAASDeviceProductId( productId ); 326 | } 327 | } 328 | 329 | private void handleAASDeviceData( BluetoothGattCharacteristic characteristic ) { 330 | String data = characteristic.getStringValue( 0 ); 331 | for( BtBandListener listener : mListeners ) { 332 | listener.onAASDeviceData( data ); 333 | } 334 | } 335 | 336 | private void handleAADeviceServiceCallback( BluetoothGattCharacteristic characteristic ) { 337 | UUID uuid = characteristic.getUuid(); 338 | 339 | if( uuid.equals( AADeviceServiceProfile.VERSION_UUID ) ) { 340 | handleAASDeviceVersion( characteristic ); 341 | } else if( uuid.equals( AADeviceServiceProfile.SMART_LINK_SERVICE_UUID ) ) { 342 | handleAASDeviceSmartLink( characteristic ); 343 | } else if( uuid.equals( AADeviceServiceProfile.PRODUCT_ID_UUID ) ) { 344 | handleAASDeviceProductId( characteristic ); 345 | } else if( uuid.equals( AADeviceServiceProfile.DATA_UUID ) ) { 346 | handleAASDeviceData( characteristic ); 347 | } else { 348 | Log.e( CLASS, "handleAADeviceServiceCallback: unknown response" ); 349 | } 350 | } 351 | 352 | private void handleGADeviceName( BluetoothGattCharacteristic characteristic ) { 353 | String name = characteristic.getStringValue( 0 ); 354 | for( BtBandListener listener : mListeners ) { 355 | listener.onGADeviceName( name ); 356 | } 357 | } 358 | 359 | private void handleGenericAccessCallback( BluetoothGattCharacteristic characteristic ) { 360 | UUID uuid = characteristic.getUuid(); 361 | 362 | if( uuid.equals( GenericAccessProfile.DEVICE_NAME_UUID ) ) { 363 | handleGADeviceName( characteristic ); 364 | } else { 365 | Log.e( CLASS, "handleGenericAccessCallback: unknown response" ); 366 | } 367 | } 368 | 369 | private void handleBatteryReadLevel( BluetoothGattCharacteristic characteristic ) { 370 | int level = BatteryProfile.readBatteryLevel( characteristic ); 371 | for( BtBandListener listener : mListeners ) { 372 | listener.onBatteryLevel( level ); 373 | } 374 | } 375 | 376 | private void handleBatteryCallback( BluetoothGattCharacteristic characteristic ) { 377 | UUID uuid = characteristic.getUuid(); 378 | if( uuid .equals( BatteryProfile.BATTERY_LEVEL_UUID ) ) { 379 | handleBatteryReadLevel( characteristic ); 380 | } 381 | } 382 | 383 | private void handleAHServiceReadMode( BluetoothGattCharacteristic characteristic ) { 384 | BandMode.AccessoryMode mode = AHServiceProfile.readMode( characteristic ); 385 | for( BtBandListener listener : mListeners ) { 386 | listener.onAHServiceReadMode( mode ); 387 | } 388 | } 389 | 390 | private void handleAHServiceReadProtocolVersion( BluetoothGattCharacteristic characteristic ) { 391 | int version = AHServiceProfile.readProtocolVersion( characteristic ); 392 | for( BtBandListener listener : mListeners ) { 393 | listener.onAHServiceReadProtocolVersion( version ); 394 | } 395 | } 396 | 397 | private void handleAHServiceReadData( BluetoothGattCharacteristic characteristic ) { 398 | for( BtBandListener listener : mListeners ) { 399 | listener.onAHServiceReadData( ); 400 | } 401 | } 402 | 403 | private void handleAHServiceReadCurrentTime( BluetoothGattCharacteristic characteristic ) { 404 | int bandSeconds = AHServiceProfile.readCurrentTime( characteristic ); 405 | Date deviceDate = AHServiceProfile.convertBandSecondsToDate( bandSeconds ); 406 | long deltaMs = deviceDate.getTime() - System.currentTimeMillis(); 407 | for( BtBandListener listener : mListeners ) { 408 | listener.onAHServiceReadCurrentTime( bandSeconds, deviceDate, deltaMs ); 409 | } 410 | } 411 | 412 | private void handleAHServiceReadUptime( BluetoothGattCharacteristic characteristic ) { 413 | int uptime = AHServiceProfile.readUptime( characteristic ); 414 | Date started = new Date( System.currentTimeMillis() - uptime * 1000 ); 415 | for( BtBandListener listener : mListeners ) { 416 | listener.onAHServiceReadUptime( uptime, started ); 417 | } 418 | } 419 | 420 | private void handleAHServiceReadEvent( BluetoothGattCharacteristic characteristic ) { 421 | BtBandEvent btBandEvent = AHServiceProfile.readEvent( characteristic ); 422 | for( BtBandListener listener : mListeners ) { 423 | listener.onAHServiceReadEvent( btBandEvent ); 424 | } 425 | } 426 | 427 | private void handleAHServiceReadAccData( BluetoothGattCharacteristic characteristic ) { 428 | int[] data = AHServiceProfile.readAccData( characteristic ); 429 | for( BtBandListener listener : mListeners ) { 430 | listener.onAHServiceReadAccData( data ); 431 | } 432 | } 433 | 434 | private void handleAHServiceCallback( BluetoothGattCharacteristic characteristic ) { 435 | UUID uuid = characteristic.getUuid(); 436 | 437 | if( uuid.equals( AHServiceProfile.MODE_UUID ) ) { 438 | handleAHServiceReadMode( characteristic ); 439 | } else if( uuid.equals( AHServiceProfile.PROTOCOL_VERSION_UUID ) ) { 440 | handleAHServiceReadProtocolVersion( characteristic ); 441 | } else if( uuid.equals( AHServiceProfile.DATA_UUID ) ) { 442 | handleAHServiceReadData( characteristic ); 443 | } else if( uuid.equals( AHServiceProfile.CURRENT_TIME_UUID ) ) { 444 | handleAHServiceReadCurrentTime( characteristic ); 445 | } else if( uuid.equals( AHServiceProfile.DEBUG_UUID ) ) { 446 | handleAHServiceReadUptime( characteristic ); 447 | } else if( uuid.equals( AHServiceProfile.EVENT_UUID ) ) { 448 | handleAHServiceReadEvent( characteristic ); 449 | } else if( uuid.equals( AHServiceProfile.ACCEL_DATA_UUID ) ) { 450 | handleAHServiceReadAccData( characteristic ); 451 | } else { 452 | Log.e( CLASS, "handleOnCharacteristicRead: unknown response" ); 453 | } 454 | } 455 | 456 | public void onCharacteristicRead( BluetoothGattCharacteristic characteristic ) { 457 | BluetoothGattService service = characteristic.getService(); 458 | BaseProfile serviceProfile = Profiles.getService( service.getUuid() ); 459 | 460 | Log.d( CLASS, "onCharacteristicRead: " + getCharacteristicInfo( characteristic ) ); 461 | if( serviceProfile.getClass().equals( BatteryProfile.class ) ) { 462 | handleBatteryCallback( characteristic ); 463 | } else if( serviceProfile.getClass().equals( AHServiceProfile.class ) ) { 464 | handleAHServiceCallback( characteristic ); 465 | } else if( serviceProfile.getClass().equals( DeviceInformationProfile.class ) ) { 466 | handleDeviceInfoCallback( characteristic ); 467 | } else if( serviceProfile.getClass().equals( AADeviceServiceProfile.class ) ) { 468 | handleAADeviceServiceCallback( characteristic ); 469 | } else if( serviceProfile.getClass().equals( GenericAccessProfile.class ) ) { 470 | handleGenericAccessCallback( characteristic ); 471 | } else { 472 | Log.w( CLASS, "onCharacteristicRead: unhandled event. class=" + serviceProfile.getClass() ); 473 | } 474 | processQueue(); 475 | } 476 | 477 | public void onCharacteristicChanged( BluetoothGattCharacteristic characteristic ) { 478 | BluetoothGattService service = characteristic.getService(); 479 | BaseProfile serviceProfile = Profiles.getService( service.getUuid() ); 480 | 481 | Log.d( CLASS, "onCharacteristicChanged: " + getCharacteristicInfo( characteristic ) ); 482 | if( serviceProfile.getClass().equals( BatteryProfile.class ) ) { 483 | handleBatteryCallback( characteristic ); 484 | } else if( serviceProfile.getClass().equals( AHServiceProfile.class ) ) { 485 | handleAHServiceCallback( characteristic ); 486 | } else if( serviceProfile.getClass().equals( DeviceInformationProfile.class ) ) { 487 | handleDeviceInfoCallback( characteristic ); 488 | } else if( serviceProfile.getClass().equals( AADeviceServiceProfile.class ) ) { 489 | handleAADeviceServiceCallback( characteristic ); 490 | } else if( serviceProfile.getClass().equals( GenericAccessProfile.class ) ) { 491 | handleGenericAccessCallback( characteristic ); 492 | } else { 493 | Log.w( CLASS, "onCharacteristicChanged: unhandled event. class=" + serviceProfile.getClass() ); 494 | } 495 | processQueue(); 496 | } 497 | 498 | public void onCharacteristicWrite( BluetoothGattCharacteristic characteristic ) { 499 | Log.d( CLASS, "onCharacteristicWrite: " + getCharacteristicInfo( characteristic ) ); 500 | processQueue(); 501 | } 502 | 503 | public void onDescriptorRead( BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor ) { 504 | Log.d( CLASS, "onDescriptorRead: " + getDescriptorInfo( descriptor ) ); 505 | processQueue(); 506 | } 507 | 508 | // TODO: Add callbacks 509 | // TODO: track in a better way if a notification is enabled 510 | public void onDescriptorWrite( BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor ) { 511 | BluetoothGattService service = characteristic.getService(); 512 | BaseProfile serviceProfile = Profiles.getService( service.getUuid() ); 513 | 514 | Log.d( CLASS, "onDescriptorWrite: " + getDescriptorInfo( descriptor ) ); 515 | 516 | UUID uuid = characteristic.getUuid(); 517 | 518 | if( serviceProfile.getClass().equals( AHServiceProfile.class ) ) { 519 | if( uuid.equals( AHServiceProfile.DATA_UUID ) ) { 520 | mDataNotificationsEnabled = !mDataNotificationsEnabled; 521 | } else if( uuid.equals( AHServiceProfile.DEBUG_UUID ) ) { 522 | mDebugNotificationsEnabled = !mDebugNotificationsEnabled; 523 | } else if( uuid.equals( AHServiceProfile.EVENT_UUID ) ) { 524 | mEventNotificationsEnabled = !mEventNotificationsEnabled; 525 | } else if( uuid.equals( AHServiceProfile.ACCEL_DATA_UUID ) ) { 526 | mAccNotificationsEnabled = !mAccNotificationsEnabled ; 527 | } else { 528 | Log.w( CLASS, "onCharacteristicChanged: unhandled event. uuid=" + uuid 529 | + " class=" + serviceProfile.getClass() ); 530 | } 531 | } else { 532 | Log.w( CLASS, "onCharacteristicChanged: unhandled event. class=" + serviceProfile.getClass() ); 533 | } 534 | 535 | processQueue(); 536 | } 537 | 538 | public boolean connect() { 539 | return mBtBridge.connect(); 540 | } 541 | 542 | public boolean disconnect() { 543 | return mBtBridge.disconnect(); 544 | } 545 | 546 | } 547 | --------------------------------------------------------------------------------