From ee205a5bd083bd1e9b733e595023f9d19ab40fea Mon Sep 17 00:00:00 2001 From: Devendra Date: Sun, 23 Mar 2025 01:36:56 +0530 Subject: [PATCH] Add v2xeamberelectric plugin in nymea_plugin_repo --- v2xeamberelectric/.gitignore | 43 ++ v2xeamberelectric/LICENSE.LGPL3 | 165 ++++++++ v2xeamberelectric/README.md | 8 + v2xeamberelectric/debian/changelog | 5 + v2xeamberelectric/debian/compat | 1 + v2xeamberelectric/debian/control | 26 ++ v2xeamberelectric/debian/copyright | 14 + .../nymea-plugin-v2xeambereletric.install.in | 1 + v2xeamberelectric/debian/rules | 29 ++ v2xeamberelectric/debian/source/format | 1 + .../integrationpluginv2xe_amber_electric.json | 176 ++++++++ v2xeamberelectric/v2xe_amber_electric.cpp | 399 ++++++++++++++++++ v2xeamberelectric/v2xe_amber_electric.h | 84 ++++ v2xeamberelectric/v2xe_amber_electric.pro | 13 + 14 files changed, 965 insertions(+) create mode 100644 v2xeamberelectric/.gitignore create mode 100644 v2xeamberelectric/LICENSE.LGPL3 create mode 100644 v2xeamberelectric/README.md create mode 100644 v2xeamberelectric/debian/changelog create mode 100644 v2xeamberelectric/debian/compat create mode 100644 v2xeamberelectric/debian/control create mode 100644 v2xeamberelectric/debian/copyright create mode 100644 v2xeamberelectric/debian/nymea-plugin-v2xeambereletric.install.in create mode 100644 v2xeamberelectric/debian/rules create mode 100644 v2xeamberelectric/debian/source/format create mode 100644 v2xeamberelectric/integrationpluginv2xe_amber_electric.json create mode 100644 v2xeamberelectric/v2xe_amber_electric.cpp create mode 100644 v2xeamberelectric/v2xe_amber_electric.h create mode 100644 v2xeamberelectric/v2xe_amber_electric.pro diff --git a/v2xeamberelectric/.gitignore b/v2xeamberelectric/.gitignore new file mode 100644 index 00000000..1625ed4e --- /dev/null +++ b/v2xeamberelectric/.gitignore @@ -0,0 +1,43 @@ +# 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 diff --git a/v2xeamberelectric/LICENSE.LGPL3 b/v2xeamberelectric/LICENSE.LGPL3 new file mode 100644 index 00000000..0a041280 --- /dev/null +++ b/v2xeamberelectric/LICENSE.LGPL3 @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. diff --git a/v2xeamberelectric/README.md b/v2xeamberelectric/README.md new file mode 100644 index 00000000..7c08a00d --- /dev/null +++ b/v2xeamberelectric/README.md @@ -0,0 +1,8 @@ +# v2xe_amber_electric_api +-------------------------------- + +Description of the plugin... + +plugin for amber electric api to get live data of energy use , + + diff --git a/v2xeamberelectric/debian/changelog b/v2xeamberelectric/debian/changelog new file mode 100644 index 00000000..ad09740e --- /dev/null +++ b/v2xeamberelectric/debian/changelog @@ -0,0 +1,5 @@ +nymea-plugin-v2xeamberelectric (0.0.1) bookworm; urgency=medium + + * Initial release. + + -- devendragajjar Mon, 21 Aug 2017 10:12:00 +0000 diff --git a/v2xeamberelectric/debian/compat b/v2xeamberelectric/debian/compat new file mode 100644 index 00000000..b4de3947 --- /dev/null +++ b/v2xeamberelectric/debian/compat @@ -0,0 +1 @@ +11 diff --git a/v2xeamberelectric/debian/control b/v2xeamberelectric/debian/control new file mode 100644 index 00000000..41a8107e --- /dev/null +++ b/v2xeamberelectric/debian/control @@ -0,0 +1,26 @@ +Source: nymea-plugin-v2xeamberelectric +Section: utils +Priority: optional +Maintainer: devendragajjar +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 diff --git a/v2xeamberelectric/debian/copyright b/v2xeamberelectric/debian/copyright new file mode 100644 index 00000000..7c431a35 --- /dev/null +++ b/v2xeamberelectric/debian/copyright @@ -0,0 +1,14 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: ${ProjectName} +Upstream-Contact: devendragajjar +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 + diff --git a/v2xeamberelectric/debian/nymea-plugin-v2xeambereletric.install.in b/v2xeamberelectric/debian/nymea-plugin-v2xeambereletric.install.in new file mode 100644 index 00000000..d434a6ea --- /dev/null +++ b/v2xeamberelectric/debian/nymea-plugin-v2xeambereletric.install.in @@ -0,0 +1 @@ +usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginEV_charger.so diff --git a/v2xeamberelectric/debian/rules b/v2xeamberelectric/debian/rules new file mode 100644 index 00000000..682dbb99 --- /dev/null +++ b/v2xeamberelectric/debian/rules @@ -0,0 +1,29 @@ +#!/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 + diff --git a/v2xeamberelectric/debian/source/format b/v2xeamberelectric/debian/source/format new file mode 100644 index 00000000..89ae9db8 --- /dev/null +++ b/v2xeamberelectric/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/v2xeamberelectric/integrationpluginv2xe_amber_electric.json b/v2xeamberelectric/integrationpluginv2xe_amber_electric.json new file mode 100644 index 00000000..30c11b16 --- /dev/null +++ b/v2xeamberelectric/integrationpluginv2xe_amber_electric.json @@ -0,0 +1,176 @@ +{ + "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": ["energystorage", "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": "price", + "displayName": "Feedin Price", + "displayNameEvent": "AveragePrice_changed", + "type": "double", + "minValue": 0, + "maxValue": 100, + "defaultValue": 100, + "unit": "EuroCentPerKiloWattHour", + "suggestLogging": true + }, + { + "id": "a25d3b55-9b93-4465-90e3-5d36adb8fb23", + "name": "currentprice", + "displayName": "Current Price", + "displayNameEvent": "currentPrice_changed", + "type": "double", + "minValue": 0, + "maxValue": 1000, + "unit":"EuroCentPerKiloWattHour", + "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":"EuroCentPerKiloWattHour", + "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":"EuroCentPerKiloWattHour", + "defaultValue": 0, + "suggestLogging": true + }, + { + "id": "690d562e-a75d-4da9-940f-e1908544dbae", + "name": "chargingState", + "displayName": "Charging state", + "displayNameEvent": "Charging state changed", + "type": "QString", + "possibleValues": ["idle", "charging", "discharging"], + "defaultValue": "idle" + }, + { + "id": "d5ce4925-49e5-49b6-88d8-6e3889080be2", + "name": "currentPower", + "displayName": "Current power", + "displayNameEvent": "Current power changed", + "type": "double", + "unit": "Watt", + "defaultValue": 0, + "cached": false, + "suggestLogging": true + }, + { + "id": "420d2e55-afeb-4a83-b67a-e3c0a86ecc02", + "name": "capacity", + "displayName": "Capacity", + "displayNameEvent": "Capacity changed", + "type": "double", + "unit": "KiloWattHour", + "defaultValue": 0 + }, + { + "id": "df196e56-f33a-4883-a9b4-345dab2bac95", + "name": "batteryLevel", + "displayName": "Battery level", + "displayNameEvent": "Battery level changed", + "type": "int", + "unit": "Percentage", + "defaultValue": "0", + "minValue": 0, + "maxValue": 100 + }, + { + "id": "6225b633-b159-4794-9e54-84912049fd32", + "name": "cellTemperature", + "displayName": "Cell temperature", + "displayNameEvent": "Cell temperature changed", + "type": "double", + "unit": "DegreeCelsius", + "defaultValue": "0", + "cached": false + }, + { + "id": "20410ff8-b9aa-4b63-a091-c3636278718e", + "name": "batteryCritical", + "displayName": "Battery level critical", + "displayNameEvent": "Battery level critical changed", + "type": "bool", + "defaultValue": false + } + + ] + } + ] + } + ] +} + + + diff --git a/v2xeamberelectric/v2xe_amber_electric.cpp b/v2xeamberelectric/v2xe_amber_electric.cpp new file mode 100644 index 00000000..060dfa4d --- /dev/null +++ b/v2xeamberelectric/v2xe_amber_electric.cpp @@ -0,0 +1,399 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2024 devendragajjar * + * * + * 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 * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "v2xe_amber_electric.h" +#include "plugininfo.h" +#include "hardwaremanager.h" +#include "network/networkaccessmanager.h" + +#include +#include +#include +#include +#include +#include + + + + +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 " <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 " <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 diff --git a/v2xeamberelectric/v2xe_amber_electric.h b/v2xeamberelectric/v2xe_amber_electric.h new file mode 100644 index 00000000..6f267fae --- /dev/null +++ b/v2xeamberelectric/v2xe_amber_electric.h @@ -0,0 +1,84 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2020 devendragajjar * + * * + * 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 * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef INTEGRATIONPLUGINEV_CHARGER_H +#define INTEGRATIONPLUGINEV_CHARGER_H + +#include "integrations/integrationplugin.h" +#include "extern-plugininfo.h" +#include "plugintimer.h" +#include "network/networkaccessmanager.h" + +#include +#include +#include +#include +#include + +#define ENABLE_RENEWEBLE_API 0 + +class v2xe_amber_electric: public IntegrationPlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginv2xe_amber_electric.json") + Q_INTERFACES(IntegrationPlugin) + + +public: + explicit v2xe_amber_electric(); + ~v2xe_amber_electric(); + + void init() override; + + void setupThing(ThingSetupInfo *info) override; + + void executeAction(ThingActionInfo *info) override; + + void thingRemoved(Thing *thing) override; + +private slots: + void onPluginTimer(); + void requestSitePriceData(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: + PluginTimer *m_pluginTimer = nullptr; + QString m_consumerKey; + QString m_current_site; + QHash m_serverUrls; + QHash m_connectedStateTypeIds; + QHash m_forecastPriceStateTypeIds; + QHash m_currentPriceStateTypeIds; + QHash m_currentSiteTypeIds; + QHash m_currentfeddinStateTypeIds; + QHash m_fururefeedinStateTypeIds; + + void onSiteDataReceived(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 diff --git a/v2xeamberelectric/v2xe_amber_electric.pro b/v2xeamberelectric/v2xe_amber_electric.pro new file mode 100644 index 00000000..5c58270e --- /dev/null +++ b/v2xeamberelectric/v2xe_amber_electric.pro @@ -0,0 +1,13 @@ +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 +