@@ -42,18 +42,13 @@ class EdgeImpulseRunnerFacade:
4242 """Facade for Edge Impulse Object Detection and Classification."""
4343
4444 def __init__ (self ):
45- """Initialize the EdgeImpulseRunnerFacade with the API path."""
46- infra = load_brick_compose_file (self .__class__ )
47- for k , v in infra ["services" ].items ():
48- self .host = k
49- self .infra = v
50- break # Only one service is expected
51-
52- self .host = resolve_address (self .host )
45+ """Initialize the EdgeImpulseRunnerFacade with the API path.
5346
54- self .port = 1337 # Default EI HTTP port
55- self .url = f"http://{ self .host } :{ self .port } "
56- logger .warning (f"[{ self .__class__ .__name__ } ] Host: { self .host } - Ports: { self .port } - URL: { self .url } " )
47+ Raises:
48+ RuntimeError: If the Edge Impulse runner address cannot be resolved.
49+ """
50+ self .url = self ._get_ei_url ()
51+ logger .info (f"[{ self .__class__ .__name__ } ] URL: { self .url } " )
5752
5853 def infer_from_file (self , image_path : str ) -> dict | None :
5954 if not image_path or image_path == "" :
@@ -124,47 +119,58 @@ def process(self, item):
124119 logger .error (f"[{ self .__class__ } ] Error processing file { item } : { e } " )
125120 return None
126121
127- def infer_from_features (self , features : list ) -> dict | None :
128- """Infer from features using the Edge Impulse API.
122+ @classmethod
123+ def infer_from_features (cls , features : list ) -> dict | None :
124+ """
125+ Infer from features using the Edge Impulse API.
129126
130127 Args:
128+ cls: The class method caller.
131129 features (list): A list of features to send to the Edge Impulse API.
132130
133131 Returns:
134132 dict | None: The response from the Edge Impulse API as a dictionary, or None if an error occurs.
135133 """
136134 try :
137- response = requests .post (f"{ self .url } /api/features" , json = {"features" : features })
135+ url = cls ._get_ei_url ()
136+ model_info = cls .get_model_info (url )
137+ features = features [: int (model_info .input_features_count )]
138+
139+ response = requests .post (f"{ url } /api/features" , json = {"features" : features })
138140 if response .status_code == 200 :
139141 return response .json ()
140142 else :
141- logger .warning (f"[{ self . __class__ } ] error: { response .status_code } . Message: { response .text } " )
143+ logger .warning (f"[{ cls . __name__ } ] error: { response .status_code } . Message: { response .text } " )
142144 return None
143145 except Exception as e :
144- logger .error (f"[{ self . __class__ .__name__ } ] Error: { e } " )
146+ logger .error (f"[{ cls .__name__ } ] Error: { e } " )
145147 return None
146148
147- def get_model_info (self ) -> EdgeImpulseModelInfo | None :
149+ @classmethod
150+ def get_model_info (cls , url : str = None ) -> EdgeImpulseModelInfo | None :
148151 """Get model information from the Edge Impulse API.
149152
153+ Args:
154+ cls: The class method caller.
155+ url (str): The base URL of the Edge Impulse API. If None, it will be determined automatically.
156+
150157 Returns:
151158 model_info (EdgeImpulseModelInfo | None): An instance of EdgeImpulseModelInfo containing model details, None if an error occurs.
152159 """
153- if not self .host or not self .port :
154- logger .error (f"[{ self .__class__ } ] Host or port not set. Cannot fetch model info." )
155- return None
160+ if not url :
161+ url = cls ._get_ei_url ()
156162
157163 http_client = HttpClient (total_retries = 6 ) # Initialize the HTTP client with retry logic
158164 try :
159- response = http_client .request_with_retry (f"{ self . url } /api/info" )
165+ response = http_client .request_with_retry (f"{ url } /api/info" )
160166 if response .status_code == 200 :
161- logger .debug (f"[{ self . __class__ . __name__ } ] Fetching model info from { self . url } /api/info -> { response .status_code } { response .json } " )
167+ logger .debug (f"[{ cls . __name__ } ] Fetching model info from { url } /api/info -> { response .status_code } { response .json } " )
162168 return EdgeImpulseModelInfo (response .json ())
163169 else :
164- logger .warning (f"[{ self . __class__ } ] Error fetching model info: { response .status_code } . Message: { response .text } " )
170+ logger .warning (f"[{ cls } ] Error fetching model info: { response .status_code } . Message: { response .text } " )
165171 return None
166172 except Exception as e :
167- logger .error (f"[{ self . __class__ } ] Error fetching model info: { e } " )
173+ logger .error (f"[{ cls } ] Error fetching model info: { e } " )
168174 return None
169175 finally :
170176 http_client .close () # Close the HTTP client session
@@ -237,3 +243,19 @@ def _extract_anomaly_score(self, item: dict):
237243 return class_results ["anomaly" ]
238244
239245 return None
246+
247+ @classmethod
248+ def _get_ei_url (cls ):
249+ infra = load_brick_compose_file (cls )
250+ if not infra or "services" not in infra :
251+ raise RuntimeError ("Cannot load Brick Compose file to resolve Edge Impulse runner address." )
252+ host = None
253+ for k , v in infra ["services" ].items ():
254+ host = k
255+ break
256+ if not host :
257+ raise RuntimeError ("Cannot resolve Edge Impulse runner address from Brick Compose file." )
258+ addr = resolve_address (host )
259+ if not addr :
260+ raise RuntimeError ("Host address resolution failed for Edge Impulse runner." )
261+ return f"http://{ addr } :1337"
0 commit comments