rk_devices library

Device protocols that carry their own timing — framed, parsed, and never waited on.

Weighing scales, customer displays, cash drawers and MDB vending framing: one implementation of each conversation, instead of one per transport.

The rule this package is shaped by

Timing that a peripheral controller owns stays there. MDB's five-millisecond reply window and a stepper's microsecond pulses are held by hardware timers and UARTs, not by a general-purpose host running a till. So this package speaks protocols and holds no deadlines: it frames, parses and reports.

Concretely, the native library performs no I/O, opens nothing, sleeps never and spawns no thread. Every call is a pure function of its arguments. That is what makes "no device failure may block taking money" structural here rather than promised — nothing that cannot wait can make anyone wait.

The one place time appears is Stabilizer, and it holds no clock either: the caller supplies the elapsed time on every offer, and its budget is a Duration rather than a number of attempts.

Getting a library

final devices = RkDevices.tryOpen();
if (devices == null) {
  // No native library for this host. That is a third state, not an
  // error — see DrawerPulseUnsupportedHere.
}

The native crate lives in rust/ inside this package and builds to a cdylib/staticlib with a plain C ABI. Wiring it into a Flutter build is deliberately not this package's business.

Classes

DisplayBytes
Bytes to send, and how many characters could not be sent as themselves.
DisplayGeometry
Lines and columns, fixed by the manufacturer.
DrawerPulse
The three outcomes of asking for a drawer pulse.
DrawerPulseBytes
Here are the bytes. Sending them is the caller's job, and whether the drawer physically opened is nobody's: see DrawerReporting.cannotReport.
DrawerPulseRefused
The request itself was wrong — a pulse longer than the protocol can carry, an unknown model.
DrawerPulseUnsupportedHere
There is no native rk_devices library on this host, so no drawer support at all. Distinct from a failure, and it must stay distinct.
MdbAck
0x00 with the mode bit set.
MdbBadChecksum
A complete block whose checksum does not add up. Ask for a retransmit — which in MDB is what RET is for.
MdbBlock
A data block whose checksum verified. payload excludes the checksum.
MdbIncomplete
No word with the mode bit set yet. Nothing may be dropped.
MdbNak
0xFF with the mode bit set — heard and refused.
MdbReply
What came back from a peripheral.
MdbRet
0xAA with the mode bit set — repeat the last block.
RkDevices
A loaded rk_devices native library.
ScaleFrame
What one parse found in the buffer it was given.
ScaleGarbageFrame
A complete line this protocol cannot read. Skip consumed and keep going: reporting this apart from ScaleIncompleteFrame is what lets a caller resynchronise instead of stalling.
ScaleIncompleteFrame
No terminator yet. consumed is zero: keep the bytes and read more.
ScaleReadingFrame
A complete, understood line.
Stabilizer
The settling rule, holding native state the caller owns.
WeightReading
One weight, exactly as the scale sent it.
WriteContinue
offset bytes reached the wire. Send payload.sublist(offset) next — and only that. Starting over duplicates bytes the device has already acted on.
WriteDone
Everything reached the wire.
WriteResume
What may be done after a write, and nothing more.
WriteUnknown
How much reached the device is not knowable. Neither continuing nor repeating is safe at the byte level; the decision belongs to whatever owns the job, and is safe there only because a print job is idempotent by identifier (И29).

Enums

DisplayModel
DisplayOp
DrawerModel
DrawerPin
DrawerReporting
Whether anything can be learned about the drawer over the same wire.
Heard
What the caller heard on the wire since the last offer to a Stabilizer.
MdbAddress
ScaleMeasure
ScaleProtocol
ScaleStability
SettleVerdict
The answer to "may I put this number on a receipt yet".
WeightUnit
The unit the scale itself named. Never converted by this package: a conversion is a rounding decision about a number that is about to be multiplied by a price.
Wire
The transports whose partial-write behaviour differs.

Constants

rkDevicesVersion → const String
The version this package reports about itself.

Properties

hasNativeDevices bool
Whether a native rk_devices library could be loaded on this host.
no setter

Functions

cashDrawerPulse({DrawerModel model = DrawerModel.escposKick, DrawerPin pin = DrawerPin.pin2, Duration? on, Duration? off}) DrawerPulse
The cash-drawer pulse, with all three outcomes a drawer has ever had.
remainingAfterWrite({required RkDevices devices, required Wire wire, required Uint8List payload, required int? accepted}) Uint8List?
A convenience over RkDevices.resolveWrite for the common shape: hand it the payload and what the wire said, get back the bytes still to send.

Exceptions / Errors

RkDevicesException
A native call that could not do what it was asked.
RkDevicesUnavailable
The native library could not be loaded on this host.