688 changes: 688 additions & 0 deletions rtr/_pv_1_2_4/__init__.py

Large diffs are not rendered by default.

145 changes: 145 additions & 0 deletions rtr/_pv_1_2_4/plugin.yaml
@@ -0,0 +1,145 @@
# Metadata for the Smart-Plugin
plugin:
type: system # plugin type (gateway, interface, protocol, system, web)
description: # Alternative: description in multiple languages
de: 'Raum Temperatur Regler'
en: 'Room Temperatur controller'
maintainer: Thomas Creutz / bmxp
tester: bmxp
state: ready
support: https://knx-user-forum.de/forum/supportforen/smarthome-py/31450-rtr-heizungs-plugin
documentation: https://www.smarthomeng.de/dev/user/plugins/rtr/README.html
version: 1.2.4 # Plugin version
sh_minversion: 1.2 # minimum shNG version to use this plugin
restartable: True
multi_instance: False # plugin supports multi instance
classname: RTR # class containing the plugin

parameters:
default_Kp:
type: int
default: 10
description:
de: 'Standard Verstärkungsfaktor für erstellte Items'
en: 'default proportional gain for created items'

default_Ki:
type: int
default: 15
description:
de: 'Standard Integralfaktor für erstellte Items'
en: 'default integral gain for created items'

cycle_time:
type: int
default: 60
description:
de: "Abständen in Sekunden, in denen die Regelung arbeitet. Dieser Wert sollte nur geändert werden, wenn man weiss was man tut!"
en: "Cycle timer in secounds. Don't change when you don't know what you do!"

defaultBoostTime:
type: int
default: 240
description:
de: "Legt die Standard Zeit in Minuten fest, nachdem die Boost-Temperatur automatisch zurück auf Standard gesetzt wird"
en: "Defines the default time in minutes, when the boost-temperature gets autmatically set back to Default"

defaultOnExpiredTimer:
type: bool
default: true
description:
de: "Wenn nicht aktiviert, werden beim wiederherstellen von abgelaufenen Timern die Temperaturen nicht zurück auf Default gesetzt"
en: "when not True, a expired timer will not set back to Default-Temperature on a timer restore (when SH will be restarted)"

defaultValveProtect:
type: bool
default: true
description:
de: "Wenn Wahr wird für alle Regler Ventilschutz voreingestellt"
en: "If True, all controller will preset to protect valves"

item_attributes:
rtr_current:
type: int
mandatory: True
description:
de: 'Ordnet das Item dem Regler/Controller mit gegebener ID als Ist-Wert zu'
en: 'Defines the Item as current value for the given controller ID'

rtr_Kp:
type: int
description:
de: 'Ordnet dem Item einen vom Standard abweichenden Verstärkungsfaktor zu. Muss auf dem selben Item wie rtr_current gesetzt werden'
en: 'Defines a different proportional gain for the controller. Only valid in the same Item where rtr_current is defined'

rtr_Ki:
type: int
description:
de: 'Ordnet dem Item einen vom Standard abweichenden Integralfaktor zu. Muss auf dem selben Item wie rtr_current gesetzt werden'
en: 'Defines a different integral gain for the controller. Only valid in the same Item where rtr_current is defined'

rtr_setpoint:
type: int
mandatory: True
description:
de: 'Ordnet das Item dem Regler/Controller mit gegebener ID als Soll-Wert zu'
en: 'Defines the Item as setpoint value for the given controller ID'

rtr_temp_default:
type: float
description:
de: 'Ordnet dem Regler/Controller eine Standard Temperatur zu, auf die rtr_setpoint zurück gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden'
en: 'Defines a default temperature for rtr_setpoint. Only valid in the same Item where rtr_setpoint is defined'

rtr_temp_drop:
type: float
description:
de: 'Ordnet dem Regler/Controller eine Absenk-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion drop gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden'
en: 'Defines a drop temperature for rtr_setpoint, which is set by calling the drop function. Only valid in the same Item where rtr_setpoint is defined'

rtr_temp_boost:
type: float
description:
de: 'Ordnet dem Regler eine Boost-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion boost gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden'
en: 'Defines a boost temperature for rtr_setpoint, which is set by calling the boost function. Only valid in the same Item where rtr_setpoint is defined'

rtr_temp_boost_time:
type: int
description:
de: 'Ordnet dem Regler eine Standard Zeit für den Boost in Minten zu und überschreibt somit den globalen Standard defaultBoostTime. Muss auf dem selben Item wie rtr_setpoint gesetzt werden'
en: 'Defines a default boost time in minutes for this controller and so overrides the global defaultBoostTime. Only valid in the same Item where rtr_setpoint is defined'

rtr_actuator:
type: int
mandatory: True
description:
de: 'Ordnet das Item dem Controller mit gegebener ID als Stellgröße zu'
en: 'Defines the Item as actuator value for the given controller ID'

rtr_valve_protect:
type: bool
description:
de: 'Aktiviert den Ventilschutz für diesen Controller'
en: 'Activates the valve protection for this controller ID'

rtr_hvac_mode:
type: int
description:
de: 'Setzt den Modus'
en: 'Sets the mode'

rtr_stops:
type: list(int)
description:
de: 'Ordnet das Item dem einen oder mehreren Controllern per ID als Stop-Objekt zu. Kann nur auf einem Item vom Typ Bool gesetzt werden. Ist der Item Wert True, Pausiert die Regelung'
en: 'Defines the Item as stop item for the given controller IDs. Only valid on Item-Type Bool. If Item is True, the controller gets paused'

item_structs: NONE
# Definition of item-structure templates for this plugin (enter 'item_structs: NONE', if section should be empty)

logic_parameters: NONE
# Definition of logic parameters defined by this plugin

plugin_functions: NONE
# Definition of function interface of the plugin

11 changes: 11 additions & 0 deletions rtr/locale.yaml
@@ -0,0 +1,11 @@
# translations for the web interface
plugin_translations:
# Translations for the plugin specially for the web interface
'Wert 2': {'de': '=', 'en': 'Value 2'}
'Wert 4': {'de': '=', 'en': 'Value 4'}

# Alternative format for translations of longer texts:
'Hier kommt der Inhalt des Webinterfaces hin.':
de: '='
en: 'Here goes the content of the web interface.'

6 changes: 3 additions & 3 deletions rtr/plugin.yaml
Expand Up @@ -3,14 +3,14 @@ plugin:
type: system # plugin type (gateway, interface, protocol, system, web)
description: # Alternative: description in multiple languages
de: 'Raum Temperatur Regler'
en: 'Room Temperatur controller'
en: 'Room Temperature controller'
maintainer: Thomas Creutz / bmxp
tester: bmxp
state: ready
support: https://knx-user-forum.de/forum/supportforen/smarthome-py/31450-rtr-heizungs-plugin
documentation: https://www.smarthomeng.de/dev/user/plugins/rtr/README.html
version: 1.2.4 # Plugin version
sh_minversion: 1.2 # minimum shNG version to use this plugin
version: 1.6.0 # Plugin version
sh_minversion: 1.6 # minimum shNG version to use this plugin
restartable: True
multi_instance: False # plugin supports multi instance
classname: RTR # class containing the plugin
Expand Down
102 changes: 102 additions & 0 deletions rtr/webif/__init__.py
@@ -0,0 +1,102 @@
#!/usr/bin/env python3
# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
#########################################################################
# Copyright 2020- <AUTHOR> <EMAIL>
#########################################################################
# This file is part of SmartHomeNG.
# https://www.smarthomeNG.de
# https://knx-user-forum.de/forum/supportforen/smarthome-py
#
# Sample plugin for new plugins to run with SmartHomeNG version 1.5 and
# upwards.
#
# SmartHomeNG is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# SmartHomeNG is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with SmartHomeNG. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################

import datetime
import time
import os

from lib.item import Items
from lib.model.smartplugin import SmartPluginWebIf


# ------------------------------------------
# Webinterface of the plugin
# ------------------------------------------

import cherrypy
import csv
from jinja2 import Environment, FileSystemLoader


class WebInterface(SmartPluginWebIf):

def __init__(self, webif_dir, plugin):
"""
Initialization of instance of class WebInterface
:param webif_dir: directory where the webinterface of the plugin resides
:param plugin: instance of the plugin
:type webif_dir: str
:type plugin: object
"""
self.logger = plugin.logger
self.webif_dir = webif_dir
self.plugin = plugin
self.items = Items.get_instance()

self.tplenv = self.init_template_environment()


@cherrypy.expose
def index(self, reload=None):
"""
Build index.html for cherrypy
Render the template and return the html file to be delivered to the browser
:return: contents of the template after beeing rendered
"""
tmpl = self.tplenv.get_template('index.html')
# add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...)
return tmpl.render(p=self.plugin, items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path'])))


@cherrypy.expose
def get_data_html(self, dataSet=None):
"""
Return data to update the webpage
For the standard update mechanism of the web interface, the dataSet to return the data for is None
:param dataSet: Dataset for which the data should be returned (standard: None)
:return: dict with the data needed to update the web page.
"""
if dataSet is None:
# get the new data
data = {}

# data['item'] = {}
# for i in self.plugin.items:
# data['item'][i]['value'] = self.plugin.getitemvalue(i)
#
# return it as json the the web page
# try:
# return json.dumps(data)
# except Exception as e:
# self.logger.error("get_data_html exception: {}".format(e))
return {}

6 changes: 6 additions & 0 deletions rtr/webif/static/img/readme.txt
@@ -0,0 +1,6 @@
This directory is for storing images that are used by the web interface.

If you want to have your own logo on the top of the web interface, store it here and name it plugin_logo.<extension>.

Extension can be png, svg or jpg

135 changes: 135 additions & 0 deletions rtr/webif/templates/index.html
@@ -0,0 +1,135 @@
{% extends "base_plugin.html" %}

{% set logo_frame = false %}

<!-- set update_interval to a value > 0 (in milliseconds) to enable periodic data updates -->
{% set update_interval = 0 %}

<!--
Additional script tag for plugin specific javascript code go into this block
-->
{% block pluginscripts %}
<script>
function handleUpdatedData(response, dataSet=null) {
if (dataSet === 'devices_info' || dataSet === null) {
var objResponse = JSON.parse(response);
myProto = document.getElementById(dataSet);
for (var device in objResponse) {
<!--
shngInsertText (device+'_source', objResponse[device]['source']);
shngInsertText (device+'_powerState', objResponse[device]['powerState']);
-->
}
}
}
</script>
{% endblock pluginscripts %}


{% block headtable %}
<table class="table table-striped table-hover">
<tbody>
<tr>
<td class="py-1"><strong>default_Kp</strong></td>
<td class="py-1">{{ p._defaults['Kp'] }}</td>
<td class="py-1" width="50px"></td>
<td class="py-1"><strong>defaultBoostTime</strong></td>
<td class="py-1">{{ p._defaults['tempBoostTime'] }}</td>
<td class="py-1" width="50px"></td>
</tr>
<tr>
<td class="py-1"><strong>default_Ki</strong></td>
<td class="py-1">{{ p._defaults['Ki'] }}</td>
<td></td>
<td class="py-1"><strong>defaultOnExpiredTimer</strong></td>
<td class="py-1">{{ p._defaultOnExpiredTimer }}</td>
<td></td>
</tr>
<tr>
<td class="py-1"><strong>cycle_time</strong></td>
<td class="py-1">{{ p._cycle_time }}</td>
<td></td>
<td class="py-1"><strong>default ValveProtect</strong></td>
<td class="py-1">{{ p._defaults['valveProtect'] }}</td>
<td></td>
</tr>
</tbody>
</table>
{% endblock headtable %}


<!--
Additional buttons for the web interface (if any are needed) - displayed below the headtable-section
-->
{% block buttons %}
{% if 1==2 %}
<div>
<button id="btn1" class="btn btn-shng btn-sm" name="scan" onclick="shngPost('', {learn: 'on'})"><i class="fas fa-question"></i>&nbsp;&nbsp;&nbsp;{{ _('nach Devices suchen') }}&nbsp;</button>
</div>
{% endif %}
{% endblock %}

<!--
Define the number of tabs for the body of the web interface (1 - 3)
-->
{% set tabcount = 1 %}


<!--
Set the tab that will be visible on start, if another tab that 1 is wanted (1 - 3)
-->
{% if item_count==0 %}
{% set start_tab = 2 %}
{% endif %}


<!--
Content block for the first tab of the Webinterface
-->
{% set tab1title = "<strong>" ~ p.get_shortname() ~ " Controller</strong>" %}
{% block bodytab1 %}
<div class="container-fluid m-2">
{% for c in p._controller %}
<h2>{{ c }}</h2>
<table>
{% set pairs = p._controller[c] %}
{% for key in pairs %}
<tr>
<td>{{ key }}</td><td>{{ pairs[key] }}</td>
</tr>
{% endfor %}
</table>
</li>
{% endfor %}
</div>
{% endblock bodytab1 %}


<!--
Content block for the second tab of the Webinterface
-->
{% set tab2title = "<strong>" ~ p.get_shortname() ~ " Geräte</strong> (" ~ device_count ~ ")" %}
{% block bodytab2 %}
{% endblock bodytab2 %}


<!--
Content block for the third tab of the Webinterface
If wanted, a title for the tab can be defined as:
{% set tab3title = "<strong>" ~ p.get_shortname() ~ " Geräte</strong>" %}
It has to be defined before (and outside) the block bodytab3
-->
{% block bodytab3 %}
{% endblock bodytab3 %}


<!--
Content block for the fourth tab of the Webinterface
If wanted, a title for the tab can be defined as:
{% set tab4title = "<strong>" ~ p.get_shortname() ~ " Geräte</strong>" %}
It has to be defined before (and outside) the block bodytab4
-->
{% block bodytab4 %}
{% endblock bodytab4 %}