Traffic Routing in HERE SDK - here-api

I am using the following code to create a route using the Premium Android SDK:
RouteOptions ro = new RouteOptions();
ro.setTransportMode(RouteOptions.TransportMode.CAR);
ro.setRouteType(RouteOptions.Type.BALANCED);
ro.setRouteCount(1);
RoutePlan rp = new RoutePlan();
// start route on current position
rp.setRouteOptions(ro);
rp.addWaypoint(new RouteWaypoint(currentGeoCoordinate));
rp.addWaypoint(new RouteWaypoint(stopGeoCordinate));
DynamicPenalty dp = new DynamicPenalty();
dp.setTrafficPenaltyMode(TrafficPenaltyMode.OPTIMAL);
stopGeoCordinate = new GeoCoordinate(trip.getLatitude(), trip.getLongitude());
CoreRouter rm = new CoreRouter();
rm.setDynamicPenalty(dp);
rm.calculateRoute(rp, new CoreRouter.Listener() { ...
Using the Android Studio Network Profiler I have seen this single request result in about 30 of the same backend API calls to the following URL:
https://v154-105-30-8.route.hybrid.api.here.com/rt?.....
Is this the expected behavior so that a single traffic routing request results in 30 transactions, or am I doing something fundamentally incorrect?

As a follow up, the SDK team acknowledged there is a bug with SDK 3.14 (and possibly earlier).
When the NavigationManager is set to DYNAMIC traffic routing, if the route would go slightly off the path, it would immediately call the server for rerouting. In the example I created, a .5 mile trip resulted in 70 calls to the Server Routing API.
The SDK team stated this should only occur after 5 seconds but was not working properly. 3.15 should address this issue.
So, if anyone is using 3.14 (I am unsure about earlier versions) with the NavigationManager and DYNAMIC routing, check your transaction count as it may be much higher then expected.

Related

Web Service Call Stopped Processing

I have a bunch of Xamarin iOS applications running on our Corporate iPhones and iPads. I recently upgraded my Visual Studio and Mac Book Pro to latest release version and my applications are no longer PROCESSING data from my web service correctly. I did not change version of Xamarin.Forms
VS 2017 Version 15.9.13
Xamarin.Forms.2.4.0.282
The web services are http. I have my NSAppTransportSecurityNSAllowsArbitraryLoads
set to allow http.
I am using the flag true to generate the Task.Factory.FromAsync methods in the Web Service Reference.cs file.
I could go on with describing how everything works if anyone needs more info.
Luckily, my Mac Book Pro Simulator has old and new versions of my apps installed in different iPhone/iPad devices for me to test. I installed fiddler to make sure all the requests/responses were the same. My old App in one device works and my new App in a different device fails. Same thing for ALL of my Applications. Old one works and new one fails.
When I review fiddler, the requests and responses are all working the same:
Request is made
App gets an authentication prompt
Authentication happens
Request returns code 200 with the data requested
The only difference in Fiddler is that two of the headers are in a different order: Working one has SOAPAction first and Content-Type next, the one failing has Content-Type and then SOAPAction. I am grasping at straws here because the order of these headers should not matter.
This is for all the applications. The only problem is that my new applications are ignoring the response. It is almost like the endMethod function from the parameter passed to FromAsync is never called.
This is the function call:
public async Task<ProcessLogon> ExecuteSaveLogon(DeviceItem DeviceItem)
{
ResultLogin = new ProcessLogon();
try
{
var ProcessLogon = await Task<WebServiceTrading.ProcessLogon>.Factory.FromAsync(serviceTrading.BeginSaveLogon, serviceTrading.EndSaveLogon, ToServiceTrading(DeviceItem), TaskCreationOptions.None);
ResultLogin = FromServiceTrading(ProcessLogon);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(#"ExecuteSaveLogon ERROR {0}", ex.Message);
}
return ResultLogin;
}
Does anyone know of any DEBUG or LOGGING tools that I could use to find out why my successful response is lost?

IdentityModel.OidcClient library doesn't seem to work with UWP

We are using ASP.NET Identity with IdentityServer4. We've added a Client to use with Azure AD. This works great within a web page, that part is working.
Our end goal is a UWP app, so we found the IdentityModel.OidcClient which has a UWP sample. This sample has two browser classes. We configured HTTPS, but the WabBrowser class now refuses to connect to the site at all. If I change the config to hit https://demo.identityserver.io then it works, but all the other config is the same, so I'm not sure what the problem could be. It shows an error message in the pop up browser that it could not connect.
I looked at the SystemBrowser class, but this logs in fine, then the browser window does not close, and even if we close it, the code doesn't move on to get back a result. Looking at the source, this is not surprising, it calls:
Launcher.LaunchUriAsync(new Uri(options.StartUrl));
and that's all. The RedirectUri is not passed in, and mechanism appears to exist to use it. So, the behaviour we see appears to be the extent of what the class can do.
Looking at the console .NET Core sample, it has a SystemBrowser class that works. I updated the UWP sample to use the Fall Creators Update and was able to bring in the ASP.NET Core dlls needed to compile this code. It sets up a class like this:
public LoopbackHttpListener(int port, string path = null)
{
path = path ?? String.Empty;
if (path.StartsWith("/")) path = path.Substring(1);
_url = $"http://127.0.0.1:{port}/{path}";
_host = new WebHostBuilder()
.UseKestrel()
.UseUrls(_url)
.Configure(Configure)
.Build();
_host.Start();
}
and I can confirm this gets called only once, but even if I hard code an unused IP address, I get an error that the IP is in use.
So, at this stage, the sample that exists for UWP works for the demo server but not for ours (I suspect an HTTPS issue, but that's not the error I get), and importing code that works for a Core sample, does not work either. I've spent a couple of days on this and would appreciate a nudge in the right direction.
So, to recap, the WabBrowser seems the best bet but, for my localhost IdentityServer I get this:
and if I try to use a .NET Core library that works elsewhere, it thinks a port is in use. I suspect I need to work out why WabBrowser can't connect to my local site. I have turned off Fiddler. I can browse to my https URL and get a disco document, in the browser, at https://localhost:44305/.well-known/openid-configuration.
There are extra steps necessary to enable localhost in the Web Authentication Broker -
https://msdn.microsoft.com/en-us/library/windows/desktop/jj658959%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
This website gave me the fix. Here is a synopsis:
Remove loopback isolation
For security and reliability reasons, UWP applications are not allowed to send requests to the loopback interface. While Visual Studio automatically creates exemptions for debugged apps, this feature won't be helpful in this case, as the authentication broker always executes in a separate process.
If you see this (cryptic) error message in your Windows event logs, then you're likely facing this issue:
AuthHost encountered a navigation error at URL: [...] with StatusCode: 0x800C0005.
One option to fix it is to use the loopack exemption utility developed by Eric Lawrence. It's natively included in Fiddler 4 but can also be downloaded as a standalone software. To allow the authentication broker to communicate with the loopback interface, exempt the applications starting with microsoft.windows.authhost and save your changes:
If everything was properly configured, you should now see the login/consent page returned by your server.

Previously working Python script using Google Reporting API v4 now returning 403

I wrote a python script to pull yesterday's data from Google Analytics. I'm using OAuth v2 with Google Reporting API v4. The backbone of the script is essentially the same as Google's sample version, except I included recursion to overcome the pagination limitation and am outputting the results to a CSV file.
Today it started to return a 403 error:
HttpError 403 when requesting https://analyticsreporting.googleapis.com/v4/reports:batchGet?alt=json returned "The caller does not have permission"
I did my due diligence by searching for a solution, but I already am using the ViewID and the computer that it's running on isn't signed into any other accounts (it exists to only run reports). I've also tried creating a new client_secrets.json file and verifying that I am within quotas, but the issue still persists. Nothing changed between yesterday and today, yet it refuses to run today.
EDIT
I'm using the same connection object, it's only instantiated once, the code is the exact same as on Google's website here -> Hello Analytics Reporting API v4 - Python
def initialize_analyticsreporting():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[tools.argparser])
flags = parser.parse_args([])
flow = client.flow_from_clientsecrets(
CLIENT_SECRETS_PATH, scope=SCOPES,
message=tools.message_if_missing(CLIENT_SECRETS_PATH))
storage = file.Storage('analyticsreporting.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage, flags)
http = credentials.authorize(http=httplib2.Http())
analytics = build('analytics', 'v4', http=http, discoveryServiceUrl=DISCOVERY_URI)
return analytics
I'm invoking it the batchGet method on each request like so...
response = analytics.reports().batchGet(body=loaded_request.get("request", {})).execute()
I've managed to work around this by using the exponential back-off in conjunction with recursion and try/except block, similar to the method recommended by Google here -> Error Responses
Like so:
try:
response = analytics.reports().batchGet(body=loaded_request.get("request", {})).execute()
except HttpError as err:
print(err)
time.sleep(2**expontential_backoff)
expontential_backoff += 1
if expontential_backoff < 5:
get_response(analytics, request, page_token, file_name, expontential_backoff)
else:
print("expontential_backoff:", expontential_backoff, "Exceeded")
return
If the error hits then when by when n > 1 it usually works just fine. I'm not terribly fond of this method, ideally I would like it to work correctly.
If there is no other solution, then hopefully this will help someone in the future.

Do I need a new PayPal API to support TLS 1.2 on .Net server?

I am running ASP.Net 4.5, but using a very old version of the PayPal SOAP api. The reference is to paypal_base.dll with a reported version of 4.3.1.0. The code that calls the API has "using" statements that reference:
com.paypal.sdk.services
com.paypal.soap.api.
I have verified at the point where the call to the PayPal api is made, that this value
System.Net.ServicePointManager.SecurityProtocol
includes both ssl3 and tls1.2.
I am pointing at the "sandbox" mode.
But when the setExpressCheckout call is made, I get a runtime exception that says:
The request was aborted: Could not create SSL/TLS secure channel.
I have downloaded the PayPal API Samples project and using the same sandbox credentials, it works. Looking in Fiddler, the calls are nearly identical except the samples API call goes to api-3t.sandbox.paypal.com, while my code goes to api-aa.sandbox.paypal.com, but according to the documentation on TLS 1.2 readyness, both apis should work. I don't see anywhere in either API to set the endpoint other than switching between "live" and "sandbox".
In the fiddler response, both show:
"A SSLv3-compatible ServerHello handshake was found. Fiddler extracted the parameters below.
Version: 3.3 (TLS/1.2)"
And the responses are identical except for the "random" parameter. So the old API call is using TLS 1.2
My code and the Samples API code are only slightly different, the sample uses:
SetExpressCheckoutRequestType request = new SetExpressCheckoutRequestType();
populateRequestObject(request); //populate request data
SetExpressCheckoutReq wrapper = new SetExpressCheckoutReq();
wrapper.SetExpressCheckoutRequest = request;
Dictionary<string, string> configurationMap = Configuration.GetAcctAndConfig(); //set merchant config
PayPalAPIInterfaceServiceService service = new PayPalAPIInterfaceServiceService(configurationMap);
SetExpressCheckoutResponseType setECResponse = service.SetExpressCheckout(wrapper); //make the call
Where my (again, very old code looks like this):
CallerServices caller = new CallerServices();
caller.APIProfile = SetProfile.ApplicationProfile; //set merchant config
SetExpressCheckoutRequestType pp_request = new SetExpressCheckoutRequestType();
// Create the request details object
pp_request.SetExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType();
pp_request.SetExpressCheckoutRequestDetails.PaymentAction = paymentAction;
pp_request.SetExpressCheckoutRequestDetails.PaymentActionSpecified = true;
pp_request.SetExpressCheckoutRequestDetails.OrderTotal = new BasicAmountType();
pp_request.SetExpressCheckoutRequestDetails.OrderTotal.currencyID = currencyCodeType;
pp_request.SetExpressCheckoutRequestDetails.OrderTotal.Value = paymentAmount;
pp_request.SetExpressCheckoutRequestDetails.CancelURL = cancelURL;
pp_request.SetExpressCheckoutRequestDetails.ReturnURL = returnURL;
return (SetExpressCheckoutResponseType) caller.Call("SetExpressCheckout", pp_request); //do the call
The sample code works, my code throws the SSL/TLS error. I tried upgrading to the latest SDK, but so much has changed, it will be quite a large effort to migrate all that code.
From fiddler, it seems to be using TLS 1.2 even with the old API, but I get a runtime exception about the SSL/TLS connection. Is it because of the different endpoint? Is the old API just too old?
Thanks in advance for any help - I would love to avoid migrating all that ancient code!.
EDIT: I should mention I am using the UserName/Password/Signature credentials, not certificate based credentials.
As TLS1.2 is supported in .Net4.5 but it is not a default protocol. you need to opt-in to use it. The following code will make TLS 1.2 default, make sure to execute it before making a connection to secured resource:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
I was having a similar issue, with a PP Sandbox credentialing "HttpWebRequest" in C# Web Application 4.5, receiving the following error: "You must write ContentLength bytes to the request stream before calling [Begin]GetResponse".
I read this Q/A and applied the ServicePointManager reference from above answer - as the first line in my HttpWebRequest call method, and it worked. Thanks to all.
FYI, the example code I am building is from //learn.microsoft.com, "Getting Started with ASP.NET 4.5 Web Forms and Visual Studio 2017".

TodoList sample Bing Maps service returns error with status blank

I am working thru the sample todolist application for the Cordova SDK.
the url is here
https://msdn.microsoft.com/en-us/library/dn832630.aspx
I set up a key on the BING Maps website. I can access the location service sending latitude and longitude thru a standard web browser, pasting in the URL with my key.
However the angular call always fails. What is worse is the error is always blank. no status code no error message. Was thinking it must be CORS.
I have run through the sample and downloaded the code sample and both have the same issue.
For anyone going thru the sample. I have realised today that Angular is evil. They say it is nicely testable javascript with dependancy injection, however it doesn't seem to be too interested in telling you what the error is when you have one, it just fails. Great and noble programming ideas, but without an error message it isn't much good.
Anyhow the fix is that Angular is very strict about json code so the line in services.js for the Bings Maps Service method getAddressFromPosition
it used to work with .get() but this was probably an old version of Angular when the demo was written. I tried using 1.2 but the Ripple emulator didn't like references to browser specific code. So I used the latest 1.3.13 I believe.
This is where to access the Bing location service with the Cordova geolocation coordinates returns Json, but Angular wants them wrapped in JSONP. searching the increasing fragmented web it appeared the error might be CORS no, so a many different people had their JSONP calls in controllers, modules, services, some using $http others $resources. Finally using bits and pieces I got JSONP to work with $resources and to plug it into the $promise the call from the controller requires. I used a static Url with Coordinates I knew worked, so you will have to use the :param angular notation to put those back in. Hope it helps someone.
So change to:
getAddressFromPosition: function (position) {
var resource = $resource(url, {}, {
jsonp_query: {
method: 'JSONP'
}
});
return resource.jsonp_query().$promise.then(function (response) {
return response.resourceSets[0].resources[0].address.formattedAddress;
}, function (error) {
return position.coords.latitude + "," + position.coords.longitude
});
edit:
I put the above in and it worked. However the problem was for some reason, perhaps thru debugging, another instance of the app was deployed on another port in ripple. This then change the app to run on this new port. The initial port was 4400. The problem is that and $http or $resource calls in angular have to go thru this emulator, and the emulator was seeing this as cross domain, unless it is configured to the same port the app is running under.
so Url:
http://localhost:4409/index.html?enableripple=cordova-3.0.0-iPhone5
then in the Settings Div dropdown on the right side, the Proxy Port must also be set to 4409 or else the browser will complain that the $http request is cross-domain, before the emulator actually executes it to query Azure mobile service or Bing maps.
So this was very frustrating. However VS Cordova has definately reduced the amount of bits you have to configure to make hybrid mobile apps, there are still little glitches like this which can trip you up. I assumed it was something with angular, because there was no error messages, but in Chrome in the Dev Tools console that was where the error was, and after some googling it was plain that it was the ripple emulator running on a different port than its proxy was not allowing the call to be forwarded on due to Access-Control-Allow not being set.

Resources