During one of my experiments with GeoEvent Server GeoEvent Extension for Server, I needed to test out real-time streaming. Having only dabbled with JSON before, it was time for me to get real. To Python!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# @date 13/05/2015 | |
# @author Cindy Williams | |
# | |
# Creates a point feature class in memory containing | |
# random points within a predefined extent, and posts | |
# the points as ESRI JSON to a REST endpoint. | |
# | |
# For use as a standalone script | |
# | |
import json | |
import requests | |
import random | |
import os | |
import arcpy | |
from string import ascii_uppercase | |
arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(4326) | |
headers = {'Content-Type': 'application/json'} | |
url ="" # Insert REST endpoint here for POST | |
ext = "17.7556923735604 -34.8330442856367 24.2223940143152 -30.4302569614079" # Predefined extent | |
gdb = r"in_memory" | |
ftr = "randompts" | |
points = os.path.join(gdb, ftr) | |
def attrToesriJSON(x, y, name): | |
# Format for ESRI JSON | |
return {"attributes":{"Name":name}, "geometry":{"x":x,"y":y}} | |
arcpy.management.CreateRandomPoints(gdb, ftr, "", ext) | |
arcpy.management.AddField(points, "Name", "TEXT", "#", "#", 10) | |
with arcpy.da.UpdateCursor(points, ("SHAPE@XY", "Name")) as cursor: | |
for row in cursor: | |
# Assign a random label to each point. Not worried about repeating IDs here | |
row[1] = random.choice(ascii_uppercase) + str(random.randrange(1000, 10000)) | |
cursor.updateRow(row) | |
# Generate the JSON | |
data_json = json.dumps(attrToesriJSON(row[0][0], row[0][1], row[1])) | |
# Post the JSON | |
response = requests.post(url, data=data_json, headers=headers) | |
# Optional: persist to disk | |
arcpy.conversion.FeaturesToJSON(points, r"C:\Some\Arb\Folder\randompts.json") |
I’d like to point out that even though I only wrote this script 4 months ago, I’ve learned enough in the meantime to want to rewrite this script. I’d still like to walk it through it though, because the tweaks I would like to make to it are more optimisations/best practice than fixing any bugs.
IIRC, this was my first dalliance with the delightful requests module. In Line 22, I used the url provided by GeoEvent after setting up a “Receive Features on a REST Endpoint” input connector. In Line 23, I manually entered an extent I had determined using a technique I like to call “looking at it in ArcMap”. This extent is used in the Create Random Points geoprocessing tool to constrain the area in which random points would be created.
(I’ve been moving away from using geoprocessing tools available in arcpy, in favour of pure Python. Instead of calling the Create Random Points tool, I would rather use the random tool to generate the coordinates and then physically build the point geometries.)
In the search cursor, after processing every row as JSON and assigning a random label, the JSON is POSTed. What this does mean is that the REST service is going to get hammered with those points one after the other. For testing purposes, only a small set of points were generated, and the server can easily handle the load.
What if, in some future scenario, I have (hundreds of) thousands of points trying to get through at the same time? I can’t easily think of such a scenario, but since I’ve been moving more and more into development, I’d like to keep these things in mind.