phomemo-printer/main.go

150 lines
3.9 KiB
Go
Raw Normal View History

2023-02-01 16:44:41 +01:00
package main
import (
phomemofilter "brainbaking.com/phomemoprinter/filter"
2023-02-01 16:44:41 +01:00
"log"
"os"
"os/exec"
"strconv"
"strings"
2023-02-01 16:44:41 +01:00
"time"
"tinygo.org/x/bluetooth"
)
var adapter = bluetooth.DefaultAdapter
var phomemoFolder = "/Downloads/phomemo"
func main() {
home, _ := os.UserHomeDir()
inDir := home + phomemoFolder
files, err := os.ReadDir(inDir)
must(phomemoFolder + " does not exist", err)
2023-02-01 16:44:41 +01:00
if len(files) == 0 {
log.Printf("No files to print found in %s, nothing to do. Quitting.\n", inDir)
2023-02-01 16:44:41 +01:00
os.Exit(0)
}
must("Enable Bluetooth stack", adapter.Enable())
2023-02-01 16:44:41 +01:00
log.Println("Scanning for Bluetooth devices...")
ch := make(chan bluetooth.ScanResult, 1)
timeout := make(chan bool, 1)
go func() {
time.Sleep(10 * time.Second)
timeout <- true
}()
2023-02-01 16:44:41 +01:00
go func() {
err = adapter.Scan(func(adapter *bluetooth.Adapter, device bluetooth.ScanResult) {
if device.LocalName() == "Mr.in_M02" {
ch <- device
adapter.StopScan()
}
})
must("start scan", err)
}()
select {
case device := <- ch:
log.Println("Found device: ", device.Address.String(), device.RSSI, device.LocalName())
tryToPrint(device, inDir, files)
case <- timeout:
log.Fatal("Timeout trying to locate Phomemo M02, is it on? Quitting.")
}
2023-02-01 16:44:41 +01:00
}
func tryToPrint(phomemoAddress bluetooth.ScanResult, dir string, files []os.DirEntry) {
var phomemo *bluetooth.Device
phomemo, err := adapter.Connect(phomemoAddress.Address, bluetooth.ConnectionParams{})
must("failed to connect to adapter", err)
log.Println("connected to ", phomemoAddress.Address.String())
defer func() {
if err := phomemo.Disconnect(); err != nil {
log.Println(err)
} else {
log.Println("disconnected")
}
}()
srvcs, err := phomemo.DiscoverServices(nil)
must("failed to discover service", err)
log.Println("Discovering all services on device...")
srvc := srvcs[0] // there's only one (0000ff00-...) anyway
log.Println("- service", srvc.UUID().String())
chars, err := srvc.DiscoverCharacteristics(nil)
must("failed to discover characteristics of service", err)
pyfilterloc := dir + "/" + "phomemo-filter.py"
dumpFilter(pyfilterloc)
defer func() {
os.RemoveAll(pyfilterloc)
}()
2023-02-01 16:44:41 +01:00
// 3 characteristics to discover 0000ff01, 0000ff02, and 0000ff03
for _, file := range files {
filePath := dir + "/" + file.Name()
if isPossibleToPrint(filePath) {
writeData(pyfilterloc, filePath, chars[1]) // 0000ff02-...
readResult(chars[0]) // 0000ff01-...
os.RemoveAll(filePath)
}
2023-02-01 16:44:41 +01:00
}
log.Println("-- DONE")
}
func isPossibleToPrint(filename string) bool {
return strings.HasSuffix(filename, ".jpg") ||
strings.HasSuffix(filename, ".JPG") ||
strings.HasSuffix(filename, ".png") ||
strings.HasSuffix(filename, ".PNG")
}
func dumpFilter(filename string) {
err := os.WriteFile(filename, phomemofilter.Pyfilter, 0666)
must("unable to dump python filter for use", err)
}
func writeData(pyfilterloc string, path string, char bluetooth.DeviceCharacteristic) {
2023-02-01 16:44:41 +01:00
// first, it needs to be prepared for the printer
pathpho := path + ".pho"
argstr := []string{"-c", "/usr/local/bin/python " + pyfilterloc + " " + path + " > " + pathpho}
log.Println("args", argstr)
2023-02-01 16:44:41 +01:00
_, err := exec.Command("/bin/zsh", argstr...).Output()
must("something went wrong while filtering phomemo data py", err)
data, _ := os.ReadFile(pathpho)
log.Printf("-- writing file %s to characteristic %s\n", path, char.UUID().String())
_, err = char.WriteWithoutResponse(data)
if err != nil {
log.Println(" ", err.Error())
}
time.Sleep(1 * time.Second)
os.RemoveAll(pathpho)
}
func readResult(char bluetooth.DeviceCharacteristic) {
log.Println("-- reading from to characteristic", char.UUID().String())
buf := make([]byte, 28)
n, err := char.Read(buf)
if err != nil {
log.Println(" ", err.Error())
} else {
log.Println(" data bytes", strconv.Itoa(n))
log.Println(" value =", buf[:n])
}
time.Sleep(1 * time.Second)
}
func must(action string, err error) {
if err != nil {
panic("failed to " + action + ": " + err.Error())
}
}