feat(hal): add Puloon bill dispenser driver for Douro ATM

Port the Puloon RS232 dispenser protocol from lamassu-machine to
the lamassu-next HAL package. Adds Douro machine preset with Puloon
dispenser on /dev/ttyS1 and ID003 validator on /dev/ttyS0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-22 20:01:26 -05:00
commit 350e7a8974
7 changed files with 556 additions and 8 deletions

View file

@ -15,7 +15,7 @@ import type { HalConfig, CassetteConfig } from '@/services/hal'
/**
* Supported machine models
*/
export type MachineModel = 'sintra' | 'gaia' | 'custom'
export type MachineModel = 'sintra' | 'douro' | 'gaia' | 'custom'
/**
* Full device configuration
@ -35,7 +35,7 @@ export interface DeviceConfig {
/** Bill dispenser configuration */
dispenser: {
/** Dispenser model */
type: 'f56'
type: 'f56' | 'puloon'
/** Serial device path */
device: string
/** Cassette configuration */
@ -66,6 +66,24 @@ export const MACHINE_PRESETS: Record<MachineModel, Omit<DeviceConfig, 'fiatCode'
},
},
/**
* Lamassu Douro
* - Validator: JCM iVIZION (ID003 protocol) on /dev/ttyS0
* - Dispenser: Puloon on /dev/ttyS1
*/
douro: {
model: 'douro',
validator: {
type: 'id003',
device: '/dev/ttyS0',
},
dispenser: {
type: 'puloon',
device: '/dev/ttyS1',
cassettes: [{ denomination: 20, count: 50 }],
},
},
/**
* Lamassu Gaia
* - Validator: JCM iVIZION (ID003 protocol)
@ -165,7 +183,7 @@ export function loadDeviceConfigFromEnv(): DeviceConfig {
const dispenserDevice = import.meta.env.VITE_LAMASSU_DISPENSER_DEVICE
if (dispenserDevice) {
overrides.dispenser = {
type: 'f56',
type: MACHINE_PRESETS[model].dispenser.type,
device: dispenserDevice,
cassettes: [],
}
@ -180,7 +198,7 @@ export function loadDeviceConfigFromEnv(): DeviceConfig {
overrides.dispenser.cassettes = cassettes
} else {
overrides.dispenser = {
type: 'f56',
type: MACHINE_PRESETS[model].dispenser.type,
device: MACHINE_PRESETS[model].dispenser.device,
cassettes,
}

View file

@ -28,7 +28,7 @@ export interface HalConfig {
fiatCode: string
}
dispenser: {
type: 'f56'
type: 'f56' | 'puloon'
device: string
cassettes: CassetteConfig[]
}