Skip to content

Commit

Permalink
status now accepts outlet argument
Browse files Browse the repository at this point in the history
  • Loading branch information
albireox committed Nov 24, 2023
1 parent 7047797 commit 958691d
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 30 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## 1.0.2

### ✨ Improved

* It's now possible to call `status` with an outlet and a summary of the status for only that outlet will be issued.

### 🔧 Fixed

* Issue an NPS refresh before issuing any status.
Expand Down
21 changes: 19 additions & 2 deletions src/lvmnps/actor/commands/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

from typing import TYPE_CHECKING

import click

from lvmnps.actor.commands.onoff import OutletNameParamType

from . import lvmnps_command_parser


Expand All @@ -21,12 +25,25 @@


@lvmnps_command_parser.command()
async def status(command: NPSCommand):
"""Outputs the status of the network power switch."""
@click.argument("OUTLET", type=OutletNameParamType(), required=False)
async def status(command: NPSCommand, outlet: int | str | None = None):
"""Outputs the status of the network power switch.
If an OUTLET is passed, returns only the status of that outlet.
"""

nps = command.actor.nps

await nps.refresh()

if outlet is not None:
try:
outlet_obj = nps.get(outlet)
return command.finish(outlet_info=outlet_obj.model_dump())
except Exception:
return command.fail(f"Invalid outlet {outlet!r}.")

command.info(nps_type=nps.nps_type)
command.info(outlet_names=list(nps.outlets))

Expand Down
55 changes: 31 additions & 24 deletions src/lvmnps/actor/schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"definitions": {
"$defs": {
"script": {
"type": "object",
"description": "Information about a user script",
Expand All @@ -12,6 +12,30 @@
},
"required": ["name", "args", "running", "thread_id"],
"additionalProperties": false
},
"outlet_field": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Original name of the outlet"
},
"normalised_name": {
"type": "string",
"description": "Normalised outlet name"
},
"id": {
"type": "integer",
"description": "Numerical outlet identifier"
},
"state": {
"type": "boolean",
"description": "Outlet state (true=ON)"
}
},
"required": ["name", "normalised_name", "id", "state"],
"additionalProperties": true,
"description": "Properties of each outlet"
}
},
"type": "object",
Expand All @@ -25,31 +49,14 @@
"outlets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Original name of the outlet"
},
"normalised_name": {
"type": "string",
"description": "Normalised outlet name"
},
"id": {
"type": "integer",
"description": "Numerical outlet identifier"
},
"state": {
"type": "boolean",
"description": "Outlet state (true=ON)"
}
},
"required": ["name", "normalised_name", "id", "state"],
"additionalProperties": true,
"description": "Properties of each outlet"
"$ref": "#/$defs/outlet_field"
}
},
"script": { "$ref": "#/definitions/script" },
"outlet_info": {
"$ref": "#/$defs/outlet_field",
"description": "Information about a specific outlet"
},
"script": { "$ref": "#/$defs/script" },
"scripts": { "type": "array", "items": { "$ref": "#/definitions/script" } }
},
"additionalProperties": false
Expand Down
4 changes: 2 additions & 2 deletions tests/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ nps:
init_parameters:
host: 127.0.0.1
port: 8088
user: admin
password: admin
user: lvm
password: lvm00

actor:
name: lvmnps.test
Expand Down
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ async def nps_actor(mocker: MockerFixture, lvmnps_config: Configuration):
actor = NPSActor.from_config(lvmnps_config)

actor.nps = mocker.MagicMock(spec=DLIClient)
actor.nps.get = mocker.MagicMock(side_effect=lambda x: actor.nps.outlets[x])

actor.nps.nps_type = "dli"
actor.nps.outlets = {"outlet_1": DLIOutletModel(id=1, name="outlet_1")}

Expand Down
33 changes: 31 additions & 2 deletions tests/test_actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async def test_actor_netio_nps(lvmnps_config: Configuration):
assert isinstance(actor.nps, NetIOClient)


async def test_command_status(nps_actor: NPSActor, mocker: MockerFixture):
async def test_command_status(nps_actor: NPSActor):
cmd = await nps_actor.invoke_mock_command("status")
await cmd

Expand All @@ -73,7 +73,36 @@ async def test_command_status(nps_actor: NPSActor, mocker: MockerFixture):
}


async def test_command_refresh(nps_actor: NPSActor, mocker: MockerFixture):
async def test_command_status_outlet(nps_actor: NPSActor):
cmd = await nps_actor.invoke_mock_command("status outlet_1")
await cmd

assert cmd.status.did_succeed
assert len(cmd.replies) == 2
assert cmd.replies[-1].body == {
"outlet_info": {
"critical": False,
"cycle_delay": None,
"id": 1,
"index": 0,
"locked": False,
"name": "outlet_1",
"normalised_name": "outlet_1",
"physical_state": False,
"state": False,
"transient_state": False,
}
}


async def test_command_status_invalid_outlet(nps_actor: NPSActor):
cmd = await nps_actor.invoke_mock_command("status outlet_5")
await cmd

assert cmd.status.did_fail


async def test_command_refresh(nps_actor: NPSActor):
cmd = await nps_actor.invoke_mock_command("refresh")
await cmd

Expand Down

0 comments on commit 958691d

Please sign in to comment.