Empallink-sample-project-android-master
功能介绍
- 搜索E4手环
- 连接设备
- 采集10s的数据
- 断开连接
使用方法
- 下载Github源码
- 在MainActivity.java的EMPATICA_KEY中输入设备的API码
- 导入.aar依赖包
- 编译运行
- 打开设备,进行连接
代码分析
导入依赖库:
import com.empatica.empalink.ConnectionNotAllowedException;
import com.empatica.empalink.EmpaDeviceManager; // 有关设备搜索、连接、API检验
import com.empatica.empalink.EmpaticaDevice; // 设备信息
import com.empatica.empalink.config.EmpaSensorStatus;// 注释类型:是否在手腕上
import com.empatica.empalink.config.EmpaSensorType; //枚举类型:传感器类型
import com.empatica.empalink.config.EmpaStatus; //枚举类型:连接状态
import com.empatica.empalink.delegate.EmpaDataDelegate; // 实例:接收设备的电量、传感器数据、时间戳
import com.empatica.empalink.delegate.EmpaStatusDelegate;// 实例:接受EmpaDeviceManager的信息
主程序派生于AppCompatActivity,是EmpaDataDelegate和EmpaStatusDelegate的实例,首先定义了一些变量。
private static final int REQUEST_ENABLE_BT = 1;
private static final int REQUEST_PERMISSION_ACCESS_COARSE_LOCATION = 1;
private static final String EMPATICA_API_KEY = "ee75b37389644a73b301767a4c0972e2";
/* EMPATICA_API_KEY从E4官网的账号中获得,再将我们购买的设备录入 */
private EmpaDeviceManager deviceManager = null;
private TextView accel_xLabel;
private TextView accel_yLabel;
private TextView accel_zLabel;
private TextView bvpLabel;
private TextView edaLabel;
private TextView ibiLabel;
private TextView temperatureLabel;
private TextView batteryLabel;
private TextView statusLabel;
private TextView deviceNameLabel;
private LinearLayout dataCnt;
接下来是一堆重写的函数:
/* 初始化与xml元素相对应的变量,设置按钮的功能,调用initEmpaticaDeviceManager() */
@Override
protected void onCreate(Bundle savedInstanceState)
/* 判断是否得到使用BLE的权利 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
/* 请求使用BLE,检查API_KEY是否为空 */
private void initEmpaticaDeviceManager()
/* 设置活动的生命周期 */
@Override
protected void onPause()
/* 设置活动的生命周期 */
@Override
protected void onDestroy()
/* 判断当前设备能否与API_KEY匹配。若匹配,停止搜索,更新设备ID */
@Override
public void didDiscoverDevice(EmpaticaDevice bluetoothDevice, String deviceName, int rssi, boolean allowed)
/* 当发现蓝牙被关闭时,请求用户开启蓝牙 */
@Override
public void didRequestEnableBluetooth()
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
/* 调用didUpdateOnWristStatus*/
@Override
public void didUpdateSensorStatus(@EmpaSensorStatus int status, EmpaSensorType type)
/* 更新设备的连接状态 */
@Override
public void didUpdateStatus(EmpaStatus status)
/* 更新各个传感器的参数 */
@Override
public void didReceiveAcceleration(int x, int y, int z, double timestamp)
@Override
public void didReceiveBVP(float bvp, double timestamp)
@Override
public void didReceiveBatteryLevel(float battery, double timestamp)
@Override
public void didReceiveGSR(float gsr, double timestamp)
@Override
public void didReceiveIBI(float ibi, double timestamp)
@Override
public void didReceiveTemperature(float temp, double timestamp)
private void updateLabel(final TextView label, final String text)
@Override
public void didReceiveTag(double timestamp)
@Override
public void didEstablishConnection()
/* 更新UI界面里手腕检测值 */
@Override
public void didUpdateOnWristStatus(@EmpaSensorStatus final int status)
void show()
void hide()
但是整个程序的驱动器在哪里啊。。
好像不太熟悉Java的运行方式。
代码修改
- 根据IBI参数(ECG间期时长)计算心率,替代IBI,显示在UI界面上;
HR=\frac{60}{IBI} - 在UI界面上显示TimeStamp,新建TextView控件,在didReceiveAcceleratioin函数中更新TimeStamp的值。
/*
MainActivity.java
*/
@Override
public void didReceiveAcceleration(int x, int y, int z, double timestamp) {
updateLabel(accel_xLabel, "" + x);
updateLabel(accel_yLabel, "" + y);
updateLabel(accel_zLabel, "" + z);
updateLabel(time_stamp, "" + timestamp);
}
/*
activity_main.xml
*/
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/wrist_status_label"
android:text="timeStamp" />
<TextView
android:id="@+id/timeStamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/wrist_status_label"
android:width="50dp"
android:text="@string/emptyText" />
出现的问题是:显示的timestamp值是一个很长位数的数字,需要在开始更新状态时设置一个初始值作为0基准值,该基准值为当前时间到1970年1月1日00:00:00的秒数,所以我们需要获取当前设备的时间.为此,查阅资料发现java自带的函数System.currentTimeMills()
可以返回当前距离基准时间的值(且精度高了3位)修改后的代码可以实现以程序运行时作为基准时。
private double initTimeStamp = (double)System.currentTimeMillis() / 1000;
@Override
public void didReceiveAcceleration(int x, int y, int z, double timestamp) {
updateLabel(accel_xLabel, "" + x);
updateLabel(accel_yLabel, "" + y);
updateLabel(accel_zLabel, "" + z);
updateLabel(time_stamp, "" + (timestamp - initTimeStamp));
}
将数值显示转换成波形显示
为了避免程序无法响应,使用基于SurfaceView控件的方式进行作图,相当于在主线程中开启了一个子线程进行绘图缓冲,每次绘图完成后就终止子线程。
由于界面大小限制,先只绘制Temperature的波形图。
首先新建一个mView类,继承于View类,在上面进行背景网格的绘制和波形曲线的绘制。
- 背景网格绘制:
设置画笔颜色、粗细:
private Paint mPaint;
private Path mPath = new Path();
int mBackgroundColor = Color.WHITE;
int mTextColor = Color.BLUE;
int mGridColor = Color.GRAY;
int mPointColor = Color.RED;
int mLineColor = Color.RED;
int hNum = 6;
float data = 0;
int xMove = 20;
int x = 0;
float y;
boolean isFull = true;
public mView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
重载onDraw函数:
@Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(mBackgroundColor);
canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
mPaint.setColor(mTextColor);
mPaint.setTextSize(40);
String text = "Temp Curve";
//canvas.drawText(text, 0, 40, mPaint);
mPaint.setColor(mGridColor);
for(int i=0; i < hNum+1; i++) {
canvas.drawLine(0, i * getHeight()/hNum, getWidth(), 5 + i * getHeight()/hNum, mPaint);
}
mPaint.setColor(mPointColor);
mPaint.setStrokeWidth(10);
for(int i = 0; i < getWidth(); i++) {
canvas.drawPoint(i, i * getHeight()/getWidth(), mPaint);
}
}
- 波形曲线绘制:
接收E4手环传过来的数据:
/** Send data into mView **/
public void setListData(float newData) {
data = newData;
}
坐标映射:
/** Axis transform **/
public float axisTrans(float data) {
float y;
float Rmin = 30;
float Rmax = 36;
float mHeight = 120;
y = -2 * data + 240;
return y;
}
曲线绘制:
/** Draw curve **/
public void drawCurve(Canvas canvas) {
/** No data Recieved **/
if (data == 0) {
return;
}
y = axisTrans(data);
if (x > getWidth()) {
x = 0;
mPath.reset();
mPath.moveTo(0, y);
}
x += xMove;
mPath.lineTo(x, y);
mPaint.setColor(mLineColor);
mPaint.setStrokeWidth(10);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(mPath, mPaint);
}
第二步:在xml中部署画布:
<com.empatica.sample.mView
android:id="@+id/waveform"
android:layout_width="wrap_content"
android:layout_height="120dp" />
第三步:在MainActivity中的didRecievedXXX()中将收到的E4手环数据发送到mView中,刷新页面,进行波形的显示。
/** Send data to canvas and update UI **/
waveForm.setListData(temp);
waveForm.postInvalidate();
网友评论