Flutter and the Dart ecosystem struggles to provide a capable Bluetooth Stack. For a stable product, I decided to proxy the communications with my thermal printer through an ESP32.
The thing I am trying to build will expose ESPs’ bluetooth capability through an onboard web server. Through this I will be able to send any commands to the printer over Wi-Fi, and ESP will handle the stream of Bytes.
The first prototype for this needed for me to connect my ESP with the thermal printer over bluetooth to print anything on the printer.
It started with getting an app called nRF connect on the phone.
https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=en&gl=US&pli=1
With this I scanned my homespace and confirmed that the printer I need to work with has BLE capabilities. I’m using an ATPoS 401.
As scary as BLE sounds, it is simple enough:
- Scan through the central and connect with a device
- Scan device for services
- Scan each service for characteristics
- One of the above characteristics will support write
- Write ByteArray to the said characteristic
Manufacturer provided an ESC command guide to get ByteArrrays for the desired action, and I will try to build a library for it.. But I built an interesting program with what I found:
import ble
import bytes
/**
ESC Commands...
*/
CUT ::= #[0x1d, 0x56, 0x00]
find-device-for-service central /ble.Central --service/ble.BleUuid -> ble.RemoteScannedDevice:
scan-duration_ := Duration --s=3
central.scan --duration=scan-duration_ : | device /ble.RemoteScannedDevice|
if device.data.service-classes.contains (ble.BleUuid "18f0"):
return device
throw "Device not found"
get-write-characteristic-from-peripheral peripheral /ble.RemoteDevice -> ble.RemoteCharacteristic:
peripheral.discover-services
peripheral.discovered-services.do: |service /ble.RemoteService |
service.discover-characteristics
service.discovered-characteristics.do: |characteristic /ble.RemoteCharacteristic |
if service.uuid == (ble.BleUuid "18f0") and characteristic.properties == 12:
return characteristic
throw "correct characteristic not found"
list-everything-for-peripheral peripheral /ble.RemoteDevice:
services := peripheral.discover-services
peripheral.discovered-services.do: |service /ble.RemoteService|
service.discover-characteristics
service.discovered-characteristics.do: | characteristic /ble.RemoteCharacteristic |
characteristic.discover-descriptors
print "$service.uuid/$characteristic.uuid properties: $characteristic.properties"
main:
adapter_ := ble.Adapter
central := ble.Central adapter_
device-to-connect /ble.RemoteScannedDevice := find-device-for-service central --service=(ble.BleUuid "18f0")
print "Device to connect: $device-to-connect.data.service-classes"
peripheral /ble.RemoteDevice := central.connect device-to-connect.address
write-characteristic /ble.RemoteCharacteristic := get-write-characteristic-from-peripheral peripheral
print "$write-characteristic.properties"
write-characteristic.write #[0x1b, 0x4A, 0x01]/// move lines
write-characteristic.write "Hello Nancy!\nThis is a secret message written just for you.\nYou are loved :)".to-byte-array
write-characteristic.write #[0x1b, 0x4A, 0x01]/// move lines
write-characteristic.write CUT
With this, every time I would turn my ESP on, a secret message will be printed out from the printer.
With this today ended with good success, and good learning around ESP’s BLE capabilities and Toit’s adaptation of the same.