# Path: allthingstalk/assets.py
# class Asset:
# 
#     SENSOR = 'sensor'
#     ACTUATOR = 'actuator'
#     CONFIG = 'config'
#     VIRTUAL = 'virtual'
# 
#     _PROFILE_CLASS = None
# 
#     def __init__(self, *, kind='sensor', name=None, title=None,
#                  description='', handler=None, profile=None, **kwargs):
#         """References the asset identified by name. The asset is created on the platform
#         if it doesn't already exist. If the asset is initialized from a device class,
#         it's default name is set to the member name referencing it.
# 
#         :param str kind: Asset kind: sensor, actuator, virtual or config
#         :param str name: Asset's name. If the asset is initialized from a device class, the name defaults to the name of the member referencing the asset, e.g. for ``my_asset = IntegerAsset()``, the integer asset's name will be set to ``'my_asset'``
#         :param str title: Asset's title. By default it gets set to capitalized name.
#         :param str description: Asset's description
#         :param Profile profile: Asset's profile. For default profiles, it's recommend to use Asset variants with preset profile, like IntegerAsset or StringAsset.
#         """
# 
#         self.id = None
#         self.thing_id = None
#         self.kind = kind if kind else 'sensor'
#         self.name = name
#         self._internal_id = name
#         self.title = title or name
#         self.description = description
#         self.handler = handler
#         if self.__class__._PROFILE_CLASS:
#             self.profile = self.__class__._PROFILE_CLASS(**kwargs)
#         elif profile is not None:
#             self.profile = profile
#         else:
#             raise exceptions.InvalidAssetProfileException()
#         if 'type' in self.profile:
#             self.type = self.profile['type']
# 
#     @staticmethod
#     def from_dict(d):
#         asset = Asset(
#             kind=d['is'],
#             name=d['name'],
#             title=d['title'],
#             description=d['description'],
#             profile=d['profile'])
#         asset.id = d['id']
#         asset.thing_id = d['deviceId']
#         return asset
# 
# Path: allthingstalk/asset_state.py
# class AssetState:
#     """AssetState is used instead of primitive state values (like ``2``, ``"a"``
#     or ``True``) when publishing data with a custom timestamp, i.e. not the
#     current timestamp at the time of publishing."""
# 
#     def __init__(self, value, at=None):
#         """Initializes the asset state.
# 
#         :param value: Any JSON-serializable value applicable to the given :class:`~allthingstalk.Asset`.
#         :param datetime.datetime at: Optional timestamp
#         """
# 
#         self.value = value
#         if at is None:
#             self.at = datetime.datetime.utcnow()
#         elif isinstance(at, str):
#             self.at = parse_date(at)
#         elif isinstance(at, datetime.datetime):
#             self.at = at
#         else:
#             raise ValueError('Invalid timestamp in at: %s' % at)
# 
#         if self.at.tzinfo is None:
#             self.at = self.at.replace(tzinfo=dateutil.tz.tzutc())
# 
#     def __repr__(self):
#         return 'AssetState(value=%s, at=%s)' % (self.value, self.at)
# 
#     def __str__(self):
#         return str(self.value)
# 
# Path: allthingstalk/exceptions.py
# class AssetStateRetrievalException(Exception):
#     """Asset state could not be retrieved."""
#     pass
# 
# class AccessForbiddenException(Exception):
#     """Access Forbidden."""
#     pass


import logging
import pkg_resources
import paho.mqtt.client as paho_mqtt
import requests
from .assets import Asset
from .asset_state import AssetState
from .exceptions import AssetStateRetrievalException, AccessForbiddenException
        :param str device_id: AllThingsTalk Device Identifier
        :return: Asset list returned by AllThingsTalk API.
        :rtype: list of Asset
        """

        r = requests.get('%s/device/%s/assets' % (self.http, device_id), headers=self._get_headers())
        if r.status_code == 403:
            raise AccessForbiddenException('Could not use token "%s" to access device "%s" on "%s".'
                                           % (self.token, device_id, self.http))
        return [Asset.from_dict(asset_dict) for asset_dict in r.json()]

    def create_asset(self, device_id, asset):
        """Creates a device asset.

        :param str device_id: AllThingsTalk Device Identifier
        :param Asset asset: The asset
        :return: The asset
        :rtype: Asset
        """

        attalk_asset = {
            'Name': asset.name,
            'Title': asset.title,
            'Description': asset.description,
            'Is': asset.kind,
            'Profile': asset.profile
        }
        asset_dict = requests.post('%s/device/%s/assets' % (self.http, device_id),
                                   headers=self._get_headers(),
                                   json=attalk_asset).json()

# Path: allthingstalk/assets.py
# class Asset:
# 
#     SENSOR = 'sensor'
#     ACTUATOR = 'actuator'
#     CONFIG = 'config'
#     VIRTUAL = 'virtual'
# 
#     _PROFILE_CLASS = None
# 
#     def __init__(self, *, kind='sensor', name=None, title=None,
#                  description='', handler=None, profile=None, **kwargs):
#         """References the asset identified by name. The asset is created on the platform
#         if it doesn't already exist. If the asset is initialized from a device class,
#         it's default name is set to the member name referencing it.
# 
#         :param str kind: Asset kind: sensor, actuator, virtual or config
#         :param str name: Asset's name. If the asset is initialized from a device class, the name defaults to the name of the member referencing the asset, e.g. for ``my_asset = IntegerAsset()``, the integer asset's name will be set to ``'my_asset'``
#         :param str title: Asset's title. By default it gets set to capitalized name.
#         :param str description: Asset's description
#         :param Profile profile: Asset's profile. For default profiles, it's recommend to use Asset variants with preset profile, like IntegerAsset or StringAsset.
#         """
# 
#         self.id = None
#         self.thing_id = None
#         self.kind = kind if kind else 'sensor'
#         self.name = name
#         self._internal_id = name
#         self.title = title or name
#         self.description = description
#         self.handler = handler
#         if self.__class__._PROFILE_CLASS:
#             self.profile = self.__class__._PROFILE_CLASS(**kwargs)
#         elif profile is not None:
#             self.profile = profile
#         else:
#             raise exceptions.InvalidAssetProfileException()
#         if 'type' in self.profile:
#             self.type = self.profile['type']
# 
#     @staticmethod
#     def from_dict(d):
#         asset = Asset(
#             kind=d['is'],
#             name=d['name'],
#             title=d['title'],
#             description=d['description'],
#             profile=d['profile'])
#         asset.id = d['id']
#         asset.thing_id = d['deviceId']
#         return asset
# 
# Path: allthingstalk/asset_state.py
# class AssetState:
#     """AssetState is used instead of primitive state values (like ``2``, ``"a"``
#     or ``True``) when publishing data with a custom timestamp, i.e. not the
#     current timestamp at the time of publishing."""
# 
#     def __init__(self, value, at=None):
#         """Initializes the asset state.
# 
#         :param value: Any JSON-serializable value applicable to the given :class:`~allthingstalk.Asset`.
#         :param datetime.datetime at: Optional timestamp
#         """
# 
#         self.value = value
#         if at is None:
#             self.at = datetime.datetime.utcnow()
#         elif isinstance(at, str):
#             self.at = parse_date(at)
#         elif isinstance(at, datetime.datetime):
#             self.at = at
#         else:
#             raise ValueError('Invalid timestamp in at: %s' % at)
# 
#         if self.at.tzinfo is None:
#             self.at = self.at.replace(tzinfo=dateutil.tz.tzutc())
# 
#     def __repr__(self):
#         return 'AssetState(value=%s, at=%s)' % (self.value, self.at)
# 
#     def __str__(self):
#         return str(self.value)
# 
# Path: allthingstalk/exceptions.py
# class AssetStateRetrievalException(Exception):
#     """Asset state could not be retrieved."""
#     pass
# 
# class AccessForbiddenException(Exception):
#     """Access Forbidden."""
#     pass


# Path: allthingstalk/clients.py
import logging
import pkg_resources
import paho.mqtt.client as paho_mqtt
import requests
from .assets import Asset
from .asset_state import AssetState
from .exceptions import AssetStateRetrievalException, AccessForbiddenException

        :param str device_id: AllThingsTalk Device Identifier
        :return: Asset list returned by AllThingsTalk API.
        :rtype: list of Asset
        """

        r = requests.get('%s/device/%s/assets' % (self.http, device_id), headers=self._get_headers())
        if r.status_code == 403:
            raise AccessForbiddenException('Could not use token "%s" to access device "%s" on "%s".'
                                           % (self.token, device_id, self.http))
        return [Asset.from_dict(asset_dict) for asset_dict in r.json()]

    def create_asset(self, device_id, asset):
        """Creates a device asset.

        :param str device_id: AllThingsTalk Device Identifier
        :param Asset asset: The asset
        :return: The asset
        :rtype: Asset
        """

        attalk_asset = {
            'Name': asset.name,
            'Title': asset.title,
            'Description': asset.description,
            'Is': asset.kind,
            'Profile': asset.profile
        }
        asset_dict = requests.post('%s/device/%s/assets' % (self.http, device_id),
                                   headers=self._get_headers(),
                                   json=attalk_asset).json()

        return Asset.from_dict(asset_dict)