@@ -155,28 +155,95 @@ def fetch_measurements_for_sensor(
155155 )
156156 except Exception as e :
157157 print (f"Error executing query on table { table_name } : { e } " )
158- # query = sql.SQL("SELECT * FROM {} WHERE id = ANY(%s)").format(
159- # sql.Identifier(table_name)
160- # )
161- # cur.execute(query, (ids,))
162- # columns = [desc[0] for desc in cur.description]
163- # for row in cur.fetchall():
164- # data = {col: val for col, val in zip(columns[3:], row[3:])}
165- # filtered_data = {k: v for k, v in data.items() if v is not None}
166- # measurements.append(
167- # Measurement(
168- # # sensor_id=row[1],
169- # table_name=table_name,
170- # timestamp=str(row[2]),
171- # data=filtered_data,
172- # )
173- # )
174158
175159 # Now sort all measurements by timestamp descending
176160 measurements .sort (key = lambda x : x .timestamp , reverse = True )
177161 return measurements
178162
179163
164+ def fetch_locations_for_device_list (conn , device_list : list [str ]) -> list :
165+ """Fetch the latest location for each device in the device_list."""
166+ with conn .cursor () as cur :
167+ query = """
168+ SELECT
169+ m.measurement_id,
170+ r.measurement_table_name,
171+ s.sensor_name
172+ FROM measurements m
173+ JOIN application_measurements_registry r
174+ ON m.registry_id = r.id
175+ JOIN sensors s
176+ ON m.sensor_id = s.id
177+ ORDER BY m.timestamp DESC
178+ """
179+ cur .execute (
180+ query ,
181+ )
182+
183+ rows = cur .fetchall ()
184+
185+ # Step 2: Group measurement_ids by table name
186+ table_to_ids = defaultdict (list )
187+ for measurement_id , table_name , sensor_name in rows :
188+ print (
189+ f"Sensor name in DB: { sensor_name } , measurement_id: { measurement_id } , table_name: { table_name } "
190+ )
191+ table_to_ids [table_name ].append ((measurement_id , sensor_name ))
192+
193+ locations = []
194+
195+ # Step 3: Query each table for its measurement_ids
196+ for table_name , info in table_to_ids .items ():
197+ measurement_ids , sensor_names = zip (* info )
198+ ids = list (measurement_ids )
199+ print (f"IDs: { ids } " )
200+ # Check if latitude and longitude columns exist in the table
201+ cur .execute (
202+ sql .SQL (
203+ "SELECT column_name FROM information_schema.columns WHERE table_name = %s AND column_name IN ('latitude', 'longitude')"
204+ ),
205+ (table_name ,),
206+ )
207+ columns_present = {row [0 ] for row in cur .fetchall ()}
208+ if not {"latitude" , "longitude" }.issubset (columns_present ):
209+ continue
210+ select_fields = sql .SQL ("id, timestamp, latitude, longitude" )
211+ query = sql .SQL (
212+ "SELECT {} FROM {} WHERE id = ANY(%s) ORDER BY timestamp DESC"
213+ ).format (select_fields , sql .Identifier (table_name ))
214+ # print(f"Executing query on table {table_name} for IDs: {ids}")
215+ # print(f"Query: {query.as_string(conn)}")
216+
217+ try :
218+ cur .execute (query , (ids ,))
219+ columns = [desc [0 ] for desc in cur .description ]
220+ rows = cur .fetchall ()
221+ for row in rows :
222+ data = {col : val for col , val in zip (columns [1 :], row [1 :])}
223+ filtered_data = {k : v for k , v in data .items () if v is not None }
224+
225+ # sensor_name = sensor_names[ids.index(row[0])]
226+ filtered_data ["sensor_name" ] = sensor_name
227+ print (f"Sensor name: { sensor_name } " )
228+ if filtered_data :
229+ if (
230+ filtered_data .get ("latitude" ) is not None
231+ and filtered_data .get ("longitude" ) is not None
232+ ):
233+ locations .append (
234+ Measurement (
235+ table_name = table_name ,
236+ timestamp = str (row [1 ]),
237+ data = filtered_data ,
238+ )
239+ )
240+ break
241+ except Exception as e :
242+ print (f"Error executing query on table { table_name } : { e } " )
243+
244+ return locations
245+
246+
180247def fetch_sensors_for_application (conn , app_name : str ) -> list | None :
181248 """Fetch all sensors for a given application name."""
182249 with conn .cursor () as cur :
0 commit comments