1.Tìm hiểu Beacon và cơ chế hoạt động

Beacon là thiết bị điện tử nhỏ phát ra tín hiệu bluetooth năng lượng thấp Bluetooth Low Energy (BLE). Bất kỳ thiết bị nào có công nghệ BLE đều có thể bắt được tín hiệu này, chẳng hạn điện thoại thông minh và máy tính bảng. Công nghệ mới này tạo ra cuộc cách mạnh hóa cho quyết định của các công ty về phương thức tùy chỉnh sản phẩm và dịch vụ của mình hướng đến khách hàng.
Để tìm hiểu hoạt động của Beacons ta tìm hiểu trước tiên về BLE.

1.1 BLE – Bluetooth Low Energy

Beacons sử dụng công nghệ BLE (Bluetooth Low Energy), còn được gọi là Bluetooth Smart. BLE sử dụng giao thức khác Classic Bluetooth, và không tương thích ngược. BLE sử dụng cùng băng tần 2.4GHz.
Có hai kiểu thiết bị BLE:
+) Bluetooth Smart Ready: hỗ trợ cả BLE và Classic Bluetooth.
+) Bluetooth Smart: chỉ hỗ trợ BLE
Hầu hết điện thoại và máy tính mới đều hỗ trợ Bluetooth Smart Ready, còn beacons chỉ là BLE không hỗ trợ Classic Bluetooth.
Ưu thế lớn nhất của BLE là tiết kiệm năng lượng, cho phép beacons truyền thông tin liên tục lên đến 2-3 năm chỉ với một viên pin nhỏ. Khoảng cách truyền BLE cũng lên đến 100m như Classic Bluetooth.
BLE có hai chế độ trao đổi thông tin:
Advertising: chỉ truyền một chiều
Connecting: trao đổi hai chiều
Beacons chỉ sử dụng chế độ truyền advertising (chỉ gửi thông tin một chiều). Beacons theo một chu kỳ sẽ phát thông tin quảng bá để các thiết bị khác như smartphone nhận. Beacons có thể phát với chu kỳ từ 20ms đến 10s, chu kỳ càng dài thì thời lượng pin càng lâu.

1.2 Định dạng gói tin của Beacons là gì?

Một gói tin để các thiết bị đọc được phải tuân theo các chuẩn đã được định trước, trước tiên là gói dữ liệu advertising.Một gói tin advertising có độ dài lên đến 47 bytes.

1.3 Phân loại Beacon.

  • IBeacon
    Là giao thức BLE được Apple đưa ra 12/2013, đây là một bộ giao thức chính thức đầu tiên về BLE, đa số mọi beacons đều hỗ trợ. Giao thức này được hỗ trợ chỉ trên iOS, nhưng hiện nay có thể tìm rất nhiều hàm API hỗ trợ tìm kiếm các iBeacon trên Android. Cần có một ứng dụng để tìm kiếm beacons và thực hiện các thao tác với chúng.
    iBeacon hỗ trợ hai kiểu tương tác, giám sát (monitoring) và vùng phủ (ranging). Với chế độ giám sát ứng dụng sẽ cảnh báo ngay cả khi ứng dụng đã tắt. Khác chế độ giám sát, chế độ cự ly chỉ hoạt động khi ứng dụng đang chạy.
    Với iBeacon thì các beacon sẽ phát ra dữ liệu gì?, chúng phát ba thông tin UUID, Major, và Minor. Sẽ không bao giờ có hai beacon cùng UUID, Major, và Minor.
  • Eddystone
    Là giao thức BLE do Google công bố 7/2015, được hỗ trợ chính thức trên cả hai nền tảng iOS và Android. Là một giao thức mở và hỗ trợ nhiều gói tin khác nhau. Chỉ hỗ trợ một kiểu tương tác cơ bản, gần giống với vùng phủ của iBeacon.
    Các gói tin của Eddystone gồm có:
    Eddystone-UID: gần giống gói tin của iBeacon, gồm các thông tin Namespace (chức năng giống UUID của iBeacon) và Instance (chức năng giống Major và Minor của iBeacon)
    Eddystone-URL: gửi thông tin một đường dẫn trang web. Với gói tin này trên điện thoại sẽ mở trang web và ko cần cái ứng dụng.
    Eddystone-TLM: là gói tin gửi các thông tin của beacons như điện áp pin, nhiệt độ, số gói tin đã gửi, và thời gian bật beacons. Gói tin này sẽ gửi với chu kỳ dài hơn hai gói trên.
    Eddystone có thể thay thế iBeacon?
    +) Hỗ trợ chính thức trên iOS và Android.
    +) Hỗ trợ 3 loại gói tin khác nhau.
    +) Không cần cái ứng dụng.
    +) Là một giao thức mở hỗ trợ đa nền tảng.
    Thôi lan man thế là đủ rồi , giờ mình sẽ vào phần chính luôn .

2.Lập trình với beacon

2.1 Thiết bị

Đầu tiên , bạn cần phải có cục beacon(tất nhiên rồi ) ,beacon có nhiều loại với nhiều hãng , mình thì sử dụng beacon của estimote , nó có hình dáng như thế này :

(giống 1 cục tẩy to có gắn chữ estimote)
Bên trong của nó thì như này :

Bên trong của nó là 1 thiết bị phát tín hiệu bluetooth , mặt sau thì là 1 lớp dính có thể gắn lên các bề mặt như mặt tường , mặt bàn .....

2.2 Lập trình

Để sử dụng được lib thì ta phải thêm dòng này vào gradle :

dependencies {
  compile 'com.estimote:sdk:1.0.3:release@aar'
}

Nếu target version của bạn là 23 đổ lên thì phải thêm dòng này vào ACCESS_COARSE_LOCATION permission vào Manifest nữa

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

Bản thân Sdk cũng hỗ trợ phần request permission cho chúng ta , chỉ cần thêm lệnh này vào onCreate():

   SystemRequirementsChecker.checkWithDefaultDialogs(this);

Lệnh này sẽ gọi permission của bluetooth , Location vv......

2.2.1 Beacon regions

Mỗi beacon được định nghĩa bởi 3 giá trị :

    +) UUID, hiển thị dưới dạng string  ,ví dụ :  “B9407F30-F5F8-466E-AFF9-25556B57FE6D”
    +) major number, dạng  unsigned short integer, là  integer trong khoảng 1 to 65535, (0 là reserved valuemajor number, dạng  unsigned short integer, là  integer trong khoảng 1 to 65535, (0 là reserved value)
    +) minor number, cũng là unsigned short integer, giống major number.

2.2.2 Beacon Manager

Để tương tác với lớp beacon , ta sẽ dùng lớp beacon manager , lớp này giúp ta tương tác với beacon .
Đa phần đều muốn quản lí beacon trong suốt thời gian chạy app (không cần biết là activity nào đang sử dụng) ,để làm điều đó , ta phải khởi tạo và lưu trữ đối tượng BeaconManager trong 1 subclass của Application(extend từ Application class)

package com.example.airport;

import android.app.Application;
import com.estimote.sdk.BeaconManager;

public class MyApplication extends Application {

    private BeaconManager beaconManager;

    @Override
    public void onCreate() {
        super.onCreate();

        beaconManager = new BeaconManager(getApplicationContext());
     }
}

Tiếp theo là khai báo nó trong manifest :

<application
    <!-- add this: -->
    android:name=".MyApplication"
    <!-- the rest of the file follows -->
    android:allowBackup="true"
    <!-- etc. ... -->

còn nếu bạn muốn sử dụng nó riêng trong activity thì vẫn được thôi , thay vì getApplicationContext , chúng ta chỉ cần truyền vào context của Activity là được

    private BeaconManager mBeaconManager;

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      mBeaconManager = new BeaconManager(this);
    }

Để test thì thì bạn có thể monitor theo riêng 1 cái beacon :

beaconManager = new BeaconManager(getApplicationContext());
// add this below:
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
    @Override
    public void onServiceReady() {
        beaconManager.startMonitoring(new Region(
                "monitored region",
                UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"),
                22504, 48827));
    }
});

Để biết dc UUID của beacon thì có 2 cách , 1 là bạn lên Estimote Cloud , đăng nhập và lấy thông tin của beacon để nhập vào ,
2 là bạn dùng hàm setRangingListener của beacon manager để lấy UUID của các beacon .
Sau bước này thì ta có thể show ra thông tin của beacon bằng notification :

public void showNotification(String title, String message) {
    Intent notifyIntent = new Intent(this, MainActivity.class);
    notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivities(this, 0,
            new Intent[] { notifyIntent }, PendingIntent.FLAG_UPDATE_CURRENT);
    Notification notification = new Notification.Builder(this)
            .setSmallIcon(android.R.drawable.ic_dialog_info)
            .setContentTitle(title)
            .setContentText(message)
            .setAutoCancel(true)
            .setContentIntent(pendingIntent)
            .build();
    notification.defaults |= Notification.DEFAULT_SOUND;
    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(1, notification);
}

Và notification đó sẽ hiện lên mỗi khi người dùng bước vào range của beacon :

// find this line:
beaconManager = new BeaconManager(getApplicationContext());
// add this below:
beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() {
    @Override
    public void onEnteredRegion(Region region, List<Beacon> list) {
        showNotification(
                "Your gate closes in 47 minutes.",
                "Current security wait time is 15 minutes, "
                        + "and it's a 5 minute walk from security to the gate. "
                        + "Looks like you've got plenty of time!");
    }
    @Override
    public void onExitedRegion(Region region) {
        // could add an "exit" notification too if you want (-:
    }
});

Mình sẽ kết thúc phần 1 ở đấy , phần 2 mình sẽ nói chi tiết hơn về cách quét và xử lí thông tin của beacon .