Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- **Expanded** Shelly emulation logs to report battery detection, inactivity, and reconnection events ([#241](https://github.com/tomquist/astrameter/pull/241)).
- **Reduced** throttling output noise by replacing unconditional `print` calls in `ThrottledPowermeter` with structured logging (`logger.debug` for routine wait/fetch/cache messages; failures remain at error level) ([#251](https://github.com/tomquist/astrameter/pull/251)).
- **Improved** Shelly UDP server robustness by adding socket timeouts to avoid hangs during shutdown and testing ([#233](https://github.com/tomquist/astrameter/pull/233)).
- **Upgraded** `JSON_PATHS` parsing in the JSON HTTP and MQTT powermeters to the `jsonpath-ng` extended syntax, so values that arrive with a unit suffix (e.g. openHAB `Number:Power` returning `"331.74 W"`) can be sanitized inside the path with `` `split(...)` `` or `` `sub(/regex/, replacement)` `` instead of failing the float conversion ([#349](https://github.com/tomquist/astrameter/pull/349)).

### Fixed
- **Fixed** Modbus `UNIT_ID` handling and clarified Home Assistant entity ID configuration in the docs ([#191](https://github.com/tomquist/astrameter/pull/191), [#195](https://github.com/tomquist/astrameter/pull/195)).
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,8 @@ TOPIC = home/powermeter
The `JSON_PATH` option is used to extract the power value from a JSON payload. The path must be a [valid JSONPath expression](https://goessner.net/articles/JsonPath/).
If the payload is a simple integer value, you can omit this option.

Both `JSON_PATH` and `JSON_PATHS` are parsed with the [`jsonpath-ng` extended syntax](https://github.com/h2non/jsonpath-ng#extensions), so you can chain extensions like `` `split(...)` `` or `` `sub(/regex/, replacement)` `` to massage a payload value before it's converted to a float — for instance `$.state.`split( , 0, -1)`` or `$.state.`sub(/[^0-9.\-]+$/, )`` to strip a unit suffix like `"331.74 W"`. See the [JSON HTTP](#json-http) section below for more examples.

#### Multi-phase MQTT

For three-phase setups, there are two options:
Expand Down Expand Up @@ -717,6 +719,13 @@ PASSWORD = pass (Optional)
HEADERS = Authorization: Bearer token
```

`JSON_PATHS` is parsed with the [`jsonpath-ng` extended syntax](https://github.com/h2non/jsonpath-ng#extensions), so you can chain extensions like `` `split(...)` `` or `` `sub(/regex/, replacement)` `` to massage the value before it's converted to a float. For example, an openHAB `Number:Power` item returns `"331.74 W"` — strip the unit with either of:

```ini
JSON_PATHS = $.state.`split( , 0, -1)`
JSON_PATHS = $.state.`sub(/[^0-9.\-]+$/, )`
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

### TQ Energy Manager

```ini
Expand Down
4 changes: 4 additions & 0 deletions config.ini.example
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,10 @@ THROTTLE_INTERVAL = 0
# [JSON_HTTP]
#URL = http://example.com/api
#JSON_PATHS = $.power
## JSON_PATHS supports jsonpath-ng extensions; strip a unit suffix like
## "331.74 W" with `split` or `sub`:
##JSON_PATHS = $.state.`split( , 0, -1)`
##JSON_PATHS = $.state.`sub(/[^0-9.\-]+$/, )`
#USERNAME = user
#PASSWORD = pass
#HEADERS = Authorization: Bearer token
Expand Down
2 changes: 1 addition & 1 deletion src/astrameter/powermeter/json_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import aiohttp
from aiohttp import BasicAuth, ClientTimeout
from jsonpath_ng import parse
from jsonpath_ng.ext import parse

from astrameter.config.logger import logger

Expand Down
11 changes: 11 additions & 0 deletions src/astrameter/powermeter/json_http_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ async def test_three_phase(mock_aiohttp_session):
await meter.stop()


async def test_strips_unit_suffix_via_jsonpath_ext(mock_aiohttp_session):
mock_aiohttp_session.set_json({"state": "331.74 W"})
with patch("aiohttp.ClientSession", return_value=mock_aiohttp_session):
meter = JsonHttpPowermeter(
"http://localhost", "$.state.`sub(/[^0-9.\\-]+$/, )`"
)
await meter.start()
assert await meter.get_powermeter_watts() == [331.74]
await meter.stop()


async def test_headers_and_auth(mock_aiohttp_session):
mock_aiohttp_session.set_json({"power": 50})
with patch("aiohttp.ClientSession", return_value=mock_aiohttp_session) as mock_cls:
Expand Down
2 changes: 1 addition & 1 deletion src/astrameter/powermeter/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import ssl

import aiomqtt
from jsonpath_ng import parse
from jsonpath_ng.ext import parse

from astrameter.config.logger import logger

Expand Down
Loading