POST
|
You could not use a Update Cursor. What I like to do is Copy to in_memory arcpy.TableToTable_conversion(inDir + "\\" + inDB + "\\" + table, "in_memory", table) Add a field Calc the new field Join back to original FC or table Calc over the value Now if it is a web map then you could just use Arcade and it would be love time dynamic. Hope that helps.
... View more
01-02-2020
07:53 AM
|
0
|
0
|
572
|
POST
|
I do not think you can just give it a URL and it goes. I am doing something similar where I run QA from a Hosted Feature Service directly. Well its kind of direct. It still has to "download" the data but it goes from a json object right to a search cursor. Mine has to poll a SAML card so it is more complicated. (But you have not been able to hardcode a password in for some time due to OUTH2 - at least that is what Esri said when when my old script went out.) Its hard to take out the Auth code but here is the basics. See the bottom for a simple example. Hope that helps. I use it a lot. Now this is a search cursor like you wrote in script. But if you want to run a geoprocesing tool I am not sure. You could try giving it the object below. Or you may have to download a copy, unzip, feed into the tool. If so you can use this same code but instead submit a download job. I use this to backup AGOL every night. See below to the next script. import os
from uuid import uuid4
import requests
import arcpy, time, datetime
import requests
from requests_arcgis_auth import ArcGISPortalSAMLAuth
# this is on github if you need it for SAML
import tempfile
import wincertstore
# New code from Patrick to handle the SSL scanner
pem_file = r''
with tempfile.NamedTemporaryFile(delete=False) as tf:
for storename in ("CA", "ROOT"):
with wincertstore.CertSystemStore(storename) as store:
for cert in store.itercerts(usage=wincertstore.SERVER_AUTH):
# Py v2
try:
tf.write(cert.get_pem().decode("ascii"))
# Py v3
except:
tf.write(bytes(cert.get_pem(),"ascii"))
tf.flush()
pem_file = tf.name
tf.close()
# Setup Parameters & Authentication
url = r'https://yourorg.maps.arcgis.com/sharing/rest'
client_id = r'okjhasdfhahl'
s = requests.session()
# New add from Patirck to handle SSL scanner
s.verify = pem_file
s.auth = ArcGISPortalSAMLAuth(client_id,verify=pem_file)
#s.auth = ArcGISPortalSAMLAuth(client_id)
# For GeoPlatform
serviceURL = r'https://www.arcgis.com/sharing/rest'
# Standard end of URL
endURL = "/query?f=json&where=1=1&outFields=*&returnGeometry=true"
# set the service item id here
# MT
#item_id_to_query = r'sdfgsdfgdgsgsdg'
# feature class numbers vary by state - set them up here
# MT
##plotsURL = "/" + "0" + endURL
##photosURL = "/" + "1" + endURL
##plotcharURL = "/" + "2" + endURL
##lpiURL = "/" + "3" + endURL
##gapURL = "/" + "4" + endURL
##specrichURL = "/" + "5" + endURL
##soilURL = "/" + "6" + endURL
##plotobURL = "/" + "7" + endURL
##gapdetailURL = "/" + "15" + endURL
##lpidetailURL = "/" + "14" + endURL
##specrichdetailURL = "/" + "12" + endURL
##unknownURL = "/" + "9" + endURL
##print "Running MT"
##useLogFile("MT", logFileDir)
# THIS is where you load into an object for the search cursor
# load in all the layers into vars
# get the base URL and token started
response = s.post(url+"/content/items/{}?f=json".format(item_id_to_query))
fs_endpoint = response.json().get('url')
# plots
q_response = s.get(fs_endpoint + plotsURL)
plotsF = arcpy.FeatureSet()
plotsF.load(q_response.url)
# photos
q_response = s.get(fs_endpoint + photosURL)
photosF = arcpy.FeatureSet()
photosF.load(q_response.url)
# and more...
plotKeys = []
# get a list of Eval PlotKeys from Plots
whereClause = "EvalStatus = 'Eval'"
with arcpy.da.SearchCursor(plotsF,"PlotKey", whereClause) as cursor:
for row in cursor:
plotKeys.append(row[0])
# do other stuff
# old that I left inhere in case it makes more sense without all the card stuff
# Make a request to the item & obtain the feature service endpoint
##response = s.post(url+"/content/items/{}?f=json".format(item_id_to_query))
##fs_endpoint = response.json().get('url')
##print ("Item ID {} feature service is hosted at {}".format(item_id_to_query,fs_endpoint))
##
### Query the end-point.
### Keep in mind, this only works because the service is 'federated' with the portal.
### This would not work for ANY service (including public/anonymous) as it will attach the token, and this token is only good for the specific portal we are working with
##q_response = s.get(fs_endpoint + "/0/query?f=json&where=1=1&outFields=*&returnGeometry=true")
##features = q_response.json().get('features')
##print ("Found {} records on layer 0 of the fs endpoint".format(len(features)))
##
### Load to a 'feature set'
### Keep in mind, this works because the 'token' is present in the HTTP GET URL.
### May not be supported if it needs to be a POST or the parameters end up in the body of the request
##fs = arcpy.FeatureSet()
##fs.load(q_response.url) Download part of script # Submit a job to export a service to FGDB (to user folder)
print ("Submitting an AGOL job to export Feature Service data to FGDB from Item ID {}...".format(item_to_export))
params = {}
params['itemId'] = item_to_export
params['title'] = export_title
params['exportFormat'] = 'File Geodatabase'
params['f']='json'
response = s.post(serviceURL+"/content/users/{}/export".format(username),data=params)
new_item_id = response.json().get('exportItemId')
job_id = response.json().get('jobId')
"""{u'exportFormat': u'fileGeodatabase',
u'exportItemId': u'2009ac16f2bc4dbgsdfg4f2a89f',
u'jobId': u'5927523c-4af6-4ada-bc00-d8sdgsdgsdfd0::KbxwQRRfWyEYLgp4',
u'ownerFolder': u'342aesdfgsdfgsdfgsd1b92beed',
u'serviceItemId': u'54250asfdgsdfgsdfgsddd82a363cf4',
u'size': 167141376,
u'type': u'file'}"""
print ("Job {} submitted. \nNew Item ID: {}".format(job_id,new_item_id))
# Check Status (loop until completed)
print ("Checking the job status every {} seconds...".format(check_job_status_interval_in_sec))
params = {}
params['jobId'] = job_id
params['jobType'] = 'export'
params['f'] = 'json'
status = "processing"
while status=="processing":
status_response = s.post(serviceURL+"/content/users/{}/items/{}/status".format(username,new_item_id),data=params)
#{u'itemId': u'2009ac16dfasdfasda89f',u'status': u'processing',u'statusMessage': u'Job Status for jobId: 5dfa23c-4af6-4ada-bc00-d8asdfasdfad0'}
status = status_response.json().get('status')
exported_item_id = status_response.json().get('itemId')
print (" -- Job Status: {}".format(status))
if status == "processing":
#print (" -- Checking status in {} seconds".format(check_job_status_interval_in_sec))
time.sleep(check_job_status_interval_in_sec)
print ("Final Export Status: {}".format(status))
# Download FGDB Export
print ("Downloading final exported FGDB...")
download_response = s.get(serviceURL+"/content/items/{}/data?f=json".format(exported_item_id))
# Save to local
dt = datetime.strftime(datetime.now(),"%Y%m%d_%H%M%S")
out_file = os.path.join(download_folder,"{}_{}.zip".format(export_title,dt))
print ("Saving final downloaded FGDB to {}...".format(out_file))
f = open(out_file,'wb')
f.write(download_response.content)
f.close()
# Remove the extracted FGDB from AGOL (cleanup)
print ("Removing the exported FGDB ({}) on AGOL (cleaning up)...".format(exported_item_id))
params = {}
params['f'] = "json"
params['items'] = exported_item_id
delete_response = s.post(serviceURL+r'/content/users/{}/deleteItems'.format(username),data=params)
print ("Delete result: {}".format(delete_response.content))
... View more
01-02-2020
07:27 AM
|
0
|
0
|
1102
|
POST
|
The trick here is to have your relationship class using the APN field and also leave the 123 globalid to parentglobalid one in there as well. It can come in handy if APN ever gets messed up. You can still inherit the APN into the repeat like you are doing here. Once you submit the relationship will work.
... View more
01-02-2020
07:07 AM
|
1
|
1
|
612
|
POST
|
You can rename them all using a calculated field from the form when exporting in a Python script. Not sure if that will help you but I have the code for it. What I do now is just export them to a directory with the Plot name. Then we have a URL or UNC path name in the feature class attributes instead. Keeping them all in the GDB or SDE got too big rather quickly. I guess you could export, rename and reimport but not much fun.
... View more
12-31-2019
01:03 PM
|
0
|
3
|
1738
|
POST
|
I do percent cover by Gap categories. Yes you will need to set up a bunch of ifs then sum. Start with the if to parse it out Cat1C if(${Gap}>=25 and ${Gap}<=50, ${Gap}, 0) Cat2C if(${Gap}>=51 and ${Gap}<=100, ${Gap}, 0) etc... Then sum if it is in a repeat (prob is) sumCanCat1 sum(${Cat1C}) The divide. ${sumCanCat1} div 25 Note my denominator was static at 25. But in another form I have to have a second calc to get the denominator. Do not count 0 values for the denominator nonzerowoodyhgt if(${HeightWoody}>0,1,0) Then use it (instead of just count(HeightWoody) as that would include the 0s). Average Woody Height sum(${HeightWoody}) div sum(${nonzerowoodyhgt}) Hope that helps.
... View more
12-31-2019
12:52 PM
|
2
|
1
|
251
|
POST
|
Do you have any commas in your lookup values or the return values? That will cause the splitting thing - which I think is happening.
... View more
12-30-2019
06:42 AM
|
0
|
0
|
363
|
POST
|
We do species also (for LPI). They wanted a "same as last" button like Access had. Of course cannot do that but we did something else that they like it. Make a Defaults page where they can config a "default" pin drop like this Then on the real pin drop have a Use Defaults Yes/No This will allow for auto populate Before After You can then use or not use a default for each drop. You can even change the defaults half way in and then use those. You can also use defaults then delete say lower1 really easy and it is still faster. Data team likes that they still have to specifically choose the default so that we know it was on purpose. Add a calc like this if(${UseDefaults}='Yes',${TopCanopyDefault},'') Our crews love it so far. Hope it helps.
... View more
12-27-2019
02:01 PM
|
4
|
1
|
998
|
POST
|
So assuming you did the relationship part there are 2 ways. (You should have already made a new Hosted service that has the master and the form with a relationship class between them, then repoint the form). Super easy way is just to map the forms with a symbol based on the Yes/No. Like a big checkmark vs say an X. If the relationship is 1:1 then you can often just use the relationships attributes that are built into the pop up. Just scroll to the bottom and you will see things like {relationships\0\objectid}. If it is 1:M then you can only get a count of the forms found. But this may be enough for you. (I also wonder if a 1:1 would even let you make 2) If you want only the ones that are marked as Yes in the form you can use Arcade. BUT I just remembered you can not change the symbol and use a related lookup yet. I think cause it is too slow. You can have it in the attribute table or in the popup however. So you could have the master popup say in large Red type or something "Already Flushed". Sorry forgot about the feature set not working there yet. The arcade just uses the key to go look it up. Here I have a popup with Red text. Then if an error is found I see text in Red otherwise it is just blank and see nothing. if ($feature.EvalStatus == "Eval") {
var sql = "PlotKey = '" + $feature.PlotKey + "'";
var tbl = Filter(FeatureSetByName($map,"Plot Char"), sql);
var tblCnt = count(tbl)
if (tblCnt < 1) {
return "\n----No Plot Char form found!"
}
else if (tblCnt > 1) {
return "\n----More than 1 Plot Char form found!"
}
else {
return ''
}
}
else {
return ''
} Hope that helps. See my other post below with links to more.
... View more
12-27-2019
12:14 PM
|
1
|
2
|
1188
|
POST
|
Turns out I was using the app GPS Test by Chartcross Limited (space) but you are using GPSTest by barbeauDev (nospace). I got GPSTest (nospace) going and my Pixel 4 is using L1 sand L5. But as you say it does not seem to actually improve anything. GPS Test stops getting lower at 3m and never better. GPSTest goes down to 3.8 and never any better. This could just be Android reporting a min of 3m ever. I read somewhere once it will never actually report better than 3m in the software (liability?). Both Collector and 123 are both reporting 12.4 feet - so right at the 3.8 m. Hope that helps? See this article for more info https://medium.com/@sjbarbeau/dual-frequency-gnss-on-android-devices-152b8826e1c Other quote "There is a bit/lot of confusion because chips report “theoretical” accuracy and that’s now under 1 meter with DF, however no one’s seen anything better than 3/5 meters I believe with actual testing. It’s not hard to see why, tiny GPS antennas, interference, etc…DF on smartphones is going to be mostly useful on smartphones to eliminate “bounced” signals in deep urban canyons." In my last job we did a lot of testing and in the end it had way more to do with the size of antenna then anything else. This is why a bad elf is no better for example. Once we added a antenna the size of a dinner plate it got way better.
... View more
12-26-2019
12:23 PM
|
2
|
0
|
3112
|
POST
|
Do you want the symbol to change on the related "master" feature class or the form feature class itself?
... View more
12-26-2019
12:10 PM
|
0
|
4
|
1188
|
POST
|
Thanks I am not seeing a CF anywhere. I do see two different symbols under the satellites. I will ask our device testers and see how they checked.
... View more
12-23-2019
11:49 AM
|
0
|
2
|
3112
|
POST
|
Dan I just got a Pixel 4 and have used GPS Test before. How do you tell it is using the 2 bands? Our org did a lot of testing trying to get the Note and S10 to work in dual band but with no luck. It has the chip but no firmware to support dual bands. Thanks
... View more
12-23-2019
11:13 AM
|
0
|
4
|
3112
|
POST
|
Why would you not want 123 to record the spatial point? We use this all the time to confirm they actually went to the correct spot each time. We also did culvert work and would have a user go out to repair and say a culvert is fine - turned out they were at the wrong spot which we could easily see. Great for QA when they mess up a visit also (they say they went to 35 but actually went to 44).
... View more
12-19-2019
09:10 AM
|
0
|
0
|
253
|
POST
|
We have a workflow to create new forms each time instead of editing. Have a Key in Collector that passes to 123. Then relate all the forms using that Key back to the original point. This way you have a change log, full editor tracking, etc.
... View more
12-19-2019
09:06 AM
|
0
|
4
|
680
|
POST
|
123 is always WGS84 I think since your tablet is WGS84. I have the same issue. What I do is just make a lat/long static field and calc it in. I do this because we want to know if anyone moves it. You may be able to change 123 to use a diff map but I think anytime you as what is my GPS it will always be 84. But I also have the code for Arcade to create them dynamically. That way if a point ever moves it auto changes the lat/long. var originShift = 2.0 * PI * 6378137.0 / 2.0;
var lon = (Geometry($feature).x / originShift) * 180.0;
var lat = (Geometry($feature).y / originShift) * 180.0;
lat = 180.0 / PI * (2.0 * Atan( Exp( lat * PI / 180.0)) - PI / 2.0);
return lon + " " + lat;
... View more
12-19-2019
08:52 AM
|
2
|
2
|
968
|
Title | Kudos | Posted |
---|---|---|
1 | 08-07-2023 10:40 AM | |
1 | yesterday | |
1 | yesterday | |
1 | 01-10-2024 09:32 AM | |
2 | yesterday |
Online Status |
Online
|
Date Last Visited |
2 hours ago
|