Статьи

Управление сферо с помощью датчика температуры в Android

Одна из самых интересных тем вокруг Android — это то, как мы можем подключить наши смартфоны к другим устройствам или интеллектуальным устройствам, чтобы получать от них информацию или управлять ими. В этом посте я хочу представить новый способ использования нашего телефона Android и объяснить, как мы можем использовать его для управления шаром Sphero .

Вступление

В этом проекте для Android я хочу описать, как мы можем встроить датчик температуры в смартфон для управления цветом шара Sphero . Другими словами, я хочу изменить цветовой шар в соответствии с температурой, измеренной смартфоном, даже если смартфоны находятся в режиме ожидания или активность не находится на переднем плане.

Это интересный проект, потому что его можно использовать для описания некоторой важной концепции:

и, наконец, что не менее важно, как подключить и использовать Sphero ball с SDK . То, что мы хотим разработать, как показано ниже:

Android-сферо

Дизайн приложения

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

  • Активность, которая является интерфейсом приложения
  • Сервис, который контролирует датчик температуры
  • Сервис, который подключается к мячу и контролирует его цвет

android_sphero_temperature

Глядя на рисунок ниже, мы можем заметить, что действие пользовательского интерфейса запускает две службы и прослушивает события, поступающие от этих служб, более подробно это действие настроило сигнал тревоги, который используется для запуска службы датчика температуры, чтобы мы не истощали батарея. Тревога может быть настроена на запуск каждый фиксированный промежуток времени. Каждый раз, когда датчик температуры запускается, он измеряет температуру окружающей среды с помощью датчика смартфона и передает значение. UI Activity прослушивает эти события и показывает значение для UI, в то же время служба Ball Connection прослушивает одно и то же событие, и как только она получает событие, эта служба вычисляет компоненты цвета (R, G, B) и установить цвет мяча.

Создать службу датчика температуры: код

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

1
2
3
public class SensorService  extends Service implements SensorEventListener {
...
}

мы должны реализовать SensorEventListener для прослушивания событий датчика, затем в onStartCommand мы регистрируем этот класс как слушатель:

1
2
3
4
5
6
7
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
     sManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
     sensor = sManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
     sManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
     return Service.START_STICKY;
}

наконец, когда мы получаем уведомление о новом значении температуры, мы обрабатываем его:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
@Override
public void onSensorChanged(SensorEvent event) {
   // We get the temperature and notify it to the Activity
   float temp = event.values[0];
   Intent i = new Intent();
   i.setAction(TEMP_BALL_SENSOR);
   i.putExtra("value", temp);
   sendBroadcast(i);
 
   // stop listener
   if (sManager != null)
         sManager.unregisterListener(this);
 
   // stop service
   stopSelf();
}

В строке 15 мы прекращаем обслуживание, потому что не хотим постоянно читать значения, чтобы не разрядить батарею.

Создание службы подключения Ball: код

Другой сервис, который мы должны реализовать, — это управление соединением Sphero через Bluetooth. Вы можете обратиться к Sphero SDK, чтобы получить больше информации. Мы хотим обработать соединение в сервисе Android:

1
2
3
public class BallConnectionService extends Service {
..
}

теперь в onStartCommand мы начинаем подключаться к Sphero и одновременно начинаем прослушивать входящее событие температуры (строка 8).

01
02
03
04
05
06
07
08
09
10
11
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
   if (mySphero == null)
     doConnection();
 
   IntentFilter rec = new IntentFilter();
   rec.addAction(SensorService.TEMP_BALL_SENSOR);
   registerReceiver(receiver, rec);
 
   return Service.START_STICKY;
}

в doConnection мы устанавливаем реальное соединение:

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
46
47
48
49
private void doConnection() {
 
     sendStatus(CONNECTING);
     createNotification("Connecting...");
 
     RobotProvider.getDefaultProvider().addConnectionListener(new ConnectionListener() {
         @Override
          public void onConnected(Robot robot) {
             Log.d("Temp", "Connected");
             mySphero = (Sphero) robot;
             sendStatus(CONNECTED);
             createNotification("Connected");
          }
 
          @Override
          public void onConnectionFailed(Robot robot) {
              Log.d("Temp", "Conection failed");
              sendStatus(FAILED);
          }
 
          @Override
          public void onDisconnected(Robot robot) {
              Log.d("Temp", "Disconnected");
              mySphero = null;
              createNotification("Disconnected!");
          }
      });
 
      RobotProvider.getDefaultProvider().addDiscoveryListener(new DiscoveryListener() {
          @Override
          public void onBluetoothDisabled() {
               Log.d("Temp", "BT Disabled");
           }
 
           @Override
           public void discoveryComplete(List<Sphero> spheros) {
               Log.d("Temp", "Found ["+spheros.size()+"]");
           }
 
           @Override
           public void onFound(List<Sphero> spheros) {
              // Do connection
              Log.d("Temp", "Found ball");
              RobotProvider.getDefaultProvider().connect(spheros.get(0));
           }
        });
 
        boolean success = RobotProvider.getDefaultProvider().startDiscovery(this);
  }

Код кажется сложным, но он действительно прост, если вы внимательно посмотрите на него. Мы начинаем трансляцию события, которое мы пытаемся подключить к Sphero (строка 3), затем, используя Sphere API, мы регистрируем прослушиватель, чтобы узнать, когда соединение установлено, и транслируем новое событие, что соединение активно, в конце этого метода мы начинаем обнаруживать, если новый Sphero и готов к подключению.

Последняя часть сервиса используется для прослушивания температурного события и установки цветного шара:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        float val = intent.getFloatExtra("value", 0);
        Log.d("Temp", "Received value ["+val+"]");
        if (mySphero != null) {
           // send color to sphero
 
           int red = (int) (255 * val / RANGE) * (val > 10 ? 1 : 0);
           int green = (int) ( (255 * (RANGE - Math.abs(val)) / RANGE) * (val < 10 ? 0.2 : 1) );
           int blue = (int) (255 * (10 - val) / 10) * (val < 10  ? 1 : 0);
 
           mySphero.setColor(red, green, blue);
        }
      }
 ;

Создать активность

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

1
2
3
4
5
PendingIntent pi = createAlarm();
AlarmManager scheduler = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
scheduler.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60 * 1000, pi);
Intent i1 = new Intent(this, BallConnectionService.class);
startService(i1);

В этом простом коде мы создаем PendingIntent и получаем ссылку на AlarmManager , наконец, мы планируем тревогу так, чтобы служба могла быть запущена через фиксированный промежуток времени. (строка 3). В методе createAlarm () мы устанавливаем намерение:

1
2
3
4
5
6
private PendingIntent createAlarm() {
    AlarmManager scheduler = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this,SensorService.class );
    PendingIntent scheduledIntent = PendingIntent.getService(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    return scheduledIntent;
}

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

1
2
3
4
5
6
7
private BroadcastReceiver sensorReceiver = new BroadcastReceiver() {
   @Override
   public void onReceive(Context context, Intent intent) {
       float val = intent.getFloatExtra("value", 0);
       tempView.setText(String.format("%.1f",val));
    }
 };

В строке 5 мы показываем текущую температуру, а для обслуживания мяча имеем:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
private BroadcastReceiver ballReceiver = new BroadcastReceiver() {
   @Override
   public void onReceive(Context context, Intent intent) {
       int status = intent.getIntExtra("status", -1000);
 
       Log.d("Temp", "Value Status ["+status+"]");
       if  (status == BallConnectionService.CONNECTING) {
           tempView.startAnimation(pulseAnim);
           Toast.makeText(MyActivity.this, "Connecting...", Toast.LENGTH_SHORT).show();
        }
        else if (status == BallConnectionService.CONNECTED) {
            tempView.clearAnimation();
            Intent i = new Intent(MyActivity.this, SensorService.class);
            startService(i);
            Toast.makeText(MyActivity.this, "Connected", Toast.LENGTH_LONG).show();
        }
        else if (status == BallConnectionService.FAILED) {
            Toast.makeText(MyActivity.this, "Connection failed. Try again pressing start button", Toast.LENGTH_LONG).show();
        }
 
      }
    };
  • Исходный код скоро будет доступен @ github.
Ссылка: Управляйте Sphero с помощью датчика температуры в Android от нашего партнера JCG Франческо Аццолы в блоге Surviving w / Android .