16
16
17
17
18
18
class PluginManager ():
19
- """Loads plugins and reads/writes plugin data"""
19
+ """Loads plugins and reads/writes plugin data. """
20
20
21
- def __init__ (self ):
22
- """Initializes the plugin manager and loads the plugin list"""
21
+ def __init__ (self , callback = None ):
22
+ """Initializes the plugin manager and loads the plugin list. """
23
23
self .plugin_folder = PLUGIN_FOLDER
24
+ self .callback = callback
24
25
self .plugins = {}
25
26
self .load_plugins ()
26
27
27
28
def load_plugin_from_file (self , filename ):
28
- """Loads a plugin from a specified plugin config file and adds it to the plugin list"""
29
+ """Loads a plugin from a specified plugin config file and adds it to the plugin list. """
29
30
try :
30
31
info ('Loading plugin: {}' .format (filename ))
31
32
loaded = []
@@ -41,8 +42,9 @@ def load_plugin_from_file(self, filename):
41
42
'filename' : filename ,
42
43
'section' : section ,
43
44
'channel' : config .get (section , 'channel' ),
44
- 'name' : config .get (section , 'name' , section )
45
+ 'name' : config .get (section , 'name' , section ),
45
46
}
47
+ plugin ['id' ] = plugin_name + ':' + plugin ['channel' ]
46
48
inherit_items = {}
47
49
if inherit in config .sections ():
48
50
if inherit == section :
@@ -70,7 +72,16 @@ def load_plugin_from_file(self, filename):
70
72
self .override_plugin_value (config , section , 'write' , plugin )
71
73
except :
72
74
pass
73
- self .plugins [plugin_name + ':' + plugin ['channel' ]] = plugin
75
+ try :
76
+ self .override_plugin_value (config , section , 'register_callback' , plugin )
77
+ getattr (plugin ['instance' ], plugin ['register_callback' ])(lambda x : self .data_changed (x , plugin ))
78
+ except :
79
+ pass
80
+ try :
81
+ self .override_plugin_value (config , section , 'unregister_callback' , plugin )
82
+ except :
83
+ pass
84
+ self .plugins [plugin ['id' ]] = plugin
74
85
loaded .append (section )
75
86
except Exception as e :
76
87
error (e )
@@ -79,13 +90,13 @@ def load_plugin_from_file(self, filename):
79
90
info ('Loaded sections: {}' .format (loaded ))
80
91
81
92
def load_plugins (self ):
82
- """Loads plugins from any plugin config files found in the plugin folder"""
93
+ """Loads plugins from any plugin config files found in the plugin folder. """
83
94
for root , dirnames , filenames in os .walk (self .plugin_folder ):
84
95
for filename in fnmatch .filter (filenames , '*.plugin' ):
85
96
self .load_plugin_from_file (os .path .join (root , filename ))
86
97
87
98
def get_plugin (self , filename , section ):
88
- """Return the plugin for the corresponding filename and section"""
99
+ """Return the plugin for the corresponding filename and section. """
89
100
return next (plugin for plugin in self .plugins .values () if plugin ['filename' ] == filename and plugin ['section' ] == section )
90
101
91
102
def override_plugin_value (self , config , section , key , plugin ):
@@ -96,7 +107,7 @@ def override_plugin_value(self, config, section, key, plugin):
96
107
plugin [key ] = config .get (section , key , plugin [key ])
97
108
98
109
def get_plugin_readings (self ):
99
- """Return a list with current readings for all plugins"""
110
+ """Return a list with current readings for all plugins. """
100
111
readings = []
101
112
for key , plugin in self .plugins .items ():
102
113
try :
@@ -111,7 +122,7 @@ def get_plugin_readings(self):
111
122
return readings
112
123
113
124
def convert_to_dict (self , value ):
114
- """Convert a tuple value to a dict containing value, type and unit"""
125
+ """Convert a tuple value to a dict containing value, type and unit. """
115
126
value_dict = {}
116
127
try :
117
128
if value is None or value [0 ] is None :
@@ -123,18 +134,19 @@ def convert_to_dict(self, value):
123
134
if not value_dict :
124
135
value_dict ['value' ] = value
125
136
if 'type' in value_dict and 'unit' not in value_dict :
126
- if value_dict ['type' ] == ' digital_actuator' :
137
+ if value_dict ['type' ] in ( 'digital_sensor' , ' digital_actuator') :
127
138
value_dict ['unit' ] = 'd'
128
- elif value_dict ['type' ] == ' analog_actuator' :
139
+ elif value_dict ['type' ] in ( 'analog_sensor' , ' analog_actuator') :
129
140
value_dict ['unit' ] = 'null'
130
141
return value_dict
131
142
132
143
def is_plugin (self , plugin , channel = None ):
133
- """Returns True if the specified plugin or plugin:channel are valid plugins"""
144
+ """Returns True if the specified plugin or plugin:channel are valid plugins. """
134
145
try :
135
146
key = plugin
136
147
if channel is not None :
137
148
key = plugin + ':' + channel
149
+ info ('Checking for {} in {}' .format (key , self .plugins .keys ()))
138
150
return key in self .plugins .keys ()
139
151
except :
140
152
return False
@@ -155,18 +167,37 @@ def write_value(self, plugin, channel, value):
155
167
return False
156
168
return True
157
169
158
- def disable (self , plugin ):
159
- """Disable the specified plugin"""
170
+ def disable (self , plugin_id ):
171
+ """Disable the specified plugin. """
160
172
disabled = False
161
173
try :
162
- output , result = executeCommand ('sudo python3 -m myDevices.plugins.disable "{}" "{}"' .format (self .plugins [plugin ]['filename' ], self .plugins [plugin ]['section' ]))
174
+ plugin = self .plugins [plugin_id ]
175
+ output , result = executeCommand ('sudo python3 -m myDevices.plugins.disable "{}" "{}"' .format (plugin ['filename' ], plugin ['section' ]))
163
176
if result == 0 :
164
177
disabled = True
165
- info ('Plugin \' {}\' disabled' .format (plugin ))
178
+ info ('Plugin \' {}\' disabled' .format (plugin_id ))
166
179
else :
167
- info ('Plugin \' {}\' not disabled' .format (plugin ))
168
- del self .plugins [plugin ]
180
+ info ('Plugin \' {}\' not disabled' .format (plugin_id ))
181
+ if 'unregister_callback' in plugin :
182
+ getattr (plugin ['instance' ], plugin ['unregister_callback' ])()
183
+ del self .plugins [plugin_id ]
169
184
except Exception as e :
170
185
info (e )
171
186
pass
172
- return disabled
187
+ return disabled
188
+
189
+ def register_callback (self , callback ):
190
+ """Register the callback to use when plugin data has changed."""
191
+ self .callback = callback
192
+
193
+ def unregister_callback (self ):
194
+ """Unregister the callback to use when plugin data has changed."""
195
+ self .callback = None
196
+
197
+ def data_changed (self , value , plugin ):
198
+ """Callback that is called when data has changed."""
199
+ if self .callback :
200
+ data = self .convert_to_dict (value )
201
+ data ['name' ] = plugin ['name' ]
202
+ data ['id' ] = plugin ['id' ]
203
+ self .callback (data )
0 commit comments