Skip to content

Commit e32b0ef

Browse files
committed
Merge branch 'develop'
# Conflicts: # __init__.py
2 parents 4c01047 + 54f78b8 commit e32b0ef

236 files changed

Lines changed: 17571 additions & 16728 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
def plugin_release():
2-
return '1.9.0'
2+
return '1.9.1'
33

44
def plugin_branch():
55
return 'master'

alexa/plugin.yaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ plugin:
33
# Global plugin attributes
44
type: web # plugin type (gateway, interface, protocol, system, web)
55
description:
6-
de: 'Plugin zur Ansteuerung von SmartHomeNG via Amazon Echo / Alexa, **seit SmartHomeNG v1.3**'
7-
en: ''
6+
de: 'Plugin zur Ansteuerung von SmartHomeNG via Amazon Echo / Alexa'
7+
en: 'Plugin to control SmartHomeNG through an Amazon Echo (Alexa)'
88
maintainer: hotzen
99
tester: psilo909
1010
state: deprecated
@@ -16,6 +16,7 @@ plugin:
1616
sh_minversion: 1.3 # minimum shNG version to use this plugin
1717
# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
1818
multi_instance: False # plugin supports multi instance
19+
restartable: unknown
1920
classname: Alexa # class containing the plugin
2021

2122
parameters:
@@ -34,10 +35,10 @@ parameters:
3435
de: 'Port Nummer des service Hosts'
3536
en: 'port number of the service host'
3637

37-
item_attributes:
38+
item_attributes: NONE
3839
# Definition of item attributes defined by this plugin
3940

40-
item_structs:
41+
item_structs: NONE
4142
# Definition of item-structure templates for this plugin
4243

4344
plugin_functions: NONE

appletv/plugin.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ plugin:
77
en: 'Controls an Apple TV'
88
fr: 'Contrôle un Apple TV'
99
maintainer: Foxi352
10+
tester: Foxi352
1011
state: ready
1112
keywords: appletv media
1213
# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page
@@ -15,6 +16,7 @@ plugin:
1516
version: 1.6.1 # Plugin version
1617
sh_minversion: 1.6 # minimum shNG version to use this plugin
1718
multi_instance: True # plugin supports multi instance
19+
restartable: unknown
1820
classname: AppleTV # class containing the plugin
1921

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

36-
item_attributes:
38+
item_attributes: NONE
3739
# Definition of item attributes defined by this plugin
3840

3941
item_structs:
@@ -99,7 +101,7 @@ item_structs:
99101
type: str
100102
visu_acl: ro
101103
cache: Yes
102-
appletv@instance: playing_fingerprint
104+
appletv@instance: playing_fingerprint
103105
genre:
104106
type: str
105107
visu_acl: ro
@@ -155,7 +157,7 @@ item_structs:
155157
type: str
156158
visu_acl: ro
157159
cache: Yes
158-
appletv@instance: playing_repeat_text
160+
appletv@instance: playing_repeat_text
159161
shuffle:
160162
type: num
161163
visu_acl: rw

asterisk/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,9 @@ def stop(self):
321321
Stop method for the plugin
322322
"""
323323
self.logger.debug("Stop method called")
324-
self._client.close()
324+
if self._client.connected():
325+
self._client.close()
325326
self.alive = False
326327
self._reply_lock.acquire()
327328
self._reply_lock.notify()
328329
self._reply_lock.release()
329-
# self.close()

asterisk/plugin.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ plugin:
1212
documentation: https://www.smarthomeng.de/user/plugins/asterisk/README.html
1313
support: https://knx-user-forum.de/forum/supportforen/smarthome-py/
1414
version: 1.4.0 # Plugin version
15-
sh_minversion: 1.8.2a # minimum shNG version to use this plugin
15+
sh_minversion: 1.9.0 # minimum shNG version to use this plugin
1616
# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
1717
# py_minversion: 3.6 # minimum Python version to use for this plugin
1818
# py_maxversion: # maximum Python version to use for this plugin (leave empty if latest)

avdevice/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ Hopefully several different AV devices based on TCP or Serial RS232 connections
1313
Tested with Pioneer (< 2016 models) and Denon AV receivers, Epson projector Oppo Bluray player
1414

1515
## Changelog
16-
### planned for v1.6.3
17-
* include model file for Anthem AV
16+
### v1.6.3
17+
* updated webinterface implementation, realtime values, fixes
1818

1919
### v1.6.2
2020
* implement lineending send and response parameters

avdevice/__init__.py

Lines changed: 39 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from .AVDeviceFunctions import Translate
4444
from .AVDeviceFunctions import ConvertValue
4545
from .AVDeviceFunctions import CreateExpectedResponse
46+
from .webif import WebInterface
4647

4748
VERBOSE1 = logging.DEBUG - 1
4849
VERBOSE2 = logging.DEBUG - 2
@@ -52,13 +53,15 @@
5253

5354
class AVDevice(SmartPlugin):
5455
ALLOW_MULTIINSTANCE = True
55-
PLUGIN_VERSION = "1.6.2"
56+
PLUGIN_VERSION = "1.6.3"
5657

5758
def __init__(self, smarthome):
59+
super().__init__()
5860
self.itemsApi = Items.get_instance()
5961
if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5':
6062
self.logger = logging.getLogger(__name__)
61-
self.init_webinterface()
63+
self.init_webinterface(WebInterface)
64+
self._item_values = {}
6265
try:
6366
self.alive = False
6467
self._name = self.get_fullname()
@@ -194,6 +197,7 @@ def _resetitem(self, founditem):
194197
self._name, founditem, self._items[zone][itemlist]['Item'], search))
195198
if founditem == search:
196199
founditem(previousvalue, 'AVDevice', self._tcp)
200+
self._update_item_values(founditem, previousvalue)
197201
self.logger.info("Resetting {}: Item {} to {}".format(
198202
self._name, founditem, previousvalue))
199203
resetting = founditem
@@ -204,6 +208,7 @@ def _resetitem(self, founditem):
204208
"Resetting {}: Search {} in {}.".format(self._name, founditem, compare))
205209
if founditem == compare:
206210
founditem(previousvalue, 'AVDevice', self._tcp)
211+
self._update_item_values(founditem, previousvalue)
207212
self.logger.info("Resetting {}: Item {} to {}".format(
208213
self._name, founditem, previousvalue))
209214
resetting = founditem
@@ -248,11 +253,13 @@ def _resetondisconnect(self, caller):
248253
self._items_speakers[zone][itemlist]['Value'] = 0
249254
speakeritem = self._items_speakers[zone][itemlist]['Item']
250255
speakeritem(0, 'AVDevice', self._tcp)
256+
self._update_item_values(speakeritem, 0)
251257
self.logger.log(VERBOSE1,
252258
'Resetting {}: Speakers to 0 for item {}'.format(self._name,
253259
speakeritem))
254260
speakeritem = self._items[zone]['speakers']['Item']
255261
speakeritem(0, 'AVDevice', self._tcp)
262+
self._update_item_values(speakeritem, 0)
256263
self.logger.log(VERBOSE1,
257264
'Resetting {}: Speakers to 0 for item {}'.format(self._name, speakeritem))
258265
if 'volume' in self._items[zone].keys() and self._depend0_volume0 is True:
@@ -268,6 +275,21 @@ def _resetondisconnect(self, caller):
268275
'Resetting {}: Not resetting on disconnect because this feature is disabled in the plugin config.'.format(
269276
self._name))
270277

278+
def _update_item_values(self, item, payload):
279+
"""
280+
Update dict for periodic updates of the web interface
281+
282+
:param item:
283+
:param payload:
284+
"""
285+
if not self._item_values.get(item.id()):
286+
self._item_values[item.id()] = {}
287+
if isinstance(payload, bool):
288+
self._item_values[item.id()]['value'] = str(payload)
289+
else:
290+
self._item_values[item.id()]['value'] = payload
291+
return
292+
271293
# Store actual value to a temporary dict for resetting purposes
272294
def _write_itemsdict(self, data, found):
273295
zone = updated = 0
@@ -425,7 +447,7 @@ def _parse_depend_item(self, item, info, zone):
425447
"Initializing {}: Creating dependency for {} in {}: {}".format(self._name, info, zone, self._items[zone][info]))
426448

427449
def _logics_dependencies(self, zone=None, item=None):
428-
deps = {'a': [], 'b':[], 'c':[], 'd':[]}
450+
deps = {'a': [], 'b': [], 'c': [], 'd': []}
429451
try:
430452
info = item.property.path
431453
search = 'Slave_item'
@@ -436,7 +458,7 @@ def _logics_dependencies(self, zone=None, item=None):
436458
depitem = self._dependencies[search][zone].get(info)
437459
for d in depitem:
438460
deps[d.get('Group')].append("{}{}{}".format(d['Item'], d['Compare'], d['Dependvalue']))
439-
deps = dict( [(k,v) for k,v in deps.items() if len(v)>0])
461+
deps = dict([(k, v) for k, v in deps.items() if len(v) > 0])
440462
except Exception as err:
441463
deps = None
442464
return deps
@@ -530,7 +552,8 @@ def _sortbuffer(buffer, bufferlist):
530552

531553
try:
532554
buffer = ''
533-
tidy = lambda c: re.sub(
555+
556+
def tidy(c): return re.sub(
534557
r'(^\s*[{0}]+|^\s*\Z)|(\s*\Z|\s*[{0}]+)'.format(self._lineending_response),
535558
lambda m: self._lineending_response if m.lastindex == 2 else '',
536559
c)
@@ -564,8 +587,8 @@ def _sortbuffer(buffer, bufferlist):
564587
try:
565588
cond1 = not self._sendingcommand == 'done' and not self._sendingcommand == 'gaveup'
566589
try:
567-
cond2 = (self._sendingcommand.split(',')[2] == '' or self._sendingcommand.split(',')[2] == ' ' or
568-
self._sendingcommand.split(',')[2] == 'none')
590+
cond2 = (self._sendingcommand.split(',')[2] == '' or self._sendingcommand.split(',')[2] == ' '
591+
or self._sendingcommand.split(',')[2] == 'none')
569592
except Exception:
570593
cond2 = self._sendingcommand == ''
571594
if cond1 and not cond2:
@@ -798,9 +821,9 @@ def _sortbuffer(buffer, bufferlist):
798821
maximum = abs(self._response_buffer) if type(self._response_buffer) is int else 11
799822
# Removing empty entries
800823
bufferlist = list(filter(lambda a: a != '', bufferlist))
801-
newbuffer = [buf for buf in bufferlist if not buf.startswith(tuple(self._ignore_response)) and
802-
'' not in self._ignore_response and
803-
buf.startswith(tuple(self._response_commands))]
824+
newbuffer = [buf for buf in bufferlist if not buf.startswith(tuple(self._ignore_response))
825+
and '' not in self._ignore_response
826+
and buf.startswith(tuple(self._response_commands))]
804827
bufferlist = newbuffer[-1 * max(min(len(newbuffer), maximum), 0):]
805828
buffering = False
806829
if bufferlist:
@@ -1922,6 +1945,7 @@ def _duplicateindex(seq, seqitem):
19221945
self._name, av_function, value))
19231946

19241947
item(value, 'AVDevice', self._tcp)
1948+
self._update_item_values(item, value)
19251949
self.logger.debug("Parsing Input {}: Updated Item {} with {} Value: {}.".format(
19261950
self._name, item, expectedtype, value))
19271951
if av_function in self._items[zone].keys():
@@ -1983,7 +2007,7 @@ def _duplicateindex(seq, seqitem):
19832007
except Exception:
19842008
commanditem = None
19852009
if commanditem:
1986-
command = '{};{}'.format(command_split, commanditem)
2010+
command = '{};{}'.format(command_split, commanditem)
19872011
self.logger.log(VERBOSE1,
19882012
"Parsing Input {}: Reorder command commandsplit {}, commanditem {}. Command: {}".format(
19892013
self._name, command_split, commanditem, command))
@@ -2111,10 +2135,10 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl
21112135
except Exception:
21122136
depending = False
21132137
self.logger.log(VERBOSE1, "Updating Item {}: Depending is {}.".format(self._name, depending))
2114-
condition1 = (self.has_iattr(item.conf, 'avdevice') and
2115-
self.get_iattr_value(item.conf, 'avdevice') == 'reload')
2116-
condition2 = (self.has_iattr(item.conf, 'avdevice_zone0') and
2117-
self.get_iattr_value(item.conf, 'avdevice_zone0') == 'reload')
2138+
condition1 = (self.has_iattr(item.conf, 'avdevice')
2139+
and self.get_iattr_value(item.conf, 'avdevice') == 'reload')
2140+
condition2 = (self.has_iattr(item.conf, 'avdevice_zone0')
2141+
and self.get_iattr_value(item.conf, 'avdevice_zone0') == 'reload')
21182142
if condition1 or condition2:
21192143
self._initialize()
21202144
self.logger.info("Initializing {}: Reloaded Text file and functions".format(self._name))
@@ -3048,108 +3072,3 @@ def stop(self):
30483072
self._serialwrapper.close()
30493073
except Exception:
30503074
self.logger.log(VERBOSE1, "Stopping {}: No Serial socket to close.".format(self._name))
3051-
3052-
def init_webinterface(self):
3053-
""""
3054-
Initialize the web interface for this plugin
3055-
3056-
This method is only needed if the plugin is implementing a web interface
3057-
"""
3058-
try:
3059-
self.mod_http = Modules.get_instance().get_module('http')
3060-
except Exception:
3061-
self.mod_http = None
3062-
if self.mod_http is None:
3063-
self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname()))
3064-
return False
3065-
3066-
import sys
3067-
if "SmartPluginWebIf" not in list(sys.modules['lib.model.smartplugin'].__dict__):
3068-
self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname()))
3069-
return False
3070-
3071-
# set application configuration for cherrypy
3072-
webif_dir = self.path_join(self.get_plugin_dir(), 'webif')
3073-
config = {
3074-
'/': {
3075-
'tools.staticdir.root': webif_dir,
3076-
},
3077-
'/static': {
3078-
'tools.staticdir.on': True,
3079-
'tools.staticdir.dir': 'static'
3080-
}
3081-
}
3082-
3083-
# Register the web interface as a cherrypy app
3084-
self.mod_http.register_webif(WebInterface(webif_dir, self),
3085-
self.get_shortname(),
3086-
config,
3087-
self.get_classname(), self.get_instance_name(),
3088-
description='')
3089-
3090-
return True
3091-
3092-
3093-
# ------------------------------------------
3094-
# Webinterface of the plugin
3095-
# ------------------------------------------
3096-
3097-
import cherrypy
3098-
from jinja2 import Environment, FileSystemLoader
3099-
3100-
3101-
class WebInterface(SmartPluginWebIf):
3102-
3103-
def __init__(self, webif_dir, plugin):
3104-
"""
3105-
Initialization of instance of class WebInterface
3106-
3107-
:param webif_dir: directory where the webinterface of the plugin resides
3108-
:param plugin: instance of the plugin
3109-
:type webif_dir: str
3110-
:type plugin: object
3111-
"""
3112-
self.logger = logging.getLogger(__name__)
3113-
self.webif_dir = webif_dir
3114-
self.plugin = plugin
3115-
self.tplenv = self.init_template_environment()
3116-
3117-
@cherrypy.expose
3118-
def index(self, action=None, item_id=None, item_path=None, reload=None):
3119-
"""
3120-
Build index.html for cherrypy
3121-
3122-
Render the template and return the html file to be delivered to the browser
3123-
3124-
:return: contents of the template after beeing rendered
3125-
"""
3126-
config_reloaded = False
3127-
keep_cleared = False
3128-
command_cleared = False
3129-
query_cleared = False
3130-
send_cleared = False
3131-
if action is not None:
3132-
if action == "reload":
3133-
self.plugin._initialize()
3134-
config_reloaded = True
3135-
if action == "connect":
3136-
self.plugin.connect('webif')
3137-
if action == "clear_query_history":
3138-
self.plugin._clear_history('query')
3139-
query_cleared = True
3140-
if action == "clear_send":
3141-
self.plugin._clear_history('send')
3142-
send_cleared = True
3143-
if action == "clear_command_history":
3144-
self.plugin._clear_history('command')
3145-
command_cleared = True
3146-
if action == "clear_keep_commands":
3147-
self.plugin._clear_history('keep')
3148-
keep_cleared = True
3149-
3150-
tmpl = self.tplenv.get_template('index.html')
3151-
# add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...)
3152-
return tmpl.render(p=self.plugin,
3153-
config_reloaded=config_reloaded, query_cleared=query_cleared,
3154-
command_cleared=command_cleared, keep_cleared=keep_cleared, send_cleared=send_cleared,
3155-
language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now())

0 commit comments

Comments
 (0)