Dispenser re-initialization after errors #29

Closed
opened 2026-06-13 22:02:52 +00:00 by padreug · 0 comments
Owner

Migrated from aiolabs/lamassu-next#29 — opened by @padreug on 2026-02-23.\n\n## Problem

After a dispense error, PuloonDispenser.close() is called which sets initialized = false and closes the serial port. But nothing ever re-initializes the dispenser. The next dispense attempt will fail because the serial port is closed.

In brain.js (lib/brain.js:4072-4087), the catch handler checks !this.billDispenser.initialized and re-initializes after a 200ms delay:

if (!this.billDispenser.initialized) {
  setTimeout(() => {
    return this.billDispenser.init({
      cassettes, fiatCode, recyclers, ...
    })
  }, 200)
}

Current behavior

  1. Dispense error → this.close() → initialized = false, serial port closed
  2. Next dispense attempt → dispenser.dispense() on closed port → crash or silent failure

Required behavior

After a dispense error, the dispenser must be re-initialized before the next attempt. Options:

Option A (lazy re-init): Check initialized before each dispenseCash() call in hal.ts. If not initialized, re-init with the stored config.

Option B (eager re-init): Re-initialize immediately after error with a delay (matching brain.js pattern).

Option A is simpler and matches how brain.js works (the re-init happens at the next dispense, not immediately).

Implementation

In hal.ts:dispenseCash(), before calling dispenser.dispense():

if (!dispenser.initialized) {
  await dispenser.init({ fiatCode, cassettes })
}

This requires PuloonDispenser.init() to allow re-initialization (reset initializing flag after close()).

Impact

Blocker for hardware testing. A single dispense error permanently disables cash-out until app restart.

> _Migrated from [aiolabs/lamassu-next#29](https://git.atitlan.io/aiolabs/lamassu-next/issues/29) — opened by @padreug on 2026-02-23._\n\n## Problem After a dispense error, `PuloonDispenser.close()` is called which sets `initialized = false` and closes the serial port. But nothing ever re-initializes the dispenser. The next dispense attempt will fail because the serial port is closed. In brain.js (`lib/brain.js:4072-4087`), the catch handler checks `!this.billDispenser.initialized` and re-initializes after a 200ms delay: ```js if (!this.billDispenser.initialized) { setTimeout(() => { return this.billDispenser.init({ cassettes, fiatCode, recyclers, ... }) }, 200) } ``` ## Current behavior 1. Dispense error → `this.close()` → `initialized = false`, serial port closed 2. Next dispense attempt → `dispenser.dispense()` on closed port → crash or silent failure ## Required behavior After a dispense error, the dispenser must be re-initialized before the next attempt. Options: **Option A (lazy re-init):** Check `initialized` before each `dispenseCash()` call in `hal.ts`. If not initialized, re-init with the stored config. **Option B (eager re-init):** Re-initialize immediately after error with a delay (matching brain.js pattern). Option A is simpler and matches how brain.js works (the re-init happens at the _next_ dispense, not immediately). ## Implementation In `hal.ts:dispenseCash()`, before calling `dispenser.dispense()`: ```typescript if (!dispenser.initialized) { await dispenser.init({ fiatCode, cassettes }) } ``` This requires `PuloonDispenser.init()` to allow re-initialization (reset `initializing` flag after `close()`). ## Impact **Blocker for hardware testing.** A single dispense error permanently disables cash-out until app restart.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/bitspire#29
No description provided.