create a macos launchd file, use channels to wait for BLE con
This commit is contained in:
parent
5695d442c6
commit
0badf20ff2
|
@ -14,3 +14,7 @@ If you're on macOS, the Python pybluez Bluetooth drivers don't work (well) on th
|
||||||
The script checks a folder for files (intended to be set up as a cron job), if there are any, sends them to the printer (if detected), **and deletes them**.
|
The script checks a folder for files (intended to be set up as a cron job), if there are any, sends them to the printer (if detected), **and deletes them**.
|
||||||
|
|
||||||
See `main.go`, you'll probably want to edit some variables. I hacked everything together in a day for our specific case.
|
See `main.go`, you'll probably want to edit some variables. I hacked everything together in a day for our specific case.
|
||||||
|
|
||||||
|
## Launchd service
|
||||||
|
|
||||||
|
To install as a `launchd` service (mac's "cron"), copy the binary to `/usr/local/bin` and the file `com.brainbaking.PhomemoPrinter.plist` to `~/Library/LaunchAgents`. Then, in a terminal, type `launchctl load com.brainbaking.PhomemoPrinter.plist`.
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>com.brainbaking.phomemoprinter</string>
|
||||||
|
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/usr/local/bin/phomemoprinter</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>Nice</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
|
||||||
|
<key>StartInterval</key>
|
||||||
|
<integer>60</integer>
|
||||||
|
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>/tmp/PhomemoPrinter.err</string>
|
||||||
|
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>/tmp/PhomemoPrinter.out</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
69
main.go
69
main.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"tinygo.org/x/bluetooth"
|
"tinygo.org/x/bluetooth"
|
||||||
)
|
)
|
||||||
|
@ -18,29 +19,40 @@ func main() {
|
||||||
inDir := home + phomemoFolder
|
inDir := home + phomemoFolder
|
||||||
|
|
||||||
files, err := os.ReadDir(inDir)
|
files, err := os.ReadDir(inDir)
|
||||||
must(phomemoFolder, err)
|
must(phomemoFolder + " does not exist", err)
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
log.Printf("No files to print found in %s. Quitting.\n", inDir)
|
log.Printf("No files to print found in %s, nothing to do. Quitting.\n", inDir)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable BLE interface.
|
must("Enable Bluetooth stack", adapter.Enable())
|
||||||
must("enable BLE stack", adapter.Enable())
|
|
||||||
|
|
||||||
// Start scanning. Use this to figure out your device's UUID. Phomemo uses a non-random one.
|
log.Println("Scanning for Bluetooth devices...")
|
||||||
println("scanning...")
|
ch := make(chan bluetooth.ScanResult, 1)
|
||||||
var phomemoAddress bluetooth.ScanResult
|
timeout := make(chan bool, 1)
|
||||||
err = adapter.Scan(func(adapter *bluetooth.Adapter, device bluetooth.ScanResult) {
|
go func() {
|
||||||
if device.LocalName() == "Mr.in_M02" {
|
time.Sleep(10 * time.Second)
|
||||||
phomemoAddress = device
|
timeout <- true
|
||||||
|
}()
|
||||||
|
|
||||||
println("found device: ", device.Address.String(), device.RSSI, device.LocalName())
|
go func() {
|
||||||
adapter.StopScan()
|
err = adapter.Scan(func(adapter *bluetooth.Adapter, device bluetooth.ScanResult) {
|
||||||
}
|
if device.LocalName() == "Mr.in_M02" {
|
||||||
})
|
ch <- device
|
||||||
must("start scan", err)
|
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.")
|
||||||
|
}
|
||||||
|
|
||||||
tryToPrint(phomemoAddress, inDir, files)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryToPrint(phomemoAddress bluetooth.ScanResult, dir string, files []os.DirEntry) {
|
func tryToPrint(phomemoAddress bluetooth.ScanResult, dir string, files []os.DirEntry) {
|
||||||
|
@ -66,31 +78,42 @@ func tryToPrint(phomemoAddress bluetooth.ScanResult, dir string, files []os.DirE
|
||||||
chars, err := srvc.DiscoverCharacteristics(nil)
|
chars, err := srvc.DiscoverCharacteristics(nil)
|
||||||
must("failed to discover characteristics of service", err)
|
must("failed to discover characteristics of service", err)
|
||||||
|
|
||||||
dumpFilter("phomemo-filter.py")
|
pyfilterloc := dir + "/" + "phomemo-filter.py"
|
||||||
|
dumpFilter(pyfilterloc)
|
||||||
defer func() {
|
defer func() {
|
||||||
os.RemoveAll("phomemo-filter.py")
|
os.RemoveAll(pyfilterloc)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// 3 characteristics to discover 0000ff01, 0000ff02, and 0000ff03
|
// 3 characteristics to discover 0000ff01, 0000ff02, and 0000ff03
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
filePath := dir + "/" + file.Name()
|
filePath := dir + "/" + file.Name()
|
||||||
writeData(filePath, chars[1]) // 0000ff02-...
|
if isPossibleToPrint(filePath) {
|
||||||
readResult(chars[0]) // 0000ff01-...
|
writeData(pyfilterloc, filePath, chars[1]) // 0000ff02-...
|
||||||
os.RemoveAll(filePath)
|
readResult(chars[0]) // 0000ff01-...
|
||||||
|
os.RemoveAll(filePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("-- DONE")
|
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) {
|
func dumpFilter(filename string) {
|
||||||
err := os.WriteFile(filename, phomemofilter.Pyfilter, 0666)
|
err := os.WriteFile(filename, phomemofilter.Pyfilter, 0666)
|
||||||
must("unable to dump python filter for use", err)
|
must("unable to dump python filter for use", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeData(path string, char bluetooth.DeviceCharacteristic) {
|
func writeData(pyfilterloc string, path string, char bluetooth.DeviceCharacteristic) {
|
||||||
// first, it needs to be prepared for the printer
|
// first, it needs to be prepared for the printer
|
||||||
pathpho := path + ".pho"
|
pathpho := path + ".pho"
|
||||||
argstr := []string{"-c", "python phomemo-filter.py " + path + " > " + pathpho}
|
argstr := []string{"-c", "/usr/local/bin/python " + pyfilterloc + " " + path + " > " + pathpho}
|
||||||
|
log.Println("args", argstr)
|
||||||
_, err := exec.Command("/bin/zsh", argstr...).Output()
|
_, err := exec.Command("/bin/zsh", argstr...).Output()
|
||||||
must("something went wrong while filtering phomemo data py", err)
|
must("something went wrong while filtering phomemo data py", err)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue