Poprawa scen instruktażowej oraz z podziekowaniem dodanie canvy XR oraz rozbudowanie tych scen, rozszerzenie skryptu o drugie urzadzenie do tętna
This commit is contained in:
@@ -8,13 +8,21 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
// Klasa dla danych z M5Stick (Têtno + GSR)
|
||||
[Serializable]
|
||||
public class SensorData
|
||||
public class M5StickData
|
||||
{
|
||||
public float hr;
|
||||
public float gsr;
|
||||
}
|
||||
|
||||
// Klasa dla danych z SeeedStudio (Tylko Têtno)
|
||||
[Serializable]
|
||||
public class SeeedData
|
||||
{
|
||||
public float hr;
|
||||
}
|
||||
|
||||
public class ExperimentManager : MonoBehaviour
|
||||
{
|
||||
public static ExperimentManager Instance;
|
||||
@@ -22,20 +30,28 @@ public class ExperimentManager : MonoBehaviour
|
||||
[Header("MQTT Settings")]
|
||||
public string brokerIp = "127.0.0.1";
|
||||
public int port = 1883;
|
||||
public string topic = "m5stick/state";
|
||||
public string topicM5Stick = "m5stick/state";
|
||||
public string topicSeeed = "seeedstudio-mr60bha2/state";
|
||||
|
||||
[Header("Watchdog Settings")]
|
||||
public float timeoutSeconds = 5f; // Czas w sekundach do w³¹czenia alarmu
|
||||
|
||||
private IMqttClient _mqttClient;
|
||||
private string _subjectFolderPath;
|
||||
private string _currentCsvFilePath;
|
||||
|
||||
private ConcurrentQueue<SensorData> _dataQueue = new ConcurrentQueue<SensorData>();
|
||||
// Œcie¿ki do plików CSV
|
||||
private string _m5stickCsvFilePath;
|
||||
private string _seeedCsvFilePath;
|
||||
|
||||
// Zmienne do pilnowania czasu
|
||||
private float _timeSinceLastMessage = 0f;
|
||||
private bool _isDataTimeoutWarningShown = false;
|
||||
// Osobne kolejki dla obu urz¹dzeñ
|
||||
private ConcurrentQueue<M5StickData> _m5stickQueue = new ConcurrentQueue<M5StickData>();
|
||||
private ConcurrentQueue<SeeedData> _seeedQueue = new ConcurrentQueue<SeeedData>();
|
||||
|
||||
// Zmienne do pilnowania czasu (Watchdog) dla obu urz¹dzeñ
|
||||
private float _timeSinceLastM5Stick = 0f;
|
||||
private float _timeSinceLastSeeed = 0f;
|
||||
private bool _isM5StickTimeoutWarningShown = false;
|
||||
private bool _isSeeedTimeoutWarningShown = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
@@ -66,26 +82,40 @@ public class ExperimentManager : MonoBehaviour
|
||||
|
||||
public void SetPhase(string phaseName)
|
||||
{
|
||||
string fileName = $"{phaseName}_Data_{DateTime.Now:yyyyMMdd_HHmmss}.csv";
|
||||
_currentCsvFilePath = Path.Combine(_subjectFolderPath, phaseName, fileName);
|
||||
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
||||
|
||||
if (!File.Exists(_currentCsvFilePath))
|
||||
// Tworzenie nazw plików dla obu urz¹dzeñ
|
||||
string m5stickFileName = $"{phaseName}_M5Stick_Data_{timestamp}.csv";
|
||||
string seeedFileName = $"{phaseName}_Seeed_Data_{timestamp}.csv";
|
||||
|
||||
_m5stickCsvFilePath = Path.Combine(_subjectFolderPath, phaseName, m5stickFileName);
|
||||
_seeedCsvFilePath = Path.Combine(_subjectFolderPath, phaseName, seeedFileName);
|
||||
|
||||
// Nag³ówki dostosowane do danych
|
||||
if (!File.Exists(_m5stickCsvFilePath))
|
||||
{
|
||||
File.WriteAllText(_currentCsvFilePath, "Timestamp;HR;GSR\n");
|
||||
File.WriteAllText(_m5stickCsvFilePath, "Timestamp;HR;GSR\n");
|
||||
}
|
||||
|
||||
Debug.Log($"[ExperimentManager] Now logging to: {_currentCsvFilePath}");
|
||||
if (!File.Exists(_seeedCsvFilePath))
|
||||
{
|
||||
File.WriteAllText(_seeedCsvFilePath, "Timestamp;HR\n");
|
||||
}
|
||||
|
||||
Debug.Log($"[ExperimentManager] Logging M5Stick to: {_m5stickCsvFilePath}");
|
||||
Debug.Log($"[ExperimentManager] Logging Seeed to: {_seeedCsvFilePath}");
|
||||
}
|
||||
|
||||
public string GetCurrentFolderPath()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_currentCsvFilePath)) return null;
|
||||
return Path.GetDirectoryName(_currentCsvFilePath);
|
||||
if (string.IsNullOrEmpty(_m5stickCsvFilePath)) return null;
|
||||
return Path.GetDirectoryName(_m5stickCsvFilePath);
|
||||
}
|
||||
|
||||
public void StopLogging()
|
||||
{
|
||||
_currentCsvFilePath = null;
|
||||
_m5stickCsvFilePath = null;
|
||||
_seeedCsvFilePath = null;
|
||||
Debug.Log("[ExperimentManager] Logging stopped. Data collection finished.");
|
||||
}
|
||||
|
||||
@@ -100,15 +130,25 @@ public class ExperimentManager : MonoBehaviour
|
||||
|
||||
_mqttClient.ApplicationMessageReceivedAsync += e =>
|
||||
{
|
||||
string topic = e.ApplicationMessage.Topic;
|
||||
string payload = Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment);
|
||||
|
||||
try
|
||||
{
|
||||
SensorData data = JsonUtility.FromJson<SensorData>(payload);
|
||||
_dataQueue.Enqueue(data);
|
||||
if (topic == topicM5Stick)
|
||||
{
|
||||
M5StickData data = JsonUtility.FromJson<M5StickData>(payload);
|
||||
_m5stickQueue.Enqueue(data);
|
||||
}
|
||||
else if (topic == topicSeeed)
|
||||
{
|
||||
SeeedData data = JsonUtility.FromJson<SeeedData>(payload);
|
||||
_seeedQueue.Enqueue(data);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[MQTT] Parse error: {ex.Message}");
|
||||
Debug.LogWarning($"[MQTT] Parse error on topic {topic}: {ex.Message}");
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
@@ -116,12 +156,15 @@ public class ExperimentManager : MonoBehaviour
|
||||
try
|
||||
{
|
||||
await _mqttClient.ConnectAsync(options, CancellationToken.None);
|
||||
|
||||
// Subskrypcja obu tematów
|
||||
var subOptions = new MqttClientSubscribeOptionsBuilder()
|
||||
.WithTopicFilter(topic)
|
||||
.WithTopicFilter(f => f.WithTopic(topicM5Stick))
|
||||
.WithTopicFilter(f => f.WithTopic(topicSeeed))
|
||||
.Build();
|
||||
|
||||
await _mqttClient.SubscribeAsync(subOptions, CancellationToken.None);
|
||||
Debug.Log("<color=green>[MQTT] Connected successfully!</color>");
|
||||
Debug.Log("<color=green>[MQTT] Connected successfully and subscribed to M5Stick & Seeed!</color>");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -131,42 +174,75 @@ public class ExperimentManager : MonoBehaviour
|
||||
|
||||
void Update()
|
||||
{
|
||||
bool receivedNewDataThisFrame = false;
|
||||
bool receivedM5StickThisFrame = false;
|
||||
bool receivedSeeedThisFrame = false;
|
||||
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||
|
||||
// Opró¿nianie kolejki i zapis
|
||||
while (_dataQueue.TryDequeue(out SensorData newData))
|
||||
// Opró¿nianie kolejki dla M5Stick
|
||||
while (_m5stickQueue.TryDequeue(out M5StickData m5Data))
|
||||
{
|
||||
receivedNewDataThisFrame = true;
|
||||
receivedM5StickThisFrame = true;
|
||||
|
||||
if (!string.IsNullOrEmpty(_currentCsvFilePath))
|
||||
if (!string.IsNullOrEmpty(_m5stickCsvFilePath))
|
||||
{
|
||||
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||
string csvLine = $"{timestamp};{newData.hr};{newData.gsr}\n";
|
||||
File.AppendAllText(_currentCsvFilePath, csvLine);
|
||||
string csvLine = $"{timestamp};{m5Data.hr};{m5Data.gsr}\n";
|
||||
File.AppendAllText(_m5stickCsvFilePath, csvLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Opró¿nianie kolejki dla SeeedStudio
|
||||
while (_seeedQueue.TryDequeue(out SeeedData seeedData))
|
||||
{
|
||||
receivedSeeedThisFrame = true;
|
||||
|
||||
if (!string.IsNullOrEmpty(_seeedCsvFilePath))
|
||||
{
|
||||
string csvLine = $"{timestamp};{seeedData.hr}\n";
|
||||
File.AppendAllText(_seeedCsvFilePath, csvLine);
|
||||
}
|
||||
}
|
||||
|
||||
// --- SYSTEM WATCHDOG (Pilnowanie transmisji) ---
|
||||
if (receivedNewDataThisFrame)
|
||||
if (_mqttClient != null && _mqttClient.IsConnected)
|
||||
{
|
||||
_timeSinceLastMessage = 0f; // Resetujemy stoper
|
||||
|
||||
if (_isDataTimeoutWarningShown)
|
||||
// Watchdog: M5Stick
|
||||
if (receivedM5StickThisFrame)
|
||||
{
|
||||
// Jeœli wczeœniej wywaliliœmy b³¹d, a teraz dane wróci³y, dajemy znaæ, ¿e ju¿ jest OK
|
||||
Debug.Log("<color=green>[ExperimentManager] Transmisja odzyskana! M5Stick znów nadaje.</color>");
|
||||
_isDataTimeoutWarningShown = false;
|
||||
_timeSinceLastM5Stick = 0f;
|
||||
if (_isM5StickTimeoutWarningShown)
|
||||
{
|
||||
Debug.Log("<color=green>[ExperimentManager] Transmisja odzyskana! M5Stick znów nadaje.</color>");
|
||||
_isM5StickTimeoutWarningShown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_mqttClient != null && _mqttClient.IsConnected)
|
||||
{
|
||||
// Czas leci tylko wtedy, gdy Unity myœli, ¿e MQTT jest po³¹czone
|
||||
_timeSinceLastMessage += Time.deltaTime;
|
||||
|
||||
if (_timeSinceLastMessage >= timeoutSeconds && !_isDataTimeoutWarningShown)
|
||||
else
|
||||
{
|
||||
Debug.LogError($"<color=red><b>[UWAGA MQTT!]</b> Brak danych od {timeoutSeconds} sekund! SprawdŸ M5Stick!</color>");
|
||||
_isDataTimeoutWarningShown = true;
|
||||
_timeSinceLastM5Stick += Time.deltaTime;
|
||||
if (_timeSinceLastM5Stick >= timeoutSeconds && !_isM5StickTimeoutWarningShown)
|
||||
{
|
||||
Debug.LogError($"<color=red><b>[UWAGA MQTT!]</b> Brak danych od M5Stick przez {timeoutSeconds} sek!</color>");
|
||||
_isM5StickTimeoutWarningShown = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Watchdog: SeeedStudio
|
||||
if (receivedSeeedThisFrame)
|
||||
{
|
||||
_timeSinceLastSeeed = 0f;
|
||||
if (_isSeeedTimeoutWarningShown)
|
||||
{
|
||||
Debug.Log("<color=green>[ExperimentManager] Transmisja odzyskana! SeeedStudio znów nadaje.</color>");
|
||||
_isSeeedTimeoutWarningShown = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_timeSinceLastSeeed += Time.deltaTime;
|
||||
if (_timeSinceLastSeeed >= timeoutSeconds && !_isSeeedTimeoutWarningShown)
|
||||
{
|
||||
Debug.LogError($"<color=red><b>[UWAGA MQTT!]</b> Brak danych od SeeedStudio przez {timeoutSeconds} sek!</color>");
|
||||
_isSeeedTimeoutWarningShown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user