Cannot get Core Motion Updates using watchOS 5: "[Gyro] Manually set gyro-interrupt-calibration to 800" - gyroscope

I am trying to get Core Motion data from an Apple Watch 3 (WatchOS 5.1) but although the DeviceMotion is available (isDeviceMotionAvailable property is true), the handler is never triggered. I get the following message in the console right after parsing super.willActivate():
[Gyro] Manually set gyro-interrupt-calibration to 800
I am using the following function to get Device Motion updates:
func startQueuedUpdates() {
if motion.isDeviceMotionAvailable {
self.motion.deviceMotionUpdateInterval = 1.0 / 100.0
self.motion.showsDeviceMovementDisplay = true
self.motion.startDeviceMotionUpdates(using: .xMagneticNorthZVertical, to: self.queue, withHandler:{
(data, error) in
// Make sure the data is valid before accessing it.
if let validData = data {
print(String(validData.userAcceleration.x))
}
})
}
}
In the InterfaceController I have declared
let motion = CMMotionManager()
let queue : OperationQueue = OperationQueue.main
Has anyone met this message before and managed to resolve it?
Note: I have checked the isGyroAvailable property and it is false.

The trick here is to match the startDeviceMotionUpdates(using: CMAttitudeReferenceFrame parameter to your device's capabilities. If it has no magnetometer, it cannot relate to magnetic north, and even if it has a magnetometer, it cannot relate to true north unless it knows where you are (i.e. has latitude & longitude). If it hasn't got the capabilities to comply with the parameter you select, the update will be called, but the data will be nil.
If you start it up with the minimum .xArbitraryZVertical you will get updates from the accelerometer, but you won't get a meaningful heading, just a relative one, through the CMDeviceMotion.attitude property ...
if motion.isDeviceMotionAvailable {
print("Motion available")
print(motion.isGyroAvailable ? "Gyro available" : "Gyro NOT available")
print(motion.isAccelerometerAvailable ? "Accel available" : "Accel NOT available")
print(motion.isMagnetometerAvailable ? "Mag available" : "Mag NOT available")
motion.deviceMotionUpdateInterval = 1.0 / 60.0
motion.showsDeviceMovementDisplay = true
motion.startDeviceMotionUpdates(using: .xArbitraryZVertical) // *******
// Configure a timer to fetch the motion data.
self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
if let data = self.motion.deviceMotion {
print(data.attitude.yaw)
}
}
}

Related

Improved / efficient code for multiple if - React Native

I´m a technical project manager coordinating developers. My coding skills are limited and so I align with my devs on logical structure. For a mobile app (React Native to serve Android and iOS) we are currently developing user current location logic. Turned out we have specific Android and iOS settings, what may require native developmetn for location service handling.
I´m currently reviewing the following pseudocode and, besides others, concerned about the MULTIPLE IF statements and thinking if there is a more efficient way, as here we seem to jump into every IF, even when location is set already before.
I think there can be something like "until", "break" or similar .. and maybe relevant to consider the specific dev language, React Native in that case?
Any help, as pseudocode or if possible to make it specific already considering React Native, is very much appreciated.
Many thanks in advance!
Code
////Central Location Service to get current location.
var currentLocation;
var locationType
if Android {
DEFINED_ACCURACY = QUALITY_BALANCED_POWER
} else id iOS {
DEFINED_ACCURACY = kCLLocationAccuracyHundredMeters
}
DEFINED_DISTANCE = 3000
function startLocationService(){
var locationservice = LocationService()
locationservcie.accuracy = DEFINED_ACCURACY
locationservcie.distance = DEFINED_DISTANCE
locationservcie.startListnertoLocationUpdate() {
cacheData(location, currentTime);
currentLocation = location
}
}
function getLocationFromLocationService() {
if locationServcieEnabled == false
return NULL;
if locationPermissionGranted == false
return NULL;
return currentLocation;
}
function getCurrentLocation() {
var lcoation = NULL;
var accuracy = Not_defined;
lcoation = getLocationFromLocationService() //GPS, network
locationType = locationService
if lcoation == NULL {
locationdata == getLastKnownLocation()
if locationdata.Age < DEFINED_DURATION {
location = locationdata.location
locationType = locationService
}
}
if location == NULL {
location == getCachedLocationWithin24Hour()
locationType = locationService
}
if location == NULL {
location = getLocationfromTelephony()
locationType = other
}
if location == NULL {
if permissionToUseBilling == false {
askForPermissionToUseBilling()
}
location = getLocationFromBillimg()
accuracy = other
}
if location == NULL {
location = getLocationOfDEfaultCountry()
accuracy = other
}
return location, Other
}
I think you can use switches to cover different cases from javascript.
Probably your dev team knows, but did not want to bring it into pseudo code?
const location = getLocationFromLocationService() ;
switch (location) {
case 'NULL':
//DO SOMETHING WHEN NULL;
break;
case 'New York':
// DO SOMETHING WHEN New York;
// No break leads to run also into the next case
case 'Bern':
console.log('I love nice cities.');
break;
default:
console.log(`Sorry, we are out of ${location}.`);
}
Interestingly you seem to have multiple times the same if case?
Maybe you will to nest it or have to use a switch with multiple expressions.
case ("Bern" && "ANOTHERExpression to be true"):
Link to switch documentation
Please don't underestimate your dev team. ;-)

I am trying to get data over an OpenWeather API in Rust but I am facing some iusse regarding parsing I guess

extern crate openweather;
use openweather::LocationSpecifier;
static API_KEY: &str = "e85e0a3142231dab28a2611888e48f22";
fn main() {
let loc = LocationSpecifier::Coordinates {
lat: 24.87,
lon: 67.03,
};
let weather = openweather::get_current_weather(loc, API_KEY).unwrap();
print!(
"Right now in Minneapolis, MN it is {}K",
weather.main.humidity
);
}
error : thread 'main' panicked at 'called Result::unwrap() on an
Err value: ErrorReport { cod: 0, message: "Got unexpected response:
\"{\\"coord\\":{\\"lon\\":67.03,\\"lat\\":24.87},\\"weather\\":[{\\"id\\":803,\\"main\\":\\"Clouds\\",\\"description\\":\\"broken
clouds\\",\\"icon\\":\\"04n\\"}],\\"base\\":\\"stations\\",\\"main\\":{\\"temp\\":294.15,\\"pressure\\":1018,\\"humidity\\":60,\\"temp_min\\":294.15,\\"temp_max\\":294.15},\\"visibility\\":6000,\\"wind\\":{\\"speed\\":5.1,\\"deg\\":30},\\"clouds\\":{\\"all\\":70},\\"dt\\":1574012543,\\"sys\\":{\\"type\\":1,\\"id\\":7576,\\"country\\":\\"PK\\",\\"sunrise\\":1573955364,\\"sunset\\":1573994659},\\"timezone\\":18000,\\"id\\":1174872,\\"name\\":\\"Karachi\\",\\"cod\\":200}\""
}
The issue is a JSON parsing error due to the deserialized struct not matching OpenWeather's JSON, perhaps the API recently added this? With your example, the OpenWeatherCurrent struct is missing timezone.
But it looks like there is an open PR that will fix this, you can test it by doing the following:
Change your Cargo.toml dependency to openweather = { git = "https://github.com/caemor/openweather" }.
The PR author has also updated the get_current_weather signature so you'll need to change lines 2, 10 to the following:
use openweather::{LocationSpecifier, Settings};
let weather = openweather::get_current_weather(&loc, API_KEY, &Settings::default()).unwrap();

Paypal Php Sdk - NotifyUrl is not a fully qualified URL Error

I have this code
$product_info = array();
if(isset($cms['site']['url_data']['product_id'])){
$product_info = $cms['class']['product']->get($cms['site']['url_data']['product_id']);
}
if(!isset($product_info['id'])){
/*
echo 'No product info.';
exit();
*/
header_url(SITE_URL.'?subpage=user_subscription#xl_xr_page_my%20account');
}
$fee = $product_info['yearly_price_end'] / 100 * $product_info['fee'];
$yearly_price_end = $product_info['yearly_price_end'] + $fee;
$fee = ($product_info['setup_price_end'] / 100) * $product_info['fee'];
$setup_price_end = $product_info['setup_price_end'] + $fee;
if(isset($_SESSION['discountcode_amount'])){
$setup_price_end = $setup_price_end - $_SESSION['discountcode_amount'];
unset($_SESSION['discountcode_amount']);
}
$error = false;
$plan_id = '';
$approvalUrl = '';
$ReturnUrl = SITE_URL.'payment/?payment_type=paypal&payment_page=process_agreement';
$CancelUrl = SITE_URL.'payment/?payment_type=paypal&payment_page=cancel_agreement';
$now = $cms['date'];
$now->modify('+5 minutes');
$apiContext = new \PayPal\Rest\ApiContext(
new \PayPal\Auth\OAuthTokenCredential(
$cms['options']['plugin_paypal_clientid'], // ClientID
$cms['options']['plugin_paypal_clientsecret'] // ClientSecret
)
);
use PayPal\Api\ChargeModel;
use PayPal\Api\Currency;
use PayPal\Api\MerchantPreferences;
use PayPal\Api\PaymentDefinition;
use PayPal\Api\Plan;
use PayPal\Api\Patch;
use PayPal\Api\PatchRequest;
use PayPal\Common\PayPalModel;
use PayPal\Api\Agreement;
use PayPal\Api\Payer;
use PayPal\Api\ShippingAddress;
// Create a new instance of Plan object
$plan = new Plan();
// # Basic Information
// Fill up the basic information that is required for the plan
$plan->setName($product_info['name'])
->setDescription($product_info['desc_text'])
->setType('fixed');
// # Payment definitions for this billing plan.
$paymentDefinition = new PaymentDefinition();
// The possible values for such setters are mentioned in the setter method documentation.
// Just open the class file. e.g. lib/PayPal/Api/PaymentDefinition.php and look for setFrequency method.
// You should be able to see the acceptable values in the comments.
$setFrequency = 'Year';
//$setFrequency = 'Day';
$paymentDefinition->setName('Regular Payments')
->setType('REGULAR')
->setFrequency($setFrequency)
->setFrequencyInterval("1")
->setCycles("999")
->setAmount(new Currency(array('value' => $yearly_price_end, 'currency' => $cms['session']['client']['currency']['iso_code'])));
// Charge Models
$chargeModel = new ChargeModel();
$chargeModel->setType('SHIPPING')
->setAmount(new Currency(array('value' => 0, 'currency' => $cms['session']['client']['currency']['iso_code'])));
$paymentDefinition->setChargeModels(array($chargeModel));
$merchantPreferences = new MerchantPreferences();
// ReturnURL and CancelURL are not required and used when creating billing agreement with payment_method as "credit_card".
// However, it is generally a good idea to set these values, in case you plan to create billing agreements which accepts "paypal" as payment_method.
// This will keep your plan compatible with both the possible scenarios on how it is being used in agreement.
$merchantPreferences->setReturnUrl($ReturnUrl)
->setCancelUrl($CancelUrl)
->setAutoBillAmount("yes")
->setInitialFailAmountAction("CONTINUE")
->setMaxFailAttempts("0")
->setSetupFee(new Currency(array('value' => $setup_price_end, 'currency' => $cms['session']['client']['currency']['iso_code'])));
$plan->setPaymentDefinitions(array($paymentDefinition));
$plan->setMerchantPreferences($merchantPreferences);
// ### Create Plan
try {
$output = $plan->create($apiContext);
} catch (Exception $ex){
die($ex);
}
echo $output->getId().'<br />';
echo $output.'<br />';
Been working with paypal php sdk for some days now and my code stop working.
So i went back to basic and i am still getting the same damn error.
I am trying to create a plan for subscription but getting the following error:
"NotifyUrl is not a fully qualified URL"
I have no idea how to fix this as i dont use NotfifyUrl in my code?
Could be really nice if anyone had an idea how to fix this problem :)
Thanks
PayPal did a update to their API last night which has caused problem within their SDK.
They are sending back null values in their responses.
I MUST stress the error is not on sending the request to PayPal, but on processing their response.
BUG Report : https://github.com/paypal/PayPal-PHP-SDK/issues/1151
Pull Request : https://github.com/paypal/PayPal-PHP-SDK/pull/1152
Hope this helps, but their current SDK is throwing exceptions.
Use below simple fix.
Replace below function in vendor\paypal\rest-api-sdk-php\lib\PayPal\Api\MerchantPreferences.php
public function setNotifyUrl($notify_url)
{
if(!empty($notify_url)){
UrlValidator::validate($notify_url, "NotifyUrl");
}
$this->notify_url = $notify_url;
return $this;
}
If you get the same error for return_url/cancel_url, add the if condition as above.
Note: This is not a permanent solution, you can use this until getting the update from PayPal.
From the GitHub repo for the PayPal PHP SDK, I see that the error you mentioned is thrown when MerchantPreferences is not given a valid NotifyUrl. I see you're setting the CancelUrl and ReturnUrl, but not the NotifyUrl. You may simply need to set that as well, i.e.:
$NotifyUrl = (some url goes here)
$obj->setNotifyUrl($NotifyUrl);
Reason behind it!
error comes from.
vendor\paypal\rest-api-sdk-php\lib\PayPal\Validation\UrlValidator.php
line.
if (filter_var($url, FILTER_VALIDATE_URL) === false) {
throw new \InvalidArgumentException("$urlName is not a fully qualified URL");
}
FILTER_VALIDATE_URL: according to this php function.
INVALID URL: "http://cat_n.domain.net.in/"; // IT CONTAIN _ UNDERSCORE.
VALID URL: "http://cat-n.domain.net.in/"; it separated with - dash
here you can dump your url.
vendor\paypal\rest-api-sdk-php\lib\PayPal\Validation\UrlValidator.php
public static function validate($url, $urlName = null)
{
var_dump($url);
}
And then check this here: https://www.w3schools.com/PHP/phptryit.asp?filename=tryphp_func_validate_url
you can check here what character will reason for invalid.

iOS 10 Local Notifications not showing

I've been working on setting up local notifications for my app in iOS 10, but when testing in the simulator I found that the notifications would be successfully scheduled, but would never actually appear when the time they were scheduled for came. Here's the code I've been using:
let UNcenter = UNUserNotificationCenter.current()
UNcenter.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
// Enable or disable features based on authorization
if granted == true {
self.testNotification()
}
}
Then it runs this code (assume the date/time is in the future):
func testNotification () {
let date = NSDateComponents()
date.hour = 16
date.minute = 06
date.second = 00
date.day = 26
date.month = 1
date.year = 2017
let trigger = UNCalendarNotificationTrigger(dateMatching: date as DateComponents, repeats: false)
let content = UNMutableNotificationContent()
content.title = "TestTitle"
content.body = "TestBody"
content.subtitle = "TestSubtitle"
let request = UNNotificationRequest(identifier: "TestID", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("error: \(error)")
} else {
print("Scheduled Notification")
}
}
}
From this code, it will always print "Scheduled Notification", but when the notification is supposed to be triggered, it never triggers. I've been unable to find any fix for this.
Here are a few steps.
Make sure you have the permission. If not, use UNUserNotificationCenter.current().requestAuthorization to get that. Or follow the answer below if you want to show the request pop up more than once.
If you want to show the notification foreground, having to assign UNUserNotificationCenterDelegate to somewhere.
This answer might help.

How to read file comment field

In OS X Finder there is 'Comment' file property. It can be checked in finder by adding 'Comment' column or edited/checked after right clicking on file or folder and selecting 'Get info'.
How to read this value in swift or objective-c?
I checked already NSURL and none of them seems to be the right ones
Do not use the low-level extended attributes API to read Spotlight metadata. There's a proper Spotlight API for that. (It's called the File Metadata API.) Not only is it a pain in the neck, there's no guarantee that Apple will keep using the same extended attribute to store this information.
Use MDItemCreateWithURL() to create an MDItem for the file. Use MDItemCopyAttribute() with kMDItemFinderComment to obtain the Finder comment for the item.
Putting the pieces together (Ken Thomases reading answer above and writing answer link) you can extend URL with a computed property with a getter and a setter to read/write comments to your files:
update: Xcode 8.2.1 • Swift 3.0.2
extension URL {
var finderComment: String? {
get {
guard isFileURL else { return nil }
return MDItemCopyAttribute(MDItemCreateWithURL(kCFAllocatorDefault, self as CFURL), kMDItemFinderComment) as? String
}
set {
guard isFileURL, let newValue = newValue else { return }
let script = "tell application \"Finder\"\n" +
String(format: "set filePath to \"%#\" as posix file \n", absoluteString) +
String(format: "set comment of (filePath as alias) to \"%#\" \n", newValue) +
"end tell"
guard let appleScript = NSAppleScript(source: script) else { return }
var error: NSDictionary?
appleScript.executeAndReturnError(&error)
if let error = error {
print(error[NSAppleScript.errorAppName] as! String)
print(error[NSAppleScript.errorBriefMessage] as! String)
print(error[NSAppleScript.errorMessage] as! String)
print(error[NSAppleScript.errorNumber] as! NSNumber)
print(error[NSAppleScript.errorRange] as! NSRange)
}
}
}
}
As explained in the various answers to Mac OS X : add a custom meta data field to any file,
Finder comments can be read and set programmatically with getxattr() and setxattr(). They are stored as extended attribute
"com.apple.metadata:kMDItemFinderComment", and the value is a property
list.
This works even for files not indexed by Spotlight, such as those on a network server volume.
From the Objective-C code here
and here I made this simple Swift function
to read the Finder comment (now updated for Swift 4 and later):
func finderComment(url : URL) -> String? {
let XAFinderComment = "com.apple.metadata:kMDItemFinderComment"
let data = url.withUnsafeFileSystemRepresentation { fileSystemPath -> Data? in
// Determine attribute size:
let length = getxattr(fileSystemPath, XAFinderComment, nil, 0, 0, 0)
guard length >= 0 else { return nil }
// Create buffer with required size:
var data = Data(count: length)
// Retrieve attribute:
let result = data.withUnsafeMutableBytes { [count = data.count] in
getxattr(fileSystemPath, XAFinderComment, $0.baseAddress, count, 0, 0)
}
guard result >= 0 else { return nil }
return data
}
// Deserialize to String:
guard let data = data, let comment = try? PropertyListSerialization.propertyList(from: data,
options: [], format: nil) as? String else {
return nil
}
return comment
}
Example usage:
let url = URL(fileURLWithPath: "/path/to/file")
if let comment = finderComment(url: url) {
print(comment)
}
The function returns an optional string which is nil if the file
has no Finder comment, or if anything went wrong while retrieving it.