-
Notifications
You must be signed in to change notification settings - Fork 101
/
UartInterfaceActivity.java
185 lines (141 loc) · 5.93 KB
/
UartInterfaceActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package com.adafruit.bluefruit.le.connect.app;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.adafruit.bluefruit.le.connect.ble.BleManager;
import com.adafruit.bluefruit.le.connect.ble.BleUtils;
import java.nio.charset.Charset;
import java.util.Arrays;
public class UartInterfaceActivity extends AppCompatActivity implements BleManager.BleManagerListener {
// Log
private final static String TAG = UartInterfaceActivity.class.getSimpleName();
// Service Constants
public static final String UUID_SERVICE = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
public static final String UUID_RX = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
public static final String UUID_TX = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";
public static final String UUID_DFU = "00001530-1212-EFDE-1523-785FEABCD123";
public static final int kTxMaxCharacters = 20;
// Data
protected BleManager mBleManager;
protected BluetoothGattService mUartService;
private boolean isRxNotificationEnabled = false;
// region Send Data to UART
protected void sendData(String text) {
final byte[] value = text.getBytes(Charset.forName("UTF-8"));
sendData(value);
}
protected void sendData(byte[] data) {
if (mUartService != null) {
// Split the value into chunks (UART service has a maximum number of characters that can be written )
for (int i = 0; i < data.length; i += kTxMaxCharacters) {
final byte[] chunk = Arrays.copyOfRange(data, i, Math.min(i + kTxMaxCharacters, data.length));
mBleManager.writeService(mUartService, UUID_TX, chunk);
}
} else {
Log.w(TAG, "Uart Service not discovered. Unable to send data");
}
}
// Send data to UART and add a byte with a custom CRC
protected void sendDataWithCRC(byte[] data) {
// Calculate checksum
byte checksum = 0;
for (byte aData : data) {
checksum += aData;
}
checksum = (byte) (~checksum); // Invert
// Add crc to data
byte dataCrc[] = new byte[data.length + 1];
System.arraycopy(data, 0, dataCrc, 0, data.length);
dataCrc[data.length] = checksum;
// Send it
Log.d(TAG, "Send to UART: " + BleUtils.bytesToHexWithSpaces(dataCrc));
sendData(dataCrc);
}
// endregion
// region SendDataWithCompletionHandler
protected interface SendDataCompletionHandler {
void sendDataResponse(String data);
}
final private Handler sendDataTimeoutHandler = new Handler();
private Runnable sendDataRunnable = null;
private SendDataCompletionHandler sendDataCompletionHandler = null;
protected void sendData(byte[] data, SendDataCompletionHandler completionHandler) {
if (completionHandler == null) {
sendData(data);
return;
}
if (!isRxNotificationEnabled) {
Log.w(TAG, "sendData warning: RX notification not enabled. completionHandler will not be executed");
}
if (sendDataRunnable != null || sendDataCompletionHandler != null) {
Log.d(TAG, "sendData error: waiting for a previous response");
return;
}
Log.d(TAG, "sendData");
sendDataCompletionHandler = completionHandler;
sendDataRunnable = new Runnable() {
@Override
public void run() {
Log.d(TAG, "sendData timeout");
final SendDataCompletionHandler dataCompletionHandler = sendDataCompletionHandler;
UartInterfaceActivity.this.sendDataRunnable = null;
UartInterfaceActivity.this.sendDataCompletionHandler = null;
dataCompletionHandler.sendDataResponse(null);
}
};
sendDataTimeoutHandler.postDelayed(sendDataRunnable, 2 * 1000);
sendData(data);
}
protected boolean isWaitingForSendDataResponse() {
return sendDataRunnable != null;
}
// endregion
// region BleManagerListener (used to implement sendData with completionHandler)
@Override
public void onConnected() {
}
@Override
public void onConnecting() {
}
@Override
public void onDisconnected() {
}
@Override
public void onServicesDiscovered() {
mUartService = mBleManager.getGattService(UUID_SERVICE);
}
protected void enableRxNotifications() {
isRxNotificationEnabled = true;
mBleManager.enableNotification(mUartService, UUID_RX, true);
}
@Override
public void onDataAvailable(BluetoothGattCharacteristic characteristic) {
// Check if there is a pending sendDataRunnable
if (sendDataRunnable != null) {
if (characteristic.getService().getUuid().toString().equalsIgnoreCase(UUID_SERVICE)) {
if (characteristic.getUuid().toString().equalsIgnoreCase(UUID_RX)) {
Log.d(TAG, "sendData received data");
sendDataTimeoutHandler.removeCallbacks(sendDataRunnable);
sendDataRunnable = null;
if (sendDataCompletionHandler != null) {
final byte[] bytes = characteristic.getValue();
final String data = new String(bytes, Charset.forName("UTF-8"));
final SendDataCompletionHandler dataCompletionHandler = sendDataCompletionHandler;
sendDataCompletionHandler = null;
dataCompletionHandler.sendDataResponse(data);
}
}
}
}
}
@Override
public void onDataAvailable(BluetoothGattDescriptor descriptor) {
}
@Override
public void onReadRemoteRssi(int rssi) {
}
// endregion
}