Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"TypeError: 'NoneType' object is not subscriptable" for Android devices #50

Closed
cmilando opened this issue Jun 30, 2020 · 18 comments · Fixed by #58
Closed

"TypeError: 'NoneType' object is not subscriptable" for Android devices #50

cmilando opened this issue Jun 30, 2020 · 18 comments · Fixed by #58
Assignees
Labels
bug Bugs or issues which will cause a problem for users invalid Marks a PR or issue that is missing information

Comments

@cmilando
Copy link

Hi @bachya,
Thanks so much for this helpful app. I'm trying to get set up to use it in a research study, but am having trouble getting off the ground.

When trying to run your example code, i get the following response:

{"version":1,"revision":1,"timestamp":"2020-06-30T13:16:15.732Z","timestamp_ms":1593522975732,"result_code":0,"result":{"message":"invalid app version, version=null, app_id=null"}}

Seems like DEFAULT_APP_VERSION is hard-coded in client.py? Admittedly an api novice, so any help is greatly appreciated

@issuelabeler issuelabeler bot added the invalid Marks a PR or issue that is missing information label Jun 30, 2020
@bachya bachya added bug Bugs or issues which will cause a problem for users and removed invalid Marks a PR or issue that is missing information labels Jun 30, 2020
@bachya
Copy link
Owner

bachya commented Jul 3, 2020

@cmilando I've not seen that before – do you use the iOS or Android app?

@cmilando
Copy link
Author

cmilando commented Jul 4, 2020

@bachya We're using iOS, and just updated the iphone software and refreshed the TILE app.

@bachya
Copy link
Owner

bachya commented Jul 5, 2020

Hmm, I'm using iOS as well and when I run the example, I get all the expected info back. I wonder if in the background, Tile's cloud is somehow matching your account to an "expected" version of the app.

We'll need to see what the traffic looks like as your phone talks to the Tile app. How familiar are you with sniffing HTTP traffic (using something like Charles, Fiddler, etc.)?

@cmilando
Copy link
Author

cmilando commented Jul 6, 2020

I'm not familiar with that technique, but happy to follow your suggestions.

In addition to that, is there some version of "turn it off and turn it on again" that maybe I can try first? I turned on background app refresh and updated the phone to start. Perhaps I should try with the dev version of pytile rather than the pip version? Again happy to follow your lead

@bachya
Copy link
Owner

bachya commented Jul 6, 2020

@cmilando I don't think so – if the app wasn't working at all, I don't think we'd see that particular error. That said, two things to rule out:

  1. Try deleting and reinstalling the iOS app.
  2. Try using the dev branch of pytile, as you suggest.

If those don't work, let me know and I'll walk you through traffic sniffing 101. 👍

@cmilando
Copy link
Author

cmilando commented Jul 9, 2020

Hi @bachya just a quick update that 1) didn't work, trying to install dev branch now

@cmilando
Copy link
Author

hi @bachya, sorry for the delay, I've tried the dev branch, and on several TILE accounts, with no avail (getting the same error see below). I've also used multiple environments (jupyter notebook via Anaconda, Pycharm), and just installed pytile again following the recent push.

Error requesting data from users/XXXXXXX/user_tiles: 401, message='Unauthorized', url=URL('https://production.tile-api.com/api/v1/users/XXXXXXXXX/user_tiles')

then going to that url gives the same error as above:
{"version":1,"revision":1,"timestamp":"2020-07-31T00:15:07.520Z","timestamp_ms":1596154507520,"result_code":0,"result":{"message":"invalid app version, version=null, app_id=null"}}

Ready for the 101 if you are open to it! Or any other advice of course.

@bachya
Copy link
Owner

bachya commented Aug 6, 2020

@cmilando Depending on your OS, there are several apps that you can use to sniff traffic; I happen to like Charles Proxy the best, so that's what I'll use for my instructions (note that you can get a free trial before having to buy).

In general, what you'll be doing is using Charles on your computer as a proxy between the Tile app on your phone and Tile's cloud. Charles will record the requests/responses in sequence, which will allow us to see what's going on. Note that this traffic sniffing will contain sensitive information, like username/password, tokens, etc. So, it's crucial to make sure you redact sensitive info before posting anything here.

Charles' documentation is the place to start; it will guide you from start to finish. Pay particular attention to the SSL Proxying section: because the Tile app communicates with the Tile cloud via HTTPS, you'll need to follow the instructions here to properly decrypt that traffic (otherwise, you won't be able to see the data).

Take a spin through all this and let's see how you get on. If this ends up being too much or something you don't want to do, another (possibly bad) option is for you to email me your Tile credentials, I do the sniffing, then as soon as I'm done, I let you know and you can recycle those credentials. Totally up to you and I respect if that isn't something you want to do.

Let me know!

@cmilando
Copy link
Author

cmilando commented Aug 7, 2020

@bachya thanks for this -- will try and get back to you

@stale
Copy link

stale bot commented Sep 9, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Sep 9, 2020
@cmilando
Copy link
Author

@bachya so I finally got this to work, through the normal channels, with some caveats:

  • had to update to python 3.8(.3) rather than 3.7(.7) which I had been running and where asynio.run() was failing
  • it seems like some non-iOS devices throw an error in the await api.async_get_tiles() function (e.g., divide by zero) during the initialization of the Tile class object, but the line states = await self.async_request("get", "tiles/tile_states") in the api object works, however the latitude and longitude for those non-iOS devices is clearly wrong (e.g., -90, -180). So might be prudent to add some tryCatch there.

But thanks again for your responsiveness, and this app!

@bachya
Copy link
Owner

bachya commented Sep 11, 2020

Thanks for posting, @cmilando. Can you show me an example of the invalid data that you've found? That'll help me catch it appropriately. Thanks!

@cmilando
Copy link
Author

cmilando commented Sep 11, 2020

This is the code (sanitized)

import asyncio
import pprint
from aiohttp import ClientSession
from pytile import async_login
from pytile.errors import TileError

pp = pprint.PrettyPrinter(indent=2)

async def main():  
    async with ClientSession() as session:

        try:
            api = await async_login("<USER.NAME>", "<PASSWORD>", session)

            print(api)

            states = await api.async_request("get", "tiles/tile_states")

            pp.pprint(states)

            tiles = await api.async_get_tiles()
            print(f"Tile Count: {len(tiles)}")

        except TileError as err:
            print(err)

asyncio.run(main())

The states output looks like

{ 'result': [ { 'location': { 'client_name': None,
                              'horizontal_accuracy': xx.xxxx,
                              'latitude': xx.xxxx,
                              'location_timestamp': xxxxxxxxx,
                              'longitude': xx.xxxxxxxxxx},
                'mark_as_lost': {'is_lost': False, 'timestamp': -1},
                'tile_id': 'xxxxxxxxxxxxxxxxxxxx'},
              { 'location': { 'client_name': None,
                              'horizontal_accuracy': xx.x,
                              'latitude': -90.1,
                              'location_timestamp': xxxxxxxxxxxxxxxxxxxx,
                              'longitude': -180.1},
                'mark_as_lost': {'is_lost': False, 'timestamp': -1},
                'tile_id': 'p!xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'}],
  'result_code': 0,
  'revision': 1,
  'timestamp': '2020-09-11T15:15:01.131Z',
  'timestamp_ms': xxxxxxxxxxxxxxx,

And here is the error that comes when the tiles = await api.async_get_tiles() line is run

Traceback (most recent call last):
  File "<input>", line 29, in <module>
  File "C:\Python\Python38\lib\asyncio\runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
    return future.result()
  File "<input>", line 13, in main
  File "C:\XXXX\XXXX\tile_devices\lib\site-packages\pytile\api.py", line 57, in async_get_tiles
    return {
  File "C:\XXXX\XXXX\tile_devices\lib\site-packages\pytile\api.py", line 58, in <dictcomp>
    tile_uuid: Tile(self.async_request, tile_data["result"])
  File "C:\XXXX\XXXX\tile_devices\lib\site-packages\pytile\tile.py", line 18, in __init__
    tile_data["last_tile_state"]["timestamp"] / 1000
TypeError: 'NoneType' object is not subscriptable

@bachya
Copy link
Owner

bachya commented Sep 11, 2020

Thanks, @cmilando. That shows that the "get tile list" call is working, but the "get tile details" is throwing an exception. I need a bit more info to diagnose. I just pushed an updated examples/test_api.py to the dev branch. Can you change to debug-level logging on line 18:

logging.basicConfig(level=logging.DEBUG)

...and post the (scrubbed of sensitive output)? Thanks!

@cmilando
Copy link
Author

Hopefully this is it?

DEBUG:pytile.api:Data received from /clients/XXXXXX-XXXX-XXXX-XXXXXX:{
   'version':1,
   'revision':1,
   'timestamp':'2020-09-11T16:38:06.018Z',
   'timestamp_ms':1599842286018,
   'result_code':0,
   'result':{
      'locale':'en-US',
      'entityName':'CLIENT',
      'client_uuid':'XXXXXX-XXXX-XXXX-XXXXXX',
      'app_id':'ios-tile-production',
      'app_version':'2.69.0.4123',
      'os_name':None,
      'os_release':None,
      'model':None,
      'signed_in_user_uuid':None,
      'registration_timestamp':1599842285999,
      'user_device_name':None,
      'beta_option':False,
      'last_modified_timestamp':1599842285999
   }
}DEBUG:pytile.api:Data received from /clients/XXXXXX-XXXX-XXXX-XXXXXX/sessions:{
   'version':1,
   'revision':1,
   'timestamp':'2020-09-11T16:38:06.062Z',
   'timestamp_ms':1599842286062,
   'result_code':0,
   'result':{
      'client_uuid':'XXXXXX-XXXX-XXXX-XXXXXX',
      'user':{
         'user_uuid':'XXXXXX-XXXX-XXXX-XXXXXX',
         'full_name':None,
         'email':'XXXXX@email.com',
         'beta_eligibility':False,
         'gift_recipient':False,
         'locale':'es-US',
         'email_shared':True,
         'image_url':None,
         'status':'ACTIVATED',
         'pw_exists':True,
         'registration_timestamp':1595458231851,
         'linked_accounts':[
            
         ],
         'shipping_address_timestamp':None,
         'last_modified_timestamp':1599757799215
      },
      'session_start_timestamp':1599842286055,
      'session_expiration_timestamp':1599863886055,
      'changes':'EXISTING_ACCOUNT'
   }
}DEBUG:pytile.api:Data received from /tiles/tile_states:{
   'version':1,
   'revision':1,
   'timestamp':'2020-09-11T16:38:06.095Z',
   'timestamp_ms':1599842286095,
   'result_code':0,
   'result':[
      {
         'location':{
            'latitude':XX.XXXX,
            'longitude':-XX.XXXX,
            'location_timestamp':1599828864858,
            'horizontal_accuracy':48.007248,
            'client_name':None
         },
         'tile_id':'XXXXXXXXXXXXX',
         'mark_as_lost':{
            'timestamp':-1,
            'is_lost':False
         }
      },
      {
         'location':{
            'latitude':-90.1,
            'longitude':-180.1,
            'location_timestamp':1597364056723,
            'horizontal_accuracy':25.0,
            'client_name':None
         },
         'tile_id':'p!XXXXXXXXXXXXXXX',
         'mark_as_lost':{
            'timestamp':-1,
            'is_lost':False
         }
      }
   ]
}DEBUG:pytile.api:Data received from /tiles/XXXXXXXXXXXXX:{
   'version':1,
   'revision':1,
   'timestamp':'2020-09-11T16:38:06.132Z',
   'timestamp_ms':1599842286132,
   'result_code':0,
   'result':{
      'group':None,
      'parents':[
         
      ],
      'user_node_relationships':None,
      'owner_user_uuid':'XXXXXX-XXXX-XXXX-XXXXXX',
      'node_type':None,
      'name':'XXXXXXX',
      'description':None,
      'image_url':None,
      'product':'MORRO1',
      'archetype':'PURSE',
      'visible':True,
      'user_node_data':{
         
      },
      'permissions_mask':None,
      'tile_uuid':'XXXXXXXXXXXXX',
      'firmware_version':'26.04.02.0',
      'category':None,
      'superseded_tile_uuid':None,
      'is_dead':False,
      'hw_version':'12.03',
      'configuration':{
         'fw10_advertising_interval':None
      },
      'last_tile_state':{
         'uuid':'XXXXXXXXXXXXX',
         'connectionStateCode':0,
         'ringStateCode':0,
         'tile_uuid':'XXXXXXXXXXXXX',
         'client_uuid':'XXXXXX-XXXX-XXXX-XXX-XXXX',
         'timestamp':1599828864858,
         'advertised_rssi':-78.0,
         'client_rssi':0.0,
         'battery_level':0.0,
         'latitude':XX.xxxxxx,
         'longitude':-XX.xxxxx,
         'altitude':8.220993150608749,
         'raw_h_accuracy':48.007248,
         'v_accuracy':3.0,
         'speed':0.0,
         'course':None,
         'authentication':None,
         'owned':False,
         'has_authentication':None,
         'lost_timestamp':-1,
         'connection_client_uuid':None,
         'connection_event_timestamp':0,
         'last_owner_update':0,
         'partner_id':None,
         'partner_client_id':None,
         'speed_accuracy':None,
         'course_accuracy':None,
         'discovery_timestamp':1599828879210,
         'connection_state':'DISCONNECTED',
         'ring_state':'STOPPED',
         'is_lost':False,
         'h_accuracy':48.007248,
         'voip_state':'OFFLINE'
      },
      'firmware':{
         'expected_firmware_version':'26.04.02.0',
         'expected_firmware_imagename':'Tile_FW_Image_26.04.02.0.bin',
         'expected_firmware_urlprefix':'https://s3.amazonaws.com/tile-tofu-fw/prod/',
         'expected_firmware_publish_date':1574812800000,
         'expected_ppm':None,
         'expected_advertising_interval':6400,
         'security_level':1,
         'expiry_timestamp':1599863886130,
         'expected_tdt_cmd_config':'XXXXXXX'
      },
      'auth_key':'XXXXXXXXXXXXX',
      'renewal_status':'NONE',
      'metadata':{
         'battery_state':'10'
      },
      'battery_status':'NONE',
      'serial_number':None,
      'auto_retile':False,
      'all_user_node_relationships':None,
      'tile_type':'TILE',
      'is_lost':False,
      'auth_timestamp':1597364228155,
      'registration_timestamp':1597364228155,
      'status':'ACTIVATED',
      'activation_timestamp':1597364228742,
      'thumbnail_image':None,
      'last_modified_timestamp':1597467604853
   }
}DEBUG:pytile.api:Data received from /tiles/p!XXXXXXXXXXXXXXX:{
   'version':1,
   'revision':1,
   'timestamp':'2020-09-11T16:38:06.224Z',
   'timestamp_ms':1599842286224,
   'result_code':0,
   'result':{
      'group':None,
      'parents':[
         
      ],
      'user_node_relationships':None,
      'owner_user_uuid':'XXXXXX-XXXX-XXXX-XXXXXX',
      'node_type':None,
      'name':'XXXXXXXXX',
      'description':None,
      'image_url':None,
      'product':'PHONE',
      'archetype':'PHONE',
      'visible':True,
      'user_node_data':{
         
      },
      'permissions_mask':None,
      'tile_uuid':'p!XXXXXXXXXXXXXXX',
      'firmware_version':'1.0',
      'category':None,
      'superseded_tile_uuid':None,
      'is_dead':False,
      'hw_version':None,
      'configuration':{
         'fw10_advertising_interval':None
      },
      'last_tile_state':None,
      'firmware':None,
      'auth_key':None,
      'renewal_status':'NONE',
      'metadata':{
         
      },
      'battery_status':'NONE',
      'serial_number':None,
      'auto_retile':False,
      'all_user_node_relationships':None,
      'tile_type':'PHONE',
      'is_lost':False,
      'auth_timestamp':0,
      'registration_timestamp':1597364056723,
      'status':'ACTIVATED',
      'activation_timestamp':1597364058103,
      'thumbnail_image':None,
      'last_modified_timestamp':1597364058104
   }
}

Traceback (most recent call last):
  File "<input>", line 36, in <module>
  File "C:\Python\Python38\lib\asyncio\runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
    return future.result()
  File "<input>", line 23, in main
  File "C:\xxxx\xxxxx\PycharmProjects\xxx\tile_devices\venv\lib\site-packages\pytile\api.py", line 57, in async_get_tiles
    return {
  File "C:\xxxx\xxxxx\PycharmProjects\xxxx\tile_devices\venv\lib\site-packages\pytile\api.py", line 58, in <dictcomp>
    tile_uuid: Tile(self.async_request, tile_data["result"])
  File "C:\xxx\xxxxx\PycharmProjects\xxxxx\tile_devices\venv\lib\site-packages\pytile\tile.py", line 18, in __init__
    tile_data["last_tile_state"]["timestamp"] / 1000
TypeError: 'NoneType' object is not subscriptable

@bachya
Copy link
Owner

bachya commented Sep 11, 2020

@cmilando Very helpful! The "problem" appears to be that last child (with a redacted ID of p!XXXXXXXXXXXXXXX): it has a last_tile_state value of None. I've never seen that before. Can you tell me more about this particular Tile? What type, is it still active, etc.

@cmilando
Copy link
Author

@bachya yes, still active, however, as you can see, there is some issue with the location that is being recorded. This Tile device is actually a Samsung Galaxy J7 Star (I'm sure you've seen this but ids beginning with p! indicate phones and are longer strings, whereas shorter strings with no p! prefix are Tile devices). So this is for the case where the TILE app is monitoring the phone's location, as well as the Tile's.

@bachya
Copy link
Owner

bachya commented Sep 11, 2020

Fascinating. As you alluded to previously, there must be some difference between iOS and Android: my iPhone shows that information.

At any rate, I can add appropriate logic to catch this and handle the exception. Thanks for your help!

@bachya bachya changed the title "invalid app version" when logging in "TypeError: 'NoneType' object is not subscriptable" for Android devices Sep 11, 2020
@bachya bachya removed the wontfix label Sep 11, 2020
@issuelabeler issuelabeler bot added the invalid Marks a PR or issue that is missing information label Sep 11, 2020
@bachya bachya self-assigned this Sep 11, 2020
@github-actions github-actions bot locked and limited conversation to collaborators Oct 31, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Bugs or issues which will cause a problem for users invalid Marks a PR or issue that is missing information
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants