Skip to content

Commit 67c3d1c

Browse files
committed
Add inheritance for plugin devices.
1 parent afb98c7 commit 67c3d1c

File tree

1 file changed

+55
-26
lines changed

1 file changed

+55
-26
lines changed

myDevices/plugins/manager.py

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -33,30 +33,47 @@ def load_plugin_from_file(self, filename):
3333
plugin_name = os.path.splitext(os.path.basename(filename))[0]
3434
info('Sections: {}'.format(config.sections()))
3535
for section in config.sections():
36-
enabled = config.get(section, 'enabled', 'true').lower() == 'true'
37-
if enabled:
38-
plugin = {
39-
'filename': filename,
40-
'section': section,
41-
'channel': config.get(section, 'channel'),
42-
'name': config.get(section, 'name', section),
43-
'module': config.get(section, 'module'),
44-
'class': config.get(section, 'class'),
45-
'init_args': json.loads(config.get(section, 'init_args', '{}'))
46-
}
47-
folder = os.path.dirname(filename)
48-
if folder not in sys.path:
49-
sys.path.append(folder)
50-
imported_module = importlib.import_module(plugin['module'])
51-
device_class = getattr(imported_module, plugin['class'])
52-
plugin['instance'] = device_class(**plugin['init_args'])
53-
plugin['read'] = getattr(plugin['instance'], config.get(section, 'read'))
54-
try:
55-
plugin['write'] = getattr(plugin['instance'], config.get(section, 'write'))
56-
except:
57-
pass
58-
self.plugins[plugin_name + ':' + plugin['channel']] = plugin
59-
loaded.append(section)
36+
try:
37+
enabled = config.get(section, 'enabled', 'true').lower() == 'true'
38+
inherit = config.get(section, 'inherit', None)
39+
if enabled:
40+
plugin = {
41+
'filename': filename,
42+
'section': section,
43+
'channel': config.get(section, 'channel'),
44+
'name': config.get(section, 'name', section)
45+
}
46+
inherit_items = {}
47+
if inherit in config.sections():
48+
if inherit == section:
49+
raise ValueError('Section \'{}\' cannot inherit from itself'.format(section))
50+
inherit_from = self.get_plugin(filename, inherit)
51+
inherit_items = {key:value for key, value in inherit_from.items() if key not in plugin.keys()}
52+
plugin.update(inherit_items)
53+
elif inherit:
54+
raise ValueError('Section \'{}\' cannot inherit from \'{}\'. Check spelling and section ordering.'.format(section, inherit))
55+
self.override_plugin_value(config, section, 'module', plugin)
56+
self.override_plugin_value(config, section, 'class', plugin)
57+
if 'init_args' not in plugin:
58+
plugin['init_args'] = '{}'
59+
self.override_plugin_value(config, section, 'init_args', plugin)
60+
if not inherit_items or inherit_items['class'] is not plugin['class'] or inherit_items['init_args'] is not plugin['init_args']:
61+
info('Creating instance of {} for {}'.format(plugin['class'], plugin['name']))
62+
folder = os.path.dirname(filename)
63+
if folder not in sys.path:
64+
sys.path.append(folder)
65+
imported_module = importlib.import_module(plugin['module'])
66+
device_class = getattr(imported_module, plugin['class'])
67+
plugin['instance'] = device_class(**json.loads(plugin['init_args']))
68+
self.override_plugin_value(config, section, 'read', plugin)
69+
try:
70+
self.override_plugin_value(config, section, 'write', plugin)
71+
except:
72+
pass
73+
self.plugins[plugin_name + ':' + plugin['channel']] = plugin
74+
loaded.append(section)
75+
except Exception as e:
76+
error(e)
6077
except Exception as e:
6178
error(e)
6279
info('Loaded sections: {}'.format(loaded))
@@ -67,12 +84,23 @@ def load_plugins(self):
6784
for filename in fnmatch.filter(filenames, '*.plugin'):
6885
self.load_plugin_from_file(os.path.join(root, filename))
6986

87+
def get_plugin(self, filename, section):
88+
"""Return the plugin for the corresponding filename and section"""
89+
return next(plugin for plugin in self.plugins.values() if plugin['filename'] == filename and plugin['section'] == section)
90+
91+
def override_plugin_value(self, config, section, key, plugin):
92+
"""Override the plugin value for the specified key if it exists in the config file"""
93+
if key not in plugin:
94+
plugin[key] = config.get(section, key)
95+
else:
96+
plugin[key] = config.get(section, key, plugin[key])
97+
7098
def get_plugin_readings(self):
7199
"""Return a list with current readings for all plugins"""
72100
readings = []
73101
for key, plugin in self.plugins.items():
74102
try:
75-
value = plugin['read']()
103+
value = getattr(plugin['instance'], plugin['read'])()
76104
value_dict = self.convert_to_dict(value)
77105
if value_dict:
78106
cayennemqtt.DataChannel.add(readings, cayennemqtt.DEV_SENSOR, key, name=plugin['name'], **value_dict)
@@ -119,7 +147,8 @@ def write_value(self, plugin, channel, value):
119147
info('Write value {} to {}'.format(value, actuator))
120148
if actuator in self.plugins.keys():
121149
try:
122-
self.plugins[actuator]['write'](float(value))
150+
write_function = getattr(self.plugins[actuator]['instance'], self.plugins[actuator]['write'])
151+
write_function(float(value))
123152
except:
124153
return False
125154
else:

0 commit comments

Comments
 (0)