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

Switch from telnet to API #6

Open
eliahru opened this issue Feb 10, 2020 · 4 comments
Open

Switch from telnet to API #6

eliahru opened this issue Feb 10, 2020 · 4 comments

Comments

@eliahru
Copy link

eliahru commented Feb 10, 2020

Hi @foxel,

Do you have plans to start using Keenetic API instead of telnet? I believe it will make the client more mature since JSON output the API returns is definitely more universal to parse comparing with tables returned in telnet mode.
The API is available on Keenetic devices by URL http://x.x.x.x/rci
The commands you use in TELNET are almost the same via API:

Thank you!

Regards,
Ilya

@alryaz
Copy link

alryaz commented Mar 7, 2021

Interested in this, will attempt to develop something to work out a pull request

@alryaz
Copy link

alryaz commented Mar 8, 2021

Okay, just made an initial API client implementation. It needs a lot of debugging and tests coverage, but it should be capable of doing some generic stuff at the moment. GitHub Repository Here

Example usage:

async with APIClient('<host>', <port>, '<username>', '<password>') as client:
  await client.authenticate()
  # Use functions from Telnet-based client
  await client.get_devices()
  # Use console commands
  await client.api_request(ConsoleCommand('show version'))
  # Multiline command expansion
  await client.api_requests(ConsoleCommand('show', 'interfaces', ['1', '2']))
  # Use RCI Post requests
  await client.api_request({'show': {'version': {}}})
  await client.api_requests([{'show': {'version': {}}}])
  # Use dynamic accessors
  await client.api.show.version()
  await client.api.show('version')
  await client.api.show.interfaces['1']

# Own sessions and out of context operation
session = aiohttp.ClientSession(timeout=50)
client = APIClient(..., session=session)
client.authenticate()
client.show.version()
await client.close()

# Telnet connector adapter (should be fast deprecated, but alas)
telnet_connection_object: TelnetConnection
async with APIClient.from_telnet_connection(telnet_connection_object) as client:
  ...

I will continue refining this branch, but I would also like main developer (@foxel) to greenlight this progress, as this might require a major overhaul of the Telnet connector to maintain cross-compatibility.

@foxel
Copy link
Owner

foxel commented Mar 9, 2021

Hello @alryaz

I've looked thru the code you are proposing and find it very promising. My initial idea was to have a single client with different connection methods available as Connection implementations.

Within my trial with HTTP API I faced a huge issue when guys from NDM Systems changed the way authentication works. Since that time I'm using Telnet as it's well documented in their CLI manuals.

Currently deciding on which type of response is expected (dict/list/collection) is done by the Client class which is clearly limiting the development of HTTP connection as Connection implementation.

As of now, I see you have a separate APIClient with a public interface compatible with the original implementation of the Client. How close do you think you can get to idea of having a single client with switchable connections/backends?

@dtretyakov
Copy link

@foxel FYI @notabene00 already created custom keenetic device tracker component for Home Assistant: https://github.com/notabene00/HA-Keenetic-device_tracker

Also, there is well-documented set of helper functions written in PowerShell: https://github.com/ryzhovau/keenetic-powershell/tree/main/Public

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants