Skip to content

Commit

Permalink
Add MiSTeX platform support (#77)
Browse files Browse the repository at this point in the history
* fixing launching on mistex

* update mistex cmd

* set up build for mistex

* workaround tracker errors for slow mister startup
  • Loading branch information
wizzomafizzo authored Jul 6, 2024
1 parent 6fe8eca commit 7dfe090
Show file tree
Hide file tree
Showing 12 changed files with 597 additions and 36 deletions.
30 changes: 29 additions & 1 deletion Taskfile.dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dotenv: [".env"]
tasks:
build:
cmds:
- go build --ldflags "-linkmode external -extldflags -static -s -w" -o _build/${PLATFORM}_{{ARCH}} ./cmd/$PLATFORM
- go build --ldflags "-linkmode external -extldflags -static -s -w" -o _build/${PLATFORM}_{{ARCH}}/${TAPTO_BIN} ./cmd/$PLATFORM

build-image-mister:
vars:
Expand All @@ -20,6 +20,13 @@ tasks:
cmds:
- docker build --platform linux/arm/v7 -t {{.IMAGE_NAME}} {{.DOCKERFILE}}

build-image-mistex:
vars:
IMAGE_NAME: tapto/mistex-build
DOCKERFILE: "{{.PWD}}/scripts/linux_arm64/build"
cmds:
- docker build --platform linux/arm/v8 -t {{.IMAGE_NAME}} {{.DOCKERFILE}}

build-mister:
vars:
BUILD_DIR: "{{.PWD}}/_build/mister_arm"
Expand All @@ -34,13 +41,34 @@ tasks:
- rm -f {{.BUILD_DIR}}/tapto-mister.zip
- zip {{.BUILD_DIR}}/tapto-mister.zip {{.BUILD_DIR}}/tapto.sh {{.BUILD_DIR}}/taptui.sh

build-mistex:
vars:
BUILD_DIR: "{{.PWD}}/_build/mistex_arm64"
BUILDCACHE: "{{.BUILD_DIR}}/.go-buildcache"
MODCACHE: "{{.BUILD_DIR}}/.go-modcache"
IMAGE_NAME: tapto/mistex-build
IMG_BUILDCACHE: /home/build/.cache/go-build
IMG_MODCACHE: /home/build/go/pkg/mod
cmds:
- docker run --rm --platform linux/arm/v8 -v {{.BUILDCACHE}}:{{.IMG_BUILDCACHE}} -v {{.MODCACHE}}:{{.IMG_MODCACHE}} -v {{.PWD}}:/build --user 1000:1000 {{.IMAGE_NAME}} bash -c "PLATFORM=mistex TAPTO_BIN=tapto.sh task build"
- cp {{.PWD}}/scripts/taptui/taptui.sh {{.BUILD_DIR}}
- rm -f {{.BUILD_DIR}}/tapto-mistex.zip
- zip {{.BUILD_DIR}}/tapto-mistex.zip {{.BUILD_DIR}}/tapto.sh {{.BUILD_DIR}}/taptui.sh

deploy-mister:
cmds:
- task: build-mister
- scp _build/mister_arm/taptui.sh root@${MISTER_IP}:/media/fat/Scripts/taptui.sh
- scp _build/mister_arm/tapto.sh root@${MISTER_IP}:/media/fat/Scripts/tapto.sh
- ssh root@${MISTER_IP} /media/fat/Scripts/tapto.sh -service restart

deploy-mistex:
cmds:
- task: build-mistex
- scp _build/mistex_arm64/taptui.sh root@${MISTEX_IP}:/media/fat/Scripts/taptui.sh
- scp _build/mistex_arm64/tapto.sh root@${MISTEX_IP}:/media/fat/Scripts/tapto.sh
- ssh root@${MISTEX_IP} /media/fat/Scripts/tapto.sh -service restart

clean: rm -rf _build

test: go test ./...
Expand Down
13 changes: 1 addition & 12 deletions cmd/mister/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func main() {
flag.Parse()

if *versionOpt {
fmt.Println(appVersion)
fmt.Println("TapTo v" + appVersion + " (mister)")
os.Exit(0)
}

Expand All @@ -158,17 +158,6 @@ func main() {
os.Exit(1)
}

log.Info().Msgf("TapTo v%s", appVersion)
log.Info().Msgf("config path = %s", cfg.IniPath)
log.Info().Msgf("app path = %s", cfg.AppPath)
log.Info().Msgf("connection_string = %s", cfg.GetConnectionString())
log.Info().Msgf("allow_commands = %t", cfg.GetAllowCommands())
log.Info().Msgf("disable_sounds = %t", cfg.GetDisableSounds())
log.Info().Msgf("probe_device = %t", cfg.GetProbeDevice())
log.Info().Msgf("exit_game = %t", cfg.GetExitGame())
log.Info().Msgf("exit_game_blocklist = %s", cfg.GetExitGameBlocklist())
log.Info().Msgf("debug = %t", cfg.GetDebug())

if cfg.GetDebug() {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
} else {
Expand Down
245 changes: 245 additions & 0 deletions cmd/mistex/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
/*
TapTo
Copyright (C) 2023 Gareth Jones
Copyright (C) 2023, 2024 Callan Barrett
This file is part of TapTo.
TapTo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
TapTo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TapTo. If not, see <http://www.gnu.org/licenses/>.
*/

package main

import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io"
"net/http"
"net/url"
"os"
"os/exec"
"strings"

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"

"github.com/wizzomafizzo/tapto/pkg/daemon/api"
"github.com/wizzomafizzo/tapto/pkg/platforms/mister"
"github.com/wizzomafizzo/tapto/pkg/platforms/mistex"
"github.com/wizzomafizzo/tapto/pkg/utils"

"github.com/wizzomafizzo/tapto/pkg/config"
"github.com/wizzomafizzo/tapto/pkg/daemon"
)

const appName = "tapto"

func tryAddToStartup() (bool, error) {
unitPath := "/etc/systemd/system/tapto.service"
unitFile := `[Unit]
Description=TapTo service
[Service]
Type=forking
Restart=no
ExecStart=/media/fat/Scripts/tapto.sh -service start
[Install]
WantedBy=multi-user.target
`

_, err := os.Stat(unitPath)
if err == nil {
return false, nil
}

err = os.WriteFile(unitPath, []byte(unitFile), 0644)
if err != nil {
return false, err
}

cmd := exec.Command("systemctl", "daemon-reload")
err = cmd.Run()
if err != nil {
return false, err
}

cmd = exec.Command("systemctl", "enable", "tapto.service")
err = cmd.Run()
if err != nil {
return false, err
}

return true, nil
}

func handleWriteCommand(textToWrite string, svc *mister.Service, cfg *config.UserConfig) {
log.Info().Msgf("writing text to tag: %s", textToWrite)

if !svc.Running() {
_, _ = fmt.Fprintln(os.Stderr, "TapTo service is not running, please start it before writing.")
log.Error().Msg("TapTo service is not running, exiting")
os.Exit(1)
}

body, err := json.Marshal(api.ReaderWriteRequest{Text: textToWrite})
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "Error encoding request:", err)
log.Error().Msgf("error encoding request: %s", err)
os.Exit(1)
}

resp, err := http.Post(
// TODO: don't hardcode port
"http://127.0.0.1:7497/api/v1/readers/0/write",
"application/json",
bytes.NewBuffer(body),
)
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "Error sending request:", err)
log.Error().Msgf("error sending request: %s", err)
os.Exit(1)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
errBody, err := io.ReadAll(resp.Body)
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "Error reading response:", err)
log.Error().Msgf("error reading response: %s", err)
os.Exit(1)
}

_, _ = fmt.Fprintf(os.Stderr, "Error writing to tag: %s\n", strings.TrimSpace(string(errBody)))
log.Error().Msgf("error writing to tag: %s", strings.TrimSpace(string(errBody)))
os.Exit(1)
}

_, _ = fmt.Fprintln(os.Stderr, "Successfully wrote to tag.")
log.Info().Msg("successfully wrote to tag")
os.Exit(0)
}

func handleLaunchCommand(tokenToLaunch string, svc *mister.Service, cfg *config.UserConfig) {
log.Info().Msgf("launching token: %s", tokenToLaunch)

if !svc.Running() {
_, _ = fmt.Fprintln(os.Stderr, "TapTo service is not running, please start it before launching.")
log.Error().Msg("TapTo service is not running, exiting")
os.Exit(1)
}

resp, err := http.Get("http://127.0.0.1:7497/api/v1/launch/" + url.QueryEscape(tokenToLaunch))
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "Error sending request:", err)
log.Error().Msgf("error sending request: %s", err)
os.Exit(1)
}
defer resp.Body.Close()

_, _ = fmt.Fprintln(os.Stderr, "Successfully launched token.")
log.Info().Msg("successfully launched token")
os.Exit(0)
}

func main() {
svcOpt := flag.String("service", "", "manage TapTo service (start, stop, restart, status)")
writeOpt := flag.String("write", "", "write text to tag")
launchOpt := flag.String("launch", "", "execute text as if it were a token")
versionOpt := flag.Bool("version", false, "print version and exit")
flag.Parse()

if *versionOpt {
fmt.Println("TapTo v" + config.Version + " (mistex)")
os.Exit(0)
}

err := utils.InitLogging()
if err != nil {
fmt.Println("Error initializing logging:", err)
os.Exit(1)
}

cfg, err := config.NewUserConfig(appName, &config.UserConfig{
TapTo: config.TapToConfig{
ProbeDevice: true,
},
})
if err != nil {
log.Error().Msgf("error loading user config: %s", err)
fmt.Println("Error loading config:", err)
os.Exit(1)
}

if cfg.GetDebug() {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
} else {
zerolog.SetGlobalLevel(zerolog.InfoLevel)
}

svc, err := mister.NewService(mister.ServiceArgs{
Name: appName,
Entry: func() (func() error, error) {
return daemon.StartDaemon(&mistex.Platform{}, cfg)
},
})
if err != nil {
log.Error().Msgf("error creating service: %s", err)
fmt.Println("Error creating service:", err)
os.Exit(1)
}

if *writeOpt != "" {
handleWriteCommand(*writeOpt, svc, cfg)
} else if *launchOpt != "" {
handleLaunchCommand(*launchOpt, svc, cfg)
}

svc.ServiceHandler(svcOpt)

fmt.Println("TapTo v" + config.Version)

added, err := tryAddToStartup()
if err != nil {
log.Error().Msgf("error adding to startup: %s", err)
fmt.Println("Error adding to startup:", err)
os.Exit(1)
} else if added {
log.Info().Msg("added to startup")
fmt.Println("Added TapTo to MiSTeX startup.")
}

if !svc.Running() {
err := svc.Start()
fmt.Println("TapTo service not running, starting...")
if err != nil {
log.Error().Msgf("error starting service: %s", err)
fmt.Println("Error starting TapTo service:", err)
} else {
log.Info().Msg("service started manually")
fmt.Println("TapTo service started.")
}
} else {
fmt.Println("TapTo service is running.")
}

ip, err := utils.GetLocalIp()
if err != nil {
fmt.Println("Device address: Unknown")
} else {
fmt.Println("Device address:", ip.String())
}
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
github.com/txn2/txeh v1.4.0 // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/tools v0.22.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
)
Expand All @@ -27,7 +27,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/stretchr/testify v1.9.0 // indirect
golang.org/x/term v0.21.0 // indirect
golang.org/x/term v0.22.0 // indirect
)

require (
Expand All @@ -39,7 +39,7 @@ require (
github.com/gorilla/websocket v1.5.1
github.com/hsanjuan/go-ndef v0.0.1
github.com/rs/zerolog v1.31.0
github.com/wizzomafizzo/mrext v0.0.0-20240702040552-4b6236c5c8f0
github.com/wizzomafizzo/mrext v0.0.0-20240705120538-5efdc40f9c08
go.etcd.io/bbolt v1.3.9
golang.org/x/sync v0.7.0
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/txn2/txeh v1.4.0 h1:0tdvpA4HGJrj8X3kmrU6o/JFStI009nKxwDpMK5CnRU=
github.com/txn2/txeh v1.4.0/go.mod h1:Mgq0hY184zCrDBLgvkIp+9NYGHoYbJcu4xKqUcx1shc=
github.com/wizzomafizzo/mrext v0.0.0-20240702040552-4b6236c5c8f0 h1:6/sixD2xPLQ4mWufWV3WMdpvcGvVQ+Uwv3RwN1k63Pg=
github.com/wizzomafizzo/mrext v0.0.0-20240702040552-4b6236c5c8f0/go.mod h1:pWjoPIzJIXlDfEmdf++eUqsZKrEsYVkOHy39s/H7WLA=
github.com/wizzomafizzo/mrext v0.0.0-20240705120538-5efdc40f9c08 h1:IfCVEDGCzNY4Lx+1tUUkTOLEv4yxXh9Jpsj6T+8YWr4=
github.com/wizzomafizzo/mrext v0.0.0-20240705120538-5efdc40f9c08/go.mod h1:pWjoPIzJIXlDfEmdf++eUqsZKrEsYVkOHy39s/H7WLA=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
Expand All @@ -67,11 +67,11 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
Loading

0 comments on commit 7dfe090

Please sign in to comment.