def ReconnectToArchicad(): global conn global acc global act global acu conn = ACConnection.connect() if conn: acc = conn.commands act = conn.types acu = conn.utilities
def main(iArchiCADPort): aElementIdItems = [] aElementIdItemsDict = [] # Set internal connection with ArchiCAD conn = ACConnection.connect(int(iArchiCADPort)) assert conn acc = conn.commands # Get all elements ID aElementIdItems = acc.GetAllElements() # Convert to dictionaries for ElementId in aElementIdItems: objProps = ElementId.to_dict() aElementIdItemsDict.append(objProps) print(aElementIdItemsDict) return aElementIdItemsDict
import json, platform, subprocess from archicad import ACConnection from tkinter import messagebox ################################ CONFIGURATION ################################# errorMessageTitleArchicadNotFound = 'Could not find Archicad!' errorMessageDetailsArchicadNotFound = 'A running Archicad instance is required to initialize the schedule.' errorMessageTitleAdditionalCommandsNotFound = 'Could not find the required additional JSON commands!' errorMessageDetailsAdditionalCommandsNotFound = 'The latest version of AdditionalJSONCommands Add-On is required.\nDownload it from github:\nhttps://github.com/tlorantfy/archicad-additional-json-commands/releases' errorMessageTitleCommandExecutionFailed = 'Failed to execute Archicad command!' ################################################################################ conn = ACConnection.connect() if not conn: messagebox.showerror(errorMessageTitleArchicadNotFound, errorMessageDetailsArchicadNotFound) exit() acc = conn.commands act = conn.types acu = conn.utilities def IsUsingMacOS(): return platform.system() == 'Darwin' def IsUsingWindows(): return platform.system() == 'Windows'
def main(): # Try read configuration file try: objConfig = Config(os.path.dirname(os.path.abspath(__file__)) + '\\'+ 'config.json') except: print("Can't configure program") # Rewrite with thread wrapper 'cause subprocess.popen call might be not thread-safe # Try open ArchiCAD and wait until it's full start try: # Open session data file with open(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '\\'+ 'session.json', "r") as json_file: objSessionConfig = json.load(json_file) #ACInstance = Utilities.OpenFile(objConfig.sResourceFilePath) # Open AC with file # Another way to open file and get PID ACInstance = subprocess.Popen([objConfig.sProcessPath, objConfig.sResourceFilePath], stderr=subprocess.STDOUT, stdout=subprocess.PIPE) # Write session ArchiCAD PID to config objSessionConfig["iACPID"] = ACInstance.pid # Get additional process info ACProcess = psutil.Process(objSessionConfig["iACPID"]) # Write AC process start datetime objSessionConfig["tACstartDatetime"] = datetime.datetime.fromtimestamp(ACProcess._create_time).strftime("%Y-%m-%d %H:%M:%S") time.sleep(objConfig.iWaitTimeForFileOpen) # Need to find corresponding event except: print("Can't start ArchiCAD and open %s" % objConfig.sResourceFilePath) try: # Get ArchiCAD API ports range rACPortRange = ACConnection._port_range() # Get process connections ACProcessConnections = ACProcess.connections() for iACConnElem in ACProcessConnections: if iACConnElem.laddr.port in rACPortRange: # Check port in range. Have to be rewritten depending on connection type iArchiCADPort = iACConnElem.laddr.port # Write session ArchiCAD port to config objSessionConfig["iACProcessPort"] = iArchiCADPort # Write session data to file for other python-subprocesses with open(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '\\'+ 'session.json', "w") as json_file: json.dump(objSessionConfig, json_file) # Start internal connection with ArchiCAD try: conn = ACConnection.connect(objSessionConfig["iACProcessPort"]) assert conn acc = conn.commands except: print('Can not establish connection') # Check internal connection and run futher if ok bIsAlive = acc.IsAlive() if bIsAlive: try: # Call external python script. You can change to your script by editing sExecutableScriptPath in config.json # objComplited = subprocess.run(["python",objConfig.sExecutableScriptPath,str(objSessionConfig["iACProcessPort"])], capture_output=True, text=True) objComplited = subprocess.check_call(["python",objConfig.sExecutableScriptPath]) # Get result from external python script run # sResult = objComplited.stdout[objComplited.stdout.find("["):-1].replace("\'","\"") # Write result to JSON # WriteToJSON(objConfig.sResultFilePath, sResult) # Kill ArchiCAD process in any way. Can't find appropriate func in AC python library ACProcess.terminate() except: print('Can not external python script') else: pass except: print('Can not establish internal connection to %s' % objConfig.sProcessName)
def main(iACProcessPort): # Define locals aElements = [] aPropertyAllItems = [] aPropertyGUID = [] aElementsPropertyData = [] aClassificationSystemItems = [] objClassificationSystemID = [] aACElementsDB = [] aPropertyLocalListID = [] # Try read configuration file try: objConfig = Config( os.path.dirname(os.path.abspath(__file__)) + '\\' + 'config.json') except: print("Can't configure program") # Set internal connection with ArchiCAD try: conn = ACConnection.connect(iACProcessPort) assert conn acc = conn.commands except: print("Can't connect to ArchiCAD") # Get Classification system data try: # Get all Classification systems aClassificationSystems = acc.GetAllClassificationSystems() # Get specific classification system mentioned in config.json objClassificationSystem = next( c for c in aClassificationSystems if c.name == objConfig.sACClassificationName and c.version == objConfig.sACClassificationVersion) # Get all Classification system items in tree tClassificationSystemItems = acc.GetAllClassificationsInSystem( objClassificationSystem.classificationSystemId) except: print("Can't get ArchiCAD Classification system data") # Flatten Classification system items for simplier usage try: for aClassificationSystemItem in tClassificationSystemItems: # First level for root Classification items aClassificationSystemItems.append( ClassificationItem( aClassificationSystemItem.classificationItem. classificationItemId.guid, aClassificationSystemItem.classificationItem.id, aClassificationSystemItem.classificationItem.name, aClassificationSystemItem.classificationItem.description)) # Call recursive function for inner levels of items GetClassificationSystemItem( aClassificationSystemItem.classificationItem, aClassificationSystemItems) except: print("Can't flatten Classification system items") # Get all elements try: aElements = acc.GetAllElements() except: print("Can't get ArchiCAD elements") # Get properties data try: # Get all ArchiCAD properties names aPropertyAllItems = acc.GetAllPropertyNames() # Filter properties list to BuiltIn & properties defined in config.json # Just need to get Element ID & Element type aPropertyItems = list( filter( lambda p: p.type == 'BuiltIn' and p.nonLocalizedName in objConfig.aACPropertyName, aPropertyAllItems)) # Iterate through filtered properties for pPropertyName in objConfig.aACPropertyName: aPropertyItem = [ p for p in aPropertyItems if p.nonLocalizedName == pPropertyName ] aPropertyLocalListID.append(aPropertyItems.index(aPropertyItem[0])) # Get filtered properties GUIDs aPropertyGUID = acc.GetPropertyIds(aPropertyItems) except: print("Can't get ArchiCAD properties") # Get elements properties data try: aElementsPropertyData = acc.GetPropertyValuesOfElements( aElements, aPropertyGUID) except: print("Can't get ArchiCAD elements properties data") # Get elements classification try: # Make temporal list of Classification system IDs objClassificationSystemID.append( objClassificationSystem.classificationSystemId) # Get elements classification data aElementsnClassificationItem = acc.GetClassificationsOfElements( aElements, objClassificationSystemID) except: print("Can't get elements Classification data") # Set elements data - guid, id, type, classificationName, classificationGUID, classificationSystemGUID for insertion in DB try: for iElementId, iElementProperty, iElementClassification in zip( aElements, aElementsPropertyData, aElementsnClassificationItem): if iElementClassification.classificationIds[ 0].classificationId.classificationItemId is not None: # Get Classification item based on element classification iClassSystemItemTemp = next( (f for f in aClassificationSystemItems if f.guid == iElementClassification.classificationIds[0]. classificationId.classificationItemId.guid), None) # Check classification item if iClassSystemItemTemp is not None: iClassSystemItemTempID = iClassSystemItemTemp.id iClassSystemItemTempGUID = iClassSystemItemTemp.guid else: iClassSystemItemTempID = 'Unclassified' iClassSystemItemTempGUID = '00000000-0000-0000-0000-000000000000' else: iClassSystemItemTempID = 'Unclassified' iClassSystemItemTempGUID = '00000000-0000-0000-0000-000000000000' # Insert data in temp list aACElementsDB.append( (iElementId.elementId.guid, iElementProperty.propertyValues[ aPropertyLocalListID[0]].propertyValue.value, iElementProperty.propertyValues[ aPropertyLocalListID[1]].propertyValue.value, iClassSystemItemTempGUID, iClassSystemItemTempID, iElementClassification.classificationIds[0].classificationId. classificationSystemId.guid)) except: print("Can't set elements data for futher DB insertion") # Provide postgreSQL connection try: objPGConfig = Config( os.path.dirname(os.path.abspath(__file__)) + '\\' + '__NOTSYNC_postgresqlConfig.json') pgConn = psycopg2.connect(database=objPGConfig.database, user=objPGConfig.user, password=objPGConfig.password, host=objPGConfig.host) pgCur = pgConn.cursor() psycopg2.extras.register_uuid() except: print("Can't connect to DB") # Prepare table for insertion try: pgCur.execute("truncate table ac_classification_check") pgConn.commit() except: print("Can't truncate DB") # Insert data in DB try: pgQuery = """INSERT INTO ac_classification_check ("elemGUID", "elemID", "elemType", "classGUID", "classType", "classSysGUID") VALUES (%s, %s, %s, %s, %s, %s);""" psycopg2.extras.execute_batch(pgCur, pgQuery, aACElementsDB, page_size=10000) pgConn.commit() except: print("Can't insert data in DB") # Close connection pgCur.close() pgConn.close() return aACElementsDB
except: print("Can't insert data in DB") # Close connection pgCur.close() pgConn.close() return aACElementsDB # Set up entry point if __name__ == '__main__': # Init AC port # Try read configuration file try: objSessionConfig = Config( os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '\\' + 'session.json') except: print("Can't configure program") # Check ArchiCAD port # Get ArchiCAD API ports range rACPortRange = ACConnection._port_range() try: if objSessionConfig.iACProcessPort in rACPortRange: main(objSessionConfig.iACProcessPort) else: # If args is empty set port with error value raise Exception("Invalid ArchiCAD port") except Exception as inst: print(inst.args)
def main(iACProcessPort): # Define locals aACElementsDB = [] aElementClassification = [] aClassificationSystemItems = [] # Try read configuration file try: objConfig = Config( os.path.dirname(os.path.abspath(__file__)) + '\\' + 'config.json') except: print("Can't configure program") # Read classification mapping file try: objClassConfig = Config( os.path.dirname(os.path.abspath(__file__)) + '\\' + 'AC-AUT-ClassificationMapping.json') except: print("Can't read classification mapping file") # Read classification fix file try: firstline = True with open( os.path.dirname(os.path.abspath(__file__)) + '\\' + objConfig.aACClassificationFixFileName, 'r') as f: csvReader = csv.reader(f) for row in csvReader: if firstline: firstline = False continue aACElementsDB.append( Element(row[0], row[1], row[2], row[3], row[5], row[6])) except: print("Can't read classification fix file") # Set internal connection with ArchiCAD try: conn = ACConnection.connect(iACProcessPort) assert conn acc = conn.commands act = conn.types except: print("Can't connect to ArchiCAD") # Get Classification system data try: # Get all Classification systems aClassificationSystems = acc.GetAllClassificationSystems() # Get specific classification system mentioned in config.json objClassificationSystem = next( c for c in aClassificationSystems if c.name == objConfig.sACClassificationName) # Get all Classification system items in tree tClassificationSystemItems = acc.GetAllClassificationsInSystem( objClassificationSystem.classificationSystemId) except: print("Can't get ArchiCAD Classification system data") # Flatten Classification system items for simplier usage try: for aClassificationSystemItem in tClassificationSystemItems: # First level for root Classification items aClassificationSystemItems.append( ClassificationItem( aClassificationSystemItem.classificationItem. classificationItemId.guid, aClassificationSystemItem.classificationItem.id, aClassificationSystemItem.classificationItem.name, aClassificationSystemItem.classificationItem.description)) # Call recursive function for inner levels of items GetClassificationSystemItem( aClassificationSystemItem.classificationItem, aClassificationSystemItems) except: print("Can't flatten Classification system items") # Prepare data for classification fixture try: for iACElement in aACElementsDB: sClassMappingName = next( c for c in objClassConfig.ElemClassMapping if c.element == iACElement.type).ACclassificationType[0] sClassACGUID = next(c for c in aClassificationSystemItems if c.id == sClassMappingName).guid aElementClassification.append( act.ElementClassification( act.ElementId(iACElement.guid), act.ClassificationId( act.ClassificationSystemId(iACElement.classSysGUID), act.ClassificationItemId(sClassACGUID)))) except: print("Can't prepare data for classification fixture") # Try fix elements classification try: acc.SetClassificationsOfElements(aElementClassification) except: print("Can't fix elements classification") return aACElementsDB