""" Copyright 2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ import arcpy import argparse import sys import json from arcgis.gis import GIS from arcgis.features import FeatureLayerCollection # Parse Command-line arguments def parseArguments(): parser = argparse.ArgumentParser( usage='Add/Update GNSS metadate fields') arcpy.AddMessage("Parsing Arguments..") parser.add_argument('url', help='Organization url') parser.add_argument('username', help='Organization username') parser.add_argument('password', help='Organization password') parser.add_argument('itemId', type=str, help='Feature service Item Id') parser.add_argument('layerIndex', type=int, help='Feature Layer index. If not specified use 0 as index') parser.add_argument('-r', dest='remove', default=False, type=bool, help='Set True if GNSS metadata fields need to be removed') args_parser = parser.parse_args() if '*' in args_parser.password: args_parser.password = password = arcpy.GetParameterAsText(2) arcpy.AddMessage("Done parsing arguments..") return args_parser # Search for a item id and add GNSS Metadata fields def searchItems_addGNSSMetadataFields(args_parser): # Search ItemIds gis = GIS(args_parser.url, args_parser.username, args_parser.password) arcpy.AddMessage("Signed into organization..") itemId = args_parser.itemId try: featureLayerItem = gis.content.get(itemId) # Construct a FeatureLayerCollection from the portal item. featureLayerCollection = FeatureLayerCollection.fromitem(featureLayerItem) # Extract fields from Feature layer service definition featureLayerFields = featureLayerCollection.manager.layers[args_parser.layerIndex].properties[ 'fields'] if args_parser.layerIndex else \ featureLayerCollection.manager.layers[0].properties['fields'] # Feature Layer index featureLayerIndex = args_parser.layerIndex if args_parser.layerIndex else 0 # Check if the Feature layer is of type esriGeometryPoint if featureLayerCollection.manager.layers[featureLayerIndex].properties['geometryType'] != 'esriGeometryPoint': arcpy.AddError("Feature layer is not a point layer") raise ValueError("Feature layer is not a point layer") # New fields which need to be added gnssMetadataFields = {'fields': []} # Operations list - Add, Update or delete GNSS Metadata fields. operations = [] arcpy.AddMessage("Adding/Updating gnss fields..") # Add/Update GNSS Metadata fields if not args_parser.remove: # ESRIGNSS_POSITIONSOURCETYPE positionsourcetypeField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_POSITIONSOURCETYPE'] if positionsourcetypeField: # Field does exist check if the domain is set. if positionsourcetypeField[0]['domain'] == None: if ([operation for operation in operations if operation == 'updateDefinition']): operations.append('updateDefinition') positionsourcetypeFieldIndex = featureLayerFields.index(positionsourcetypeField[0]) positionsourcetypeDomain = {'type': 'codedValue', 'name': 'ESRI_POSITIONSOURCETYPE_DOMAIN', 'codedValues': [{'name': 'Unknown', 'code': 0}, {'name': 'User defined', 'code': 1}, {'name': 'Integrated (System) Location Provider', 'code': 2}, {'name': 'External GNSS Receiver', 'code': 3}, {'name': 'Network Location Provider', 'code': 4}]} featureLayerFields[positionsourcetypeFieldIndex]['domain'] = positionsourcetypeDomain else: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_POSITIONSOURCETYPE', 'type': 'esriFieldTypeInteger', 'alias': 'Position source type', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': {'type': 'codedValue', 'name': 'ESRI_POSITIONSOURCETYPE_DOMAIN', 'codedValues': [ {'name': 'Unknown', 'code': 0}, {'name': 'User defined', 'code': 1}, {'name': 'Integrated (System) Location Provider', 'code': 2}, {'name': 'External GNSS Receiver', 'code': 3}, {'name': 'Network Location Provider', 'code': 4}]}, 'defaultValue': None}) # ESRIGNSS_RECEIVER recieverField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_RECEIVER'] if not recieverField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_RECEIVER', 'type': 'esriFieldTypeString', 'alias': 'Receiver Name', 'sqlType': 'sqlTypeOther', 'length': 50, 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_LATITUDE latitudeField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_LATITUDE'] if not latitudeField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_LATITUDE', 'type': 'esriFieldTypeDouble', 'alias': 'Latitude', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_LONGITUDE longitudeField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_LONGITUDE'] if not longitudeField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_LONGITUDE', 'type': 'esriFieldTypeDouble', 'alias': 'Longitude', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_ALTITUDE altitudeField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_ALTITUDE'] if not altitudeField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_ALTITUDE', 'type': 'esriFieldTypeDouble', 'alias': 'Altitude', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_H_RMS horizontalAccuracyField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_H_RMS'] if not horizontalAccuracyField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_H_RMS', 'type': 'esriFieldTypeDouble', 'alias': 'Horizontal Accuracy (m)', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_V_RMS verticalAccuracyField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_V_RMS'] if not verticalAccuracyField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_V_RMS', 'type': 'esriFieldTypeDouble', 'alias': 'Vertical Accuracy (m)', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_FIXDATETIME fixTimeField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_FIXDATETIME'] if not fixTimeField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_FIXDATETIME', 'type': 'esriFieldTypeDate', 'alias': 'Fix Time', 'sqlType': 'sqlTypeOther', 'length': 0, 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_FIXTYPE fixTypeField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_FIXTYPE'] if fixTypeField: # Field does exist check if the domain is set. if fixTypeField[0]['domain'] == None: if ([operation for operation in operations if operation == 'updateDefinition']): operations.append('updateDefinition') fixtypeFieldIndex = featureLayerFields.index(fixTypeField[0]) fixTypeDomain = {'type': 'codedValue', 'name': 'ESRI_FIX_TYPE_DOMAIN', 'codedValues': [{'name': 'Fix not valid', 'code': 0}, {'name': 'GPS', 'code': 1}, {'name': 'Differential GPS', 'code': 2}, {'name': 'RTK Fixed', 'code': 4}, {'name': 'RTK Float', 'code': 5}]} featureLayerFields[fixtypeFieldIndex]['domain'] = fixTypeDomain else: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_FIXTYPE', 'type': 'esriFieldTypeInteger', 'alias': 'Fix Type', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': {'type': 'codedValue', 'name': 'ESRI_FIX_TYPE_DOMAIN', 'codedValues': [ {'name': 'Fix not valid', 'code': 0}, {'name': 'GPS', 'code': 1}, {'name': 'Differential GPS', 'code': 2}, {'name': 'RTK Fixed', 'code': 4}, {'name': 'RTK Float', 'code': 5}]}, 'defaultValue': None}) # ESRIGNSS_CORRECTIONAGE correctionAgeField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_CORRECTIONAGE'] if not correctionAgeField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_CORRECTIONAGE', 'type': 'esriFieldTypeDouble', 'alias': 'Correction Age', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_STATIONID stationIdField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_STATIONID'] if stationIdField: # Field does exist check if the domain is set. if stationIdField[0]['domain'] == None: if ([operation for operation in operations if operation == 'updateDefinition']): operations.append('updateDefinition') stationIdFieldIndex = featureLayerFields.index(stationIdField[0]) stationIdDomain = {'type': 'range', 'name': 'ESRI_STATION_ID_DOMAIN', 'range': [0, 1023]} featureLayerFields[stationIdFieldIndex]['domain'] = stationIdDomain else: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_STATIONID', 'type': 'esriFieldTypeInteger', 'alias': 'Station ID', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': {'type': 'range', 'name': 'ESRI_STATION_ID_DOMAIN', 'range': [0, 1023]}, 'defaultValue': None}) # ESRIGNSS_NUMSATS numstatsField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_NUMSATS'] if numstatsField: # Field does exist check if the domain is set. if numstatsField[0]['domain'] == None: if ([operation for operation in operations if operation == 'updateDefinition']): operations.append('updateDefinition') numSatellitesFieldIndex = featureLayerFields.index(numstatsField[0]) numSatellitesDomain = {'type': 'range', 'name': 'ESRI_NUM_SATS_DOMAIN', 'range': [0, 99]} featureLayerFields[numSatellitesFieldIndex]['domain'] = numSatellitesDomain else: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_NUMSATS', 'type': 'esriFieldTypeInteger', 'alias': 'Number of Satellites', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': {'type': 'range', 'name': 'ESRI_NUM_SATS_DOMAIN', 'range': [0, 99]}, 'defaultValue': None}) # ESRIGNSS_PDOP pdopField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_PDOP'] if not pdopField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_PDOP', 'type': 'esriFieldTypeDouble', 'alias': 'PDOP', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_HDOP hdopField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_HDOP'] if not hdopField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_HDOP', 'type': 'esriFieldTypeDouble', 'alias': 'HDOP', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_VDOP vdopField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_VDOP'] if not vdopField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_VDOP', 'type': 'esriFieldTypeDouble', 'alias': 'VDOP', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_DIRECTION directionField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_DIRECTION'] if not directionField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_DIRECTION', 'type': 'esriFieldTypeDouble', 'alias': 'Direction of travel (°)', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_SPEED speedField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_SPEED'] if not speedField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_SPEED', 'type': 'esriFieldTypeDouble', 'alias': 'Speed (km/h)', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRISNSR_AZIMUTH azimuthField = [field for field in featureLayerFields if field['name'] == 'ESRISNSR_AZIMUTH'] if not azimuthField: gnssMetadataFields['fields'].append({'name': 'ESRISNSR_AZIMUTH', 'type': 'esriFieldTypeDouble', 'alias': 'Compass reading (°)', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_AVG_H_RMS averageHorizontalAccuracyField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_AVG_H_RMS'] if not averageHorizontalAccuracyField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_AVG_H_RMS', 'type': 'esriFieldTypeDouble', 'alias': 'Average Horizontal Accuracy (m)', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_AVG_V_RMS averageVerticalAccuracyField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_AVG_V_RMS'] if not averageVerticalAccuracyField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_AVG_V_RMS', 'type': 'esriFieldTypeDouble', 'alias': 'Average Vertical Accuracy (m)', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_AVG_POSITIONS averagePositionsField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_AVG_POSITIONS'] if not averagePositionsField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_AVG_POSITIONS', 'type': 'esriFieldTypeInteger', 'alias': 'Averaged Positions', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # ESRIGNSS_H_STDDEV" standardDeviationField = [field for field in featureLayerFields if field['name'] == 'ESRIGNSS_H_STDDEV'] if not standardDeviationField: gnssMetadataFields['fields'].append({'name': 'ESRIGNSS_H_STDDEV', 'type': 'esriFieldTypeDouble', 'alias': 'Standard Deviation (m)', 'sqlType': 'sqlTypeOther', 'nullable': True, 'editable': True, 'domain': None, 'defaultValue': None}) # Check if AddToDefinition operation needs to be added. initialFeatureLayerFieldsCount = len(featureLayerFields) if (len(gnssMetadataFields[ 'fields']) + initialFeatureLayerFieldsCount) > initialFeatureLayerFieldsCount: operations.append('addToDefinition') else: operations.append('deleteFromDefinition') gnssMetadataFields = { 'fields': [{'name': 'ESRIGNSS_DIRECTION'}, {'name': 'ESRIGNSS_SPEED'}, {'name': 'ESRISNSR_AZIMUTH'}, {'name': 'ESRIGNSS_POSITIONSOURCETYPE'}, {'name': 'ESRIGNSS_FIXDATETIME'}, {'name': 'ESRIGNSS_RECEIVER'}, {'name': 'ESRIGNSS_H_RMS'}, {'name': 'ESRIGNSS_V_RMS'}, {'name': 'ESRIGNSS_LATITUDE'}, {'name': 'ESRIGNSS_LONGITUDE'}, {'name': 'ESRIGNSS_ALTITUDE'}, {'name': 'ESRIGNSS_PDOP'}, {'name': 'ESRIGNSS_HDOP'}, {'name': 'ESRIGNSS_VDOP'}, {'name': 'ESRIGNSS_CORRECTIONAGE'}, {'name': 'ESRIGNSS_FIXTYPE'}, {'name': 'ESRIGNSS_STATIONID'}, {'name': 'ESRIGNSS_AVG_H_RMS'}, {'name': 'ESRIGNSS_AVG_V_RMS'}, {'name': 'ESRIGNSS_AVG_POSITIONS'}, {'name': 'ESRIGNSS_H_STDDEV'}, {'name': 'ESRIGNSS_NUMSATS'}]} # Add/Delete/Modify service definition. for operation in operations: # Add if operation == 'addToDefinition': response = featureLayerCollection.manager.layers[featureLayerIndex].add_to_definition( gnssMetadataFields) arcpy.AddMessage("Successfully added GNSS fields..") # Delete elif operation == 'deleteFromDefinition': response = featureLayerCollection.manager.layers[featureLayerIndex].delete_from_definition( gnssMetadataFields) # Modify else: response = featureLayerCollection.manager.layers[featureLayerIndex].update_definition( featureLayerFields) arcpy.AddMessage("Successfully updated GNSS fields..") result = response['success'] if not result: print('Failed to update Feature layer service definition..') else: print('Service definition updated successfully..') except Exception as e: arcpy.AddError(e) if __name__ == '__main__': args_parser = parseArguments() searchItems_addGNSSMetadataFields(args_parser)