diff --git a/README.rst b/README.rst
index c3d89da..61886c0 100644
--- a/README.rst
+++ b/README.rst
@@ -32,7 +32,7 @@ Carson Living Python should work against **Python 2.x >= 2.7** and **Python 3.x
 .. code-block::
 
     # Installing from PyPi
-    $ pip install carson-living
+    $ pip install carson_living
 
     # Installing latest development
     $ pip install \
diff --git a/carson_living/auth.py b/carson_living/auth.py
index 637035c..f719251 100644
--- a/carson_living/auth.py
+++ b/carson_living/auth.py
@@ -32,17 +32,35 @@ class CarsonAuth(object):
         _token: current JWT token
         _token_payload: current JWT token payload
         _token_expiration_time: current JWT token expiration time
+        _token_update_cb:
+            gets executed whenever the token gets update to a
+            non-None value.
     """
 
-    def __init__(self, username, password, token=None):
+    def __init__(self, username, password,
+                 initial_token=None, token_update_cb=None):
         self._username = username
         self._password = password
         self._token = None
         self._token_payload = None
         self._token_expiration_time = None
+        self._token_update_cb = None
 
         # Set and init token values
-        self.token = token
+        self.token = initial_token
+
+        # Set token updater after initial token (so it does not fire)
+        self._token_update_cb = token_update_cb
+
+    @property
+    def username(self):
+        """Username
+
+        Returns:
+            the configured username
+
+        """
+        return self._username
 
     @property
     def token(self):
@@ -88,6 +106,9 @@ class CarsonAuth(object):
             self._token_expiration_time = self._token_payload.get('exp')
 
             self._token = token
+
+            if self._token_update_cb is not None:
+                self._token_update_cb(token)
             _LOGGER.info('Set access Token for %s',
                          self._token_payload.get('email', '<no e-mail found>'))
         except InvalidTokenError:
@@ -101,7 +122,7 @@ class CarsonAuth(object):
             CarsonAuthenticationError: On authentication error.
 
         """
-        _LOGGER.info('Getting new access Token for %s', self._username)
+        _LOGGER.info('Getting new access token for %s', self._username)
 
         response = requests.post(
             (API_URI + AUTH_ENDPOINT),
@@ -114,7 +135,9 @@ class CarsonAuth(object):
         try:
             data = default_carson_response_handler(response)
             self.token = data.get('token')
+            return self.token
         except CarsonAPIError as error:
+            _LOGGER.warning('Authentication for %s failed', self._username)
             raise CarsonAuthenticationError(error)
 
     def valid_token(self):
diff --git a/carson_living/carson.py b/carson_living/carson.py
index b0e115f..06cd5dd 100644
--- a/carson_living/carson.py
+++ b/carson_living/carson.py
@@ -24,8 +24,10 @@ class Carson(CarsonAuth):
                 The building properties that are associated with
                 the current user
     """
-    def __init__(self, username, password, token=None):
-        super(Carson, self).__init__(username, password, token)
+    def __init__(self, username, password,
+                 initial_token=None, token_update_cb=None):
+        super(Carson, self).__init__(username, password,
+                                     initial_token, token_update_cb)
 
         self._user = None
         self._buildings = {}
diff --git a/pylintrc b/pylintrc
index bb0966a..31fbf82 100644
--- a/pylintrc
+++ b/pylintrc
@@ -23,3 +23,6 @@ disable=
 reports=no
 
 [EXCEPTIONS]
+
+[SIMILARITIES]
+ignore-imports=yes

CarsonAuth.update_token() should return token
Currently implementers that use manual authentication need to make two calls

```
auth = CarsonAuth(data["username"], data["password"])
auth.update_token()
return auth.token
```
diff --git a/tests/test_auth.py b/tests/test_auth.py
index 702edb0..91db067 100644
--- a/tests/test_auth.py
+++ b/tests/test_auth.py
@@ -4,6 +4,12 @@
 import unittest
 import requests_mock
 
+# 2.7 support fallback
+try:
+    from unittest.mock import Mock
+except ImportError:
+    from mock import Mock
+
 from carson_living import (CarsonAuth,
                            CarsonAPIError,
                            CarsonTokenError,
@@ -26,6 +32,8 @@ class TestCarsonAuth(unittest.TestCase):
     def test_auth_init(self):
         """Test default class initialization"""
         auth = CarsonAuth(USERNAME, PASSWORD)
+
+        self.assertEqual(auth.username, USERNAME)
         self.assertIsNone(auth.token)
         self.assertIsNone(auth.token_payload)
         self.assertIsNone(auth.token_expiration_date)
@@ -43,27 +51,40 @@ class TestCarsonAuth(unittest.TestCase):
         """Test default class initialization with token"""
         token, token_payload = get_encoded_token()
 
-        auth = CarsonAuth(USERNAME, PASSWORD, token)
+        mock_token_update_cb = Mock()
+
+        auth = CarsonAuth(USERNAME, PASSWORD, token, mock_token_update_cb)
+
+        self.assertEqual(auth.username, USERNAME)
         self.assertEqual(auth.token, token)
         self.assertEqual(auth.token_payload, token_payload)
         self.assertEqual(auth.token_expiration_date, token_payload.get('exp'))
         self.assertTrue(auth.valid_token())
 
+        # make sure that token update cb is not executed with an initial token.
+        mock_token_update_cb.assert_not_called()
+
     @requests_mock.Mocker()
     def test_update_token_success(self, mock):
         """Test token update"""
         mock.post('https://api.carson.live/api/v1.4.1/auth/login/',
                   text=load_fixture('carson.live', 'carson_login.json'))
 
-        auth = CarsonAuth(USERNAME, PASSWORD)
-        auth.update_token()
+        mock_token_update_cb = Mock()
+
+        auth = CarsonAuth(USERNAME, PASSWORD,
+                          token_update_cb=mock_token_update_cb)
+        token = auth.update_token()
 
+        self.assertEqual(auth.username, USERNAME)
+        self.assertEqual(FIXTURE_TOKEN, token)
         self.assertEqual(FIXTURE_TOKEN, auth.token)
         self.assertTrue(mock.called)
         self.assertEqual(USERNAME,
                          mock.last_request.json().get('username'))
         self.assertEqual(PASSWORD,
                          mock.last_request.json().get('password'))
+        mock_token_update_cb.assert_called_once_with(FIXTURE_TOKEN)
 
     @requests_mock.Mocker()
     def test_update_token_fail(self, mock):
diff --git a/tests/test_carson.py b/tests/test_carson.py
index a7aa944..0baf763 100644
--- a/tests/test_carson.py
+++ b/tests/test_carson.py
@@ -67,6 +67,13 @@ class TestCarson(CarsonUnitTestBase):
             self.c_mock_me['isService'],
             user.is_service)
 
+        self.assertIn(str(user.entity_id), str(user))
+        self.assertIn(user.first_name, str(user))
+        self.assertIn(user.last_name, str(user))
+
+        self.assertIn(user.unique_entity_id, repr(user))
+        self.assertIn("CarsonUser", repr(user))
+
     def test_api_buildings_initialization(self):
         """Test correct buildings entities after initialization"""
         buildings = self.carson.buildings
@@ -143,6 +150,18 @@ class TestCarson(CarsonUnitTestBase):
         self.assertIsNotNone(self.first_building.eagleeye_api)
         self.assertEqual(8, len(self.first_building.eagleeye_api.cameras))
 
+        self.assertIn(str(self.first_building.entity_id),
+                      str(self.first_building))
+        self.assertIn(self.first_building.name,
+                      str(self.first_building))
+        self.assertIn(self.first_building.pmc_name,
+                      str(self.first_building))
+
+        self.assertIn(self.first_building.unique_entity_id,
+                      repr(self.first_building))
+        self.assertIn("CarsonBuilding",
+                      repr(self.first_building))
+
     @requests_mock.Mocker()
     def test_later_carson_update_changes_entities(self, mock):
         """Later calling update changes the entities"""

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest requests_mock
apt-get update apt-get install -y gcc
3.9
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/rado0x54/python-carson-living.git@a9bb4f6595165acc6952e77c434f4581c4a26758#egg=carson_living
certifi==2025.1.31
charset-normalizer==3.4.1
exceptiongroup==1.2.2
idna==3.10
iniconfig==2.1.0
packaging==24.2
pluggy==1.5.0
PyJWT==2.10.1
pytest==8.3.5
requests==2.32.3
requests-mock==1.12.1
tomli==2.2.1
urllib3==2.3.0

name: python-carson-living
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - exceptiongroup==1.2.2
      - idna==3.10
      - iniconfig==2.1.0
      - packaging==24.2
      - pluggy==1.5.0
      - pyjwt==2.10.1
      - pytest==8.3.5
      - requests==2.32.3
      - requests-mock==1.12.1
      - tomli==2.2.1
      - urllib3==2.3.0
prefix: /opt/conda/envs/python-carson-living

tests/test_auth.py::TestCarsonAuth::test_auth_init
tests/test_auth.py::TestCarsonAuth::test_auth_valid_token_init tests/test_auth.py::TestCarsonAuth::test_expired_token_is_invalid tests/test_auth.py::TestCarsonAuth::test_raise_communication_error_on_empty tests/test_auth.py::TestCarsonAuth::test_raise_communication_error_wrong_json tests/test_auth.py::TestCarsonAuth::test_recursive_retry tests/test_auth.py::TestCarsonAuth::test_successful_query_with_initial_token tests/test_auth.py::TestCarsonAuth::test_successful_query_without_initial_token tests/test_auth.py::TestCarsonAuth::test_update_token_success tests/test_carson.py::TestCarson::test_api_buildings_initialization tests/test_carson.py::TestCarson::test_api_initialization tests/test_carson.py::TestCarson::test_api_user_initialization tests/test_carson.py::TestCarson::test_later_carson_update_changes_entities
tests/test_auth.py::TestCarsonAuth::test_auth_invalid_token_throws tests/test_auth.py::TestCarsonAuth::test_update_token_fail
README.rst pylintrc carson_living/carson.py carson_living/auth.py
README.rst pylintrc carson_living/carson.py carson_living/auth.py