转载

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

前提条件

Android 方面:

  • 安装 Android Studio:https://developer.android.com/sdk/index.html
  • 一个 Android 移动设备
  • 一个 Android 手表

IBM Bluemix 方面:

  • 一个 IBMBluemix 帐户

回页首

创建一个新的 Android Wear 项目

首先,创建一个新的 Android 项目 (File->New->New Project)。

在向导中,键入“HeartRate”作为应用程序名称并选择您的项目所在的位置。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

单击“Next”,选择“Phone and Tablet”和“Wear”,然后根据您的设备选择最低限度的 SDK。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

单击“Next”,为移动应用程序选择“Blank Activity”。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

单击“Next”,在 Activity Name 字段中键入“HeartRateMobileActivity”。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

单击“Next”,为 Wear 应用程序选择“Blank Wear Activity”。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

单击“Next”,在 Activity Name 字段中键入“HeartRateWearActivity”。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

单击“Finish”。

回页首

开发基本的可穿戴设备应用程序

权限

确保“mobile”和“wear”清单文件具有“BODY_SENSOR”权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ibm.hcs.heartrate" >  <uses-permission android:name="android.permission.BODY_SENSORS" /> …

更新可穿戴设备活动

在“wear”string.xml 文件中添加一个标签:

<string name="heartRateText">Heart Rate : N/A</string>

打开 Wear 的布局“round_activity_heart_rate_wear.xml”,然后使用“heartRateTextView”更改“id”字段,并使用 “@string/heartRateText”更改“text”字段。

打开“HeartRateWearActivity”字段并更改“onCreate”函数。

@Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_heart_rate_wear);  final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);  stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {  @Override  public void onLayoutInflated(WatchViewStub stub) {  mTextView = (TextView) stub.findViewById(R.id.heartRateTextView);  }  }); }

创建一个新服务

创建一个名为“HeartRateWearService”的服务,验证清单文件:

<service android:name=".HeartRateWearService">

使用以下代码替换生成的文件:

点击查看代码清单

关闭 [x]

public class HeartRateWearService extends Service implements SensorEventListener{  private SensorManager sensorManager;  private Sensor heartRateSensor;  private ScheduledExecutorService heartRateScheduler;  public HeartRateWearService() {  }   @Override  public void onCreate() {  super.onCreate();  getHeartRateValues();  }   private void getHeartRateValues() {  sensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));  heartRateSensor = sensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);  if (heartRateSensor != null) {  heartRateScheduler = Executors.newScheduledThreadPool(1);  heartRateScheduler.scheduleAtFixedRate(  new Runnable() {  @Override  public void run() {  sensorManager.registerListener(HeartRateWearService.this, heartRateSensor, SensorManager.SENSOR_DELAY_NORMAL);  try {  Thread.sleep(10000);  } catch (InterruptedException e) {  }  sensorManager.unregisterListener(HeartRateWearService.this,heartRateSensor);  }  }, 3, 15, TimeUnit.SECONDS);  }  }   @Override  public IBinder onBind(Intent intent) {  return null;  }   @Override  public void onDestroy() {  if (sensorManager != null)  sensorManager.unregisterListener(this);  heartRateScheduler.shutdown();   super.onDestroy();  }   @Override  public void onSensorChanged(SensorEvent event) {  // sends an Intent to the Activity   Intent intent = new Intent();  intent.setAction("heartRateAction");  intent.putExtra("HeartRate", event.values[0]);  sendBroadcast(intent);  }    @Override  public void onAccuracyChanged(Sensor sensor, int accuracy) {  }

显示进行活动时的心率

打开“HeartRateWearActivity”文件,添加此属性:

private HeartRateBroadcastReceiver heartRateBroadcastReceiver;

添加此内部类:

private class HeartRateBroadcastReceiver extends BroadcastReceiver {  @Override  public void onReceive(Context arg0, Intent arg1) {  // ahr  Log.v(this.getClass().getName(), "Value Recieved");  if (arg1.getAction().equals("heartRateAction")) {  float hr = arg1.getFloatExtra("HeartRate", 0);  if (HeartRateWearActivity.this.mTextView != null) {  HeartRateWearActivity.this.mTextView.setText("Heart Rate : " + hr);  }  }  }  }

添加以下方法:

@Override protected void onStart() {  // initialize the broadcast recieiver  heartRateBroadcastReceiver = new HeartRateBroadcastReceiver();  IntentFilter intentFilter = new IntentFilter();  intentFilter.addAction("heartRateAction");  registerReceiver(heartRateBroadcastReceiver, intentFilter);   // start HeartRateWearService  startService(new Intent(this, HeartRateWearService.class));  super.onStart(); }  @Override protected void onStop() {  unregisterReceiver(heartRateBroadcastReceiver);  stopService(new Intent(this, HeartRateWearService.class));  super.onStop(); }

回页首

将心率发送给移动应用程序

更新 Wear 应用程序以发送心率

打开“HeartRateWearService”,添加属性:

private GoogleApiClient googleApiClient; private ExecutorService executorService;

在“onCreate”函数中初始化 executorService:

@Override public void onCreate() {  …  …  executorService = Executors.newCachedThreadPool(); }

添加以下函数:

点击查看代码清单

关闭 [x]

private boolean isConnected() {  if (googleApiClient == null)  googleApiClient = new GoogleApiClient.Builder(this.getApplication().getApplicationContext()).addApi(Wearable.API).build();   if (googleApiClient.isConnected()) {  return true;  }   ConnectionResult result = googleApiClient.blockingConnect(15000, TimeUnit.MILLISECONDS);  return result.isSuccess(); }  private void sendToMobile(final SensorEvent event) {  executorService.submit(new Runnable() {  @Override  public void run() {    PutDataMapRequest dataMap = PutDataMapRequest.create("/sensor/heartRate");  dataMap.getDataMap().putLong("timestamp", event.timestamp);  dataMap.getDataMap().putFloat("value", event.values[0]);  PutDataRequest putDataRequest = dataMap.asPutDataRequest();  if (isConnected()) {  Wearable.DataApi.putDataItem(googleApiClient, putDataRequest).setResultCallback(new ResultCallback<DataApi.DataItemResult>() {  @Override  public void onResult(DataApi.DataItemResult dataItemResult) {  Log.v(this.getClass().getName(), "Sending heartRate: " + dataItemResult.getStatus().isSuccess());  }  });  }  }  });  }

在“onSensorChanged”函数中添加此指令:

@Override public void onSensorChanged(SensorEvent event) {  …  …  sendToMobile(event); }

更新移动活动

在“mobile”string.xml 文件中添加一个标签:

<string name="heartRateText">Heart Rate : N/A</string>

打开移动布局“activity_heart_rate_mobile.xml”,然后使用“heartRateTextView”更改“id”字段,并使用 “@string/heartRateText”更改“text”字段。

创建一个新的移动服务

在移动模块中创建一个新服务“HeartRateMobileWearableListenerService”。

更新移动清单:

<service android:name=".HeartRateMobileWearableListenerService" >  <intent-filter>  <action android:name="com.google.android.gms.wearable.BIND_LISTENER"/>  </intent-filter>  </service>

更改“HeartRateMobileWearableListenerService”代码:

public class HeartRateMobileWearableListenerService extends WearableListenerService {  @Override  public void onDataChanged(DataEventBuffer dataEvents) {  Log.d(this.getClass().getName(), "onDataChanged()");  for (DataEvent dataEvent : dataEvents) {  if (dataEvent.getType() == DataEvent.TYPE_CHANGED) {  DataItem dataItem = dataEvent.getDataItem();  Uri uri = dataItem.getUri();  String path = uri.getPath();  if (path.equals("/sensor/heartRate")) {  DataMap map = DataMapItem.fromDataItem(dataItem).getDataMap();  long timestamp = map.getLong("timestamp");  float value = map.getFloat("value");  Intent intent = new Intent();  intent.setAction("heartRateAction");  intent.putExtra("HeartRate", value);  sendBroadcast(intent);  }  }  }  } }

显示进行移动活动时的心率

打开“HeartRateMobileActivity”,添加此属性:

private HeartRateBroadcastReceiver heartRateBroadcastReceiver;

添加此内部类:

点击查看代码清单

关闭 [x]

private class HeartRateBroadcastReceiver extends BroadcastReceiver {  @Override  public void onReceive(Context arg0, Intent arg1) {  // ahr  Log.v(this.getClass().getName(), "Value Recieved");  if (arg1.getAction().equals("heartRateAction")) {  float hr = arg1.getFloatExtra("HeartRate", 0);  ((TextView)HeartRateMobileActivity.this.findViewById(R.id.heartRateTextView)).setText("Heart Rate : " + hr);  }  } }

添加“onStart”函数:

@Override protected void onStart() {  super.onStart();  // ahr  heartRateBroadcastReceiver = new HeartRateBroadcastReceiver();  IntentFilter intentFilter = new IntentFilter();  intentFilter.addAction("heartRateAction");  registerReceiver(heartRateBroadcastReceiver, intentFilter); }

回页首

向 IoT Fundation 发布心率

在 IoT Fundation 服务中创建一个设备

  • 连接到您的 IBM Bluemix 帐户
  • 在 Catalog 选项卡中,选择“Internet of Things Fundation Starter”
  • 在 Name 字段中输入“HeartRate”并单击“Create”按钮
针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板
  • 在 Catalog 选项卡中,选择“Internet of Things”
  • 单击“Create”按钮
  • 启动 Internet of Things Foundation 仪表板
  • 选择“Devices”选项卡,然后选择“Add Device”
  • 在 Device Type 字段中键入“Wear”,并在 Device ID 字段中键入“myWatch”,然后单击“Continue”
针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板
  • 保存设备凭证(Organization ID、Device type and ID 和 Authentication Token)
针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

在您的移动模块中导入 mqtt 库

  • 在 HeartRatemobilelibs org.eclipse.paho.android.service.jar 和 org.eclipse.paho.client.mqttv3.jar 文件中填写相应的内容
  • 关闭并重新打开项目

更新移动清单

添加 mqtt 服务:

<service android:name="org.eclipse.paho.android.service.MqttService" />

添加 WAKE_LOCK 权限:

<uses-permission android:name="android.permission.WAKE_LOCK" />

创建 MQTTHandler

创建新的 MqttHandler 类,复制以下代码并更改组织和设备令牌:

public class MqttHandler implements MqttCallback {    private static MqttHandler instance;  private MqttAndroidClient mqttClient;  Context context;    private static String ORG = "YOUR_IOT_ORGANISATION";  private static String DEVICE_TYPE = "Wear";  private static String DEVICE_ID = "myWatch";  private static String TOKEN = "YOUR_DEVICE_TOKEN";  private static String TOPIC = "iot-2/evt/hr/fmt/json";    private MqttHandler(Context context) {  this.context = context;  }      public static MqttHandler getInstance(Context context) {  if (instance == null) {  instance = new MqttHandler(context);  }  return instance;  }      @Override  public void connectionLost(Throwable throwable) {  }    @Override  public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {  }    @Override  public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {  }    public void connect(IMqttActionListener listener) {  if (!isConnected()) {  String iotPort = "1883";  String iotHost = ORG+".messaging.internetofthings.ibmcloud.com";  String iotClientId = "d:"+ORG+":"+DEVICE_TYPE+":"+DEVICE_ID;    String connectionUri = "tcp://" + iotHost + ":" + iotPort;    if (mqttClient != null) {  mqttClient.unregisterResources();  mqttClient = null;  }    mqttClient = new MqttAndroidClient(context, connectionUri, iotClientId);  mqttClient.setCallback(this);    MqttConnectOptions options = new MqttConnectOptions();  options.setCleanSession(true);  options.setUserName("use-token-auth");  options.setPassword(TOKEN.toCharArray());    try {  mqttClient.connect(options, context, listener);  } catch (MqttException e) {    }  }  }    public void disconnect(IMqttActionListener listener) {  if (isConnected()) {  try {  mqttClient.disconnect(context, listener);  mqttClient = null;  } catch (MqttException e) {  e.printStackTrace();  }  }  }    public void publish(long timestamp, float heartRateValue) {  if (isConnected()) {  String msg = "{'timestamp':"+timestamp+",'heartRate':"+heartRateValue+"}";  MqttMessage mqttMsg = new MqttMessage(msg.getBytes());  mqttMsg.setRetained(false);  mqttMsg.setQos(0);  try {  mqttClient.publish(TOPIC, mqttMsg);  } catch (Exception e) {    }  }  }    private boolean isConnected() {  if (mqttClient != null) {  return mqttClient.isConnected();  }  return false;  }  }

连接到 IoT foundation

打开 HeartRateMobileActivity,添加此属性:

private boolean connected = false;

在 onStart 函数的末尾处添加此代码:

MqttHandler.getInstance(this).connect(new IMqttActionListener() {  @Override  public void onSuccess(IMqttToken iMqttToken) {  connected = true;  }   @Override  public void onFailure(IMqttToken iMqttToken, Throwable throwable) {  } });

在 onStop 函数的开头处添加此代码:

MqttHandler.getInstance(this).disconnect(new IMqttActionListener() {  @Override  public void onSuccess(IMqttToken iMqttToken) {  connected = false;  }   @Override  public void onFailure(IMqttToken iMqttToken, Throwable throwable) {  } });

向 IoT Fundation 发送心率

使用下列代码更新 onReceive 函数:

点击查看代码清单

关闭 [x]

public void onReceive(Context arg0, Intent arg1) {  // ahr  Log.v(this.getClass().getName(), "Value Recieved");  if (arg1.getAction().equals("heartRateAction")) {  float hr = arg1.getFloatExtra("HeartRate", 0);  long ts = arg1.getLongExtra("timestamp", 0);  ((TextView)HeartRateMobileActivity.this.findViewById(R.id.heartRateTextView)).setText("Heart Rate : " + hr);   if (connected)  MqttHandler.getInstance(HeartRateMobileActivity.this).publish(ts, hr);   } }

回页首

创建实时仪表板

创建一个 API 秘钥

打开 IoT Fundation Dashboar,选择“Access”和“API Key”,然后生成一个新的 API 秘钥。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

将秘钥和身份验证令牌保存在一个文件中。

创建 Internet of Things Real-Time Insights 服务

打开 IBM Bluemix dashboard,然后打开 Catalog 并选择“IoT Real-Time Insights”。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

单击“USE”按钮。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

添加一个数据源

单击“Add a data source”按钮,单击“Add New data source”,然后键入 IoT Fundation 组织令牌和 API 秘钥/身份验证令牌。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

验证,选择“Devices”和“Browse Devices”,然后就会看到您的 IoT 设备。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

创建消息模式

选择“Manage Schemas”,然后选择“Add new message schema”。键入一个名称并链接一个新的数据源。选择 IoT Hear Rate 数据源和 “Wear”类型,然后进行验证。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

添加新的数据点。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

验证。

创建规则

选择“Analytics”,然后选择“Add new rule”,键入名称和描述。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

添加一个条件。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

通过单击来编辑条件“Heart Rate greater than 120 b/m”。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

验证,通过单击来编辑动作“Send an email to …”并进行验证,然后您必须激活该规则。

创建仪表板

选择“Dashboards”和“Browse Dashboards”,然后选择“Add new Dashboard”,键入仪表板名称并进行验证。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

选择仪表板并添加以下组件:

1) 一个 Text 组件

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

2) 一个带有心率线的 Chart 组件

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

3) 一个映射到 myWatch 的 Device 组件

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

4) 一个带有警告组件的 Filtered Devices 组件

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

5) 一个用于设备组件的 Alert 组件

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

结果:

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板

现在,在启动 Android Wear 应用程序时,就可以在 Chart 组件和 Device 组件中看到实时心率值。如果心率大于 120,就会收到警报电子邮件,并在 Alert 组件中查看具体情况。

针对 Android Wear 应用程序的 Bluemix IoT 实时仪表板
原文  http://www.ibm.com/developerworks/cn/iot/iot-android-wear-iot-bluemix/index.html?ca=drs-
正文到此结束
Loading...