parent
e05906fed5
commit
971185decf
@ -0,0 +1,121 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.bmonitor;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import agent.sense.android.iot.carbon.wso2.org.wso2_senseagent.R;
|
||||
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
|
||||
import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
|
||||
|
||||
public class BeaconMonitoringActivity extends AppCompatActivity {
|
||||
|
||||
private BluetoothLeScanner mScanner;
|
||||
private BluetoothUtils mBluetoothUtils;
|
||||
private LeDeviceListAdapter mLeDeviceListAdapter;
|
||||
private BluetoothLeDeviceStore mDeviceStore;
|
||||
|
||||
protected ListView mList;
|
||||
|
||||
public static final int MINIMUM_DISTANCE = -70;
|
||||
|
||||
public static Map itemMap;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_beacon_monitoring);
|
||||
|
||||
itemMap = new HashMap<String, String>();
|
||||
itemMap.put("DC:5F:BD:68:88:D5", "Noodles");
|
||||
itemMap.put("EF:0F:50:D5:BA:A1", "Vegetables");
|
||||
itemMap.put("FA:F2:CF:84:C2:F7", "Oil");
|
||||
|
||||
mList = (ListView) this.findViewById(android.R.id.list);
|
||||
|
||||
mDeviceStore = new BluetoothLeDeviceStore();
|
||||
mBluetoothUtils = new BluetoothUtils(this);
|
||||
mScanner = new BluetoothLeScanner(mLeScanCallback, mBluetoothUtils);
|
||||
startScan();
|
||||
}
|
||||
|
||||
private final BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
|
||||
@Override
|
||||
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
|
||||
final BluetoothLeDevice deviceLe = new BluetoothLeDevice(device, rssi, scanRecord, System.currentTimeMillis());
|
||||
if(deviceLe!= null && deviceLe.getName()!= null && !deviceLe.getName().equals("Unknown Device")){
|
||||
mDeviceStore.addDevice(deviceLe);
|
||||
|
||||
if(deviceLe.getRssi() > MINIMUM_DISTANCE){
|
||||
Object[] objects = new Object[4];
|
||||
objects[0] = deviceLe.getName();
|
||||
objects[1] = deviceLe.getAddress();
|
||||
objects[2] = deviceLe.getRssi();
|
||||
objects[3] = itemMap.get(device.getAddress());
|
||||
|
||||
new SendToSiddi().execute(objects);
|
||||
}
|
||||
|
||||
|
||||
final EasyObjectCursor<BluetoothLeDevice> c = mDeviceStore.getDeviceCursor();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLeDeviceListAdapter.swapCursor(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void startScan() {
|
||||
|
||||
mLeDeviceListAdapter = new LeDeviceListAdapter(this, mDeviceStore.getDeviceCursor());
|
||||
mList.setAdapter(mLeDeviceListAdapter);
|
||||
|
||||
final boolean mIsBluetoothOn = mBluetoothUtils.isBluetoothOn();
|
||||
final boolean mIsBluetoothLePresent = mBluetoothUtils.isBluetoothLeSupported();
|
||||
mBluetoothUtils.askUserToEnableBluetoothIfNeeded();
|
||||
if (mIsBluetoothOn && mIsBluetoothLePresent) {
|
||||
mScanner.scanLeDevice(-1, true);
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SendToSiddi extends AsyncTask<Object, Object, Void>{
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Object... objects) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.bmonitor;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconDevice;
|
||||
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
|
||||
import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
|
||||
|
||||
public class BluetoothLeDeviceStore {
|
||||
private final Map<String, BluetoothLeDevice> mDeviceMap;
|
||||
|
||||
|
||||
public BluetoothLeDeviceStore() {
|
||||
mDeviceMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public void addDevice(final BluetoothLeDevice device) {
|
||||
if (mDeviceMap.containsKey(device.getAddress())) {
|
||||
mDeviceMap.get(device.getAddress()).updateRssiReading(device.getTimestamp(), device.getRssi());
|
||||
} else {
|
||||
mDeviceMap.put(device.getAddress(), device);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
mDeviceMap.clear();
|
||||
}
|
||||
|
||||
public EasyObjectCursor<BluetoothLeDevice> getDeviceCursor() {
|
||||
return new EasyObjectCursor<>(
|
||||
BluetoothLeDevice.class,
|
||||
getDeviceList(),
|
||||
"address");
|
||||
}
|
||||
|
||||
public List<BluetoothLeDevice> getDeviceList() {
|
||||
final List<BluetoothLeDevice> methodResult = new ArrayList<>(mDeviceMap.values());
|
||||
|
||||
Collections.sort(methodResult, new Comparator<BluetoothLeDevice>() {
|
||||
|
||||
@Override
|
||||
public int compare(final BluetoothLeDevice arg0, final BluetoothLeDevice arg1) {
|
||||
return arg0.getAddress().compareToIgnoreCase(arg1.getAddress());
|
||||
}
|
||||
});
|
||||
|
||||
return methodResult;
|
||||
}
|
||||
|
||||
private String getListAsCsv() {
|
||||
final List<BluetoothLeDevice> list = getDeviceList();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(CsvWriterHelper.addStuff("mac"));
|
||||
sb.append(CsvWriterHelper.addStuff("name"));
|
||||
sb.append(CsvWriterHelper.addStuff("firstTimestamp"));
|
||||
sb.append(CsvWriterHelper.addStuff("firstRssi"));
|
||||
sb.append(CsvWriterHelper.addStuff("currentTimestamp"));
|
||||
sb.append(CsvWriterHelper.addStuff("currentRssi"));
|
||||
sb.append(CsvWriterHelper.addStuff("adRecord"));
|
||||
sb.append(CsvWriterHelper.addStuff("iBeacon"));
|
||||
sb.append(CsvWriterHelper.addStuff("uuid"));
|
||||
sb.append(CsvWriterHelper.addStuff("major"));
|
||||
sb.append(CsvWriterHelper.addStuff("minor"));
|
||||
sb.append(CsvWriterHelper.addStuff("txPower"));
|
||||
sb.append(CsvWriterHelper.addStuff("distance"));
|
||||
sb.append(CsvWriterHelper.addStuff("accuracy"));
|
||||
sb.append('\n');
|
||||
|
||||
for (final BluetoothLeDevice device : list) {
|
||||
sb.append(CsvWriterHelper.addStuff(device.getAddress()));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getName()));
|
||||
sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getFirstTimestamp())));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getFirstRssi()));
|
||||
sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getTimestamp())));
|
||||
sb.append(CsvWriterHelper.addStuff(device.getRssi()));
|
||||
sb.append(CsvWriterHelper.addStuff(ByteUtils.byteArrayToHexString(device.getScanRecord())));
|
||||
final boolean isIBeacon = BeaconUtils.getBeaconType(device) == BeaconType.IBEACON;
|
||||
final String uuid;
|
||||
final String minor;
|
||||
final String major;
|
||||
final String txPower;
|
||||
final String distance;
|
||||
final String accuracy;
|
||||
|
||||
if (isIBeacon) {
|
||||
final IBeaconDevice beacon = new IBeaconDevice(device);
|
||||
uuid = String.valueOf(beacon.getUUID());
|
||||
minor = String.valueOf(beacon.getMinor());
|
||||
major = String.valueOf(beacon.getMajor());
|
||||
txPower = String.valueOf(beacon.getCalibratedTxPower());
|
||||
distance = beacon.getDistanceDescriptor().toString().toLowerCase(Locale.US);
|
||||
accuracy = String.valueOf(beacon.getAccuracy());
|
||||
} else {
|
||||
uuid = "";
|
||||
minor = "";
|
||||
major = "";
|
||||
txPower = "";
|
||||
distance = "";
|
||||
accuracy = "";
|
||||
}
|
||||
|
||||
sb.append(CsvWriterHelper.addStuff(isIBeacon));
|
||||
sb.append(CsvWriterHelper.addStuff(uuid));
|
||||
sb.append(CsvWriterHelper.addStuff(minor));
|
||||
sb.append(CsvWriterHelper.addStuff(major));
|
||||
sb.append(CsvWriterHelper.addStuff(txPower));
|
||||
sb.append(CsvWriterHelper.addStuff(distance));
|
||||
sb.append(CsvWriterHelper.addStuff(accuracy));
|
||||
|
||||
sb.append('\n');
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void shareDataAsEmail(final Context context) {
|
||||
final long timeInMillis = System.currentTimeMillis();
|
||||
|
||||
final String to = null;
|
||||
final String subject = "";
|
||||
|
||||
final String message = "";
|
||||
|
||||
final Intent i = new Intent(Intent.ACTION_SEND);
|
||||
i.setType("plain/text");
|
||||
try {
|
||||
final File outputDir = context.getCacheDir();
|
||||
final File outputFile = File.createTempFile("bluetooth_le_" + timeInMillis, ".csv", outputDir);
|
||||
outputFile.setReadable(true, false);
|
||||
generateFile(outputFile, getListAsCsv());
|
||||
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(outputFile));
|
||||
i.putExtra(Intent.EXTRA_EMAIL, new String[]{to});
|
||||
i.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
i.putExtra(Intent.EXTRA_TEXT, message);
|
||||
context.startActivity(Intent.createChooser(i, "Email Subject"));
|
||||
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static FileWriter generateFile(final File file, final String contents) {
|
||||
FileWriter writer = null;
|
||||
try {
|
||||
writer = new FileWriter(file);
|
||||
writer.append(contents);
|
||||
writer.flush();
|
||||
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.bmonitor;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
public class BluetoothLeScanner {
|
||||
private final Handler mHandler;
|
||||
private final BluetoothAdapter.LeScanCallback mLeScanCallback;
|
||||
private final BluetoothUtils mBluetoothUtils;
|
||||
private boolean mScanning;
|
||||
|
||||
public BluetoothLeScanner(final BluetoothAdapter.LeScanCallback leScanCallback, final BluetoothUtils bluetoothUtils) {
|
||||
mHandler = new Handler();
|
||||
mLeScanCallback = leScanCallback;
|
||||
mBluetoothUtils = bluetoothUtils;
|
||||
}
|
||||
|
||||
public boolean isScanning() {
|
||||
return mScanning;
|
||||
}
|
||||
|
||||
public void scanLeDevice(final int duration, final boolean enable) {
|
||||
if (enable) {
|
||||
if (mScanning) {
|
||||
return;
|
||||
}
|
||||
Log.d("TAG", "~ Starting Scan");
|
||||
// Stops scanning after a pre-defined scan period.
|
||||
if (duration > 0) {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d("TAG", "~ Stopping Scan (timeout)");
|
||||
mScanning = false;
|
||||
mBluetoothUtils.getBluetoothAdapter().stopLeScan(mLeScanCallback);
|
||||
}
|
||||
}, duration);
|
||||
}
|
||||
mScanning = true;
|
||||
mBluetoothUtils.getBluetoothAdapter().startLeScan(mLeScanCallback);
|
||||
} else {
|
||||
Log.d("TAG", "~ Stopping Scan");
|
||||
mScanning = false;
|
||||
mBluetoothUtils.getBluetoothAdapter().stopLeScan(mLeScanCallback);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.bmonitor;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
public final class BluetoothUtils {
|
||||
public final static int REQUEST_ENABLE_BT = 2001;
|
||||
private final Activity mActivity;
|
||||
private final BluetoothAdapter mBluetoothAdapter;
|
||||
|
||||
public BluetoothUtils(final Activity activity) {
|
||||
mActivity = activity;
|
||||
final BluetoothManager btManager = (BluetoothManager) mActivity.getSystemService(Context.BLUETOOTH_SERVICE);
|
||||
mBluetoothAdapter = btManager.getAdapter();
|
||||
}
|
||||
|
||||
public void askUserToEnableBluetoothIfNeeded() {
|
||||
if (isBluetoothLeSupported() && (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled())) {
|
||||
final Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
mActivity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
|
||||
}
|
||||
}
|
||||
|
||||
public BluetoothAdapter getBluetoothAdapter() {
|
||||
return mBluetoothAdapter;
|
||||
}
|
||||
|
||||
public boolean isBluetoothLeSupported() {
|
||||
return mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
|
||||
}
|
||||
|
||||
public boolean isBluetoothOn() {
|
||||
if (mBluetoothAdapter == null) {
|
||||
return false;
|
||||
} else {
|
||||
return mBluetoothAdapter.isEnabled();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.bmonitor;
|
||||
|
||||
public class CsvWriterHelper {
|
||||
private static final String QUOTE = "\"";
|
||||
|
||||
public static String addStuff(final Integer text) {
|
||||
return QUOTE + text + QUOTE + ",";
|
||||
}
|
||||
|
||||
public static String addStuff(final Long text) {
|
||||
return QUOTE + text + QUOTE + ",";
|
||||
}
|
||||
|
||||
public static String addStuff(final boolean value) {
|
||||
return QUOTE + value + QUOTE + ",";
|
||||
}
|
||||
|
||||
public static String addStuff(String text) {
|
||||
if (text == null) {
|
||||
text = "<blank>";
|
||||
}
|
||||
text = text.replace(QUOTE, "'");
|
||||
|
||||
return QUOTE + text.trim() + QUOTE + ",";
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.bmonitor;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.v4.widget.SimpleCursorAdapter;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import agent.sense.android.iot.carbon.wso2.org.wso2_senseagent.R;
|
||||
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
|
||||
import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconDevice;
|
||||
import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
|
||||
|
||||
public class LeDeviceListAdapter extends SimpleCursorAdapter {
|
||||
private final LayoutInflater mInflator;
|
||||
private final Activity mActivity;
|
||||
|
||||
public static final DecimalFormat DOUBLE_TWO_DIGIT_ACCURACY = new DecimalFormat("#.##");
|
||||
public static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
public LeDeviceListAdapter(final Activity activity, final EasyObjectCursor<BluetoothLeDevice> cursor) {
|
||||
super(activity, R.layout.list_item_device, cursor, new String[0], new int[0], 0);
|
||||
mInflator = activity.getLayoutInflater();
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public EasyObjectCursor<BluetoothLeDevice> getCursor() {
|
||||
return ((EasyObjectCursor<BluetoothLeDevice>) super.getCursor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BluetoothLeDevice getItem(final int i) {
|
||||
return getCursor().getItem(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(final int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int i, View view, final ViewGroup viewGroup) {
|
||||
final ViewHolder viewHolder;
|
||||
// General ListView optimization code.
|
||||
if (view == null) {
|
||||
view = mInflator.inflate(R.layout.list_item_device, null);
|
||||
viewHolder = new ViewHolder();
|
||||
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
|
||||
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
|
||||
viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi);
|
||||
viewHolder.deviceIcon = (ImageView) view.findViewById(R.id.device_icon);
|
||||
viewHolder.deviceLastUpdated = (TextView) view.findViewById(R.id.device_last_update);
|
||||
viewHolder.ibeaconMajor = (TextView) view.findViewById(R.id.ibeacon_major);
|
||||
viewHolder.ibeaconMinor = (TextView) view.findViewById(R.id.ibeacon_minor);
|
||||
viewHolder.ibeaconDistance = (TextView) view.findViewById(R.id.ibeacon_distance);
|
||||
viewHolder.ibeaconUUID = (TextView) view.findViewById(R.id.ibeacon_uuid);
|
||||
viewHolder.ibeaconTxPower = (TextView) view.findViewById(R.id.ibeacon_tx_power);
|
||||
viewHolder.ibeaconSection = view.findViewById(R.id.ibeacon_section);
|
||||
viewHolder.ibeaconDistanceDescriptor = (TextView) view.findViewById(R.id.ibeacon_distance_descriptor);
|
||||
view.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) view.getTag();
|
||||
}
|
||||
|
||||
final BluetoothLeDevice device = getCursor().getItem(i);
|
||||
final String deviceName = device.getName();
|
||||
|
||||
final double rssi = device.getRssi();
|
||||
|
||||
if (deviceName != null && deviceName.length() > 0) {
|
||||
viewHolder.deviceName.setText(deviceName + " (" + BeaconMonitoringActivity.itemMap.get(device.getAddress()) + ")");
|
||||
} else {
|
||||
viewHolder.deviceName.setText(R.string.unknown_device);
|
||||
}
|
||||
|
||||
|
||||
if (BeaconUtils.getBeaconType(device) == BeaconType.IBEACON) {
|
||||
final IBeaconDevice iBeacon = new IBeaconDevice(device);
|
||||
final String accuracy = DOUBLE_TWO_DIGIT_ACCURACY.format(iBeacon.getAccuracy());
|
||||
|
||||
viewHolder.deviceIcon.setImageResource(R.drawable.beacon);
|
||||
viewHolder.ibeaconSection.setVisibility(View.VISIBLE);
|
||||
viewHolder.ibeaconMajor.setText(String.valueOf(iBeacon.getMajor()));
|
||||
viewHolder.ibeaconMinor.setText(String.valueOf(iBeacon.getMinor()));
|
||||
viewHolder.ibeaconTxPower.setText(String.valueOf(iBeacon.getCalibratedTxPower()));
|
||||
viewHolder.ibeaconUUID.setText(iBeacon.getUUID());
|
||||
viewHolder.ibeaconDistance.setText(
|
||||
mActivity.getString(R.string.formatter_meters, accuracy));
|
||||
viewHolder.ibeaconDistanceDescriptor.setText(iBeacon.getDistanceDescriptor().toString());
|
||||
} else {
|
||||
if(device.getRssi() > BeaconMonitoringActivity.MINIMUM_DISTANCE){
|
||||
viewHolder.deviceIcon.setImageResource(R.drawable.beacon_red);
|
||||
}else{
|
||||
viewHolder.deviceIcon.setImageResource(R.drawable.beacon);
|
||||
}
|
||||
|
||||
viewHolder.ibeaconSection.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
final String rssiString =
|
||||
mActivity.getString(R.string.formatter_db, String.valueOf(rssi));
|
||||
final String runningAverageRssiString =
|
||||
mActivity.getString(R.string.formatter_db, String.valueOf(device.getRunningAverageRssi()));
|
||||
|
||||
viewHolder.deviceLastUpdated.setText(
|
||||
android.text.format.DateFormat.format(
|
||||
TIME_FORMAT, new java.util.Date(device.getTimestamp())));
|
||||
viewHolder.deviceAddress.setText(device.getAddress());
|
||||
viewHolder.deviceRssi.setText(rssiString + " / " + runningAverageRssiString);
|
||||
return view;
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
TextView deviceName;
|
||||
TextView deviceAddress;
|
||||
TextView deviceRssi;
|
||||
TextView ibeaconUUID;
|
||||
TextView ibeaconMajor;
|
||||
TextView ibeaconMinor;
|
||||
TextView ibeaconTxPower;
|
||||
TextView ibeaconDistance;
|
||||
TextView ibeaconDistanceDescriptor;
|
||||
TextView deviceLastUpdated;
|
||||
View ibeaconSection;
|
||||
ImageView deviceIcon;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.bmonitor;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class TimeFormatter {
|
||||
private final static String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
|
||||
private final static SimpleDateFormat ISO_FORMATTER = new UtcDateFormatter(ISO_FORMAT, Locale.US);
|
||||
|
||||
public static String getIsoDateTime(final Date date) {
|
||||
return ISO_FORMATTER.format(date);
|
||||
}
|
||||
|
||||
public static String getIsoDateTime(final long millis) {
|
||||
return getIsoDateTime(new Date(millis));
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/**
|
||||
* ****************************************************************************
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
||||
* <p/>
|
||||
* GenieConnect Ltd. ("COMPANY") CONFIDENTIAL
|
||||
* Unpublished Copyright (c) 2010-2013 GenieConnect Ltd., All Rights Reserved.
|
||||
* <p/>
|
||||
* NOTICE:
|
||||
* All information contained herein is, and remains the property of COMPANY.
|
||||
* The intellectual and technical concepts contained herein are proprietary to
|
||||
* COMPANY and may be covered by U.S. and Foreign Patents, patents in process, and
|
||||
* are protected by trade secret or copyright law. Dissemination of this
|
||||
* information or reproduction of this material is strictly forbidden unless prior
|
||||
* written permission is obtained from COMPANY. Access to the source code
|
||||
* contained herein is hereby forbidden to anyone except current COMPANY employees,
|
||||
* managers or contractors who have executed Confidentiality and Non-disclosure
|
||||
* agreements explicitly covering such access.
|
||||
* <p/>
|
||||
* The copyright notice above does not evidence any actual or intended publication
|
||||
* or disclosure of this source code, which includes information that is
|
||||
* confidential and/or proprietary, and is a trade secret, of COMPANY.
|
||||
* <p/>
|
||||
* ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE, OR PUBLIC
|
||||
* DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT THE EXPRESS WRITTEN
|
||||
* CONSENT OF COMPANY IS STRICTLY PROHIBITED, AND IN VIOLATION OF APPLICABLE LAWS
|
||||
* AND INTERNATIONAL TREATIES. THE RECEIPT OR POSSESSION OF THIS SOURCE CODE
|
||||
* AND/OR RELATED INFORMATION DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE,
|
||||
* DISCLOSE OR DISTRIBUTE ITS CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING
|
||||
* THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.
|
||||
* ****************************************************************************
|
||||
*/
|
||||
package org.wso2.carbon.iot.android.sense.bmonitor;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class UtcDateFormatter extends java.text.SimpleDateFormat {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String TIME_ZONE_STRING = "UTC";
|
||||
private static final TimeZone TIME_ZONE_UTC = TimeZone.getTimeZone(TIME_ZONE_STRING);
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
public UtcDateFormatter(final String template) {
|
||||
super(template);
|
||||
super.setTimeZone(TIME_ZONE_UTC);
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
public UtcDateFormatter(final String template, final DateFormatSymbols symbols) {
|
||||
super(template, symbols);
|
||||
super.setTimeZone(TIME_ZONE_UTC);
|
||||
}
|
||||
|
||||
public UtcDateFormatter(final String template, final Locale locale) {
|
||||
super(template, locale);
|
||||
super.setTimeZone(TIME_ZONE_UTC);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will throw an UnsupportedOperationException.
|
||||
* You are not be able to change the TimeZone of this object
|
||||
*
|
||||
* (non-Javadoc)
|
||||
* @see java.text.DateFormat#setTimeZone(java.util.TimeZone)
|
||||
*/
|
||||
@Override
|
||||
public void setTimeZone(final TimeZone timezone) {
|
||||
throw new UnsupportedOperationException("This SimpleDateFormat can only be in " + TIME_ZONE_STRING);
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.siddhi.dto;
|
||||
|
||||
public class BLE {
|
||||
int id;
|
||||
long timeStamp;
|
||||
String location;
|
||||
|
||||
public BLE(int id, String location){
|
||||
this.id = id;
|
||||
this.location = location;
|
||||
timeStamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public long getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
public void setTimeStamp(long timeStamp) {
|
||||
this.timeStamp = timeStamp;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.siddhi.eventprocessor.core;
|
||||
|
||||
import org.wso2.carbon.iot.android.sense.siddhi.dto.BLE;
|
||||
import org.wso2.carbon.iot.android.sense.siddhi.eventprocessor.wrapper.SidhdhiWrapper;
|
||||
import org.wso2.siddhi.core.SiddhiManager;
|
||||
import org.wso2.siddhi.core.event.Event;
|
||||
import org.wso2.siddhi.core.stream.input.InputHandler;
|
||||
import org.wso2.siddhi.core.ExecutionPlanRuntime;
|
||||
import org.wso2.siddhi.core.stream.output.StreamCallback;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
|
||||
public class SidhdhiQueryExecutor implements Runnable {
|
||||
|
||||
protected String query = null;
|
||||
private static SiddhiManager siddhiManager = new SiddhiManager();
|
||||
private static final int INTERVAL = 3000;
|
||||
|
||||
public volatile Thread sidhdiThread;
|
||||
private ReadWriteLock rwlock = new ReentrantReadWriteLock();
|
||||
|
||||
//TODO have another array initialized so that a list of callbacks can be stored, String[] callbackList
|
||||
public SidhdhiQueryExecutor(String query){
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public void run(){
|
||||
//TODO the array of callbacks needs to be passed to invoke
|
||||
//TODO what is retruned should be a map of callbacks and outputs
|
||||
ExecutionPlan executionPlan = new ExecutionPlan().invoke();
|
||||
|
||||
Thread thisThread = Thread.currentThread();
|
||||
|
||||
while (sidhdiThread == thisThread) {
|
||||
InputHandler inputHandler = executionPlan.getInputHandler();
|
||||
|
||||
//Sending events to Siddhi
|
||||
try {
|
||||
List<BLE> bleReadings = read();
|
||||
for(BLE ble : bleReadings){
|
||||
System.out.println("Publishing data...");
|
||||
inputHandler.send(new Object[]{ble.getId(), ble.getTimeStamp(), ble.getLocation()});
|
||||
}
|
||||
|
||||
thisThread.sleep(INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<BLE> read()
|
||||
{
|
||||
List<BLE> bleData;
|
||||
rwlock.readLock().lock();
|
||||
try {
|
||||
//TODO Reading BLE VALUES
|
||||
bleData = SidhdhiWrapper.getBleData();
|
||||
} finally {
|
||||
rwlock.readLock().unlock();
|
||||
}
|
||||
return bleData;
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
sidhdiThread = null;
|
||||
}
|
||||
|
||||
public void start(){
|
||||
sidhdiThread = new Thread(this);
|
||||
sidhdiThread.start();
|
||||
}
|
||||
|
||||
private class ExecutionPlan {
|
||||
|
||||
private InputHandler inputHandler;
|
||||
|
||||
public InputHandler getInputHandler() {
|
||||
return inputHandler;
|
||||
}
|
||||
|
||||
//TODO should expect an array of callbacks
|
||||
public ExecutionPlan invoke() {
|
||||
|
||||
//Generating runtime
|
||||
ExecutionPlanRuntime runtime = siddhiManager.createExecutionPlanRuntime(query);
|
||||
|
||||
|
||||
|
||||
//TODO logic needs to be revised so that array of callbacks are processed
|
||||
runtime.addCallback("dataOut", new StreamCallback() {
|
||||
@Override
|
||||
public void receive(Event[] events) {
|
||||
System.out.println("Location Match event initiated.");
|
||||
if (events.length > 0) {
|
||||
//TODO Configure Event here!
|
||||
System.out.println("Firing location match event...");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//Retrieving InputHandler to push events into Siddhi
|
||||
inputHandler = runtime.getInputHandler("dataIn");
|
||||
|
||||
//Starting event processing
|
||||
runtime.start();
|
||||
System.out.println("Execution Plan Started!");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.siddhi.eventprocessor.wrapper;
|
||||
|
||||
import org.wso2.carbon.iot.android.sense.siddhi.dto.BLE;
|
||||
import org.wso2.carbon.iot.android.sense.siddhi.eventprocessor.core.SidhdhiQueryExecutor;
|
||||
import org.wso2.carbon.iot.android.sense.siddhi.reader.BLEReader;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class SidhdhiWrapper {
|
||||
|
||||
private static List<BLE> bleData;
|
||||
|
||||
public static List<BLE> getBleData() {
|
||||
return bleData;
|
||||
}
|
||||
|
||||
public static void setBleData(List<BLE> bleData) {
|
||||
SidhdhiWrapper.bleData = bleData;
|
||||
}
|
||||
|
||||
public static void main(String args[]){
|
||||
String query = "@Import('iot.sample.input:1.0.0')\n" +
|
||||
"define stream dataIn (id int, timestamp long, location string);\n" +
|
||||
"\n" +
|
||||
"@Export('iot.sample.output:1.0.0')\n" +
|
||||
"define stream dataOut (action string, timestamp long);\n" +
|
||||
"\n" +
|
||||
"from every e1=dataIn[location=='loc_1'] -> e2=dataIn[location=='loc_2'] -> e3=dataIn[location=='loc_3']\n" +
|
||||
"select 'x' as action, e3.timestamp\n" +
|
||||
"insert into dataOut;";
|
||||
|
||||
BLEReader blEReader = new BLEReader();
|
||||
blEReader.start();
|
||||
|
||||
SidhdhiQueryExecutor queryExecutor = new SidhdhiQueryExecutor(query);
|
||||
queryExecutor.start();
|
||||
}
|
||||
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.iot.android.sense.siddhi.reader;
|
||||
|
||||
import org.wso2.carbon.iot.android.sense.siddhi.dto.BLE;
|
||||
import org.wso2.carbon.iot.android.sense.siddhi.eventprocessor.wrapper.SidhdhiWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class BLEReader implements Runnable{
|
||||
|
||||
private ReadWriteLock rwlock = new ReentrantReadWriteLock();
|
||||
List<BLE> bleData = new ArrayList<BLE>();
|
||||
public volatile Thread bleReader;
|
||||
private static final int INTERVAL = 2000;
|
||||
|
||||
public void run(){
|
||||
Thread thisThread = Thread.currentThread();
|
||||
while (bleReader == thisThread) {
|
||||
write();
|
||||
try {
|
||||
thisThread.sleep(INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
bleReader = null;
|
||||
}
|
||||
|
||||
public void start(){
|
||||
bleReader = new Thread(this);
|
||||
bleReader.start();
|
||||
}
|
||||
|
||||
public void write()
|
||||
{
|
||||
rwlock.writeLock().lock();
|
||||
try {
|
||||
bleData.add(new BLE(123, "loc_1"));
|
||||
bleData.add(new BLE(123, "loc_2"));
|
||||
bleData.add(new BLE(123, "loc_3"));
|
||||
SidhdhiWrapper.setBleData(bleData);
|
||||
} finally {
|
||||
rwlock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/listContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentTop="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical|center_horizontal"
|
||||
android:text="@string/no_data"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,203 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2013 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/device_icon"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:paddingRight="5dp"
|
||||
android:paddingTop="5dp"
|
||||
android:src="@drawable/beacon"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/device_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="24sp"/>
|
||||
|
||||
<GridLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="2">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_mac"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/device_address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12sp"
|
||||
android:typeface="monospace"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_updated"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/device_last_update"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_rssi"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/device_rssi"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:textSize="12sp"/>
|
||||
</GridLayout>
|
||||
|
||||
<GridLayout
|
||||
android:id="@+id/ibeacon_section"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="4">
|
||||
|
||||
<!-- ROW 1 -->
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_uuid"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ibeacon_uuid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnSpan="3"
|
||||
android:paddingRight="5dp"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<!-- ROW 2 -->
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_major"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ibeacon_major"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_minor"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ibeacon_minor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<!-- ROW 3 -->
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_tx_power"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ibeacon_tx_power"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_distance"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ibeacon_distance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<!-- ROW 4 -->
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="5dp"
|
||||
android:text="@string/label_decriptor"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ibeacon_distance_descriptor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnSpan="3"
|
||||
android:paddingRight="5dp"
|
||||
android:textSize="12sp"/>
|
||||
</GridLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
Loading…
Reference in new issue