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
56pip 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
1213import 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
1616from 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
2120def 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 )
3337stream.publish(handler)
3438```
3539
3640### Publish one signal as an event
3741``` python
3842import 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
4245from 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
5866import os
5967import numpy as np
60- from avenieca.utils import Config
68+ from avenieca.config.broker import Broker
69+ from avenieca.data import Signal
6170from avenieca.utils.signal import get_state_as_list, get_state_as_array
6271from 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
6986def 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 )
7693client.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
0 commit comments