Skip to content

Commit

Permalink
Merge pull request #991 from sisamiwe/dev_tasmota
Browse files Browse the repository at this point in the history
Tasmota: Zigbee and WebIF improvement
  • Loading branch information
Morg42 authored Jan 13, 2025
2 parents 850341c + d59d67c commit 56a368f
Show file tree
Hide file tree
Showing 14 changed files with 1,726 additions and 930 deletions.
445 changes: 269 additions & 176 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
sh_minversion: 1.10.0.3 # minimum shNG version to use this plugin
# 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

0 comments on commit 56a368f

Please sign in to comment.