Skip to content

Commit

Permalink
Merge pull request #657 from Morg42/smartplugin-1
Browse files Browse the repository at this point in the history
smartplugin: add pause_item (instead of suspend item)
  • Loading branch information
onkelandy authored Jul 3, 2024
2 parents 3783a79 + 631ce46 commit 65903b9
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 247 deletions.
11 changes: 7 additions & 4 deletions dev/sample_module/module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ module:
# Global plugin attributes
classname: SampleModule
version: 1.0.0
sh_minversion: 1.8
# sh_maxversion: # maximum shNG version to use this module (leave empty if latest)
# py_minversion: 3.6 # minimum Python version to use for this module
# py_maxversion: # maximum Python version to use for this module (leave empty if latest)

# these min/max-versions MUST be given in quotes, or e.g. 3.10 will be interpreted as 3.1 (3.1 < 3.9 < 3.10)
sh_minversion: '1.10' # minimum shNG version to use this plugin
# sh_maxversion: '1.11' # maximum shNG version to use this plugin (omit if latest)
# py_minversion: '3.10' # minimum Python version to use for this plugin
# py_maxversion: '4.25' # maximum Python version to use for this plugin (omit if latest)

description:
de: 'Modul implementiert ...'
en: 'Module implements ...'
Expand Down
32 changes: 32 additions & 0 deletions dev/sample_mqttplugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def __init__(self, sh):
# Call init code of parent class (MqttPlugin)
super().__init__()

# if you want to use an item to toggle plugin execution, enable the
# definition in plugin.yaml and uncomment the following line
#self._pause_item_path = self.get_parameter_value('pause_item')

# Initialization code goes here

# On initialization error use:
Expand All @@ -78,6 +82,10 @@ def run(self):

self.alive = True

# let the plugin change the state of pause_item
if self._pause_item:
self._pause_item(False, self.get_fullname())

# start subscription to all topics
self.start_subscriptions()

Expand All @@ -88,6 +96,13 @@ def stop(self):
self.logger.dbghigh(self.translate("Methode '{method}' aufgerufen", {'method': 'stop()'}))
self.alive = False

# let the plugin change the state of pause_item
if self._pause_item:
self._pause_item(True, self.get_fullname())

# if you use schedulers, this stops all schedulers the plugin has started.
#self.scheduler_remove_all()

# stop subscription to all topics
self.stop_subscriptions()

Expand All @@ -104,6 +119,13 @@ def parse_item(self, item):
with the item, caller, source and dest as arguments and in case of the knx plugin the value
can be sent to the knx with a knx write function within the knx plugin.
"""
# check for pause item
if item.property.path == self._pause_item_path:
self.logger.debug(f'pause item {item.property.path} registered')
self._pause_item = item
self.add_item(item, updating=True)
return self.update_item

if self.has_iattr(item.conf, 'foo_itemid'):
self.logger.debug(f"parse item: {item.property.path}")

Expand Down Expand Up @@ -148,6 +170,16 @@ def update_item(self, item, caller=None, source=None, dest=None):
:param source: if given it represents the source
:param dest: if given it represents the dest
"""
# check for pause item
if item is self._pause_item:
if caller != self.get_shortname():
self.logger.debug(f'pause item changed to {item()}')
if item() and self.alive:
self.stop()
elif not item() and not self.alive:
self.run()
return

if self.alive and caller != self.get_shortname():
# code to execute if the plugin is not stopped
# and only, if the item has not been changed by this this plugin:
Expand Down
24 changes: 13 additions & 11 deletions dev/sample_mqttplugin/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,28 @@ plugin:
# support: https://knx-user-forum.de/forum/supportforen/smarthome-py

version: 1.0.0 # Plugin version
sh_minversion: 1.8 # minimum shNG version to use this plugin
# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
# py_minversion: 3.6 # minimum Python version to use for this plugin
# py_maxversion: # maximum Python version to use for this plugin (leave empty if latest)

# these min/max-versions MUST be given in quotes, or e.g. 3.10 will be interpreted as 3.1 (3.1 < 3.9 < 3.10)
sh_minversion: '1.10' # minimum shNG version to use this plugin
# sh_maxversion: '1.11' # maximum shNG version to use this plugin (omit if latest)
# py_minversion: '3.10' # minimum Python version to use for this plugin
# py_maxversion: '4.25' # maximum Python version to use for this plugin (omit if latest)

multi_instance: false # plugin supports multi instance
restartable: unknown
suspendable: false # plugin can be suspended, must be implemented in code
restartable: unknown # plugin supports stopping and starting again, must be implemented
classname: SamplePlugin # class containing the plugin

parameters:
# Definition of parameters to be configured in etc/plugin.yaml (enter 'parameters: NONE', if section should be empty)

# item to toggle suspend mode
suspend_item:
# item to toggle plugin execution, remove if not wanted
# (needs plugin to be restartable)
pause_item:
type: str
default: ''
description:
de: 'Item zum Schalten des Suspend-Modus'
en: 'item for toggling suspend mode'

de: 'Item, um die Ausführung des Plugins zu steuern'
en: 'item for controlling plugin execution'

item_attributes:
# Definition of item attributes defined by this plugin (enter 'item_attributes: NONE', if section should be empty)
Expand Down
52 changes: 49 additions & 3 deletions dev/sample_plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ def __init__(self, sh):
# (maybe you want to make it a plugin parameter?)
# self._cycle = 60

# if you want to use an item to toggle plugin execution, enable the
# definition in plugin.yaml and uncomment the following line
#self._pause_item_path = self.get_parameter_value('pause_item')

# Initialization code goes here

# On initialization error use:
Expand All @@ -88,10 +92,16 @@ def run(self):
Run method for the plugin
"""
self.logger.dbghigh(self.translate("Methode '{method}' aufgerufen", {'method': 'run()'}))

# connect to network / web / serial device
# (enable the following lines if you want to open a connection
# don't forget to implement a connect (and disconnect) method.. :) )
#self.connect()

# setup scheduler for device poll loop
# (enable the following line, if you need to poll the device.
# Rember to un-comment the self._cycle statement in __init__ as well)
#self.scheduler_add('poll_device', self.poll_device, cycle=self._cycle)
#self.scheduler_add(self.get_fullname() + '_poll', self.poll_device, cycle=self._cycle)

# Start the asyncio eventloop in it's own thread
# and set self.alive to True when the eventloop is running
Expand All @@ -100,8 +110,15 @@ def run(self):

self.alive = True # if using asyncio, do not set self.alive here. Set it in the session coroutine

# let the plugin change the state of pause_item
if self._pause_item:
self._pause_item(False, self.get_fullname())

# if you need to create child threads, do not make them daemon = True!
# They will not shutdown properly. (It's a python bug)
# Also, don't create the thread in __init__() and start them here, but
# create and start them here. Threads can not be restarted after they
# have been stopped...

def stop(self):
"""
Expand All @@ -110,13 +127,25 @@ def stop(self):
self.logger.dbghigh(self.translate("Methode '{method}' aufgerufen", {'method': 'stop()'}))
self.alive = False # if using asyncio, do not set self.alive here. Set it in the session coroutine

# if you use a scheduled poll loop, enable the following line
#self.scheduler_remove('poll_device')
# let the plugin change the state of pause_item
if self._pause_item:
self._pause_item(True, self.get_fullname())

# this stops all schedulers the plugin has started.
# you can disable/delete the line if you don't use schedulers
self.scheduler_remove_all()

# stop the asyncio eventloop and it's thread
# If you use asyncio, enable the following line
#self.stop_asyncio()

# If you called connect() on run(), disconnect here
# (remember to write a disconnect() method!)
#self.disconnect()

# also, clean up anything you set up in run(), so the plugin can be
# cleanly stopped and started again

def parse_item(self, item):
"""
Default plugin parse_item method. Is called when the plugin is initialized.
Expand All @@ -130,6 +159,13 @@ def parse_item(self, item):
with the item, caller, source and dest as arguments and in case of the knx plugin the value
can be sent to the knx with a knx write function within the knx plugin.
"""
# check for pause item
if item.property.path == self._pause_item_path:
self.logger.debug(f'pause item {item.property.path} registered')
self._pause_item = item
self.add_item(item, updating=True)
return self.update_item

if self.has_iattr(item.conf, 'foo_itemtag'):
self.logger.debug(f"parse item: {item}")

Expand Down Expand Up @@ -163,6 +199,16 @@ def update_item(self, item, caller=None, source=None, dest=None):
:param source: if given it represents the source
:param dest: if given it represents the dest
"""
# check for pause item
if item is self._pause_item:
if caller != self.get_shortname():
self.logger.debug(f'pause item changed to {item()}')
if item() and self.alive:
self.stop()
elif not item() and not self.alive:
self.run()
return

if self.alive and caller != self.get_fullname():
# code to execute if the plugin is not stopped
# and only, if the item has not been changed by this plugin:
Expand Down
23 changes: 13 additions & 10 deletions dev/sample_plugin/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,28 @@ plugin:
# support: https://knx-user-forum.de/forum/supportforen/smarthome-py

version: 1.0.0 # Plugin version (must match the version specified in __init__.py)
sh_minversion: 1.8 # minimum shNG version to use this plugin
# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
# py_minversion: 3.6 # minimum Python version to use for this plugin
# py_maxversion: # maximum Python version to use for this plugin (leave empty if latest)

# these min/max-versions MUST be given in quotes, or e.g. 3.10 will be interpreted as 3.1 (3.1 < 3.9 < 3.10)
sh_minversion: '1.10' # minimum shNG version to use this plugin
# sh_maxversion: '1.11' # maximum shNG version to use this plugin (omit if latest)
# py_minversion: '3.10' # minimum Python version to use for this plugin
# py_maxversion: '4.25' # maximum Python version to use for this plugin (omit if latest)

multi_instance: false # plugin supports multi instance
restartable: unknown
suspendable: false # plugin can be suspended, must be implemented in code
restartable: unknown # plugin supports stopping and starting again, must be implemented
classname: SamplePlugin # class containing the plugin

parameters:
# Definition of parameters to be configured in etc/plugin.yaml (enter 'parameters: NONE', if section should be empty)

# item to toggle suspend mode
suspend_item:
# item to toggle plugin execution, remove if not wanted
# (needs plugin to be restartable)
pause_item:
type: str
default: ''
description:
de: 'Item zum Schalten des Suspend-Modus'
en: 'item for toggling suspend mode'
de: 'Item, um die Ausführung des Plugins zu steuern'
en: 'item for controlling plugin execution'

param1:
type: str
Expand Down
9 changes: 7 additions & 2 deletions dev/sample_smartdevice_plugin/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ plugin:
# documentation: https://github.com/smarthomeNG/smarthome/wiki/
# support: https://knx-user-forum.de/forum/supportforen/smarthome-py/
version: 0.0.1 # !! adjust
sh_minversion: 1.9.5
py_minversion: 3.6

# these min/max-versions MUST be given in quotes, or e.g. 3.10 will be interpreted as 3.1 (3.1 < 3.9 < 3.10)
sh_minversion: '1.10' # minimum shNG version to use this plugin
# sh_maxversion: '1.11' # maximum shNG version to use this plugin (omit if latest)
# py_minversion: '3.10' # minimum Python version to use for this plugin
# py_maxversion: '4.25' # maximum Python version to use for this plugin (omit if latest)

multi_instance: true
restartable: true
suspendable: true # plugin can be suspended, implemented in sdp
Expand Down
9 changes: 7 additions & 2 deletions dev/sample_smartdevice_standalone_plugin/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ plugin:
# documentation: https://github.com/smarthomeNG/smarthome/wiki/
# support: https://knx-user-forum.de/forum/supportforen/smarthome-py/
version: 0.0.1 # !! adjust
sh_minversion: 1.9.5
py_minversion: 3.6

# these min/max-versions MUST be given in quotes, or e.g. 3.10 will be interpreted as 3.1 (3.1 < 3.9 < 3.10)
sh_minversion: '1.10' # minimum shNG version to use this plugin
# sh_maxversion: '1.11' # maximum shNG version to use this plugin (omit if latest)
# py_minversion: '3.10' # minimum Python version to use for this plugin
# py_maxversion: '4.25' # maximum Python version to use for this plugin (omit if latest)

multi_instance: true
restartable: true
suspendable: true # plugin can be suspended, implemented in sdp
Expand Down
4 changes: 1 addition & 3 deletions lib/model/mqttplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(self):
"""
Initialization Routine for the mqtt extension class to SmartPlugin
"""
SmartPlugin.__init__(self)
super().__init__()

# get instance of MQTT module
try:
Expand All @@ -60,8 +60,6 @@ def __init__(self):
# get broker configuration (for display in web interface)
self.broker_config = self.mod_mqtt.get_broker_config()

return True


def translate(self, txt, vars=None, block=None):
"""
Expand Down
Loading

0 comments on commit 65903b9

Please sign in to comment.