Skip to content

Commit 63e7cd7

Browse files
committed
Add extension plugin support.
1 parent 6031e0a commit 63e7cd7

File tree

4 files changed

+57
-41
lines changed

4 files changed

+57
-41
lines changed

myDevices/devices/analog/__init__.py

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from myDevices.utils.types import toint, M_JSON
1717
from myDevices.devices import instance
1818

19+
1920
class ADC():
2021
def __init__(self, channelCount, resolution, vref):
2122
self._analogCount = channelCount
@@ -34,79 +35,73 @@ def checkAnalogValue(self, value):
3435
if not 0 <= value <= self._analogMax:
3536
raise ValueError("Value %d out of range [%d..%d]" % (value, 0, self._analogMax))
3637

37-
#@request("GET", "analog/count")
3838
@response("%d")
3939
def analogCount(self):
4040
return self._analogCount
4141

42-
#@request("GET", "analog/resolution")
4342
@response("%d")
4443
def analogResolution(self):
4544
return self._analogResolution
4645

47-
#@request("GET", "analog/max")
4846
@response("%d")
4947
def analogMaximum(self):
5048
return int(self._analogMax)
5149

52-
#@request("GET", "analog/vref")
5350
@response("%.2f")
5451
def analogReference(self):
5552
return self._analogRef
5653

5754
def __analogRead__(self, channel, diff):
5855
raise NotImplementedError
5956

60-
#@request("GET", "analog/%(channel)d/integer")
6157
@response("%d")
6258
def analogRead(self, channel, diff=False):
6359
self.checkAnalogChannel(channel)
6460
return self.__analogRead__(channel, diff)
6561

66-
#@request("GET", "analog/%(channel)d/float")
6762
@response("%.2f")
6863
def analogReadFloat(self, channel, diff=False):
6964
return self.analogRead(channel, diff) / float(self._analogMax)
7065

71-
#@request("GET", "analog/%(channel)d/volt")
7266
@response("%.2f")
7367
def analogReadVolt(self, channel, diff=False):
7468
if self._analogRef == 0:
7569
raise NotImplementedError
7670
return self.analogReadFloat(channel, diff) * self._analogRef
7771

78-
#@request("GET", "analog/*/integer")
7972
@response(contentType=M_JSON)
8073
def analogReadAll(self):
8174
values = {}
8275
for i in range(self._analogCount):
8376
values[i] = self.analogRead(i)
8477
return values
8578

86-
#@request("GET", "analog/*/float")
8779
@response(contentType=M_JSON)
8880
def analogReadAllFloat(self):
8981
values = {}
9082
for i in range(self._analogCount):
9183
values[i] = float("%.2f" % self.analogReadFloat(i))
9284
return values
9385

94-
#@request("GET", "analog/*/volt")
9586
@response(contentType=M_JSON)
9687
def analogReadAllVolt(self):
9788
values = {}
9889
for i in range(self._analogCount):
9990
values[i] = float("%.2f" % self.analogReadVolt(i))
10091
return values
10192

102-
def read(self, channel, diff=False):
103-
return self.analogRead(channel, diff)
93+
def read(self, channel, data_type=None, diff=False):
94+
read_functions = {'float': self.analogReadFloat,'f': self.analogReadFloat,
95+
'volt': self.analogReadVolt,'v': self.analogReadVolt}
96+
read_function = read_functions.get(data_type, self.analogRead)
97+
return read_function(channel, diff)
10498

10599
def readFloat(self, channel, diff=False):
106-
return self.analogReadFloat(channel, diff)
100+
return self.analogReadFloat(channel, diff)
107101

108102
def readVolt(self, channel, diff=False):
109-
return self.analogReadVolt(channel, diff)
103+
return self.analogReadVolt(channel, diff)
104+
110105

111106
class DAC(ADC):
112107
def __init__(self, channelCount, resolution, vref):
@@ -118,21 +113,18 @@ def __family__(self):
118113
def __analogWrite__(self, channel, value):
119114
raise NotImplementedError
120115

121-
#@request("POST", "analog/%(channel)d/integer/%(value)d")
122116
@response("%d")
123117
def analogWrite(self, channel, value):
124118
self.checkAnalogChannel(channel)
125119
self.checkAnalogValue(value)
126120
self.__analogWrite__(channel, value)
127121
return self.analogRead(channel)
128122

129-
#@request("POST", "analog/%(channel)d/float/%(value)f")
130123
@response("%.2f")
131124
def analogWriteFloat(self, channel, value):
132125
self.analogWrite(channel, int(value * self._analogMax))
133126
return self.analogReadFloat(channel)
134127

135-
#@request("POST", "analog/%(channel)d/volt/%(value)f")
136128
@response("%.2f")
137129
def analogWriteVolt(self, channel, value):
138130
self.analogWriteFloat(channel, value /self._analogRef)
@@ -147,6 +139,7 @@ def writeFloat(self, channel, value):
147139
def writeVolt(self, channel, value):
148140
return self.analogWriteVolt(channel, value)
149141

142+
150143
class PWM():
151144
def __init__(self, channelCount, resolution, frequency):
152145
self._pwmCount = channelCount
@@ -179,41 +172,34 @@ def __pwmRead__(self, channel):
179172
def __pwmWrite__(self, channel, value):
180173
raise NotImplementedError
181174

182-
#@request("GET", "pwm/count")
183175
@response("%d")
184176
def pwmCount(self):
185177
return self._pwmCount
186178

187-
#@request("GET", "pwm/resolution")
188179
@response("%d")
189180
def pwmResolution(self):
190181
return self._pwmResolution
191182

192-
#@request("GET", "pwm/max")
193183
@response("%d")
194184
def pwmMaximum(self):
195185
return int(self._pwmMax)
196186

197-
#@request("GET", "pwm/%(channel)d/integer")
198187
@response("%d")
199188
def pwmRead(self, channel):
200189
self.checkPWMChannel(channel)
201190
return self.__pwmRead__(channel)
202191

203-
#@request("GET", "pwm/%(channel)d/float")
204192
@response("%.2f")
205193
def pwmReadFloat(self, channel):
206194
return self.pwmRead(channel) / float(self._pwmMax)
207195

208-
#@request("POST", "pwm/%(channel)d/integer/%(value)d")
209196
@response("%d")
210197
def pwmWrite(self, channel, value):
211198
self.checkPWMChannel(channel)
212199
self.checkPWMValue(value)
213200
self.__pwmWrite__(channel, value)
214201
return self.pwmRead(channel)
215202

216-
#@request("POST", "pwm/%(channel)d/float/%(value)f")
217203
@response("%.2f")
218204
def pwmWriteFloat(self, channel, value):
219205
self.pwmWrite(channel, int(value * self._pwmMax))
@@ -256,7 +242,6 @@ def AngleToRatio(self, value):
256242
f /= self.period
257243
return f
258244

259-
#@request("GET", "pwm/%(channel)d/angle")
260245
@response("%.2f")
261246
def pwmReadAngle(self, channel):
262247
f = self.pwmReadFloat(channel)
@@ -267,7 +252,6 @@ def pwmReadAngle(self, channel):
267252
f = f
268253
return f
269254

270-
#@request("POST", "pwm/%(channel)d/angle/%(value)f")
271255
@response("%.2f")
272256
def pwmWriteAngle(self, channel, value):
273257
if self.reverse[channel]:
@@ -278,7 +262,6 @@ def pwmWriteAngle(self, channel, value):
278262
self.pwmWriteFloat(channel, f)
279263
return self.pwmReadAngle(channel)
280264

281-
#@request("GET", "pwm/*")
282265
@response(contentType=M_JSON)
283266
def pwmWildcard(self):
284267
values = {}

myDevices/devices/analog/helper.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
from myDevices.utils.types import toint
1717
from myDevices.devices import instance
1818
from myDevices.utils.logger import info
19+
from myDevices.plugins.manager import PluginManager
1920

2021
class AnalogSensor():
2122
def __init__(self, adc, channel):
2223
self.adcname = adc
2324
self.channel = toint(channel)
2425
self.adc = None
26+
self.pluginManager = PluginManager()
2527
self.setADCInstance()
2628

2729
def __str__(self):
@@ -33,32 +35,44 @@ def __family__(self):
3335
def setADCInstance(self):
3436
if not self.adc:
3537
self.adc = instance.deviceInstance(self.adcname)
38+
if not self.adc:
39+
self.adc = self.pluginManager.get_extension(self.adcname)
3640

37-
#@request("GET", "integer")
3841
@response("%d")
3942
def read(self):
4043
self.setADCInstance()
41-
return self.adc.analogRead(self.channel)
44+
try:
45+
value = self.adc.analogRead(self.channel)
46+
except:
47+
value = getattr(self.adc['instance'], self.adc['read'])(self.channel)
48+
return value
4249

43-
#@request("GET", "float")
4450
@response("%.2f")
4551
def readFloat(self):
4652
self.setADCInstance()
47-
return self.adc.analogReadFloat(self.channel)
53+
try:
54+
value = self.adc.analogReadFloat(self.channel)
55+
except:
56+
value = getattr(self.adc['instance'], self.adc['read'])(self.channel, 'float')
57+
return value
4858

49-
#@request("GET", "volt")
5059
@response("%.2f")
5160
def readVolt(self):
5261
self.setADCInstance()
53-
return self.adc.analogReadVolt(self.channel)
62+
try:
63+
value = self.adc.analogReadVolt(self.channel)
64+
except:
65+
value = getattr(self.adc['instance'], self.adc['read'])(self.channel, 'volt')
66+
return value
67+
5468

5569
class Photoresistor(AnalogSensor):
5670
def __init__(self, adc, channel):
5771
AnalogSensor.__init__(self, adc, channel)
5872

5973
def __str__(self):
6074
return "Photoresistor"
61-
75+
6276
class Thermistor(AnalogSensor):
6377
def __init__(self, adc, channel):
6478
AnalogSensor.__init__(self, adc, channel)

myDevices/plugins/manager.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,21 @@
1010
import myDevices.cloud.cayennemqtt as cayennemqtt
1111
from myDevices.utils.config import Config
1212
from myDevices.utils.logger import debug, error, exception, info
13+
from myDevices.utils.singleton import Singleton
1314
from myDevices.utils.subprocess import executeCommand
1415

1516
PLUGIN_FOLDER = '/etc/myDevices/plugins'
1617

1718

18-
class PluginManager():
19+
class PluginManager(Singleton):
1920
"""Loads plugins and reads/writes plugin data."""
2021

2122
def __init__(self, callback=None):
2223
"""Initializes the plugin manager and loads the plugin list."""
2324
self.plugin_folder = PLUGIN_FOLDER
2425
self.callback = callback
2526
self.plugins = {}
26-
self.load_plugins()
27+
self.extensions = {}
2728

2829
def load_plugin_from_file(self, filename):
2930
"""Loads a plugin from a specified plugin config file and adds it to the plugin list."""
@@ -42,15 +43,19 @@ def load_plugin_from_file(self, filename):
4243
try:
4344
enabled = config.get(section, 'enabled', 'true').lower() == 'true'
4445
inherit = config.get(section, 'inherit', None)
46+
extension = config.get(section, 'extension', 'false').lower() == 'true'
4547
if enabled or section in inherited_from:
4648
plugin = {
4749
'enabled': enabled,
4850
'filename': filename,
4951
'section': section,
50-
'channel': config.get(section, 'channel'),
5152
'name': config.get(section, 'name', section),
5253
}
53-
plugin['id'] = plugin_name + ':' + plugin['channel']
54+
if not extension:
55+
plugin['channel'] = config.get(section, 'channel')
56+
plugin['id'] = plugin_name + ':' + plugin['channel']
57+
else:
58+
plugin['id'] = plugin_name + ':' + section
5459
inherit_items = {}
5560
if inherit in config.sections():
5661
if inherit == section:
@@ -86,8 +91,11 @@ def load_plugin_from_file(self, filename):
8691
try:
8792
self.override_plugin_value(config, section, 'unregister_callback', plugin)
8893
except:
89-
pass
90-
self.plugins[plugin['id']] = plugin
94+
pass
95+
if not extension:
96+
self.plugins[plugin['id']] = plugin
97+
else:
98+
self.extensions[plugin['id']] = plugin
9199
loaded.append(section)
92100
except Exception as e:
93101
error(e)
@@ -103,11 +111,21 @@ def load_plugins(self):
103111
#Remove any disabled plugins that were only loaded because they are inherited from.
104112
self.plugins = {key:value for key, value in self.plugins.items() if value['enabled']}
105113
info('Enabled plugins: {}'.format(self.plugins.keys()))
114+
info('Enabled extensions: {}'.format(self.extensions.keys()))
106115

107116
def get_plugin(self, filename, section):
108117
"""Return the plugin for the corresponding filename and section."""
109118
return next(plugin for plugin in self.plugins.values() if plugin['filename'] == filename and plugin['section'] == section)
110119

120+
def get_extension(self, id):
121+
"""Return the extension with the corresponding id."""
122+
extension = None
123+
try:
124+
extension = self.extensions[id]
125+
except:
126+
pass
127+
return extension
128+
111129
def override_plugin_value(self, config, section, key, plugin):
112130
"""Override the plugin value for the specified key if it exists in the config file"""
113131
if key not in plugin:
@@ -209,4 +227,4 @@ def data_changed(self, value, plugin):
209227
data = self.convert_to_dict(value)
210228
data['name'] = plugin['name']
211229
data['id'] = plugin['id']
212-
self.callback(data)
230+
self.callback(data)

myDevices/sensors/sensors.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def __init__(self):
5252
self.disabledSensors[row[0]] = 1
5353
self.realTimeMonitorRunning = False
5454
self.pluginManager = PluginManager(self.OnPluginChange)
55+
self.pluginManager.load_plugins()
5556
self.InitCallbacks()
5657
self.StartMonitoring()
5758

0 commit comments

Comments
 (0)