Empalink例程阅读

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
    */
     

出现的问题是:显示的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中部署画布:

            

第三步:在MainActivity中的didRecievedXXX()中将收到的E4手环数据发送到mView中,刷新页面,进行波形的显示。

            /** Send data to canvas and update UI **/
            waveForm.setListData(temp);
            waveForm.postInvalidate();

你可能感兴趣的:(Empalink例程阅读)