alarmService = $alarmService; } public function createOrUpdateAlarm(Request $request) { try { $alarmData = [ 'type' => $request->type ?? null, 'severity' => $request->severity ?? null, 'acknowledged' => false ?? null, 'cleared' => $request->cleared ?? Carbon::now()->timestamp, 'startTs' => $request->startTs ?? Carbon::now()->timestamp, 'endTs' => $request->endTs ?? Carbon::now()->timestamp, 'details' => $request->details ?? [], 'propagate' => $request->propagate ?? false, 'propagateToOwner' => $request->propagateToOwner ?? false, 'propagateToTenant' => $request->propagateToTenant ?? false, 'originator' => $request->originator ?? 1, 'assigneeId' => $request->assigneeId ?? 1, ]; // Handle updating existing alarm if (!empty($request->id)) { $alarmData['id'] = $request->id; } // Call Service to create/update device $apiResponse = $this->alarmService->createOrUpdateAlarm($alarmData); return jsonResponseWithSuccessMessage( !empty($request->id) ? 'Alarm updated successfully' : 'Alarm created successfully', ['api_response' => $apiResponse] ); } catch (Exception $e) { Log::error("Error: " . $e->getMessage()); $errorResponse = json_decode($e->getMessage(), true); if (json_last_error() === JSON_ERROR_NONE) { return jsonResponseWithErrorMessage($errorResponse['message'] ?? 'Something went wrong', 400, $errorResponse); } return jsonResponseWithErrorMessage($e->getMessage(), 500); } } public function getAlarmById($id) { try { $token = app('App\Services\AdminService')->getToken(); // Fetch cached token $url = env('THINGSBOARD_URL') . "/api/alarm/{$id}"; $response = Http::withHeaders([ 'X-Authorization' => 'Bearer ' . $token, 'accept' => 'application/json', ])->get($url); if ($response->successful()) { $responseData = $response->json(); $data = $responseData['data'] ?? $responseData ?? []; if (empty($data)) { return jsonResponseWithErrorMessage('No data found for the provided ID', 404); } $filteredData = [ 'originator' => $data['originator'] ?? null, 'severity' => $data['severity'] ?? null, 'startTs' => $data['startTs'] ?? null, 'type' => $data['type'] ?? null, 'status' => $data['status'] ?? null, 'assignee' => $data['assigneeId'] ?? null, ]; return jsonResponseWithSuccessMessage('Alarm data fetched successfully', $filteredData); } return jsonResponseWithErrorMessage('Failed to fetch alarm data: ' . $response->body(), $response->status()); } catch (\Exception $e) { return jsonResponseWithErrorMessage('An error occurred while fetching the alarm: ' . $e->getMessage(), 500); } } public function acknowledgeAlarmById($id) { try { $token = app('App\Services\AdminService')->getToken(); // Fetch cached token0 $url = env('THINGSBOARD_URL') . "/api/alarm/{$id}"; $getResponse = Http::withHeaders([ 'X-Authorization' => 'Bearer ' . $token, 'accept' => 'application/json', ])->get($url); if (!$getResponse->successful()) { return jsonResponseWithErrorMessage('Failed to fetch alarm: ' . $getResponse->body(), $getResponse->status()); } $alarmData = $getResponse->json(); if ($alarmData['acknowledged'] ?? false) { return jsonResponseWithSuccessMessage('Alarm is already acknowledged', [ 'id' => $alarmData['id']['id'] ?? $id, 'acknowledged' => true, 'ackTs' => $alarmData['ackTs'] ?? null, 'status' => $alarmData['status'] ?? 'UNKNOWN' ]); } $ackUrl = env('THINGSBOARD_URL') . "/api/alarm/{$id}/ack"; $ackResponse = Http::withHeaders([ 'X-Authorization' => 'Bearer ' . $token, 'accept' => 'application/json', ])->post($ackUrl); if ($ackResponse->successful()) { $ackData = $ackResponse->json(); return jsonResponseWithSuccessMessage('Alarm acknowledged successfully', [ 'id' => $ackData['id']['id'] ?? $id, 'acknowledged' => $ackData['acknowledged'] ?? true, 'ackTs' => $ackData['ackTs'] ?? now()->timestamp, 'status' => $ackData['status'] ?? 'ACTIVE_ACK' ]); } return jsonResponseWithErrorMessage('Failed to acknowledge alarm: ' . $ackResponse->body(), $ackResponse->status()); } catch (\Exception $e) { return jsonResponseWithErrorMessage('An error occurred: ' . $e->getMessage(), 500); } } public function clearAlarmById($id) { try { $token = app(AdminService::class)->getToken(); // Fetch cached token $url = env('THINGSBOARD_URL') . "/api/alarm/{$id}"; // Fetch the alarm details first $getResponse = Http::withHeaders([ 'X-Authorization' => 'Bearer ' . $token, 'accept' => 'application/json', ])->get($url); if (!$getResponse->successful()) { return jsonResponseWithErrorMessage('Failed to fetch alarm: ' . $getResponse->body(), $getResponse->status()); } $alarmData = $getResponse->json(); if ($alarmData['cleared'] ?? false) { return jsonResponseWithSuccessMessage('Alarm is already cleared', [ 'id' => $alarmData['id']['id'] ?? $id, 'cleared' => true, 'clearTs' => $alarmData['clearTs'] ?? null, 'status' => $alarmData['status'] ?? 'UNKNOWN' ]); } // Clear the alarm $clearUrl = env('THINGSBOARD_URL') . "/api/alarm/{$id}/clear"; $clearResponse = Http::withHeaders([ 'X-Authorization' => 'Bearer ' . $token, 'accept' => 'application/json', ])->post($clearUrl); if ($clearResponse->successful()) { $clearData = $clearResponse->json(); return jsonResponseWithSuccessMessage('Alarm cleared successfully', [ 'id' => $clearData['id']['id'] ?? $id, 'cleared' => $clearData['cleared'] ?? true, 'clearTs' => $clearData['clearTs'] ?? now()->timestamp, 'status' => $clearData['status'] ?? 'CLEARED' ]); } return jsonResponseWithErrorMessage('Failed to clear alarm: ' . $clearResponse->body(), $clearResponse->status()); } catch (\Exception $e) { Log::error('Error clearing alarm: ' . $e->getMessage()); return jsonResponseWithErrorMessage('An error occurred: ' . $e->getMessage(), 500); } } public function filterAlarm(Request $request) { try { $token = readHeaderToken(); $useId = $token['sub']; $alarmData = $request->only([ 'severity', 'pageSize', 'page', 'startTs', 'endTs', 'deviceId', 'assetId' ]); $apiResponse = $this->alarmService->filterAlarm($alarmData, $useId); return jsonResponseWithSuccessMessage('Alarm data retrieved successfully', ['api_response' => $apiResponse]); } catch (Exception $e) { Log::error("Error: " . $e->getMessage()); $errorResponse = json_decode($e->getMessage(), true); if (json_last_error() === JSON_ERROR_NONE) { return jsonResponseWithErrorMessage($errorResponse['message'] ?? 'Something went wrong', 400, $errorResponse); } return jsonResponseWithErrorMessage($e->getMessage(), 500); } } public function getDeviceAlarms(Request $request) { $validator = Validator::make($request->all(), [ 'device_id' => 'required|string', 'pageSize' => 'nullable|integer', 'page' => 'nullable|integer', ]); // Handle validation failure if ($validator->fails()) { return response()->json(['error' => $validator->errors()->first()], 400); } // Get the device ID from the request $deviceId = $request->input('device_id'); $pageSize = $request->input('pageSize', 1000); $page = $request->input('page', 0); // Fetch ThingsBoard token $token = $this->alarmService->getToken(); if (!$token) { return response()->json(['error' => 'Failed to fetch ThingsBoard token'], 401); } $baseUrl = env('THINGSBOARD_URL'); // Get timestamps for the past 24 hours $endTime = now()->timestamp * 1000; // Current time in ms $startTime = now()->subHours(24)->timestamp * 1000; // 24 hours ago in ms // Fetch alarms from ThingsBoard API $response = Http::withHeaders([ 'Authorization' => "Bearer $token", 'Accept' => 'application/json', ])->get("$baseUrl/api/v2/alarms", [ 'statusList' => 'ACTIVE', 'severityList' => 'CRITICAL,MAJOR,MINOR,WARNING', 'pageSize' => $pageSize, 'page' => $page, 'startTime' => $startTime, 'endTime' => $endTime, 'sortProperty' => 'createdTime', 'sortOrder' => 'DESC' ]); // If the request fails, return an error if (!$response->successful()) { return response()->json(['error' => 'Failed to fetch alarms'], $response->status()); } $alarms = $response->json()['data'] ?? []; // Get the token from the Authorization header $token = $request->header('Authorization'); if ($token) { $token = str_replace('Bearer ', '', $token); // Decode the token try { $user = JWTAuth::toUser($token); } catch (\Exception $e) { return response()->json(['error' => 'Invalid token'], 401); } if (!$user) { return response()->json(['error' => 'User not found in the token'], 401); } // Retrieve the customer_id from the decoded user $customerId = $user->customer_id; } else { return response()->json(['error' => 'Token not provided'], 400); } // Alert initialization $alert = false; // Retrieve the device data to check if it belongs to the logged-in user's customer_id $device = Device::find($deviceId); if (!$device) { return response()->json(['error' => 'Device not found'], 404); } // Check if the device's customer_id matches the logged-in user's customer_id if ($device->customer_id !== $customerId) { return response()->json(['error' => 'Device does not belong to the logged-in user\'s customer'], 403); } // Get device display name $deviceDisplayName = $device->display_name; // Iterate through the alarms to check if any match the criteria foreach ($alarms as $alarm) { // Match the device ID with the alarm's originator $isDeviceMatch = isset($alarm['originator']['id']) && $alarm['originator']['id'] === $deviceId; // Match the assignee user ID with the logged-in user $isUserMatch = isset($alarm['assignee']['id']['id']) && $alarm['assignee']['id']['id'] === $user->id; // Match the alarm type with the device's display name $isTypeMatch = isset($alarm['type']) && $alarm['type'] === $deviceDisplayName; // Check if the device, user, and alarm type conditions are met if ($isDeviceMatch && $isUserMatch && $isTypeMatch) { $alert = true; break; } } return response()->json([ 'alert' => $alert, 'alarms' => $alarms, 'message' => $alert ? 'Alarm conditions met!' : 'No matching alarms found.' ]); } }