Mapbox API requests for Static Map and Polyline - api

I'm rewording a question I asked earlier in hopes that it will get me some feedback.
I need to generate a static map from Mapbox that shows two end points and the polyline route between them. The method outlined below is what I'm using. It sometimes works and sometimes doesn't--and that is what's driving me crazy.
First, I use the two GPS end points to make an API request that generates the polyline. Then I use a second API request with the two end points and the polyline to generate the static map. The first part always seems to work. I get an encoded polyline that I can run through an online decoding tool and it shows the various points along the path just fine, but the second step to generate the map from Mapbox sometimes gives me the expected map and sometimes gives me an error code. The code is usually {"message":"Not Found"}, but sometimes I get a {"message":"Not Authorized - No Token"} error code.
I use this API with the two end points to get a JSON file that has a polyline:
https://api.mapbox.com/directions/v5/mapbox/driving/POINT1;POINT2?access_token=TOKEN
Then, once I have the polyline, I am using this API to generate the map:
https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(POINT1),pin-s-b+000(POINT2),path-5+f44-0.5(POLYLINE)/auto/500x300?access_token=TOKEN
This works fine...
Point 1 = -87.321536,36.584454
Point 2 = -104.793676,38.749513
Polyline = }kh~Ez{}sO|HUuHmj#uhHbOyAla#kisAdelC|aMf~w#egO|uaAahfBr{|#w_#sAozkCcwFsp#v]__w#hjFjf#bdCkaJhmzAiyXtzb#fJ|{#{p[|~yErtBdacE{x^vkvHrZfuKo[tpBfxSrcuBocGpi_AqhCvjb#wgAvfsDhyc#fkrD~mD~bkDayD~ywCsui#vjmEoyBpk|AiOhHrvEdueApda#huoA|v[zuhFsySvwaAvbDwqHxXpwDYj#riJULheEfXh^tdAj~I^gIhAkEY~#kHseBlGyC^kA
Map API request = https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(-87.321536,36.584454),pin-s-b+000(-104.793676,38.749513),path-5+f44-0.5(}kh~Ez{}sO|HUuHmj#uhHbOyAla#kisAdelC|aMf~w#egO|uaAahfBr{|#w_#sAozkCcwFsp#v]__w#`hjFjf#bdCkaJhmzAiyXtzb#fJ|{#{p[|~yErtBdacE{x^vkvHrZfuKo[tpBfxSrcuBocGpi_AqhCvjb#wgAvfsDhyc#fkrD~mD~bkDayD~ywCsui#vjmEoyBpk|AiOhHrvEdueApda#huoA|v[zuhFsySvwaAvbD`wqHxXpwDYj#riJULheEfXh^tdAj~I`^gI`hAkEY~#kHseBlGyC^kA)/auto/500x300?access_token=TOKEN
Map (yay!)
This does not work...
Point 1 = -87.321536,36.584454
Point 2 = -85.855218,37.690038
Polyline = }kh~Ez{}sO|HUtCurC}xCkhC}~BqvIuc_#o~l#oaI}aUrs#kkL}~Iso\qHoyGsiKaTpQcRdlGusK_DEiz#w^cwOakJurAizT{hCugF_bBenSsOclZkdCw]mgEwyDogLgfBatEubCmkGxa#icLe_Do_Spf#cw]}sEgOaDgT{[zFyIk~Bts#
Map API request = https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(-87.321536,36.584454),pin-s-b+000(-85.855218,37.690038),path-5+f44-0.5(}kh~Ez{}sO|HUtCurC}xCkhC}~BqvIuc_#o~l#oaI}aUrs#kkL}~Iso\qHoyGsiKa`TpQcRdlGusK_DEiz#w^cwOakJurAizT{hCugF_bBenSs`OclZkdCw]mgEwyDogLgfBatEubCmkGxa#icLe_Do_Spf#cw]}sEgOaDgT{[zFyIk~Bts#)/auto/500x300?access_token=TOKEN
No Map :-(
This is a small part of a much bigger project where I am automating the process for generating project reports, but the problem isn't with my jQuery/AJAX code. It's a problem with my APIs and/or Mapbox. If there is a better/faster/easier way to get these maps, then I am absolutely open to suggestions, because this does not seem like the most efficient way to do it. I will be generating these reports from a computer. I am not worried about bandwidth or scaling down for a phone application. The file can be as cumbersome as it wants to be as long as I can consistently generate a map every time.

Steve's comment hints at the right solution, but just to make it absolutely clear - this is happening because you are not properly encoding the path polyline in your request. Polylines in particular have a nasty habit of including reserved characters that will break URIs unless properly encoded at the time of the request.
When I encode the polyline portion of your path overlay with a simple tool like url encode decode, I'm able to make your request work as expected:
https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(-87.321536,36.584454),pin-s-b+000(-85.855218,37.690038),path-5+f44-0.5(%7Dkh~Ez%7B%7DsO%7CHUtCurC%7DxCkhC%7D~BqvIuc_%40o~l%40oaI%7DaUrs%40kkL%7D~Iso%2FqHoyGsiKa%60TpQcRdlGusK_DEiz%40w%5EcwOakJurAizT%7BhCugF_bBenSs%60OclZkdCw%5DmgEwyDogLgfBatEubCmkGxa%40icLe_Do_Spf%40cw%5D%7DsEgOaDgT%7B%5BzFyIk~Bts%40)/auto/500x300?access_token=MAPBOX_ACCESS_TOKEN
⚠️ disclaimer: I currently work at Mapbox ⚠️

Related

REST API signature guidance

Seeking guidance on REST API Signature for an API.
To handle logistics, we want to support shipping label generation for courier packages.
Which of these would be a more RESTFul way to model these APIs.
Generate Label API : POST /package/{package-id}/label.
Regenerate Label API : POST /package/{package-id}/label/regenerate.
vs
Generate Label API : POST /package/{package-id}/label?operation=generate.
Regenerate Label API : POST /package/{package-id}/label?operation=regenerate.
Regenerate API ends up creating a new Label for the package, based on updated shipping dates, etc passed as part of request payload.
Just use:
POST /package/{package-id}/label
PUT/PATCH /package/{package-id}/label
https://restfulapi.net/http-methods/
If the /package/{package-id}/label is a 'label resource' that you're creating, then the appropriate method is probably PUT here.
But 'regenerating' is a bit hard to explain here. Could you just fetch the label over and over again by doing a GET request on /package/{package-id}/label.
If 'creating a label' or 'regenerating a label' doesn't have side-effects (such as a physical printer printing a label), then a GET might work best.
If 'creating a label' or 'regenerating a label' is not really returning a label but causing some external effect in a different system, then it feels better for this to be more like the RPC call you mentioned.
POST /package/{package-id}/label
Then my question is, why is there a difference between 'generating' and 'regenerating'. It sounds like you're just doing the same thing twice. Do you really need 2 endpoints? Can't the system figure out if a label was created before for the {package-id}?
If the system doesn't know the label is generated vs regenerated, and only the client can know I would be inclined to use the same endpoint and add some flag to the request body instead of having 2 different URLS.

Sony A7Sii not showing expected API features

I'm trying to control a Sony a7SII via the pysony Sony Camera API wrapper.
https://github.com/Bloodevil/sony_camera_api
I'm able to connect to the camera, start the session, but I'm not getting the expected list of possible API functions back.
My process looks like this:
import pysony
api = pysony.SonyAPI()
api.startRecMode()
api.getAvailableApiList()
{'id': 1, 'result': [['getVersions', 'getMethodTypes', 'getApplicationInfo', 'getAvailableApiList', 'getEvent', 'actTakePicture', 'stopRecMode', 'startLiveview', 'stopLiveview', 'awaitTakePicture', 'getSupportedSelfTimer', 'setExposureCompensation', 'getExposureCompensation', 'getAvailableExposureCompensation', 'getSupportedExposureCompensation', 'setShootMode', 'getShootMode', 'getAvailableShootMode', 'getSupportedShootMode', 'getSupportedFlashMode']]}
As you can see, the returned list does not contain a full set of controls.
Specifically, I want to be able to set the shutter speed and aperture. Which based on this matrix https://developer.sony.com/develop/cameras/ I should be able to do.
Any ideas would be much appreciated.
Turns out, both pysony and the API are working fine.
You must install the Remote App from the store rather than relying on the "embedded" remote that ships with the camera to get full API functionality.
Also as a note; it seems to take a little time for the 'api.startRecMode()' to actually update the available API list. Sensible to add a little delay to your code.
See:
src/example/dump_camera_capabilities.py

how to get errors from tileupdatemanager

In my winrt app, I am trying to update the live tile based on polled URIs. There is currently no update happening and I can't figure out how to troubleshoot. There are numerous scenarios that could be breaking things but i can't seem to find anyway to get insight into potential errors.
The TileUpdateManager seems to be a bit of a black hole that absorbs information but never lets it out.
Does anyone know of how to view errors from the TileUpdateManager?
If it interests anyone, here is my update code:
TileUpdateManager.CreateTileUpdaterForApplication().EnableNotificationQueue(true);
PeriodicUpdateRecurrence recurrence = PeriodicUpdateRecurrence.HalfHour;
List<Uri> urisToPoll = new List<Uri>();
urisToPoll.Add(new Uri(#"http://livetileservice2012.azurewebsites.net/api/liveupdate/1"));
urisToPoll.Add(new Uri(#"http://livetileservice2012.azurewebsites.net/api/liveupdate/2"));
TileUpdateManager.CreateTileUpdaterForApplication().StartPeriodicUpdateBatch(urisToPoll, recurrence);
To expand on Nathan's comment, here are two steps you can take to troubleshoot:
Enter your URI straight into a browser to see the results that are returned, and inspect them for being proper XML. As Nathan points out, your URIs are returning JSON which will be ignored by the tile update manager. As a working example (that I use in Chapter 13 of my HTML/JS book), try http://programmingwin8-js-ch13-hellotiles.azurewebsites.net/Default.cshtml.
If you feel that your URI is returning proper XML, try it in the Push and Periodic Notifications Sample (Scenarios 4 and 5 for tiles and badges). If this works, then the error would be in your app code and not in the service.
Do note that StartPeriodicUpdate[Batch] will send a request to the service right away, rather than waiting for the first interval to pass.
Also, if you think that you might have a problem with the service, it's possible to step through its code using Visual Studio Express for Web running on the localhost, when the app is also running inside Visual Studio Express for Win8 (where localhost is enabled).
.Kraig

How to get mapserver to work

I've been working with MapServer for about 2 hours now , but it seems alittle bit complicated to get started with.
So here's my question
Is there any way to get mapserver to show a simple map of whole world in which I can move the map to see different parts of the world ?
( from what I've learnt so far , it just shows you the Map you've passed the mapserv cgi , and the map is static and cannot be moved ! )
EDIT :
I'm still wondering if I can have a simple map for the whole world or a country or whatever ! Should I be Writing .Map Files for everything On my own ??
Okay , so after looking it up and struggling alittle , I found some JS libraries to do this, One of the was Open Layers. You just have to reference it at the beginning of your html page like :
<script src="http://openlayers.org/api/OpenLayers.js"></script>
and then you can have zoom and move options for your map by binding MapServer data as follows to the OpenLayers init function.
Var map, layer;
function init(){
map = new OpenLayers.Map( 'map' );
layer = new OpenLayers.Layer.MapServer( "NAME",
"http://localhost/cgi-bin/mapserv", {map: 'PATH_TO_.MAP'} );
map.addLayer(layer);
map.zoomToMaxExtent();
}
And lots of cool tutorials can be found in spatialhorizons.com.
Hope this helps someone :)
MapServer is just that, a MAP SERVER. It sounds like you are currently using a cgi script to display a hosted map. WMS providers like MapServer host data that can be viewed using a WMS client application. There are many such applications. You will need a more sophisticated client application to connect to the MapServer in order to perform more complicated map manipulations.
check out GoogleEarth
or NASA WorldWind
or I haven't used this yet but it looks like it might be the easiest, if least dependable.
First MapServer is the GIS server side technology. The zoom in/ pan is the client side behavior in my opinion.
When we look at the moment that user pan/zoom at one web application, what really happened is the front end application get the pan/zoom event and make calls to mapserver to get the new map to return to the client side.
So it is more likely your leaflet, Google map API, Openlayers, etc. are handling the detection of the client movement and parse it into new getmap request and send the request to mapserver to get the response.
What you saw from the MapServer using get request is static and it is suppose to be so. The dynamic part is happened in the client side to make dynamic calls from the front end application to make these static calls. That is interactive when client side dynamically sending out request and refresh the map from the response.

Amazon S3 pre signed URLs using Amazon Java SDK and extra / characters

I've been creating Presigned HTTP PUT URLs and everything was working great until I wanted to start using "folders" in S3; I wanted the key to have the character '/'.
Now I get Signature doesn't match when I send the HTTP PUT requests due to the fact the '/' probably changes to %2F... If I escape the character before creating the presigned URL it works great, but then the Amazon console management doesn't understand it and shows it as one file instead of subfolders.
Any idea?
P.s.
The HTTP PUT requests are sent using C++ with POCO NET library.
EDIT
I'm using Poco HttpRequest from C++ to my Java web server to generate a signed url (returned on the response).
C++ then uses this url to put a file in s3 using Poco again.
The problem was that the urls returned from the web server were parsed through Poco URI objects that auto decoded the s3 object key thus changing it.With that in mind I was able to fix my problem.
Tricky - I'll try to approach this bottom up.
Disclaimer: I got carried away visually inspecting the Poco libraries instead of actually debugging a code sample, which should yield more reliable results much faster, see below ;)
Analysis
If I escape the character before creating the presigned URL it works
great, but then the Amazon console management doesn't understand it
and shows it as one file instead of subfolders.
The latter stems from S3 not having a concept of folders on the storage level actually, see e.g. section Index Documents and Folders within Index Document Support:
Objects stored in Amazon S3 are stored within a flat container, i.e.,
an Amazon S3 bucket, and it does not provide any hierarchical
organization, similar to a file system's. However, you can create a
logical hierarchy using object key names and use these names to infer
logical folders that contain these objects.
That's exactly what the AWS Management Console is doing here as well:
The AWS Management Console also supports the concept of folders, by
using the same key naming convention used in the preceding sample.
However, your test regarding the assumption of / being encoded as %2F proves, that this is indeed how Poco::Net is encoding the URL when performing the HTTP PUT request.
(I'm actually a bit surprised that the AWS Java SDK seems to generate different URLs here for / vs. %2F, insofar a recent analysis regarding Why is my S3 pre-signed request invalid when I set a response header override that contains a “+”? seems to indicate respective canonicalization by the AWS .NET SDK, see below for more on this.)
Potential Solution
In order for your scenario to work as desired, you'll need to figure out where the URL is encoded this way - I could think of two components in principle:
Poco::Net
Finding out why Poco::Net is encoding the URL different than S3 (if at all, see below) is best done by debugging your code, here's where I'd start:
Class HTTPRequest uses class URI in turn, which automatically performs a few normalizations on all URIs and URI parts passed to it, in particular percent-encoded characters are decoded. The other way round is handled by method encode(), which is where things get interesting and call for a breakpoint, see URI.cpp:
lines 575 ff. - here encode() does its magic, which indeed seems to be in place, insofar neither the code within the function nor the various chars passed in via the reserved parameter contain the offending / (see lines 47 ff. for the respective constants in use)
consequently you might want to set a breakpoint in this function and backtrace the callstack to find out which code is actually doing the encoding upfront, which might not yield an offender at all, see below.
Java => C++ transition
You haven't specified yet, which channel is actually used to communicate the pre-signed URL generated by the AWS Java SDK to C++ in turn. Given the code review (mind you, visual inspection only, I haven't debugged this myself yet) of the Poco::Net functionality yields the conclusion, that no obvious offender can be identified in the library itself, thus it seems more likely that it might already enter your C++ layer encoded (easily verified via debugging of course) - are you by chance using any kind of web service between these components for example?
Good luck!