forked from Elara6331/itd
Compare commits
No commits in common. "e9d7cf17705bba1126ef29219e599ca5ca622d19" and "4cdd47311f6d382aad9d965e7be84c395b2f65c9" have entirely different histories.
e9d7cf1770
...
4cdd47311f
@ -22,7 +22,6 @@
|
||||
- Weather
|
||||
- BLE Filesystem
|
||||
- Navigation (PureMaps)
|
||||
- FUSE Filesystem
|
||||
|
||||
---
|
||||
|
||||
|
12
calls.go
12
calls.go
@ -10,7 +10,7 @@ import (
|
||||
"go.arsenm.dev/logger/log"
|
||||
)
|
||||
|
||||
func initCallNotifs(ctx context.Context, wg WaitGroup, dev *infinitime.Device) error {
|
||||
func initCallNotifs(ctx context.Context, dev *infinitime.Device) error {
|
||||
// Connect to system bus. This connection is for method calls.
|
||||
conn, err := utils.NewSystemBusConn(ctx)
|
||||
if err != nil {
|
||||
@ -53,12 +53,9 @@ func initCallNotifs(ctx context.Context, wg WaitGroup, dev *infinitime.Device) e
|
||||
var respHandlerOnce sync.Once
|
||||
var callObj dbus.BusObject
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done("callNotifs")
|
||||
for {
|
||||
select {
|
||||
case event := <-callCh:
|
||||
// For every message received
|
||||
for event := range callCh {
|
||||
// Get path to call object
|
||||
callPath := event.Body[0].(dbus.ObjectPath)
|
||||
// Get call object
|
||||
@ -99,9 +96,6 @@ func initCallNotifs(ctx context.Context, wg WaitGroup, dev *infinitime.Device) e
|
||||
}
|
||||
}
|
||||
})
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -106,8 +106,5 @@ func setCfgDefaults() {
|
||||
"notifs.ignore.body": []string{},
|
||||
|
||||
"music.vol.interval": 5,
|
||||
|
||||
"fuse.enabled": false,
|
||||
"fuse.mountpoint": "/tmp/itd/mnt",
|
||||
}, "."), nil)
|
||||
}
|
||||
|
66
fuse.go
66
fuse.go
@ -1,66 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/hanwen/go-fuse/v2/fs"
|
||||
"github.com/hanwen/go-fuse/v2/fuse"
|
||||
"go.arsenm.dev/infinitime"
|
||||
"go.arsenm.dev/itd/internal/fusefs"
|
||||
"go.arsenm.dev/logger/log"
|
||||
)
|
||||
|
||||
func startFUSE(ctx context.Context, wg WaitGroup, dev *infinitime.Device) error {
|
||||
// This is where we'll mount the FS
|
||||
err := os.MkdirAll(k.String("fuse.mountpoint"), 0o755)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ignore the error because nothing might be mounted on the mountpoint
|
||||
_ = fusefs.Unmount(k.String("fuse.mountpoint"))
|
||||
|
||||
root, err := fusefs.BuildRootNode(dev)
|
||||
if err != nil {
|
||||
log.Error("Building root node failed").
|
||||
Err(err).
|
||||
Send()
|
||||
return err
|
||||
}
|
||||
|
||||
server, err := fs.Mount(k.String("fuse.mountpoint"), root, &fs.Options{
|
||||
MountOptions: fuse.MountOptions{
|
||||
// Set to true to see how the file system works.
|
||||
Debug: false,
|
||||
SingleThreaded: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("Mounting failed").
|
||||
Str("target", k.String("fuse.mountpoint")).
|
||||
Err(err).
|
||||
Send()
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("Mounted on target").
|
||||
Str("target", k.String("fuse.mountpoint")).
|
||||
Send()
|
||||
|
||||
fusefs.BuildProperties(dev)
|
||||
|
||||
if err != nil {
|
||||
log.Warn("Error getting BLE filesystem").Err(err).Send()
|
||||
return err
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done("fuse")
|
||||
<-ctx.Done()
|
||||
server.Unmount()
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
5
go.mod
5
go.mod
@ -10,12 +10,11 @@ require (
|
||||
github.com/cheggaaa/pb/v3 v3.1.0
|
||||
github.com/gen2brain/dlgs v0.0.0-20220603100644-40c77870fa8d
|
||||
github.com/godbus/dbus/v5 v5.1.0
|
||||
github.com/hanwen/go-fuse/v2 v2.2.0
|
||||
github.com/knadh/koanf v1.4.4
|
||||
github.com/mattn/go-isatty v0.0.17
|
||||
github.com/mozillazg/go-pinyin v0.19.0
|
||||
github.com/urfave/cli/v2 v2.23.7
|
||||
go.arsenm.dev/drpc v0.0.0-20230328202554-c1f2aa71e794
|
||||
go.arsenm.dev/drpc v0.0.0-20230104221210-aa7525743d98
|
||||
go.arsenm.dev/infinitime v0.0.0-20230104230015-512d48bc2469
|
||||
go.arsenm.dev/logger v0.0.0-20230104225304-d706171ea6df
|
||||
golang.org/x/text v0.5.0
|
||||
@ -74,7 +73,7 @@ require (
|
||||
golang.org/x/mobile v0.0.0-20221110043201-43a038452099 // indirect
|
||||
golang.org/x/mod v0.7.0 // indirect
|
||||
golang.org/x/net v0.4.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/tools v0.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
honnef.co/go/js/dom v0.0.0-20221001195520-26252dedbe70 // indirect
|
||||
|
12
go.sum
12
go.sum
@ -257,8 +257,6 @@ github.com/goxjs/gl v0.0.0-20210104184919-e3fafc6f8f2a/go.mod h1:dy/f2gjY09hwVfI
|
||||
github.com/goxjs/glfw v0.0.0-20191126052801-d2efb5f20838/go.mod h1:oS8P8gVOT4ywTcjV6wZlOU4GuVFQ8F5328KY3MJ79CY=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hanwen/go-fuse/v2 v2.2.0 h1:jo5QZYmBLNcl9ovypWaQ5yXMSSV+Ch68xoC3rtZvvBM=
|
||||
github.com/hanwen/go-fuse/v2 v2.2.0/go.mod h1:B1nGE/6RBFyBRC1RRnf23UpwCdyJ31eukw34oAKukAc=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
@ -341,8 +339,6 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
@ -529,8 +525,8 @@ github.com/yuin/goldmark v1.5.3/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5ta
|
||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs=
|
||||
github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
|
||||
go.arsenm.dev/drpc v0.0.0-20230328202554-c1f2aa71e794 h1:8KQpRoQmCTgDvyHFStaIiz5NUNNqMHqVlZoGvIk+OwQ=
|
||||
go.arsenm.dev/drpc v0.0.0-20230328202554-c1f2aa71e794/go.mod h1:K5cFls42m5q1RIphTVojRdXLaoCknq/kBqQt8Ow3XuA=
|
||||
go.arsenm.dev/drpc v0.0.0-20230104221210-aa7525743d98 h1:Tt/05IEOeIEfovj8YLxDaZz+SP8eR1uPLtcgD5Pf4EI=
|
||||
go.arsenm.dev/drpc v0.0.0-20230104221210-aa7525743d98/go.mod h1:K5cFls42m5q1RIphTVojRdXLaoCknq/kBqQt8Ow3XuA=
|
||||
go.arsenm.dev/infinitime v0.0.0-20230104230015-512d48bc2469 h1:LsJHg+8rQSYnTE1sSCjBCACxUUVMZIOQani8J6wF2/E=
|
||||
go.arsenm.dev/infinitime v0.0.0-20230104230015-512d48bc2469/go.mod h1:scUyDmLmCHn6CanGbau8yjTjzyhUbLJcsjmDCCKMIII=
|
||||
go.arsenm.dev/logger v0.0.0-20230104225304-d706171ea6df h1:8mBHvEe7BJmpOeKSMA5YLqrGo9dCpePocTeR0C1+/2w=
|
||||
@ -756,8 +752,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -1,607 +0,0 @@
|
||||
package fusefs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/hanwen/go-fuse/v2/fs"
|
||||
"github.com/hanwen/go-fuse/v2/fuse"
|
||||
"go.arsenm.dev/infinitime"
|
||||
"go.arsenm.dev/infinitime/blefs"
|
||||
"go.arsenm.dev/logger/log"
|
||||
)
|
||||
|
||||
type ITProperty struct {
|
||||
name string
|
||||
Ino uint64
|
||||
gen func() ([]byte, error)
|
||||
}
|
||||
|
||||
type DirEntry struct {
|
||||
isDir bool
|
||||
modtime uint64
|
||||
size uint32
|
||||
path string
|
||||
}
|
||||
|
||||
type ITNode struct {
|
||||
fs.Inode
|
||||
kind nodeKind
|
||||
Ino uint64
|
||||
|
||||
lst []DirEntry
|
||||
self DirEntry
|
||||
path string
|
||||
}
|
||||
|
||||
type nodeKind uint8
|
||||
|
||||
const (
|
||||
nodeKindRoot = iota
|
||||
nodeKindInfo
|
||||
nodeKindFS
|
||||
nodeKindReadOnly
|
||||
)
|
||||
|
||||
var (
|
||||
myfs *blefs.FS = nil
|
||||
inodemap map[string]uint64 = nil
|
||||
)
|
||||
|
||||
func BuildRootNode(dev *infinitime.Device) (*ITNode, error) {
|
||||
var err error
|
||||
inodemap = make(map[string]uint64)
|
||||
myfs, err = dev.FS()
|
||||
if err != nil {
|
||||
log.Error("FUSE Failed to get filesystem").Err(err).Send()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ITNode{kind: nodeKindRoot}, nil
|
||||
}
|
||||
|
||||
var properties = make([]ITProperty, 6)
|
||||
|
||||
func BuildProperties(dev *infinitime.Device) {
|
||||
properties[0] = ITProperty{
|
||||
"heartrate", 2,
|
||||
func() ([]byte, error) {
|
||||
ans, err := dev.HeartRate()
|
||||
return []byte(strconv.Itoa(int(ans)) + "\n"), err
|
||||
},
|
||||
}
|
||||
properties[1] = ITProperty{
|
||||
"battery", 3,
|
||||
func() ([]byte, error) {
|
||||
ans, err := dev.BatteryLevel()
|
||||
return []byte(strconv.Itoa(int(ans)) + "\n"), err
|
||||
},
|
||||
}
|
||||
properties[2] = ITProperty{
|
||||
"motion", 4,
|
||||
func() ([]byte, error) {
|
||||
ans, err := dev.Motion()
|
||||
return []byte(strconv.Itoa(int(ans.X)) + " " + strconv.Itoa(int(ans.Y)) + " " + strconv.Itoa(int(ans.Z)) + "\n"), err
|
||||
},
|
||||
}
|
||||
properties[3] = ITProperty{
|
||||
"stepcount", 6,
|
||||
func() ([]byte, error) {
|
||||
ans, err := dev.StepCount()
|
||||
return []byte(strconv.Itoa(int(ans)) + "\n"), err
|
||||
},
|
||||
}
|
||||
properties[4] = ITProperty{
|
||||
"version", 7,
|
||||
func() ([]byte, error) {
|
||||
ans, err := dev.Version()
|
||||
return []byte(ans + "\n"), err
|
||||
},
|
||||
}
|
||||
properties[5] = ITProperty{
|
||||
"address", 8,
|
||||
func() ([]byte, error) {
|
||||
ans := dev.Address()
|
||||
return []byte(ans + "\n"), nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var _ fs.NodeReaddirer = (*ITNode)(nil)
|
||||
|
||||
// Readdir is part of the NodeReaddirer interface
|
||||
func (n *ITNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
|
||||
switch n.kind {
|
||||
case 0:
|
||||
// root folder
|
||||
r := make([]fuse.DirEntry, 2)
|
||||
r[0] = fuse.DirEntry{
|
||||
Name: "info",
|
||||
Ino: 0,
|
||||
Mode: fuse.S_IFDIR,
|
||||
}
|
||||
r[1] = fuse.DirEntry{
|
||||
Name: "fs",
|
||||
Ino: 1,
|
||||
Mode: fuse.S_IFDIR,
|
||||
}
|
||||
return fs.NewListDirStream(r), 0
|
||||
|
||||
case 1:
|
||||
// info folder
|
||||
r := make([]fuse.DirEntry, 6)
|
||||
for ind, value := range properties {
|
||||
r[ind] = fuse.DirEntry{
|
||||
Name: value.name,
|
||||
Ino: value.Ino,
|
||||
Mode: fuse.S_IFREG,
|
||||
}
|
||||
}
|
||||
|
||||
return fs.NewListDirStream(r), 0
|
||||
|
||||
case 2:
|
||||
// on info
|
||||
files, err := myfs.ReadDir(n.path)
|
||||
if err != nil {
|
||||
log.Error("FUSE ReadDir failed").Str("path", n.path).Err(err).Send()
|
||||
return nil, syscallErr(err)
|
||||
}
|
||||
|
||||
log.Debug("FUSE ReadDir succeeded").Str("path", n.path).Int("objects", len(files)).Send()
|
||||
r := make([]fuse.DirEntry, len(files))
|
||||
n.lst = make([]DirEntry, len(files))
|
||||
for ind, entry := range files {
|
||||
info, err := entry.Info()
|
||||
if err != nil {
|
||||
log.Error("FUSE Info failed").Str("path", n.path).Err(err).Send()
|
||||
return nil, syscallErr(err)
|
||||
}
|
||||
name := info.Name()
|
||||
|
||||
file := DirEntry{
|
||||
path: n.path + "/" + name,
|
||||
size: uint32(info.Size()),
|
||||
modtime: uint64(info.ModTime().Unix()),
|
||||
isDir: info.IsDir(),
|
||||
}
|
||||
n.lst[ind] = file
|
||||
|
||||
ino := inodemap[file.path]
|
||||
if ino == 0 {
|
||||
ino = uint64(len(inodemap)) + 1
|
||||
inodemap[file.path] = ino
|
||||
}
|
||||
|
||||
if file.isDir {
|
||||
r[ind] = fuse.DirEntry{
|
||||
Name: name,
|
||||
Mode: fuse.S_IFDIR,
|
||||
Ino: ino + 10,
|
||||
}
|
||||
} else {
|
||||
r[ind] = fuse.DirEntry{
|
||||
Name: name,
|
||||
Mode: fuse.S_IFREG,
|
||||
Ino: ino + 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
return fs.NewListDirStream(r), 0
|
||||
}
|
||||
r := make([]fuse.DirEntry, 0)
|
||||
return fs.NewListDirStream(r), 0
|
||||
}
|
||||
|
||||
var _ fs.NodeLookuper = (*ITNode)(nil)
|
||||
|
||||
func (n *ITNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fs.Inode, syscall.Errno) {
|
||||
switch n.kind {
|
||||
case 0:
|
||||
// root folder
|
||||
if name == "info" {
|
||||
stable := fs.StableAttr{
|
||||
Mode: fuse.S_IFDIR,
|
||||
Ino: uint64(0),
|
||||
}
|
||||
operations := &ITNode{kind: nodeKindInfo, Ino: 0}
|
||||
child := n.NewInode(ctx, operations, stable)
|
||||
return child, 0
|
||||
} else if name == "fs" {
|
||||
stable := fs.StableAttr{
|
||||
Mode: fuse.S_IFDIR,
|
||||
Ino: uint64(1),
|
||||
}
|
||||
operations := &ITNode{kind: nodeKindFS, Ino: 1, path: ""}
|
||||
child := n.NewInode(ctx, operations, stable)
|
||||
return child, 0
|
||||
}
|
||||
case 1:
|
||||
// info folder
|
||||
for _, value := range properties {
|
||||
if value.name == name {
|
||||
stable := fs.StableAttr{
|
||||
Mode: fuse.S_IFREG,
|
||||
Ino: uint64(value.Ino),
|
||||
}
|
||||
operations := &ITNode{kind: nodeKindReadOnly, Ino: value.Ino}
|
||||
child := n.NewInode(ctx, operations, stable)
|
||||
return child, 0
|
||||
}
|
||||
}
|
||||
|
||||
case 2:
|
||||
// FS object
|
||||
if len(n.lst) == 0 {
|
||||
n.Readdir(ctx)
|
||||
}
|
||||
|
||||
for _, file := range n.lst {
|
||||
if file.path != n.path+"/"+name {
|
||||
continue
|
||||
}
|
||||
log.Debug("FUSE Lookup successful").Str("path", file.path).Send()
|
||||
|
||||
if file.isDir {
|
||||
stable := fs.StableAttr{
|
||||
Mode: fuse.S_IFDIR,
|
||||
Ino: inodemap[file.path],
|
||||
}
|
||||
operations := &ITNode{kind: nodeKindFS, path: file.path}
|
||||
child := n.NewInode(ctx, operations, stable)
|
||||
return child, 0
|
||||
} else {
|
||||
stable := fs.StableAttr{
|
||||
Mode: fuse.S_IFREG,
|
||||
Ino: inodemap[file.path],
|
||||
}
|
||||
operations := &ITNode{
|
||||
kind: nodeKindFS, path: file.path,
|
||||
self: file,
|
||||
}
|
||||
child := n.NewInode(ctx, operations, stable)
|
||||
return child, 0
|
||||
}
|
||||
}
|
||||
log.Warn("FUSE Lookup failed").Str("path", n.path+"/"+name).Send()
|
||||
}
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
type bytesFileReadHandle struct {
|
||||
content []byte
|
||||
}
|
||||
|
||||
var _ fs.FileReader = (*bytesFileReadHandle)(nil)
|
||||
|
||||
func (fh *bytesFileReadHandle) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
|
||||
log.Debug("FUSE Executing Read").Int("size", len(fh.content)).Send()
|
||||
end := off + int64(len(dest))
|
||||
if end > int64(len(fh.content)) {
|
||||
end = int64(len(fh.content))
|
||||
}
|
||||
return fuse.ReadResultData(fh.content[off:end]), 0
|
||||
}
|
||||
|
||||
type sensorFileReadHandle struct {
|
||||
content []byte
|
||||
}
|
||||
|
||||
var _ fs.FileReader = (*sensorFileReadHandle)(nil)
|
||||
|
||||
func (fh *sensorFileReadHandle) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
|
||||
log.Debug("FUSE Executing Read").Int("size", len(fh.content)).Send()
|
||||
end := off + int64(len(dest))
|
||||
if end > int64(len(fh.content)) {
|
||||
end = int64(len(fh.content))
|
||||
}
|
||||
return fuse.ReadResultData(fh.content[off:end]), 0
|
||||
}
|
||||
|
||||
var _ fs.FileFlusher = (*sensorFileReadHandle)(nil)
|
||||
|
||||
func (fh *sensorFileReadHandle) Flush(ctx context.Context) (errno syscall.Errno) {
|
||||
return 0
|
||||
}
|
||||
|
||||
type bytesFileWriteHandle struct {
|
||||
content []byte
|
||||
path string
|
||||
}
|
||||
|
||||
var _ fs.FileWriter = (*bytesFileWriteHandle)(nil)
|
||||
|
||||
func (fh *bytesFileWriteHandle) Write(ctx context.Context, data []byte, off int64) (written uint32, errno syscall.Errno) {
|
||||
log.Debug("FUSE Executing Write").Str("path", fh.path).Int("prev_size", len(fh.content)).Int("next_size", len(data)).Send()
|
||||
if off != int64(len(fh.content)) {
|
||||
log.Error("FUSE Write file size changed unexpectedly").Int("expect", int(off)).Int("received", len(fh.content)).Send()
|
||||
return 0, syscall.ENXIO
|
||||
}
|
||||
fh.content = append(fh.content[:], data[:]...)
|
||||
return uint32(len(data)), 0
|
||||
}
|
||||
|
||||
var _ fs.FileFlusher = (*bytesFileWriteHandle)(nil)
|
||||
|
||||
func (fh *bytesFileWriteHandle) Flush(ctx context.Context) (errno syscall.Errno) {
|
||||
log.Debug("FUSE Attempting flush").Str("path", fh.path).Send()
|
||||
fp, err := myfs.Create(fh.path, uint32(len(fh.content)))
|
||||
if err != nil {
|
||||
log.Error("FUSE Flush failed: create").Str("path", fh.path).Err(err).Send()
|
||||
return syscallErr(err)
|
||||
}
|
||||
|
||||
if len(fh.content) == 0 {
|
||||
log.Debug("FUSE Flush no data to write").Str("path", fh.path).Send()
|
||||
err = fp.Close()
|
||||
if err != nil {
|
||||
log.Error("FUSE Flush failed during close").Str("path", fh.path).Err(err).Send()
|
||||
return syscallErr(err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
go func() {
|
||||
// For every progress event
|
||||
for sent := range fp.Progress() {
|
||||
log.Debug("FUSE Flush progress").Int("bytes", int(sent)).Int("total", len(fh.content)).Send()
|
||||
}
|
||||
}()
|
||||
|
||||
r := bytes.NewReader(fh.content)
|
||||
nread, err := io.Copy(fp, r)
|
||||
if err != nil {
|
||||
log.Error("FUSE Flush failed during write").Str("path", fh.path).Err(err).Send()
|
||||
fp.Close()
|
||||
return syscallErr(err)
|
||||
}
|
||||
if int(nread) != len(fh.content) {
|
||||
log.Error("FUSE Flush failed during write").Str("path", fh.path).Int("expect", len(fh.content)).Int("got", int(nread)).Send()
|
||||
fp.Close()
|
||||
return syscall.EIO
|
||||
}
|
||||
err = fp.Close()
|
||||
if err != nil {
|
||||
log.Error("FUSE Flush failed during close").Str("path", fh.path).Err(err).Send()
|
||||
return syscallErr(err)
|
||||
}
|
||||
log.Debug("FUSE Flush done").Str("path", fh.path).Int("size", len(fh.content)).Send()
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ fs.FileFsyncer = (*bytesFileWriteHandle)(nil)
|
||||
|
||||
func (fh *bytesFileWriteHandle) Fsync(ctx context.Context, flags uint32) (errno syscall.Errno) {
|
||||
return fh.Flush(ctx)
|
||||
}
|
||||
|
||||
var _ fs.NodeGetattrer = (*ITNode)(nil)
|
||||
|
||||
func (bn *ITNode) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
||||
log.Debug("FUSE getattr").Str("path", bn.path).Send()
|
||||
out.Ino = bn.Ino
|
||||
out.Mtime = bn.self.modtime
|
||||
out.Ctime = bn.self.modtime
|
||||
out.Atime = bn.self.modtime
|
||||
out.Size = uint64(bn.self.size)
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ fs.NodeSetattrer = (*ITNode)(nil)
|
||||
|
||||
func (bn *ITNode) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
|
||||
log.Debug("FUSE setattr").Str("path", bn.path).Send()
|
||||
out.Size = 0
|
||||
out.Mtime = 0
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ fs.NodeOpener = (*ITNode)(nil)
|
||||
|
||||
func (f *ITNode) Open(ctx context.Context, openFlags uint32) (fh fs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
|
||||
switch f.kind {
|
||||
case 2:
|
||||
// FS file
|
||||
if openFlags&syscall.O_RDWR != 0 {
|
||||
log.Error("FUSE Open failed: RDWR").Str("path", f.path).Send()
|
||||
return nil, 0, syscall.EROFS
|
||||
}
|
||||
|
||||
if openFlags&syscall.O_WRONLY != 0 {
|
||||
log.Debug("FUSE Opening for write").Str("path", f.path).Send()
|
||||
fh = &bytesFileWriteHandle{
|
||||
path: f.path,
|
||||
content: make([]byte, 0),
|
||||
}
|
||||
return fh, fuse.FOPEN_DIRECT_IO, 0
|
||||
} else {
|
||||
log.Debug("FUSE Opening for read").Str("path", f.path).Send()
|
||||
fp, err := myfs.Open(f.path)
|
||||
if err != nil {
|
||||
log.Error("FUSE: Opening failed").Str("path", f.path).Err(err).Send()
|
||||
return nil, 0, syscallErr(err)
|
||||
}
|
||||
|
||||
defer fp.Close()
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
|
||||
go func() {
|
||||
// For every progress event
|
||||
for sent := range fp.Progress() {
|
||||
log.Debug("FUSE Read progress").Int("bytes", int(sent)).Int("total", int(f.self.size)).Send()
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = io.Copy(b, fp)
|
||||
if err != nil {
|
||||
log.Error("FUSE Read failed").Str("path", f.path).Err(err).Send()
|
||||
fp.Close()
|
||||
return nil, 0, syscallErr(err)
|
||||
}
|
||||
|
||||
fh = &bytesFileReadHandle{
|
||||
content: b.Bytes(),
|
||||
}
|
||||
return fh, fuse.FOPEN_DIRECT_IO, 0
|
||||
}
|
||||
|
||||
case 3:
|
||||
// Device file
|
||||
|
||||
// disallow writes
|
||||
if openFlags&(syscall.O_RDWR|syscall.O_WRONLY) != 0 {
|
||||
return nil, 0, syscall.EROFS
|
||||
}
|
||||
|
||||
for _, value := range properties {
|
||||
if value.Ino == f.Ino {
|
||||
ans, err := value.gen()
|
||||
if err != nil {
|
||||
return nil, 0, syscallErr(err)
|
||||
}
|
||||
|
||||
fh = &sensorFileReadHandle{
|
||||
content: ans,
|
||||
}
|
||||
return fh, fuse.FOPEN_DIRECT_IO, 0
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, 0, syscall.EINVAL
|
||||
}
|
||||
|
||||
var _ fs.NodeCreater = (*ITNode)(nil)
|
||||
|
||||
func (f *ITNode) Create(ctx context.Context, name string, flags uint32, mode uint32, out *fuse.EntryOut) (node *fs.Inode, fh fs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
|
||||
if f.kind != 2 {
|
||||
return nil, nil, 0, syscall.EROFS
|
||||
}
|
||||
|
||||
path := f.path + "/" + name
|
||||
ino := uint64(len(inodemap)) + 11
|
||||
inodemap[path] = ino
|
||||
|
||||
stable := fs.StableAttr{
|
||||
Mode: fuse.S_IFREG,
|
||||
Ino: ino,
|
||||
}
|
||||
operations := &ITNode{
|
||||
kind: nodeKindFS, Ino: ino,
|
||||
path: path,
|
||||
}
|
||||
node = f.NewInode(ctx, operations, stable)
|
||||
|
||||
fh = &bytesFileWriteHandle{
|
||||
path: path,
|
||||
content: make([]byte, 0),
|
||||
}
|
||||
|
||||
log.Debug("FUSE Creating file").Str("path", path).Send()
|
||||
|
||||
errno = 0
|
||||
return node, fh, fuseFlags, 0
|
||||
}
|
||||
|
||||
var _ fs.NodeMkdirer = (*ITNode)(nil)
|
||||
|
||||
func (f *ITNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*fs.Inode, syscall.Errno) {
|
||||
if f.kind != 2 {
|
||||
return nil, syscall.EROFS
|
||||
}
|
||||
|
||||
path := f.path + "/" + name
|
||||
err := myfs.Mkdir(path)
|
||||
if err != nil {
|
||||
log.Error("FUSE Mkdir failed").
|
||||
Str("path", path).
|
||||
Err(err).
|
||||
Send()
|
||||
return nil, syscallErr(err)
|
||||
}
|
||||
|
||||
ino := uint64(len(inodemap)) + 11
|
||||
inodemap[path] = ino
|
||||
|
||||
stable := fs.StableAttr{
|
||||
Mode: fuse.S_IFDIR,
|
||||
Ino: ino,
|
||||
}
|
||||
operations := &ITNode{
|
||||
kind: nodeKindFS, Ino: ino,
|
||||
path: path,
|
||||
}
|
||||
node := f.NewInode(ctx, operations, stable)
|
||||
|
||||
log.Debug("FUSE Mkdir success").
|
||||
Str("path", path).
|
||||
Int("ino", int(ino)).
|
||||
Send()
|
||||
return node, 0
|
||||
}
|
||||
|
||||
var _ fs.NodeRenamer = (*ITNode)(nil)
|
||||
|
||||
func (f *ITNode) Rename(ctx context.Context, name string, newParent fs.InodeEmbedder, newName string, flags uint32) syscall.Errno {
|
||||
if f.kind != 2 {
|
||||
return syscall.EROFS
|
||||
}
|
||||
|
||||
p1 := f.path + "/" + name
|
||||
p2 := newParent.EmbeddedInode().Path(nil)[2:] + "/" + newName
|
||||
|
||||
err := myfs.Rename(p1, p2)
|
||||
if err != nil {
|
||||
log.Error("FUSE Rename failed").
|
||||
Str("src", p1).
|
||||
Str("dest", p2).
|
||||
Err(err).
|
||||
Send()
|
||||
|
||||
return syscallErr(err)
|
||||
}
|
||||
log.Debug("FUSE Rename sucess").
|
||||
Str("src", p1).
|
||||
Str("dest", p2).
|
||||
Send()
|
||||
|
||||
ino := inodemap[p1]
|
||||
delete(inodemap, p1)
|
||||
inodemap[p2] = ino
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ fs.NodeUnlinker = (*ITNode)(nil)
|
||||
|
||||
func (f *ITNode) Unlink(ctx context.Context, name string) syscall.Errno {
|
||||
if f.kind != 2 {
|
||||
return syscall.EROFS
|
||||
}
|
||||
|
||||
delete(inodemap, f.path+"/"+name)
|
||||
err := myfs.Remove(f.path + "/" + name)
|
||||
if err != nil {
|
||||
log.Error("FUSE Unlink failed").
|
||||
Str("file", f.path+"/"+name).
|
||||
Err(err).
|
||||
Send()
|
||||
|
||||
return syscallErr(err)
|
||||
}
|
||||
|
||||
log.Debug("FUSE Unlink success").
|
||||
Str("file", f.path+"/"+name).
|
||||
Send()
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ fs.NodeRmdirer = (*ITNode)(nil)
|
||||
|
||||
func (f *ITNode) Rmdir(ctx context.Context, name string) syscall.Errno {
|
||||
return f.Unlink(ctx, name)
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package fusefs
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"go.arsenm.dev/infinitime/blefs"
|
||||
)
|
||||
|
||||
func syscallErr(err error) syscall.Errno {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
switch err := err.(type) {
|
||||
case blefs.FSError:
|
||||
switch err.Code {
|
||||
case 0x02: // filesystem error
|
||||
return syscall.EIO // TODO
|
||||
case 0x05: // read-only filesystem
|
||||
return syscall.EROFS
|
||||
case 0x03: // no such file
|
||||
return syscall.ENOENT
|
||||
case 0x04: // protocol error
|
||||
return syscall.EPROTO
|
||||
case -5: // input/output error
|
||||
return syscall.EIO
|
||||
case -84: // filesystem is corrupted
|
||||
return syscall.ENOTRECOVERABLE // TODO
|
||||
case -2: // no such directory entry
|
||||
return syscall.ENOENT
|
||||
case -17: // entry already exists
|
||||
return syscall.EEXIST
|
||||
case -20: // entry is not a directory
|
||||
return syscall.ENOTDIR
|
||||
case -39: // directory is not empty
|
||||
return syscall.ENOTEMPTY
|
||||
case -9: // bad file number
|
||||
return syscall.EBADF
|
||||
case -27: // file is too large
|
||||
return syscall.EFBIG
|
||||
case -22: // invalid parameter
|
||||
return syscall.EINVAL
|
||||
case -28: // no space left on device
|
||||
return syscall.ENOSPC
|
||||
case -12: // no more memory available
|
||||
return syscall.ENOMEM
|
||||
case -61: // no attr available
|
||||
return syscall.ENODATA // TODO
|
||||
case -36: // file name is too long
|
||||
return syscall.ENAMETOOLONG
|
||||
}
|
||||
default:
|
||||
switch err {
|
||||
case blefs.ErrFileNotExists: // file does not exist
|
||||
return syscall.ENOENT
|
||||
case blefs.ErrFileReadOnly: // file is read only
|
||||
return syscall.EACCES
|
||||
case blefs.ErrFileWriteOnly: // file is write only
|
||||
return syscall.EACCES
|
||||
case blefs.ErrInvalidOffset: // invalid file offset
|
||||
return syscall.EINVAL
|
||||
case blefs.ErrOffsetChanged: // offset has already been changed
|
||||
return syscall.ESPIPE
|
||||
case blefs.ErrReadOpen: // only one file can be opened for reading at a time
|
||||
return syscall.ENFILE
|
||||
case blefs.ErrWriteOpen: // only one file can be opened for writing at a time
|
||||
return syscall.ENFILE
|
||||
case blefs.ErrNoRemoveRoot: // refusing to remove root directory
|
||||
return syscall.EPERM
|
||||
}
|
||||
}
|
||||
|
||||
return syscall.EIO
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package fusefs
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/hanwen/go-fuse/v2/fuse"
|
||||
)
|
||||
|
||||
func Unmount(mountPoint string) error {
|
||||
return unmount(mountPoint, &fuse.MountOptions{DirectMount: false})
|
||||
}
|
||||
|
||||
// Unfortunately, the FUSE library does not export its unmount function,
|
||||
// so this is required until that changes
|
||||
//
|
||||
//go:linkname unmount github.com/hanwen/go-fuse/v2/fuse.unmount
|
||||
func unmount(mountPoint string, opts *fuse.MountOptions) error
|
77
main.go
77
main.go
@ -26,8 +26,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@ -76,7 +74,21 @@ func main() {
|
||||
LogLevel: level,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
go func() {
|
||||
<-sigCh
|
||||
cancel()
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
os.Exit(0)
|
||||
}()
|
||||
signal.Notify(
|
||||
sigCh,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
)
|
||||
|
||||
// Connect to InfiniTime with default options
|
||||
dev, err := infinitime.Connect(ctx, opts)
|
||||
@ -133,88 +145,49 @@ func main() {
|
||||
log.Error("Error setting current time on connected InfiniTime").Err(err).Send()
|
||||
}
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
go func() {
|
||||
sig := <-sigCh
|
||||
log.Warn("Signal received, shutting down").Stringer("signal", sig).Send()
|
||||
cancel()
|
||||
}()
|
||||
|
||||
wg := WaitGroup{&sync.WaitGroup{}}
|
||||
|
||||
// Initialize music controls
|
||||
err = initMusicCtrl(ctx, wg, dev)
|
||||
err = initMusicCtrl(ctx, dev)
|
||||
if err != nil {
|
||||
log.Error("Error initializing music control").Err(err).Send()
|
||||
}
|
||||
|
||||
// Start control socket
|
||||
err = initCallNotifs(ctx, wg, dev)
|
||||
err = initCallNotifs(ctx, dev)
|
||||
if err != nil {
|
||||
log.Error("Error initializing call notifications").Err(err).Send()
|
||||
}
|
||||
|
||||
// Initialize notification relay
|
||||
err = initNotifRelay(ctx, wg, dev)
|
||||
err = initNotifRelay(ctx, dev)
|
||||
if err != nil {
|
||||
log.Error("Error initializing notification relay").Err(err).Send()
|
||||
}
|
||||
|
||||
// Initializa weather
|
||||
err = initWeather(ctx, wg, dev)
|
||||
err = initWeather(ctx, dev)
|
||||
if err != nil {
|
||||
log.Error("Error initializing weather").Err(err).Send()
|
||||
}
|
||||
|
||||
// Initialize metrics collection
|
||||
err = initMetrics(ctx, wg, dev)
|
||||
err = initMetrics(ctx, dev)
|
||||
if err != nil {
|
||||
log.Error("Error intializing metrics collection").Err(err).Send()
|
||||
}
|
||||
|
||||
// Initialize puremaps integration
|
||||
err = initPureMaps(ctx, wg, dev)
|
||||
// Initialize metrics collection
|
||||
err = initPureMaps(ctx, dev)
|
||||
if err != nil {
|
||||
log.Error("Error intializing puremaps integration").Err(err).Send()
|
||||
}
|
||||
|
||||
// Start fuse socket
|
||||
if k.Bool("fuse.enabled") {
|
||||
err = startFUSE(ctx, wg, dev)
|
||||
if err != nil {
|
||||
log.Error("Error starting fuse socket").Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
// Start control socket
|
||||
err = startSocket(ctx, wg, dev)
|
||||
err = startSocket(ctx, dev)
|
||||
if err != nil {
|
||||
log.Error("Error starting socket").Err(err).Send()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
type x struct {
|
||||
n int
|
||||
*sync.WaitGroup
|
||||
}
|
||||
|
||||
func (xy *x) Add(i int) {
|
||||
xy.n += i
|
||||
xy.WaitGroup.Add(i)
|
||||
fmt.Println("add: counter:", xy.n)
|
||||
}
|
||||
|
||||
func (xy *x) Done() {
|
||||
xy.n -= 1
|
||||
xy.WaitGroup.Done()
|
||||
fmt.Println("done: counter:", xy.n)
|
||||
// Block forever
|
||||
select {}
|
||||
}
|
||||
|
||||
func onReqPasskey() (uint32, error) {
|
||||
|
5
maps.go
5
maps.go
@ -18,7 +18,7 @@ const (
|
||||
progressProperty = interfaceName + ".progress"
|
||||
)
|
||||
|
||||
func initPureMaps(ctx context.Context, wg WaitGroup, dev *infinitime.Device) error {
|
||||
func initPureMaps(ctx context.Context, dev *infinitime.Device) error {
|
||||
// Connect to session bus. This connection is for method calls.
|
||||
conn, err := utils.NewSessionBusConn(ctx)
|
||||
if err != nil {
|
||||
@ -59,10 +59,7 @@ func initPureMaps(ctx context.Context, wg WaitGroup, dev *infinitime.Device) err
|
||||
}
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done("pureMaps")
|
||||
|
||||
signalCh := make(chan *dbus.Message, 10)
|
||||
monitorConn.Eavesdrop(signalCh)
|
||||
|
||||
|
10
metrics.go
10
metrics.go
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"path/filepath"
|
||||
|
||||
"time"
|
||||
|
||||
"go.arsenm.dev/infinitime"
|
||||
@ -12,7 +11,7 @@ import (
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
func initMetrics(ctx context.Context, wg WaitGroup, dev *infinitime.Device) error {
|
||||
func initMetrics(ctx context.Context, dev *infinitime.Device) error {
|
||||
// If metrics disabled, return nil
|
||||
if !k.Bool("metrics.enabled") {
|
||||
return nil
|
||||
@ -126,13 +125,6 @@ func initMetrics(ctx context.Context, wg WaitGroup, dev *infinitime.Device) erro
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done("metrics")
|
||||
<-ctx.Done()
|
||||
db.Close()
|
||||
}()
|
||||
|
||||
log.Info("Initialized metrics collection").Send()
|
||||
|
||||
return nil
|
||||
|
13
music.go
13
music.go
@ -21,14 +21,13 @@ package main
|
||||
import (
|
||||
"context"
|
||||
|
||||
|
||||
"go.arsenm.dev/infinitime"
|
||||
"go.arsenm.dev/itd/mpris"
|
||||
"go.arsenm.dev/itd/translit"
|
||||
"go.arsenm.dev/logger/log"
|
||||
)
|
||||
|
||||
func initMusicCtrl(ctx context.Context, wg WaitGroup, dev *infinitime.Device) error {
|
||||
func initMusicCtrl(ctx context.Context, dev *infinitime.Device) error {
|
||||
mpris.Init(ctx)
|
||||
|
||||
maps := k.Strings("notifs.translit.use")
|
||||
@ -55,14 +54,9 @@ func initMusicCtrl(ctx context.Context, wg WaitGroup, dev *infinitime.Device) er
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done("musicCtrl")
|
||||
// For every music event received
|
||||
for {
|
||||
select {
|
||||
case musicEvt := <-musicEvtCh:
|
||||
for musicEvt := range musicEvtCh {
|
||||
// Perform appropriate action based on event
|
||||
switch musicEvt {
|
||||
case infinitime.MusicEventPlay:
|
||||
@ -78,9 +72,6 @@ func initMusicCtrl(ctx context.Context, wg WaitGroup, dev *infinitime.Device) er
|
||||
case infinitime.MusicEventVolDown:
|
||||
mpris.VolDown(uint(k.Int("music.vol.interval")))
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
12
notifs.go
12
notifs.go
@ -29,7 +29,7 @@ import (
|
||||
"go.arsenm.dev/logger/log"
|
||||
)
|
||||
|
||||
func initNotifRelay(ctx context.Context, wg WaitGroup, dev *infinitime.Device) error {
|
||||
func initNotifRelay(ctx context.Context, dev *infinitime.Device) error {
|
||||
// Connect to dbus session bus
|
||||
bus, err := utils.NewSessionBusConn(ctx)
|
||||
if err != nil {
|
||||
@ -54,13 +54,9 @@ func initNotifRelay(ctx context.Context, wg WaitGroup, dev *infinitime.Device) e
|
||||
// Send events to channel
|
||||
bus.Eavesdrop(notifCh)
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done("notifRelay")
|
||||
// For every event sent to channel
|
||||
for {
|
||||
select {
|
||||
case v := <-notifCh:
|
||||
for v := range notifCh {
|
||||
// If firmware is updating, skip
|
||||
if firmwareUpdating {
|
||||
continue
|
||||
@ -95,10 +91,6 @@ func initNotifRelay(ctx context.Context, wg WaitGroup, dev *infinitime.Device) e
|
||||
}
|
||||
|
||||
dev.Notify(sender, msg)
|
||||
case <-ctx.Done():
|
||||
bus.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
12
socket.go
12
socket.go
@ -25,7 +25,6 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"time"
|
||||
|
||||
"go.arsenm.dev/drpc/muxserver"
|
||||
@ -42,7 +41,7 @@ var (
|
||||
ErrDFUInvalidUpgType = errors.New("invalid upgrade type")
|
||||
)
|
||||
|
||||
func startSocket(ctx context.Context, wg WaitGroup, dev *infinitime.Device) error {
|
||||
func startSocket(ctx context.Context, dev *infinitime.Device) error {
|
||||
// Make socket directory if non-existant
|
||||
err := os.MkdirAll(filepath.Dir(k.String("socket.path")), 0o755)
|
||||
if err != nil {
|
||||
@ -78,13 +77,10 @@ func startSocket(ctx context.Context, wg WaitGroup, dev *infinitime.Device) erro
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("Starting control socket").Str("path", k.String("socket.path")).Send()
|
||||
go muxserver.New(mux).Serve(ctx, ln)
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done("socket")
|
||||
muxserver.New(mux).Serve(ctx, ln)
|
||||
}()
|
||||
// Log socket start
|
||||
log.Info("Started control socket").Str("path", k.String("socket.path")).Send()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
16
waitgroup.go
16
waitgroup.go
@ -1,16 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"go.arsenm.dev/logger/log"
|
||||
)
|
||||
|
||||
type WaitGroup struct {
|
||||
*sync.WaitGroup
|
||||
}
|
||||
|
||||
func (wg WaitGroup) Done(c string) {
|
||||
log.Info("Component stopped").Str("name", c).Send()
|
||||
wg.WaitGroup.Done()
|
||||
}
|
21
weather.go
21
weather.go
@ -9,7 +9,6 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"time"
|
||||
|
||||
"go.arsenm.dev/infinitime"
|
||||
@ -62,14 +61,7 @@ type OSMData []struct {
|
||||
|
||||
var sendWeatherCh = make(chan struct{}, 1)
|
||||
|
||||
func sleepCtx(ctx context.Context, d time.Duration) {
|
||||
select {
|
||||
case <-time.After(d):
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}
|
||||
|
||||
func initWeather(ctx context.Context, wg WaitGroup, dev *infinitime.Device) error {
|
||||
func initWeather(ctx context.Context, dev *infinitime.Device) error {
|
||||
if !k.Bool("weather.enabled") {
|
||||
return nil
|
||||
}
|
||||
@ -82,21 +74,14 @@ func initWeather(ctx context.Context, wg WaitGroup, dev *infinitime.Device) erro
|
||||
|
||||
timer := time.NewTimer(time.Hour)
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done("weather")
|
||||
for {
|
||||
_, ok := <-ctx.Done()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Attempt to get weather
|
||||
data, err := getWeather(ctx, lat, lon)
|
||||
if err != nil {
|
||||
log.Warn("Error getting weather data").Err(err).Send()
|
||||
// Wait 15 minutes before retrying
|
||||
sleepCtx(ctx, 15*time.Minute)
|
||||
time.Sleep(15 * time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
@ -189,8 +174,6 @@ func initWeather(ctx context.Context, wg WaitGroup, dev *infinitime.Device) erro
|
||||
select {
|
||||
case <-timer.C:
|
||||
case <-sendWeatherCh:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
Loading…
Reference in New Issue
Block a user