<\/HEAD>
Im Rahmen des Waze Connected Citizen Program (CCP)<\/A> erhalten Partner Zugang zu Echtzeit-Verkehrsstaus und Vorfällen, die über die Waze-App gemeldet werden (im XML- und JSON-Format). Es gibt bereits Techniken und Dokumentationen<\/A>, wie diese Daten in eine ArcGIS-Plattform mit GeoEvent integriert werden können.<\/P><\/P>
In diesem Blog werde ich eine Technik beschreiben, um diese Daten über Python und den Windows Task Scheduler in ArcGIS Online zu integrieren. Das
ursprüngliche Python-Skript<\/A> wurde von Joel Meier<\/A> entwickelt, welches ich angepasst habe, um den vorgeschlagenen Workflow zu erfüllen. Ein besonderer Dank geht auch an meine Kollegen Edmund Hall<\/A> und Louis Tian<\/A>, die mir beim Debuggen geholfen haben. Und nicht zuletzt möchte ich Andrew Stauffer<\/A>03danken, der uns als Partner unterstützt hat und das Beste aus dem Waze CCP<\/A> herausholt.<\/P><\/P>
Erstellen von ArcGIS Online Feature-Layern zur Speicherung von Verkehrsinformationen<\/H2>Melden Sie sich bei ArcGIS Online > Meine Inhalte an, klicken Sie auf Erstellen > Feature-Layer, wählen Sie Von URL aus<\/EM> und geben Sie die genaue URL der Punkt-Feature-Layer-Vorlage ein. Wiederholen Sie anschließend denselben Vorgang für den Linien-Feature-Layer. Dadurch werden neue leere Feature-Layer mit dem erforderlichen Schema erstellt (Feldnamen, Typen und räumliche Referenz)<\/EM>.<\/P>Punkt-Feature-Layer-Vorlage<\/STRONG><\/SPAN><\/P>https:\/\/services1.arcgis.com\/E5n4f1VY84i0xSjy\/arcgis\/rest\/services\/WazeTrafficAlertsEmpty\/FeatureServer<\/A><\/SPAN><\/P>Linien-Feature-Layer-Vorlage<\/STRONG><\/SPAN><\/P>
https:\/\/services1.arcgis.com\/E5n4f1VY84i0xSjy\/arcgis\/rest/services/WazeTrafficJamsEmpty/FeatureServer<\/_a>Alternativ besuchen Sie https://developers.arcgis.com/layers/new, um Punkt- und Linien-Geometrie-Feature-Layer (WKID = 4326) mit den folgenden Feldern zu erstellen.
Punkt - Feature LayerOBJECTID (Typ: esriFieldTypeOID, Alias: OBJECTID, SQL-Typ: sqlTypeOther, Länge: 0, nullable: false, bearbeitbar: false)*DateReported (Typ: esriFieldTypeDate, Alias: DateReported, SQL-Typ: sqlTypeTimestamp2, Länge: 0, nullable: true, bearbeitbar: true)Title (Typ: esriFieldTypeString, Alias: Title, SQL-Typ: sqlTypeOther, Länge: 25, nullable: true, bearbeitbar: true)ReportType (Typ: esriFieldTypeString, Alias: ReportType, SQL-Typ: sqlTypeOther, Länge: 25, nullable: true, bearbeitbar: true)ReportSubtype (Typ: esriFieldTypeString, Alias: ReportSubtype, SQL-Typ: sqlTypeOther, Länge: 50, nullable: true, bearbeitbar: true)Street (Typ: esriFieldTypeString, Alias: Street, SQL-Typ: sqlTypeOther, Länge: 256, nullable: true, bearbeitbar: true)City (Typ: esriFieldTypeString, Alias: City, SQL-Typ: sqlTypeOther, Länge: 50, nullable: true, bearbeitbar: true)Description (Typ: esriFieldTypeString, Alias: Beschreibung, SQL-Typ: sqlTypeOther, Länge: 1024, nullable: true, bearbeitbar: true)<\/EM><\/SPAN><\/LI>UUID (Typ: esriFieldTypeDouble, Alias: UUID, SQL-Typ: sqlTypeOther, nullable: true, bearbeitbar: true)<\/EM><\/SPAN><\/LI><\/UL>Shape__Length (Typ: esriFieldTypeDouble, Alias: Shape__Length, SQL-Typ: sqlTypeDouble, nullable: true, nicht bearbeitbar)*<\/STRONG><\/EM><\/SPAN><\/LI>CreationDate (Typ: esriFieldTypeDate, Alias: CreationDate, SQL-Typ: sqlTypeOther, Länge: 8, nullable: true, nicht bearbeitbar)*<\/STRONG><\/EM><\/SPAN><\/LI>Creator (Typ: esriFieldTypeString, Alias: Creator, SQL-Typ: sqlTypeOther, Länge: 128, nullable: true, nicht bearbeitbar)*<\/STRONG><\/EM><\/SPAN><\/LI>EditDate (Typ: esriFieldTypeDate, Alias: EditDate, SQL-Typ: sqlTypeOther, Länge: 8, nullable: true, nicht bearbeitbar)*<\/STRONG><\/EM><\/SPAN><\/LI>Editor (Typ: esriFieldTypeString, Alias: Editor, SQL-Typ: sqlTypeOther, Länge: 128, nullable: true, nicht bearbeitbar)*<\/STRONG><\/EM><\/SPAN><\/LI><\/UL>*<\/STRONG>vorausgefüllte Felder<\/EM><\/SPAN><\/P>Bitte stellen Sie sicher, dass Sie die genauen Feldnamen und Typen<\/EM><\/STRONG> verwenden (alternativ müssten Sie das Skript anpassen).<\/SPAN><\/P>Sobald Feature-Layer konfiguriert sind, bitte Aktivieren Sie die Bearbeitung<\/STRONG> und setzen Sie sie auf PRIVATE<\/STRONG>.<\/SPAN><\/P>Bitte beziehen Sie sich auf "Waze Feed Technical Specifications [Get Waze Data]"<\/EM><\/STRONG> im Partner's Portal<\/A> für genaue Definitionen zu Feldbeschreibungen.<\/P><\/BLOCKQUOTE><\/P>
Konfiguration des Python-Skripts<\/H4>Ersetzen Sie die Kommentarabschnitte (Zeilen 6, 9 und 10)<\/SPAN><\/EM> mit Ihrem eigenen XML-Feed und URLs für Ihre Punkt- und Linien-Feature-Layer.<\/P>import<\/SPAN> xml.<\/SPAN>etree.<\/SPAN>ElementTree as<\/SPAN> ET
import<\/SPAN> urllib.<\/span>request
import<\/span> arcpy
from<\/span> datetime import<\/span> datetime
namespaces ={'georss': 'http://www.georss.org/georss', 'linqmap': 'http://www.linqmap.com'}
tree = ET.ElementTree(file=urllib.request.urlopen('##URL for XML waze connection##'))
root = tree.getroot()
channel_head = []
fcp = "##URL to Point - Feature Layer##"
fcl = "##URL to Line - Feature Layer##"
for member in root.findall('channel/item'):
channel = []
Title = member.find('title').text.upper()
try:
point = member.find('georss:point', namespaces)
line = member.find('georss:line', namespaces)
except:
pass
print('Fehler Stufe 0')
if point != None:
try:
Date = member.find('pubDate').text
DateReported = datetime.strptime(Date, '%a %b %d %H:%M:%S %z %Y')
if len(member.findall('linqmap:city', namespaces)) > 0:
City = member.find('linqmap:city', namespaces).text
else:
City = ''
if len(member.findall('linqmap:street', namespaces)) > 0:
Street = member.find('linqmap:street', namespaces).text
else:
Street = ''
if len(member.findall('linqmap:subtype', namespaces)) > 0 and member.find token">.<\/SPAN>find(<\/SPAN>'linqmap:subtype'<\/SPAN>,<\/SPAN> namespaces)<\/SPAN>.<\/SPAN>text ist<\/SPAN> nicht<\/SPAN> None:<\/SPAN>\n Subtype =<\/SPAN> member.<\/SPAN>find(<\/SPAN>'linqmap:subtype'<\/SPAN>,<\/SPAN> namespaces)<\/SPAN>.<\/SPAN>text.<\/SPAN>replace(<\/SPAN>'_'<\/SPAN>,<\/SPAN> ' '<\/SPAN>)<\/SPAN>.<\/SPAN>capitalize(<\/SPAN>)<\/SPAN>\n sonst<\/SPAN>:<\/SPAN>\n Subtype =<\/SPAN> ''<\/Span>\n\n UUID =<\/SPAN> member.<\/Span>find(<\/Span>'linqmap:uuid'<\/Span>,<\/Span> namespaces)<\/Span>.<\/Span>text\n Reliability =<\/Span> member.<\/Span>find(<\/Span>'linqmap:reliability'<\/Span>,<\/Span> namespaces)<\/Span>.<\/span>text\n\n wenn len(member.findall('linqmap:reportDescription', namespaces)) 3e 30):
Description = member.find('linqmap:reportDescription', namespaces).text
sonst:
Description = ''
Type = member.find('linqmap:type', namespaces).text.replace('_', ' ').capitalize()
point = member.find('georss:point', namespaces).text.replace(' -', ',-').split(' ')
row = Subtype, Type, Title, DateReported, City, Street, UUID, Reliability, Description, float(point[1]), float(point[0])
cursor = arcpy.da.InsertCursor(fcp, ["ReportSubtype", "ReportType", "Title", "DateReported", "City", "Street", "UUID", "Reliability", "Description", "SHAPE@X", "SHAPE@Y"])
cursor.insertRow(row)
del cursor
print('stage 1')
except:
pass
print('fail Stage 1')
elif line != None:
if Title != 'IRREGULARITY':
try:
Date = member.find('pubDate').text
DateReported = datetime.strptime(Date, '%a %b %d %H:%M:%S %z %Y')
if len(member.findall('linqmap:city', namespaces)) > 0:
City = member.find('linqmap:city', namespaces).text
else:
City = ''
if len(member.findall('linqmap:startNode', namespaces)) > 0:
StartNode = member.find('linqmap:startNode', namespaces).text
else:
StartNode = ''
if len(<\/SPAN>member.<\/SPAN>findall(<\/SPAN>'linqmap:endNode'<\/SPAN>,<\/SPAN> namespaces)<\/SPAN>)<\/SPAN> ><\/SPAN> 0<\/SPAN>:<\/SPAN>
EndNode =<\/SPAN> member.<\/SPAN>find(<\/SPAN>'linqmap:endNode'<\/SPAN>,<\/SPAN> namespaces)<\/SPAN>.<\/SPAN>text
else<\/SPAN>:<\/SPAN>
EndNode =<\/SPAN> ''<\/SPAN>
if<\/SPAN> len(<\/SPAN>member.<\/SPAN>findall(<\/SPAN>'linqmap:reportDescription'<\/Span>,<\/span> namespaces)<\/span>)<\/span> ><\/span> 0<\/span>:<\/span>
Beschreibung =<\/span> member.<\/span>find(<\/span>'linqmap:reportDescription'<\/span>,<\/span> namespaces)<\/span>.<\/span>text
else<\/span>:<\/span>
Beschreibung =<\/span> ''<\/span>
if<\/span> len(<\/span>member.<\/span>findall(<\/span>'linqmap:street'<\/span>,<\/span> namespaces)<\/span>)<\/span> ><\/span> 0<\/span>:<\/span>
Straße =<\/span> member.<\/span>find(<\/span>'linqmap:street'<\/span>,<\/span> namespaces)<\/span>.<\/span>text
else<\/span>:<\/span>
Straße =<\/span> ''<\/span>
UUID < spanclass= "operatortoken" > = < \/ span > member < spanclass= " punctuationtoken " > . < \/ span > find < spanclass= " punctuationtoken " > ( < \/ span > < spanclass= " stringtoken " > 'linqmap:uuid' < \/ span > , namespaces < spanclass= " punctuationtoken " > ) < \/ span > . text
Typ < spanclass= " operatortoken " > = < \/ span > member < spanclass= " punctuationtoken " > . < \/ span > find < spanclass= " punctuationtoken " > ( < \/ span > < spanclass= " stringtoken " > 'linqmap:type' < \/ span > , namespaces < spanclass= " punctuationtoken " > ) < \/ span > . text . replace ( '_' , ' ' ) . capitalize ( )
Länge < spanclass= " operatortoken " > = < \/ span > member < spanclass= " punctuationtoken " > . find ( 'linqmap:length' , namespaces ) . text
Ebene < spanclass= " operatortoken " > = < \/ span > member < spanclass= " punctuationtoken " > . find ( 'linqmap:level' , namespaces ) . text
Linie < spanclass= " operatortoken " > = < \/ span > member . find ( 'georss:line' , namespaces ) . text . replace ( '\n' , '' ) . replace ( ' ' , '],[' ) . replace ( '],[-' , ', -' ) . split ( ', ' )
Geschwindigkeit < spanclass= " operatortoken " > = < \/ span > member . find ( 'linqmap:speed' , namespaces ) . text
Verzögerung < spanclass= " operatortoken " > = < \/ span > member . find ( 'linqmap:delay' , namespaces ) . text
cur = arcpy.da.InsertCursor(fcl, ["Speed", "Delay", "Title", "ReportType", "DateReported", "City", "Street", "Length", "ReportLevel", "UUID", "StartNode", "EndNode", "Description", "SHAPE@"])
array = arcpy.Array()
für coords in Linie:
xy = coords.split('],[')
array.add(arcpy.Point(xy[1], xy[0]))
cur.insertRow([Geschwindigkeit, Verzögerung, Titel, Typ, DatumGemeldet, Stadt, Straße, Länge, Ebene, UUID, StartNode, EndNode, Beschreibung, arcpy.Polyline(array)])
del cur
print( token">'Stufe 2'<\/SPAN>)<\/SPAN>
außerhalb von Ausnahme<\/SPAN>:<\/SPAN>
passiere<\/SPAN>
drucke<\/SPAN>(<\/SPAN>'Stufe 2 fehlgeschlagen'<\/SPAN>)<\/SPAN>
sonst<\/SPAN>:<\/SPAN>
versuche<\/SPAN>:<\/SPAN>
Datum =<\/SPAN> mitglied.<\/SPAN>finde(<\/SPAN>'updateDate'<\/SPAN>)<\/SPAN>.<\/SPAN>text
DatumGemeldet =<\/SPAN> datetime.<\/SPAN>strptime(<\/SPAN>Datum, <\/SPAN> '%a %b %d %H:%M:%S %z %Y'<\/SPAN>)<\/SPAN>
wenn<\/SPAN> len(<\/SPAN>mitglied.<\/SPAN>findealle(<\/Span>'linqmap:city'<\/Span>, <\/Span> namespaces)<\/Span> 0:
StartKnoten = mitglied.find('linqmap:startNode', namespaces).text
sonst:
StartKnoten = ''
wenn len(mitglied.findall('linqmap:endNode', namespaces)) > 0:
EndKnoten = mitglied.find('linqmap:endNode', namespaces).text
sonst:
EndKnoten = ''
wenn len(mitglied.findall('linqmap:reportDescription', namespaces)) > 0:
Beschreibung = mitglied.find('linqmap:reportDescription', namespaces).text
sonst:
Beschreibung = ''
wenn len(mitglied.findall('linqmap:street', namespaces)) > 0:
Straße = mitglied.find('linqmap:street', namespaces).text
sonst:
Straße = ''
UUID = mitglied.find('linqmap:id', namespaces).text
Typ = mitglied.find('linqmap:type', namespaces).text.replace('_', ' ').capitalize()
Länge = mitglied.find('linqmap:length', namespaces).text
Ebene = mitglied.find('linqmap:trend', namespaces).text
linie = mitglied.find('georss:line', namespaces).text.replace('\n', '').replace(' ', '],[').replace'],[-', ', -').split(', ')
Geschwindigkeit = mitglied.find('linqmap:speed', namespaces).text
Verzögerung = mitglied.find('linqmap:delaySeconds', namespaces).text
cur = arcpy.da.InsertCursor(fcl, ["Speed", "Delay", "Title", "ReportType"] token">,"DateReported","City","Street","Length","ReportLevel","UUID","StartNode","EndNode","Description","SHAPE@"])
array = arcpy.Array()
für coords in line:
xy = coords.split('],[')
array.add(arcpy.Point(xy[1], xy[0]))
cur.insertRow([Speed,Delay,Title,Type,DateReported,City,Street,Length,Level,UUID,StartNode,EndNode,Description,arcpy.Polyline(array)])
del cur
print('Stufe 3'<\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN><\/SPAN>
Planung des Skripts
Sobald das Python-Skript läuft, verwenden Sie den Windows Aufgabenplanung, um das Skript in bestimmten Zeitintervallen auszuführen, wodurch neue Features zu den ArcGIS Online Feature-Layern hinzugefügt werden (diese Technik hält eine Historie aller Verkehrsinformationen seit dem ersten Ausführen des Skripts).

Anzeige von Live-Verkehrsinformationen
Um Live-Verkehrsinformationen anzuzeigen - erstellen Sie Feature-Layer-Ansichten und definieren Sie deren Features, um nur Features anzuzeigen, die in den letzten x Minuten erstellt wurden, wobei x die Häufigkeit ist, mit der Sie das Python-Skript eingerichtet haben.
Ich habe das Python-Skript so eingerichtet, dass es alle 4 Minuten ausgeführt wird - entsprechend die Feature-Layer-Ansichten, um Features anzuzeigen, die in den letzten 4 Minuten erstellt wurden.

Sobald eingerichtet, können Sie diese Ansichten öffentlich teilen und in öffentlich zugänglichen Anwendungen anzeigen.
Unten finden Sie Links zu unseren Feature-Layer-Ansichten und eine Karte, die diese Features zusammen mit Straßen-/Gehwegssperrungen anzeigt.
*Klicken Sie hier, um mehr über unseren Antragsprozess für Straßen-/Gehwegarbeiten zu erfahren

E-Mail an bestimmte Personen senden, wenn ein Unfall gemeldet wird
Ich habe die folgende Methode verwendet, alternativ könnten Sie ähnliche Python-Skripte nutzen oder Ihr eigenes Python-Skript erstellen, um eine E-Mail auszulösen, wenn neue Features zu einem Feature-Layer hinzugefügt werden.
Führen Sie das E-Mail-Skript Ihrer Wahl auf einer neuen Feature-Layer-Ansicht (Geometrietyp = Punkt), die nur Unfälle (ReportType = "Accident"), bei denen DateReported in den letzten x Minuten lag, anzeigt.

Und schließlich richten Sie den Windows Aufgabenplaner ein, um alle neuen Features (Unfälle) zu erfassen, die in den letzten x Minuten aufgetreten sind.
Ich hoffe, Sie können diese Workflows nutzen, um sie an Ihre eigenen Geschäftsanforderungen anzupassen. Und bitte zögern Sie nicht, Ihre Gedanken, Kommentare oder Fragen im Kommentarbereich unten zu teilen.
Viele Grüße! - Gee Fernando