0

Whenever I try to attempt to connect in the server using websocket, it throws and error that says: Websocket error: WebsocketChannelException: WebSocketException: Connection to 'http://host:port/v2/ws-tracking?first_query=first_value&second_query=second_value# was not upgraded to websocket'.

The server side uses FastAPI as a backend and the router is configured as a websocket. Additionally, this is running on our GCP VM instance as a docker container so I am not sure if there seems to be a problem with the cloud server we are hosting it in.

This is the code block for our flutter mobile app:

import 'package:flutter/material.dart';
import 'package:lifttrack/cam/preview.dart';
import 'package:video_player/video_player.dart';
import 'package:image_picker/image_picker.dart';
import 'package:ffmpeg_kit_flutter/ffmpeg_kit.dart';
import 'package:ffmpeg_kit_flutter/return_code.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:web_socket_channel/io.dart';
import 'package:flutter_tts/flutter_tts.dart';
import 'dart:io';
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';

import '../services/api_services.dart'; // a module

class VideoPage extends StatefulWidget {
  final String exerciseType;

  const VideoPage({required this.exerciseType, super.key});

  @override
  _VideoPageState createState() => _VideoPageState();
}

class _VideoPageState extends State<VideoPage> {
  VideoPlayerController? _controller;
  File? _videoFile;
  final ImagePicker _picker = ImagePicker();
  IOWebSocketChannel? _channel;
  final List<Map<String, dynamic>> _annotatedFrames = [];
  final FlutterTts _flutterTts = FlutterTts();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _connectWebSocket();
    });
  }

Future<void> _connectWebSocket() async {
    try {
      // Use cached user data if available
      final user = await ApiService().getCurrentUser();
      final username = user.userName;

      // Construct WebSocket URL with username and exercise_name as query parameters
      final uri = Uri(
        scheme: 'ws', // Use 'wss' for secure connections in production
        host: 'x.x.x.x', // Assume the host exist
        port: xxxx, // Assume is a valid port
        path: '/v2/ws-tracking', // ws endpoint from the FastAPI backend
        queryParameters: {
          'username': username,
          'exercise_name': widget.exerciseType,
        },
      );

      final wsUrl = uri.toString();
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Connecting to WebSocket...')),
      );

      _channel = IOWebSocketChannel.connect(wsUrl);

      _channel?.stream.listen((dynamic data) async {
        if (data != null) {
          try {
            if (data is String) {
              final decodedData = jsonDecode(data);
              if (decodedData is Map && decodedData['type'] == 'analysis') {
                final accuracy = decodedData['accuracy'];
                final suggestions = decodedData['suggestions'];
                final predictedClass = decodedData['predicted_class'];
                
                // Enhanced TTS feedback
                await _speakAnalysisFeedback(accuracy, suggestions, predictedClass);
                
                // Additional TTS for immediate feedback
                await _flutterTts.speak("Starting analysis. Please wait...");
              }
            } else if (data is Uint8List) {
              // Handle binary frame data
              setState(() {
                _annotatedFrames.add({
                  'timestamp': DateTime.now().millisecondsSinceEpoch,
                  'image': data,
                });
              });
            }
          } catch (e) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text('Error processing received data: $e')),
            );
          }
        }
      }, onError: (error) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('WebSocket error: $error')),
        );
      }, onDone: () {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('WebSocket connection closed by server')),
        );
      });
    } catch (error) {
      if (error is UnauthorizedException) {
        showDialog(
          context: context,
          barrierDismissible: false,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('Session Expired'),
              content: Text('Session expired. Please log in again.'),
              actions: [
                TextButton(
                  onPressed: () {
                    Navigator.of(context).pop();
                    Navigator.of(context).pushNamedAndRemoveUntil(
                      '/login',
                      (route) => false,
                    );
                  },
                  child: Text('OK'),
                ),
              ],
            );
          },
        );
        return;
      }
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('WebSocket connection failed: $error')),
      );
    }
  }
}

Currently, I tried to force the connection by adding a header to upgrade the protocol. But hoping to find a permanent solution to this problem. Badly need this project to be finished because this is our thesis.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.