Skip to content

Commit e2a2e8c

Browse files
committed
Definition of Readables/Writables in AppConfig.py
1 parent 9a4a4ad commit e2a2e8c

4,328 files changed

Lines changed: 269 additions & 1052988 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.

App.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,7 @@ def load_control(control):
99
RIPControl = getattr(module, control_name)
1010

1111
info = config['control']['info']
12-
return RIPControl(
13-
info['name'],
14-
info['description'],
15-
info['authors'],
16-
info['keywords'],
17-
)
12+
return RIPControl(info)
1813

1914
if __name__ == "__main__":
2015
control = load_control(config['control'])

AppConfig.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# This file contains the configuration of the RIP server applicationself.
1+
# This file contains the configuration of the RIP server application.
22
config = {
33
# TO DO: The server will listen to host:port
44
'server': {
@@ -10,14 +10,25 @@
1010
# The 'impl' field should contain the name of the module (.py) and the
1111
# class that implement the control interface
1212
'control': {
13-
'impl_module': 'RIPOctave',
13+
'impl_module': 'RIPGeneric',
1414
# Also, if the class name is not the same as the module name:
1515
#'impl_name': 'RIPOctave',
1616
'info': {
17-
'name': 'Octave',
18-
'description': 'An implementation of RIP to control Octave',
19-
'authors': 'D. Garcia, J. Chacon',
20-
'keywords': 'Octave, Raspberry PI, Robot',
21-
}
17+
'name': 'RIP Generic',
18+
'description': 'A generic implementation of RIP',
19+
'authors': 'J. Chacon',
20+
'keywords': 'Raspberry PI, RIP',
21+
# Server readable objects
22+
'readables': [{
23+
'name':'time',
24+
'description':'Server time in seconds',
25+
'type':'float',
26+
'min':'0',
27+
'max':'Inf',
28+
'precision':'0'
29+
}],
30+
# Server writable objects
31+
'writables': []
32+
},
2233
}
2334
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# This file contains the configuration of the RIP server application.
2+
config = {
3+
# TO DO: The server will listen to host:port
4+
'server': {
5+
'host': '127.0.0.1',
6+
'port': 8080,
7+
},
8+
# The 'control' section configures the mapping between the RIP protocol
9+
# and the actual implementation of the functionality.
10+
# The 'impl' field should contain the name of the module (.py) and the
11+
# class that implement the control interface
12+
'control': {
13+
'impl_module': 'RIPAdapterTemplate',
14+
'info': {
15+
'name': 'RIPRandom',
16+
'description': 'A random numbers generator',
17+
},
18+
}
19+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This file contains the configuration of the RIP server application.
2+
config = {
3+
# TO DO: The server will listen to host:port
4+
'server': {
5+
'host': '127.0.0.1',
6+
'port': 8080,
7+
},
8+
# The 'control' section configures the mapping between the RIP protocol
9+
# and the actual implementation of the functionality.
10+
# The 'impl' field should contain the name of the module (.py) and the
11+
# class that implement the control interface
12+
'control': {
13+
'impl_module': 'RIPGeneric',
14+
# Also, if the class name is not the same as the module name:
15+
#'impl_name': 'RIPOctave',
16+
'info': {
17+
'name': 'RIP Generic',
18+
'description': 'A generic implementation of RIP',
19+
'authors': 'J. Chacon',
20+
'keywords': 'Raspberry PI, RIP',
21+
# Server readable objects
22+
'readables': [{
23+
'name':'time',
24+
'description':'Server time in seconds',
25+
'type':'float',
26+
'min':'0',
27+
'max':'Inf',
28+
'precision':'0'
29+
}],
30+
# Server writable objects
31+
'writables': []
32+
},
33+
}
34+
}

config-examples/AppConfig-Octave.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# This file contains the configuration of the RIP server applicationself.
1+
# This file contains the configuration of the RIP server application.
22
config = {
33
# TO DO: The server will listen to host:port
44
'server': {
@@ -18,6 +18,24 @@
1818
'description': 'An implementation of RIP to control Octave',
1919
'authors': 'D. Garcia, J. Chacon',
2020
'keywords': 'Octave, Raspberry PI, Robot',
21-
}
21+
# Server readable objects
22+
'readables': [{
23+
'name':'x',
24+
'description':'Testing readable variable',
25+
'type':'float',
26+
'min':'-Inf',
27+
'max':'Inf',
28+
'precision':'0'
29+
}],
30+
# Server writable objects
31+
'writables': [{
32+
'name':'x',
33+
'description':'Testing readable variable',
34+
'type':'float',
35+
'min':'-Inf',
36+
'max':'Inf',
37+
'precision':'0'
38+
}],
39+
},
2240
}
2341
}

config-examples/AppConfig-RedPitaya.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# This file contains the configuration of the RIP server applicationself.
1+
# This file contains the configuration of the RIP server application.
22
config = {
33
# TO DO: The server will listen to host:port
44
'server': {
@@ -12,10 +12,12 @@
1212
'control': {
1313
'impl_module': 'RIPRedPitaya',
1414
'info': {
15-
'name': 'Octave',
15+
'name': 'RedPitaya',
1616
'description': 'An implementation of RIP to control Red Pitaya',
1717
'authors': 'Amine my-taj',
1818
'keywords': 'Red Pitaya, Raspberry PI',
19+
'readables': [],
20+
'writables': [],
1921
}
2022
}
2123
}

rip/RIPAdapterTemplate.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
'''
2+
@author: jcsombria
3+
'''
4+
import random
5+
from rip.RIPGeneric import RIPGeneric
6+
7+
class RIPAdapterTemplate(RIPGeneric):
8+
'''
9+
RIP Adapter Template
10+
'''
11+
12+
def __init__(self, info={}):
13+
'''
14+
Constructor
15+
'''
16+
super().__init__(info)
17+
18+
def default_info(self):
19+
'''
20+
You can provide default metadata here. AppConfig will override this definition.
21+
'''
22+
return {
23+
'name':'RIPAdapterTemplate',
24+
'description':'A template to extend RIP Generic',
25+
'authors':'J. Chacon',
26+
'keywords':'Adapter Template',
27+
'readables':[{
28+
'name':'time',
29+
'description':'Server time in seconds',
30+
'type':'float',
31+
'min':'0',
32+
'max':'Inf',
33+
'precision':'0',
34+
}, {
35+
'name':'random',
36+
'description':'Random value generator',
37+
'type':'float',
38+
'min':'0',
39+
'max':'1',
40+
'precision':'0'
41+
}],
42+
'writables': [{
43+
'name':'seed',
44+
'description':'Random seed',
45+
'type':'float',
46+
'min':'0',
47+
'max':'1',
48+
'precision':'0'
49+
}],
50+
}
51+
52+
def set(self, expid, variables, values):
53+
'''
54+
Write on or more variables
55+
'''
56+
n = len(variables)
57+
for i in range(n):
58+
try:
59+
n, v = variables[i], values[i]
60+
if v in writables:
61+
self.n = v
62+
except:
63+
pass
64+
65+
def get(self, expid, variables):
66+
'''
67+
Retrieve one or more variables under request
68+
'''
69+
toReturn = {}
70+
n = len(variables)
71+
for i in range(n):
72+
name = variables[i]
73+
try:
74+
toReturn[name] = random.rand
75+
except:
76+
pass
77+
return toReturn
78+
79+
def getValuesToNotify(self):
80+
'''
81+
Variables to include in periodic SSE updates
82+
'''
83+
return [
84+
['time', 'random'],
85+
[self.sampler.lastTime(), self.random]
86+
]
87+
88+
@property
89+
def seed(self):
90+
return self._seed
91+
92+
@seed.setter
93+
def seed(self, value):
94+
random.seed(value)
95+
96+
@property
97+
def random(self):
98+
return random.random()
99+
100+
@random.setter
101+
def random(self, value):
102+
pass

rip/RIPGeneric.py

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,16 @@ class RIPGeneric(JsonRpcServer):
1414
RIP Server - Reference Implementation
1515
'''
1616

17-
def __init__(self, name='RIP Generic', description='Generic RIP Server Implementation.', authors='J. Chacon', keywords='RIP'):
17+
def __init__(self, info={}):
1818
'''
1919
Constructor
2020
'''
21-
super().__init__(name, description)
22-
23-
self.authors = authors
24-
self.keywords = keywords
21+
metadata = self._parse_info(info)
22+
super().__init__(metadata['name'], metadata['description'])
23+
self.metadata = metadata
2524
self.ssePeriod = 0.5
2625
self.sseRunning = False
2726
self._running = False
28-
self.readables = [{
29-
'name':'time',
30-
'description':'Server time in seconds',
31-
'type':'float',
32-
'min':'0',
33-
'max':'Inf',
34-
'precision':'0'
35-
},
36-
]
37-
self.writables = []
3827
self.addMethods({
3928
'get': { 'description': 'To read server variables',
4029
'params': { 'expId': 'string', 'variables': '[string]' },
@@ -46,6 +35,32 @@ def __init__(self, name='RIP Generic', description='Generic RIP Server Implement
4635
},
4736
})
4837

38+
def default_info(self):
39+
return {
40+
'name':'RIP Generic',
41+
'description':'Generic RIP Server Implementation.',
42+
'authors': 'J. Chacon',
43+
'keywords': 'Raspberry PI, RIP',
44+
'readables': [{
45+
'name':'time',
46+
'description':'Server time in seconds',
47+
'type':'float',
48+
'min':'0',
49+
'max':'Inf',
50+
'precision':'0',
51+
}],
52+
'writables': [],
53+
}
54+
55+
def _parse_info(self, info):
56+
metadata = self.default_info()
57+
for p in info:
58+
try:
59+
metadata[p] = info[p]
60+
except:
61+
print('[WARNING] Property: %s not specified. Setting default value.' % p)
62+
return metadata
63+
4964
def start(self):
5065
'''
5166
Iniatilizes the server. Any code meant to be run at init should be here.
@@ -81,16 +96,16 @@ def build_info(self, address):
8196
info = RIPServerInfo(
8297
self.name,
8398
self.description,
84-
authors=self.authors,
85-
keywords=self.keywords
99+
authors=self.metadata['authors'],
100+
keywords=self.metadata['keywords']
86101
)
87102
readables = RIPVariablesList(
88-
list_=self.readables,
103+
list_=self.metadata['readables'],
89104
methods=[self.buildSSEGetInfo(address), self.buildPOSTGetInfo(address)],
90105
read_notwrite=True
91106
)
92107
writables = RIPVariablesList(
93-
list_=self.writables,
108+
list_=self.metadata['writables'],
94109
methods=[self.buildPOSTSetInfo(address)],
95110
read_notwrite=False
96111
)
@@ -108,7 +123,7 @@ def buildSSEGetInfo(self, address):
108123
RIPParam(name='variables',required='no',location='query',type_='array',subtype='string'),
109124
],
110125
returns='text/event-stream',
111-
example='%s/RIP/SSE?expId=%s' % (address, self.name),
126+
example='%s/RIP/SSE?expId=%s' % (address, self.metadata['name']),
112127
)
113128

114129
def buildPOSTGetInfo(self, address):
@@ -129,7 +144,7 @@ def buildPOSTGetInfo(self, address):
129144
returns='application/json',
130145
example={ '%s/RIP/POST' % address: {
131146
'headers': {'Accept': 'application/json','Content-Type': 'application/json'},
132-
'body': {'jsonrpc':'2.0', 'method':'get', 'params':['%s' % self.name, [r['name'] for r in self.readables]], 'id':'1'}
147+
'body': {'jsonrpc':'2.0', 'method':'get', 'params':['%s' % self.metadata['name'], [r['name'] for r in self.metadata['readables']]], 'id':'1'}
133148
}}
134149
)
135150

@@ -149,7 +164,7 @@ def buildPOSTSetInfo(self, address):
149164
example_post_set = {
150165
'%s/RIP/POST' % address: {
151166
'headers': {'Accept': 'application/json','Content-Type': 'application/json'},
152-
'body': {'jsonrpc':'2.0','method':'set','params':['%s' % self.name,[w['name'] for w in self.writables],['val' for w in self.writables]],'id':'1'}
167+
'body': {'jsonrpc':'2.0','method':'set','params':['%s' % self.metadata['name'],[w['name'] for w in self.metadata['writables']],['val' for w in self.metadata['writables']]],'id':'1'}
153168
}
154169
}
155170
return RIPMethod(

0 commit comments

Comments
 (0)