customerInfoService = $customerInfoService; } // public function alertMessage(Request $request){ // $token = readHeaderToken(); // if (!$token) { // return response()->json([ // 'success' => false, // 'error' => 'Authorization token required' // ], 401); // } // $validator = Validator::make($request->all(), [ // 'device_id' => 'required|string', // 'startTs' => 'nullable|string', // 'endTs' => 'nullable|string', // ]); // if ($validator->fails()) { // return response()->json([ // 'success' => false, // 'error' => $validator->errors()->first() // ], 400); // } // $deviceId = $request->input('device_id'); // // $deviceWithTelemetry = Device::with([ // // 'deviceProfile', // // 'timeseriesKeys' => function ($query) { // // $query->where(function ($q) { // // $q->where('display_on_dashboard', true) // // ->orWhere('display_on_popup', true); // // }) // // ->select('id','device_profile_xid', 'display_name') // // ->with(['timeseriesAlert' => function($query) { // Use singular name to match model // // $query->select('id', 'timeseries_key_master_xid', 'min_value', 'max_value', 'color_code', 'alert_msg'); // // }]); // // } // // ]) // // ->where('id', $deviceId) // // ->firstOrFail(); // } // public function alertMessage(Request $request) // { // try { // // Authentication // $token = readHeaderToken(); // if (!$token) { // return response()->json([ // 'success' => false, // 'message' => 'Authorization token required' // ], 401); // } // // Validation // $validator = Validator::make($request->all(), [ // 'device_id' => 'required|string|exists:devices,id', // 'startTs' => 'nullable|numeric', // 'endTs' => 'nullable|numeric|gte:startTs', // ]); // if ($validator->fails()) { // return response()->json([ // 'success' => false, // 'message' => $validator->errors()->first() // ], 400); // } // // Fetch device with relationships // $device = Device::with([ // 'deviceProfile', // 'timeseriesKeys' => function ($query) { // $query->where(function ($q) { // $q->where('display_on_dashboard', true) // ->orWhere('display_on_popup', true); // }) // ->select('id', 'device_profile_xid', 'key_name', 'display_name') // ->with(['timeseriesAlert' => function ($query) { // $query->select('id', 'timeseries_key_master_xid', 'min_value', 'max_value', 'color_code', 'alert_msg'); // }]); // } // ])->findOrFail($request->device_id); // // Get telemetry data // $telemetryData = $this->customerInfoService->getTelemetryDataDevice( // $device, // $device->timeseriesKeys->pluck('key_name')->toArray(), // $request->startTs, // $request->endTs // ); // if (isset($telemetryData['error'])) { // throw new \Exception($telemetryData['error']); // } // // Process data // $result = [ // 'alerts' => [], // 'normal_telemetry' => [] // ]; // foreach ($device->timeseriesKeys as $key) { // if (!isset($telemetryData[$key->key_name])) continue; // $dataPoint = $telemetryData[$key->key_name][0] ?? null; // if (!$dataPoint || !isset($dataPoint['value'])) continue; // $item = [ // 'key' => $key->key_name, // 'display_name' => $key->display_name, // 'value' => $dataPoint['value'], // 'timestamp' => $dataPoint['ts'] ?? null // ]; // // Check alerts // // Inside your alertMessage controller method, modify the alert check: // foreach ($key->timeseriesAlert as $alert) { // $isBelowMin = $alert->min_value !== null && $dataPoint['value'] < $alert->min_value; // $isAboveMax = $alert->max_value !== null && $dataPoint['value'] > $alert->max_value; // if ($isBelowMin || $isAboveMax) { // Log::warning("Alert triggered", [ // 'device' => $device->id, // 'key' => $key->key_name, // 'value' => $dataPoint['value'], // 'threshold_min' => $alert->min_value, // 'threshold_max' => $alert->max_value, // 'condition' => $isBelowMin ? 'below_min' : 'above_max' // ]); // $item['alert'] = [ // 'message' => $alert->alert_msg, // 'color_code' => $alert->color_code, // 'thresholds' => [ // 'min' => $alert->min_value, // 'max' => $alert->max_value // ] // ]; // $result['alerts'][] = $item; // continue 2; // } // } // $result['normal_telemetry'][] = $item; // } // return response()->json([ // 'success' => true, // 'device' => [ // 'id' => $device->id, // 'name' => $device->name, // 'profile' => $device->deviceProfile // ], // 'data' => $result // ]); // } catch (\Exception $e) { // Log::error("Alert processing failed: {$e->getMessage()}", [ // 'device_id' => $request->device_id ?? null, // 'trace' => $e->getTraceAsString() // ]); // return response()->json([ // 'success' => false, // 'message' => 'Failed to process alerts: ' . $e->getMessage() // ], 500); // } // } public function alertMessage(Request $request) { try { // Authentication $token = readHeaderToken(); if (!$token) { return response()->json([ 'success' => false, 'message' => 'Authorization token required' ], 401); } // Validation $validator = Validator::make($request->all(), [ 'device_id' => 'required|string|exists:devices,id', 'startTs' => 'nullable|numeric', 'endTs' => 'nullable|numeric|gte:startTs', ]); if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => $validator->errors()->first() ], 400); } // Fetch device with relationships $device = Device::with([ 'deviceProfile', 'timeseriesKeys' => function ($query) { $query->where(function ($q) { $q->where('display_on_dashboard', true) ->orWhere('display_on_popup', true); }) ->select('id', 'device_profile_xid', 'key_name', 'display_name') ->with(['timeseriesAlert' => function ($query) { $query->select('id', 'timeseries_key_master_xid', 'min_value', 'max_value', 'color_code', 'alert_msg'); }]); } ])->findOrFail($request->device_id); // Get telemetry data FIRST $telemetryData = $this->customerInfoService->getTelemetryDataDevice( $device, $device->timeseriesKeys->pluck('key_name')->toArray(), $request->startTs, $request->endTs ); if (isset($telemetryData['error'])) { throw new \Exception($telemetryData['error']); } // Get only the keys that actually exist in ThingsBoard response $existingKeys = array_keys($telemetryData); // Process data $result = [ 'alerts' => [], 'normal_telemetry' => [] ]; foreach ($device->timeseriesKeys as $key) { // Skip if this key doesn't exist in ThingsBoard response if (!in_array($key->key_name, $existingKeys)) { continue; } $dataPoint = $telemetryData[$key->key_name][0] ?? null; if (!$dataPoint || !isset($dataPoint['value'])) { continue; } // Convert values to float for proper comparison $currentValue = (float)$dataPoint['value']; $item = [ 'key' => $key->key_name, 'display_name' => $key->display_name, 'value' => $currentValue, 'timestamp' => $dataPoint['ts'] ?? null ]; $alertTriggered = false; foreach ($key->timeseriesAlert as $alert) { // Convert thresholds to float $minValue = $alert->min_value !== null ? (float)$alert->min_value : null; $maxValue = $alert->max_value !== null ? (float)$alert->max_value : null; $isBelowMin = $minValue !== null && $currentValue < $minValue; $isAboveMax = $maxValue !== null && $currentValue > $maxValue; if ($isBelowMin || $isAboveMax) { Log::warning("Alert triggered", [ 'device' => $device->id, 'key' => $key->key_name, 'value' => $currentValue, 'threshold_min' => $minValue, 'threshold_max' => $maxValue, 'condition' => $isBelowMin ? 'below_min' : 'above_max' ]); $item['alert'] = [ 'message' => $alert->alert_msg, 'color_code' => $alert->color_code, 'thresholds' => [ 'min' => $minValue, 'max' => $maxValue ] ]; $result['alerts'][] = $item; $alertTriggered = true; break; } } if (!$alertTriggered) { $result['normal_telemetry'][] = $item; } } return response()->json([ 'success' => true, 'device' => [ 'id' => $device->id, 'name' => $device->name, 'profile' => $device->deviceProfile ], 'data' => $result ]); } catch (\Exception $e) { Log::error("Alert processing failed: {$e->getMessage()}", [ 'device_id' => $request->device_id ?? null, 'trace' => $e->getTraceAsString() ]); return response()->json([ 'success' => false, 'message' => 'Failed to process alerts: ' . $e->getMessage() ], 500); } } }