Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
# Conflicts:
#	__init__.py
  • Loading branch information
msinn committed Feb 13, 2022
2 parents 4c01047 + 54f78b8 commit e32b0ef
Show file tree
Hide file tree
Showing 236 changed files with 17,571 additions and 16,728 deletions.
2 changes: 1 addition & 1 deletion __init__.py
@@ -1,5 +1,5 @@
def plugin_release():
return '1.9.0'
return '1.9.1'

def plugin_branch():
return 'master'
Expand Down
9 changes: 5 additions & 4 deletions alexa/plugin.yaml
Expand Up @@ -3,8 +3,8 @@ plugin:
# Global plugin attributes
type: web # plugin type (gateway, interface, protocol, system, web)
description:
de: 'Plugin zur Ansteuerung von SmartHomeNG via Amazon Echo / Alexa, **seit SmartHomeNG v1.3**'
en: ''
de: 'Plugin zur Ansteuerung von SmartHomeNG via Amazon Echo / Alexa'
en: 'Plugin to control SmartHomeNG through an Amazon Echo (Alexa)'
maintainer: hotzen
tester: psilo909
state: deprecated
Expand All @@ -16,6 +16,7 @@ plugin:
sh_minversion: 1.3 # minimum shNG version to use this plugin
# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
multi_instance: False # plugin supports multi instance
restartable: unknown
classname: Alexa # class containing the plugin

parameters:
Expand All @@ -34,10 +35,10 @@ parameters:
de: 'Port Nummer des service Hosts'
en: 'port number of the service host'

item_attributes:
item_attributes: NONE
# Definition of item attributes defined by this plugin

item_structs:
item_structs: NONE
# Definition of item-structure templates for this plugin

plugin_functions: NONE
Expand Down
8 changes: 5 additions & 3 deletions appletv/plugin.yaml
Expand Up @@ -7,6 +7,7 @@ plugin:
en: 'Controls an Apple TV'
fr: 'Contrôle un Apple TV'
maintainer: Foxi352
tester: Foxi352
state: ready
keywords: appletv media
# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page
Expand All @@ -15,6 +16,7 @@ plugin:
version: 1.6.1 # Plugin version
sh_minversion: 1.6 # minimum shNG version to use this plugin
multi_instance: True # plugin supports multi instance
restartable: unknown
classname: AppleTV # class containing the plugin

parameters:
Expand All @@ -33,7 +35,7 @@ parameters:
en: 'Timeout in seconds to scan the local network for AppleTV devices'
fr: "Délai d'attente en secondes du scan réseau pour trouver les appareils AppleTV"

item_attributes:
item_attributes: NONE
# Definition of item attributes defined by this plugin

item_structs:
Expand Down Expand Up @@ -99,7 +101,7 @@ item_structs:
type: str
visu_acl: ro
cache: Yes
appletv@instance: playing_fingerprint
appletv@instance: playing_fingerprint
genre:
type: str
visu_acl: ro
Expand Down Expand Up @@ -155,7 +157,7 @@ item_structs:
type: str
visu_acl: ro
cache: Yes
appletv@instance: playing_repeat_text
appletv@instance: playing_repeat_text
shuffle:
type: num
visu_acl: rw
Expand Down
4 changes: 2 additions & 2 deletions asterisk/__init__.py
Expand Up @@ -321,9 +321,9 @@ def stop(self):
Stop method for the plugin
"""
self.logger.debug("Stop method called")
self._client.close()
if self._client.connected():
self._client.close()
self.alive = False
self._reply_lock.acquire()
self._reply_lock.notify()
self._reply_lock.release()
# self.close()
2 changes: 1 addition & 1 deletion asterisk/plugin.yaml
Expand Up @@ -12,7 +12,7 @@ plugin:
documentation: https://www.smarthomeng.de/user/plugins/asterisk/README.html
support: https://knx-user-forum.de/forum/supportforen/smarthome-py/
version: 1.4.0 # Plugin version
sh_minversion: 1.8.2a # minimum shNG version to use this plugin
sh_minversion: 1.9.0 # 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)
Expand Down
4 changes: 2 additions & 2 deletions avdevice/README.md
Expand Up @@ -13,8 +13,8 @@ Hopefully several different AV devices based on TCP or Serial RS232 connections
Tested with Pioneer (< 2016 models) and Denon AV receivers, Epson projector Oppo Bluray player

## Changelog
### planned for v1.6.3
* include model file for Anthem AV
### v1.6.3
* updated webinterface implementation, realtime values, fixes

### v1.6.2
* implement lineending send and response parameters
Expand Down
159 changes: 39 additions & 120 deletions avdevice/__init__.py
Expand Up @@ -43,6 +43,7 @@
from .AVDeviceFunctions import Translate
from .AVDeviceFunctions import ConvertValue
from .AVDeviceFunctions import CreateExpectedResponse
from .webif import WebInterface

VERBOSE1 = logging.DEBUG - 1
VERBOSE2 = logging.DEBUG - 2
Expand All @@ -52,13 +53,15 @@

class AVDevice(SmartPlugin):
ALLOW_MULTIINSTANCE = True
PLUGIN_VERSION = "1.6.2"
PLUGIN_VERSION = "1.6.3"

def __init__(self, smarthome):
super().__init__()
self.itemsApi = Items.get_instance()
if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5':
self.logger = logging.getLogger(__name__)
self.init_webinterface()
self.init_webinterface(WebInterface)
self._item_values = {}
try:
self.alive = False
self._name = self.get_fullname()
Expand Down Expand Up @@ -194,6 +197,7 @@ def _resetitem(self, founditem):
self._name, founditem, self._items[zone][itemlist]['Item'], search))
if founditem == search:
founditem(previousvalue, 'AVDevice', self._tcp)
self._update_item_values(founditem, previousvalue)
self.logger.info("Resetting {}: Item {} to {}".format(
self._name, founditem, previousvalue))
resetting = founditem
Expand All @@ -204,6 +208,7 @@ def _resetitem(self, founditem):
"Resetting {}: Search {} in {}.".format(self._name, founditem, compare))
if founditem == compare:
founditem(previousvalue, 'AVDevice', self._tcp)
self._update_item_values(founditem, previousvalue)
self.logger.info("Resetting {}: Item {} to {}".format(
self._name, founditem, previousvalue))
resetting = founditem
Expand Down Expand Up @@ -248,11 +253,13 @@ def _resetondisconnect(self, caller):
self._items_speakers[zone][itemlist]['Value'] = 0
speakeritem = self._items_speakers[zone][itemlist]['Item']
speakeritem(0, 'AVDevice', self._tcp)
self._update_item_values(speakeritem, 0)
self.logger.log(VERBOSE1,
'Resetting {}: Speakers to 0 for item {}'.format(self._name,
speakeritem))
speakeritem = self._items[zone]['speakers']['Item']
speakeritem(0, 'AVDevice', self._tcp)
self._update_item_values(speakeritem, 0)
self.logger.log(VERBOSE1,
'Resetting {}: Speakers to 0 for item {}'.format(self._name, speakeritem))
if 'volume' in self._items[zone].keys() and self._depend0_volume0 is True:
Expand All @@ -268,6 +275,21 @@ def _resetondisconnect(self, caller):
'Resetting {}: Not resetting on disconnect because this feature is disabled in the plugin config.'.format(
self._name))

def _update_item_values(self, item, payload):
"""
Update dict for periodic updates of the web interface
:param item:
:param payload:
"""
if not self._item_values.get(item.id()):
self._item_values[item.id()] = {}
if isinstance(payload, bool):
self._item_values[item.id()]['value'] = str(payload)
else:
self._item_values[item.id()]['value'] = payload
return

# Store actual value to a temporary dict for resetting purposes
def _write_itemsdict(self, data, found):
zone = updated = 0
Expand Down Expand Up @@ -425,7 +447,7 @@ def _parse_depend_item(self, item, info, zone):
"Initializing {}: Creating dependency for {} in {}: {}".format(self._name, info, zone, self._items[zone][info]))

def _logics_dependencies(self, zone=None, item=None):
deps = {'a': [], 'b':[], 'c':[], 'd':[]}
deps = {'a': [], 'b': [], 'c': [], 'd': []}
try:
info = item.property.path
search = 'Slave_item'
Expand All @@ -436,7 +458,7 @@ def _logics_dependencies(self, zone=None, item=None):
depitem = self._dependencies[search][zone].get(info)
for d in depitem:
deps[d.get('Group')].append("{}{}{}".format(d['Item'], d['Compare'], d['Dependvalue']))
deps = dict( [(k,v) for k,v in deps.items() if len(v)>0])
deps = dict([(k, v) for k, v in deps.items() if len(v) > 0])
except Exception as err:
deps = None
return deps
Expand Down Expand Up @@ -530,7 +552,8 @@ def _sortbuffer(buffer, bufferlist):

try:
buffer = ''
tidy = lambda c: re.sub(

def tidy(c): return re.sub(
r'(^\s*[{0}]+|^\s*\Z)|(\s*\Z|\s*[{0}]+)'.format(self._lineending_response),
lambda m: self._lineending_response if m.lastindex == 2 else '',
c)
Expand Down Expand Up @@ -564,8 +587,8 @@ def _sortbuffer(buffer, bufferlist):
try:
cond1 = not self._sendingcommand == 'done' and not self._sendingcommand == 'gaveup'
try:
cond2 = (self._sendingcommand.split(',')[2] == '' or self._sendingcommand.split(',')[2] == ' ' or
self._sendingcommand.split(',')[2] == 'none')
cond2 = (self._sendingcommand.split(',')[2] == '' or self._sendingcommand.split(',')[2] == ' '
or self._sendingcommand.split(',')[2] == 'none')
except Exception:
cond2 = self._sendingcommand == ''
if cond1 and not cond2:
Expand Down Expand Up @@ -798,9 +821,9 @@ def _sortbuffer(buffer, bufferlist):
maximum = abs(self._response_buffer) if type(self._response_buffer) is int else 11
# Removing empty entries
bufferlist = list(filter(lambda a: a != '', bufferlist))
newbuffer = [buf for buf in bufferlist if not buf.startswith(tuple(self._ignore_response)) and
'' not in self._ignore_response and
buf.startswith(tuple(self._response_commands))]
newbuffer = [buf for buf in bufferlist if not buf.startswith(tuple(self._ignore_response))
and '' not in self._ignore_response
and buf.startswith(tuple(self._response_commands))]
bufferlist = newbuffer[-1 * max(min(len(newbuffer), maximum), 0):]
buffering = False
if bufferlist:
Expand Down Expand Up @@ -1922,6 +1945,7 @@ def _duplicateindex(seq, seqitem):
self._name, av_function, value))

item(value, 'AVDevice', self._tcp)
self._update_item_values(item, value)
self.logger.debug("Parsing Input {}: Updated Item {} with {} Value: {}.".format(
self._name, item, expectedtype, value))
if av_function in self._items[zone].keys():
Expand Down Expand Up @@ -1983,7 +2007,7 @@ def _duplicateindex(seq, seqitem):
except Exception:
commanditem = None
if commanditem:
command = '{};{}'.format(command_split, commanditem)
command = '{};{}'.format(command_split, commanditem)
self.logger.log(VERBOSE1,
"Parsing Input {}: Reorder command commandsplit {}, commanditem {}. Command: {}".format(
self._name, command_split, commanditem, command))
Expand Down Expand Up @@ -2111,10 +2135,10 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl
except Exception:
depending = False
self.logger.log(VERBOSE1, "Updating Item {}: Depending is {}.".format(self._name, depending))
condition1 = (self.has_iattr(item.conf, 'avdevice') and
self.get_iattr_value(item.conf, 'avdevice') == 'reload')
condition2 = (self.has_iattr(item.conf, 'avdevice_zone0') and
self.get_iattr_value(item.conf, 'avdevice_zone0') == 'reload')
condition1 = (self.has_iattr(item.conf, 'avdevice')
and self.get_iattr_value(item.conf, 'avdevice') == 'reload')
condition2 = (self.has_iattr(item.conf, 'avdevice_zone0')
and self.get_iattr_value(item.conf, 'avdevice_zone0') == 'reload')
if condition1 or condition2:
self._initialize()
self.logger.info("Initializing {}: Reloaded Text file and functions".format(self._name))
Expand Down Expand Up @@ -3048,108 +3072,3 @@ def stop(self):
self._serialwrapper.close()
except Exception:
self.logger.log(VERBOSE1, "Stopping {}: No Serial socket to close.".format(self._name))

def init_webinterface(self):
""""
Initialize the web interface for this plugin
This method is only needed if the plugin is implementing a web interface
"""
try:
self.mod_http = Modules.get_instance().get_module('http')
except Exception:
self.mod_http = None
if self.mod_http is None:
self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname()))
return False

import sys
if "SmartPluginWebIf" not in list(sys.modules['lib.model.smartplugin'].__dict__):
self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname()))
return False

# set application configuration for cherrypy
webif_dir = self.path_join(self.get_plugin_dir(), 'webif')
config = {
'/': {
'tools.staticdir.root': webif_dir,
},
'/static': {
'tools.staticdir.on': True,
'tools.staticdir.dir': 'static'
}
}

# Register the web interface as a cherrypy app
self.mod_http.register_webif(WebInterface(webif_dir, self),
self.get_shortname(),
config,
self.get_classname(), self.get_instance_name(),
description='')

return True


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

import cherrypy
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 = logging.getLogger(__name__)
self.webif_dir = webif_dir
self.plugin = plugin
self.tplenv = self.init_template_environment()

@cherrypy.expose
def index(self, action=None, item_id=None, item_path=None, 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
"""
config_reloaded = False
keep_cleared = False
command_cleared = False
query_cleared = False
send_cleared = False
if action is not None:
if action == "reload":
self.plugin._initialize()
config_reloaded = True
if action == "connect":
self.plugin.connect('webif')
if action == "clear_query_history":
self.plugin._clear_history('query')
query_cleared = True
if action == "clear_send":
self.plugin._clear_history('send')
send_cleared = True
if action == "clear_command_history":
self.plugin._clear_history('command')
command_cleared = True
if action == "clear_keep_commands":
self.plugin._clear_history('keep')
keep_cleared = True

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,
config_reloaded=config_reloaded, query_cleared=query_cleared,
command_cleared=command_cleared, keep_cleared=keep_cleared, send_cleared=send_cleared,
language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now())

0 comments on commit e32b0ef

Please sign in to comment.