hacf-fr / freebox-api

Manage your freebox in Python using the Freebox OS API
https://readthedocs.org/projects/freebox-api/
GNU General Public License v3.0
31 stars 17 forks source link

API calls on LAN, offline mode #52

Open SNoof85 opened 4 years ago

SNoof85 commented 4 years ago

Just made some testing because the way we are getting informations from the API needs a active internet connection (wich is more than stupid imo !) The API endpoint does exists on api_domain with SSL and a specified port. But when internet connection is down, we can't get anymore informations.

The API endpoint also exists in LAN on http://192.168.1.254 but without SSL...

Could we get an alternative to fetch datas from this endpoint ? Giving us some local polling instead of internet polling ?

foreign-sub commented 4 years ago

I can think of some ways to alleviate the problem, but i need more details on the usage scenario. Is it like you can't connect to the freebox when using open because the link is down and dns fails to resolve the api ssl adress. Or like you lose connection while you have an opened session and further request fails for some reason ? Also please detail which version you're using for testing (as a commit tag for ex). Anyway i'm thinking i could add some kind of struct which could contain multiple ways to contact a freebox as fallbacks if needed.

SNoof85 commented 4 years ago

Usage is to get informations from the API from a system in the Freebox LAN. When we fecth informations from the API SSL adress it needs an active internet connection because the system in the LAN uses this SSL API adress wich needs to be resolved by DNS. And this is resolved to the external IP of the freebox. I wan't to track the connection status of my freebox because i have many connections issues at this time, but each time my freebox goes back to Step 2 (synchro lost) i can't get any informations from the API. If i was using the LAN interface from the freebox to gather informations, even with no internet connection i could get the informations. No matter the version i use for testing, as in all versions the only way to get an API connection to the box uses SSL.

https://github.com/stilllman/aiofreepybox/blob/41d4905e81347293832078872ed26bcfd204a2ba/aiofreepybox/aiofreepybox.py#L249

https is hardoced here.

And here too : https://github.com/stilllman/aiofreepybox/blob/41d4905e81347293832078872ed26bcfd204a2ba/aiofreepybox/aiofreepybox.py#L75

On my dev setup i removed the ssl context from the aiohttp.TCPConnector and changed the https to http and i was able to use "192.168.1.254" on port 80 to get API informations. Whitout these modifications the connection can't be established on a non SSL endpoint.

On architecture point of view i don't know what's the best :

Last but not least an example to show how stupid it is to get datas from an internet API endpoint : image image Home Assistant was not able to detect the link down from API becaus ewhen the link is down, API doesn't answer and then Home Assistant ignore the not fetched informations. With local API endpoint the link down would have been seen !

I can think of some ways to alleviate the problem, but i need more details on the usage scenario. Is it like you can't connect to the freebox when using open because the link is down and dns fails to resolve the api ssl adress. Or like you lose connection while you have an opened session and further request fails for some reason ?

Both cases are valid, open a connection to API does not work when internet is down, and even when it's already opened if internet goes down call to API during link failure won't work. Situation is restored as soon as link goes up again !

foreign-sub commented 4 years ago

Usage is to get informations from the API from a system in the Freebox LAN. When we fecth informations from the API SSL adress it needs an active internet connection because the system in the LAN uses this SSL API adress wich needs to be resolved by DNS. And this is resolved to the external IP of the freebox.

ok so it's mostly the first case.

I wan't to track the connection status of my freebox because i have many connections issues at this time, but each time my freebox goes back to Step 2 (synchro lost) i can't get any informations from the API. If i was using the LAN interface from the freebox to gather informations, even with no internet connection i could get the informations.

HA is running, tries to sync, sends the info to afpbx which fails to resolve and errors out that it can't connect... hmmm

No matter the version i use for testing, as in all versions the only way to get an API connection to the box uses SSL.

https://github.com/stilllman/aiofreepybox/blob/41d4905e81347293832078872ed26bcfd204a2ba/aiofreepybox/aiofreepybox.py#L249

https is hardoced here.

And here too :

https://github.com/stilllman/aiofreepybox/blob/41d4905e81347293832078872ed26bcfd204a2ba/aiofreepybox/aiofreepybox.py#L75

On my dev setup i removed the ssl context from the aiohttp.TCPConnector and changed the https to http and i was able to use "192.168.1.254" on port 80 to get API informations. Whitout these modifications the connection can't be established on a non SSL endpoint.

Yeah it was, but not anymore, actually if you use the version available in #22 (the add-fbx-detect branch), it has a _DEFAULT_SSL flag that you can edit to False to force a non ssl link, but you still need to provide an ip adress otherwise it will try to resolve mafreebox.freebox.fr

On architecture point of view i don't know what's the best :

  • Get and alternative to use LAN non SSL endpoint OR WAN SSL endpoint (i would vote for this one !)
  • Use only LAN non SSL endpoint but this will kill the possibility to fetch datas from outside the LAN...

Both cases are valid, open a connection to API does not work when internet is down, and even when it's already opened if internet goes down call to API during link failure won't work. Situation is restored as soon as link goes up again !

If you're using the freebox dns, i guess the real issue here is on the shoulders of the freebox devs as in: "Freebox dns must return the freebox LAN ip adress if the link is down (if resolving (self).fbxos.fr) otherwise the API is unusable" and also "Freebox api_version call must return the freebox lan adress and disable https_available if link is down otherwise the API is unusable"

I can think of ways to workaround it, but some could have drawbacks. Is writing an other config file containing some connections info about the freebox an option ? Because i don't really see any other way to do it correctly. The problem is : "Say you're fetching info from your local freebox, afpbx finds out the lan went down and switch to a local adress to restore the link" so far you're ok but now "Say you're trying to fetch infos from a remote freebox (not on lan), then link goes down but now afpbx tries to connect to the local freebox and keeps bumping into authorisation errors blindly instead of returning a connection error" An other option would be to store the uid in HA and add it as an optional parameter, so it could only connect to the specified freebox if provided. Without knowing "who is who" in some way i have no idea how to solve this.

SNoof85 commented 4 years ago

mhhh did not saw that _DEFAULT_SSL flag. That would do the trick.

I do not need magic things to check if we have to grab informations from LAN, or WAN or any other way, the configuration is static. The goal is to have something working LAN only, no need for internet connection to get infos from API. That flag will do it.

FYI the mafreebox.freebox.fr works even when internet connection is down.

So i'll be patient, wait for a pypi release but i will try also with your repo on my dev setup. I need to change the way i'm testing it to try with your repo but that's my stuff (i use a devcontainer to dev but in this devcontainer we can't change the 3rd party libs, it's overwritten at each restart of the container 😄 )

I'll give a try with venv 👍

foreign-sub commented 4 years ago

FYI the mafreebox.freebox.fr works even when internet connection is down.

ok good so the workaround could be to fallback to it if resolve fails, the api could do it by itself if using auto detection, otherwise you still have to provide a uid to make sure it's the right one.

So i'll be patient, wait for a pypi release but i will try also with your repo on my dev setup. I need to change the way i'm testing it to try with your repo but that's my stuff (i use a devcontainer to dev but in this devcontainer we can't change the 3rd party libs, it's overwritten at each restart of the container )

Yes i have the same issue ahah.

foreign-sub commented 4 years ago

@SNoof85, please try #22 @ 90b277e it should solve your issues. Also you can now open a freebox by it's uid with ...open(uid="...."), so the config process for ha config flow could be:

You can also manage a "fleet" of freeboxes with get_db(), and clean up entries with clean_db().