Exemplo n.º 1
0
    def aggregated_report(self, payload):
        """ Return aggregated data report
        
            Args:
            payload (dict): dict containing iotkit REST API advanced-search
            parameters.

            Returns:
            JSON message containing returned data set
            
            See the Aggregated Report interface page on the iotkit REST API
            wiki for request and response message formats.
            https://github.com/enableiot/iotkit-api/wiki/Aggregated-Report-Interface
            
        """
        url = "{0}/accounts/{1}/data/report".format(globals.base_url, self.id)

        data = json.dumps(payload)
        # print url, data
        resp = requests.post(url,
                             data=data,
                             headers=get_auth_headers(self.client.user_token),
                             proxies=self.client.proxies,
                             verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        return js
Exemplo n.º 2
0
    def advanced_data_query(self, payload):
        """ Advanced data query supports multiple filters and sorting options
        
            Args:
            payload (dict): dict containing iotkit REST API advanced-search
            parameters.

            Returns:
            JSON message containing returned data set
            
            See the Advanced Data Inquiry page on the iotkit REST API wiki for
            request and response message formats
            https://github.com/enableiot/iotkit-api/wiki/Advanced-Data-Inquiry
            
        """
        url = "{0}/accounts/{1}/data/search/advanced".format(
            globals.base_url, self.id)

        data = json.dumps(payload)
        resp = requests.post(url,
                             data=data,
                             headers=get_auth_headers(self.client.user_token),
                             proxies=self.client.proxies,
                             verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        return js
Exemplo n.º 3
0
    def update_account(self, acct_info):
        """ Update account attributes for current account instance

            Args:
            account_info (dict): A dict containing updated account attributes

            Returns:
            JSON message containing account attributes

        """
        data = json.dumps(acct_info)
        if acct_info:
            url = "{0}/accounts/{1}".format(globals.base_url, self.id)
            resp = requests.put(url,
                                data=data,
                                headers=get_auth_headers(
                                    self.client.user_token),
                                proxies=self.client.proxies,
                                verify=globals.g_verify)
            check(resp, 200)
            js = resp.json()
            #update_properties(self, js)  # save account properties
            self.info = js
            return js
        else:
            raise ValueError("Invalid account info given.")
Exemplo n.º 4
0
    def get_user_tokeninfo(self):
        """ Get user token details

        Returns:
        --------
        JSON message containing access token details
        e.g.,
        Response 200 OK (application/json)
            {
                "header": {
                    "typ": "JWT",
                    "alg": "RS256"
                },
                "payload": {
                    "jti": "7b1430a2-dd61-4a47-919c-495cadb1ea7b",
                    "iss": "http://enableiot.com",
                    "sub": "53fdff4418b547e4241b8358",
                    "exp": "2014-10-02T07:53:25.361Z"
                }
            }

        """
        url = "{0}/auth/tokenInfo".format(self.base_url)
        resp = requests.get(url, headers=get_auth_headers(self.user_token),
                            proxies=self.proxies, verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        return js
Exemplo n.º 5
0
    def list_account_users(self):
        """ List all users associated with this account

            Returns:
            A list of user-attribute JSON messages
            Example,
                [
                    {
                        "id": "54e7cf2399fe4c41202e5b2f",
                        "accounts": {
                            "88f741fe-4087-42ef-a042-93c021e0148e": "admin"
                        },
                        "created": 1424477987329,
                        "email": "*****@*****.**",
                        "termsAndConditions": true,
                        "updated": 1424478023196,
                        "verified": true
                    }
                ]

        """
        url = "{0}/accounts/{1}/users".format(globals.base_url, self.id)
        resp = requests.get(url,
                            headers=get_auth_headers(self.client.user_token),
                            proxies=self.client.proxies,
                            verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        return js
Exemplo n.º 6
0
    def get_user_tokeninfo(self):
        """ Get user token details

        Returns:
        --------
        JSON message containing access token details
        e.g.,
        Response 200 OK (application/json)
            {
                "header": {
                    "typ": "JWT",
                    "alg": "RS256"
                },
                "payload": {
                    "jti": "7b1430a2-dd61-4a47-919c-495cadb1ea7b",
                    "iss": "http://enableiot.com",
                    "sub": "53fdff4418b547e4241b8358",
                    "exp": "2014-10-02T07:53:25.361Z"
                }
            }

        """
        url = "{0}/auth/tokenInfo".format(self.base_url)
        resp = requests.get(url,
                            headers=get_auth_headers(self.user_token),
                            proxies=self.proxies,
                            verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        return js
Exemplo n.º 7
0
 def get_attributes(self):
     url = "{0}/accounts/{1}/devices".format(
         self.client.base_url, self.account_id)
     resp = requests.get(url, headers=get_auth_headers(
         self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
     check(resp, 200)
     js = resp.json()
     return js
Exemplo n.º 8
0
 def get_user_info(self, user_id=None):
     # Get the user's info
     url = "{0}/users/{1}".format(globals.base_url, user_id)
     resp = requests.get(url, headers=get_auth_headers(
         self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
     check(resp, 200)
     js = resp.json()
     self.id = js["id"]
     return js
 def get_comp_types(self, full=False):
     url = "{0}/accounts/{1}/cmpcatalog".format(self.client.base_url,
                                                self.account.id)
     if full == True:
         url += "?full=true"
     resp = requests.get(url, headers=get_auth_headers(
         self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
     check(resp, 200)
     js = resp.json()
     return js
Exemplo n.º 10
0
 def update_user(self, user_info):
     if user_info:
         # given a user_id, get the user's info
         url = "{0}/users/{1}".format(globals.base_url, self.id)
         data = json.dumps(user_info)
         resp = requests.put(url, data=data, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         check(resp, 200)
     else:
         raise ValueError("No user info given.")
     return None
Exemplo n.º 11
0
 def get_account_invites(self):
     if self.account:
         url = "{0}/accounts/{1}/invites".format(
             self.client.base_url, self.account.id)
         resp = requests.get(url, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         check(resp, 200)
         js = resp.json()
         return js
     else:
         raise ValueError("No account provided.")
Exemplo n.º 12
0
 def get_user_invites(self, email):
     if email:
         url = "{0}/invites/{1}".format(
             self.client.base_url, urllib.quote(email))
         resp = requests.get(url, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         check(resp, 200)
         js = resp.json()
         return js
     else:
         raise ValueError("No email provided.")
Exemplo n.º 13
0
 def add_comp_type(self, component_info=None):
     if component_info:
         url = "{0}/accounts/{1}/cmpcatalog".format(self.client.base_url,
                                                    self.account.id)
         data = json.dumps(component_info)
         resp = requests.post(url, data=data, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         check(resp, 201)
         js = resp.json()
         return js
     else:
         raise ValueError("No component info given.")
Exemplo n.º 14
0
 def send_data(self, dataSeries):
     url = "{0}/data/{1}".format(self.client.base_url, self.device_id)
     payload = {
         "on": time.time(),
         "accountId": self.account_id,
         "data": dataSeries
     }
     data = json.dumps(payload)
     resp = requests.post(url, data=data, headers=get_auth_headers(
         self.device_token), proxies=self.client.proxies, verify=globals.g_verify)
     check(resp, 201)
     return resp.text
Exemplo n.º 15
0
 def update_device(self, device_info, device_id=None):
     if not device_id:
         device_id = self.device_id
     url = "{0}/accounts/{1}/devices/{2}".format(
         self.client.base_url, self.account_id, device_id)
     data = json.dumps(device_info)
     resp = requests.put(url, data=data, headers=get_auth_headers(
         self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
     check(resp, 200)
     js = resp.json()
     self.info = js
     return js
Exemplo n.º 16
0
 def delete_device(self, device_id=None):
     if not device_id:
         device_id = self.device_id
     if device_id:
         url = "{0}/accounts/{1}/devices/{2}".format(
             self.client.base_url, self.account_id, device_id)
         resp = requests.delete(url, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         check(resp, 204)
         self.device_id = None
         self.info = None
     else:
         raise ValueError("No active device selected.")
Exemplo n.º 17
0
 def activate_new_device(self, activation_code):
     url = "{0}/accounts/{1}/devices/{2}/activation".format(
         self.client.base_url, self.account_id, self.device_id)
     activation = {
         "activationCode": activation_code
     }
     data = json.dumps(activation)
     resp = requests.put(url, data=data, headers=get_auth_headers(
         self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
     check(resp, 200)
     js = resp.json()
     self.device_token = js["deviceToken"]
     return self.device_token
Exemplo n.º 18
0
def verify_restservice(url):
    """To verify that the REST service is working, GET the blueprints list.

    There's nothing special about the blueprints endpoint, it's simply one
    that also requires the storage backend to be up, so if it works, there's
    a good chance everything is configured correctly.
    """
    blueprints_url = urlparse.urljoin(url, 'api/v2.1/blueprints')

    headers = utils.get_auth_headers(True)

    if utils.is_upgrade or utils.is_rollback:
        # if we're doing an upgrade, we're in maintenance mode - this request
        # is safe to perform in maintenance mode, so let's bypass the check
        headers = utils.create_maintenance_headers()
    else:
        headers = utils.get_auth_headers(True)

    req = urllib2.Request(blueprints_url, headers=headers)

    try:
        response = urllib2.urlopen(req)
    except urllib2.URLError as e:
        ctx.abort_operation(
            'REST service returned an invalid response: {0}'.format(e))
    if response.code == 401:
        ctx.abort_operation('Could not connect to the REST service: '
                            '401 unauthorized. Possible access control '
                            'misconfiguration')
    if response.code != 200:
        ctx.abort_operation(
            'REST service returned an unexpected response: {0}'.format(
                response.code))

    try:
        json.load(response)
    except ValueError as e:
        ctx.abort_operation(
            'REST service returned malformed JSON: {0}'.format(e))
Exemplo n.º 19
0
def verify_restservice(url):
    """To verify that the REST service is working, GET the blueprints list.

    There's nothing special about the blueprints endpoint, it's simply one
    that also requires the storage backend to be up, so if it works, there's
    a good chance everything is configured correctly.
    """
    blueprints_url = urlparse.urljoin(url, 'api/v2.1/blueprints')

    headers = utils.get_auth_headers(True)

    if utils.is_upgrade or utils.is_rollback:
        # if we're doing an upgrade, we're in maintenance mode - this request
        # is safe to perform in maintenance mode, so let's bypass the check
        headers = utils.create_maintenance_headers()
    else:
        headers = utils.get_auth_headers(True)

    req = urllib2.Request(blueprints_url, headers=headers)

    try:
        response = urllib2.urlopen(req)
    except urllib2.URLError as e:
        ctx.abort_operation('REST service returned an invalid response: {0}'
                            .format(e))
    if response.code == 401:
        ctx.abort_operation('Could not connect to the REST service: '
                            '401 unauthorized. Possible access control '
                            'misconfiguration')
    if response.code != 200:
        ctx.abort_operation('REST service returned an unexpected response: {0}'
                            .format(response.code))

    try:
        json.load(response)
    except ValueError as e:
        ctx.abort_operation('REST service returned malformed JSON: {0}'
                            .format(e))
Exemplo n.º 20
0
 def get_comp_type(self, component_id):
     if component_id:
         url = "{0}/accounts/{1}/cmpcatalog/{2}".format(self.client.base_url,
                                                        self.account.id,
                                                        component_id)
         resp = requests.get(url, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         #check(resp, 200)
         if resp.status_code == 404:
             return None
         js = resp.json()
         return js
     else:
         raise ValueError("No component ID given.")
Exemplo n.º 21
0
 def accept_invite(self, email):
     if email:
         url = "{0}/invites/{1}/status".format(
             self.client.base_url, email)
         payload = {
             "accept": True
         }
         data = json.dumps(dict(payload))
         resp = requests.put(url, data=data, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         check(resp, 200)
         js = resp.json()
         return js
     else:
         raise ValueError("No email provided.")
Exemplo n.º 22
0
 def change_password(self, username, oldpassword, newpassword):
     if username and oldpassword and newpassword:
         # given a user_id, get the user's info
         url = "{0}/users/{1}/change_password".format(
             globals.base_url, username)
         payload = {
             "currentpwd": oldpassword,
             "password": newpassword
         }
         data = json.dumps(payload)
         resp = requests.put(url, data=data, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         check(resp, 200)
     else:
         raise ValueError("No username, old or new password given.")
     return None
Exemplo n.º 23
0
 def create_device(self, device_info, activate=False):
     if device_info:
         url = "{0}/accounts/{1}/devices".format(
             self.client.base_url, self.account_id)
         data = json.dumps(device_info)
         resp = requests.post(url, data=data, headers=get_auth_headers(
             self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
         check(resp, 201)
         js = resp.json()
         self.device_id = js["deviceId"]
         self.info = js
         if activate:
             activation_code = self.account.renew_activation_code()
             self.activate_new_device(activation_code)
         return js
     else:
         raise ValueError("No account name given.")
Exemplo n.º 24
0
    def create_account(self, account_name):
        """ Create a new account.

            Args:
            account_name (str): alias/name for account

            Returns:
            JSON message containing account attributes.
            Example:
                {
                    "name":"AccountName",
                    "healthTimePeriod":86400,
                    "created":1406919627586,
                    "updated":1406919627586,
                    "exec_interval":300,
                    "base_line_exec_interval":86400,
                    "cd_model_frequency":604800,
                    "cd_execution_frequency":600,
                    "data_retention":0,
                    "id":"321ef007-8449-477f-9ea0-d702d77e64b9"
                }

        """

        if account_name:
            url = "{0}/accounts".format(globals.base_url)
            payload = {"name": account_name}
            data = json.dumps(payload)
            resp = requests.post(url,
                                 data=data,
                                 headers=get_auth_headers(
                                     self.client.user_token),
                                 proxies=self.client.proxies,
                                 verify=globals.g_verify)
            check(resp, 201)
            js = resp.json()
            self.id = js["id"]
            #update_properties(self, js)  # save account properties
            self.info = js
            return js
        else:
            raise ValueError("No account name given.")
Exemplo n.º 25
0
    def delete_account(self, account_id):
        """ Delete account with given account ID

            Args:
            account_id (str): account ID of account to delete

            Returns:
            No value is returned. A ValueError will be thrown if the device ID is invalid

        """
        if account_id:
            url = "{0}/accounts/{1}".format(globals.base_url, account_id)
            resp = requests.delete(url,
                                   headers=get_auth_headers(
                                       self.client.user_token),
                                   proxies=self.client.proxies,
                                   verify=globals.g_verify)
            check(resp, 204)
        else:
            raise ValueError("Invalid account ID.")
Exemplo n.º 26
0
    def renew_activation_code(self):
        """ Return new activation code

        Returns:
        JSON message containing activation code and expiration time.
        Example,
            {
                "activationCode": "5nLyMJrh",
                "timeLeft": 1424731140
            }

        """
        url = "{0}/accounts/{1}/activationcode/refresh".format(
            globals.base_url, self.id)
        resp = requests.put(url,
                            headers=get_auth_headers(self.client.user_token),
                            proxies=self.client.proxies,
                            verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        return js["activationCode"]
Exemplo n.º 27
0
def verify_restservice(url):
    """To verify that the REST service is working, GET the blueprints list.

    There's nothing special about the blueprints endpoint, it's simply one
    that also requires the storage backend to be up, so if it works, there's
    a good chance everything is configured correctly.
    """
    security_config = runtime_props['security_configuration']
    headers = utils.get_auth_headers(
        username=security_config['admin_username'],
        password=security_config['admin_password'])

    utils.verify_service_http(SERVICE_NAME, url, headers=headers)

    blueprints_url = urlparse.urljoin(url, 'api/v2.1/blueprints')
    req = urllib2.Request(blueprints_url, headers=headers)

    try:
        response = urllib2.urlopen(req)
    # keep an erroneous HTTP response to examine its status code, but still
    # abort on fatal errors like being unable to connect at all
    except urllib2.HTTPError as e:
        response = e
    except urllib2.URLError as e:
        ctx.abort_operation(
            'REST service returned an invalid response: {0}'.format(e))
    if response.code == 401:
        ctx.abort_operation('Could not connect to the REST service: '
                            '401 unauthorized. Possible access control '
                            'misconfiguration')
    if response.code != 200:
        ctx.abort_operation(
            'REST service returned an unexpected response: {0}'.format(
                response.code))

    try:
        json.load(response)
    except ValueError as e:
        ctx.abort_operation(
            'REST service returned malformed JSON: {0}'.format(e))
Exemplo n.º 28
0
    def get_account(self, account_name, account_id=None):
        """ Look up account attributes for a given account and load instance
            attributes with returned values

            Args:
            account_name (str): alias/name of account to lookup (first match will be returned)
            account_id (str): use account ID (GUID) of account to help match

            Returns:
            account ID (str): Account ID (GUID) or matching account

        """

        if account_name:
            # given a user_id, get the account_id of the associated account with account_name
            # if there are multiple accounts with the same name, return one of
            # them
            url = "{0}/users/{1}".format(globals.base_url, self.client.user_id)
            resp = requests.get(url,
                                headers=get_auth_headers(
                                    self.client.user_token),
                                proxies=self.client.proxies,
                                verify=globals.g_verify)
            check(resp, 200)
            js = resp.json()
            if 'accounts' in js:
                accounts = js["accounts"]
                for key, value in accounts.iteritems():
                    if 'name' in value and value["name"] == account_name:
                        # if account_id is given, verify its value also
                        if account_id and account_id == key or not account_id:
                            self.id = key
                            return self.id
            msg = "Account name {0} not found.".format(account_name)
            msg = msg + "Available accounts are: {0}".format(
                [value["name"] for key, value in accounts.iteritems()])
            raise ValueError(msg)
        else:
            raise ValueError("No account name given.")
Exemplo n.º 29
0
    def get_activation_code(self):
        """ Return previous activation code if it is still valid

        Returns:
        JSON message containing activation code and expiration time.
        Values will be "None" if the code has expired.
        Example,
            {
                "activationCode": "5nLyMJrh",
                "timeLeft": 1424731140
            }

        """
        url = "{0}/accounts/{1}/activationcode".format(globals.base_url,
                                                       self.id)
        resp = requests.get(url,
                            headers=get_auth_headers(self.client.user_token),
                            proxies=self.client.proxies,
                            verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        return js["activationCode"]
Exemplo n.º 30
0
    def get_info(self):
        """ Return account attributes for a given account.

            Args:
            account_name (str): alias/name of account to lookup (first match will be returned)
            account_id (str): use account ID (GUID) of account to help match

            Returns:
            JSON message containing account information.
            Example:
                {
                    "name": "AccountName",
                    "healthTimePeriod": 86400,
                    "created": 1404415261310,
                    "updated": 1404415261310,
                    "exec_interval": 120,
                    "base_line_exec_interval": 86400,
                    "cd_model_frequency": 604800,
                    "cd_execution_frequency": 600,
                    "data_retention": 0,
                    "attributes":{
                        "phone":"123456789",
                        "another_attribute":"another_value"
                    },
                    "id": "321ef007-8449-477f-9ea0-d702d77e64b9"
                }

        """

        url = "{0}/accounts/{1}".format(globals.base_url, self.id)
        resp = requests.get(url,
                            headers=get_auth_headers(self.client.user_token),
                            proxies=self.client.proxies,
                            verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        #update_properties(self, js)  # save account properties
        self.info = js
        return js
Exemplo n.º 31
0
    def get_devices(self):
        """ List all users associated with this account

            Returns:
            A list of device-attribute JSON messages
            Example,
                [
                    {
                        "attributes": {
                            "agent_version": "1.5.1",
                            "hardware_vendor": "Genuine Intel(R) CPU   4000  @  500MHz",
                            "hardware_model": "linux",
                            "Model Name": "ia32",
                            "Firmware Version": "3.10.17-poky-edison+"
                        },
                        "created": 1424713173378,
                        "components": [
                            {
                                "name": "temp",
                                "type": "temperature.v1.0",
                                "cid": "f4f942c1-7d6f-4771-bbd4-9cfa9717ba5a"
                            }
                        ],
                        "deviceId": "jumbo-edison",
                        "gatewayId": "jumbo-edison",
                        "name": "jumbo-edison-NAME",
                        "status": "active"
                    }
                ]

        """
        url = "{0}/accounts/{1}/devices".format(
            self.client.base_url, self.account_id)
        resp = requests.get(url, headers=get_auth_headers(
            self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
        check(resp, 200)
        js = resp.json()
        return js
Exemplo n.º 32
0
ctx.download_resource(
    join('components', 'utils.py'),
    join(dirname(__file__), 'utils.py'))
import utils  # NOQA

NGINX_SERVICE_NAME = 'nginx'


def check_response(response):
    """Check if the response looks like a correct REST service response.

    We can get a 200, or a 401 in case auth is enabled. We don't expect a
    502, though, as this would mean nginx isn't correctly proxying to
    the REST service.
    """
    return response.code in {200, 401}


utils.start_service(NGINX_SERVICE_NAME, append_prefix=False)
utils.systemd.verify_alive(NGINX_SERVICE_NAME, append_prefix=False)

nginx_url = 'http://127.0.0.1/api/v2.1/blueprints'

if utils.is_upgrade or utils.is_rollback:
    headers = utils.create_maintenance_headers()
else:
    headers = utils.get_auth_headers(True)

utils.verify_service_http(NGINX_SERVICE_NAME, nginx_url, check_response,
                          headers=headers)
Exemplo n.º 33
0
 def delete_user(self, user_id):
     # Get the user's info
     url = "{0}/users/{1}".format(globals.base_url, user_id)
     resp = requests.delete(url, headers=get_auth_headers(
         self.client.user_token), proxies=self.client.proxies, verify=globals.g_verify)
     check(resp, 204)
Exemplo n.º 34
0
    def search_data(self, time0, time1, devices, components, csv=None):
        """ Retrieve data for a list of devices and components in a
            given time period.

            Args:
            time0 (int): beginning time
            time1 (int): ending time (None = current timestamp)
            devices (list of strings): list of devices IDs to return data for
            components (list of strings): list of component IDs to return data for
            csv (bool): return results in JSON or CSV format

            Returns:
            JSON or CSV message
                {
                    "from": 1234567890,
                    "to": 1234567890,
                    "maxPoints": 100,
                    "series": [
                        {
                            "deviceId": "D1",
                            "deviceName": "D1",
                            "componentId": "e3a48caa-e4c5-46bb-951e-8f9d0a4be516",
                            "componentName": "temp",
                            "componentType": "temperature.v1.0",
                            "points": [
                                {"ts":9874569871, "value":25},
                                {"ts":9874569899, "value":24}
                            ]
                        },
                        {
                            "deviceId": "D2",
                            "deviceName": "D2",
                            "componentId": "76a95112-2159-4ee6-8e91-6a69b9c51edc",
                            "componentName": "Humidity 1",
                            "componentType": "humidity.v1.0",
                            "points": [
                                {"ts":9874569871,"value":"55"},
                                {"ts":9874569899,"value":"65"}
                            ]
                        }
                    ]
                }

        """

        url = "{0}/accounts/{1}/data/search".format(globals.base_url, self.id)
        if csv:
            url = url + "?output=csv"
        payload = {
            "from": time0,
            "targetFilter": {
                "deviceList": devices
            },
            "metrics": []
        }
        if time1:
            payload["to"] = time1
        for c in components:
            payload["metrics"].append({"id": c, "op": "none"})
        payload["targetFilter"]["deviceList"] = devices
        data = json.dumps(payload)
        resp = requests.post(url,
                             data=data,
                             headers=get_auth_headers(self.client.user_token),
                             proxies=self.client.proxies,
                             verify=globals.g_verify)
        check(resp, 200)
        if csv:
            return resp.text
        else:
            js = resp.json()
            return js["series"]