OK, so I was able to find the issue. I will post it because it may help someone in the future.
The logic with the intervals was just fine. The problem was with the interaction of the Bluetooth hook and this useEffect. In the question, I just put the part of the code that handles the timers, but this was inside a useEffect triggered by the change in step (the app has multiple steps where you have to trigger nodes, which are PCBs that send messages via BLE/MESH).
So... at the beginning of the useEffect I was setting the triggeredDevice to null so that if it was the same as the previous step, it would force the app to interpret it as changed, hence triggering its useEffect (not this one, another).
useEffect(() => {
if (currentStep <= selectedSteps) {
const selectedArray = Array.from(selectedDevices);
const masterDevice = selectedArray[0];
setTriggeredDevice(null); // <--- This I had to comment out
const randomIndex = Math.floor(Math.random() * selectedArray.length);
const selectedCorrectDevice = selectedArray[randomIndex];
This was "colliding" with the setting of that state within the read characteristic function in the BLE hook:
const startListeningToCharacteristic = async (device: Device, characteristicUUID: string) => {
if (device) {
try {
if (isDeviceConnected(device.id)) {
const subscription = device.monitorCharacteristicForService(
TERMINAL_UUID_SERVICE,
characteristicUUID,
(error, characteristic) => {
if (characteristic?.value) {
const decodedData = base64.decode(characteristic.value);
console.log(`Received data: ${decodedData}`);
try {
const parsedData = JSON.parse(decodedData);
const deviceId = parsedData.node;
setTriggeredDevice(""); // This I added to force the trigger
setTriggeredDevice(deviceId);
} catch (parseError) {
console.error("Error parsing JSON data:", parseError);
}
} else {
console.log("No Data received");
}
}
);
characteristicSubscriptions.current[device.id] = subscription;
} else {
console.log(`Device ${device.id} is not connected.`);
listConnectedDevices();
}
} catch (error) {
console.error("Error during monitoring setup:", error);
}
} else {
console.log("No Device Connected");
}
};
So I added that empty string setting before the deviceId setting to force it, and the setInterval ran perfectly. I don't fully understand why there was an issue with this, but I think it might have been some kind of race condition or something like that.