Example #1
0
 def setUp(self):
     self.name = self.id()[len(self.__module__) + 1:]
     logFile = 'test_files/{0}.log'.format(self.name)
     if os.path.exists(logFile):
         os.remove(logFile)
     logger.initLogger((logFile, logging.DEBUG), logging.INFO)
     logger.reportInfo('*******Start {0}*************'.format(self.name))
     self.currentAssertions = []
     self.pyknxScriptsDirectory = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', '..'))
     self.pyknxModulesDirectory = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
Example #2
0
 def setUp(self):
     self.name = self.id()[len(self.__module__) + 1:]
     logFile = 'test_files/{0}.log'.format(self.name)
     if os.path.exists(logFile):
         os.remove(logFile)
     logger.initLogger((logFile, logging.DEBUG), logging.INFO)
     logger.reportInfo('*******Start {0}*************'.format(self.name))
     self.currentAssertions = []
     self.pyknxScriptsDirectory = os.path.normpath(
         os.path.join(os.path.dirname(__file__), '..', '..'))
     self.pyknxModulesDirectory = os.path.normpath(
         os.path.join(os.path.dirname(__file__), '..'))
Example #3
0
    def run(linknxAddress, userFile, communicatorAddress, userScriptArgs=None, verbosityLevel=logging.INFO, logFile=None, daemonizes=False, pidFile=None):
        def signal_handler(signal, frame):
            logger.reportInfo('Terminating...')
            communicator.stopListening()

        # Init logger.
        if not logFile is None:
            logger.initLogger((logFile, verbosityLevel), None)
        else:
            logger.initLogger(None, verbosityLevel)

        if isinstance(linknxAddress, tuple):
            linknxAddr = (linknxAddress[0], int(linknxAddress[1]))
        elif isinstance(linknxAddress, str):
            tokens = linknxAddress.split(':')
            linknxAddr = (tokens[0], int(tokens[1]))
        else:
                raise Exception('Unrecognized linknx address format.')
        linknx = Linknx(linknxAddr[0], int(linknxAddr[1]))

        # Fork if requested.
        if daemonizes:
            pid = os.fork()
        else:
            pid = os.getpid()

        if pid != 0 and pidFile != None:
            with open(pidFile, 'w') as f:
                f.write(str(pid))

        # If we are in the parent process (when forking), there is nothing left
        # to do. The communicator should run in the child process.
        if pid != 0 and daemonizes:
            return

        # Start communicator.
        communicator = Communicator(linknx, userFile, communicatorAddress, userScriptArgs=userScriptArgs)
        communicator.startListening()

        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)

        # Main loop.
        while communicator.isListening:
            time.sleep(1)

        # Clean pid file.
        if pidFile != None and os.path.exists(pidFile):
            os.remove(pidFile)
Example #4
0
        raise Exception('Malformed value for ' + option +'. Expecting a tuple (hostname:port)')
    return (addrStr[0:ix], int(addrStr[ix + 1:]))

def makeArgumentParser(description):
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('-c', '--comm-addr', dest='communicatorAddress', help='Address of the communicator. This argument must specify the hostname or the ip address followed by a colon and the port to listen on. Default is "localhost:1029"', default='localhost:1029')
    parser.add_argument('-l', '--linknx-addr', dest='linknxAddress', help='Address of the linknx server to bind to. This argument must specify the hostname or the ip address followed by a colon and the port. Default is "localhost:1028"', default='localhost:1028')
    parser.add_argument('userFile', help='use FILE as the user python script that implements callbacks functions declared in the linknx configuration (see the pyknxcallback attributes in XML).', metavar='FILE')
    parser.add_argument('--log-file', dest='logFile', help='write communicator\'s output to FILE rather than to standard output.', metavar='FILE', default=None)
    parser.add_argument('-d', '--daemonize', help='ask daemon to detach and run as a background daemon.', action='store_true', default=False)
    parser.add_argument('--pid-file', dest='pidFile', help='writes the PID of the daemon process to PIDFILE.', metavar='PIDFILE')
    parser.add_argument('-v', '--verbose', dest='verbosityLevel', help='set verbosity level. Default is "error".', metavar='LEVEL', choices=[l.lower() for l in logger.getLevelsToString()], default='error')
    return parser

if __name__ == '__main__':
    parser = makeArgumentParser(__doc__)
    args = parser.parse_args()

    # Configure logger.
    logger.initLogger(None, args.verbosityLevel.upper())

    args.communicatorAddress = parseAddress(args.communicatorAddress, 'communicator address')

    try:
        Communicator.run(args.linknxAddress, args.userFile, args.communicatorAddress, logFile=args.logFile, verbosityLevel=args.verbosityLevel, daemonizes=args.daemonize, pidFile=args.pidFile)
    except SystemExit:
        # This is a normal exit.
        pass
    except:
        logger.reportException()
Example #5
0
import argparse
import sys
import logging
import os
from pyknx import logger

__doc__ = __doc__.format(scriptname=os.path.basename(__file__))

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('linknxConfig', help='use LKNCONF as the source linknx configuration.', metavar='LKNCONF')
    parser.add_argument('-i', '--input-file', dest='homewatcherConfig', help='read homewatcher configuration from HWCONF rather than from standard input.', metavar='HWCONF')
    parser.add_argument('-o', '--output-file', dest='outputFile', help='write the modified linknx configuration to FILE rather than to standard output.', metavar='FILE')
    parser.add_argument('-v', '--verbose', dest='verbosityLevel', help='set verbosity level.', metavar='LEVEL', choices=[l.lower() for l in logger.getLevelsToString()], default='error')
    args = parser.parse_args()

    # Configure logger.
    logger.initLogger(None, args.verbosityLevel.upper())

    # Start configurator.
    configurator = Configurator(args.homewatcherConfig, args.linknxConfig, args.outputFile)

    # Generate config.
    try:
        configurator.cleanConfig()
        configurator.generateConfig()
        configurator.writeConfig()
    except:
        logger.reportException()
        sys.exit(2)
Example #6
0
#
# For any question, feature requests or bug reports, feel free to contact me at:
# knx at aminate dot net

import os
import glob
import importlib
from pyknx import logger
import homewatcher.plugin
import logging
"""
Homewatcher subpackage that contains the dynamically loaded plugins.
"""

_plugins = []
logger.initLogger(stdoutLogLevel=logging.ERROR)


def loadPlugins():
    global _plugins
    pluginDirectory = os.path.dirname(__file__)

    pluginModules = glob.glob(os.path.join(pluginDirectory, '*.py'))

    # Scan all modules in the 'plugins' subdirectory and instanciate all classes
    # that inherit Plugin.
    for moduleFile in pluginModules:
        if os.path.basename(moduleFile) == '__init__.py': continue
        module = importlib.import_module('homewatcher.plugins.{0}'.format(
            os.path.splitext(os.path.basename(moduleFile))[0]))
        for symbolName in dir(module):
Example #7
0
import sys
import getopt
import logging
from pyknx import logger, tcpsocket

def printUsage():
    print(__doc__)

def parseAddress(addrStr, option):
    ix = addrStr.find(':')
    if ix < 0:
        raise Exception('Malformed value for ' + option +'. Expecting a tuple (hostname:port)')
    return (addrStr[0:ix], int(addrStr[ix + 1:]))

if __name__ == '__main__':
    logger.initLogger(None, logging.INFO, usesDetailedLogging=False)
    try:
        options, remainder = getopt.getopt(sys.argv[1:], 'c:a:v:', ['comm-addr=', 'argument=', 'verbose=', 'help'])
    except getopt.GetoptError as err:
        logger.reportException()
        sys.exit(2)

    # Parse command line arguments.
    communicatorAddress = ('127.0.0.1',1029)
    arguments = []
    verbosity = logging.INFO
    for option, value in options:
        if option == '-c' or option == '--comm-addr':
            communicatorAddress = parseAddress(value, option)
        elif option == '-a' or option == '--argument':
            arguments.append(value)
Example #8
0
def handleRequest(requestType, doc):
    logger.initLogger(None, logging.INFO, usesDetailedLogging=False)

    parser = argparse.ArgumentParser(description=doc)
    parser.add_argument(
        '-s',
        '--server',
        dest='host',
        help=
        'Hostname of the machine running the linknx daemon. Default is localhost.',
        default='localhost')
    parser.add_argument('-p',
                        '--port',
                        dest='port',
                        help='Port linknx listens on. Default is 1028.',
                        default=1028)
    if requestType == 'read':
        parser.add_argument(
            'objectIds',
            help='ID represents the identifier of the object to read.',
            metavar='ID',
            nargs='+')
        parser.add_argument(
            '-R',
            '--regex',
            action='store_true',
            help=
            'ID in the "object" argument is interpreted as a regex and used to find objects to read. The pattern must comply with the \'re\' python module.'
        )
        parser.add_argument(
            '--value-only',
            action='store_true',
            help=
            'Output the value of the queried object but do not prefix it with the object\'s id.'
        )
        parser.add_argument(
            '--expected-value',
            help=
            'Expected value of the object. This script will exit with a non-zero return code if the value is not the expected one. This is useful when using this script in a "if" test of a shell script.'
        )
    elif requestType == 'write':
        parser.add_argument(
            'object',
            help='ID represents the identifier of the object to write to.',
            metavar='ID')
        parser.add_argument(
            'value',
            help='Assigns VALUE to the object identified by ID.',
            metavar='VALUE')
    elif requestType == 'execute':
        parser.add_argument(
            '--action',
            help=
            'use the ACTION string as the XML representation of the action to execute rather than reading it from standard input.',
            metavar='ACTION')
    else:
        raise Exception('Unsupported request type "{0}".'.format(requestType))
    parser.add_argument(
        '-v',
        '--verbose',
        dest='verbosityLevel',
        help='Set verbosity level. Default is "error".',
        metavar='LEVEL',
        choices=[l.lower() for l in logger.getLevelsToString()],
        default='error')
    args = parser.parse_args()

    # Configure logger.
    logger.initLogger(None, args.verbosityLevel.upper())

    # Start linknx.
    linknx = Linknx(args.host, int(args.port))
    try:
        if requestType == 'read':
            objects = linknx.getObjects(
                objectIds=args.objectIds
            ) if not args.regex else linknx.getObjects(patterns=args.objectIds)

            # No object.
            if not objects:
                logger.reportWarning('No such object.')
                sys.exit(10)

            # Count tabs to align columns.
            report = objects.getValues()
            longestId = max([len(obj) for obj in report.keys()])
            succeeds = True
            for o in sorted(report):
                v = report[o]
                spaceCount = longestId - len(o)
                spaces = ''
                while spaceCount > 0:
                    spaces += ' '
                    spaceCount -= 1
                if args.value_only:
                    print('{0}'.format(v))
                else:
                    print('{0} {2} {1}'.format(o, v, spaces))

                if args.expected_value != None:
                    obj = linknx.getObject(o)
                    convertedExpectedValue = obj.convertValueToString(
                        args.expected_value)
                    convertedObjectValue = obj.convertValueToString(v)
                    succeeds = succeeds and convertedExpectedValue == convertedObjectValue

            if not succeeds: exit(100)

        elif requestType == 'write':
            linknx.getObject(args.object).value = args.value
        elif requestType == 'execute':
            if args.action == None:
                action = ''.join(sys.stdin.readlines())
            else:
                action = args.action
            linknx.executeAction(action)
        else:
            raise Exception('Unsupported request type.')

    except Exception as e:
        logger.reportException()
        sys.exit(3)
Example #9
0
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Pyknx. If not, see <http://www.gnu.org/licenses/>.
#
# For any question, feature requests or bug reports, feel free to contact me at:
# knx at aminate dot net

"""
Outputs the current version of the Pyknx package.
"""

import pyknx
import argparse
import sys
import logging
import os
from pyknx import logger

__doc__ = __doc__.format(scriptname=os.path.basename(__file__))

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description=__doc__)
    args = parser.parse_args()

    # Configure logger.
    logger.initLogger(None)

    print(pyknx.version)
Example #10
0
def handleRequest(requestType, doc):
    logger.initLogger(None, logging.INFO, usesDetailedLogging=False)

    parser = argparse.ArgumentParser(description=doc)
    parser.add_argument('-s', '--server', dest='host', help='Hostname of the machine running the linknx daemon. Default is localhost.', default='localhost')
    parser.add_argument('-p', '--port', dest='port', help='Port linknx listens on. Default is 1028.', default=1028)
    if requestType == 'read':
        parser.add_argument('objectIds', help='ID represents the identifier of the object to read.', metavar='ID', nargs='+')
        parser.add_argument('-R', '--regex', action='store_true', help='ID in the "object" argument is interpreted as a regex and used to find objects to read. The pattern must comply with the \'re\' python module.')
        parser.add_argument('--value-only', action='store_true', help='Output the value of the queried object but do not prefix it with the object\'s id.')
        parser.add_argument('--expected-value', help='Expected value of the object. This script will exit with a non-zero return code if the value is not the expected one. This is useful when using this script in a "if" test of a shell script.')
    elif requestType == 'write':
        parser.add_argument('object', help='ID represents the identifier of the object to write to.', metavar='ID')
        parser.add_argument('value', help='Assigns VALUE to the object identified by ID.', metavar='VALUE')
    elif requestType == 'execute':
        parser.add_argument('--action', help='use the ACTION string as the XML representation of the action to execute rather than reading it from standard input.', metavar='ACTION')
    else:
        raise Exception('Unsupported request type "{0}".'.format(requestType))
    parser.add_argument('-v', '--verbose', dest='verbosityLevel', help='Set verbosity level. Default is "error".', metavar='LEVEL', choices=[l.lower() for l in logger.getLevelsToString()], default='error')
    args = parser.parse_args()

    # Configure logger.
    logger.initLogger(None, args.verbosityLevel.upper())

    # Start linknx.
    linknx = Linknx(args.host, int(args.port))
    try:
        if requestType == 'read':
            objects = linknx.getObjects(objectIds=args.objectIds) if not args.regex else linknx.getObjects(patterns=args.objectIds)

            # No object.
            if not objects:
                logger.reportWarning('No such object.')
                sys.exit(10)

            # Count tabs to align columns.
            report = objects.getValues()
            longestId = max([len(obj) for obj in report.keys()])
            succeeds = True
            for o in sorted(report):
                v = report[o]
                spaceCount = longestId - len(o)
                spaces=''
                while spaceCount > 0:
                    spaces+=' '
                    spaceCount -= 1
                if args.value_only:
                    print('{0}'.format(v))
                else:
                    print('{0} {2} {1}'.format(o, v, spaces))

                if args.expected_value != None:
                    obj = linknx.getObject(o)
                    convertedExpectedValue = obj.convertValueToString(args.expected_value)
                    convertedObjectValue = obj.convertValueToString(v)
                    succeeds = succeeds and convertedExpectedValue == convertedObjectValue

            if not succeeds: exit(100)

        elif requestType == 'write':
            linknx.getObject(args.object).value = args.value
        elif requestType == 'execute':
            if args.action == None:
                action = ''.join(sys.stdin.readlines())
            else:
                action = args.action
            linknx.executeAction(action)
        else:
            raise Exception('Unsupported request type.')

    except Exception as e:
        logger.reportException()
        sys.exit(3)
Example #11
0
# You should have received a copy of the GNU General Public License
# along with Homewatcher. If not, see <http://www.gnu.org/licenses/>.
#
# For any question, feature requests or bug reports, feel free to contact me at:
# knx at aminate dot net
"""
Outputs the current version of the Homewatcher package.
"""

# Check that pyknx is present as soon as possible.
from homewatcher import ensurepyknx

from homewatcher.configuration import Configuration
import homewatcher
import argparse
import sys
import logging
import os
from pyknx import logger

__doc__ = __doc__.format(scriptname=os.path.basename(__file__))

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description=__doc__)
    args = parser.parse_args()

    # Configure logger.
    logger.initLogger(None)

    print(homewatcher.version)