Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tasmota: Zigbee and WebIF improvement #991

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 176 additions & 86 deletions tasmota/__init__.py

Large diffs are not rendered by default.

Empty file modified tasmota/locale.yaml
100755 → 100644
Empty file.
7 changes: 2 additions & 5 deletions tasmota/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ plugin:
documentation: http://smarthomeng.de/user/plugins/tasmota/user_doc.html
support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1520293-support-thread-für-das-tasmota-plugin

version: 1.5.2 # Plugin version
sh_minversion: '1.9.3' # minimum shNG version to use this plugin
version: 1.6.0 # Plugin version
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Versionsnummer idealerweise immer quoten (Eindeutigkeit)

sh_minversion: 1.10.0. # minimum shNG version to use this plugin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'1.10.0' oder '1.10.0.3', aber nicht mit "." enden lassen -> startet nicht

# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
# py_minversion: # minimum Python version to use for this plugin
multi_instance: True # plugin supports multi instance
Expand All @@ -38,7 +38,6 @@ parameters:
de: 'Zeitabstand in Sekunden in dem die Tasmota Devices Telemetrie Daten senden sollen'
en: 'Timeperiod in seconds in which Tasmota devices shall send telemetry data'


item_attributes:
tasmota_topic:
type: str
Expand Down Expand Up @@ -128,5 +127,3 @@ item_structs: NONE
plugin_functions: NONE

logic_parameters: NONE


11 changes: 10 additions & 1 deletion tasmota/user_doc.rst
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ folgenden Beispiel gezeigt:
tasmota_zb_device: snzb02_01
tasmota_zb_attr: Temperature

Das Plugin versucht eine ZigBee-Bridge automatisch zu erkennen. Zudem kann diese auch per Attribut dediziert definiert werden:

.. code-block:: yaml

temp:
type: num
tasmota_topic: ZB-GW03_01
tasmota_zb_device: bridge

Für die Nutzung von SML Devices über ein Tasmota-Gerät müssen in dem entsprechenden Item die drei Attribute
``tasmota_topic``, ``tasmota_sml_device`` und ``tasmota_sml_attr`` konfiguriert werden, wie im
folgenden Beispiel gezeigt:
Expand Down Expand Up @@ -147,7 +156,7 @@ Die folgenden Attribute (Werte für das Item-Attribut ``tasmota-attr``) sind bis
* "rf_send": Zu sendende RF Daten bei Tasmota Device mit RF Sendemöglichkeit (SONOFF RF Bridge) -> dict {'RfSync': 12220, 'RfLow': 440, 'RfHigh': 1210, 'RfCode':'#F06104'}, r/w
* "rf_key_send": Zu sendender RF-Key Tasmota Device mit RF Sendemöglichkeit (SONOFF RF Bridge) -> num [1-16], r/w
* "rf_key_recv": Zu empfangender RF-Key Tasmota Device mit RF Sendemöglichkeit (SONOFF RF Bridge) -> num [1-16], r/w
* rf_key: 'RF Key'
* "rf_key": RF Key
* "zb_permit_join": Schaltet das Pairing an der ZigBee Bridge ein/aus -> bool, r/w
* "zb_forget": Löscht das Zigbee-Gerät aus dem Item Wert aus der Liste bekannter Geräte in der Zigbee-Bridge -> str, r/w
* "zb_ping": Sendet ein Ping zum Zigbee-Gerät aus dem Item Wert -> str, r/w
Expand Down
Empty file modified tasmota/user_doc/assets/webif_tab1.jpg
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified tasmota/user_doc/assets/webif_tab2.jpg
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified tasmota/user_doc/assets/webif_tab3.jpg
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified tasmota/user_doc/assets/webif_tab4.jpg
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified tasmota/user_doc/assets/webif_tab5.jpg
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified tasmota/user_doc/assets/webif_tab6.jpg
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
137 changes: 95 additions & 42 deletions tasmota/webif/__init__.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,19 @@ def index(self, reload=None):
"""
self.plugin.get_broker_info()

pagelength = self.plugin.get_parameter_value('webif_pagelength')
tmpl = self.tplenv.get_template('index.html')

items = self.plugin.get_item_list()

return tmpl.render(p=self.plugin,
webif_pagelength=pagelength,
items=items,
item_count=len(items),
plugin_shortname=self.plugin.get_shortname(),
plugin_version=self.plugin.get_version(),
plugin_info=self.plugin.get_info(),
webif_pagelength=self.plugin.get_parameter_value('webif_pagelength'),
item_count=len(self.plugin.get_item_list()),
zigbee = True if self.plugin.tasmota_zigbee_devices else False,
broker_config = self.plugin.broker_config,
full_topic = self.plugin.full_topic,
maintenance=True if self.plugin.log_level == 10 else False,
)

@cherrypy.expose
def get_data_html(self, dataSet=None):
def get_data_html(self, dataSet=None, params=None):
"""
Return data to update the webpage

Expand All @@ -91,37 +87,94 @@ def get_data_html(self, dataSet=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

self.logger.debug(f"get_data_html: {dataSet=}, {params=}")

data = dict()

if dataSet == "items_info":
data[dataSet] = {}
for item in self.plugin.get_item_list():
item_data = {
'value': item.property.value,
'type': item.property.type,
'topic': self.plugin.get_iattr_value(item.conf, 'tasmota_topic'),
'relais': self._get_relay_value(item),
'last_update': item.property.last_update.strftime('%d.%m.%Y %H:%M:%S'),
'last_change': item.property.last_change.strftime('%d.%m.%Y %H:%M:%S'),
}
data['items_info'][item.property.path] = item_data

elif dataSet == "devices_info":
data[dataSet] = {}
for device_name, device_data in self.plugin.tasmota_devices.items():
device_data = device_data.copy()
device_data.pop('discovery_config', None)
data[dataSet][device_name] = device_data

elif dataSet == "zigbee_info":
data[dataSet] = self.plugin.tasmota_zigbee_devices.copy()

elif dataSet == "broker_info":
self.plugin.get_broker_info()
data = dict()
data['broker_info'] = self.plugin._broker
data['broker_uptime'] = self.plugin.broker_uptime()
data[dataSet] = self.plugin._broker.copy()
data[dataSet]['broker_uptime'] = self.plugin.broker_uptime()

elif dataSet == "details_info":
data['devices_info'] = {}
for device_name, device_data in self.plugin.tasmota_devices.items():
device_data = device_data.copy()
device_data.pop('discovery_config', None)
data['devices_info'][device_name] = device_data
data['zigbee_info'] = self.plugin.tasmota_zigbee_devices.copy()

# return it as json the web page
try:
return json.dumps(data, default=str)
except Exception as e:
self.logger.error("get_data_html exception: {}".format(e))
return {}

data['item_values'] = {}
for item in self.plugin.get_item_list():
data['item_values'][item.property.path] = {}
data['item_values'][item.property.path]['value'] = item.property.value
data['item_values'][item.property.path]['last_update'] = item.property.last_update.strftime('%d.%m.%Y %H:%M:%S')
data['item_values'][item.property.path]['last_change'] = item.property.last_change.strftime('%d.%m.%Y %H:%M:%S')

data['device_values'] = {}
for device in self.plugin.tasmota_devices:
data['device_values'][device] = {}
data['device_values'][device]['online'] = self.plugin.tasmota_devices[device].get('online', '-')
data['device_values'][device]['uptime'] = self.plugin.tasmota_devices[device].get('uptime', '-')
data['device_values'][device]['fw_ver'] = self.plugin.tasmota_devices[device].get('fw_ver', '-')
data['device_values'][device]['wifi_signal'] = self.plugin.tasmota_devices[device].get('wifi_signal', '-')
data['device_values'][device]['sensors'] = self.plugin.tasmota_devices[device].get('sensors', '-')
data['device_values'][device]['lights'] = self.plugin.tasmota_devices[device].get('lights', '-')
data['device_values'][device]['rf'] = self.plugin.tasmota_devices[device].get('rf', '-')

data['tasmota_zigbee_devices'] = self.plugin.tasmota_zigbee_devices

# return it as json the web page
try:
return json.dumps(data, default=str)
except Exception as e:
self.logger.error("get_data_html exception: {}".format(e))
return {}
return

@cherrypy.expose
def submit(self, cmd=None, params=None):

self.logger.debug(f"submit: {cmd=}, {params=}")
result = None

if cmd == "zbstatus":
result = self.plugin._poll_zigbee_devices()

elif cmd == "tasmota_status":
result = self.plugin._interview_device(params)

elif cmd == "zb_ping":
result = self.plugin._poll_zigbee_device(params)

self.logger.debug(f"submit: {cmd=}, {params=} --> {result=}")

if result is not None:
# JSON zurücksenden
cherrypy.response.headers['Content-Type'] = 'application/json'
self.logger.debug(f"Result for web interface: {result}")
return json.dumps(result).encode('utf-8')

def _get_relay_value(self, item):
"""
Determines the relay value based on item configuration.

Args:
item: The item object containing configuration data.
Returns:
The relay value as a string.
"""

relay = self.plugin.get_iattr_value(item.conf, 'tasmota_relay')
if relay in ['1', '2', '3', '4', '5', '6', '7', '8']:
return relay

if self.plugin.get_iattr_value(item.conf, 'tasmota_attr') == 'relay':
return "1"

return "-"

Empty file modified tasmota/webif/static/img/plugin_logo.svg
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified tasmota/webif/static/img/readme.txt
100755 → 100644
Empty file.
Loading