Skip to content

Commit 65f33fd

Browse files
committed
Added new example for nested schema
1 parent f0b6ee5 commit 65f33fd

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

examples/nested_thing.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import random
2+
import math
3+
import uuid
4+
5+
from labthings.server.quick import create_app
6+
from labthings.server.decorators import ThingProperty, PropertySchema
7+
from labthings.server.view import View
8+
from labthings.server.find import find_component
9+
from labthings.server.schema import Schema
10+
from labthings.server import fields
11+
12+
13+
"""
14+
Class for our lab component functionality. This could include serial communication,
15+
equipment API calls, network requests, or a "virtual" device as seen here.
16+
"""
17+
18+
19+
class DataSet:
20+
def __init__(self, xs, ys):
21+
self.xs = xs
22+
self.ys = ys
23+
24+
25+
class DataSetSchema(Schema):
26+
xs = fields.List(fields.Number())
27+
ys = fields.List(fields.Number())
28+
29+
30+
class MyComponent:
31+
def __init__(self):
32+
self.id = uuid.uuid4()
33+
self.x_range = range(-100, 100)
34+
self.magic_denoise = 200
35+
36+
def noisy_pdf(self, x, mu=0.0, sigma=25.0):
37+
"""
38+
Generate a noisy gaussian function (to act as some pretend data)
39+
40+
Our noise is inversely proportional to self.magic_denoise
41+
"""
42+
x = float(x - mu) / sigma
43+
return (
44+
math.exp(-x * x / 2.0) / math.sqrt(2.0 * math.pi) / sigma
45+
+ (1 / self.magic_denoise) * random.random()
46+
)
47+
48+
@property
49+
def data(self):
50+
"""
51+
Return a 1D data trace.
52+
"""
53+
return DataSet(self.x_range, [self.noisy_pdf(x) for x in self.x_range])
54+
55+
56+
class MyComponentSchema(Schema):
57+
id = fields.UUID()
58+
magic_denoise = fields.Int()
59+
data = fields.Nested(DataSetSchema())
60+
61+
62+
"""
63+
Create a view to view and change our magic_denoise value, and register is as a Thing property
64+
"""
65+
66+
67+
@ThingProperty # Register this view as a Thing Property
68+
@PropertySchema( # Define the data we're going to output (get), and what to expect in (post)
69+
fields.Integer(
70+
required=True,
71+
example=200,
72+
minimum=100,
73+
maximum=500,
74+
description="Value of magic_denoise",
75+
)
76+
)
77+
class DenoiseProperty(View):
78+
79+
# Main function to handle GET requests (read)
80+
def get(self):
81+
"""Show the current magic_denoise value"""
82+
83+
# When a GET request is made, we'll find our attached component
84+
my_component = find_component("org.labthings.example.mycomponent")
85+
return my_component.magic_denoise
86+
87+
# Main function to handle POST requests (write)
88+
def post(self, new_property_value):
89+
"""Change the current magic_denoise value"""
90+
91+
# Find our attached component
92+
my_component = find_component("org.labthings.example.mycomponent")
93+
94+
# Apply the new value
95+
my_component.magic_denoise = new_property_value
96+
97+
return my_component.magic_denoise
98+
99+
100+
"""
101+
Create a view to quickly get some noisy data, and register is as a Thing property
102+
"""
103+
104+
105+
@ThingProperty
106+
@PropertySchema(MyComponentSchema())
107+
class MyComponentProperty(View):
108+
# Main function to handle GET requests
109+
def get(self):
110+
"""Show the current data value"""
111+
112+
# Find our attached component
113+
return find_component("org.labthings.example.mycomponent")
114+
115+
116+
# Create LabThings Flask app
117+
app, labthing = create_app(
118+
__name__,
119+
prefix="/api",
120+
title=f"My Lab Device API",
121+
description="Test LabThing-based API",
122+
version="0.1.0",
123+
)
124+
125+
# Attach an instance of our component
126+
labthing.add_component(MyComponent(), "org.labthings.example.mycomponent")
127+
128+
# Add routes for the API views we created
129+
labthing.add_view(DenoiseProperty, "/denoise")
130+
labthing.add_view(MyComponentProperty, "/component")
131+
132+
133+
# Start the app
134+
if __name__ == "__main__":
135+
app.run(host="0.0.0.0", port="5000", threaded=True, debug=True, use_reloader=False)

0 commit comments

Comments
 (0)