Questo e' un tentativo di realizzare un homekit, un sistema di domotica, che permetta di accendere dei dispositivi con un sensore di prossimita' (tipo il lampadario quando si entra in una stanza)
I componenti di questo kit sono
1) un orologio con Android Wear
2) un Raspberry (qualsiasi modello) con un dongle Bluetooth LE
3) un rele
L'orologio e' stato programmato come emettitore di beacon (e' possibile modificare il valore del minor in modo da personalizzarlo)
Di seguito il codice Android
--------------------------------------
apply plugin: 'com.android.application'
android {
compileSdkVersion 21 buildToolsVersion "21.1.2"
defaultConfig {
applicationId "luca_innocenti.beacontrasmitter" minSdkVersion 21 targetSdkVersion 21 versionCode 1 versionName "1.0" }
buildTypes {
release {
minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' }
}
}
final def var = repositories {
jcenter{
url "http://jcenter.bintray.com/" }
}
var
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.android.support:wearable:1.2.0' compile 'com.google.android.gms:play-services-wearable:7.5.0'}
dependencies {
compile 'org.altbeacon:android-beacon-library:2+'
}
--------------------------------------
--------------------------------------
package luca_innocenti.beacontrasmitter;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.wearable.view.WatchViewStub;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.pm.PackageManager;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.BeaconTransmitter;
import org.altbeacon.beacon.Identifier;
import java.util.Arrays;
@TargetApi(21)
public class MainActivity extends Activity {
private BeaconTransmitter mBeaconTransmitter;
private TextView testo;
private SeekBar barra;
private Button pulsante;
private int stato;
private TextView testo2;
private TextView testo3;
private void trasmetti(){
if (checkPrerequisites()) {
// //mBeaconTransmitter = new BeaconTransmitter(this, new BeaconParser().setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25")); mBeaconTransmitter = new BeaconTransmitter(this, new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
//beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24")); // iBeacons
//beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")); // Estimotes
//beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:0-3=a7ae2eb7,i:4-19,i:20-21,i:22-23,p:24-24")); // easiBeacons
// uuid estimote B9407F30-F5F8-466E-AFF9-25556B57FE6D
Beacon beacon = new Beacon.Builder()
.setId1("B9407F30-F5F8-466E-AFF9-25556B57FE6D")
.setId2("999")
.setId3(testo.getText().toString())
.setManufacturer(0x015D) // Simula Estimote .setTxPower(-59)
.setDataFields(Arrays.asList(new Long[]{0l}))
.build();
mBeaconTransmitter.startAdvertising(beacon);
stato = 1;
}
}
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
@Override public void onLayoutInflated(WatchViewStub stub) {
barra = (SeekBar) stub.findViewById(R.id.seekBar);
testo = (TextView) stub.findViewById(R.id.textView);
testo2 = (TextView) stub.findViewById(R.id.textView2);
testo3 = (TextView) stub.findViewById(R.id.textView3);
pulsante = (Button) stub.findViewById(R.id.button);
barra.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
testo.setText(String.valueOf(new Integer(progress)));
}
@Override public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override public void onStopTrackingTouch(SeekBar seekBar) {
}
}
);
pulsante.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
testo2.setText("Trasmitter ON");
testo3.setText("B9407F30-F5F8-466E-AF\nF9-25556B-57FE6D-999-"+testo.getText());
pulsante.setEnabled(false);
barra.setEnabled(false);
trasmetti();
}
});
}
});
}
@Override protected void onDestroy() {
super.onDestroy();
if (stato == 1) {
mBeaconTransmitter.stopAdvertising();
}
}
@TargetApi(21)
private boolean checkPrerequisites() {
if (android.os.Build.VERSION.SDK_INT < 18) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not supported by this device's operating system");
builder.setMessage("You will not be able to transmit as a Beacon");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override public void onDismiss(DialogInterface dialog) {
finish();
}
});
builder.show();
return false;
}
if (!getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not supported by this device");
builder.setMessage("You will not be able to transmit as a Beacon");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override public void onDismiss(DialogInterface dialog) {
finish();
}
});
builder.show();
return false;
}
if (!((BluetoothManager) getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter().isEnabled()){
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable Bluetooth and restart this app.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override public void onDismiss(DialogInterface dialog) {
finish();
}
});
builder.show();
return false;
}
try {
// Check to see if the getBluetoothLeAdvertiser is available. If not, this will throw an exception indicating we are not running Android L ((BluetoothManager) this.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter().getBluetoothLeAdvertiser();
}
catch (Exception e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE advertising unavailable");
builder.setMessage("Sorry, the operating system on this device does not support Bluetooth LE advertising. As of July 2014, only the Android L preview OS supports this feature in user-installed apps.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override public void onDismiss(DialogInterface dialog) {
finish();
}
});
builder.show();
return false;
}
return true;
}
}
--------------------------------------
Per leggere la prossimita' dell'orologio ho montato sulla Raspberry un dongle Broadcome (gia' visto qui) ed il programma in Python iBeacon-Scanner (Github) leggermente modificato
Il programma cicla fino quando non vede un dispositivo con minor=1, allora controlla l'Rssi e stima la distanza. Se la distanza e' inferiore ad un determinato valore si puo' agire sulle porte GPIO ed attivare il rele' (funzione da implementare ma di facilissima realizzazione)
--------------------------------------
import blescan
import sys
import bluetooth._bluetooth as bluez
dev_id = 0
try:
sock = bluez.hci_open_dev(dev_id)
#print "ble thread started"
except:
print "error accessing bluetooth device..."
sys.exit(1)
blescan.hci_le_set_scan_parameters(sock)
blescan.hci_enable_le_scan(sock)
while True:
returnedList = blescan.parse_events(sock, 10)
#print "----------"
for beacon in returnedList:
#print beacon
valori = beacon.split(",")
mac = valori[0]
uuid = valori[1]
major = valori[2]
minor = valori[3]
rssi = valori[4]
rssi2 = valori[5]
#print minor
if (minor == "1"):
#print minor+" "+rssi2
if (int(rssi2) > -75):
print "vicino"
else:
print "lontano"
--------------------------------------