Skip to content

Commit c13df81

Browse files
authored
Merge pull request #1 from aveni-hub/rest-api
Add REST API, Data and Models
2 parents e781753 + e4fb01f commit c13df81

39 files changed

Lines changed: 1782 additions & 99 deletions

README.md

Lines changed: 265 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,86 @@
11
# avenieca-python
2-
Python SDK for publishing state signals to the AveniECA suite.
2+
Python SDK for ingress and retrieval to an AveniECA instance.
3+
Stream state through Kafka, interact with the REST API.
34

45
```bash
56
pip install avenieca-python
67
```
78

89
## Usage
910

10-
### Stream continuously to a topic
11+
### Stream continuously to your twin's sub_topic
1112
```python
1213
import os
13-
import numpy as np
14-
from avenieca.utils import Config
15-
from avenieca.utils import Signal
14+
from avenieca.config.broker import Broker
15+
from avenieca.data import Signal
1616
from avenieca.producers import Stream
1717

18-
# Define a handler that returns a signal dict like
19-
# the sample in avenieca.utils.signal
18+
# Define a handler that returns a Signal dataclass
2019

2120
def handler():
22-
Signal["valence"] = 10
23-
Signal["state"] = np.array([0.2, 0.3, 0.8])
24-
return Signal
21+
signal = Signal(
22+
valence=10,
23+
state=[0.2, 0.3, 0.8],
24+
)
25+
return signal
2526

26-
# Initialize Kafka configuration for the Stream
27-
Config["bootstrap_servers"] = os.environ["KAFKA_URL"]
28-
Config["topic"] = "left_wheel" #digital twin subscriber-topic
27+
# Initialize broker configuration for the Stream
28+
config = Broker(
29+
url=os.environ["KAFKA_URL"],
30+
sub_topic="left_wheel", #ECA twin subscriber-topic
31+
group="test",
32+
pub_topic=""
33+
)
2934

30-
#Initialize the Stream object with a sync_rate
31-
# (the rate at which to publish signals).
32-
stream = Stream(config=Config, sync_rate=1)
35+
# Initialize the Stream object with a sync_rate
36+
stream = Stream(config=config, sync_rate=1)
3337
stream.publish(handler)
3438
```
3539

3640
### Publish one signal as an event
3741
```python
3842
import os
39-
import numpy as np
40-
from avenieca.utils import Config
41-
from avenieca.utils import Signal
43+
from avenieca.config.broker import Broker
44+
from avenieca.data import Signal
4245
from avenieca.producers import Event
4346

44-
# Initialize Kafka configuration for the Event
45-
Config["bootstrap_servers"] = os.environ["KAFKA_URL"]
46-
Config["topic"] = "left_wheel" #digital twin subscriber-topic
47+
config = Broker(
48+
url=os.environ["KAFKA_URL"],
49+
sub_topic="left_wheel",
50+
group="test",
51+
pub_topic=""
52+
)
4753

4854
# Define the signal
49-
Signal["valence"] = 9
50-
Signal["state"] = np.array([0.2, 0.3, 0.8])
55+
signal = Signal(
56+
valence=9.0,
57+
state=[0.2, 0.3, 0.8],
58+
)
5159

52-
event = Event(config=Config)
53-
event.publish(Signal)
60+
event = Event(config=config)
61+
event.publish(signal)
5462
```
5563

5664
### Consume from kafka topic
5765
```python
5866
import os
5967
import numpy as np
60-
from avenieca.utils import Config
68+
from avenieca.config.broker import Broker
69+
from avenieca.data import Signal
6170
from avenieca.utils.signal import get_state_as_list, get_state_as_array
6271
from avenieca.consumer import Consumer
6372

64-
# Initialize Kafka configuration for the Event
65-
Config["bootstrap_servers"] = os.environ["KAFKA_URL"]
66-
Config["topic"] = "left_wheel" #digital twin subscriber-topic
73+
config = Broker(
74+
url=os.environ["KAFKA_URL"],
75+
sub_topic="left_wheel",
76+
group="test",
77+
pub_topic=""
78+
)
79+
80+
signal = Signal(
81+
valence=9.0,
82+
state=[0.2, 0.3, 0.8],
83+
)
6784

6885
# Define a handler to process incoming messages
6986
def handler(data):
@@ -72,24 +89,239 @@ def handler(data):
7289
assert valence == 10
7390
assert state == "[0.2, 0.3, 0.8]"
7491

75-
client = Consumer(config=Config)
92+
client = Consumer(config=config)
7693
client.consume(handler, True) # pass in handler
7794

7895
# You can use util functions in your handler to
7996
# convert the state signal from byte string to
8097
# np.ndarray or python list
81-
def handler(data):
98+
def handler1(data):
8299
assert data["valence"] == 10
83100
assert data["state"] == "[0.2, 0.3, 0.8]"
84101
get_state_as_list(data)
85102
assert data["state"] == [0.2, 0.3, 0.8]
86103

87-
def handler(data):
104+
def handler2(data):
88105
assert data["valence"] == 10
89106
assert data["state"] == "[0.2, 0.3, 0.8]"
90107
get_state_as_array(data)
91108
assert True, np.array_equal(data["state"], np.array([0.2, 0.3, 0.8]))
92109
```
110+
### REST API
111+
```python
112+
import os
113+
from pprint import pprint
114+
115+
import avenieca.config.twin
116+
from avenieca.api.model import *
117+
from avenieca.api.eca import ECA
118+
119+
username = os.getenv("USERNAME")
120+
password = os.getenv("PASSWORD")
121+
config = Config(uri="http://localhost:2580/v1", username=username, password=password)
122+
123+
eca = ECA(config)
124+
125+
'''ESS'''
126+
ess = ESSInsert(
127+
module_id="air_conditioner",
128+
state=[11],
129+
valence=10.0,
130+
score=4,
131+
embedding_input=1,
132+
context=None,
133+
)
134+
res, status = eca.ess.create(data=ess)
135+
res, status = eca.ess.get_all(module_id="air_conditioner")
136+
res, status = eca.ess.get_one(module_id="air_conditioner", db_id=8)
137+
res, status = eca.ess.update(module_id="air_conditioner", db_id=8, data=ess)
138+
res, status = eca.ess.get_one_sequence(module_id="air_conditioner", sequence_id=3)
139+
res, status = eca.ess.get_all_sequence(module_id="air_conditioner")
140+
res, status = eca.ess.get_one_pretty(module_id="gwp_record", db_id=1)
141+
res, status = eca.ess.search(data=Search(
142+
module_id="air_conditioner",
143+
state=[18],
144+
limit=1
145+
))
146+
res, status = eca.ess.get_one_embedding(module_id="air_conditioner", embedding_input=1)
147+
res, status = eca.ess.get_all_aggregates(module_id="team", aggregate_module_id="gwp_aggregate", ess_id=1)
148+
149+
'''Sequence'''
150+
sequence = SequenceInsert(
151+
module_id="air_conditioner",
152+
instance_id=10,
153+
status="e",
154+
context=None,
155+
)
156+
res, status = eca.sequence.create(data=sequence)
157+
res, status = eca.sequence.get_one(module_id="air_conditioner", db_id=4)
158+
res, status = eca.sequence.get_all(module_id="air_conditioner")
159+
res, status = eca.sequence.update(module_id="air_conditioner", db_id=4, data=sequence)
160+
res, status = eca.sequence.delete(module_id="aggregate001", db_id=59)
161+
162+
163+
nsr = NextStateRequest(
164+
module_id="aggregate001",
165+
recall=20,
166+
range=20,
167+
n=1,
168+
status="e",
169+
)
170+
res, status = eca.cortex.predictions(data=nsr)
171+
res, status = eca.cortex.predictions_raw(data=nsr)
172+
173+
'''Document'''
174+
document = DocumentInsert(
175+
doc_id="001",
176+
text="testing 123",
177+
embed=True,
178+
)
179+
res, status = eca.document.create(data=document)
180+
res, status = eca.document.get_one(db_id=20)
181+
res, status = eca.document.get_all()
182+
res, status = eca.document.update(db_id=20, data=document)
183+
res, status = eca.document.delete(db_id=100)
184+
185+
'''Embedding'''
186+
input_hash = avenieca.encode("my_secret", "the inputs")
187+
embedding = EmbeddingInputInsert(
188+
module_id="air_conditioner",
189+
input="the inputs",
190+
hash=input_hash
191+
)
192+
res, status = eca.embedding.create(data=embedding)
193+
res, status = eca.embedding.get_one(module_id="air_conditioner", db_id=1)
194+
res, status = eca.embedding.get_all(module_id="air_conditioner")
195+
res, status = eca.embedding.update(module_id="air_conditioner", db_id=1, data=embedding)
196+
res, status = eca.embedding.delete(module_id="air_conditioner", db_id=1)
197+
198+
'''Response'''
199+
res, status = eca.response.get_one(db_id=100)
200+
res, status = eca.response.get_all()
201+
202+
'''Retrieval'''
203+
retrieval = RetrievalRequest(
204+
query="what is the temperature on 3rd of may at around 1pm?"
205+
)
206+
res, status = eca.retrieval.query(data=retrieval)
207+
208+
'''create ess, then create aggregate'''
209+
ess_temperature = ESSResponse(
210+
id=2,
211+
created_at='',
212+
updated_at='',
213+
module_id="temperature",
214+
state=[28.0],
215+
valence=-90,
216+
score=1,
217+
context=None,
218+
embedding_input=None
219+
)
220+
ess_air_conditioner = ESSResponse(
221+
id=5,
222+
created_at='',
223+
updated_at='',
224+
state=[25.0],
225+
module_id='air_conditioner',
226+
valence=90.0,
227+
score=18,
228+
embedding_input=None,
229+
context=None
230+
)
231+
ess_occupancy = ESSResponse(
232+
id=7,
233+
created_at='',
234+
updated_at='',
235+
state=[10.0],
236+
module_id='occupancy',
237+
valence=-90.0,
238+
score=6,
239+
embedding_input=None,
240+
context=None
241+
)
242+
ess_purifier = ESSResponse(
243+
id=3,
244+
state=[2.0],
245+
module_id='purifier',
246+
valence=90.0,
247+
score=28,
248+
embedding_input=None,
249+
context=None)
250+
ess_air_quality_index = ESSResponse(
251+
id=6,
252+
created_at='',
253+
updated_at='',
254+
state=[70.0],
255+
module_id='air_quality_index',
256+
valence=-90.0,
257+
score=2,
258+
embedding_input=None,
259+
context=None
260+
)
261+
aggregate_insert = ESSInsert(
262+
module_id="aggregate001",
263+
state=[],
264+
valence=10.0,
265+
avg_ess_valence=0.0,
266+
score=0,
267+
total_ess_score=0,
268+
avg_ess_score=0,
269+
aggregate_id=[],
270+
aggregate_valence=[],
271+
aggregate_score=[],
272+
aggregate_module_id=[],
273+
aggregate_shape=[],
274+
aggregate_context=[],
275+
aggregate_emb_inp=[],
276+
context=None,
277+
)
278+
279+
280+
def create_aggregate_from_ess(array_ess: List[ESSResponse], aggregate_insert: ESSInsert):
281+
total_ess_score = 0
282+
total_ess_valence = 0.0
283+
for ess in array_ess:
284+
aggregate_insert.state.extend(ess.state)
285+
aggregate_insert.aggregate_module_id.append(ess.module_id)
286+
aggregate_insert.aggregate_id.append(ess.id)
287+
aggregate_insert.aggregate_context.append(ess.context)
288+
aggregate_insert.aggregate_valence.append(ess.valence)
289+
aggregate_insert.aggregate_score.append(ess.score)
290+
aggregate_insert.aggregate_emb_inp.append(ess.embedding_input)
291+
aggregate_insert.aggregate_shape.append(len(ess.state))
292+
total_ess_score += ess.score
293+
total_ess_valence += ess.valence
294+
aggregate_insert.total_ess_score = total_ess_score
295+
aggregate_insert.avg_ess_score = int(total_ess_score / len(array_ess))
296+
aggregate_insert.avg_ess_valence = total_ess_valence / len(array_ess)
297+
aggregate_insert.valence = total_ess_valence
298+
return aggregate_insert
299+
300+
agg_in = create_aggregate_from_ess(
301+
[
302+
ess_air_conditioner,
303+
ess_air_quality_index,
304+
ess_occupancy,
305+
ess_purifier,
306+
ess_temperature
307+
],
308+
aggregate_insert)
309+
310+
res, status = eca.ess.create(data=agg_in)
311+
res, status = eca.ess.upsert(module_id="aggregate001", db_id=5)
312+
313+
res, status = eca.sequence.create(data=SequenceInsert(
314+
module_id="aggregate001",
315+
instance_id=34,
316+
status="sk"
317+
))
318+
319+
try:
320+
pprint(res.__dict__)
321+
except:
322+
print(len(res))
323+
print(status)
324+
```
93325

94326
## Tests
95327
```bash

avenieca/api/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from avenieca.api.utils import *
2+
from avenieca.api import *

avenieca/api/auth.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import requests
2+
3+
from avenieca.api.client import Client
4+
from avenieca.api.model import Config
5+
from avenieca.api.model import AuthLogin
6+
from avenieca.api.model import AuthResponse
7+
from avenieca.api.model import Error
8+
9+
10+
class Auth:
11+
"""Initializes an Auth object to make calls to the /login endpoint.
12+
13+
Parameters
14+
----------
15+
config : dict of config values
16+
"""
17+
18+
def __init__(self, config: Config):
19+
self.client = Client(config)
20+
21+
def login(self, data: AuthLogin):
22+
"""
23+
login to retrieve api-token.
24+
Parameters
25+
----------
26+
data = {"username": "","password": ""}
27+
"""
28+
response, status = self.client.http_post("/login", "", data.__dict__)
29+
if status != requests.codes['ok']:
30+
try:
31+
return Error(**response), status
32+
except TypeError:
33+
return response, status
34+
auth_response = AuthResponse(**response)
35+
return auth_response, status

0 commit comments

Comments
 (0)