美文网首页
Empalink例程阅读

Empalink例程阅读

作者: Betrayer丶 | 来源:发表于2018-07-11 15:48 被阅读0次

    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();
    

    相关文章

      网友评论

          本文标题:Empalink例程阅读

          本文链接:https://www.haomeiwen.com/subject/gkbhpftx.html