def get_version(self):
        """Return version of audioid monitor service

        :returns: version
        :rtype: dict
        :raises: :exc:`AudioidMonUnexpectedError` if an unexpected error occurs.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.version()
        {u'author': u'mufin GmbH',
        u'copyright': u'Copyright (c) 2013-2017 mufin GmbH, all rights reserved.',
        u'version': u'1.6.3'}
        """
        url = self.__base_url + "/version"
        try:
            resp = requests.get(url)
            try:
                resp.raise_for_status()
                return resp.json()
            except requests.HTTPError as err:
                raise exceptions.AudioidMonUnexpectedError(repr(resp.json()))
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)
    def get_license(self):
        """Return license info of audioid monitor service

        :returns: license info; for more information see audioid monitor online documentation
        :rtype: dict
        :raises: :exc:`AudioidMonUnexpectedError` if an unexpected error occurs.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.license()
        {
          "valid": true,
          "details": "",
          "expiryDate": "2018-01-01T00:00:00Z",
          "beginDate": "2017-01-01T00:00:00Z",
          "fingerprintConfig": "broadcast"
        }

        """
        url = self.__base_url + "/v1/license"
        try:
            resp = requests.get(url)
            try:
                resp.raise_for_status()
                return resp.json()
            except requests.HTTPError as err:
                raise exceptions.AudioidMonUnexpectedError(repr(resp.json()))
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)
    def delete_fingerprints(self):
        """Delete all fingerprint from the database.

        :raises: :exc:`AudioidMonNotEnoughResources` if the audioid-mon service has not enough system resources.
        :raises: :exc:`AudioidMonResourceBusy` if the audioid-mon service is busy with other tasks.
        :raises: :exc:`AudioidMonUnexpectedError` if an unexpected error occurs.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.delete_fingerprints()

        """
        url = self.__base_url + "/v1/references"
        try:
            resp = requests.delete(url)
            try:
                resp.raise_for_status()
            except requests.HTTPError as err:
                if resp.json()["code"] == 20115:
                    raise exceptions.AudioidMonNotEnoughResources(
                        repr(resp.json()))
                elif resp.json()["code"] == 20119:
                    raise exceptions.AudioidMonResourceBusy(repr(resp.json()))
                else:
                    raise exceptions.AudioidMonUnexpectedError(
                        repr(resp.json()))
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)
    def get_status(self):
        """Return system status of audioid monitor service

        :returns: system status; for more information see audioid monitor  online documentation
        :rtype: dict
        :raises: :exc:`AudioidMonUnexpectedError` if an unexpected error occurs.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.system_status()
        {u'cluster': {u'cells': [[{u'fingerprints': {u'count': 0, u'durationMs': 0},
        u'matcherId': u'audioid-mon-match-d10a07e54910-aHKWBNFir1h9'}]], u'matcher': 1},
        u'fingerprints': {u'count': 0, u'durationMs': 0},
        u'status': {u'details': u'', u'status': u'ready'}}


        """
        url = self.__base_url + "/v1/status"
        try:
            resp = requests.get(url)
            try:
                resp.raise_for_status()
                return resp.json()
            except requests.HTTPError as err:
                raise exceptions.AudioidMonUnexpectedError(repr(resp.json()))
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)
    def extract_fingerprint(self, audio_filename, fingerprint_filename):
        """Extract a fingerprint from an audio file and return a fingerprint file.

        :param audio_filename: Name of the audio file
        :type audio_filename: string
        :param fingerprint_filename: Name of fingerprint file
        :type fingerprint_filename: string
        :raises: :exc:`AudioidMonInvalidInput` if the fingerprint does not exists.
        :raises: :exc:`AudioidMonSubmittedItemIsTooLarge` if the audio file is too large.
        :raises: :exc:`AudioidMonUnexpectedError` if an expected error occurs.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.extract_fingerprint("advertisement.mp3", "advertisement.mfp")

        """
        try:
            url = self.__base_url + "/v1/extract/sync"
            files = {"upload": open(audio_filename, "rb")}
            resp = requests.post(url, files=files)
            try:
                resp.raise_for_status()
                with open(fingerprint_filename, 'wb') as file:
                    for chunk in resp:
                        file.write(chunk)
                return resp
            except requests.HTTPError as err:
                try:
                    if resp.json()["code"] == 20109:
                        raise exceptions.AudioidMonInvalidInput(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20114:
                        raise exceptions.AudioidMonSubmittedItemIsTooLarge(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20109:
                        raise exceptions.AudioidMonInvalidInput(
                            repr(resp.json()))
                    else:
                        raise exceptions.AudioidMonUnexpectedError(
                            repr(resp.json()))
                except (ValueError, KeyError):
                    raise exceptions.AudioidMonUnexpectedError(err)
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)
    def delete_fingerprint(self, id):
        """Delete a fingerprint from the database.

        :param id: The id of the fingerprint to be deleted
        :type id: long
        :raises: :exc:`AudioidMonItemNotFound` if the fingerprint does not exists.
        :raises: :exc:`AudioidMonNotEnoughResources` if the audioid-mon service has not enough system resources.
        :raises: :exc:`AudioidMonResourceBusy` if the audioid-mon service is busy with other tasks.
        :raises: :exc:`AudioidMonUnexpectedError` if the fingerprint has an invalid format.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.delete_fingerprint(1)

        """
        url = self.__base_url + "/v1/references/" + str(id)
        try:
            resp = requests.delete(url)
            try:
                resp.raise_for_status()
            except requests.HTTPError as err:
                try:
                    if resp.json()["code"] == 20106:
                        raise exceptions.AudioidMonItemNotFound(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20115:
                        raise exceptions.AudioidMonNotEnoughResources(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20119:
                        raise exceptions.AudioidMonResourceBusy(
                            repr(resp.json()))
                    else:
                        raise exceptions.AudioidMonUnexpectedError(
                            repr(resp.json()))
                except (ValueError, KeyError):
                    raise exceptions.AudioidMonUnexpectedError(
                        repr(resp.json()))
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)
    def get_fingerprint_ids(self):
        """Return list of dictionaries of fingerprints ids and durations.

        :returns: list of dictionaries {"id": id, "durationMs": durationMs}
        :rtype: list
        :raises: :exc:`AudioidMonNotEnoughResources` if the audioid-mon service has not enough system resources.
        :raises: :exc:`AudioidMonResourceBusy` if the audioid-mon service is busy with other tasks.
        :raises: :exc:`AudioidMonUnexpectedError` if an unexpected error occurs.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.get_fingerprint_ids()
        [{u'durationMs': 5632, u'id': 1}]

        :note: Returns empty list if no fingerprints are loaded.
        """
        url = self.__base_url + "/v1/references"
        try:
            resp = requests.get(url)
            try:
                resp.raise_for_status()
                return resp.json()
            except requests.HTTPError as err:
                if resp.json()["code"] == 20115:
                    raise exceptions.AudioidMonNotEnoughResources(
                        repr(resp.json()))
                elif resp.json()["code"] == 20116:
                    raise exceptions.AudioidMonInvalidFingerprint(
                        repr(resp.json()))
                elif resp.json()["code"] == 20119:
                    raise exceptions.AudioidMonResourceBusy(repr(resp.json()))
                else:
                    raise exceptions.AudioidMonUnexpectedError(
                        repr(resp.json()))
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)
    def monitor_fingerprint(self, fingerprint_filename):
        """Monitor a fingerprint and return a report.

        The report is a list of dictionaries containing matches. Each match is a
        dictionary containing the following fields:

        =========== ===========
        Key 	    Description
        =========== ===========
        referenceId The reference fingerprint id that was identified or 0 if no match.
        confidence 	The confidence of the match [0-100].
        qryStart 	The start position in the query file.
        qryStop 	The end position in the query file.
        refStart 	The start position in the reference.
        refStop 	The end position in the reference.
        =========== ===========

        The qryStart and qryStop positions are absolute timestamps based on the start time
        of the file, if the query file was extracted with a given start time parameter
        of the audioid-mon-extract tool. Otherwise the matching time is the position
        in the file since epoch (1970-01-01T00:00:00Z).

        The same goes for the reference files and refStart/refStop.

        The time format is RFC3339.


        :param fingerprint_filename: The filename of the audio fingerprint to be monitored.
        :type fingerprint_filename: string
        :returns: list of matches.
        :rtype: list

        :raises: :exc:`AudioidMonInternalError` if the uploaded fingerprint does not have a valid format.
        :raises: :exc:`AudioidMonSubmittedItemIsTooLarge` if the fingerprint exceeds the maximum size.
        :raises: :exc:`AudioidMonInvalidFingerprint` if the uploaded fingerprint does not have a valid format.
        :raises: :exc:`AudioidMonNotEnoughResources` if the audioid-mon service has not enough system resources.
        :raises: :exc:`AudioidMonResourceBusy` if the audioid-mon service is busy with other tasks.
        :raises: :exc:`AudioidMonLicenseVerificationFailed` if audioid-mon service does not have a valid license.
        :raises: :exc:`AudioidMonUnexpectedError` if an unexpected error occurs.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.monitor_fingerprint("./audioidmon/tests/resources/foo.mfp")
        [{u'confidence': 100,
          u'qryStart': u'1969-12-31T23:59:59.744Z',
          u'qryStop': u'1970-01-01T00:00:00.128Z',
          u'refStart': u'0001-01-01T00:00:00Z',
          u'refStop': u'0001-01-01T00:00:00Z',
          u'referenceId': 0},
         {u'confidence': 100,
          u'qryStart': u'1970-01-01T00:00:00.128Z',
          u'qryStop': u'1970-01-01T00:00:04.736Z',
          u'refStart': u'1970-01-01T00:00:00.128Z',
          u'refStop': u'1970-01-01T00:00:04.736Z',
          u'referenceId': 1},
         {u'confidence': 100,
          u'qryStart': u'1970-01-01T00:00:04.736Z',
          u'qryStop': u'1970-01-01T00:00:05.376Z',
          u'refStart': u'0001-01-01T00:00:00Z',
          u'refStop': u'0001-01-01T00:00:00Z',
          u'referenceId': 0}]
        """
        url = self.__base_url + "/v1/monitor/sync"
        files = {"upload": open(fingerprint_filename, "rb")}
        try:
            resp = requests.post(url, files=files)
            try:
                resp.raise_for_status()
                return resp.json()
            except requests.HTTPError as err:
                try:
                    if resp.json()["code"] == 20100:
                        raise exceptions.AudioidMonInternalError(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20114:
                        raise exceptions.AudioidMonSubmittedItemIsTooLarge(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20115:
                        raise exceptions.AudioidMonNotEnoughResources(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20116:
                        raise exceptions.AudioidMonInvalidFingerprint(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20119:
                        raise exceptions.AudioidMonResourceBusy(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20121:
                        raise exceptions.AudioidMonLicenseVerificationFailed(
                            repr(resp.json()))
                    else:
                        raise exceptions.AudioidMonUnexpectedError(
                            repr(resp.json()))
                except (
                        ValueError, KeyError
                ):  # ValueError is raised if response from service does not include JSON error message
                    raise exceptions.AudioidMonUnexpectedError(err)
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)
    def add_fingerprint(self, id, fingerprint_filename):
        """Adds a fingerprint to the database.

        :param id: The id assigned to the fingerprint. Must be an integer > 0.
        :param fingerprint_filename: The filename of the audio fingerprint.
        :type id: long
        :type fingerprint_filename: string
        :returns: dict containing id and duration of the fingerprint that has just been added, e.g. {"id": id, "durationMs": durationMs}
        :rtype: dict
        :raises: :exc:`AudioidMonInvalidInput` if id is not in a valid range
        :raises: :exc:`AudioidMonItemAlreadyExists` if fingerprint id already exists.
        :raises: :exc:`AudioidMonInvalidFingerprint` if the fingerprint has an invalid format.
        :raises: :exc:`AudioidMonSubmittedItemIsTooLarge` if the fingerprint exceeds the maximum size.
        :raises: :exc:`AudioidMonNotEnoughResources` if the audioid-mon service has not enough system resources.
        :raises: :exc:`AudioidMonResourceBusy` if the audioid-mon service is busy with other tasks.
        :raises: :exc:`AudioidMonServiceUnexpectedError` if an unexpected error occurs.
        :raises: :exc:`AudioidMonServiceNotAvailable` if a connection error occurs.

        :Example:

        >>> import audioidmon
        >>> client = audioidmon.AudioidMonService("http://127.0.0.1")
        >>> client.add_fingerprint(1, "./audioidmon/tests/resources/foo.mfp")
        {u'durationMs': 5632, u'id': 1}
        """
        url = self.__base_url + "/v1/references/" + str(id)
        try:
            files = {"upload": open(fingerprint_filename, "rb")}
            resp = requests.post(url, files=files)
            try:
                resp.raise_for_status()
                return resp.json()
            except requests.HTTPError as err:
                try:
                    if resp.json()["code"] == 20105:
                        raise exceptions.AudioidMonItemAlreadyExists(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20109:
                        raise exceptions.AudioidMonInvalidInput(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20105:
                        raise exceptions.AudioidMonItemAlreadyExists(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20114:
                        raise exceptions.AudioidMonSubmittedItemIsTooLarge(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20115:
                        raise exceptions.AudioidMonNotEnoughResources(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20116:
                        raise exceptions.AudioidMonInvalidFingerprint(
                            repr(resp.json()))
                    elif resp.json()["code"] == 20119:
                        raise exceptions.AudioidMonResourceBusy(
                            repr(resp.json()))
                    else:
                        raise exceptions.AudioidMonUnexpectedError(
                            repr(resp.json()))
                except (
                        ValueError, KeyError
                ):  # ValueError is raised if response from service does not include JSON error message
                    raise exceptions.AudioidMonUnexpectedError(repr(err))
        except requests.ConnectionError as err:
            raise exceptions.AudioidMonServiceNotAvailable(err)
        except requests.RequestException as err:
            raise exceptions.AudioidMonUnexpectedError(err)