4343from .AVDeviceFunctions import Translate
4444from .AVDeviceFunctions import ConvertValue
4545from .AVDeviceFunctions import CreateExpectedResponse
46+ from .webif import WebInterface
4647
4748VERBOSE1 = logging .DEBUG - 1
4849VERBOSE2 = logging .DEBUG - 2
5253
5354class 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