PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ] ); // Get parameters $tagName = $_GET['tag'] ?? ''; $lastTimestamp = $_GET['last_timestamp'] ?? null; $limit = min((int)($_GET['limit'] ?? 500), 7200); // Max 10000 points $startTime = $_GET['start_time'] ?? null; $endTime = $_GET['end_time'] ?? null; if (empty($tagName)) { throw new Exception('Tag name required'); } // Build query to get latest data from archive $sql = "SELECT a.TimeStamp, a.Value, a.ID FROM dbo.archive a LEFT JOIN dbo.id_names n ON a.ID = n.idnumber WHERE n.name = :tag_name"; $params = [':tag_name' => $tagName]; if ($startTime && $endTime) { $sql .= " AND a.TimeStamp BETWEEN :start_time AND :end_time"; $params[':start_time'] = $startTime; $params[':end_time'] = $endTime; } elseif ($lastTimestamp) { $sql .= " AND a.TimeStamp > :last_timestamp"; $params[':last_timestamp'] = $lastTimestamp; } $sql .= " ORDER BY a.TimeStamp DESC OFFSET 0 ROWS FETCH NEXT :limit ROWS ONLY"; $stmt = $pdo->prepare($sql); foreach ($params as $key => $value) { $stmt->bindValue($key, $value); } $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); $results = $stmt->fetchAll(); // Reverse to get chronological order $results = array_reverse($results); // Format data for Chart.js $data = []; foreach ($results as $row) { $data[] = [ 'x' => $row['TimeStamp'], 'y' => (float)$row['Value'], 'timestamp' => $row['TimeStamp'] ]; } $response = [ 'success' => true, 'data' => $data, 'count' => count($data), 'latest_timestamp' => !empty($data) ? end($data)['timestamp'] : null, 'tag' => $tagName ]; } catch (Exception $e) { $response = [ 'success' => false, 'error' => $e->getMessage() ]; } echo json_encode($response); ?>