Compare commits
2 commits
f52d942e57
...
996ed7ec67
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
996ed7ec67 | ||
|
|
332497500c |
4 changed files with 11 additions and 58 deletions
|
|
@ -221,15 +221,6 @@ export async function initializeHal(config: HalConfig): Promise<HalInstance> {
|
||||||
},
|
},
|
||||||
|
|
||||||
disableValidator: () => {
|
disableValidator: () => {
|
||||||
// If a note is sitting in escrow when we disable (inactivity timeout,
|
|
||||||
// cancel, or leaving the insert screen), return it to the customer.
|
|
||||||
// Disabling alone does NOT release an escrowed note on EBDS — it would
|
|
||||||
// be stranded in the transport until the next power cycle.
|
|
||||||
if (escrowDenomination !== null) {
|
|
||||||
console.log('[HAL] Returning escrowed bill on disable:', escrowDenomination)
|
|
||||||
escrowDenomination = null
|
|
||||||
validator?.reject()
|
|
||||||
}
|
|
||||||
validator?.disable()
|
validator?.disable()
|
||||||
validator?.lightOff()
|
validator?.lightOff()
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -139,21 +139,11 @@ export const MACHINE_PRESETS: Record<MachineModel, Omit<DeviceConfig, 'fiatCode'
|
||||||
model: 'batm3',
|
model: 'batm3',
|
||||||
validator: {
|
validator: {
|
||||||
type: 'ebds',
|
type: 'ebds',
|
||||||
// MEI bill acceptor (EBDS) on a USB-serial bridge, exposed via the
|
device: '/dev/ttyACM0',
|
||||||
// stable udev symlink /dev/ttyMEI (batm3.nix, serial A9YW78OC). The old
|
|
||||||
// /dev/ttyACM0 default assumed a CDC-ACM BNR; this hardware enumerates as
|
|
||||||
// ttyUSB* instead, so ACM0 never existed and cash-in was silently
|
|
||||||
// disabled ("[HAL] No validator"). Per-box override: VITE_LAMASSU_VALIDATOR_DEVICE.
|
|
||||||
device: '/dev/ttyMEI',
|
|
||||||
},
|
},
|
||||||
dispenser: {
|
dispenser: {
|
||||||
type: 'f56',
|
type: 'f56',
|
||||||
// Fujitsu F56 on a USB-serial bridge, via the stable udev symlink
|
device: '/dev/ttyUSB0',
|
||||||
// /dev/ttyF56 (batm3.nix, serial DDDLb103Y23). Avoids the raw
|
|
||||||
// /dev/ttyUSB0, which is enumeration-order dependent and could point at
|
|
||||||
// the wrong adapter after a re-plug/reboot. Per-box override:
|
|
||||||
// VITE_LAMASSU_DISPENSER_DEVICE.
|
|
||||||
device: '/dev/ttyF56',
|
|
||||||
cassettes: [
|
cassettes: [
|
||||||
{ denomination: 20, count: 400 },
|
{ denomination: 20, count: 400 },
|
||||||
{ denomination: 1, count: 400 },
|
{ denomination: 1, count: 400 },
|
||||||
|
|
|
||||||
|
|
@ -458,7 +458,7 @@ export const useAtmStore = defineStore('atm', () => {
|
||||||
actor.value.subscribe((newSnapshot: SnapshotFrom<ATMMachine>) => {
|
actor.value.subscribe((newSnapshot: SnapshotFrom<ATMMachine>) => {
|
||||||
const prevSnapshot = snapshot.value
|
const prevSnapshot = snapshot.value
|
||||||
snapshot.value = newSnapshot
|
snapshot.value = newSnapshot
|
||||||
console.log('[ATM] State:', JSON.stringify(newSnapshot.value))
|
console.log('[ATM] State:', newSnapshot.value)
|
||||||
|
|
||||||
// Detect transition into a complete state
|
// Detect transition into a complete state
|
||||||
const state = newSnapshot.value
|
const state = newSnapshot.value
|
||||||
|
|
@ -1374,7 +1374,7 @@ export const useAtmStore = defineStore('atm', () => {
|
||||||
console.error('[ATM] Cannot send event: machine not initialized')
|
console.error('[ATM] Cannot send event: machine not initialized')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log('[ATM] Sending event:', event.type, JSON.stringify(event))
|
console.log('[ATM] Sending event:', event)
|
||||||
actor.value.send(event)
|
actor.value.send(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -313,13 +313,6 @@ export class EbdsRs232 extends EventEmitter {
|
||||||
private serial: SerialPort | null = null
|
private serial: SerialPort | null = null
|
||||||
private ack: number = 0x0
|
private ack: number = 0x0
|
||||||
private enabledDenominations: number = 0x00
|
private enabledDenominations: number = 0x00
|
||||||
// Latched escrow decision. In EBDS the stack/return choice is NOT a one-shot
|
|
||||||
// message — it's carried as bits in the omnibus poll command, and the device
|
|
||||||
// holds the escrowed note until a poll asserts stack or return. We keep the
|
|
||||||
// action set and re-assert it on every poll until the device leaves escrow
|
|
||||||
// (cleared in _process), so a single dropped/collided frame no longer strands
|
|
||||||
// the note in escrow forever.
|
|
||||||
private pendingAction: 'none' | 'stack' | 'return' = 'none'
|
|
||||||
private lastStatusFlags: string | null = null
|
private lastStatusFlags: string | null = null
|
||||||
private firmwareLogged: boolean = false
|
private firmwareLogged: boolean = false
|
||||||
|
|
||||||
|
|
@ -412,38 +405,23 @@ export class EbdsRs232 extends EventEmitter {
|
||||||
|
|
||||||
// -- Commands (Appendix D, Controller Message) ---------------------------
|
// -- Commands (Appendix D, Controller Message) ---------------------------
|
||||||
|
|
||||||
/**
|
/** Send an Omnibus poll command with current denomination mask */
|
||||||
* Command byte 1 for the omnibus poll, encoding any latched escrow action.
|
|
||||||
* `stack` (0x3f) and `return` (0x5f) differ from the plain poll (0x1b) only
|
|
||||||
* in the stack/return bits; while an action is latched every poll re-asserts
|
|
||||||
* it until the device acts.
|
|
||||||
*/
|
|
||||||
private commandByte(): number {
|
|
||||||
if (this.pendingAction === 'stack') return 0x3f
|
|
||||||
if (this.pendingAction === 'return') return 0x5f
|
|
||||||
return 0x1b
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Send an Omnibus poll command with the current mask + latched action */
|
|
||||||
poll(): void {
|
poll(): void {
|
||||||
this._dispatch([this.enabledDenominations, this.commandByte(), 0x10])
|
this._dispatch([this.enabledDenominations, 0x1b, 0x10])
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Latch "stack the escrowed note"; re-asserted each poll until it takes. */
|
/** Stack the bill currently in escrow */
|
||||||
stack(): void {
|
stack(): void {
|
||||||
this.pendingAction = 'stack'
|
this._dispatch([this.enabledDenominations, 0x3f, 0x10])
|
||||||
this.poll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Latch "return the escrowed note"; re-asserted each poll until it takes. */
|
/** Reject/return the bill currently in escrow */
|
||||||
reject(): void {
|
reject(): void {
|
||||||
this.pendingAction = 'return'
|
this._dispatch([this.enabledDenominations, 0x5f, 0x10])
|
||||||
this.poll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Send initial setup command (disable all, reset state) */
|
/** Send initial setup command (disable all, reset state) */
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this.pendingAction = 'none'
|
|
||||||
this._dispatch([0x00, 0x1b, 0x10])
|
this._dispatch([0x00, 0x1b, 0x10])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -492,13 +470,7 @@ export class EbdsRs232 extends EventEmitter {
|
||||||
validatePacket(packet)
|
validatePacket(packet)
|
||||||
const result = interpret(packet)
|
const result = interpret(packet)
|
||||||
if (result) {
|
if (result) {
|
||||||
if (result.destructedData) {
|
if (result.destructedData) this._logStatusOnChange(result.destructedData)
|
||||||
// Clear a latched stack/return once the device has left escrow — it
|
|
||||||
// is now stacking/returning/idle, so we must stop asserting the
|
|
||||||
// action or it would leak onto the next note.
|
|
||||||
if (!result.destructedData[0].escrowed) this.pendingAction = 'none'
|
|
||||||
this._logStatusOnChange(result.destructedData)
|
|
||||||
}
|
|
||||||
this.emit('message', result)
|
this.emit('message', result)
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue