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

feature request -- cli support for all functions in the API #16

Closed
marc-portier opened this issue Dec 22, 2022 · 8 comments · Fixed by #17
Closed

feature request -- cli support for all functions in the API #16

marc-portier opened this issue Dec 22, 2022 · 8 comments · Fixed by #17

Comments

@marc-portier
Copy link
Contributor

marc-portier commented Dec 22, 2022

The current cli.py functions as a nice introduction/example on how to use the library for very specific scripted automation needs. Actually example.py would probably be a better name, since it does not provide a full CLI coverage of all the functions provided by the library.

We could however introduce such coverage via a __main__.py

It should:

  • be hooked up in the setup.py as a so called console-script 'entry-point' via setup( entry_points={'console_scripts'= ['pyamplipi = pyamplipi.__main__:main']})
  • read recurring settings like AMPLIPI_API_URL and AMPLIPI_TIMEOUT from the environment through .env + python-dotenv
  • allow to override those on the command line via -a «api_url» and -t «timeout»
  • apply configurable logging
  • provide consistent error-codes if things fail
  • use argparse to cover all of the api via some smart design of the args:
pyamplipi [-a api_url] [-t timeout] TOPIC CMD ...

pyamplipi status list  # produces comprehensible output listing / overview
pyamplipi status get > output.json  
pyamplipi status set < input.json

pyamplipi source list  # produces comprehensible output listing / overview
pyamplipi source get «sourceid» | *  > output.json  # * wildcard for getting all
pyamplipi source set «sourceid» < update.json

pyamplipi zone list  # produces comprehensible output listing / overview
pyamplipi zone get «zoneid» | * > output.json
pyamplipi zone set «zoneid» < update.json

pyamplipi group list  # produces comprehensible output listing / overview
pyamplipi group get «groupid» | * > output.json
pyamplipi group set «groupid» < update.json
pyamplipi group new < input.json  # returns created groupid
pyamplipi group del «groupid» 

pyamplipi stream list  # produces comprehensible output listing / overview
pyamplipi stream get «streamid» | * > output.json
pyamplipi stream set «streamid» < update.json
pyamplipi stream new < input.json  # returns created groupid
pyamplipi stream del «groupid» 
pyamplipi stream play «groupid»  
pyamplipi stream pause «groupid»  
pyamplipi stream stop «groupid»  
pyamplipi stream next «groupid»  
pyamplipi stream prev «groupid»  

pyamplipi announce «media_url» [«vol_f»]  # plays the announcement

pyamplipi preset list  # produces comprehensible output listing / overview
pyamplipi preset get «presetid» | * > output.json
pyamplipi preset set «presetid» < update.json
pyamplipi preset load  «presetid» < input.json
pyamplipi preset new < input.json  # returns created presetid
pyamplipi preset del «presetid» 

note:

  • edited the above after starting on this --> reordering CMD and TOPIC arguments turned out to implement more natural
  • not all preset related endpoints are available in the library yet (might be a recent v0.1.9 ? addition) -- so those would need to be added too
  • have to figure out the difference between set-preset PATCH /api/presets/{pid} and load-preset POST /api/presets/{pid}/load and how the CLI might maybe either hide or support both in the most natural way

I would be glad to provide a PR introducing the above as I see it a logical fit to what the lib is offering.

But I would also understand if you consider this as 'out of scope' and tell me to buzz off and implement this in a separate project.

@linknum23
Copy link
Collaborator

I think this sounds like a great idea. If we add this interface we would need to integrate it into some CI testing as well that is ran against a fake amplipi, in the past I have used jq for tests like this but pytest might be simpler and make more sense.

As for presets, the load function executes the partial change of state specified by the preset. So if the mute-all preset was loaded every zone would be muted when it was loaded and the api would return the full system status. So in your notation it would look like:

pyamplipi load preset «presetid» # produces comprehensible output listing / overview

@marc-portier
Copy link
Contributor Author

ok, getting started on the branch to implement

including pytest is something I could surely do as well (have some experience with that -- in fact I would typically extend the Makefile hinted in #15 with a make test for that)

However -- against which actual service would you consider the tests to be executed?

To be clear: personally I would not want to have standard tests (including clearing config) to run against my running in house amplipi - do you guys have a standard mock or docker instance one can run on localhost to do this kind of stuff? Any other advise?

@marc-portier
Copy link
Contributor Author

marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 23, 2022
marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 26, 2022
marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 26, 2022
… from json input

and apply it to implement the announce action
further progress towards brianhealey#16
marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 26, 2022
@marc-portier
Copy link
Contributor Author

While working on #16 I notice more missing features and altered models available on my local amplipi (v.0.1.9) compared to what is present in this library.

This is the same observation as was raised in #7 - the pull-request made available there (#11) is waiting to get merged on some testing for possible issues with other dependent libraries and systems ?

As I go along it looks like my branch for issue-16 is going to be facing the same limitations as it will be ontroducing more changes of a similar nature and possible impact.

Net effect to me is to also include that previous pull-request (#11) in this ongoing work and just close it.

marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 27, 2022
- removing null values from json to produce cleaner output
- introduce an interactive_confirmation for sensitive actions
- and a --force to override
- first stab at trying to use the new /status/load (still has errors though)
@linknum23
Copy link
Collaborator

There have been a couple of changes to the API from 0.1.7 to 0.1.9, here is the full diff that github shows us: micro-nova/AmpliPi@0.1.7...0.1.9-uv-hotfix

API changes will be found in amplipi/app.py and amplipi/models.py. app.py defines the API endpoints and models.py defines the JSON models used by the API.

@linknum23
Copy link
Collaborator

At a quick glance here are the changes I see to the API (from appl.py):

  • /api/factory_reset [POST]
  • /api/reset [POST]
  • /api/reboot [POST]
  • /api/shutdown [POST]
  • /api/info [GET]

For the json models (models.py) we added relative volume control, updated system information, and showed what stream commands were supported. Here is a little more detail:

  • Info fields, including information on each of the preamp boards firmware
  • for relative volume control vol_f was added to zone and groups, and for each zone a min and max volume (vol_min, vol_max) in dB can be specified to change the range of the relative volume adjustment.
  • For source_info the field supported_cmds was added. This identifies what commands can be sent to a stream that is currently being played on a source. Stream commands are still a bit awkward, they need to be send via the /api/streams/{sid}/cmd endpoint.

I hope this helps!

marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 28, 2022
this allows to reuse the running client
but also required extra io handling beyond the stdin/stdout

all in all a bit of a side-track to the ongoing work for brianhealey#16

but lays down the ground for adding the remaining actions
@marc-portier
Copy link
Contributor Author

thx for the explanations, @linknum23

the work is going well, and this helps completing what I am cooking up :)

Concerning the fact that the "info" part of the Status is really only read-only:
(meaning it is part of status-get, but is simply ignored in config-load)

I was thinking to create a split up of the models into

  • the current Status (read) model and
  • a distinct Config (write) model like this:

current:

class Status(BaseModel):
    sources: List[Source] = []
    zones: List[Zone] = []
    groups: List[Group] = []
    streams: List[Stream] = []
    presets: List[Preset] = []
    info: Optional[Info]

change to:

class Config(BaseModel):
    sources: List[Source] = []
    zones: List[Zone] = []
    groups: List[Group] = []
    streams: List[Stream] = []
    presets: List[Preset] = []
class Status(Config):
    info: Optional[Info]

wdyt?

@linknum23
Copy link
Collaborator

That sounds great. We could even change this in the AmpliPi repo.

marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 29, 2022
creating a Config model that does noet contain the read-only part 'info'
as [per agreement](brianhealey#16 (comment)) in brianhealey#16 thread
marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 29, 2022
progress for brianhealey#16
completes the 'status' part of the API
marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 29, 2022
completing the source api calls for brianhealey#16
this includes the get-image call (which produces binary / non-json)
marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 30, 2022
marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 30, 2022
marc-portier added a commit to marc-portier/pyamplipi that referenced this issue Dec 30, 2022
fixes brianhealey#16
even if some todo remain for future work
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

Successfully merging a pull request may close this issue.

2 participants