1

I'm trying to automate updating a tile service where:

  1. TPK is generated from a feature class in an .mxd (data frame is web mercator)

  2. TPK is pushed up to AGOL

  3. Tile Service is published

  4. TPK is deleted from AGOL

If the service doesn't exist, the script bombs, as we expect it to. Then we just run it again after creating the service. Once the tile service is in place we hope to update it with tiles generated from a feature class that gets edited periodically.

Once the service exists, it is failing to get overwritten and the following error occurs:

Invalid min scale in the specified source item

TPK generation script main:

#Setting variables
import datetime
print "Setting variables"
timeStamp = datetime.datetime.now().strftime("%Y%m%d")
print "timeStamp = " + timeStamp


in_map = '\\\\server\cyber_batch$\DBAGROUP\DEV\DATA\ArcGIS\MXD\AGOL\Surveyor_Tract_Map_Tiles.mxd'
print "in_map = " + in_map
service_type = "ONLINE"
print "service_type = " + service_type
output_file = r"\\server\cyber_batch$\DBAGROUP\DEV\DATA\ArcGIS\RasterTilePackages\Surveyor_Tract_Map"
print "output_file = " + output_file
format_type = "PNG"
print "format_type = " + format_type
level_of_detail = "20"
print "level_of_detail = " + level_of_detail
logFile = r'\\server\cyber_batch$\DBAGROUP\DEV\DATA\ArcGIS\RasterTilePackages\Logs\Surveyor_Tract_Map_Tiles_%s.txt' % timeStamp
print "logFile = " + logFile
print "Variables set"


#Call CreateMapTilePackage_sub script
print "CreateMapTilePackage_sub script"
from CreateMapTilePackage_sub import *
CreateMapTilePackage(in_map, service_type, output_file,
     format_type, level_of_detail, timeStamp, logFile)

TPK generation sub:

import arcpy
from arcpy import env
import os, sys, time, datetime, traceback, string

# Set environment settings
env.workspace = ""

# print results of the script to a report
#report = open(logFile,'w')

# use "scaleValues[0]","scaleValues[-1]","scaleValues[0:3]"

print "Processing..."

def CreateMapTilePackage(in_map, service_type, output_file,
     format_type, level_of_detail, timeStamp, logFile):
        report = open(logFile,'w')
    try:
        starttime = time.clock()
        result = arcpy.CreateMapTilePackage_management(in_map, service_type, output_file, format_type, level_of_detail)

        finishtime = time.clock()
        finishtime = time.clock()
        elapsedtime = finishtime - starttime

        #print messages to a file
        while result.status < 4:
            time.sleep(0.2)
        resultValue = result.getMessages()
        report.write ("completed " + str(resultValue))

        print "Exported cache successfully for " + output_file + " to " + " in " + str(elapsedtime) + " secs."


    except Exception, e:
        # If an error occurred, print line number and error message
        print "Exception :("
        tb = sys.exc_info()[2]
        report.write("Failed at step 1 \n" "Line %i" % tb.tb_lineno)
        report.write(e.message)
        exit(99)

TPK upload to AGOL main:

#Set variables
from UpdateTileLayer import *
import datetime

user= 'someuser' #raw_input('ArcGIS Online Username')
print "user = " + user
pw = 'somepassword'#raw_input('ArcGIS Online Password')
print "pw = ########"
baseUrl = "https://www.arcgis.com"
print "baseURL = " + baseUrl
referer = "http://www.arcgis.com/sharing"
print "referer = " + referer
numThreads = 10
print "Number of Threads = " + str(numThreads)
layerName ='Tract_Map_Tiles_Test'
print "layerName = " + layerName
tpk =  r"\\server\cyber_batch$\DBAGROUP\DEV\DATA\ArcGIS\RasterTilePackages\Surveyor_Tract_Map.tpk" #location of TPK
print "tpk = " + tpk
extent = ''
print "extent = " + extent
lods = '0-10' #enter levels in format outlined http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Update_Tiles/02r30000022v000000/
print "lods = " + lods

print "Variables set"

print(str(datetime.datetime.today()) + " - Start")   

updateTileLayerWithNewTPK(user,pw,layerName,tpk,extent,lods,baseUrl,referer,numThreads)

print(str(datetime.datetime.today()) + " - End") 

TPK upload to AGOL sub script (UpdateTileLayer):

from __future__ import print_function
import sys
import traceback
import time
import datetime
import Queue
import threading
import requests
import os
import mmap
import io
from LoginToAGOL import *

    ################################################################################
# Globals
owner = 'someuser'
referer = "http://www.arcgis.com/sharing"
gInterrupt = False
MAX_PARTS = 20000
PAGE_SIZE = 8192
FILE_UPLOAD_CUTOVER_SIZE = 50 * 1024 * 1024
MIN_FILE_SIZE = 5 * 1024 * 1024
MAX_FILE_SIZE = 800 * 1024 * 1024 * 1024
DEFAULT_PART_SIZE = 25 * 1024 * 1024
MAX_PART_SIZE = 150 * 1024 * 1024
verbose = True
TIMEOUT=180

def uploadTilePackage(baseUrl, agolUsername, token, layerName, extent, filename, threads, itemtype, itemtitle, verbosep,
               nostream, partsize):
    statinfo = os.stat(filename)
    if statinfo.st_size < FILE_UPLOAD_CUTOVER_SIZE:
        return uploadTilePackageSimple(agolUsername, baseUrl, filename, layerName, extent, token)
    else:
        return uploadTilePackageMultipart(baseUrl, agolUsername, token, filename, threads, itemtype, itemtitle, verbosep,
               nostream, partsize)

# delete a previously uploaded tile package identified by itemid
def deleteItem(user, token, portalUrl, itemid):
    url = '{}.maps.arcgis.com/sharing/rest/content/users/{}/items/{}/delete?f=json&token={}'.format(portalUrl, user, itemid,
                                                                                                   token)
    return requests.post(url,timeout=TIMEOUT).json()

# overwrite the previous set of tiles in the service with the new tile package
def updateTileLayer(user, token, portalUrl, orgID, layerName, extent, lods, itemid):

    print("Importing new Tile Package into Tile Layer")

    url = "https://tiles.arcgis.com/tiles/{}/arcgis/rest/admin/services/{}/MapServer/importTiles".format(orgID,
                                                                                                         layerName)
    data = {"extent": extent, "levels": lods, "token": token, 'f': 'json', "mergeBundle": 'true',
            "replaceTiles": 'true', 'sourceItemId': itemid}
    ret = requests.post(url, data,timeout=TIMEOUT).json()
    if "error" in ret:
        return {"status": "fail", "errmsg": ret["error"]["message"]}

    # check publishing status until status is complete
    statusURL = '{}.maps.arcgis.com/sharing/rest/content/users/{}/items/{}/status?jobId={}&f=json&token={}'.format(portalUrl, user, ret['itemId'], ret['jobId'], token)
    requestStatus = requests.get(statusURL)
    status = requestStatus.json()
    while status['status'] == 'processing':
        print("Status=" + status['status'])
        time.sleep(10)
        statusURL = '{}.maps.arcgis.com/sharing/rest/content/users/{}/items/{}/status?jobId={}&f=json&token={}'.format(portalUrl, user, ret['itemId'], ret['jobId'], token)
        requestStatus = requests.get(statusURL)
        status = requestStatus.json()

    # return ok status if completed
    print("Status=" + status['status'])
    if status['status'] == "completed":
        return {"status": "ok"}
    else:
        return {"status": "fail", "errmsg": status["status"]}

# The ESRI API does not set the update date when you import tiles(!), so we need to do it
# manually with a separate call.
def updateTileLayerDate(user, token, portalUrl, layerName):

    print("Setting Update Date for Tile Layer")
    result = search(token,title=layerName,type='Map Service',owner=owner)
    if "results" in result:
        if len(result["results"]) == 1:
            if "id" in result["results"][0]:
                url = '{}.maps.arcgis.com/sharing/rest/content/users/{}/items/{}/update?f=json&token={}'.format(portalUrl, user,
                                                                                                        result["results"][0]["id"],
                                                                                                        token)
                result = requests.post(url,timeout=TIMEOUT).json()
                if "success" in result:
                    if result["success"]:
                        return {"status": "ok"}
    # return fail status if not completed ok
    return {"status": "fail", "errmsg": str(result)}

    def updateTileLayerWithNewTPK(user,pw,layerName,tpk,extent,lods,baseUrl,referer,numThreads):
        # Login to AGOL to get token
        print("Logging into AGOL...")
        result = login(user, pw, baseUrl, referer)
        if result == None:
            print("Error occured logging into AGOL. No token received or ssl flag received")
            exit(99)
        if (not "token" in result and "ssl" in result):
            print("Error occured logging into AGOL. No token received or ssl flag received")
            exit(99)
        token = result["token"]
        sslFlag = result["ssl"]
        print("Logged into AGOL. Received token")

        # Create Portal URL and assign variables
        result = getAccount(sslFlag, token)
        if result == None:
            print("Error occured getting AGOL Account info.")
            exit(99)
        portalUrl = result["portalUrl"]
        orgID = result["id"]

        # Upload the tile package to AGOL
        result = uploadTilePackage(baseUrl, user, token, layerName, extent, tpk, numThreads, None, None, True, False, None)
        if not "status" in result:
            print("Error occured uploading tile package")
            exit(99)
        if result["status"] != "ok":
            print("Error occured uploading file. Status received = " + result["status"])
            if "errmsg" in result:
                print(result["errmsg"])
            exit(99)
        if not "itemid" in result:
            print("Error occured uploading file. No itemid received")
            exit(99)
        itemid = result["itemid"]
        print("Received itemid for uploaded TPK = " + itemid)

        # Call UpdateTileLayer_uploadItem version script
        result = updateTileLayer(user, token, portalUrl, orgID, layerName, extent, lods, itemid)
        if not "status" in result:
            print("Error occured importing new TPK into tile layer")
            exit(99)
        if result["status"] != "ok":
            print("Error occured importing new TPK into tile layer. Status received = " + result["status"])
            if "errmsg" in result:
                print(result["errmsg"])
            exit(99)
        print("New Tile Package imported")

        # Set the update date for the layer
        result = updateTileLayerDate(user, token, portalUrl, layerName)
        if not "status" in result:
            print("Error updating date")
            exit(99)
        if result["status"] != "ok":
            print("Error occured updating date. Status received = " + result["status"])
            if "errmsg" in result:
                print(result["errmsg"])
            exit(99)
        print("Tile Layer Update Date set to new date")

        # Clean up - Delete the uploaded tile package
        result = deleteItem(user, token, portalUrl, itemid)
        if not "success" in result:
            print("Error occured deleting tile package")
            exit(99)
        if not result["success"]:
            print("Error occured deleting tile package.")
            exit(99)
        print("TPK file deleted")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.