Beispiel #1
0
    def getCallList(self, timeout=1):
        """Get the list of phone calls made

        Example of a phone call result:

        ::

            [{'Count': None, 'Name': None, 'CalledNumber': '030868709971', 'Numbertype': 'sip', 'Duration': '0:01',
            'Caller': '015155255399', 'Called': 'SIP: 030868729971', 'Date': '02.01.14 13:14',
            'Device': 'Anrufbeantworter','Path': None, 'Port': '40', 'Type': '1', 'Id': '15'}]

        Types:

        * 1 - answered
        * 2 - missed
        * 3 - outgoing

        :param float timeout: the timeout to wait for the action to be executed
        :return: the list of made phone calls
        :rtype: list[dict[str: str]]
        """
        namespace = Fritz.getServiceType("getCallList")
        uri = self.getControlURL(namespace)

        results = self.execute(uri, namespace, "GetCallList")

        # setup proxies
        proxies = {}
        if self.httpProxy:
            proxies = {"https": self.httpProxy}

        if self.httpsProxy:
            proxies = {"http": self.httpsProxy}

        # get the content
        request = requests.get(results["NewCallListURL"],
                               proxies=proxies,
                               timeout=float(timeout))

        if request.status_code != 200:
            errorStr = DeviceTR64._extractErrorString(request)
            raise ValueError('Could not get CPE definitions "' +
                             results["NewCallListURL"] + '" : ' +
                             str(request.status_code) + ' - ' +
                             request.reason + " -- " + errorStr)

        # parse xml
        try:
            root = ET.fromstring(request.text.encode('utf-8'))
        except Exception as e:
            raise ValueError("Could not parse call list '" +
                             results["NewCallListURL"] + "': " + str(e))

        calls = []

        for child in root:
            if child.tag.lower() == "call":

                callParameters = {}

                for callChild in child:
                    callParameters[callChild.tag] = callChild.text

                calls.append(callParameters)

        return calls
Beispiel #2
0
    def discoverParticularHost(host, service="ssdp:all", deviceDefinitionURL=None, timeout=1, retries=2,
                               ipAddress="239.255.255.250", port=1900, proxies=None):
        """Discover a particular host and find the best response.

        This tries to find the most specific discovery result for the given host. Only the discovery result contains
        the URL to the XML tree which initializes the device definition. If an URL is already known it should be
        provided to avoid additional latency for a broader first device discovery.
        This method also do some magic to find the best result for the given host as UPnP devices behave sometimes
        strangely. This call is costly the result if any should be cached.

        :param str host: the host to find
        :param service: the service type or list of service types if known to search for
        :type service: str or list[str]
        :param str deviceDefinitionURL: if provided it is used to skip a first device discovery
        :param float timeout: the time to wait for each retry
        :param int retries: the amount of times how often the device is tried to discover
        :param str ipAddress: the multicast ip address to discover devices
        :param int port: the port to discover devices
        :param str proxies: proxy definition as defined here:
            `Proxy definition <http://docs.python-requests.org/en/latest/user/advanced/#proxies>`_
        :return: If the device have been found the response is returned otherwise None
        :rtype: DiscoveryResponse
        :raises ValueError: if problems with reading or parsing the xml device definition occurs
        :raises requests.exceptions.ConnectionError: when the device definitions can not be downloaded
        :raises requests.exceptions.ConnectTimeout: when download time out

        Example:
          ::

            proxies = {"http": "http://localhost:8888"}
            result = discoverParticularHost("192.168.0.1", proxies=proxies)
            if result is not None:
                print("Host: " + result.locationHost + " Port: " + result.locationPort + " Device definitions: " + \\
                    result.location)

        .. seealso::

            :class:`~simpletr64.DiscoveryResponse`, :meth:`~simpletr64.Discover.discover`
        """

        # get all IP addresses for the given host
        ipResults = socket.getaddrinfo(host, 80)

        if len(ipResults) == 0:
            return None

        ipAddresses = []

        # remember all ip addresses for the given host
        for ipAdrTupple in ipResults:
            ipAddresses.append(ipAdrTupple[4][0])

        bestPick = None
        services = []

        if deviceDefinitionURL is None:
            # no xml definition given, so lets search for one

            # search for all devices first
            discoverResults = Discover.discover(service=service, timeout=timeout, retries=retries,
                                                ipAddress=ipAddress, port=port)

            for result in discoverResults:
                if result.locationHost in ipAddresses:
                    # now we found a result for that host, pick the best service type if multiple results for the host
                    # are found
                    if Discover.rateServiceTypeInResult(result) > Discover.rateServiceTypeInResult(bestPick):
                        bestPick = result

                    # remember all services
                    if result.service not in services:
                        services.append(result.service)

            if bestPick is None:
                return None
        else:
            # create response with given parameter
            bestPick = DiscoveryResponse.create(deviceDefinitionURL, service=service)

        # some routers do not advice their TR64 capabilities but their UPnp which is only a subset of actions.
        # Try to find out if the given XML definition path will give us a better service type.
        # load xml definition

        # some devices response differently without a User-Agent
        headers = {"User-Agent": "Mozilla/5.0; SimpleTR64-3"}

        request = requests.get(bestPick.location, proxies=proxies, headers=headers, timeout=float(timeout))

        if request.status_code != 200:
            errorStr = DeviceTR64._extractErrorString(request)
            raise ValueError('Could not get CPE definitions for "' + bestPick.location + '": ' +
                             str(request.status_code) + ' - ' + request.reason + " -- " + errorStr)

        # parse xml
        try:
            root = ET.fromstring(request.text.encode('utf-8'))
        except Exception as e:
            raise ValueError("Could not parse CPE definitions for '" + bestPick.location + "': " + str(e))

        # find the first deviceType in the document tree
        for element in root.getiterator():
            # check if element tag name ends on deviceType, skip XML namespace
            if element.tag.lower().endswith("devicetype"):

                serviceFound = element.text

                # remember the service found if it does not exist yet
                if serviceFound not in services:
                    services.append(serviceFound)

                # create a specific service just to check if we found it already
                serviceFound = serviceFound.replace("schemas-upnp-org", "dslforum-org")

                # test if we already have the best service type then we dont need to do an other discovery request
                if serviceFound == bestPick.service:
                    return bestPick

                for service in services:
                    # we search for the specific device tyoe version as of specified in TR64 protocol.
                    # some devices returns different results depending on the given service type, so lets be
                    # very specific
                    specificService = service.replace("schemas-upnp-org", "dslforum-org")

                    if specificService not in services:
                        services.append(specificService)

                # we do an other discovery request with more specific service/device type
                discoverResultsSpecific = Discover.discover(service=services, timeout=float(timeout), retries=retries,
                                                            ipAddress=ipAddress, port=port)

                # iterate through all results to find the most specific one
                evenBetterPick = None

                for specificResult in discoverResultsSpecific:
                    if specificResult.locationHost in ipAddresses:
                        if Discover.rateServiceTypeInResult(specificResult) > \
                                Discover.rateServiceTypeInResult(evenBetterPick):
                            evenBetterPick = specificResult

                if evenBetterPick is not None:
                    # best we could find
                    return evenBetterPick

                # we found first deviceType tag in the XML structure, no need to go further
                break

        if deviceDefinitionURL is not None:
            # we created our own response, so no result found
            return None

        # we found only an unspecific result, return it anyway
        return bestPick
Beispiel #3
0
    def discoverParticularHost(host,
                               service="ssdp:all",
                               deviceDefinitionURL=None,
                               timeout=1,
                               retries=2,
                               ipAddress="239.255.255.250",
                               port=1900,
                               proxies=None):
        """Discover a particular host and find the best response.

        This tries to find the most specific discovery result for the given host. Only the discovery result contains
        the URL to the XML tree which initializes the device definition. If an URL is already known it should be
        provided to avoid additional latency for a broader first device discovery.
        This method also do some magic to find the best result for the given host as UPnP devices behave sometimes
        strangely. This call is costly the result if any should be cached.

        :param str host: the host to find
        :param service: the service type or list of service types if known to search for
        :type service: str or list[str]
        :param str deviceDefinitionURL: if provided it is used to skip a first device discovery
        :param float timeout: the time to wait for each retry
        :param int retries: the amount of times how often the device is tried to discover
        :param str ipAddress: the multicast ip address to discover devices
        :param int port: the port to discover devices
        :param str proxies: proxy definition as defined here:
            `Proxy definition <http://docs.python-requests.org/en/latest/user/advanced/#proxies>`_
        :return: If the device have been found the response is returned otherwise None
        :rtype: DiscoveryResponse
        :raises ValueError: if problems with reading or parsing the xml device definition occurs
        :raises requests.exceptions.ConnectionError: when the device definitions can not be downloaded
        :raises requests.exceptions.ConnectTimeout: when download time out

        Example:
          ::

            proxies = {"http": "http://localhost:8888"}
            result = discoverParticularHost("192.168.0.1", proxies=proxies)
            if result is not None:
                print("Host: " + result.locationHost + " Port: " + result.locationPort + " Device definitions: " + \\
                    result.location)

        .. seealso::

            :class:`~simpletr64.DiscoveryResponse`, :meth:`~simpletr64.Discover.discover`
        """

        # get all IP addresses for the given host
        ipResults = socket.getaddrinfo(host, 80)

        if len(ipResults) == 0:
            return None

        ipAddresses = []

        # remember all ip addresses for the given host
        for ipAdrTupple in ipResults:
            ipAddresses.append(ipAdrTupple[4][0])

        bestPick = None
        services = []

        if deviceDefinitionURL is None:
            # no xml definition given, so lets search for one

            # search for all devices first
            discoverResults = Discover.discover(service=service,
                                                timeout=timeout,
                                                retries=retries,
                                                ipAddress=ipAddress,
                                                port=port)

            for result in discoverResults:
                if result.locationHost in ipAddresses:
                    # now we found a result for that host, pick the best service type if multiple results for the host
                    # are found
                    if Discover.rateServiceTypeInResult(
                            result) > Discover.rateServiceTypeInResult(
                                bestPick):
                        bestPick = result

                    # remember all services
                    if result.service not in services:
                        services.append(result.service)

            if bestPick is None:
                return None
        else:
            # create response with given parameter
            bestPick = DiscoveryResponse.create(deviceDefinitionURL,
                                                service=service)

        # some routers do not advice their TR64 capabilities but their UPnp which is only a subset of actions.
        # Try to find out if the given XML definition path will give us a better service type.
        # load xml definition

        # some devices response differently without a User-Agent
        headers = {"User-Agent": "Mozilla/5.0; SimpleTR64-3"}

        request = requests.get(bestPick.location,
                               proxies=proxies,
                               headers=headers,
                               timeout=float(timeout))

        if request.status_code != 200:
            errorStr = DeviceTR64._extractErrorString(request)
            raise ValueError('Could not get CPE definitions for "' +
                             bestPick.location + '": ' +
                             str(request.status_code) + ' - ' +
                             request.reason + " -- " + errorStr)

        # parse xml
        try:
            root = ET.fromstring(request.text.encode('utf-8'))
        except Exception as e:
            raise ValueError("Could not parse CPE definitions for '" +
                             bestPick.location + "': " + str(e))

        # find the first deviceType in the document tree
        for element in root.iter():
            # check if element tag name ends on deviceType, skip XML namespace
            if element.tag.lower().endswith("devicetype"):

                serviceFound = element.text

                # remember the service found if it does not exist yet
                if serviceFound not in services:
                    services.append(serviceFound)

                # create a specific service just to check if we found it already
                serviceFound = serviceFound.replace("schemas-upnp-org",
                                                    "dslforum-org")

                # test if we already have the best service type then we dont need to do an other discovery request
                if serviceFound == bestPick.service:
                    return bestPick

                for service in services:
                    # we search for the specific device tyoe version as of specified in TR64 protocol.
                    # some devices returns different results depending on the given service type, so lets be
                    # very specific
                    specificService = service.replace("schemas-upnp-org",
                                                      "dslforum-org")

                    if specificService not in services:
                        services.append(specificService)

                # we do an other discovery request with more specific service/device type
                discoverResultsSpecific = Discover.discover(
                    service=services,
                    timeout=float(timeout),
                    retries=retries,
                    ipAddress=ipAddress,
                    port=port)

                # iterate through all results to find the most specific one
                evenBetterPick = None

                for specificResult in discoverResultsSpecific:
                    if specificResult.locationHost in ipAddresses:
                        if Discover.rateServiceTypeInResult(specificResult) > \
                                Discover.rateServiceTypeInResult(evenBetterPick):
                            evenBetterPick = specificResult

                if evenBetterPick is not None:
                    # best we could find
                    return evenBetterPick

                # we found first deviceType tag in the XML structure, no need to go further
                break

        if deviceDefinitionURL is not None:
            # we created our own response, so no result found
            return None

        # we found only an unspecific result, return it anyway
        return bestPick
Beispiel #4
0
    def getCallList(self, timeout=1):
        """Get the list of phone calls made

        Example of a phone call result:

        ::

            [{'Count': None, 'Name': None, 'CalledNumber': '030868709971', 'Numbertype': 'sip', 'Duration': '0:01',
            'Caller': '015155255399', 'Called': 'SIP: 030868729971', 'Date': '02.01.14 13:14',
            'Device': 'Anrufbeantworter','Path': None, 'Port': '40', 'Type': '1', 'Id': '15'}]

        Types:

        * 1 - answered
        * 2 - missed
        * 3 - outgoing

        :param float timeout: the timeout to wait for the action to be executed
        :return: the list of made phone calls
        :rtype: bool
        """
        namespace = Fritz.getServiceType("getCallList")
        uri = self.getControlURL(namespace)

        results = self.execute(uri, namespace, "GetCallList")

        # setup proxies
        proxies = {}
        if self.httpProxy:
            proxies = {"https": self.httpProxy}

        if self.httpsProxy:
            proxies = {"http": self.httpsProxy}

        # get the content
        request = requests.get(results["NewCallListURL"], proxies=proxies, timeout=float(timeout))

        if request.status_code != 200:
            errorStr = DeviceTR64._extractErrorString(request)
            raise ValueError(
                'Could not get CPE definitions "'
                + results["NewCallListURL"]
                + '" : '
                + str(request.status_code)
                + " - "
                + request.reason
                + " -- "
                + errorStr
            )

        # parse xml
        try:
            root = ET.fromstring(request.text.encode("utf-8"))
        except Exception as e:
            raise ValueError("Could not parse call list '" + results["NewCallListURL"] + "': " + str(e))

        calls = []

        for child in root.getchildren():
            if child.tag.lower() == "call":

                callParameters = {}

                for callChild in child.getchildren():
                    callParameters[callChild.tag] = callChild.text

                calls.append(callParameters)

        return calls