Added UDP control functionality to TaskTimer, allowing timer commands via UDP. Updated README to include new timer commands: START, PAUSE, RESUME, and RESET.
This commit is contained in:
@ -85,6 +85,13 @@ switch_scene("VR-Task1")
|
||||
- `AR-Task1`, `AR-Task2`, `AR-Task3`, `AR-Task4`
|
||||
- `Lobby`
|
||||
|
||||
**Timer Commands:**
|
||||
|
||||
- TIMER:START - Start the timer
|
||||
- TIMER:PAUSE - Pause the timer
|
||||
- TIMER:RESUME - Resume the timer
|
||||
- TIMER:RESET - Reset the timer to initial duration
|
||||
|
||||
---
|
||||
|
||||
### Chat Application (`Chat-App/`)
|
||||
|
||||
@ -2,6 +2,10 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
using TMPro;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
public class TaskTimer : MonoBehaviour
|
||||
{
|
||||
@ -15,6 +19,12 @@ public class TaskTimer : MonoBehaviour
|
||||
[Tooltip("Show warning when time is low (in seconds)")]
|
||||
public float warningThreshold = 30f;
|
||||
|
||||
[Header("UDP Control Settings")]
|
||||
[SerializeField] private int udpPort = 5555;
|
||||
[SerializeField] private bool enableUDPControl = true;
|
||||
[Tooltip("If enabled, timer will only start via UDP command (ignores autoStart)")]
|
||||
[SerializeField] private bool waitForUDPStart = false;
|
||||
|
||||
[Header("UI References")]
|
||||
[Tooltip("TextMeshPro component to display timer (recommended for VR)")]
|
||||
public TextMeshProUGUI timerTextTMP;
|
||||
@ -35,11 +45,24 @@ public class TaskTimer : MonoBehaviour
|
||||
private float timeRemaining;
|
||||
private bool isRunning;
|
||||
|
||||
// UDP infrastructure
|
||||
private UdpClient udpClient;
|
||||
private Thread udpListenerThread;
|
||||
private bool isListening = false;
|
||||
private string pendingCommand = null;
|
||||
private readonly object commandLock = new object();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
timeRemaining = taskDuration;
|
||||
|
||||
if (autoStart)
|
||||
if (enableUDPControl)
|
||||
{
|
||||
StartUDPListener();
|
||||
}
|
||||
|
||||
// Only auto-start if not waiting for UDP command
|
||||
if (autoStart && !waitForUDPStart)
|
||||
{
|
||||
StartTimer();
|
||||
}
|
||||
@ -49,6 +72,16 @@ public class TaskTimer : MonoBehaviour
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Check for pending UDP commands (must be done on main thread)
|
||||
lock (commandLock)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(pendingCommand))
|
||||
{
|
||||
ProcessTimerCommand(pendingCommand);
|
||||
pendingCommand = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRunning)
|
||||
return;
|
||||
|
||||
@ -155,5 +188,120 @@ public class TaskTimer : MonoBehaviour
|
||||
{
|
||||
return 1f - (timeRemaining / taskDuration);
|
||||
}
|
||||
|
||||
// UDP Control Methods
|
||||
private void StartUDPListener()
|
||||
{
|
||||
try
|
||||
{
|
||||
isListening = true;
|
||||
udpClient = new UdpClient(udpPort);
|
||||
udpListenerThread = new Thread(new ThreadStart(ListenForUDPCommands));
|
||||
udpListenerThread.IsBackground = true;
|
||||
udpListenerThread.Start();
|
||||
Debug.Log($"TaskTimer: UDP Listener started on port {udpPort}");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"TaskTimer: Failed to start UDP listener: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ListenForUDPCommands()
|
||||
{
|
||||
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, udpPort);
|
||||
|
||||
while (isListening)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] data = udpClient.Receive(ref remoteEndPoint);
|
||||
string message = Encoding.UTF8.GetString(data);
|
||||
ProcessUDPCommand(message);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
if (isListening)
|
||||
{
|
||||
Debug.LogError($"TaskTimer: UDP receive error: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessUDPCommand(string message)
|
||||
{
|
||||
Debug.Log($"TaskTimer: Received UDP command: {message}");
|
||||
|
||||
if (string.IsNullOrEmpty(message))
|
||||
return;
|
||||
|
||||
// Parse command format: TIMER:COMMAND (e.g., TIMER:START, TIMER:PAUSE, TIMER:RESET, TIMER:RESUME)
|
||||
string[] parts = message.Split(':');
|
||||
if (parts.Length == 2 && parts[0].Trim().ToUpper() == "TIMER")
|
||||
{
|
||||
string command = parts[1].Trim().ToUpper();
|
||||
lock (commandLock)
|
||||
{
|
||||
pendingCommand = command;
|
||||
}
|
||||
Debug.Log($"TaskTimer: Scheduled command: {command}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"TaskTimer: Invalid UDP command format: {message}. Expected format: TIMER:COMMAND (e.g., TIMER:START)");
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessTimerCommand(string command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case "START":
|
||||
StartTimer();
|
||||
break;
|
||||
case "PAUSE":
|
||||
PauseTimer();
|
||||
break;
|
||||
case "RESUME":
|
||||
ResumeTimer();
|
||||
break;
|
||||
case "RESET":
|
||||
ResetTimer();
|
||||
break;
|
||||
default:
|
||||
Debug.LogWarning($"TaskTimer: Unknown command: {command}. Valid commands: START, PAUSE, RESUME, RESET");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
StopUDPListener();
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
StopUDPListener();
|
||||
}
|
||||
|
||||
private void StopUDPListener()
|
||||
{
|
||||
isListening = false;
|
||||
|
||||
if (udpClient != null)
|
||||
{
|
||||
udpClient.Close();
|
||||
udpClient = null;
|
||||
}
|
||||
|
||||
if (udpListenerThread != null && udpListenerThread.IsAlive)
|
||||
{
|
||||
udpListenerThread.Abort();
|
||||
udpListenerThread = null;
|
||||
}
|
||||
|
||||
Debug.Log("TaskTimer: UDP Listener stopped");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user