Skip to content

Repository files navigation

BLE Library

Integration

In order to integrate the BLE library, add dependency on app level build.gradle file.

implementation'com.fretzealot:fz-android-sdk:1.0.0'

Under the <manifest> tag in your manifest, add the permissions:

<uses-permissionandroid:name="android.permission.BLUETOOTH" />
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION" />

Register following service in manfest file inside <application> tag:

<serviceandroid:name="com.fz.blelib.BluetoothLeService"android:enabled="true" />

Usage

While using the library for the first time in the app, a library instance should be created as follows:

To integrate this BLE library in android application minimum Android version 19 is required

In the activity where the library is used for the first time in the application lifecycle, DO NOT call finish(); since the library instance is created using its context throughout the app. See below example activity:

packagecom.fretzealot.led;
importandroid.Manifest;
importandroid.bluetooth.BluetoothAdapter;
importandroid.bluetooth.BluetoothDevice;
importandroid.bluetooth.BluetoothGattService;
importandroid.content.Intent;
importandroid.content.pm.PackageManager;
importandroid.os.Build;
importandroid.os.Bundle;
importandroid.support.annotation.NonNull;
importandroid.support.v4.app.ActivityCompat;
importandroid.support.v7.app.AppCompatActivity;
importandroid.widget.Toast;
importcom.fz.blelib.LEDBLELib;
importcom.fz.blelib.LEDBLELibCallback;
importjava.util.List;
publicclassMainActivityextendsAppCompatActivity {
privatestaticfinalintREQUEST_ENABLE_BT = 101;
privatestaticfinalintPERMISSION_CODE = 102;
LEDBLELibledbleLib;
@OverrideprotectedvoidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ledbleLib = LEDBLELib.getInstance(getApplicationContext());
if (ledbleLib.isSupported()) {
if (ledbleLib.isEnabled()) {
checkForPermissions();
} else {
IntentenableBtIntent = newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
} else {
Toast.makeText(this, "Bluetooth not supported", Toast.LENGTH_LONG).show();
}
}
@OverrideprotectedvoidonActivityResult(intrequestCode, intresultCode, Intentdata) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_OK) {
checkForPermissions();
}
}
privatevoidcheckForPermissions() {
if (hasPermissions(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)) {
startScanner();
} else {
ActivityCompat.requestPermissions(this, newString[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}
, PERMISSION_CODE);
}
}
privatebooleanhasPermissions(String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && permissions != null) {
for (Stringpermission : permissions) {
if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
returnfalse;
}
}
}
returntrue;
}
@OverridepublicvoidonRequestPermissionsResult(intrequestCode, @NonNullString[] permissions, @NonNullint[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_CODE) {
for (intgrantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Location permission required to connect fretzealot", Toast.LENGTH_LONG).show();
return; }
}
startScanner();
}
}
privatevoidstartScanner() {
ledbleLib.startScan(newBluetoothAdapter.LeScanCallback() {
@OverridepublicvoidonLeScan(BluetoothDevicebluetoothDevice, inti, byte[] bytes) {
if (bluetoothDevice != null && bluetoothDevice.getName() != null && bluetoothDevice.getName().toLowerCase().equals("fret zealot")) {
ledbleLib.stopScan();
startConnectionService(bluetoothDevice.getAddress());
}
}
});
}
privatevoidstartConnectionService(Stringaddress) {
ledbleLib.startService(address, newLEDBLELibCallback() {
@OverridepublicvoidonConnected() {
Toast.makeText(MainActivity.this, "Fret zealot connected", Toast.LENGTH_LONG).show();
}
@OverridepublicvoidonDisconnected() {
Toast.makeText(MainActivity.this, "Fret zealot disconnected", Toast.LENGTH_LONG).show();
}
@OverridepublicvoidonServiceDiscovered(List<BluetoothGattService> serviceList) {
}
@OverridepublicvoidonDataReceived(byte[] rxBytes) {
}
@OverridepublicvoidonBatteryString(Stringvalue) {
}
@OverridepublicvoidonManufactureNameString(Stringvalue) {
}
@OverridepublicvoidonModelNumberString(Stringvalue) {
}
@OverridepublicvoidonSerialNumberString(Stringvalue) {
}
@OverridepublicvoidonHardwareRevisionString(Stringvalue) {
}
});
ledbleLib.onResume();
}
}

The next time the library is instantiated (ideally in a different class), it can be instantiated as follows:

mLib = LEDBLELib.getInstance();

And in order to connect to a device, the following method needs to be called:

mLib.connect(deviceAddress)
ORmLib.startService() --> Below

where deviceAddress is a String.

To start the service on Fret Zealot :

mLib.startService(mDeviceAddress, mLibCallback);
protectedLEDBLELibCallbackmLibCallback = newLEDBLELibCallback() {
@OverridepublicvoidonConnected() {
Toast.makeText(MainActivity.this, "Device connected", Toast.LENGTH_SHORT).show();
}
@OverridepublicvoidonDisconnected() {
try {
mLib.disconnect();
} catch (Exceptione) {
e.printStackTrace();
}
Toast.makeText(MainActivity.this, "Device disconnected", Toast.LENGTH_SHORT).show();
}
@OverridepublicvoidonServiceDiscovered(List<BluetoothGattService> serviceList) {
try {
if (!mLib.isLED()) {
Toast.makeText(MainActivity.this, "Connected (Not LED)", Toast.LENGTH_SHORT).show();
}
} catch (Exceptione) {
e.printStackTrace();
}
}
@OverridepublicvoidonDataReceived(byte[] rxBytes) {
}
@OverridepublicvoidonBatteryString(Strings) {
}
@OverridepublicvoidonManufactureNameString(Strings) {
}
@OverridepublicvoidonModelNumberString(Strings) {
}
@OverridepublicvoidonSerialNumberString(Strings) {
}
@OverridepublicvoidonHardwareRevisionString(Strings) {
}
};

Once the instance is ready, we can use the following methods of the library to send commands to Fret Zealot. All the commands are held in a command buffer. This means that the commands are collected into a buffer prior to getting sent. A command buffer can hold a maximum of 5 commands. To insert a command into the buffer, various methods can be called as shown below. All the values sent as arguments should be converted to byte from int

Also, the parameters commonly used are:

fret and string - Fret is self explanatory, and the valid range is 0 (Open) to 14. The tuning is read from the 5th string to the 0th string: E-A-D-G-B-E. Hence, the string indices would be as follows: E=5, A=4, D=3, G=2, B=1, E=0

red, blue and green - These are the values for the LED color. Possible values for each can be between 0 and 15.

intensity - The intensity of the LED. Possible values are between 0 and 10. fadeMode - The fade effect with which to light up the LED. Possible values for fadeMode are between 0 and 4.

Fade effect reference chart:

Fade Mode Value Description
0 Fade not active //Set Pixel On **Most Common**
1 Fade in short //Fade in Pixel over 50ms
2 Fade in long //Fade out Pixel over 50ms
3 Fade out short //Fade in Pixel over 200ms
4 Fade out long //fade out Pixel over 200ms

There are several methods for controlling LED state on the fretboard

The set method - This method lights up a single LED

mLib.set((byte)fret, (byte)string, (byte)red, (byte)blue, (byte)green, (byte)intensity, (byte)fadeMode);

The set_across method - This method lights up all the frets in a string

mLib.set_across((byte)string, (byte)red, (byte)blue, (byte)green, (byte)intensity, (byte)fadeMode);

The set_all method - This method lights up the whole fretboard with the LED color supplied as arguments.

mLib.set_all((byte)string, (byte)red, (byte)blue, (byte)green, (byte)intensity, (byte)fadeMode);

The set_subset method - This method lights up a string from a given fret to the 14th fret. For example, if you need to turn on the LEDs from fret 8 to fret 14, this is the method for you. However, the upper limit (14) cannot be changed.

mLib.set_subset((byte)starting_fret, (byte)string, (byte)red, (byte)blue, (byte)green, (byte)intensity, (byte)fadeMode);

The clear method - This method sets each LED on the fretboard to off. This counts as one command of the 5 allowed in the command buffer

mLib.clear();

There exist several utility methods for inteacting with the command buffer. The command buffer holds 5 (five) serialized commands, and mirrors the size of the Bluetooth MTU. This structure does not need to be initialized.

The sendCommandBufferClear method - This method clears the buffer of any existing data, and should be invoked before each write to the fretboard.

mLib.sendCommandBufferClear();

The sendCommandFlush() method - This method dumps the contents (up to 5 commands) of the command buffer to the BLE device. A minimum of 1 ms is required as the value of DELAY. Please ensure that this method is always called in a Handler's runnable with delay.

privatestaticfinalintDELAY = 1;
newHandler().postDelayed(newRunnable() {
@Overridepublicvoidrun() {
mBLE.sendCommandFlush();
}
}, DELAY);

LED commands should be wrapped in these utility commands, to ensure delivery to the Fret Zealot. A typical command to set completely new pixels -- (C) major Triad in Standard Tuning looks as follows:

mLib.sendCommandBufferClear(); // Flush the buffermLib.clear(); //Clear all displayed PixelsmLib.set((byte) 3, (byte) 4, (byte) 0, (byte) 15, (byte) 0, (byte) 9, (byte) 0); // Set 'C' to bluemLib.set((byte) 2, (byte) 3, (byte) 0, (byte) 0, (byte) 15, (byte) 9, (byte) 0); // Set 'E' to greenmLib.set((byte) 0, (byte) 2, (byte) 15, (byte) 15, (byte) 15, (byte) 9, (byte) 0); // Set 'G' to blueprivatestaticfinalintDELAY = 1;
newHandler().postDelayed(newRunnable() {
@Overridepublicvoidrun() {
mBLE.sendCommandFlush();
}
}, DELAY); // Send commands to the Fret Zealot

The onResume() method - This method reconnects the bluetooth connection when an app activity is resumed. (For example moved to background/foreground) Please ensure to call mLib.onResume() each time the app is refocused.

@OverrideprotectedvoidonResume() {
mLib.onResume();
super.onResume();
}

The onPause() method - This method disconnect the bluetooth connection when an activity is paused. phase.

@OverrideprotectedvoidonPause() {
mLib.onPause();
super.onPause();
}

The isConnected() method - This method returns boolean value true if fretboard is connected with application and false if fretboard is not connected with application.

mLib.isConnected();

Light Show

The `set_display` method - This method takes **strand_start**, **Intensity** and **fade_mode** as parameter and light up on fretboard according to parameter fad value.

strand_start :

intensity : LED intensity on fretboard

fade_mode:

 fade_mode Description
0 No lights
1 Sparkler
2 Bolt
3 Rainbow
mLib.sendCommandBufferClear();
mLib.set_display((byte) strand_start, (byte) intensity, (byte) fadValue);
privatestaticfinalintDELAY = 1;
newHandler().postDelayed(newRunnable() {
@Overridepublicvoidrun() {
mBLE.sendCommandFlush();
}
}, DELAY);

Color Templates

FunctionColorFZ RGB
Index FingerBlue[0,0,15]
Middle FingerGreen[0,15,0]
Ring FingerYellow[12,15,0]
Finger FingerPurple[12,0,15]
Open StringWhite[12,15,15]
Muted StringRed[4,0,0]

use the ‘set_across’ command for muting

Fret Zealot App Representation

FZ Screenshot

About

The Fret Zealot Android SDK

Topics

Resources

Stars

15 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages