Search code examples
jsonrestgismaximospatial-query

Maximo/GIS spatial query


I have a work order in Maximo 7.6.1.1:

  • The WO has LatitudeY and LongitudeX coordinates in the Service Address tab.
  • The WO has a custom zone field.

And there is a feature class (polygons) in a separate GIS database.


I want to do spatial query to return an attribute from the polygon record that the WO intersects and use it to populate zone in the WO.

How can I do this?

Related keyword: Maximo Spatial


Solution

  • Adapt the code in the Library Scripts section of Maximo 76 Scripting Features (pdf):

    #What the script does:
    #     1. Takes the X&Y coordinates of a work order in Maximo
    #     2. Generates a URL from the coordinates
    #     3. Executes the URL via a separate script/library (LIB_HTTPCLIENT)
    #     4. Performs a spatial query in an ESRI REST feature service (a separate GIS system)
    #     5. Returns JSON text to Maximo with the attributes of the zone that the work 
    #        order intersected
    #     6. Parses the zone number from the JSON text
    #     7. Inserts the zone number into the work order record
    
    from psdi.mbo import MboConstants
    from java.util import HashMap
    from com.ibm.json.java import JSONObject
    
    field_to_update = "ZONE"
    gis_field_name = "ROADS_ZONE"
    
    def get_coords():
        """
        Get the y and x coordinates(UTM projection) from the WOSERVICEADDRESS table
        via the SERVICEADDRESS system relationship.
        The datatype of the LatitdeY and LongitudeX fields is decimal.
        """
        laty  = mbo.getDouble("SERVICEADDRESS.LatitudeY")
        longx = mbo.getDouble("SERVICEADDRESS.LongitudeX")
    
        #Test values
        #laty  = 4444444.7001941890
        #longx = 666666.0312127020
    
        return laty, longx
    
    
    def is_latlong_valid(laty, longx):
        #Verify if the numbers are legitimate UTM coordinates
        return (4000000 <= laty <= 5000000 and
                600000 <= longx <= 700000)
    
    
    def make_url(laty, longx, gis_field_name):
        """
        Assembles the URL (including the longx and the laty).
        Note: The coordinates are flipped in the url.
        """
    
        url = (
            "http://hostname.port"
            "/arcgis/rest/services/Example"
            "/Zones/MapServer/15/query?"
            "geometry={0}%2C{1}&"
            "geometryType=esriGeometryPoint&"
            "spatialRel=esriSpatialRelIntersects&"
            "outFields={2}&"
            "returnGeometry=false&"
            "f=pjson"
        ).format(longx, laty, gis_field_name)
    
        return url
    
    
    def fetch_zone(url):
        # Get the JSON text from the feature service (the JSON text contains the zone value).
        ctx = HashMap()
        ctx.put("url", url)
        service.invokeScript("LIBHTTPCLIENT", ctx)
        json_text = str(ctx.get("response"))
    
        # Parse the zone value from the JSON text
        obj = JSONObject.parse(json_text)
        parsed_val = obj.get("features")[0].get("attributes").get(gis_field_name)
    
        return parsed_val
    
    
    try:
        laty, longx = get_coords()
        if not is_latlong_valid(laty, longx):
            service.log('Invalid coordinates')
        else:
            url = make_url(laty, longx, gis_field_name)
            zone = fetch_zone(url)
    
            #Insert the zone value into the zone field in the work order
            mbo.setValue(field_to_update, zone, MboConstants.NOACCESSCHECK)
            service.log(zone)
    except:
        #If the script fails, then set the field value to null.
        mbo.setValue(field_to_update, None, MboConstants.NOACCESSCHECK)
        service.log("An exception occurred")
    

    LIBHTTPCLIENT: (a reusable Jython library script)

    from psdi.iface.router import HTTPHandler
    from java.util import HashMap
    from java.lang import String
    
    handler = HTTPHandler()
    map = HashMap()
    map.put("URL", url)
    map.put("HTTPMETHOD", "GET")
    responseBytes = handler.invoke(map, None)
    response = String(responseBytes, "utf-8")