Difficulty triggering mbl_mw_timer_start after successful comparator condition

edited March 2021 in iOS

Model: MetaMotion R
Firmware: 1.5.1

Hello, I hope this does not count as a "how do I code"-type question, but I have this piece of code that I believe should function, but does not.

The idea is, a single press of the MetaWear button should cancel a repetitive vibration, and begin a 5-minute countdown (snoozeTimer) to another event (flashing the LED 3 times, green). For some reason, I cannot get the snoozeList.forEach { $0.value } inside the comparator to actually trigger another timer to begin.

func clickListener() {           
        //dictionaries for activating or removing the actual alarm vibration
        var alarmList: [OpaquePointer: () -> Void] = [:]
        var alarmCleanup: [OpaquePointer: () -> Void] = [:]

        //dictionaries for activating or removing the snooze alarm
        var snoozeList: [OpaquePointer: () -> Void] = [:]
        var snoozeCleanup: [OpaquePointer: () -> Void] = [:]

        //clickListener itself
        var clickEvent = mbl_mw_switch_get_state_data_signal(self.device.board)
        clickEvent?.counterCreateCount().continueOnSuccessWith { count -> OpaquePointer in
            mbl_mw_event_record_commands(count)
            //if one click
            count.comparatorCreate(op: MBL_MW_COMPARATOR_OP_EQ, mode: MBL_MW_COMPARATOR_MODE_ABSOLUTE, references: [Float(2)]).continueOnSuccessWith { comp in
                mbl_mw_event_record_commands(comp)
                self.device.flashLED(color: .blue, intensity: 1.0, _repeat: 1)
                //turn off first vibration
                alarmCleanup.forEach { $0.value() }

                //turn on snooze alarm
                snoozeList.forEach { $0.value() }
                comp.eventEndRecord()
            }

            return count
        }.continueOnSuccessWithTask() { count in
            //this timer resets click counter every 2 seconds
            self.device.timerCreate(period: 2000).continueOnSuccessWith { repetitive in
                clickListenerList[repetitive] = {
                    mbl_mw_timer_start(repetitive)
                }
                clickListenerCleanup[repetitive] = {
                    mbl_mw_timer_stop(repetitive)
                }
                mbl_mw_event_record_commands(repetitive)
                //below is a useful debugging tool to give you a physical indication of when the clickCounter is reset
                //mbl_mw_haptic_start_buzzer(self.device.board, 250)
                mbl_mw_dataprocessor_counter_set_state(count, UInt32(0))
                repetitive.eventEndRecord()
            }.continueOnSuccessWith() {
                clickListenerList.forEach { $0.value() }
            }
        }

        device.timerCreate(period: 1200).continueOnSuccessWith { repetitive in
            alarmList[repetitive] = {
                mbl_mw_timer_start(repetitive)
            }
            alarmCleanup[repetitive] = {
                mbl_mw_timer_stop(repetitive)
            }
            mbl_mw_event_record_commands(repetitive)
            print("recording commands")
            mbl_mw_haptic_start_buzzer(self.device.board, 250)
            repetitive.eventEndRecord().continueOnSuccessWith {
                print("repetitive timer set")
            }
        }.continueOnSuccessWith {
            print("starting timer")
            //actually triggers event
            alarmList.forEach { $0.value() }
        }

        //this is the snooze alarm
        device.timerCreate(period: snoozeTime*1000, repetitions: 1, immediateFire: false).continueOnSuccessWith { snoozeTimer in
            snoozeList[snoozeTimer] = {
                mbl_mw_timer_start(snoozeTimer)
            }
            snoozeCleanup[snoozeTimer] = {
                mbl_mw_timer_stop(snoozeTimer)
            }
            mbl_mw_event_record_commands(snoozeTimer)
            //debug indication LED below
            self.device.flashLED(color: .green, intensity: 1.0, _repeat: 3)
            snoozeTimer.eventEndRecord().continueOnSuccessWith {
                print("snooze timer set")
            }
        }
}

Update: After forcing commands sequentially with .continueOnSuccessWith(Executor.mainThread), I get a BAD_ACCESS error - it looks like the MetaWear can only store/reference two timers at once. I might be wrong here, still very new to working with this API.

Update 2: I was able to get past this hurdle by setting:
self.snoozeID = mbl_mw_timer_get_id(snoozeTimer)

Then, when calling timer, using:
mbl_mw_timer_start(mbl_mw_timer_lookup_id(self.device.board, self.snoozeID))

My idea is the pointer to any timer becomes invalid if there are too many timers. Referencing a timer by ID seems to access the timer without needing to retain a pointer that may or may not change on-device. However, this fix produces variable, error-prone behaviour.

Sign In or Register to comment.