MSM ACB SDK v1 — UNIVERSAL CONTROLLER ARCHITECTURE

TARGET CONTROLLERS
- ACB-W1: 1 channel
- ACB-W2: 2 channels
- ACB-W4: 4 channels
- Future-compatible: controller capability describes channel count instead of hard-coded model logic.

LAYERS
1. MSM.ACB.Transport
   - UDP discovery 0x94
   - unicast/broadcast transaction
   - timeout/retry/reconnect
   - raw packet diagnostics

2. MSM.ACB.Protocol
   - controller info
   - status/events 0x20
   - card read/write/delete
   - relay/door open
   - anti-passback operations
   - controller backup/restore where supported

3. MSM.ACB.Controller
   - DiscoverControllers()
   - ConnectBySerial(serial)
   - Capabilities: ChannelCount, CardSlots, firmware, MAC/IP
   - Channel(n): Open/Pulse/Status
   - Events: Card, PushButton, DoorSensor, Granted/Denied

4. MSM.ACB.DeviceProfiles
   - ACCESS_DOOR
   - BARRIER_GATE
   - TRIPOD_TURNSTILE
   - FLAP_GATE
   - SWING_GATE
   - PARKING_GATE
   - CUSTOM_RELAY

PROFILE EXAMPLES
Barrier Gate:
- channel relay = OPEN pulse
- optional digital input/event = loop/push button

Tripod Turnstile:
- channel 1 = ENTRY unlock/open
- channel 2 = EXIT unlock/open (or second board channel)
- controller event remains source of card/access decision

DESIGN RULES
- Serial Number is primary controller identity; IP is transport address only.
- Never hard-code W2. Derive usable channels from controller capability/config (1/2/4).
- Application never sends raw protocol commands directly.
- Profile maps semantic actions (OpenGate/AllowEntry) to controller channel operations.
- Preserve existing tested ACB protocol engine; extend through adapters.
- All write operations use result + read-back verification where supported.
- API consumers receive normalized events independent of ACB model.

PROPOSED PUBLIC API
DiscoverControllers(timeout)
Connect(serial)
GetControllerInfo(serial)
GetCapabilities(serial)
OpenChannel(serial, channel)
PulseChannel(serial, channel, milliseconds)
GetCard(serial, cardNo)
PutCard(serial, credential)
DeleteCard(serial, cardNo)
SubscribeEvents(serial)

SEMANTIC DEVICE API
Barrier.Open()
Barrier.PulseOpen(ms)
Turnstile.AllowEntry()
Turnstile.AllowExit()
Door.Unlock(ms)

SAFETY
- Profile must validate requested channel <= ChannelCount.
- Prevent duplicate pulse commands within configured debounce interval.
- Network loss must return explicit OFFLINE/TIMEOUT; never report success optimistically.
- NO/NC and fail-safe/fail-secure remain installation profile settings.
