diff --git a/www/js/bluetooth/BluetoothCard.tsx b/www/js/bluetooth/BluetoothCard.tsx index 4af8240c4..e212121a2 100644 --- a/www/js/bluetooth/BluetoothCard.tsx +++ b/www/js/bluetooth/BluetoothCard.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Card, List, useTheme } from 'react-native-paper'; +import { Card, List, Text, Button, useTheme } from 'react-native-paper'; import { StyleSheet } from 'react-native'; type Props = any; @@ -23,14 +23,52 @@ const BluetoothCard = ({ device, isClassic, isScanningBLE }: Props) => { bgColor = device.in_range ? `rgba(200,250,200,1)` : `rgba(250,200,200,1)`; } + async function fakeMonitorCallback() { + // If we don't do this, the results start accumulating in the device object + // first call, we put a result into the device + // second call, the device already has a result, so we put another one in... + const deviceWithoutResult = { ...device }; + deviceWithoutResult.monitorResult = undefined; + deviceWithoutResult.rangeResult = undefined; + window['cordova'].plugins.locationManager.getDelegate().didDetermineStateForRegion({ + region: deviceWithoutResult, + eventType: 'didDetermineStateForRegion', + state: 'CLRegionStateInside', + }); + let timer: ReturnType = setTimeout(fakeRangeCallback, 500); + } + + async function fakeRangeCallback() { + // If we don't do this, the results start accumulating in the device object + // first call, we put a result into the device + // second call, the device already has a result, so we put another one in... + const deviceWithMajorMinor = { ...device, major: 1234, minor: 4567 }; + window['cordova'].plugins.locationManager.getDelegate().didRangeBeaconsInRegion({ + region: deviceWithMajorMinor, + eventType: 'didRangeBeaconsInRegion', + state: 'CLRegionStateInside', + }); + } + return ( } /> + + + {device.monitorResult} + + + {device.rangeResult} + + + ); }; diff --git a/www/js/bluetooth/BluetoothScanPage.tsx b/www/js/bluetooth/BluetoothScanPage.tsx index 52996b321..bb96943c7 100644 --- a/www/js/bluetooth/BluetoothScanPage.tsx +++ b/www/js/bluetooth/BluetoothScanPage.tsx @@ -4,7 +4,7 @@ import { StyleSheet, Modal, ScrollView, SafeAreaView, View, Text } from 'react-n import { gatherBluetoothClassicData } from './bluetoothScanner'; import { logWarn, displayError, displayErrorMsg, logDebug } from '../plugin/logger'; import BluetoothCard from './BluetoothCard'; -import { Appbar, useTheme, Button } from 'react-native-paper'; +import { Appbar, useTheme, TextInput, Button } from 'react-native-paper'; import { BLEBeaconDevice, BLEPluginCallback, @@ -21,17 +21,19 @@ import { */ const BluetoothScanPage = ({ ...props }: any) => { + const STATIC_ID = 'edu.berkeley.eecs.emission'; + const { t } = useTranslation(); const [bluetoothClassicList, setBluetoothClassicList] = useState([]); const [sampleBLEDevices, setSampleBLEDevices] = useState({ '426C7565-4368-6172-6D42-6561636F6E74': { - identifier: 'Katie_BLEBeacon', + identifier: STATIC_ID, minor: 4949, major: 3838, in_range: false, }, '426C7565-4368-6172-6D42-6561636F6E73': { - identifier: 'Louis-Beacon', + identifier: STATIC_ID, minor: 4949, major: 3838, in_range: false, @@ -40,6 +42,9 @@ const BluetoothScanPage = ({ ...props }: any) => { const [isScanningClassic, setIsScanningClassic] = useState(false); const [isScanningBLE, setIsScanningBLE] = useState(false); const [isClassic, setIsClassic] = useState(false); + const [newUUID, setNewUUID] = useState(null); + const [newMajor, setNewMajor] = useState(undefined); + const [newMinor, setNewMinor] = useState(undefined); const { colors } = useTheme(); // Flattens the `sampleBeacons` into an array of BLEBeaconDevices @@ -80,16 +85,27 @@ const BluetoothScanPage = ({ ...props }: any) => { } } - function setRangeStatus(uuid: string, status: boolean) { + function setMonitorStatus(uuid: string, result: string, status: boolean) { setSampleBLEDevices((prevDevices) => ({ ...prevDevices, [uuid]: { ...prevDevices[uuid], + monitorResult: result, in_range: status, }, })); } + function setRangeStatus(uuid: string, result: string) { + setSampleBLEDevices((prevDevices) => ({ + ...prevDevices, + [uuid]: { + ...prevDevices[uuid], + rangeResult: result, + }, + })); + } + // BLE LOGIC async function startBeaconScanning() { setIsScanningBLE(true); @@ -99,17 +115,30 @@ const BluetoothScanPage = ({ ...props }: any) => { delegate.didDetermineStateForRegion = function (pluginResult: BLEPluginCallback) { // `stateInside`is returned when the user enters the beacon region // `StateOutside` is either (i) left region, or (ii) started scanner (outside region) + const pluginResultStr = JSON.stringify(pluginResult, null, 2); if (pluginResult.state == 'CLRegionStateInside') { // need toUpperCase(), b/c callback returns with only lowercase values... - setRangeStatus(pluginResult.region.uuid.toUpperCase(), true); + setMonitorStatus(pluginResult.region.uuid.toUpperCase(), pluginResultStr, true); } else if (pluginResult.state == 'CLRegionStateOutside') { - setRangeStatus(pluginResult.region.uuid.toUpperCase(), false); + setMonitorStatus(pluginResult.region.uuid.toUpperCase(), pluginResultStr, false); } logDebug('[BLE] didDetermineStateForRegion'); - logDebug(JSON.stringify(pluginResult, null, 2)); + logDebug(pluginResultStr); window['cordova'].plugins.locationManager.appendToDeviceLog( - '[DOM] didDetermineStateForRegion: ' + JSON.stringify(pluginResult, null, 2), + '[DOM] didDetermineStateForRegion: ' + pluginResultStr, + ); + const beaconRegion = new window['cordova'].plugins.locationManager.BeaconRegion( + STATIC_ID, + pluginResult.region.uuid, + pluginResult.region.major, + pluginResult.region.minor, ); + window['cordova'].plugins.locationManager + .startRangingBeaconsInRegion(beaconRegion) + .fail(function (e) { + logWarn(e); + }) + .done(); }; delegate.didStartMonitoringForRegion = function (pluginResult) { @@ -120,7 +149,9 @@ const BluetoothScanPage = ({ ...props }: any) => { delegate.didRangeBeaconsInRegion = function (pluginResult) { // Not seeing this called... logDebug('[BLE] didRangeBeaconsInRegion'); - logDebug(JSON.stringify(pluginResult)); + const pluginResultStr = JSON.stringify(pluginResult, null, 2); + logDebug(pluginResultStr); + setRangeStatus(pluginResult.region.uuid.toUpperCase(), pluginResultStr); }; window['cordova'].plugins.locationManager.setDelegate(delegate); @@ -131,7 +162,7 @@ const BluetoothScanPage = ({ ...props }: any) => { // Need UUID value on iOS only, not Android (2nd parameter) // https://stackoverflow.com/questions/38580410/how-to-scan-all-nearby-ibeacons-using-coordova-based-hybrid-application const beaconRegion = new window['cordova'].plugins.locationManager.BeaconRegion( - sampleBeacon.identifier, + STATIC_ID, sampleBeacon.uuid, sampleBeacon.major, sampleBeacon.minor, @@ -149,9 +180,9 @@ const BluetoothScanPage = ({ ...props }: any) => { setIsScanningBLE(false); beaconsToArray().forEach((sampleBeacon: BLEBeaconDevice) => { - setRangeStatus(sampleBeacon.uuid, false); // "zero out" the beacons + setMonitorStatus(sampleBeacon.uuid, false); // "zero out" the beacons const beaconRegion = new window['cordova'].plugins.locationManager.BeaconRegion( - sampleBeacon.identifier, + STATIC_ID, sampleBeacon.uuid, sampleBeacon.major, sampleBeacon.minor, @@ -169,6 +200,22 @@ const BluetoothScanPage = ({ ...props }: any) => { setIsClassic(!isClassic); }; + // Add a beacon with the new UUID to the list of BLE devices to scan + function addNewUUID(newUUID: string, newMajor: number, newMinor: number) { + console.log('Before adding UUID ' + newUUID + ' entries = ' + sampleBLEDevices); + const devicesWithAddition = { ...sampleBLEDevices }; + devicesWithAddition[newUUID] = { + identifier: STATIC_ID, + minor: newMajor, + major: newMinor, + in_range: false, + }; + setSampleBLEDevices(devicesWithAddition); + setNewUUID(null); + setNewMajor(undefined); + setNewMinor(undefined); + } + const BluetoothCardList = ({ devices }) => { if (isClassic) { // When in classic mode, render devices as normal @@ -176,7 +223,7 @@ const BluetoothScanPage = ({ ...props }: any) => {
{devices.map((device) => { if (device) { - return ; + return ; } return null; })} @@ -188,7 +235,9 @@ const BluetoothScanPage = ({ ...props }: any) => {
{beaconsAsArray.map((beacon) => { if (beacon) { - return ; + return ( + + ); } })}
@@ -263,6 +312,24 @@ const BluetoothScanPage = ({ ...props }: any) => { + setNewUUID(t.toUpperCase())} + /> + setNewMajor(t)} + /> + setNewMinor(t)} + /> + diff --git a/www/js/types/BluetoothDevices.ts b/www/js/types/BluetoothDevices.ts index e628731e2..c29f55740 100644 --- a/www/js/types/BluetoothDevices.ts +++ b/www/js/types/BluetoothDevices.ts @@ -22,7 +22,14 @@ export type BLEBeaconDevice = { type_name?: string; // e.g., "BeaconRegion"; used for callback }; export type BLEDeviceList = { - [key: string]: { identifier: string; minor: number; major: number; in_range: boolean }; + [key: string]: { + identifier: string; + minor: number; + major: number; + monitorResult: string; + rangeResult: string; + in_range: boolean; + }; }; export type BLEPluginCallback = {