From 7fdaba55c9873d84f8ade650240caa6cdf9ee870 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Tue, 19 Mar 2019 20:02:17 +0000 Subject: [PATCH 01/13] Initial commit for shjq plugin --- shjq/README.md | 5 +++ shjq/__init__.py | 76 +++++++++++++++++++++++++++++++++++++++++++ shjq/plugin.yaml | 34 +++++++++++++++++++ shjq/requirements.txt | 4 +++ 4 files changed, 119 insertions(+) create mode 100644 shjq/README.md create mode 100644 shjq/__init__.py create mode 100755 shjq/plugin.yaml create mode 100644 shjq/requirements.txt diff --git a/shjq/README.md b/shjq/README.md new file mode 100644 index 000000000..9f5bc2436 --- /dev/null +++ b/shjq/README.md @@ -0,0 +1,5 @@ +# shjq + +Version 0.0.1 + + diff --git a/shjq/__init__.py b/shjq/__init__.py new file mode 100644 index 000000000..73d80bc66 --- /dev/null +++ b/shjq/__init__.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# +######################################################################### +# Copyright 2019 Torsten Dreyer torsten (at) t3r (dot) de +# Version 0.0.1 +######################################################################### +# +# This file is part of SmartHomeNG. +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +# +######################################################################### + +import logging +import requests +from requests_file import FileAdapter +import pyjq +from lib.model.smartplugin import SmartPlugin + + +class SHJQ(SmartPlugin): + ALLOW_MULTIINSTANCE = True + PLUGIN_VERSION = "0.0.1" + + def __init__(self, sh, *args, **kwargs): + """ + Initializes the plugin + @param url: URL of the json data to fetch + """ + self.logger = logging.getLogger(__name__) + self._url = self.get_parameter_value('url') + self._cycle = 30 + self._session = requests.Session() + self._session.mount('file://', FileAdapter()) + self._items = {} + + def run(self): + self.alive = True + self.scheduler_add(__name__, self.poll_device, cycle=self._cycle) + + def stop(self): + self.alive = False + + def parse_item(self, item): + if self.has_iattr(item.conf, 'shjq_source'): + attr_value = self.get_iattr_value(item.conf, 'shjq_source') + self._items[item] = attr_value + + def poll_device(self): + try: + response = self._session.get(self._url) + + except Exception as ex: + self.logger.error("Exception when sending GET request for {}: {}".format(self._url,str(ex))) + return + + if response.status_code != 200: + self.logger.error("Bad response code when GETting {}".format(self._url)) + return + + json_obj = response.json() + for k in self._items.keys(): + jqres = pyjq.first(self._items[k], json_obj) + k(jqres) + diff --git a/shjq/plugin.yaml b/shjq/plugin.yaml new file mode 100755 index 000000000..8fa2ac9fb --- /dev/null +++ b/shjq/plugin.yaml @@ -0,0 +1,34 @@ +# Metadata for the Smart-Plugin +plugin: + # Global plugin attributes + type: interface # plugin type (gateway, interface, protocol, system, web) + description: + de: 'jq json parser plugin' + en: 'jq json parser plugin' + maintainer: t3r + tester: none (yet) + keywords: solar power + documentation: http://smarthomeng.de/user/plugins_doc/config/not-yet.html + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/not-yet + + version: 0.0.1 # Plugin version + sh_minversion: 1.4 # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) + multi_instance: True # plugin supports multi instance + classname: SHJQ # class containing the plugin + +parameters: + # Definition of parameters to be configured in etc/plugin.yaml + url: + type: str + mandatory: True + description: + de: 'URL of the json input (e.g. http://foo.bar/input.json or file:///path/to/data.json)' + en: 'URL of the json input (e.g. http://foo.bar/input.json or file:///path/to/data.json)' + + +item_attributes: + # Definition of item attributes defined by this plugin + shjq_source: + type: str + diff --git a/shjq/requirements.txt b/shjq/requirements.txt new file mode 100644 index 000000000..76728880f --- /dev/null +++ b/shjq/requirements.txt @@ -0,0 +1,4 @@ +requests>=2.9.1;python_version>'3.2' +requests==2.5.1;python_version=='3.2' +requests-file +pyjq From 49ab7cf2901a34fc7d9eb8827ee048b8e99b82d7 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Wed, 20 Mar 2019 21:37:20 +0000 Subject: [PATCH 02/13] start with README --- shjq/README.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/shjq/README.md b/shjq/README.md index 9f5bc2436..5019a9e54 100644 --- a/shjq/README.md +++ b/shjq/README.md @@ -1,5 +1,114 @@ # shjq -Version 0.0.1 +This is a generic JSON to smarthome plugin. Fetch any JSON encoded +data via http(s) or from a file, extract the interesting data and feed +the values to smarthome items. +It uses the lightweight and flexible JSON processor jq [https://stedolan.github.io/jq/] +# Dependencies + +This plugin requires +- requests +- requests-file +- pyjq + +# Configuration + +## Enable the plugin in etc/plugin.yaml + +You can add as many instances as you have JSON sources to process. Make sure to add a +unique instance name to each instance if you configure more than on instance. Those +instance name will serve as a key to the item configuration further down. + +### Plugin specific attributes +#### url + +The address of the json data. Currently http://, https:// and file:// schemes are supported. +Note: using absolute file paths for the file:// schema yields in tripple forward slashes. This +might look funny but it is not an error. + +#### cycle + +The repetitive polling interval in seconds. Defaults to 30 seconds. + +### Example + +The following examples uses openweathermap and it's sample API Key. Don't use this key for anything else +but testing. Examples were taken from +[https://openweathermap.org/current]. + +### http client + + shjq: + class_name: SHJQ + class_path: plugins.shjq + url: https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22 + cycle: 30 + +### file client + + shjq: + class_name: SHJQ + class_path: plugins.shjq + url: file:///path/to/data.json + cycle: 30 + +### multi instance + shjquk: + class_name: SHJQ + class_path: plugins.shjq + url: https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22 + instance: london + + shjquk: + class_name: SHJQ + class_path: plugins.shjq + url: https://samples.openweathermap.org/data/2.5/weather?id=2172797&appid=b6907d289e10d714a6e88b30761fae22 + instance: cairns + + +## item configuration in items/myitem.yaml +This is the fun part. This is a sample item. Notice the special attribute shjq_source. + +### Single instance +just use the shjq_source attribute + + temperature: + type: num + shjq_source: .main.temp + +### Multi instance +Use the shjq_source@instance attribute syntax + + temperature: + london: + type: num + shjq_source@london: .main.temp + cairns: + type: num + shjq_source@cairns: .main.temp + +The value for the shjq_source attribute is a jq filter, passed directly to jq itself +Use any kind of jq filter that suites your needs. Make sure your filter returns a single value. +Jq filters can be tricky to develop for complex json structures. Getting them straight might be easier +outside of smarthome by using the commandline version of jq and curl like this + + curl https://json.server.org/data.json | jq -f '.object' + +Look at [https://stedolan.github.io/jq/tutorial/] to get startet with jq filters. + +# Disclaimer and License +This document and the shjq plugin for smarthome.py is free software: +you can redistribute it and/or modify it under the terms of the +GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +smjq is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with shjq. If not, see . From 1a2f5f32213228e337cc74d2f71567f24506a006 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Thu, 21 Mar 2019 08:57:23 +0000 Subject: [PATCH 03/13] introduce 'cycle' property, exception handling --- shjq/__init__.py | 26 ++++++++++++++++++++++---- shjq/plugin.yaml | 6 ++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/shjq/__init__.py b/shjq/__init__.py index 73d80bc66..fb8ce582e 100644 --- a/shjq/__init__.py +++ b/shjq/__init__.py @@ -37,10 +37,17 @@ def __init__(self, sh, *args, **kwargs): """ Initializes the plugin @param url: URL of the json data to fetch + @param cycle: the polling interval in seconds """ self.logger = logging.getLogger(__name__) self._url = self.get_parameter_value('url') - self._cycle = 30 + try: + self._cycle = int(self.get_parameter_value('cycle')) + except Exception: + self._cycle = 0 + if self._cycle <= 0: + self._cycle = 30 + self.logger.error("Bad or missing value for 'cycle', using {}".format(self._cycle)) self._session = requests.Session() self._session.mount('file://', FileAdapter()) self._items = {} @@ -66,11 +73,22 @@ def poll_device(self): return if response.status_code != 200: - self.logger.error("Bad response code when GETting {}".format(self._url)) + self.logger.error("Bad response code from GET '{}': {}".format(self._url, response.status_code)) + return + + try: + json_obj = response.json() + except Exception as ex: + self.logger.error("Response from '{}' doesn't look like json '{}'".format(self._url, str(response.content)[:30])) return - json_obj = response.json() for k in self._items.keys(): - jqres = pyjq.first(self._items[k], json_obj) + try: + jqres = pyjq.first(self._items[k], json_obj) + + except Exception as ex: + self.logger.error("jq filter failed: {}'".format(str(ex))) + continue + k(jqres) diff --git a/shjq/plugin.yaml b/shjq/plugin.yaml index 8fa2ac9fb..5df9f3062 100755 --- a/shjq/plugin.yaml +++ b/shjq/plugin.yaml @@ -25,6 +25,12 @@ parameters: description: de: 'URL of the json input (e.g. http://foo.bar/input.json or file:///path/to/data.json)' en: 'URL of the json input (e.g. http://foo.bar/input.json or file:///path/to/data.json)' + cycle: + type: num + mandatory: False + description: + de: 'The polling interval for the given url in seconds' + en: 'The polling interval for the given url in seconds' item_attributes: From 086c4a24cc1948aca304a424404accd32d332fc4 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Thu, 21 Mar 2019 09:01:05 +0000 Subject: [PATCH 04/13] Fix typo in docs --- shjq/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shjq/README.md b/shjq/README.md index 5019a9e54..7cbbd978b 100644 --- a/shjq/README.md +++ b/shjq/README.md @@ -18,7 +18,7 @@ This plugin requires ## Enable the plugin in etc/plugin.yaml You can add as many instances as you have JSON sources to process. Make sure to add a -unique instance name to each instance if you configure more than on instance. Those +unique instance name to each instance if you configure more than on instance. That instance name will serve as a key to the item configuration further down. ### Plugin specific attributes @@ -55,13 +55,13 @@ but testing. Examples were taken from cycle: 30 ### multi instance - shjquk: + shjqlon: class_name: SHJQ class_path: plugins.shjq url: https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22 instance: london - shjquk: + shjqcair: class_name: SHJQ class_path: plugins.shjq url: https://samples.openweathermap.org/data/2.5/weather?id=2172797&appid=b6907d289e10d714a6e88b30761fae22 @@ -94,7 +94,7 @@ Use any kind of jq filter that suites your needs. Make sure your filter returns Jq filters can be tricky to develop for complex json structures. Getting them straight might be easier outside of smarthome by using the commandline version of jq and curl like this - curl https://json.server.org/data.json | jq -f '.object' + curl https://json.server.org/data.json | jq '.object' Look at [https://stedolan.github.io/jq/tutorial/] to get startet with jq filters. From 47cdc5cef51acd06b177f28fd4b8bf43b5a68f60 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sat, 23 Mar 2019 09:51:40 +0000 Subject: [PATCH 05/13] Use default/valid_min properties for the cycle parameter --- shjq/__init__.py | 8 +------- shjq/plugin.yaml | 2 ++ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/shjq/__init__.py b/shjq/__init__.py index fb8ce582e..d6c615e12 100644 --- a/shjq/__init__.py +++ b/shjq/__init__.py @@ -41,13 +41,7 @@ def __init__(self, sh, *args, **kwargs): """ self.logger = logging.getLogger(__name__) self._url = self.get_parameter_value('url') - try: - self._cycle = int(self.get_parameter_value('cycle')) - except Exception: - self._cycle = 0 - if self._cycle <= 0: - self._cycle = 30 - self.logger.error("Bad or missing value for 'cycle', using {}".format(self._cycle)) + self._cycle = int(self.get_parameter_value('cycle')) self._session = requests.Session() self._session.mount('file://', FileAdapter()) self._items = {} diff --git a/shjq/plugin.yaml b/shjq/plugin.yaml index 5df9f3062..325e08082 100755 --- a/shjq/plugin.yaml +++ b/shjq/plugin.yaml @@ -28,6 +28,8 @@ parameters: cycle: type: num mandatory: False + default: 30 + valid_min: 0 description: de: 'The polling interval for the given url in seconds' en: 'The polling interval for the given url in seconds' From b83fc241dbf9222b4fc50a4b5b6169006c1121f7 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sat, 23 Mar 2019 09:54:28 +0000 Subject: [PATCH 06/13] remove our task from the scheduler upon stop() --- shjq/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/shjq/__init__.py b/shjq/__init__.py index d6c615e12..d383dccce 100644 --- a/shjq/__init__.py +++ b/shjq/__init__.py @@ -51,6 +51,7 @@ def run(self): self.scheduler_add(__name__, self.poll_device, cycle=self._cycle) def stop(self): + self.scheduler_remove(__name__ ) self.alive = False def parse_item(self, item): From 20bb0de2818c50e31ade53442dd8a52c596a3d0e Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sat, 23 Mar 2019 09:56:16 +0000 Subject: [PATCH 07/13] better keyword, correct type for cycle --- shjq/plugin.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shjq/plugin.yaml b/shjq/plugin.yaml index 325e08082..3c675f5e5 100755 --- a/shjq/plugin.yaml +++ b/shjq/plugin.yaml @@ -7,7 +7,7 @@ plugin: en: 'jq json parser plugin' maintainer: t3r tester: none (yet) - keywords: solar power + keywords: json documentation: http://smarthomeng.de/user/plugins_doc/config/not-yet.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/not-yet @@ -26,7 +26,7 @@ parameters: de: 'URL of the json input (e.g. http://foo.bar/input.json or file:///path/to/data.json)' en: 'URL of the json input (e.g. http://foo.bar/input.json or file:///path/to/data.json)' cycle: - type: num + type: int mandatory: False default: 30 valid_min: 0 From b7026fb568e66e0ae5c7daf9d317887c7ef3e37c Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sat, 23 Mar 2019 09:59:36 +0000 Subject: [PATCH 08/13] Avoid unnecessary variable assignment --- shjq/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shjq/__init__.py b/shjq/__init__.py index d383dccce..121697f10 100644 --- a/shjq/__init__.py +++ b/shjq/__init__.py @@ -56,8 +56,7 @@ def stop(self): def parse_item(self, item): if self.has_iattr(item.conf, 'shjq_source'): - attr_value = self.get_iattr_value(item.conf, 'shjq_source') - self._items[item] = attr_value + self._items[item] = self.get_iattr_value(item.conf, 'shjq_source') def poll_device(self): try: From 57abb960708697ffff3e204a10767ab27829e608 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sat, 23 Mar 2019 10:04:13 +0000 Subject: [PATCH 09/13] Add german translation --- shjq/plugin.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shjq/plugin.yaml b/shjq/plugin.yaml index 3c675f5e5..986f9c1c2 100755 --- a/shjq/plugin.yaml +++ b/shjq/plugin.yaml @@ -3,8 +3,8 @@ plugin: # Global plugin attributes type: interface # plugin type (gateway, interface, protocol, system, web) description: - de: 'jq json parser plugin' - en: 'jq json parser plugin' + de: 'json parser plugin basierend auf jq' + en: 'json parser plugin based on jq' maintainer: t3r tester: none (yet) keywords: json @@ -23,7 +23,7 @@ parameters: type: str mandatory: True description: - de: 'URL of the json input (e.g. http://foo.bar/input.json or file:///path/to/data.json)' + de: 'URL der json Eingabe-Daten (z.B. http://foo.bar/input.json oder file:///pfad/zu/data.json)' en: 'URL of the json input (e.g. http://foo.bar/input.json or file:///path/to/data.json)' cycle: type: int @@ -31,7 +31,7 @@ parameters: default: 30 valid_min: 0 description: - de: 'The polling interval for the given url in seconds' + de: 'Das Abfrage-Intervall für die gegebene URL in Sekunden' en: 'The polling interval for the given url in seconds' From fdfd66a7ffa09f279b84a7e039dd8e493c7cfcac Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sat, 23 Mar 2019 10:42:22 +0000 Subject: [PATCH 10/13] Add examples to README --- shjq/README.md | 113 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 3 deletions(-) diff --git a/shjq/README.md b/shjq/README.md index 7cbbd978b..06943036a 100644 --- a/shjq/README.md +++ b/shjq/README.md @@ -11,13 +11,13 @@ It uses the lightweight and flexible JSON processor jq [https://stedolan.github. This plugin requires - requests - requests-file -- pyjq +- pyjq # Configuration ## Enable the plugin in etc/plugin.yaml -You can add as many instances as you have JSON sources to process. Make sure to add a +You can add as many instances as you have JSON sources to process. Make sure to add a unique instance name to each instance if you configure more than on instance. That instance name will serve as a key to the item configuration further down. @@ -98,9 +98,116 @@ outside of smarthome by using the commandline version of jq and curl like this Look at [https://stedolan.github.io/jq/tutorial/] to get startet with jq filters. +# Example +## Fetch data from a SolarWatt Energy Manager and MyReserve +Note: this example uses the mutli-instance feature as it fetches data from two +sources. + +### Sample input data +#### BMSData.shtml +This file gets generated by SolarWatt's receiveBLE.py process on their raspi. The interesting +part looks like this: + + { + "FData": { + "IPV": 5.17, + "VBat": 170.1, + "VPV": 418.5, + "PGrid": 18, + "IBat": -9.91 + }, + "SData": { + "ACS": { + "U_L2": 239, + "f": 49.98 + }, + "SoC": 10 + } + } + +#### energy-manager json data +The energy manager produces a fairly huge JSON dataset, more than 4500 lines on my system. +This is an example, stripped down to what we use in this document + + { + "result": { + "items": [ + { + "guid": "urn:your-inverter-guid", + "tagValues": { + "PowerACOut": { + "value": 2419, + "tagName": "PowerACOut" + } + } + } + ] + } + } + +### etc/plugin.yaml + + swem: + class_name: SHJQ + class_path: plugins.shjq + # Replace with the ip address or hostname of your energy-manager + url: http://192.168.x.y/rest/kiwigrid/wizard/devices + instance: swem + cycle: 30 + + myreserve: + class_name: SHJQ + class_path: plugins.shjq + # Replace with the path to your BMSData-file + url: file:///tmp/BMSData.shtml + instance: myreserve + cycle: 10 + + +### items/myenergy.yaml + +Get the batteries voltage, charge current and charge power. + + battery: + u: + # note: we are fetching from the 'myreserve' plugin instance + # easy: get attribute VBat of the FData object + type: num + shjq_source@myreserve: .FData.VBat + i: + # easy: get attribute IBat of the FData object + type: num + shjq_source@myreserve: .FData.IBat + power: + # doing simple math is also straightforward + type: num + shjq_source@myreserve: (.FData.VBat * .FData.IBat * -1) + +Get the current inverter AC out power + + inverter: + type: num + # note: we are fetching from the 'swem' plugin instance + # from the items array in the result object, fetch the object where the guid matches our given guid + # from the resulting object, walk down the tree and fetch the "value" attribute + shjq_source@swem: (.result.items[] | select(.guid == "urn:your-inverter-guid").tagValues.PowerACOut.value) + # all standard attributes work as expected + visu_acl: r + sqlite: yes + +Compute the grid power, use yaml's block style feature (https://yaml-multiline.info/) to wrap long lines + + grid: + type: num + shjq_source@swem: > + (.result.items[] | + select(.deviceModel[].deviceClass == "com.kiwigrid.devices.solarwatt.MyReservePowermeter").tagValues.PowerOut.value) - + (.result.items[] | + select(.deviceModel[].deviceClass == "com.kiwigrid.devices.solarwatt.MyReservePowermeter").tagValues.PowerIn.value) + # Disclaimer and License This document and the shjq plugin for smarthome.py is free software: -you can redistribute it and/or modify it under the terms of the +you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. From 02429e9a71614a45649e6ed99e08760ad74df233 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sun, 24 Mar 2019 08:20:48 +0000 Subject: [PATCH 11/13] A little cleanup and make it 1.0.0 --- shjq/__init__.py | 6 +++--- shjq/plugin.yaml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/shjq/__init__.py b/shjq/__init__.py index 121697f10..7f081d3c9 100644 --- a/shjq/__init__.py +++ b/shjq/__init__.py @@ -2,7 +2,7 @@ # ######################################################################### # Copyright 2019 Torsten Dreyer torsten (at) t3r (dot) de -# Version 0.0.1 +# Version 1.0.0 ######################################################################### # # This file is part of SmartHomeNG. @@ -31,7 +31,7 @@ class SHJQ(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "0.0.1" + PLUGIN_VERSION = "1.0.0" def __init__(self, sh, *args, **kwargs): """ @@ -41,7 +41,7 @@ def __init__(self, sh, *args, **kwargs): """ self.logger = logging.getLogger(__name__) self._url = self.get_parameter_value('url') - self._cycle = int(self.get_parameter_value('cycle')) + self._cycle = self.get_parameter_value('cycle') self._session = requests.Session() self._session.mount('file://', FileAdapter()) self._items = {} diff --git a/shjq/plugin.yaml b/shjq/plugin.yaml index 986f9c1c2..61e8c2c3c 100755 --- a/shjq/plugin.yaml +++ b/shjq/plugin.yaml @@ -5,13 +5,13 @@ plugin: description: de: 'json parser plugin basierend auf jq' en: 'json parser plugin based on jq' - maintainer: t3r + maintainer: Torsten Dreyer tester: none (yet) keywords: json documentation: http://smarthomeng.de/user/plugins_doc/config/not-yet.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/not-yet - version: 0.0.1 # Plugin version + version: 1.0.0 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance From 099797a0b2bd980c1929e45776c1bd00ae432f6d Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sun, 24 Mar 2019 08:26:32 +0000 Subject: [PATCH 12/13] Renamed plugin to jsonread and filter attribute to jsonread_filter --- {shjq => jsonread}/README.md | 62 ++++++++++++++--------------- {shjq => jsonread}/__init__.py | 6 +-- {shjq => jsonread}/plugin.yaml | 4 +- {shjq => jsonread}/requirements.txt | 0 4 files changed, 36 insertions(+), 36 deletions(-) rename {shjq => jsonread}/README.md (81%) rename {shjq => jsonread}/__init__.py (96%) rename {shjq => jsonread}/plugin.yaml (94%) rename {shjq => jsonread}/requirements.txt (100%) diff --git a/shjq/README.md b/jsonread/README.md similarity index 81% rename from shjq/README.md rename to jsonread/README.md index 06943036a..db32150f8 100644 --- a/shjq/README.md +++ b/jsonread/README.md @@ -1,4 +1,4 @@ -# shjq +# The jsonread plugin This is a generic JSON to smarthome plugin. Fetch any JSON encoded data via http(s) or from a file, extract the interesting data and feed @@ -40,56 +40,56 @@ but testing. Examples were taken from ### http client - shjq: - class_name: SHJQ - class_path: plugins.shjq + jsonread: + class_name: JSONREAD + class_path: plugins.jsonread url: https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22 cycle: 30 ### file client - shjq: - class_name: SHJQ - class_path: plugins.shjq + jsonread: + class_name: JSONREAD + class_path: plugins.jsonread url: file:///path/to/data.json cycle: 30 ### multi instance - shjqlon: - class_name: SHJQ - class_path: plugins.shjq + jsonreadlon: + class_name: JSONREAD + class_path: plugins.jsonread url: https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22 instance: london - shjqcair: - class_name: SHJQ - class_path: plugins.shjq + jsonreadcair: + class_name: JSONREAD + class_path: plugins.jsonread url: https://samples.openweathermap.org/data/2.5/weather?id=2172797&appid=b6907d289e10d714a6e88b30761fae22 instance: cairns ## item configuration in items/myitem.yaml -This is the fun part. This is a sample item. Notice the special attribute shjq_source. +This is the fun part. This is a sample item. Notice the special attribute jsonread_filter. ### Single instance -just use the shjq_source attribute +just use the jsonread_filter attribute temperature: type: num - shjq_source: .main.temp + jsonread_filter: .main.temp ### Multi instance -Use the shjq_source@instance attribute syntax +Use the jsonread_filter@instance attribute syntax temperature: london: type: num - shjq_source@london: .main.temp + jsonread_filter@london: .main.temp cairns: type: num - shjq_source@cairns: .main.temp + jsonread_filter@cairns: .main.temp -The value for the shjq_source attribute is a jq filter, passed directly to jq itself +The value for the jsonread_filter attribute is a jq filter, passed directly to jq itself Use any kind of jq filter that suites your needs. Make sure your filter returns a single value. Jq filters can be tricky to develop for complex json structures. Getting them straight might be easier outside of smarthome by using the commandline version of jq and curl like this @@ -148,16 +148,16 @@ This is an example, stripped down to what we use in this document ### etc/plugin.yaml swem: - class_name: SHJQ - class_path: plugins.shjq + class_name: JSONREAD + class_path: plugins.jsonread # Replace with the ip address or hostname of your energy-manager url: http://192.168.x.y/rest/kiwigrid/wizard/devices instance: swem cycle: 30 myreserve: - class_name: SHJQ - class_path: plugins.shjq + class_name: JSONREAD + class_path: plugins.jsonread # Replace with the path to your BMSData-file url: file:///tmp/BMSData.shtml instance: myreserve @@ -173,15 +173,15 @@ Get the batteries voltage, charge current and charge power. # note: we are fetching from the 'myreserve' plugin instance # easy: get attribute VBat of the FData object type: num - shjq_source@myreserve: .FData.VBat + jsonread_filter@myreserve: .FData.VBat i: # easy: get attribute IBat of the FData object type: num - shjq_source@myreserve: .FData.IBat + jsonread_filter@myreserve: .FData.IBat power: # doing simple math is also straightforward type: num - shjq_source@myreserve: (.FData.VBat * .FData.IBat * -1) + jsonread_filter@myreserve: (.FData.VBat * .FData.IBat * -1) Get the current inverter AC out power @@ -190,7 +190,7 @@ Get the current inverter AC out power # note: we are fetching from the 'swem' plugin instance # from the items array in the result object, fetch the object where the guid matches our given guid # from the resulting object, walk down the tree and fetch the "value" attribute - shjq_source@swem: (.result.items[] | select(.guid == "urn:your-inverter-guid").tagValues.PowerACOut.value) + jsonread_filter@swem: (.result.items[] | select(.guid == "urn:your-inverter-guid").tagValues.PowerACOut.value) # all standard attributes work as expected visu_acl: r sqlite: yes @@ -199,14 +199,14 @@ Compute the grid power, use yaml's block style feature (https://yaml-multiline.i grid: type: num - shjq_source@swem: > + jsonread_filter@swem: > (.result.items[] | select(.deviceModel[].deviceClass == "com.kiwigrid.devices.solarwatt.MyReservePowermeter").tagValues.PowerOut.value) - (.result.items[] | select(.deviceModel[].deviceClass == "com.kiwigrid.devices.solarwatt.MyReservePowermeter").tagValues.PowerIn.value) # Disclaimer and License -This document and the shjq plugin for smarthome.py is free software: +This document and the jsonread plugin for smarthome.py is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -218,4 +218,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with shjq. If not, see . +along with jsonread. If not, see . diff --git a/shjq/__init__.py b/jsonread/__init__.py similarity index 96% rename from shjq/__init__.py rename to jsonread/__init__.py index 7f081d3c9..fa29ec54a 100644 --- a/shjq/__init__.py +++ b/jsonread/__init__.py @@ -29,7 +29,7 @@ from lib.model.smartplugin import SmartPlugin -class SHJQ(SmartPlugin): +class JSONREAD(SmartPlugin): ALLOW_MULTIINSTANCE = True PLUGIN_VERSION = "1.0.0" @@ -55,8 +55,8 @@ def stop(self): self.alive = False def parse_item(self, item): - if self.has_iattr(item.conf, 'shjq_source'): - self._items[item] = self.get_iattr_value(item.conf, 'shjq_source') + if self.has_iattr(item.conf, 'jsonread_filter'): + self._items[item] = self.get_iattr_value(item.conf, 'jsonread_filter') def poll_device(self): try: diff --git a/shjq/plugin.yaml b/jsonread/plugin.yaml similarity index 94% rename from shjq/plugin.yaml rename to jsonread/plugin.yaml index 61e8c2c3c..b58fd55f3 100755 --- a/shjq/plugin.yaml +++ b/jsonread/plugin.yaml @@ -15,7 +15,7 @@ plugin: sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance - classname: SHJQ # class containing the plugin + classname: JSONREAD # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml @@ -37,6 +37,6 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin - shjq_source: + jsonread_filter: type: str diff --git a/shjq/requirements.txt b/jsonread/requirements.txt similarity index 100% rename from shjq/requirements.txt rename to jsonread/requirements.txt From 826c6f9f1375f267c038e9aec8cff41d19652c1e Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Sun, 24 Mar 2019 14:45:27 +0000 Subject: [PATCH 13/13] Remove requests from requirementsZ --- jsonread/requirements.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/jsonread/requirements.txt b/jsonread/requirements.txt index 76728880f..de5b5f3aa 100644 --- a/jsonread/requirements.txt +++ b/jsonread/requirements.txt @@ -1,4 +1,2 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' requests-file pyjq