Ive been trying for a few days now to set a pin high (Estimote location beacon) from an app I'm building.
Im doing something wrong as i am getting an error when the block fires off. Error is: [ESTTelemetryInfo portsData]: unrecognized selector sent to instance...
Ive looked everywhere for a snippet but can't find anything. I only want to be able to set the pin high (i don't need to send any data). If i can set the pin high i figure i could set it low when done using the same methods. This is the code:
let telem = ESTTelemetryInfo.init(shortIdentifier: "xxxxxxxxxxxxxxxx")!
let setPinHigh = ESTTelemetryNotificationGPIO.init(notificationBlock: { (telemInfo) in
if telInfo.shortIdentifier! != "xxxxxxxxxxxxxxxx" { return }
telemInfo.portsData.setPort(.port0, value: .high)
})
setPinHigh.fireNotificationBlock(with: telem)
Any help would be greatly appreciated.
ps Sorry if this is incorrectly formatted (long time reader first time poster).
Cheers
Gary
Fixed..we'll sort of. For anyone wanting to know the right way to to set a pin high, in output mode, is to connect to the beacon first through the device manager: ESTDeviceManager() -set the delegate in the class as ESTDeviceManagerDelegate - startDeviceDiscovery(with: deviceFilter) then in the delegate method:
func estDeviceConnectDidSucceed(_ device: ESTDeviceConnectable) { self.settings.gpio.portsData.setPort(.port0, value: .high)
}
BUT -> at the moment there is a bug that portsData has no member 'setPort'. I've filed a bug issue with Estimote on GitHub. Will come back to report once it's fixed.
Related
Since recently, I get in the Xcode logs a lot of strange warnings from the CoreMotion framework, related to function getLocationForBundleID:
[Client] {"msg":"#NullIsland Either the latitude or longitude was exactly 0! That's highly unlikely", "latIsZero":0, "lonIsZero":0}
[Client] {"msg":"#NullIsland Received a latitude or longitude from getLocationForBundleID that was exactly zero", "latIsZero":0, "lonIsZero":0, "location":'28 5B E0 D7 EB 7F 00 00'}
I do not see any malfunction of my app. So maybe these logs can be ignored, but they are annoying anyway.
My questions are:
How can I correct a potential error?
How can I stop these warnings?
Apparently this error message is logged if property location of a CLLocationManager is read, before the CLLocationManager delivered the very first location.
My solution is the following:
I use anyway a subclass of CLLocationManager that allows me to set the location property for tests programmatically.
This is done as follows:
private var _location: CLLocation?
#objc dynamic override var location: CLLocation? {
get {
let usedLocation = _location ?? super.location // Here the error is logged if no location has been delivered yet
return usedLocation
}
set {
_location = newValue
}
}
This subclass has now an additional property
var anyLocationDelivered = false
that is set true in
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
locationManager.anyLocationDelivered = true
// …
}
and the getter is now
get {
guard anyLocationDelivered else { return nil }
let usedLocation = _location ?? super.location
return usedLocation
}
Now this error message is no longer logged.
I was getting this same error when trying to get a user's location in an app. There were two things preventing me from getting a valid lat/long. The main issue I was having was that I was using a simulator and had to set the location manually. If you're using the simulator, go to XCode, click Debug --> Simulate Location, and choose a location. I also had to make sure the correct location permission keys were added to Info.plist. You're also probably already aware, but you'll know if any keys are missing from Info.plist because a separate error message will print out to the console above or below these lat/long error messages, and it will tell you which key is missing. So basically:
Make sure you have all necessary location permissions accepted on the device/simulator being used to test the application.
Once you have location permissions, set a location if using a simulator.
Not sure if this will help at all, but I hope it does. If you've already confirmed that these are not issues, I'm not sure what may be causing the issue in your case, but stepping through the parts of your code responsible for fetching the user location would probably be beneficial to see which link in the process is failing.
The issue is likely that you ran your application on the simulator, which does NOT use your current location by default unless you manually change the simulation location in Debug, Simulate Location.
To fix the issue, either simulate your current location (as stated above) OR run your application on your physical signed device, close the application completely, and then relaunch your application.
OS_ACTIVITY_MODE = disable
To get rid of the warning do the following:
Steps
Navigate to Product -> Scheme -> Edit Scheme.
Open the Arguments tab
Environment Variables section add OS_ACTIVITY_MODE = disable
I'm stumped, iOS 11.4 ( 15F79 ), iPhone 6. Cannot get the App to Ask for Motion Data. info.plist has been set via the editor and double checked via the info.plist open in textWrangler, Also deleted key and saved via textWrangler.
<key>NSMotionUsageDescription</key>
<string>This app needs your Phones motion manager to update when the phone is tilted. Please allow this App to use your phones tilt devices</string>
I have deleted then reinstalled the app about 10 times. I have restared the phone 5 times. I have checked through settings and my app does NOT show up in Privacy-Motion and Fitness or anywhere else in settings. I am using a free developer account, maybe that has something to do with it?
I created a new Xcode game template and changed nothing apart from importing CoreMotion and this code
**** Edited, sorry I forgot to say I had started the instance, just forgot to put it here, just in case someone thinks that's the problem ************
let motionManager = CMMotionManager()
override func didMove(to view: SKView) {
motionManager.startDeviceMotionUpdates()
if motionManager.isDeviceMotionActive == true {
motionManager.accelerometerUpdateInterval = 0.2
motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
(accelerometerData: CMAccelerometerData!, error: NSError!) in
let acceleration = accelerometerData.acceleration
print(accelerometerData)
} as! CMAccelerometerHandler)
}else{
print(CMMotionActivityManager.authorizationStatus().rawValue)
}
which prints a 0 ( an Enum - case not determined ) to the console.
In my actual app it was a 3 ( same Enum - case Denied ).
As I've said, I have uninstalled, reinstalled, edited plist via Xcode and text wrangler ( a code editor ) , tried different versions of the code above, tried the code in different places ( in did move to view, in class )tried code off apple docs. etc.... I haven't been asked the NSUsage question and the App keeps crashing.
I have looked for ways to get the Alert fired up, As in CLLocationManager.requestWhenInUseAuthorization() but I cannot find a comparable CMMotion version ( I don't think there is one. ) I have created a new swift file , imported Foundation and CMMotion and just put that code there, But still no Alert asking for Motion Data.
I tried a single view app template instead of a game template thinking that might be the issue, Nope.
What do I do?
Any help Appreciated. Thanks
You are confusing two related but different classes.
CMMotionManager gives access to accelerometer, magnetometer and gyroscope data. It does not require any user permission as this information is not considered privacy related.
In your else clause you are checking the authorisation status of CMMotionActivityManager. This object reports the device motion type (walking, running, driving). This information is considered privacy related and when you create an instance of this class and request data from it, the permissions alert is displayed.
The reason your else is being triggered is because you are checking isDeviceMotionActive; this will be false until you call startDeviceMotionUpdates, which you never do. Even if you used isAccelerometerActive you would have a problem because you call startAccelerometerUpdates in the if clause which will never be reached.
You probably meant to check isAccelerometerAvailable. If this returns false then there isn't much you can do; the device doesn't have an accelerometer.
Update
It doesn't make sense to check isDeviceMotionActive immediately after calling startDeviceMotion:
You know it's active; you just started it
I imagine the start up takes some time, so you could expect to get false if you check immediately.
Apple recommends that you do not have more than one observer in place for each motion device type, so the purpose of check the is...Active to ensure you don't call start... again if you have already done so.
If you only want gyroscope data then you don't need to call startDeviceMotionUpdates at all.
I am currently working with the Inspire 2 & the M210 RTK. Can anyone help me in getting the Obstacle Avoidance sensor data output from the drone using the Mobile-SDK? I would like to get the exact distance reading from the object in front of the drone in an constantly updating value. Any code examples? I am relatively new to the DJI SDK so any help would be greatly appreciated. Thanks in advance!
Before getting into this, keep in mind that the distance you receive is not perfectly accurate.
There is a few ways you can access the sensors with the mobile SDK.
1/ Traditional interfaces using the obstacle avoidance part of the DJIFlightAssistant
Implement the delegate DJIFlightAssistantDelegate
Implement the didUpdateVisionDetectionState method
In the DJIVisionDetectionState object, there is a detectionSectors property which is an array of DJIObstacleDetectionSector which have a obstacleDistanceInMeters.
2/ Using the keys, you can start listening to the Flight Controller key DJIFlightAssistantParamDetectionSectors. The block called will contain an array of DJIObstacleDetectionSector which have a obstacleDistanceInMeters:
guard let detectionSectorsKey = DJIFlightControllerKey(param: DJIFlightAssistantParamDetectionSectors) else {
// failed to create the key
return;
}
guard let keyManager = DJISDKManager.keyManager()? else {
// failed to access the keyManager. You're most likely not registered yet.
return;
}
keyManager.startListeningForChanges(on: detectionSectorsKey, withListener: self, andUpdate: { (oldValue, newValue) in
let sectors = newValue?.value as! [DJIObstacleDetectionSector]
//do stuff.
})
On IOS, I am using the delegate method:\
func routingService(routingService: SKRoutingService!, didChangeCurrentAdvice currentAdvice: SKRouteAdvice!, isLastAdvice: Bool) {
print("adviceInstruction")
print(currentAdvice.adviceInstruction)
delegate?.didChangeCurrentAdvice(currentAdvice.adviceInstruction)
}
The currentAdvice.adviceInstruction when running in simulator mode, returns strange instructions when it lists distances, like:
in 200 50 yards turn right
I want to be able to state in my app, where you are turning and in how far. So I would expected something like in 50 yard turn right. Is there another way of doing this?
See this article for context.
If you want "human readable" text instructions, use the TTS option for audio advices: http://developer.skobbler.com/getting-started/ios#sec24
We have a strange behavior with the WinRT Geolocator in one of our app. The user clicks on a button in the app to get the current position. Works fine the first time but all subsequent click on the button returns the same coordinates even tough we move for more than one kilometer.
The application runs on a ThinkPad and we've installed an application called "GPS Satellite" and if we switch to this application, get a coordinates, and return to our app then the Geolocator returns the correct coordinates. So we know the GPS is working fine, but seems like the coordinates are kept in cache even tough we've set a expiration of a few millisecond.
private async void ExecuteObtenirCoordGPSCommand()
{
try
{
Geolocator geolocator = new Geolocator();
geolocator.DesiredAccuracy = PositionAccuracy.High;
// Make the request for the current position
Geoposition pos = await geolocator.GetGeopositionAsync(new TimeSpan(0,0,0,0,200), new TimeSpan(0,0,5));
Place.Latitude = pos.Coordinate.Latitude;
Place.Longitude = pos.Coordinate.Longitude;
}
catch
{
GPSMsgErreur = "The GPS is unavailable";
}
}
We've tried to put a expiration on the method GetGeopositionAsync but it didn't solved the problem.
We've tried to put the Geolocator var at the class level with the same result.
Any ideas?
Not sure if this is your issue but the API you are using is tagged has obsolete in this post:
http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.geolocation.geocoordinate
Try using:
Place.Latitude = pos.Coordinate.Point.Position.Latitude;
Place.Longitude = pos.Coordinate.Point.Position.Longitude;
You may also use:
double someVar = pos.Coordinate.Accuracy
to figure out what is the margin of error on the device. May be you where not far enough from your first location and your second location was within the margin of error...
I can also tell you that I have a software built with Visual Studio 2013 Windows (WinRT) that runs on a ThinkPad using the same objects you are using and it works fine.
The main difference between mine and yours is that I am using the API showed above and that I did not use the following statement:
geolocator.DesiredAccuracy = PositionAccuracy.High;
And that I did not pass any parameters to the GetGeopositionAsync method.
I hope this helps.
Cheers, Hans.