Subversion Repositories HomeAutomation

Rev

Rev 1991 | Rev 1994 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

#!/usr/bin/python

# Written by Mattias Runge 2008-05-13

import os
import sys
import getopt

moddir = sys.path[0] + "/../../EmbeddedSoftware/AVR/module"
localmoddir = os.getcwd() + "/modules"

def getModules():
    modules = []
    for fileName in os.listdir(moddir):
        if fileName[0] != '.' and fileName != "template":
            modules.append(fileName)

    return modules


def getLocalModules():
    modules = []
    for fileName in os.listdir(localmoddir):
        if fileName[0] != '.':
            modules.append(fileName)

    return modules


def parseModuleIdFromFile(moduleName, fileName):
    config_inc = open(fileName, 'r') 
    config_inc_lines = config_inc.readlines()
    config_inc.close()
    takenIds = []
    for line in config_inc_lines:
        line = line.strip("\n").strip(" ")
        
        if line.find(moduleName + "_ID") != -1:
            parts = line.split("=")
            if parts[1].strip(" ") != -1 and parts[1].strip(" ") != "<ID>":
                takenIds.append(int(parts[1].strip(" "), 16))
                print "hittade: "+parts[1].strip(" ")+" in file: "+fileName
    return takenIds


def getModuleIdsFromFile(moduleName):
    takenIds = []
    for applicationName in os.listdir("../"):   
        if applicationName[0] != '.' and os.path.exists("../" + applicationName + "/config.inc"):
            takenIds = parseModuleIdFromFile(moduleName, "../" + applicationName + "/config.inc")

    return takenIds
    

def getFreeModuleId(takenIds):
    if len(takenIds) == 0:
        return 1
    takenIds.sort()

    lastId = 0

    for takenId in takenIds:
        if takenId != lastId+1:
            return lastId+1
        lastId = takenId

    return lastId+1



def compileMainFile():
    print "Compiling new main.c..."
    main_c_template = open('src/main.c.template', 'r') 
    main_c_template_lines = main_c_template.readlines()
    main_c_template.close()
    
    modules = getLocalModules()
    
    main_c = open('src/main.c', 'w') 
    
    for main_c_template_line in main_c_template_lines:
        pos_include = main_c_template_line.find('%INCLUDE')
        pos_init = main_c_template_line.find('%INIT')
        pos_process = main_c_template_line.find('%PROCESS')
        pos_list = main_c_template_line.find('%LIST')
        pos_handlemsg = main_c_template_line.find('%HANDLEMSG')
        
        if pos_include != -1:
            for moduleName in modules:
                main_c.write(main_c_template_line[:pos_include] + "#include \"../modules/" + moduleName + "/" + moduleName + ".h\"\n")
        elif pos_init != -1:
            for moduleName in modules:
                main_c.write(main_c_template_line[:pos_init] + moduleName + "_Init();\n")
        elif pos_process != -1:
            for moduleName in modules:
                main_c.write(main_c_template_line[:pos_process] + moduleName + "_Process();\n")
        elif pos_list != -1:
            count = 1
            for moduleName in modules:
                main_c.write(main_c_template_line[:pos_list] + moduleName + "_List(" + str(count) + ");\n")
                count += 1
        elif pos_handlemsg != -1:
            for moduleName in modules:
                main_c.write(main_c_template_line[:pos_handlemsg] + moduleName + "_HandleMessage(&rxMsg);\n")
        else:
            main_c.write(main_c_template_line)

    main_c.close()
    
    print "Creation of main.c complete"

def readConfigSection(fileName, sectionName):
    fileInstance = open(fileName, 'r')
    lines = fileInstance.readlines()
    fileInstance.close()
    
    sectionLines = []
    
    inSection = False
    
    for line in lines:
        if not inSection:
            if line.find("## Section " + sectionName + " --") != -1:
                inSection = True
                sectionLines.append(line.strip("\n"))
        else:
            if line.find("## End section " + sectionName + " --") != -1:
                inSection = False
                
            sectionLines.append(line.strip("\n"))
            
    return sectionLines
    

def updateConfigFile():
    print "Updating config.inc..."
    modules = getLocalModules()
    moduleSections = {}
    applicationSection = []
    moduleName="none"
    if not os.path.exists("config.inc"):
        applicationSection = readConfigSection("src/config.inc.template", "application")
        
        for moduleName in modules:
            moduleSections[moduleName] = readConfigSection(localmoddir + "/" + moduleName + "/config.inc.template", moduleName)
    else:
        applicationSection = readConfigSection("config.inc", "application")
        
        for moduleName in modules:
            moduleSections[moduleName] = readConfigSection("config.inc", moduleName)
            
            if len(moduleSections[moduleName]) <= 1:
                moduleSections[moduleName] = readConfigSection(localmoddir + "/" + moduleName + "/config.inc.template", moduleName)
    
    timers = 0
    pcints = 0
    
    moduleIds = getModuleIdsFromFile(moduleName)
    
    for moduleName, moduleSection in moduleSections.iteritems():
        c = 0
        for line in moduleSection:
            if len(line) > 0:
                if line[0] != '#':
                    if line.find("<ID>") != -1:
                        new_ID = getFreeModuleId(moduleIds)
                        print "id = "+hex(new_ID)
                        moduleIds.append(new_ID)
                        line = line.replace("<ID>", hex(new_ID))
                    elif line.find("<TIMER>") != -1:
                        line = line[:line.find("=")+1] + hex(timers) + " /* <TIMER> -- DO NOT REMOVE THIS COMMENT -- */"
                        timers += 1
                    elif line.find("<PCINT>") != -1:
                        line = line[:line.find("=")+1] + hex(pcints) + " /* <PCINT> -- DO NOT REMOVE THIS COMMENT -- */"
                        pcints += 1
    
            moduleSection[c] = line;
            c += 1
    
    c = 0
    for line in applicationSection:
        if len(line) > 0:
            if line[0] != '#':
                if line.find("<TIMER>") != -1:
                    line = line[:line.find("=")+1] + hex(timers) + " /* <TIMER> -- DO NOT REMOVE THIS COMMENT -- */"
                    timers += 1
                elif line.find("TIMER_NUM_TIMERS=") != -1:
                    line = "TIMER_NUM_TIMERS=" + hex(timers)
                elif line.find("NUMBER_OF_MODULES=") != -1:
                    line = "NUMBER_OF_MODULES=" + hex(len(modules))
                elif line.find("<PCINT>") != -1:
                    line = line[:line.find("=")+1] + hex(pcints) + " /* <PCINT> -- DO NOT REMOVE THIS COMMENT -- */"
                    pcints += 1
                elif line.find("PCINT_NUM_PCINTS=") != -1:
                    line = "PCINT_NUM_PCINTS=" + hex(pcints)
        applicationSection[c] = line;
        c += 1
        
    config_inc = open('config.inc', 'w')
    
    for line in applicationSection:
        config_inc.write(line + "\n")
        
    for moduleName, moduleSection in moduleSections.iteritems():
        for line in moduleSection:
            config_inc.write(line + "\n")
        
    config_inc.close()
    
    print "Update of config.inc complete"


def compileSourcesFile():
    print "Compiling sources.inc..."
    
    uniqueSet = []
    uniqueSet2 = []
    if os.path.isfile("src/libraries.list.template"):
        libraries_list_template = open('src/libraries.list.template', 'r')
        libraries_list_template_lines = libraries_list_template.readlines()
        libraries_list_template.close()
    
    sources_list_template = open('src/sources.list.template', 'r')
    sources_list_template_lines = sources_list_template.readlines()
    sources_list_template.close()
    if os.path.isfile("src/libraries.list.template"):
        for libraries_list_template_line in libraries_list_template_lines:
            line =libraries_list_template_line.strip("\n").strip(" ")
            if len(line) > 0:
                if line[0] != '#':
                    uniqueSet2.append(line)
    
    for sources_list_template_line in sources_list_template_lines:
        line = sources_list_template_line.strip("\n").strip(" ")
        if len(line) > 0:
            if line[0] != '#':
                uniqueSet.append(line)
        
    modules = getLocalModules()
    
    for moduleName in modules:
        sources_list = open(localmoddir + "/" + moduleName + "/sources.list", 'r')
        sources_list_lines = sources_list.readlines()
        sources_list.close()
    
        if os.path.isfile(localmoddir + "/" + moduleName + "/libraries.list"):
            libraries_list = open(localmoddir + "/" + moduleName + "/libraries.list", 'r')
            libraries_list_lines = libraries_list.readlines()
            libraries_list.close()
        
            for libraries_list_line in libraries_list_lines:
                line = libraries_list_line.strip("\n").strip(" ")
                if len(line) > 0:
                    if line[0] != '#':
                        uniqueSet2.append("../../../module/" + moduleName + line)
        for sources_list_line in sources_list_lines:
            line = sources_list_line.strip("\n").strip(" ")
            if len(line) > 0:
                if line[0] != '#':
                    uniqueSet.append(line)
            
    
    sourcesString = "SOURCES = "
    
    #FIXME: Make uniqueSet actually unique
    
    for line in uniqueSet:
        sourcesString += line + " "
    sourcesString += "\n"
    sourcesString += "LDLIBS = "
    for line in uniqueSet2:
        sourcesString += line + " "
    sources_inc = open('sources.inc', 'w')
    sources_inc.write(sourcesString.strip(" ") + "\n")
    sources_inc.close()
    
    print "Creation of sources.inc complete"

def regenerateModules():
    print "Regenerating modules..."
    print ""
    compileSourcesFile()
    print ""
    compileMainFile()
    print ""
    updateConfigFile()
    print ""
    print "Regenerating modules complete"
    print ""


def addModule(moduleName):
    print "Trying to add module " + moduleName
    
    try:
        # the following creates symlinks to <path to modulemanager>/../../EmbeddedSoftware/AVR/module
        # and <path to modulemanager> is an absolute path which makes the symlink similar to this:
        # act_dimmer230 -> /home/arune/Documents/HomeAutomation/PcSoftware/scripts/../../EmbeddedSoftware/AVR/module/act_dimmer230
        #os.symlink(moddir + "/" + moduleName, localmoddir + "/" + moduleName)
        # instead symlink to relative path instead
        os.symlink("../../../module/" + moduleName, localmoddir + "/" + moduleName)
        print "Added module successfully"
    except OSError, (errno, strerror):
        if errno == 17:
            print "A link, file or directory named " + moduleName + " is already present in the modules directory, not linking"
        else:
            raise
    
    print ""
    
    regenerateModules()


def delModule(moduleName):
    print "Trying to remove module " + moduleName
    
    try:
        os.unlink(localmoddir + "/" + moduleName)
        print "Removed module successfully"
    except OSError, (errno, strerror):
        if errno == 2:
            print "No such " + moduleName + " present in the modules directory, not unlinking"
        else:
            raise
    
    print ""
    
    regenerateModules()

def createFile(moduleName, templateFileName, moduleFileName):
    print "Creating " + moduleName + "/" + templateFileName + "..."
    template_file = open(moddir + "/template/" + templateFileName, 'r')
    lines = template_file.readlines()
    template_file.close()

    module_file = open(moddir + "/" + moduleName + "/" + moduleFileName, 'w')
    
    for line in lines:
        line = line.replace("<template>", moduleName)
        line = line.replace("<TEMPLATE>", moduleName.upper())

        module_file.write(line)

    module_file.close()
    
def newModule(moduleName):
    print "Creating " + moddir + "/" + moduleName + " directory..."
    os.mkdir(moddir + "/" + moduleName + "/")

    createFile(moduleName, "config.inc.template", "config.inc.template")
    createFile(moduleName, "sources.list", "sources.list")
    createFile(moduleName, "template.h", moduleName + ".h")
    createFile(moduleName, "template.c", moduleName + ".c")
    createFile(moduleName, "template_eeprom.h", moduleName + "_eeprom.h")

def usage():
    print "Syntax: ./ModuleManager [options]"
    print "Options:"
    print "  --help               Print this help"
    print "  --regenerate         Regenarate modules and files"
    print "  --list               List avalible and installed modules"
    print "  --add=<module name>  Adds a module to the application"
    print "  --del=<module name>  Removes a module from the application"
    print "  --new=<module name>  Creates a new module from the module template"
    print ""


def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hlrc", ["help", "list", "regenerate", "add=", "del=", "new="])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        usage()
        sys.exit(2)
    
    if len(sys.argv) == 1:
        usage()
        sys.exit()
    
    for o, a in opts:
        if o in ("-c"):
            modules = getModules()
            
            for module in modules:
                print module

        elif o in ("-l", "--list"):
            modules = getModules()
            
            print "Available modules"
            print "================="
            for module in modules:
                print module
            

            if os.path.exists(localmoddir):
                print ""
            
                modules = getLocalModules()
            
                print "Modules used in this application"
                print "================================"
                for module in modules:
                    print module
            
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
            
        elif o in ("-r", "--regenerate"):
            regenerateModules()
            
        elif o in ("--add"):
            if len(a) == 0:
                print "No modulename specified"
                usage()
                sys.exit()
            
            if a not in getModules():
                print a + " is not a recognized module name"
                sys.exit()
                
            addModule(a)
            
        elif o in ("--del"):
            if len(a) == 0:
                print "No modulename specified"
                usage()
                sys.exit()
            
            if a not in getModules():
                print a + " is not a recognized module name"
                sys.exit()
                
            delModule(a)
            
        elif o in ("--new"):
            if len(a) == 0:
                print "No modulename specified"
                usage()
                sys.exit()
            
            if a in getModules():
                print a + " already exists"
                sys.exit()
                
            newModule(a)
            
        else:
            assert False, "unhandled option"


if __name__ == "__main__":
    main()