update review comments:
-> update file names
-> update variable with camel case
-> update debian/control
-> remove unused files and API
-> remove deprecated property
-> update indentation
-> update code as per comment
-> fix typo
This commit is contained in:
parent
fec4899238
commit
9d62caeb1c
9
debian/control
vendored
9
debian/control
vendored
@ -841,6 +841,15 @@ Description: nymea integration plugin to connect to your Tado account
|
|||||||
This package contains the nymea integration plugin for Tado devices.
|
This package contains the nymea integration plugin for Tado devices.
|
||||||
|
|
||||||
|
|
||||||
|
Package: nymea-plugin-v2xeamberelectric
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends},
|
||||||
|
${misc:Depends},
|
||||||
|
Conflicts: nymea-plugins-translations (<< 1.0.1)
|
||||||
|
Description: This nymea plugin fetches live and forecasted price data,
|
||||||
|
providing real-time and future pricing information for integration with smart energy management systems.
|
||||||
|
|
||||||
|
|
||||||
Package: nymea-plugin-wheretheissat
|
Package: nymea-plugin-wheretheissat
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${misc:Depends},
|
Depends: ${misc:Depends},
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginEV_charger.so
|
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginv2xeamberelectric.so
|
||||||
@ -84,6 +84,7 @@ PLUGIN_DIRS = \
|
|||||||
unifi \
|
unifi \
|
||||||
usbrelay \
|
usbrelay \
|
||||||
usbrly82 \
|
usbrly82 \
|
||||||
|
v2xeamberelectric \
|
||||||
wakeonlan \
|
wakeonlan \
|
||||||
wemo \
|
wemo \
|
||||||
ws2812fx \
|
ws2812fx \
|
||||||
|
|||||||
43
v2xeamberelectric/.gitignore
vendored
43
v2xeamberelectric/.gitignore
vendored
@ -1,43 +0,0 @@
|
|||||||
# C++ objects and libs
|
|
||||||
|
|
||||||
*.slo
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.la
|
|
||||||
*.lai
|
|
||||||
*.so
|
|
||||||
*.dll
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Qt-es
|
|
||||||
|
|
||||||
/.qmake.cache
|
|
||||||
/.qmake.stash
|
|
||||||
*.pro.user
|
|
||||||
*.pro.user.*
|
|
||||||
*.qbs.user
|
|
||||||
*.qbs.user.*
|
|
||||||
*.moc
|
|
||||||
moc_*.cpp
|
|
||||||
qrc_*.cpp
|
|
||||||
ui_*.h
|
|
||||||
Makefile*
|
|
||||||
*-build-*
|
|
||||||
|
|
||||||
# QtCreator
|
|
||||||
|
|
||||||
*.autosave
|
|
||||||
|
|
||||||
#QtCtreator Qml
|
|
||||||
*.qmlproject.user
|
|
||||||
*.qmlproject.user.*
|
|
||||||
|
|
||||||
build-*
|
|
||||||
html
|
|
||||||
build
|
|
||||||
vendor
|
|
||||||
*.qmlc
|
|
||||||
*.swp
|
|
||||||
|
|
||||||
.crossbuilder
|
|
||||||
@ -1,165 +0,0 @@
|
|||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 29 June 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
|
||||||
General Public License.
|
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
|
||||||
other than an Application or a Combined Work as defined below.
|
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
|
||||||
by the Library, but which is not otherwise based on the Library.
|
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
|
||||||
of using an interface provided by the Library.
|
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
|
||||||
Application with the Library. The particular version of the Library
|
|
||||||
with which the Combined Work was made is also called the "Linked
|
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
|
||||||
based on the Application, and not on the Linked Version.
|
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
|
||||||
object code and/or source code for the Application, including any data
|
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
|
||||||
without being bound by section 3 of the GNU GPL.
|
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
|
||||||
this License applicable to that copy.
|
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
|
||||||
a header file that is part of the Library. You may convey such object
|
|
||||||
code under terms of your choice, provided that, if the incorporated
|
|
||||||
material is not limited to numerical parameters, data structure
|
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
|
||||||
Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
4. Combined Works.
|
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
|
||||||
taken together, effectively do not restrict modification of the
|
|
||||||
portions of the Library contained in the Combined Work and reverse
|
|
||||||
engineering for debugging such modifications, if you also do each of
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
|
||||||
document.
|
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
|
||||||
execution, include the copyright notice for the Library among
|
|
||||||
these notices, as well as a reference directing the user to the
|
|
||||||
copies of the GNU GPL and this license document.
|
|
||||||
|
|
||||||
d) Do one of the following:
|
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
|
||||||
License, and the Corresponding Application Code in a form
|
|
||||||
suitable for, and under terms that permit, the user to
|
|
||||||
recombine or relink the Application with a modified version of
|
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
|
||||||
Corresponding Source.
|
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
|
||||||
a copy of the Library already present on the user's computer
|
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
|
||||||
be required to provide such information under section 6 of the
|
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
|
||||||
Library side by side in a single library together with other library
|
|
||||||
facilities that are not Applications and are not covered by this
|
|
||||||
License, and convey such a combined library under terms of your
|
|
||||||
choice, if you do both of the following:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
|
||||||
on the Library, uncombined with any other library facilities,
|
|
||||||
conveyed under the terms of this License.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
|
||||||
is a work based on the Library, and explaining where to find the
|
|
||||||
accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
|
||||||
versions will be similar in spirit to the present version, but may
|
|
||||||
differ in detail to address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Library as you received it specifies that a certain numbered version
|
|
||||||
of the GNU Lesser General Public License "or any later version"
|
|
||||||
applies to it, you have the option of following the terms and
|
|
||||||
conditions either of that published version or of any later version
|
|
||||||
published by the Free Software Foundation. If the Library as you
|
|
||||||
received it does not specify a version number of the GNU Lesser
|
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
|
||||||
permanent authorization for you to choose that version for the
|
|
||||||
Library.
|
|
||||||
@ -3,6 +3,5 @@
|
|||||||
|
|
||||||
Description of the plugin...
|
Description of the plugin...
|
||||||
|
|
||||||
plugin for amber electric api to get live data of energy use ,
|
This Nymea plugin fetches live and forecasted price data, providing real-time and future pricing information for integration with smart energy management systems
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
nymea-plugin-v2xeamberelectric (0.0.1) bookworm; urgency=medium
|
|
||||||
|
|
||||||
* Initial release.
|
|
||||||
|
|
||||||
-- devendragajjar <devendragajjar@gmail.com> Mon, 21 Aug 2017 10:12:00 +0000
|
|
||||||
@ -1 +0,0 @@
|
|||||||
11
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
Source: nymea-plugin-v2xeamberelectric
|
|
||||||
Section: utils
|
|
||||||
Priority: optional
|
|
||||||
Maintainer: devendragajjar <devendragajjar@gmail.com>
|
|
||||||
Standards-Version: 4.6.0
|
|
||||||
Build-depends: debhelper (>= 9.0.0),
|
|
||||||
libnymea1-dev,
|
|
||||||
nymea-dev-tools:native,
|
|
||||||
qt5-qmake:native,
|
|
||||||
pkg-config,
|
|
||||||
|
|
||||||
|
|
||||||
Package: nymea-plugin-v2xeamberelectric
|
|
||||||
Architecture: any
|
|
||||||
Multi-Arch: same
|
|
||||||
Section: libs
|
|
||||||
Depends: ${shlibs:Depends},
|
|
||||||
${misc:Depends},
|
|
||||||
Description: nymea.io plugin for v2xeamberelectric
|
|
||||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
|
||||||
server works like a translator for devices, things and services and
|
|
||||||
allows them to interact.
|
|
||||||
With the powerful rule engine you are able to connect any device available
|
|
||||||
in the system and create individual scenes and behaviors for your environment.
|
|
||||||
.
|
|
||||||
This package will install the nymea.io plugin for v2xeamberelectric
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
||||||
Upstream-Name: ${ProjectName}
|
|
||||||
Upstream-Contact: devendragajjar <devendragajjar@gmail.com>
|
|
||||||
Copyright: 2024, devendragajjar
|
|
||||||
|
|
||||||
|
|
||||||
License: LGPL-3
|
|
||||||
On Debian systems, the complete text of the GNU Lesser General
|
|
||||||
Public License can be found in `/usr/share/common-licenses/LGPL-3'.
|
|
||||||
|
|
||||||
Files: *
|
|
||||||
License: LGPL-3
|
|
||||||
Copyright: devendragajjar <devendragajjar@gmail.com>
|
|
||||||
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/make -f
|
|
||||||
# -*- makefile -*-
|
|
||||||
|
|
||||||
export DH_VERBOSE=1
|
|
||||||
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
|
|
||||||
|
|
||||||
PREPROCESS_FILES := $(wildcard debian/*.in)
|
|
||||||
|
|
||||||
$(PREPROCESS_FILES:.in=): %: %.in
|
|
||||||
sed 's,/@DEB_HOST_MULTIARCH@,$(DEB_HOST_MULTIARCH:%=/%),g' $< > $@
|
|
||||||
|
|
||||||
override_dh_install: $(PREPROCESS_FILES:.in=)
|
|
||||||
make -j9 install DESTDIR=debian/tmp AM_UPDATE_INFO_DIR=no INSTALL_ROOT=debian/tmp
|
|
||||||
dh_install
|
|
||||||
|
|
||||||
override_dh_missing:
|
|
||||||
dh_missing --list-missing
|
|
||||||
|
|
||||||
override_dh_auto_build:
|
|
||||||
dh_auto_build
|
|
||||||
make lrelease
|
|
||||||
|
|
||||||
override_dh_auto_clean:
|
|
||||||
dh_auto_clean
|
|
||||||
rm -rf $(PREPROCESS_FILES:.in=)
|
|
||||||
|
|
||||||
%:
|
|
||||||
dh $@ --parallel
|
|
||||||
|
|
||||||
@ -1 +0,0 @@
|
|||||||
3.0 (native)
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Amber_Electric_plgn",
|
|
||||||
"displayName": "Amber_Electric_plgn",
|
|
||||||
"id": "0233c848-6f6f-4907-a51c-81391e4f5356",
|
|
||||||
"vendors": [
|
|
||||||
{
|
|
||||||
"name": "Amber_Electric",
|
|
||||||
"displayName": "Amber_Electric",
|
|
||||||
"id": "ec1985b9-5891-435d-9264-e8e18d392978",
|
|
||||||
"thingClasses": [
|
|
||||||
{
|
|
||||||
"name": "V2Xe_Amber_Electric",
|
|
||||||
"displayName": "V2Xe_Amber_Electric",
|
|
||||||
"id": "11295990-7002-432e-b90c-cd4010548a32",
|
|
||||||
"setupMethod": "JustAdd",
|
|
||||||
"createMethods": ["User"],
|
|
||||||
"interfaces": ["v2xeenergymeter", "connectable"],
|
|
||||||
"paramTypes": [
|
|
||||||
{
|
|
||||||
"id": "fc899f7b-f452-44dc-b72e-ee7bb8034ff0",
|
|
||||||
"name": "auth_token",
|
|
||||||
"displayName": "auth_token",
|
|
||||||
"type" : "QString",
|
|
||||||
"defaultValue": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "c50eac84-714e-4b9c-89d5-0b939b6c18d6",
|
|
||||||
"name": "crnt_site",
|
|
||||||
"displayName": "current_site",
|
|
||||||
"type" : "QString",
|
|
||||||
"defaultValue": ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stateTypes": [
|
|
||||||
{
|
|
||||||
"id": "faf2a6c0-1897-4b9b-903a-e12b281efe24",
|
|
||||||
"name": "connected",
|
|
||||||
"displayName": "Reachable",
|
|
||||||
"displayNameEvent": "Reachable changed",
|
|
||||||
"type": "bool",
|
|
||||||
"defaultValue": false,
|
|
||||||
"cached": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "42c8a6f8-4f97-4871-8bfb-ac7e6ffffa74",
|
|
||||||
"name": "Sites",
|
|
||||||
"displayName": "Sites",
|
|
||||||
"displayNameEvent": "Sites_list_updated",
|
|
||||||
"type": "QString",
|
|
||||||
"writable": false,
|
|
||||||
"defaultValue": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "27c3f8e0-0803-4eb8-ba4f-ce78fb0997a9",
|
|
||||||
"name": "Type",
|
|
||||||
"displayName": "type",
|
|
||||||
"displayNameEvent": "type_evnet",
|
|
||||||
"type": "QString",
|
|
||||||
"defaultValue": "Amber"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "6e8d3fcd-c235-4793-95b5-321ca6e012a3",
|
|
||||||
"name": "forecastprice",
|
|
||||||
"displayName": "Feedin Price",
|
|
||||||
"displayNameEvent": "forecastPrice_changed",
|
|
||||||
"type": "double",
|
|
||||||
"minValue": 0,
|
|
||||||
"maxValue": 1000,
|
|
||||||
"defaultValue": 0,
|
|
||||||
"unit": "KiloWattHour",
|
|
||||||
"suggestLogging": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "a25d3b55-9b93-4465-90e3-5d36adb8fb23",
|
|
||||||
"name": "currentprice",
|
|
||||||
"displayName": "Current Price",
|
|
||||||
"displayNameEvent": "currentPrice_changed",
|
|
||||||
"type": "double",
|
|
||||||
"minValue": 0,
|
|
||||||
"maxValue": 1000,
|
|
||||||
"unit":"KiloWattHour",
|
|
||||||
"defaultValue": 0,
|
|
||||||
"suggestLogging": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "cd1e22b2-2154-453a-bbdf-59156893258a",
|
|
||||||
"name": "currentfeedin",
|
|
||||||
"displayName": "Current Feedin",
|
|
||||||
"displayNameEvent": "currentfeedinPrice changed",
|
|
||||||
"type": "double",
|
|
||||||
"minValue": 0,
|
|
||||||
"maxValue": 1000,
|
|
||||||
"unit":"KiloWattHour",
|
|
||||||
"defaultValue": 0,
|
|
||||||
"suggestLogging": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "52188fdf-4a4d-4ca8-b02e-cea5ed8c1615",
|
|
||||||
"name": "futurefeedin",
|
|
||||||
"displayName": "Future Feedin",
|
|
||||||
"displayNameEvent": "futurefeedinPrice changed",
|
|
||||||
"type": "double",
|
|
||||||
"minValue": 0,
|
|
||||||
"maxValue": 1000,
|
|
||||||
"unit":"KiloWattHour",
|
|
||||||
"defaultValue": 0,
|
|
||||||
"suggestLogging": true
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
102
v2xeamberelectric/integrationpluginv2xeamberelectric.json
Normal file
102
v2xeamberelectric/integrationpluginv2xeamberelectric.json
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
{
|
||||||
|
"name": "AmberElectric",
|
||||||
|
"displayName": "Amber Electric",
|
||||||
|
"id": "0233c848-6f6f-4907-a51c-81391e4f5356",
|
||||||
|
"vendors": [
|
||||||
|
{
|
||||||
|
"name": "AmberElectric",
|
||||||
|
"displayName": "Amber Electric",
|
||||||
|
"id": "ec1985b9-5891-435d-9264-e8e18d392978",
|
||||||
|
"thingClasses": [
|
||||||
|
{
|
||||||
|
"name": "V2XeAmberElectric",
|
||||||
|
"displayName": "Amber Electric - V2Xe Amber Electric",
|
||||||
|
"id": "11295990-7002-432e-b90c-cd4010548a32",
|
||||||
|
"setupMethod": "JustAdd",
|
||||||
|
"createMethods": ["User"],
|
||||||
|
"interfaces": ["smartmeter", "connectable"],
|
||||||
|
"paramTypes": [
|
||||||
|
{
|
||||||
|
"id": "fc899f7b-f452-44dc-b72e-ee7bb8034ff0",
|
||||||
|
"name": "authToken",
|
||||||
|
"displayName": "auth token",
|
||||||
|
"type" : "QString",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c50eac84-714e-4b9c-89d5-0b939b6c18d6",
|
||||||
|
"name": "currentSite",
|
||||||
|
"displayName": "current site",
|
||||||
|
"type" : "QString",
|
||||||
|
"defaultValue": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateTypes": [
|
||||||
|
{
|
||||||
|
"id": "faf2a6c0-1897-4b9b-903a-e12b281efe24",
|
||||||
|
"name": "connected",
|
||||||
|
"displayName": "Reachable",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false,
|
||||||
|
"cached": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "42c8a6f8-4f97-4871-8bfb-ac7e6ffffa74",
|
||||||
|
"name": "Sites",
|
||||||
|
"displayName": "Sites",
|
||||||
|
"type": "QString",
|
||||||
|
"writable": false,
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "27c3f8e0-0803-4eb8-ba4f-ce78fb0997a9",
|
||||||
|
"name": "Type",
|
||||||
|
"displayName": "type",
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": "Amber"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6e8d3fcd-c235-4793-95b5-321ca6e012a3",
|
||||||
|
"name": "forecastprice",
|
||||||
|
"displayName": "Feedin Price",
|
||||||
|
"type": "double",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"unit": "KiloWattHour",
|
||||||
|
"suggestLogging": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "a25d3b55-9b93-4465-90e3-5d36adb8fb23",
|
||||||
|
"name": "currentprice",
|
||||||
|
"displayName": "Current Price",
|
||||||
|
"type": "double",
|
||||||
|
"unit":"KiloWattHour",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"suggestLogging": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cd1e22b2-2154-453a-bbdf-59156893258a",
|
||||||
|
"name": "currentfeedin",
|
||||||
|
"displayName": "Current Feedin",
|
||||||
|
"type": "double",
|
||||||
|
"unit":"KiloWattHour",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"suggestLogging": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "52188fdf-4a4d-4ca8-b02e-cea5ed8c1615",
|
||||||
|
"name": "futurefeedin",
|
||||||
|
"displayName": "Future Feedin",
|
||||||
|
"type": "double",
|
||||||
|
"unit":"KiloWattHour",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"suggestLogging": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,399 +0,0 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
* *
|
|
||||||
* Copyright (C) 2024 devendragajjar <devendragajjar@gmail.com> *
|
|
||||||
* *
|
|
||||||
* This library is free software; you can redistribute it and/or *
|
|
||||||
* modify it under the terms of the GNU Lesser General Public *
|
|
||||||
* License as published by the Free Software Foundation; *
|
|
||||||
* version 3 of the License. *
|
|
||||||
* *
|
|
||||||
* This library 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 *
|
|
||||||
* Lesser General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU Lesser General Public *
|
|
||||||
* License along with this library; If not, see *
|
|
||||||
* <http://www.gnu.org/licenses/>. *
|
|
||||||
* *
|
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
||||||
|
|
||||||
#include "v2xe_amber_electric.h"
|
|
||||||
#include "plugininfo.h"
|
|
||||||
#include "hardwaremanager.h"
|
|
||||||
#include "network/networkaccessmanager.h"
|
|
||||||
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QSslConfiguration>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonValue>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const QString const_site = "01J1XBQFGX57137EH0C6AG040D";
|
|
||||||
const QString no_of_data_need = "5";
|
|
||||||
const QString site_http_link = "https://api.amber.com.au/v1/sites";
|
|
||||||
const QString price_http_link_front = "https://api.amber.com.au/v1/sites/";
|
|
||||||
const QString price_http_link_back = "/prices/current?next="+ no_of_data_need +"&previous=" + no_of_data_need;
|
|
||||||
//01J1XBQFGX57137EH0C6AG040D/prices/current?next=5&previous=5";
|
|
||||||
const QString auth_token = "f5b2c823de5fed2f4c6bdb7c1b0db4f5";
|
|
||||||
const QString renewble_http_link = "https://api.amber.com.au/v1/state/vic/renewables/current?next=48&previous=5&resolution=5";
|
|
||||||
|
|
||||||
|
|
||||||
v2xe_amber_electric::v2xe_amber_electric()
|
|
||||||
{
|
|
||||||
m_connectedStateTypeIds[V2Xe_Amber_ElectricThingClassId] = V2Xe_Amber_ElectricConnectedStateTypeId;
|
|
||||||
m_forecastPriceStateTypeIds[V2Xe_Amber_ElectricThingClassId] = V2Xe_Amber_ElectricForecastpriceStateTypeId;
|
|
||||||
m_currentPriceStateTypeIds[V2Xe_Amber_ElectricThingClassId] = V2Xe_Amber_ElectricCurrentpriceStateTypeId;
|
|
||||||
m_currentSiteTypeIds[V2Xe_Amber_ElectricThingClassId] = V2Xe_Amber_ElectricSitesStateTypeId;
|
|
||||||
m_currentfeddinStateTypeIds[V2Xe_Amber_ElectricThingClassId] = V2Xe_Amber_ElectricCurrentfeedinStateTypeId;
|
|
||||||
m_fururefeedinStateTypeIds[V2Xe_Amber_ElectricThingClassId] = V2Xe_Amber_ElectricFuturefeedinStateTypeId;
|
|
||||||
m_consumerKey = auth_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
v2xe_amber_electric::~v2xe_amber_electric()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void v2xe_amber_electric::init()
|
|
||||||
{
|
|
||||||
// Initialisation can be done here.
|
|
||||||
qCDebug(dcAmber_Electric_plgn()) << "Plugin initialized.";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void v2xe_amber_electric::setupThing(ThingSetupInfo *info)
|
|
||||||
{
|
|
||||||
// A thing is being set up. Use info->thing() to get details of the thing, do
|
|
||||||
// the required setup (e.g. connect to the device) and call info->finish() when done.
|
|
||||||
|
|
||||||
qCDebug(dcAmber_Electric_plgn()) << "Setup thing" << info->thing()->name() << info->thing()->params();
|
|
||||||
QString key = info->thing()->paramValue(V2Xe_Amber_ElectricThingAuth_tokenParamTypeId).toString();
|
|
||||||
if (!key.isEmpty()) {
|
|
||||||
m_consumerKey = key;
|
|
||||||
qCCritical(dcAmber_Electric_plgn()) << "m_consumerKey set " << m_consumerKey << "key " << key;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString site = info->thing()->paramValue(V2Xe_Amber_ElectricThingCrnt_siteParamTypeId).toString();
|
|
||||||
if (!site.isEmpty()) {
|
|
||||||
m_current_site = site;
|
|
||||||
qCCritical(dcAmber_Electric_plgn()) << "m_current_site set " << m_current_site ;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
m_current_site = const_site;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use defult key for now
|
|
||||||
qCCritical(dcAmber_Electric_plgn()) << "No API key set.";
|
|
||||||
qCCritical(dcAmber_Electric_plgn()) << "Either install an API key pacakge (nymea-apikeysprovider-plugin-*) or provide a key in the plugin settings.";
|
|
||||||
|
|
||||||
if (!m_pluginTimer) {
|
|
||||||
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(60);//TODO make 30 minutes after test
|
|
||||||
connect(m_pluginTimer, &PluginTimer::timeout, this, &v2xe_amber_electric::onPluginTimer);
|
|
||||||
}
|
|
||||||
info->finish(Thing::ThingErrorNoError);
|
|
||||||
}
|
|
||||||
|
|
||||||
void v2xe_amber_electric::onPluginTimer()
|
|
||||||
{
|
|
||||||
foreach (Thing *thing, myThings()) {
|
|
||||||
|
|
||||||
//requestPriceData(thing); // TODO
|
|
||||||
#if ENABLE_RENEWEBLE_API
|
|
||||||
requestRenewablesData(thing); //TODO
|
|
||||||
#endif
|
|
||||||
requestSiteData(thing);
|
|
||||||
requestSitePriceData(thing);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void v2xe_amber_electric::executeAction(ThingActionInfo *info)
|
|
||||||
{
|
|
||||||
// An action is being executed. Use info->action() to get details about the action,
|
|
||||||
// do the required operations (e.g. send a command to the network) and call info->finish() when done.
|
|
||||||
|
|
||||||
qCDebug(dcAmber_Electric_plgn()) << "Executing action for thing" << info->thing() << info->action().actionTypeId().toString() << info->action().params();
|
|
||||||
|
|
||||||
info->finish(Thing::ThingErrorNoError);
|
|
||||||
}
|
|
||||||
|
|
||||||
void v2xe_amber_electric::thingRemoved(Thing *thing)
|
|
||||||
{
|
|
||||||
// A thing is being removed from the system. Do the required cleanup
|
|
||||||
// (e.g. disconnect from the device) here.
|
|
||||||
|
|
||||||
qCDebug(dcAmber_Electric_plgn()) << "Remove thing" << thing;
|
|
||||||
}
|
|
||||||
|
|
||||||
void v2xe_amber_electric::requestSitePriceData(Thing* thing, ThingSetupInfo* setup) {
|
|
||||||
|
|
||||||
QString price_http_link = price_http_link_front + m_current_site + price_http_link_back;
|
|
||||||
|
|
||||||
m_serverUrls[V2Xe_Amber_ElectricThingClassId] = price_http_link;
|
|
||||||
|
|
||||||
QNetworkRequest request;
|
|
||||||
request.setUrl(QUrl(m_serverUrls[V2Xe_Amber_ElectricThingClassId]));
|
|
||||||
|
|
||||||
// Add the Authorization header with the token
|
|
||||||
QString token = thing->paramValue(m_consumerKey).toString();
|
|
||||||
token = m_consumerKey;
|
|
||||||
qCCritical(dcAmber_Electric_plgn) << " using m_consumerKey " <<m_consumerKey;
|
|
||||||
request.setRawHeader("Authorization", QString("Bearer %1").arg(token).toUtf8());
|
|
||||||
request.setRawHeader("accept", "application/json");
|
|
||||||
|
|
||||||
QNetworkReply* reply =hardwareManager()->networkManager()->get(request);
|
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, thing, setup, reply]() {
|
|
||||||
reply->deleteLater();
|
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
if (status != 200) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "Update reply HTTP error:" << status << reply->errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error getting data from server."));
|
|
||||||
} else {
|
|
||||||
//thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), false);//TODO remove comment
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onSitePriceDataReceived(thing, setup, reply);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void v2xe_amber_electric::onSitePriceDataReceived(Thing* thing, ThingSetupInfo* setup, QNetworkReply* reply) {
|
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "Network error:" << reply->errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Network error."));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonParseError error;
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
|
||||||
if (error.error != QJsonParseError::NoError) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "JSON parse error:" << error.errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("JSON parse error."));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jsonDoc.isArray()) {
|
|
||||||
QString channelType;
|
|
||||||
QJsonArray jsonArray = jsonDoc.array();
|
|
||||||
for (const QJsonValue &value : jsonArray) {
|
|
||||||
if (value.isObject()) {
|
|
||||||
QJsonObject jsonObject = value.toObject();
|
|
||||||
QString type = jsonObject["type"].toString(); //Get type
|
|
||||||
channelType = jsonObject["channelType"].toString();
|
|
||||||
|
|
||||||
//Current Price
|
|
||||||
if((type == "CurrentInterval") && channelType == "general"){
|
|
||||||
|
|
||||||
if (jsonObject.contains("perKwh") && jsonObject["perKwh"].isDouble()) { // Get perKwh
|
|
||||||
|
|
||||||
double perkwh = jsonObject["perKwh"].toDouble();
|
|
||||||
|
|
||||||
thing->setStateValue(m_currentPriceStateTypeIds.value(thing->thingClassId()), qAbs(perkwh));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Future Price
|
|
||||||
if((type == "ForecastInterval") && channelType == "general"){
|
|
||||||
|
|
||||||
if (jsonObject.contains("perKwh") && jsonObject["perKwh"].isDouble()) { // Get perKwh
|
|
||||||
|
|
||||||
double perkwh = jsonObject["perKwh"].toDouble();
|
|
||||||
|
|
||||||
thing->setStateValue(m_forecastPriceStateTypeIds.value(thing->thingClassId()), qAbs(perkwh));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Current Feedin //TODO what is feed in price its dummy data
|
|
||||||
if((type == "CurrentInterval") && (channelType == "feedIn")){
|
|
||||||
|
|
||||||
if (jsonObject.contains("perKwh") && jsonObject["perKwh"].isDouble()) { // Get SportPerKwh
|
|
||||||
double spotperkwh = jsonObject["perKwh"].toDouble();
|
|
||||||
|
|
||||||
thing->setStateValue(m_currentfeddinStateTypeIds.value(thing->thingClassId()), qAbs(spotperkwh));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Future Feedin
|
|
||||||
if((type == "ForecastInterval") && (channelType == "feedIn")){
|
|
||||||
|
|
||||||
if (jsonObject.contains("perKwh") && jsonObject["perKwh"].isDouble()) { // Get SportPerKwh
|
|
||||||
double spotperkwh = jsonObject["perKwh"].toDouble();
|
|
||||||
|
|
||||||
thing->setStateValue(m_fururefeedinStateTypeIds.value(thing->thingClassId()), qAbs(spotperkwh));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorNoError);
|
|
||||||
}
|
|
||||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void v2xe_amber_electric::requestSiteData(Thing* thing, ThingSetupInfo* setup) {
|
|
||||||
|
|
||||||
m_serverUrls[V2Xe_Amber_ElectricThingClassId] = site_http_link;
|
|
||||||
|
|
||||||
|
|
||||||
QNetworkRequest request;
|
|
||||||
request.setUrl(QUrl(m_serverUrls[V2Xe_Amber_ElectricThingClassId]));
|
|
||||||
|
|
||||||
// Add the Authorization header with the token
|
|
||||||
QString token = thing->paramValue(m_consumerKey).toString();
|
|
||||||
token = m_consumerKey;
|
|
||||||
qCCritical(dcAmber_Electric_plgn) << " using m_consumerKey " <<m_consumerKey;
|
|
||||||
request.setRawHeader("Authorization", QString("Bearer %1").arg(token).toUtf8());
|
|
||||||
request.setRawHeader("accept", "application/json");
|
|
||||||
|
|
||||||
QNetworkReply* reply =hardwareManager()->networkManager()->get(request);
|
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, thing, setup, reply]() {
|
|
||||||
reply->deleteLater();
|
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
if (status != 200) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "Update reply HTTP error:" << status << reply->errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error getting data from server."));
|
|
||||||
} else {
|
|
||||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
onSiteDataReceived(thing, setup, reply);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void v2xe_amber_electric::onSiteDataReceived(Thing* thing, ThingSetupInfo* setup, QNetworkReply* reply) {
|
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "Network error:" << reply->errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Network error."));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QVariantList stringList = {};
|
|
||||||
QString l_site;
|
|
||||||
QJsonParseError error;
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
|
||||||
if (error.error != QJsonParseError::NoError) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "JSON parse error:" << error.errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("JSON parse error."));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
qCCritical(dcAmber_Electric_plgn) << "onSiteDataReceived " ;
|
|
||||||
if (jsonDoc.isArray()) {
|
|
||||||
QJsonArray jsonArray = jsonDoc.array();
|
|
||||||
for (const QJsonValue &value : jsonArray) {
|
|
||||||
if (value.isObject()) {
|
|
||||||
QJsonObject jsonObject = value.toObject();
|
|
||||||
QString type = jsonObject["id"].toString(); //Get type
|
|
||||||
|
|
||||||
if(!type.isEmpty()){ //update
|
|
||||||
stringList.append(type);
|
|
||||||
qCCritical(dcAmber_Electric_plgn) << "type :" << type;
|
|
||||||
l_site = type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thing->setStateValue(m_currentSiteTypeIds.value(thing->thingClassId()), l_site);
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorNoError);
|
|
||||||
}
|
|
||||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_RENEWEBLE_API
|
|
||||||
void v2xe_amber_electric::requestRenewablesData(Thing* thing, ThingSetupInfo* setup) {
|
|
||||||
|
|
||||||
m_serverUrls[V2Xe_Amber_ElectricThingClassId] = renewble_http_link;
|
|
||||||
|
|
||||||
QNetworkRequest request;
|
|
||||||
request.setUrl(QUrl(m_serverUrls[V2Xe_Amber_ElectricThingClassId]));
|
|
||||||
|
|
||||||
// Add the Authorization header with the token
|
|
||||||
QString token = thing->paramValue(m_consumerKey).toString();
|
|
||||||
request.setRawHeader("Authorization", QString("Bearer %1").arg(token).toUtf8());
|
|
||||||
request.setRawHeader("accept", "application/json");
|
|
||||||
|
|
||||||
QNetworkReply* reply = hardwareManager()->networkManager()->get(request);
|
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, thing, setup, reply]() {
|
|
||||||
reply->deleteLater();
|
|
||||||
|
|
||||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
if (status != 200) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "Update reply HTTP error:" << status << reply->errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error getting data from server."));
|
|
||||||
} else {
|
|
||||||
//thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), false);//TODO remove comment
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onRenewablesDataReceived(thing, setup, reply);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void v2xe_amber_electric::onRenewablesDataReceived(Thing* thing, ThingSetupInfo* setup, QNetworkReply* reply) {
|
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "Network error:" << reply->errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Network error."));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonParseError error;
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
|
||||||
if (error.error != QJsonParseError::NoError) {
|
|
||||||
qCWarning(dcAmber_Electric_plgn) << "JSON parse error:" << error.errorString();
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("JSON parse error."));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jsonDoc.isArray()) {
|
|
||||||
QJsonArray jsonArray = jsonDoc.array();
|
|
||||||
for (const QJsonValue &value : jsonArray) {
|
|
||||||
if (value.isObject()) {
|
|
||||||
QJsonObject jsonObject = value.toObject();
|
|
||||||
QString type = jsonObject["type"].toString();
|
|
||||||
if (type == "ActualRenewable") {
|
|
||||||
//double renewables = jsonObject["renewables"].toDouble();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setup) {
|
|
||||||
setup->finish(Thing::ThingErrorNoError);
|
|
||||||
}
|
|
||||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
include($$[QT_INSTALL_PREFIX]/include/nymea/plugin.pri)
|
|
||||||
|
|
||||||
QT += network
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
v2xe_amber_electric.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
v2xe_amber_electric.h
|
|
||||||
|
|
||||||
DISTFILES += \
|
|
||||||
integrationpluginv2xe_amber_electric.json
|
|
||||||
|
|
||||||
297
v2xeamberelectric/v2xeamberelectric.cpp
Normal file
297
v2xeamberelectric/v2xeamberelectric.cpp
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2025 devendragajjar <devendragajjar@gmail.com> *
|
||||||
|
* *
|
||||||
|
* This library is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU Lesser General Public *
|
||||||
|
* License as published by the Free Software Foundation; *
|
||||||
|
* version 3 of the License. *
|
||||||
|
* *
|
||||||
|
* This library 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 *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; If not, see *
|
||||||
|
* <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "v2xeamberelectric.h"
|
||||||
|
#include "plugininfo.h"
|
||||||
|
#include "hardwaremanager.h"
|
||||||
|
#include "network/networkaccessmanager.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QSslConfiguration>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const QString constSite = "01J1XBQFGX57137EH0C6AG040D";
|
||||||
|
const QString noOfDataNeed = "5";
|
||||||
|
const QString siteHttpLink = "https://api.amber.com.au/v1/sites";
|
||||||
|
const QString priceHttpLinkFront = "https://api.amber.com.au/v1/sites/";
|
||||||
|
const QString priceHttpLinkBack = "/prices/current?next="+ noOfDataNeed +"&previous=" + noOfDataNeed;
|
||||||
|
const QString authToken = "f5b2c823de5fed2f4c6bdb7c1b0db4f5";
|
||||||
|
|
||||||
|
|
||||||
|
V2xeAmberElectric::V2xeAmberElectric()
|
||||||
|
{
|
||||||
|
mConsumerKey = authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
V2xeAmberElectric::~V2xeAmberElectric()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2xeAmberElectric::init()
|
||||||
|
{
|
||||||
|
// Initialisation can be done here.
|
||||||
|
qCDebug(dcAmberElectric()) << "Plugin initialized.";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void V2xeAmberElectric::setupThing(ThingSetupInfo *info)
|
||||||
|
{
|
||||||
|
// A thing is being set up. Use info->thing() to get details of the thing, do
|
||||||
|
// the required setup (e.g. connect to the device) and call info->finish() when done.
|
||||||
|
|
||||||
|
qCDebug(dcAmberElectric()) << "Setup thing" << info->thing()->name() << info->thing()->params();
|
||||||
|
QString key = info->thing()->paramValue(V2XeAmberElectricThingAuthTokenParamTypeId).toString();
|
||||||
|
if (!key.isEmpty()) {
|
||||||
|
mConsumerKey = key;
|
||||||
|
qCDebug(dcAmberElectric()) << "mConsumerKey set " << mConsumerKey << "key " << key;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString site = info->thing()->paramValue(V2XeAmberElectricThingCurrentSiteParamTypeId).toString();
|
||||||
|
if (!site.isEmpty()) {
|
||||||
|
mCurrentSite = site;
|
||||||
|
qCDebug(dcAmberElectric()) << "mCurrentSite set " << mCurrentSite ;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
mCurrentSite = constSite;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use default key for now
|
||||||
|
qCDebug(dcAmberElectric()) << "No API key set.";
|
||||||
|
qCDebug(dcAmberElectric()) << "Either install an API key pacakge (nymea-apikeysprovider-plugin-*) or provide a key in the plugin settings.";
|
||||||
|
|
||||||
|
if (!mPluginTimer) {
|
||||||
|
mPluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(30);//TODO make 30 minutes after test
|
||||||
|
connect(mPluginTimer, &PluginTimer::timeout, this, &V2xeAmberElectric::onPluginTimer);
|
||||||
|
}
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2xeAmberElectric::onPluginTimer()
|
||||||
|
{
|
||||||
|
foreach (Thing *thing, myThings()) {
|
||||||
|
|
||||||
|
requestSiteData(thing);
|
||||||
|
requestSitePriceData(thing);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2xeAmberElectric::executeAction(ThingActionInfo *info)
|
||||||
|
{
|
||||||
|
// An action is being executed. Use info->action() to get details about the action,
|
||||||
|
// do the required operations (e.g. send a command to the network) and call info->finish() when done.
|
||||||
|
|
||||||
|
qCDebug(dcAmberElectric()) << "Executing action for thing" << info->thing() << info->action().actionTypeId().toString() << info->action().params();
|
||||||
|
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2xeAmberElectric::thingRemoved(Thing *thing)
|
||||||
|
{
|
||||||
|
// A thing is being removed from the system. Do the required cleanup
|
||||||
|
// (e.g. disconnect from the device) here.
|
||||||
|
|
||||||
|
qCDebug(dcAmberElectric()) << "Remove thing" << thing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2xeAmberElectric::requestSitePriceData(Thing* thing, ThingSetupInfo* setup) {
|
||||||
|
|
||||||
|
QString price_http_link = priceHttpLinkFront + mCurrentSite + priceHttpLinkBack;
|
||||||
|
|
||||||
|
mServerUrls[V2XeAmberElectricThingClassId] = price_http_link;
|
||||||
|
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setUrl(QUrl(mServerUrls[V2XeAmberElectricThingClassId]));
|
||||||
|
|
||||||
|
// Add the Authorization header with the token
|
||||||
|
QString token = thing->paramValue(mConsumerKey).toString();
|
||||||
|
token = mConsumerKey;
|
||||||
|
qCDebug(dcAmberElectric) << " using mConsumerKey " <<mConsumerKey;
|
||||||
|
request.setRawHeader("Authorization", QString("Bearer %1").arg(token).toUtf8());
|
||||||
|
request.setRawHeader("accept", "application/json");
|
||||||
|
|
||||||
|
QNetworkReply* reply =hardwareManager()->networkManager()->get(request);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, thing, setup, reply]() {
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
if (status != 200) {
|
||||||
|
qCWarning(dcAmberElectric) << "Update reply HTTP error:" << status << reply->errorString();
|
||||||
|
if (setup) {
|
||||||
|
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error getting data from server."));
|
||||||
|
} else {
|
||||||
|
thing->setStateValue(V2XeAmberElectricConnectedStateTypeId, false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onSitePriceDataReceived(thing, setup, reply);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2xeAmberElectric::onSitePriceDataReceived(Thing* thing, ThingSetupInfo* setup, QNetworkReply* reply) {
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
qCWarning(dcAmberElectric) << "Network error:" << reply->errorString();
|
||||||
|
if (setup) {
|
||||||
|
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Network error."));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qCWarning(dcAmberElectric) << "JSON parse error:" << error.errorString();
|
||||||
|
if (setup) {
|
||||||
|
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("JSON parse error."));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonDoc.isArray()) {
|
||||||
|
QString channelType;
|
||||||
|
QJsonArray jsonArray = jsonDoc.array();
|
||||||
|
for (const QJsonValue &value : jsonArray) {
|
||||||
|
if (value.isObject()) {
|
||||||
|
QJsonObject jsonObject = value.toObject();
|
||||||
|
QString type = jsonObject["type"].toString(); //Get type
|
||||||
|
channelType = jsonObject["channelType"].toString();
|
||||||
|
//Current Price
|
||||||
|
if((type == "CurrentInterval") && channelType == "general"){
|
||||||
|
if (jsonObject.contains("perKwh") && jsonObject["perKwh"].isDouble()) { // Get perKwh
|
||||||
|
double perkwh = jsonObject["perKwh"].toDouble();
|
||||||
|
thing->setStateValue(V2XeAmberElectricCurrentpriceStateTypeId, qAbs(perkwh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Future Price
|
||||||
|
if((type == "ForecastInterval") && channelType == "general"){
|
||||||
|
if (jsonObject.contains("perKwh") && jsonObject["perKwh"].isDouble()) { // Get perKwh
|
||||||
|
double perkwh = jsonObject["perKwh"].toDouble();
|
||||||
|
thing->setStateValue(V2XeAmberElectricForecastpriceStateTypeId, qAbs(perkwh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Current Feedin //TODO what is feed in price its dummy data
|
||||||
|
if((type == "CurrentInterval") && (channelType == "feedIn")){
|
||||||
|
if (jsonObject.contains("perKwh") && jsonObject["perKwh"].isDouble()) { // Get SportPerKwh
|
||||||
|
double spotperkwh = jsonObject["perKwh"].toDouble();
|
||||||
|
thing->setStateValue(V2XeAmberElectricCurrentfeedinStateTypeId, qAbs(spotperkwh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Future Feedin
|
||||||
|
if((type == "ForecastInterval") && (channelType == "feedIn")){
|
||||||
|
if (jsonObject.contains("perKwh") && jsonObject["perKwh"].isDouble()) { // Get SportPerKwh
|
||||||
|
double spotperkwh = jsonObject["perKwh"].toDouble();
|
||||||
|
thing->setStateValue(V2XeAmberElectricFuturefeedinStateTypeId, qAbs(spotperkwh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setup) {
|
||||||
|
setup->finish(Thing::ThingErrorNoError);
|
||||||
|
}
|
||||||
|
thing->setStateValue(V2XeAmberElectricConnectedStateTypeId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void V2xeAmberElectric::requestSiteData(Thing* thing, ThingSetupInfo* setup) {
|
||||||
|
|
||||||
|
mServerUrls[V2XeAmberElectricThingClassId] = siteHttpLink;
|
||||||
|
|
||||||
|
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setUrl(QUrl(mServerUrls[V2XeAmberElectricThingClassId]));
|
||||||
|
|
||||||
|
// Add the Authorization header with the token
|
||||||
|
QString token = thing->paramValue(mConsumerKey).toString();
|
||||||
|
token = mConsumerKey;
|
||||||
|
qCDebug(dcAmberElectric) << " using mConsumerKey " <<mConsumerKey;
|
||||||
|
request.setRawHeader("Authorization", QString("Bearer %1").arg(token).toUtf8());
|
||||||
|
request.setRawHeader("accept", "application/json");
|
||||||
|
|
||||||
|
QNetworkReply* reply =hardwareManager()->networkManager()->get(request);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, thing, setup, reply]() {
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
if (status != 200) {
|
||||||
|
qCWarning(dcAmberElectric) << "Update reply HTTP error:" << status << reply->errorString();
|
||||||
|
if (setup) {
|
||||||
|
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error getting data from server."));
|
||||||
|
} else {
|
||||||
|
thing->setStateValue(V2XeAmberElectricConnectedStateTypeId, false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSiteDataReceived(thing, setup, reply);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void V2xeAmberElectric::onSiteDataReceived(Thing* thing, ThingSetupInfo* setup, QNetworkReply* reply) {
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
qCWarning(dcAmberElectric) << "Network error:" << reply->errorString();
|
||||||
|
if (setup) {
|
||||||
|
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Network error."));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QVariantList stringList = {};
|
||||||
|
QString l_site;
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qCWarning(dcAmberElectric) << "JSON parse error:" << error.errorString();
|
||||||
|
if (setup) {
|
||||||
|
setup->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("JSON parse error."));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(dcAmberElectric) << "onSiteDataReceived " ;
|
||||||
|
if (jsonDoc.isArray()) {
|
||||||
|
QJsonArray jsonArray = jsonDoc.array();
|
||||||
|
for (const QJsonValue &value : jsonArray) {
|
||||||
|
if (value.isObject()) {
|
||||||
|
QJsonObject jsonObject = value.toObject();
|
||||||
|
QString type = jsonObject["id"].toString(); //Get type
|
||||||
|
|
||||||
|
if(!type.isEmpty()){ //update
|
||||||
|
stringList.append(type);
|
||||||
|
qCDebug(dcAmberElectric) << "type :" << type;
|
||||||
|
l_site = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thing->setStateValue(V2XeAmberElectricSitesStateTypeId, l_site);
|
||||||
|
if (setup) {
|
||||||
|
setup->finish(Thing::ThingErrorNoError);
|
||||||
|
}
|
||||||
|
thing->setStateValue(V2XeAmberElectricConnectedStateTypeId, true);
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2020 devendragajjar <devendragajjar@gmail.com> *
|
* Copyright (C) 2025 devendragajjar <devendragajjar@gmail.com> *
|
||||||
* *
|
* *
|
||||||
* This library is free software; you can redistribute it and/or *
|
* This library is free software; you can redistribute it and/or *
|
||||||
* modify it under the terms of the GNU Lesser General Public *
|
* modify it under the terms of the GNU Lesser General Public *
|
||||||
@ -32,19 +32,18 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
|
||||||
#define ENABLE_RENEWEBLE_API 0
|
|
||||||
|
|
||||||
class v2xe_amber_electric: public IntegrationPlugin
|
class V2xeAmberElectric: public IntegrationPlugin
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginv2xe_amber_electric.json")
|
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginv2xeamberelectric.json")
|
||||||
Q_INTERFACES(IntegrationPlugin)
|
Q_INTERFACES(IntegrationPlugin)
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit v2xe_amber_electric();
|
explicit V2xeAmberElectric();
|
||||||
~v2xe_amber_electric();
|
~V2xeAmberElectric();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
@ -58,27 +57,15 @@ private slots:
|
|||||||
void onPluginTimer();
|
void onPluginTimer();
|
||||||
void requestSitePriceData(Thing* thing, ThingSetupInfo* setup = nullptr);
|
void requestSitePriceData(Thing* thing, ThingSetupInfo* setup = nullptr);
|
||||||
void requestSiteData(Thing* thing, ThingSetupInfo* setup = nullptr);
|
void requestSiteData(Thing* thing, ThingSetupInfo* setup = nullptr);
|
||||||
#if ENABLE_RENEWEBLE_API
|
|
||||||
void requestRenewablesData(Thing* thing, ThingSetupInfo* setup = nullptr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PluginTimer *m_pluginTimer = nullptr;
|
PluginTimer *mPluginTimer = nullptr;
|
||||||
QString m_consumerKey;
|
QString mConsumerKey;
|
||||||
QString m_current_site;
|
QString mCurrentSite;
|
||||||
QHash<ThingClassId, QString> m_serverUrls;
|
QHash<ThingClassId, QString> mServerUrls;
|
||||||
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIds;
|
|
||||||
QHash<ThingClassId, StateTypeId> m_forecastPriceStateTypeIds;
|
|
||||||
QHash<ThingClassId, StateTypeId> m_currentPriceStateTypeIds;
|
|
||||||
QHash<ThingClassId, StateTypeId> m_currentSiteTypeIds;
|
|
||||||
QHash<ThingClassId, StateTypeId> m_currentfeddinStateTypeIds;
|
|
||||||
QHash<ThingClassId, StateTypeId> m_fururefeedinStateTypeIds;
|
|
||||||
|
|
||||||
void onSiteDataReceived(Thing* thing, ThingSetupInfo* setup = nullptr, QNetworkReply* reply = nullptr);
|
void onSiteDataReceived(Thing* thing, ThingSetupInfo* setup = nullptr, QNetworkReply* reply = nullptr);
|
||||||
void onSitePriceDataReceived(Thing* thing, ThingSetupInfo* setup = nullptr, QNetworkReply* reply = nullptr);
|
void onSitePriceDataReceived(Thing* thing, ThingSetupInfo* setup = nullptr, QNetworkReply* reply = nullptr);
|
||||||
#if ENABLE_RENEWEBLE_API
|
|
||||||
void onRenewablesDataReceived(Thing* thing, ThingSetupInfo* setup = nullptr, QNetworkReply* reply = nullptr);
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INTEGRATIONPLUGINEV_CHARGER_H
|
#endif // INTEGRATIONPLUGINEV_CHARGER_H
|
||||||
13
v2xeamberelectric/v2xeamberelectric.pro
Normal file
13
v2xeamberelectric/v2xeamberelectric.pro
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
include(../plugins.pri)
|
||||||
|
|
||||||
|
QT += network
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
v2xeamberelectric.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
v2xeamberelectric.h
|
||||||
|
|
||||||
|
DISTFILES += \
|
||||||
|
integrationpluginv2xeamberelectric.json
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user