Esempio n. 1
0
def ReconnectToArchicad():
    global conn
    global acc
    global act
    global acu
    conn = ACConnection.connect()
    if conn:
        acc = conn.commands
        act = conn.types
        acu = conn.utilities
Esempio n. 2
0
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
Esempio n. 3
0
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)
Esempio n. 5
0
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
Esempio n. 6
0
    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)
Esempio n. 7
0
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