Статьи

Как разработать приложение IoT для Android с использованием Android Things and Cloud

В этой статье мы расскажем, как разработать Android-приложение для IoT, использующее Android Things . Более подробно, это приложение Android IoT будет отправлять данные, полученные с датчиков, в облако. Это приложение IoT помогает нам представить некоторые важные аспекты программирования приложения Android Things, в котором используются датчики.

Как вы, возможно, уже знаете, Android Things — это новая операционная система IoT, разработанная компанией Google, которая предоставляет возможности Android в IoT. Используя Android Things, мы можем повторно использовать знания Android для создания приложения Android Things, используя почти те же API. С этой целью в этом руководстве мы рассмотрим, как отправлять данные, полученные датчиками, непосредственно в облако с помощью облачной платформы IoT: Ubidots . Кроме того, это приложение Android IoT будет записывать все данные, полученные датчиками, в облако. В конце этого руководства вы сможете разработать приложение Android Things с поддержкой облачных вычислений. Это распространенный сценарий в проекте IoT, поэтому его полезно изучить. Более того, вы можете еще больше улучшить это приложение Android IoT для поддержки других типов датчиков или для отправки данных на другую облачную платформу. Это проект общего назначения, который можно настроить в соответствии с вашими потребностями и спецификациями облачной платформы. Если вы хотите попробовать другую облачную платформу IoT, вы можете прочитать эту статью, в которой перечислены все бесплатные платформы IoT .

Для создания этого проекта мы будем использовать:

  • Датчик температуры, давления и влажности BMP280
  • Raspberry Pi 3 для ОС Android Things

Кроме того, приложение Android IoT использует:

Как подключить Android Things к датчику BMP280 и считывать данные

На этом шаге мы расскажем, как подключить BMP280 к Android Things. BMP280 — это датчик I2C, а это значит, что нам нужно четыре разных провода для его подключения:

  • Vcc (+ 3 В)
  • GND
  • CLK (Часы)
  • ПДД (данные)

В этом уроке, как было сказано ранее, мы используем плату Raspberry Pi 3, затем, в соответствии с разводкой платы, соединения выглядят так, как показано на рисунке ниже:

После правильного подключения проводов мы можем сосредоточить наше внимание на разработке приложений Android IoT . Если вы впервые используете Android Things, важно прочитать это руководство о том, как начать работу с Android Things . В любом случае, в качестве первого шага, вы должны клонировать репозиторий шаблонов из GitHub . Это пустой проект, созданный для Android Studio, который мы будем использовать для создания нашего приложения IoT для Android. Давайте начнем создавать приложение.

Первым шагом является добавление драйвера Android Things, который приложение Android Things использует для обмена данными с датчиком. Для этого откройте gradle.build (уровень приложения) и добавьте следующую строку:

1
2
3
4
5
dependencies {
  ....
  compile 'com.google.android.things.contrib:driver-bmx280:0.4'
  ...
}

Цель этого приложения — непрерывный сбор данных с датчика, а затем необходимо реализовать тот же подход, который используется в Android, когда приложение отслеживает датчик.

Получайте данные с датчиков с помощью Android Things: SensorManager, Listeners и Drivers

Android Things предоставляет элегантный способ контролировать состояние датчика с помощью слушателей. В MainActivity добавьте следующие строки:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
private Bmx280SensorDriver sensor;
private SensorManager manager;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  Log.d(TAG, "onCreate");
  try {
    manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    registerSensors();
    sensor = new Bmx280SensorDriver(pin);
    sensor.registerTemperatureSensor();
    sensor.registerPressureSensor();
  }
  catch(IOException ioe) {
   ioe.printStackTrace();
  }
}

Код выше довольно прост:

  1. приложение получает ссылку на SensorManager
  2. приложение регистрирует слушатели датчиков, чтобы получать уведомления, когда датчики считывают новые значения
  3. он инициализирует драйвер BMP280
  4. регистрирует обратный вызов динамического датчика (температура и давление)

Давайте ненадолго пропустим шаг 2 и сосредоточим наше внимание на шагах 3 и 4. На шаге 3 приложение Android IoT создает новый экземпляр драйвера Bmx280Sensor, используя имя контакта, к которому подключен датчик. Для Raspberry Pi 3 вывод I2C1.

Прежде чем регистрировать слушателей для получения новых значений от датчиков, необходимо зарегистрировать двух разных слушателей, которые получают уведомление, когда датчик подключен к Android Things. Этот датчик BMP280 считывает два физических свойства, поэтому он считается двойным датчиком. Наконец, код для регистрации значения слушателей:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
private void registerSensors() {
  manager.registerDynamicSensorCallback(new SensorManager.DynamicSensorCallback() {
    @Override
    public void onDynamicSensorConnected(Sensor sensor) {
      if (sensor.getType() == Sensor.TYPE_AMBIENT_TEMPERATURE) {
        manager.registerListener(tempListener, sensor,
                SensorManager.SENSOR_DELAY_NORMAL);
      }
      else if(sensor.getType() == Sensor.TYPE_PRESSURE) {
        manager.registerListener(pressListener, sensor,
                SensorManager.SENSOR_DELAY_NORMAL);
     }
   }
 });
}

Метод onDynamicSensorConnected вызывается, как только датчик подключается к плате. В этот момент приложение может зарегистрировать двух слушателей, которые будут уведомлены, когда датчик прочитает новые значения.
Последний шаг — чтение данных с датчика:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
private SensorEventListener tempListener = new SensorEventListener() {
          @Override
          public void onSensorChanged(SensorEvent event) {
             // new value read
          }
 
          @Override
          public void onAccuracyChanged(Sensor sensor, int accuracy) {
          }
       };
private SensorEventListener pressListener = new SensorEventListener() {
          @Override
          public void onSensorChanged(SensorEvent event) {
            // new value read
          }
 
          @Override
          public void onAccuracyChanged(Sensor sensor, int accuracy) {
          }
      };

Как вы уже могли догадаться, в методе onSensorChanged приложение отправит новое значение в облако. На этом этапе вы можете протестировать приложение Android IoT и проверить, считывает ли оно данные с датчика. В любом случае, перед использованием приложения необходимо добавить эти разрешения в Manifest.xml :

1
2
<uses-permission android:name="com.google.android.things.permission.MANAGE_INPUT_DRIVERS" />
<uses-permission android:name="com.google.android.things.permission.MANAGE_SENSOR_DRIVERS" />

Настроить Ubidots для получения данных из приложения Android IoT

Этот шаг описывает, как настроить Ubidots для приема данных, поступающих из приложения Android Things. Перед началом необходимо иметь бесплатный аккаунт Ubidots . Затем мы должны настроить устройство, которое представляет наше устройство. Эта тема также рассматривается в нескольких публикациях в этом блоге, поэтому вы можете обратиться к этой статье: как настроить Ubidots для проекта IoT :

Следующим шагом является добавление переменных, которые будут содержать значения, отправленные из приложения Android:

Вот и все, все последующие шаги, необходимые для настройки убидотов, выполнены. Мы можем сосредоточиться на последнем этапе отправки данных в облако.

Отправка данных из Android Things в облако

На этом последнем этапе этого проекта приложение Android IoT отправляет данные в облако. Для этого в приложении используются библиотеки, разработанные для приложений Android, которые упрощают программирование приложений Android.

Ubidots предоставляет набор API, который приложение может использовать для отправки данных. Это JSON API. В этом контексте библиотека Retrofit и Gson очень полезны.

Давайте добавим зависимости в build.gradle:

1
2
3
4
5
6
dependencies {
  ...
  compile 'com.squareup.retrofit2:retrofit:2.3.0'
  compile 'com.google.code.gson:gson:2.8.2'
  compile 'com.squareup.retrofit2:converter-gson:2.3.0'
}

API /api/v1.6/collections/values который вызывает приложение, это /api/v1.6/collections/values который принимает массив JSON, содержащий:

  • идентификатор переменной
  • значение переменной

где идентификатор переменной — это уникальный идентификатор переменной, предоставляемый Ubidots, а значение — это значение, которое отправляет приложение. Для разработки Android IoT-приложения, которое вызывает этот API, мы используем Retrofit. Вкратце, эта библиотека упрощает процесс вызова JSON API. Для этого первым шагом является разработка интерфейса Java, который представляет вызванный API:

1
2
3
4
5
public interface UbiAPI {
 @POST("/api/v1.6/collections/values")
 public Call<ResponseBody> sendValue(
        @Body ArrayList<Data> dataList, @Query("token") String token);
}

Аннотация @POST объявляет контекст API, в то время как метод, определенный в интерфейсе, представляет метод, который приложение вызывает для отправки данных. Этот метод принимает в качестве тела массив Data и токен, который идентифицирует наше приложение. Класс данных:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
 
public class Data {
 
    @SerializedName("variable")
    @Expose
    private String variable;
    @SerializedName("value")
    @Expose
    private Double value;
 
    public String getVariable() {
        return variable;
    }
 
    public void setVariable(String variable) {
        this.variable = variable;
    }
 
    public Double getValue() {
        return value;
    }
 
    public void setValue(Double value) {
        this.value = value;
    }
}

Этот класс содержит переменную id и значение и описывает, как преобразовать эти значения в формат JSON. Наконец, мы должны определить клиента, который обрабатывает связь с Ubidots:

01
02
03
04
05
06
07
08
09
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
public class UbiClient {
    private static final String TAG = UbiClient.class.getSimpleName();
    private static final String UBI_BASE_URL =  "http://things.ubidots.com/";
 
    private static UbiClient client;
    private UbiAPI api;
    private Retrofit retroClient;
 
    private UbiClient() {
        retroClient = new Retrofit.Builder()
            .baseUrl(UBI_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    }
 
    public static final UbiClient getClient() {
      if (client != null)
          return client;
       
      client = new UbiClient();
      return client;
    }
 
 
    private UbiAPI getUbiClient() {
        return retroClient.create(UbiAPI.class);
    }
 
    public void sendData(ArrayList<Data> dList, String token) {
      api = client.getUbiClient();
      Call c = api.sendValue(dList, token);
      c.enqueue(new Callback() {
         @Override
         public void onResponse(Call call, Response response) {
            Log.d(TAG, "onResponse");
            Log.d(TAG, "Result:" + response.isSuccessful());
         }
 
         @Override
         public void onFailure(Call call, Throwable t) {
             t.printStackTrace();
         }
      });
   }
}

Это все. У нас есть наш клиент, который подключается к Ubidots и отправляет данные. Последний шаг — это изменение кода, показанного выше, где приложение считывает значения датчика и добавляет следующий код для отправки данных в облако:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private SensorEventListener tempListener = new SensorEventListener() {
   @Override
   public void onSensorChanged(SensorEvent event) {
 
       final Data dTemp = new Data();
       dTemp.setValue( (double) event.values[0]);
       dTemp.setVariable("59edbdc7c03f9721cc571662");
       UbiClient.getClient().sendData(new ArrayList<Data>(){{
          add(dTemp);
       }}, token);
    }
 
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
 };
 
private SensorEventListener pressListener = new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
 
      final Data dPress = new Data();
      dPress.setVariable("59edbdcec03f97212ff872c6");
      dPress.setValue( (double) event.values[0]);
      UbiClient.getClient().sendData(new ArrayList<Data>(){{
           add(dPress);
      }}, token);
   }
 
   @Override
   public void onAccuracyChanged(Sensor sensor, int accuracy) {
   }
 };

Интересный фрагмент кода — это часть, которая отправляет данные, где приложение создает информацию для отправки в облако:

1
2
3
4
5
6
7
final Data dPress = new Data();
// Variable id
dPress.setVariable("59edbdcec03f97212ff872c6");
dPress.setValue( (double) event.values[0]);
UbiClient.getClient().sendData(new ArrayList<Data>(){{
     add(dPress);
}}, token);

Не забудьте добавить разрешение на подключение к интернету в Manifest.xml

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

Запуск приложения и доступ к панели мониторинга Ubidots приводит к следующему:

Резюме

В конце этой статьи вы, надеюсь, получили знания о том, как разработать приложение IoT для Android, которое использует Android Things для отправки данных в облако. Кроме того, вы получили знания об использовании датчика I2C с Android Things.

Опубликовано на Java Code Geeks с разрешения Франческо Аццолы, партнера по нашей программе JCG. См. Оригинальную статью здесь: Как разработать приложение IoT для Android с использованием Android Things and Cloud

Мнения, высказанные участниками Java Code Geeks, являются их собственными.