我正在尝试编写一个应用程序,定期接收有关当前找到的iBeacons的近似性的更新。我有两个我想要跟踪的iBeacons,它们是我自己的,我将用于跟踪的UUID硬编码到我的代码中。iBeacons本身具有相同的主要id,但具有不同的次要id。我的问题是关于如何定期更新使用预设UUID找到的iBeacons的近似性。我知道这需要用CLLocationManager来完成,因为它实现了iBeacon范围。
我目前对CLLocationManager的体验是:
import UIKit;
import CoreLocation;
import HomeKit;
class FirstViewController: UIViewController, CLLocationManagerDelegate, HMHomeManagerDelegate, UIPickerViewDelegate, UIPickerViewDataSource{
let homeManager = HMHomeManager();
let locationManager = CLLocationManager();
var beaconsInProximity: [CLBeacon] = [];
let beaconUUID: String = "11984894-7042-9801-839A-ADECCDFEDFF0";
let beaconMajor = 0x1;
let beaconMinor: [Int] = [0x1, 0x7];
let homeName = "Home";
var lamps = [HMAccessory]();
var lampNames = [String]();
var pickerNames = [String: HMAccessory]();
var selectedLamp: HMAccessory!;
var lightHome: HMHome!;
var firstLight: HMAccessory!;
var secondLight: HMAccessory!;
var thirdTestLight: HMAccessory!;
let beaconRegion: CLBeaconRegion = CLBeaconRegion(proximityUUID: NSUUID(uuidString:"11984894-7042-9801-839A-ADECCDFEDFF0")as! UUID, identifier: "Beaconons");
@IBOutlet weak var lampSwitch: UISwitch!
@IBOutlet weak var configureLampButton: UIButton!
@IBOutlet weak var lampPicker: UIPickerView!
@IBOutlet weak var identifyLampButton: UIButton!
@IBOutlet weak var lampSelectedLabel: UILabel!
@IBOutlet weak var lampStatusLabel: UILabel!
@IBOutlet weak var beaconStatusLabel: UILabel!
override func viewDidLoad(){
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if(selectedLamp != nil){
updateLampLabel(selectedLamp);
updateLampStatusLabel(selectedLamp);
}else{
updateLampLabelNoLamp();
updateLampStatusLabelNoStatus();
}
homeManager.delegate = self;
lampPicker.delegate = self;
lampPicker.dataSource = self;
locationManager.delegate = self;
locationManager.requestAlwaysAuthorization();
locationManager.startMonitoring(for: beaconRegion);
locationManager.startRangingBeacons(in: beaconRegion);
locationManager.requestState(for: beaconRegion);
}
override func didReceiveMemoryWarning(){
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func homeManagerDidUpdateHomes(_ manager: HMHomeManager) {
for home in homeManager.homes{
for accessory in home.accessories{
if(accessory.name.contains("lamp")){
lamps.append(accessory);
pickerNames[String(describing: accessory.services[1].characteristics[0].value)] = accessory;
print("Added accessory " + String(describing: accessory.services[1].characteristics[0].value) + " to lamp list");
}
}
}
if(lamps.count != 0){
for index in 0...(lamps.count - 1){
lampNames.append(String(describing: lamps[index].services[1].characteristics[0].value));
}
}
}
func locationManager(_: CLLocationManager, didRangeBeacons: [CLBeacon], in: CLBeaconRegion){
for beacon in didRangeBeacons{
if(beacon.proximity == CLProximity.immediate){
beaconsInProximity.append(beacon);
}else{
if(beaconsInProximity.contains(beacon)){
for index in 0...beaconsInProximity.count{
if(beaconsInProximity[index] == beacon){
beaconsInProximity.remove(at: index);
}
}
}
}
}
for beacon in beaconsInProximity{
if(beacon.major.intValue == beaconMajor){
if(beacon.minor.intValue == 0x3){
if(selectedLamp != nil){
switchLamp(selectedLamp, true);
beaconStatusLabel.text = "region detected";
}
}else{
if(selectedLamp != nil){
switchLamp(selectedLamp, false);
beaconStatusLabel.text = "lamping all the lamps that have ever lamped";
}
}
}
}
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
let bRegion = region as! CLBeaconRegion;
if(bRegion.proximityUUID == beaconRegion.proximityUUID){
print("Correct region");
beaconStatusLabel.text = "Entered beacon region";
}
}
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
let bRegion = region as! CLBeaconRegion;
if(bRegion.proximityUUID == beaconRegion.proximityUUID){
print("Exited correct region");
beaconStatusLabel.text = "Beacon region left";
}
}
@IBAction func configureLampButtonPressed(_ sender: AnyObject){
if(pickerNames[lampNames[lampPicker.selectedRow(inComponent: 0)]] != nil){
selectedLamp = pickerNames[lampNames[lampPicker.selectedRow(inComponent: 0)]];
}
if(selectedLamp != nil){
updateLampLabel(selectedLamp);
updateLampStatusLabel(selectedLamp);
}else{
updateLampLabelNoLamp();
updateLampStatusLabelNoStatus();
}
}
@IBAction func identifyLampButtonPressed(_ sender: AnyObject){
if(selectedLamp != nil){
identifyLamp(selectedLamp);
}
}
@IBAction func lampSwitchFlipped(_ sender: AnyObject){
if(selectedLamp != nil){
switchLamp(selectedLamp, lampSwitch.isOn);
updateLampStatusLabel(selectedLamp);
}else{
lampSwitch.setOn(!lampSwitch.isOn, animated: true);
updateLampStatusLabelNoStatus();
}
}
func updateLampLabelNoLamp(){
lampSelectedLabel.text = "No lamp selected";
}
func updateLampLabel(_ lamp: HMAccessory){
lampSelectedLabel.text = "Selected lamp: " + lamp.name;
}
func numberOfComponents(in pickerView: UIPickerView) -> Int{
return 1;
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return lampNames.count;
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?{
return lampNames[row];
}
func booleanToInt(_ value: Bool) -> Int{
if(value){
return 1;
}else{
return 0;
}
}
func sendLocalNotificationWithMessage(_ message: String!){
}
func switchLamp(_ lamp: HMAccessory, _ value: Bool){
lamp.services[1].characteristics[1].writeValue(booleanToInt(value), completionHandler: {
error in
if let error = error{
print("Something went wrong! \(error)");
}
})
}
func identifyLamp(_ lamp: HMAccessory){
lamp.services[0].characteristics[3].writeValue(1, completionHandler: {
error in
if let error = error{
print("Something went wrong! \(error)");
}
})
}
func updateLampStatusLabel(_ lamp: HMAccessory){
lampStatusLabel.text = "Lamp status: " + String(describing: selectedLamp.services[1].characteristics[1].value);
}
func updateLampStatusLabelNoStatus(){
lampStatusLabel.text = "Select a lamp";
}
}该应用程序本身的目标是根据用户是否在附近切换灯泡。
发布于 2017-01-31 23:55:53
每次回调func locationManager(_: CLLocationManager, didRangeBeacons: [CLBeacon], in: CLBeaconRegion)时,beacon.proximity字段都会更新。这些回调将以每秒一次的速度与具有该字段的CLBeacon对象数组一起出现。所以每隔1秒你就会得到一次更新。
根据代码的设置方式,如果信标就在附近,则beaconsInProximity将正确更新,并且稍后将在回调方法中调用switchLamp。
但是,请注意,CLBeacon的proximity字段可能不会像您希望的那样快速更新。此字段派生自accuracy字段,该字段是以米为单位的距离估计值。如果距离估计值小于0.5米,则accuracy将设置为立即数。如果距离估计值大于0.5米,则将其设置为另一个值。
accuracy中的距离估计基于RSSI测量的20秒运行平均值。因此,如果您非常快速地从5米远移动到信标发射器旁边的右侧,accuracy字段将在20秒内从~5.0慢慢变为~0.0。proximity字段显示immediate大约需要20秒。
此外,重要的是要了解信标必须使用信标内部设置的measuredPower值正确校准,以便尽可能准确地估计距离。如果即使在静止20秒后,在accuracy中得到的距离估计也非常不准确,那么您可能需要进行此校准。
https://stackoverflow.com/questions/41942948
复制相似问题