Ejemplo n.º 1
0
 def run(self):
     try:
         self.socket.connect((self.linknx.host, self.linknx.port))
         logger.reportDebug('Message sent to linknx: ' +
                            self.messageWithEncodingHeader)
         answer = self.socket.sendString(self.messageWithEncodingHeader,
                                         encoding='utf8')
         while True:
             logger.reportDebug('Linknx answered ' + answer)
             answerDom = parseString(answer[0:answer.rfind(chr(4))])
             execNodes = answerDom.getElementsByTagName(
                 self.commandName)
             status = execNodes[0].getAttribute("status")
             if status == "ongoing":
                 # Wait for the final status.
                 answer = self.socket.waitForStringAnswer()
                 logger.reportDebug('New answer is {0}'.format(answer))
             else:
                 if status != "success":
                     self.error = self._getErrorFromXML(execNodes[0])
                     logger.reportError(self.error)
                 self.finalStatus = status
                 self.answerDom = answerDom
                 break
     finally:
         self.socket.close()
         if self.is_alive():
             logger.reportDebug('Thread is now stopped.')
Ejemplo n.º 2
0
 def run(self):
     try:
         self.socket.connect((self.linknx.host, self.linknx.port))
         logger.reportDebug("Message sent to linknx: " + self.messageWithEncodingHeader)
         answer = self.socket.sendString(self.messageWithEncodingHeader, encoding="utf8")
         while True:
             logger.reportDebug("Linknx answered " + answer)
             answerDom = parseString(answer[0 : answer.rfind(chr(4))])
             execNodes = answerDom.getElementsByTagName(self.commandName)
             status = execNodes[0].getAttribute("status")
             if status == "ongoing":
                 # Wait for the final status.
                 answer = self.socket.waitForStringAnswer()
                 logger.reportDebug("New answer is {0}".format(answer))
             else:
                 if status != "success":
                     self.error = self._getErrorFromXML(execNodes[0])
                     logger.reportError(self.error)
                 self.finalStatus = status
                 self.answerDom = answerDom
                 break
     finally:
         self.socket.close()
         if self.isAlive():
             logger.reportDebug("Thread is now stopped.")
Ejemplo n.º 3
0
 def _loadUserFile(self):
     # Append the directory that contains the user script to python path.
     if self._userFile:
         dirName, fileName = os.path.split(self._userFile)
         dirName = os.path.abspath(dirName)
         moduleName, fileExt = os.path.splitext(fileName)
         sys.path.append(dirName)
         logger.reportDebug('_loadUserFile: moduleName={0} fileExt={1} dirName={2}'.format(moduleName, fileExt, dirName))
         self._userModule = importlib.import_module(moduleName)
         logger.reportDebug('Imported {0}'.format(self._userModule.__file__))
         return True
     else:
         logger.reportError('No user file specified.')
         return False
Ejemplo n.º 4
0
    def assertShellCommand(self, command, expectedStdOut=None, expectedStdErr=None, expectedReturnCode=None, stdin=None):

        shouldSucceed = expectedStdErr == None and (expectedReturnCode == None or expectedReturnCode == 0)

        # Redirect command's stdout to a file so that we can compare with what
        # is expected.
        stdoutHandle, stdoutFilename = tempfile.mkstemp()
        stderrHandle, stderrFilename = tempfile.mkstemp()
        try:
            with open(stdoutFilename, 'w+') as stdoutFD:
                with open(stderrFilename, 'w+') as stderrFD:
                    returnCode = subprocess.call(command, stdout=stdoutFD, stderr=stderrFD, stdin=stdin)
                    if (returnCode == 0) != shouldSucceed:
                        logger.reportError('Command {command} output is {out}'.format(command=command, out=stdoutFD.readlines()))
                        logger.reportError('stderr is {out}'.format(out=stderrFD.readlines()))
                        self.fail('Command was expected to {failOrSucceed} but it {status}. Return code is {returnCode}'.format(failOrSucceed='succeed' if shouldSucceed else 'fail', status='succeeded' if returnCode == 0 else 'failed', returnCode=returnCode))

            # Compare output to what is expected.
            if expectedStdOut != None:
                self.assertFilesAreEqual(stdoutFilename, expectedStdOut)
            else:
                with open(stdoutFilename, 'r') as stdoutFD:
                    lines = stdoutFD.readlines()
                    self.assertEqual(os.stat(stdoutFilename).st_size, 0, 'No output was expected on standard output from this command. Output is {0}'.format(lines))
            if expectedStdErr != None:
                self.assertFilesAreEqual(stderrFilename, expectedStdErr)
            else:
                with open(stderrFilename, 'r') as stderrFD:
                    lines = stderrFD.readlines()
                    self.assertEqual(os.stat(stderrFilename).st_size, 0, 'No output was expected on standard error from this command. Output is {0}'.format(lines))

            if expectedReturnCode != None:
                self.assertEqual(returnCode, expectedReturnCode)

        finally:
            os.remove(stdoutFilename)
            os.remove(stderrFilename)
Ejemplo n.º 5
0
    def updateStatus(self):
        """
        Updates the status of this alert and raises the required events accordingly.

        """
        # Do not update if the daemon is in a process that may trigger
        # irrelevant intermediary states.
        if self.daemon.areAlertStatusUpdatesSuspended: return

        if not self.isStatusDirty:
            logger.reportDebug(
                'Status of {0} is already up-to-date, nothing to change.'.
                format(self))
            return
        logger.reportDebug('Updating status of {0}'.format(self))

        # Compute current status.
        if self._sensorsInAlert:
            newStatus = Alert.Status.ACTIVE
        elif self._sensorsInPrealert:
            newStatus = Alert.Status.INITIALIZING
        elif self.status == Alert.Status.ACTIVE and (
                self.persistenceObject != None
                and self.persistenceObject.value):
            # PAUSED status may only occur if persistence is supported.
            # Otherwise, as soon as last sensor leaves the alert, alert is
            # stopped and will start if a sensor gets triggered afterwards. This
            # is not the most convenient behaviour but with it, the user is free not to
            # define persistence.
            newStatus = Alert.Status.PAUSED
        else:
            newStatus = Alert.Status.STOPPED

        logger.reportDebug('New status for {0} is {1}'.format(self, newStatus))

        # When the alert is active, all sensors should leave the "prealert"
        # state to join the alert.
        if newStatus in (
                Alert.Status.ACTIVE, Alert.Status.PAUSED
        ):  # PAUSED is to be on the safe side as alert should always go through the ACTIVE state before going to PAUSED.
            for sensor in self._sensorsInPrealert:
                if not sensor in self._sensorsInAlert:
                    self._sensorsInAlert.add(
                        sensor
                    )  # None at this point. Timers will be created later in this method.   # sensor.makeAlertTimer(onTimeoutReached=None, onTerminated=lambda: self.removeSensorFromAlert(sensor))
            self._sensorsInPrealert = set()

        # Diff registered sensors.
        joiningSensors = self._sensorsInAlert - self._sensorsInAlertOnLastUpdateStatus
        leavingSensors = self._sensorsInAlertOnLastUpdateStatus - self._sensorsInAlert
        logger.reportDebug(
            'Updating status for {0}: joiningSensors={1}, leavingSensors={2}'.
            format(self, joiningSensors, leavingSensors))

        if newStatus == Alert.Status.ACTIVE:
            if self.persistenceObject != None:
                self.persistenceObject.value = True

        # Handle consequences of status change.
        if self.status == Alert.Status.STOPPED:
            if newStatus == Alert.Status.STOPPED:
                # No change.
                pass
            elif newStatus == Alert.Status.INITIALIZING:
                self.notifyAlertStarted()
            else:
                # Should not happen.
                logger.reportError(
                    'Unsupported switch from "{old}" to "{new}" for alert {alert}'
                    .format(alert=self, old=self.status, new=newStatus))
        elif self.status == Alert.Status.ACTIVE:
            if newStatus == Alert.Status.ACTIVE:
                # Check if a sensor joined or left.
                if joiningSensors:
                    self.notifySensorJoined()
                if leavingSensors:
                    self.notifySensorLeft()
            elif newStatus in (Alert.Status.PAUSED, Alert.Status.STOPPED):
                if not leavingSensors:
                    logger.reportError('A sensor should have left the alert.')
                else:
                    self.notifySensorLeft()

                self.notifyAlertDeactivated()

                if newStatus == Alert.Status.STOPPED:
                    self.notifyAlertReset()
                    self.notifyAlertStopped()
                elif newStatus == Alert.Status.PAUSED:
                    self.notifyAlertPaused()
                else:
                    raise Exception('Not implemented.')

            else:
                # Should not happen.
                logger.reportError(
                    'Unsupported switch from "{old}" to "{new}" for alert {alert}'
                    .format(alert=self, old=self.status, new=newStatus))
        elif self.status == Alert.Status.PAUSED:
            if newStatus == Alert.Status.PAUSED:
                # No change.
                pass
            elif newStatus == Alert.Status.STOPPED:
                self.notifyAlertReset()
                self.notifyAlertStopped()
            elif newStatus == Alert.Status.ACTIVE:
                self.notifyAlertResumed()
                if not joiningSensors:
                    logger.reportError(
                        'A sensor should have joined the alert.')
                else:
                    self.notifySensorJoined()
                self.notifyAlertActivated()
        elif self.status == Alert.Status.INITIALIZING:
            if newStatus == Alert.Status.INITIALIZING:
                # No change.
                pass
            elif newStatus == Alert.Status.ACTIVE:
                # Events to raise: started, sensor-joined, activated.
                if not joiningSensors:
                    logger.reportError(
                        'A sensor should have joined the alert.')
                else:
                    self.notifySensorJoined()
                self.notifyAlertActivated()
            elif newStatus == Alert.Status.STOPPED:
                self.notifyAlertAborted()
                self.notifyAlertStopped()

        # Stop obsolete timers for all sensors related to this alert.
        if newStatus in (Alert.Status.PAUSED, Alert.Status.STOPPED) or (
                self.status == Alert.Status.INITIALIZING
                and newStatus == Alert.Status.ACTIVE):
            for sensor in self.sensors:
                # Get the optional timer currently running for this sensor.
                timer = self._sensorTimers.get(sensor)
                if timer == None: continue

                timer.stop()
                timer = None
                del self._sensorTimers[sensor]

        for sensor in self._sensorsInAlert.union(self._sensorsInPrealert):
            # Start a new timer?
            if newStatus in (Alert.Status.INITIALIZING, Alert.Status.ACTIVE
                             ) and self._sensorTimers.get(sensor) == None:
                timer = sensor.makePrealertTimer(
                ) if newStatus == Alert.Status.INITIALIZING else sensor.makeAlertTimer(
                )
                self._sensorTimers[
                    sensor] = timer  # Prealert timer has been deleted above if applicable.
                timer.start()

        # Update persistence objects for all sensors.
        for s in self._sensorsInAlert:
            if s.persistenceObject != None:
                s.persistenceObject.value = True

        # Store current status.
        self._sensorsInAlertOnLastUpdateStatus = self._sensorsInAlert.copy()
        self.status = newStatus
        self.isStatusDirty = False
Ejemplo n.º 6
0
    # 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)
        elif option == '--help':
            printUsage()
            sys.exit(1)
        elif option == '-v' or option == '--verbose':
            verbosity = logger.parseLevel(value)
        else:
            logger.reportError('Unrecognized option ' + option)
            sys.exit(2)

    if not remainder:
        logger.reportError('Missing function name.')
        printUsage()
        sys.exit(3)

    if len(remainder) > 1:
        logger.reportError('Too many arguments: {0}'.format(remainder))
        printUsage()
        sys.exit(4)

    functionName = remainder[0]

    # Init logger.
Ejemplo n.º 7
0
    def updateStatus(self):
        """
        Updates the status of this alert and raises the required events accordingly.

        """
        # Do not update if the daemon is in a process that may trigger
        # irrelevant intermediary states.
        if self.daemon.areAlertStatusUpdatesSuspended: return

        if not self.isStatusDirty:
            logger.reportDebug('Status of {0} is already up-to-date, nothing to change.'.format(self))
            return
        logger.reportDebug('Updating status of {0}'.format(self))

        # Compute current status.
        if self._sensorsInAlert:
            newStatus = Alert.Status.ACTIVE
        elif self._sensorsInPrealert:
            newStatus = Alert.Status.INITIALIZING
        elif self.status == Alert.Status.ACTIVE and (self.persistenceObject != None and self.persistenceObject.value):
            # PAUSED status may only occur if persistence is supported.
            # Otherwise, as soon as last sensor leaves the alert, alert is
            # stopped and will start if a sensor gets triggered afterwards. This
            # is not the most convenient behaviour but with it, the user is free not to
            # define persistence.
            newStatus = Alert.Status.PAUSED
        else:
            newStatus = Alert.Status.STOPPED

        logger.reportDebug('New status for {0} is {1}'.format(self, newStatus))

        # When the alert is active, all sensors should leave the "prealert"
        # state to join the alert.
        if newStatus in (Alert.Status.ACTIVE, Alert.Status.PAUSED): # PAUSED is to be on the safe side as alert should always go through the ACTIVE state before going to PAUSED.
            for sensor in self._sensorsInPrealert:
                if not sensor in self._sensorsInAlert:
                    self._sensorsInAlert.add(sensor) # None at this point. Timers will be created later in this method.   # sensor.makeAlertTimer(onTimeoutReached=None, onTerminated=lambda: self.removeSensorFromAlert(sensor))
            self._sensorsInPrealert = set()

        # Diff registered sensors.
        joiningSensors = self._sensorsInAlert - self._sensorsInAlertOnLastUpdateStatus
        leavingSensors = self._sensorsInAlertOnLastUpdateStatus- self._sensorsInAlert
        logger.reportDebug('Updating status for {0}: joiningSensors={1}, leavingSensors={2}'.format(self, joiningSensors, leavingSensors))

        if newStatus == Alert.Status.ACTIVE:
            if self.persistenceObject != None: self.persistenceObject.value = True

        # Handle consequences of status change.
        if self.status == Alert.Status.STOPPED:
            if newStatus == Alert.Status.STOPPED:
                # No change.
                pass
            elif newStatus == Alert.Status.INITIALIZING:
                self.notifyAlertStarted()
            else:
                # Should not happen.
                logger.reportError('Unsupported switch from "{old}" to "{new}" for alert {alert}'.format(alert=self, old=self.status, new=newStatus))
        elif self.status == Alert.Status.ACTIVE:
            if newStatus == Alert.Status.ACTIVE:
                # Check if a sensor joined or left.
                if joiningSensors:
                    self.notifySensorJoined()
                if leavingSensors:
                    self.notifySensorLeft()
            elif newStatus in (Alert.Status.PAUSED, Alert.Status.STOPPED):
                if not leavingSensors:
                    logger.reportError('A sensor should have left the alert.')
                else:
                    self.notifySensorLeft()

                self.notifyAlertDeactivated()

                if newStatus == Alert.Status.STOPPED:
                    self.notifyAlertReset()
                    self.notifyAlertStopped()
                elif newStatus == Alert.Status.PAUSED:
                    self.notifyAlertPaused()
                else:
                    raise Exception('Not implemented.')

            else:
                # Should not happen.
                logger.reportError('Unsupported switch from "{old}" to "{new}" for alert {alert}'.format(alert=self, old=self.status, new=newStatus))
        elif self.status == Alert.Status.PAUSED:
            if newStatus == Alert.Status.PAUSED:
                # No change.
                pass
            elif newStatus == Alert.Status.STOPPED:
                self.notifyAlertReset()
                self.notifyAlertStopped()
            elif newStatus == Alert.Status.ACTIVE:
                self.notifyAlertResumed()
                if not joiningSensors:
                    logger.reportError('A sensor should have joined the alert.')
                else:
                    self.notifySensorJoined()
                self.notifyAlertActivated()
        elif self.status == Alert.Status.INITIALIZING:
            if newStatus == Alert.Status.INITIALIZING:
                # No change.
                pass
            elif newStatus == Alert.Status.ACTIVE:
                # Events to raise: started, sensor-joined, activated.
                if not joiningSensors:
                    logger.reportError('A sensor should have joined the alert.')
                else:
                    self.notifySensorJoined()
                self.notifyAlertActivated()
            elif newStatus == Alert.Status.STOPPED:
                self.notifyAlertAborted()
                self.notifyAlertStopped()

        # Stop obsolete timers for all sensors related to this alert.
        if newStatus in (Alert.Status.PAUSED, Alert.Status.STOPPED) or (self.status == Alert.Status.INITIALIZING and newStatus == Alert.Status.ACTIVE):
            for sensor in self.sensors:
                # Get the optional timer currently running for this sensor.
                timer = self._sensorTimers.get(sensor)
                if timer == None: continue

                timer.stop()
                timer = None
                del self._sensorTimers[sensor]

        for sensor in self._sensorsInAlert.union(self._sensorsInPrealert):
            # Start a new timer?
            if newStatus in (Alert.Status.INITIALIZING, Alert.Status.ACTIVE) and self._sensorTimers.get(sensor) == None:
                timer = sensor.makePrealertTimer() if newStatus == Alert.Status.INITIALIZING else sensor.makeAlertTimer()
                self._sensorTimers[sensor] = timer # Prealert timer has been deleted above if applicable.
                timer.start()

        # Update persistence objects for all sensors.
        for s in self._sensorsInAlert:
            if s.persistenceObject != None:
                s.persistenceObject.value = True

        # Store current status.
        self._sensorsInAlertOnLastUpdateStatus = self._sensorsInAlert.copy()
        self.status = newStatus
        self.isStatusDirty = False
Ejemplo n.º 8
0
    def generateConfig(self):
        # Read xml to get pyknx special attributes.
        config = self.config
        doc = config.ownerDocument
        rulesNode = self._getOrAddConfigElement(config, 'rules')

        # Generate a rule for each object that has a callback in the user file.
        objectNodes = config.getElementsByTagName('objects')[0]
        configuredAtLeastOne = False
        definesLegacyCallbackAttribute = False
        callbackAttributeName = self.callbackAttributeName
        for objectNode in objectNodes.getElementsByTagName('object'):
            objectConfig = ObjectConfig(objectNode)
            objectId = objectConfig.id
            callback = objectNode.getAttribute(callbackAttributeName)
            if callback == None or callback == '':
                if objectNode.getAttribute('pyknxcallback'):
                    logger.reportError('pyknxcallback found on {0}'.format(objectNode.toxml()))
                    definesLegacyCallbackAttribute = True
                logger.reportDebug('No callback found for object ' + objectConfig.id + ' (no {0} attribute for this object)'.format(callbackAttributeName))
                continue

            configuredAtLeastOne = True
            ruleNode = doc.createElement('rule')
            ruleId = '{0}{1}'.format(self._communicatorName, objectId)
            logger.reportInfo('Generating rule {0}'.format(ruleId))
            ruleNode.setAttribute('id', ruleId)
            ruleNode.setAttribute('init', 'false')
            conditionNode = doc.createElement('condition')
            conditionNode.setAttribute('type', 'object')
            conditionNode.setAttribute('id', objectId)
            # conditionNode.setAttribute('value', objectConfig.defaultValue)
            conditionNode.setAttribute('trigger', 'true')
            ruleNode.appendChild(conditionNode)
            actionListNode = doc.createElement('actionlist')
            actionListNode.setAttribute('type', 'if-true')
            ruleNode.appendChild(actionListNode)
            actionNode = self.createActionNode(callback, {'objectId' : objectId})
            actionListNode.appendChild(actionNode)
            # actionListIfFalseNode = actionListNode.cloneNode(True)
            # actionListIfFalseNode.setAttribute('type', 'on-false')
            # # ruleNode.appendChild(actionListIfFalseNode)
            rulesNode.appendChild(ruleNode)

        if not configuredAtLeastOne:
            logger.reportInfo('Nothing to do. None of the objects does define a callback attribute.')
            if definesLegacyCallbackAttribute:
                logger.reportWarning('There is at least one pyknxcallback attribute in the config file. These attributes were recognized by Pyknx before version 2.2. Did you forget to rename them to {0}?'.format(callbackAttributeName))
        else:
            # Add an ioport service for the communicator.
            servicesNode = self._getOrAddConfigElement(config, 'services')
            ioportsNode = self._getOrAddConfigElement(servicesNode, 'ioports')
            ioportNode = doc.createElement('ioport')
            ioportNode.setAttribute('id', self._communicatorName)
            try:
                hostIP = socket.gethostbyname(self._address[0])
            except:
                logger.reportWarning('Could not check that {0} is a valid ip address. Please check the output configuration. Linknx does not support hostnames, it requires IP address.'.format(self._address[0]))
                hostIP = self._address[0]
            ioportNode.setAttribute('host', hostIP) #gethostbyname converts the hostname into an ip. Linknx does not support ioport hostnames.
            ioportNode.setAttribute('port', str(self._address[1]))
            ioportNode.setAttribute('type', 'tcp')
            ioportsNode.appendChild(ioportNode)
Ejemplo n.º 9
0
    def assertShellCommand(self,
                           command,
                           expectedStdOut=None,
                           expectedStdErr=None,
                           expectedReturnCode=None,
                           stdin=None):

        shouldSucceed = expectedStdErr == None and (expectedReturnCode == None
                                                    or expectedReturnCode == 0)

        # Redirect command's stdout to a file so that we can compare with what
        # is expected.
        stdoutHandle, stdoutFilename = tempfile.mkstemp()
        stderrHandle, stderrFilename = tempfile.mkstemp()
        try:
            with open(stdoutFilename, 'w+') as stdoutFD:
                with open(stderrFilename, 'w+') as stderrFD:
                    returnCode = subprocess.call(command,
                                                 stdout=stdoutFD,
                                                 stderr=stderrFD,
                                                 stdin=stdin)
                    if (returnCode == 0) != shouldSucceed:
                        logger.reportError(
                            'Command {command} output is {out}'.format(
                                command=command, out=stdoutFD.readlines()))
                        logger.reportError(
                            'stderr is {out}'.format(out=stderrFD.readlines()))
                        self.fail(
                            'Command was expected to {failOrSucceed} but it {status}. Return code is {returnCode}'
                            .format(failOrSucceed='succeed'
                                    if shouldSucceed else 'fail',
                                    status='succeeded'
                                    if returnCode == 0 else 'failed',
                                    returnCode=returnCode))

            # Compare output to what is expected.
            if expectedStdOut != None:
                self.assertFilesAreEqual(stdoutFilename, expectedStdOut)
            else:
                with open(stdoutFilename, 'r') as stdoutFD:
                    lines = stdoutFD.readlines()
                    self.assertEqual(
                        os.stat(stdoutFilename).st_size, 0,
                        'No output was expected on standard output from this command. Output is {0}'
                        .format(lines))
            if expectedStdErr != None:
                self.assertFilesAreEqual(stderrFilename, expectedStdErr)
            else:
                with open(stderrFilename, 'r') as stderrFD:
                    lines = stderrFD.readlines()
                    self.assertEqual(
                        os.stat(stderrFilename).st_size, 0,
                        'No output was expected on standard error from this command. Output is {0}'
                        .format(lines))

            if expectedReturnCode != None:
                self.assertEqual(returnCode, expectedReturnCode)

        finally:
            os.remove(stdoutFilename)
            os.remove(stderrFilename)
Ejemplo n.º 10
0
import logging
from xml.dom.minidom import parseString
from threading import *
from pyknx import logger
from pyknx.linknx import *

def printUsage():
    print(__doc__)

if __name__ == '__main__':
    logger.initLogger(None, logging.INFO, usesDetailedLogging=False)

    try:
        options, remainder = getopt.getopt(sys.argv[1:], 'r:w:h:p:v:R:', ['read=', 'write=', 'regex=', 'host=', 'port=','verbose=','help'])
    except getopt.GetoptError as err:
        logger.reportError(sys.exc_info()[1])
        sys.exit(2)

    print('*******************')
    print('DEPRECATION NOTICE:')
    print('*******************')
    print('This script is now deprecated and its functionalities have been split into the two scripts pyknxread.py and pyknxwrite.py. An additional script named pyknxexecute.py allows for executing actions (which functionality is not handled by pyknxclient.py at all).')

    # Parse command line arguments.
    reads = False
    writes = False
    objectIds = []
    isRegex = False
    host = 'localhost'
    port = 1028
    verbosity = logging.WARNING
Ejemplo n.º 11
0
from pyknx.linknx import *


def printUsage():
    print(__doc__)


if __name__ == '__main__':
    logger.initLogger(None, logging.INFO, usesDetailedLogging=False)

    try:
        options, remainder = getopt.getopt(sys.argv[1:], 'r:w:h:p:v:R:', [
            'read=', 'write=', 'regex=', 'host=', 'port=', 'verbose=', 'help'
        ])
    except getopt.GetoptError as err:
        logger.reportError(sys.exc_info()[1])
        sys.exit(2)

    print('*******************')
    print('DEPRECATION NOTICE:')
    print('*******************')
    print(
        'This script is now deprecated and its functionalities have been split into the two scripts pyknxread.py and pyknxwrite.py. An additional script named pyknxexecute.py allows for executing actions (which functionality is not handled by pyknxclient.py at all).'
    )

    # Parse command line arguments.
    reads = False
    writes = False
    objectIds = []
    isRegex = False
    host = 'localhost'