REQ: How to connect to PTV Developer through SAP

This space is dedicated to SAP users - administrators and programmers who want to integrate PTV Developer (native), the PTV xServers or the SAP Hana Spatial Services (HSS). Topics which require specific SAP based knowhow or which deal with SAP based mechanisms will be collected here.
Post Reply
User avatar
Bernd Welter
Site Admin
Posts: 3014
Joined: Mon Apr 14, 2014 10:28 am
Contact:

REQ: How to connect to PTV Developer through SAP

Post by Bernd Welter »

Hi folks,

as more and more SAP driven partners ask me for some kick-off help in the context of PTV Developer I would love to use this forum to request your knowledge:
  • What SAP tools do you use to create connectivity to PTV Developer? (Open API 3 based)
  • What SAP specific feedback/experience would you like to share with the community?
Would be great if we as PTV could extend the tutorial how-generate-clients-ptv-developer-apis in a way that also SAP clients can find help.

Bernd
Bernd Welter
Technical Partner Manager Developer Components
PTV Logistics - Germany

Bernd at... The Forum,LinkedIn, Youtube, StackOverflow
I like the smell of PTV Developer in the morning... :twisted:
User avatar
wessendorf
Posts: 3
Joined: Thu Mar 07, 2024 10:58 am
Contact:

Re: REQ: How to connect to PTV Developer through SAP

Post by wessendorf »

Hi Bernd,

we have already developed an almost complete ABAP/4 wrapper. This allows ABAP/4 developers to consume the APIs of PTV developer as methods of ABAP/4 classes including a definition of the required input and out parameters as SAP dictionary structures. So, PTV developer can be used as simple as any other SAP method inside SAP ERP 6.0 SP08 or S/4 HANA. No additional middleware is required on top. Just the OOTB capabilities of SAP to communicate via HTTPS are required. We use this to add the capabilities of PTV developer integration to our own planning board for scheduling maintenance and service technicians.However, the underlying functions are available in encapsulated in it's own SAP namespace and can be uses as well for other purposes.

I hope this answers your question. If you look for further details, just let me know.

Michael
User avatar
Bernd Welter
Site Admin
Posts: 3014
Joined: Mon Apr 14, 2014 10:28 am
Contact:

Re: REQ: How to connect to PTV Developer through SAP

Post by Bernd Welter »

Meanwhile SAP has launched some new functionality within the Hana Spatial Services:
Based on a BYOL (bring your own license) you can integrate the core services of the PTV Developer Suite What's New for SAP Business Technology Platform | SAP Help Portal
hss 20241219.png
Further info is available here:
HSS.png
Bernd Welter
Technical Partner Manager Developer Components
PTV Logistics - Germany

Bernd at... The Forum,LinkedIn, Youtube, StackOverflow
I like the smell of PTV Developer in the morning... :twisted:
jasci01
Posts: 9
Joined: Mon Feb 12, 2018 3:49 pm

Re: REQ: How to connect to PTV Developer through SAP

Post by jasci01 »

wessendorf wrote: Mon Mar 25, 2024 3:02 pm Hi Bernd,

we have already developed an almost complete ABAP/4 wrapper. This allows ABAP/4 developers to consume the APIs of PTV developer as methods of ABAP/4 classes including a definition of the required input and out parameters as SAP dictionary structures. So, PTV developer can be used as simple as any other SAP method inside SAP ERP 6.0 SP08 or S/4 HANA. No additional middleware is required on top. Just the OOTB capabilities of SAP to communicate via HTTPS are required. We use this to add the capabilities of PTV developer integration to our own planning board for scheduling maintenance and service technicians.However, the underlying functions are available in encapsulated in it's own SAP namespace and can be uses as well for other purposes.

I hope this answers your question. If you look for further details, just let me know.

Michael
Hello Michael,

currently I have to implement xServer 2 (on Prem) connection to an existing SAP system via ABAP, and we face some problems with the swagger file. In detail, we tried to generate interfaces and client classes with ABAP OpenAPI project on github (https://github.com/abap-openapi/abap-openapi) by transforming the swagger to openAPI 3.0 and try to use it there. However, the PTV description uses the allOf operator for describing inherited types, and this is currently not supported. We tried to get rid of the allOf operator using a Python script by ChatGPT, the result was okay, but still buggy. Minor manual fixes could do the job for us, but then we are facing issues in transforming the structures into JSON, because the ABAP fieldnames are not resolved correctly in the JSON fieldnames (which require lower camel case). The solution would be to fix all fields and types by hand so that the SAP interpreter uses the correct JSON fieldnames, or to do a mapping for each field. Both would be connected with high effort.
I am curious to know if you implemented the mentioned wrapper all yourself, or if you used any kind of generator or other helpers .

Kind regards,
Frederik
User avatar
wessendorf
Posts: 3
Joined: Thu Mar 07, 2024 10:58 am
Contact:

Re: REQ: How to connect to PTV Developer through SAP

Post by wessendorf »

Hi Frederik,

Our approach is to create manuallly komplex SAP Dictionary structures that mirror the structures of PTV. Beside this we have a central api that takes care of camel case translation and can deal with PTV's mixture of Post and Get Parameters. We habe as well a Translation mechanism in cases where the PTV fieldnames are longer then the maximum allowed in SAP. As a result we have the classes almost complete for PTV developer as a ready to use library we sell to our customers.

However regrading xServer2 we have done this so far only for the stuff that was needed in our own projects.

The demo example below shows e.g. how routing then looks like from a developers perspective who wants to use the routing capabilities of PTV developer.

*&---------------------------------------------------------------------*
*& Report /MAPS/DEV_TEST_ROUTING
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT /maps/dev_test_routing.

INCLUDE: /maps/dev_helper_routines.

CONSTANTS: lc_polyline_len TYPE i VALUE 200.
DATA: ls_request TYPE /maps/dev_route_request,
ls_response TYPE /maps/dev_route_response,
ls_response2 TYPE /maps/dev_route_response,
ls_error_response TYPE /maps/dev_error_response,
ls_options TYPE /maps/dev_route_options,
ls_waypoint TYPE /maps/dev_waypoint,
lt_waypoints TYPE /maps/dev_array,
lv_timestamp TYPE timestamp,
lv_profile TYPE string,
lt_results TYPE /maps/dev_array.


PARAMETERS:
p_method TYPE /maps/dev_sel_method_routing AS LISTBOX VISIBLE LENGTH 50 OBLIGATORY USER-COMMAND method DEFAULT 'SIMPLE'.

SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF BLOCK simple WITH FRAME TITLE TEXT-001.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (60) TEXT-002.
SELECTION-SCREEN END OF LINE.
PARAMETERS:
p_lat1 TYPE string DEFAULT '49.0133618',
p_long1 TYPE string DEFAULT '8.4277972'.

SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (60) TEXT-003.
SELECTION-SCREEN END OF LINE.
PARAMETERS:
p_lat2 TYPE string DEFAULT '49.020962',
p_long2 TYPE string DEFAULT '8.413760'.

SELECTION-SCREEN END OF BLOCK simple.

SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF BLOCK complex WITH FRAME TITLE TEXT-004.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (60) TEXT-002.
SELECTION-SCREEN END OF LINE.
PARAMETERS:
p_lat_1 TYPE string DEFAULT '49.0133618',
p_long_1 TYPE string DEFAULT '8.4277972'.

SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (60) TEXT-003.
SELECTION-SCREEN END OF LINE.
PARAMETERS:
p_lat_2 TYPE string DEFAULT '49.020962',
p_long_2 TYPE string DEFAULT '8.413760'.

SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (60) TEXT-005.
SELECTION-SCREEN END OF LINE.
PARAMETERS:
p_lat_3 TYPE string DEFAULT '49.015469',
p_long_3 TYPE string DEFAULT '8.374400'.

SELECTION-SCREEN END OF BLOCK complex.

SELECTION-SCREEN SKIP.
SELECTION-SCREEN BEGIN OF BLOCK options WITH FRAME TITLE TEXT-010.
PARAMETERS:
p_vprof TYPE /maps/dev_sel_veh_profile AS LISTBOX VISIBLE LENGTH 30 DEFAULT 'EUR_VAN',
p_routet TYPE /maps/dev_route_mode AS LISTBOX VISIBLE LENGTH 15 DEFAULT 'SHORT_'.

SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT (31) TEXT-006.
PARAMETERS: p_avoid1 AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN COMMENT (6) TEXT-007.
PARAMETERS: p_avoid2 AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN COMMENT (8) TEXT-008.
PARAMETERS: p_avoid3 AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN COMMENT (12) TEXT-011.
PARAMETERS: p_avoid4 AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN COMMENT (17) TEXT-009.
SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN END OF BLOCK options.

AT SELECTION-SCREEN.
PERFORM determine_vehicle_profile USING p_vprof CHANGING lv_profile.

START-OF-SELECTION.
*#######################################################################
* calculateRoute()
*#######################################################################
IF p_method = 'SIMPLE'.

WRITE:/ '###########################################################'.
WRITE:/ ' API calculateRoute() is currently not used.'.
WRITE:/ ' Duplicate URL parameters are possibly not supported by'.
WRITE:/ ' the current SAP http client implementation.'.
WRITE:/ ' Example:'.
WRITE:/ ' waypoints=<Lat>,<Long>&waypoints=<Lat>,<Long>,...'.
WRITE:/.
WRITE:/ ' You can use API calculateRoutePost() instead.'.
WRITE:/ '###########################################################'.
RETURN.

* DATA(lv_wayp1) = |{ p_lat1 },{ p_long1 }|. ";name=W1|.
* APPEND lv_wayp1 TO lt_waypoints.
*
* DATA(lv_wayp2) = |waypoints={ p_lat2 },{ p_long2 }|. ";name=W2|.
* APPEND lv_wayp2 TO lt_waypoints.
*
** lv_profile = /maps/dev=>gc_eur_van.
* lv_profile = p_vprof.
* APPEND 'ROUTE_ID,POLYLINE' TO lt_results.
*
* GET TIME STAMP FIELD lv_timestamp.
* ls_options-start_time = /maps/dev=>conv_timestamp_to_iso( lv_timestamp ).
* ls_options-traffic_mode = /maps/dev_routing=>gc_traffic_mode_realistic.
* IF p_avoid1 IS NOT INITIAL.
* ls_options-avoid = 'TOLL'.
* ENDIF.
* IF p_avoid2 IS NOT INITIAL.
* ls_options-avoid = COND #( WHEN ls_options-avoid IS INITIAL THEN 'FERRIES' ELSE ls_options-avoid && |,FERRIES| ).
* ENDIF.
* IF p_avoid3 IS NOT INITIAL.
* ls_options-avoid = COND #( WHEN ls_options-avoid IS INITIAL THEN 'RAIL_SHUTTLES' ELSE ls_options-avoid && |,RAIL_SHUTTLES| ).
* ENDIF.
*
* /maps/dev_routing=>calculate_route( EXPORTING it_waypoints = lt_waypoints iv_profile = lv_profile is_options = ls_options it_results = lt_results
* IMPORTING es_response = ls_response es_error_response = ls_error_response
* EXCEPTIONS no_authority = 1 OTHERS = 2 ).
*
* IF sy-subrc <> 0 OR ls_error_response IS NOT INITIAL.
* PERFORM error_msg USING ls_error_response.
* ENDIF.
*
* WRITE:/.
* WRITE:/ 'getRouteByRouteId()' COLOR COL_HEADING.
* PERFORM response_output USING ls_response2.

ENDIF.

*#######################################################################
* calculateRoutePost()
*#######################################################################
IF p_method = 'COMPLEX'.
ls_waypoint-name = 'W1'.
ls_waypoint-on_road-latitude = p_lat_1.
ls_waypoint-on_road-longitude = p_long_1.
APPEND ls_waypoint TO ls_request-waypoints.

ls_waypoint-name = 'W2'.
ls_waypoint-on_road-latitude = p_lat_2.
ls_waypoint-on_road-longitude = p_long_2.
APPEND ls_waypoint TO ls_request-waypoints.

ls_waypoint-name = 'W3'.
ls_waypoint-on_road-latitude = p_lat_3.
ls_waypoint-on_road-longitude = p_long_3.
APPEND ls_waypoint TO ls_request-waypoints.

lv_profile = p_vprof.
APPEND 'ROUTE_ID,POLYLINE' TO lt_results.

GET TIME STAMP FIELD lv_timestamp.
ls_options-start_time = /maps/dev=>conv_timestamp_to_iso( lv_timestamp ).
ls_options-traffic_mode = /maps/dev_routing=>gc_traffic_mode_realistic.
IF p_avoid1 IS NOT INITIAL.
ls_options-avoid = 'TOLL'.
ENDIF.
IF p_avoid2 IS NOT INITIAL.
ls_options-avoid = COND #( WHEN ls_options-avoid IS INITIAL THEN 'FERRIES' ELSE ls_options-avoid && |,FERRIES| ).
ENDIF.
IF p_avoid3 IS NOT INITIAL.
ls_options-avoid = COND #( WHEN ls_options-avoid IS INITIAL THEN 'RAIL_SHUTTLES' ELSE ls_options-avoid && |,RAIL_SHUTTLES| ).
ENDIF.

/maps/dev_routing=>calculate_route_post( EXPORTING iv_profile = lv_profile it_results = lt_results is_options = ls_options is_request = ls_request
IMPORTING es_response = ls_response es_error_response = ls_error_response
EXCEPTIONS no_authority = 1 OTHERS = 2 ).

IF ls_error_response IS NOT INITIAL.
PERFORM error_msg USING ls_error_response.
ENDIF.

DATA(lv_header1) = |From waypoint 1 ({ p_lat_1 },{ p_long_1 }) to waypoint 3 ({ p_lat_3 },{ p_long_3 }) via waypoint 2 ({ p_lat_2 },{ p_long_2 })|.
WRITE:/ lv_header1 COLOR COL_TOTAL.
WRITE:/ 'calculateRoutePost()' COLOR COL_HEADING.
PERFORM response_output USING ls_response.

CLEAR: ls_error_response.
/maps/dev_routing=>get_route_by_route_id( EXPORTING iv_id = ls_response-route_id
IMPORTING es_response = ls_response2 es_error_response = ls_error_response
EXCEPTIONS no_authority = 1 OTHERS = 2 ).

IF sy-subrc <> 0 OR ls_error_response IS NOT INITIAL.
PERFORM error_msg USING ls_error_response.
ENDIF.

WRITE:/.
WRITE:/ 'getRouteByRouteId()' COLOR COL_HEADING.
PERFORM response_output USING ls_response2.
ENDIF.

*&---------------------------------------------------------------------*
*& Form RESPONSE_OUTPUT
*&---------------------------------------------------------------------*
FORM response_output USING ps_response TYPE /maps/dev_route_response.

WRITE: /3 'distance:', 18 ps_response-distance LEFT-JUSTIFIED.
WRITE: /3 'travel Time:', 18 ps_response-travel_time LEFT-JUSTIFIED.
WRITE: /3 'trafficDelay:',18 ps_response-traffic_delay LEFT-JUSTIFIED.
WRITE: /3 'violated:', 18 ps_response-violated LEFT-JUSTIFIED.
WRITE: /3 'routeId:', 18 ps_response-route_id LEFT-JUSTIFIED.
IF strlen( ps_response-polyline ) > lc_polyline_len.
WRITE: /3 'polyline:', 18 ps_response-polyline(150), '...' LEFT-JUSTIFIED.
ELSE.
WRITE: /3 'polyline:', 18 ps_response-polyline LEFT-JUSTIFIED.
ENDIF.

ENDFORM.
Post Reply