Added FUSE support #55
35
fuse.go
35
fuse.go
@ -12,7 +12,7 @@ import (
|
||||
func startFuse(ctx context.Context, dev *infinitime.Device) error {
|
||||
// This is where we'll mount the FS
|
||||
os.Mkdir(k.String("fuse.mountpoint"), 0755)
|
||||
root := &ITNode{kind: 0}
|
||||
root := fusefs.BuildRootNode(dev)
|
||||
server, err := fs.Mount(k.String("fuse.mountpoint"), root, &fs.Options{
|
||||
MountOptions: fuse.MountOptions{
|
||||
// Set to true to see how the file system works.
|
||||
@ -32,43 +32,12 @@ func startFuse(ctx context.Context, dev *infinitime.Device) error {
|
||||
Str("target", k.String("fuse.mountpoint")).
|
||||
Send()
|
||||
|
||||
properties[0] = ITProperty{"heartrate", 2,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.WatchHeartRate(ctx)
|
||||
return converterU8(ctx, ans), err
|
||||
}}
|
||||
properties[1] = ITProperty{"battery", 3,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.WatchBatteryLevel(ctx)
|
||||
return converterU8(ctx, ans), err
|
||||
}}
|
||||
properties[2] = ITProperty{"motion", 4,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.WatchMotion(ctx)
|
||||
return converterMotionValues(ctx, ans), err
|
||||
}}
|
||||
properties[3] = ITProperty{"stepcount", 5,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.WatchStepCount(ctx)
|
||||
return converterU32(ctx, ans), err
|
||||
}}
|
||||
properties[4] = ITProperty{"version", 6,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.Version()
|
||||
return converter1String(ctx, ans), err
|
||||
}}
|
||||
properties[5] = ITProperty{"address", 7,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans := dev.Address()
|
||||
return converter1String(ctx, ans), nil
|
||||
}}
|
||||
fusefs.BuildProperties(dev)
|
||||
|
||||
myfs, err = dev.FS()
|
||||
if err != nil {
|
||||
log.Warn("Error getting BLE filesystem").Err(err).Send()
|
||||
return err
|
||||
}
|
||||
inodemap = make(map[string]uint64)
|
||||
|
||||
// Wait until unmount before exiting
|
||||
go server.Serve()
|
||||
|
@ -89,7 +89,51 @@ type ITNode struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func BuildRootNode(dev *infinitime.Device) *ITNode {
|
||||
inodemap = make(map[string]uint64)
|
||||
myfs, _ = dev.FS()
|
||||
|
||||
return &ITNode{kind: 0}
|
||||
}
|
||||
|
||||
var properties = make([]ITProperty, 6)
|
||||
|
||||
yannickulrich marked this conversation as resolved
|
||||
func BuildProperties(dev *infinitime.Device) {
|
||||
properties[0] = ITProperty{"heartrate", 2,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.WatchHeartRate(ctx)
|
||||
return converterU8(ctx, ans), err
|
||||
}}
|
||||
properties[1] = ITProperty{"battery", 3,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.WatchBatteryLevel(ctx)
|
||||
return converterU8(ctx, ans), err
|
||||
}}
|
||||
properties[2] = ITProperty{"motion", 4,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.WatchMotion(ctx)
|
||||
return converterMotionValues(ctx, ans), err
|
||||
}}
|
||||
properties[3] = ITProperty{"stepcount", 5,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.WatchStepCount(ctx)
|
||||
return converterU32(ctx, ans), err
|
||||
}}
|
||||
properties[4] = ITProperty{"version", 6,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans, err := dev.Version()
|
||||
return converter1String(ctx, ans), err
|
||||
}}
|
||||
properties[5] = ITProperty{"address", 7,
|
||||
func(ctx context.Context) (<-chan []byte, error) {
|
||||
ans := dev.Address()
|
||||
return converter1String(ctx, ans), nil
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
var myfs *blefs.FS = nil;
|
||||
var inodemap map[string]uint64 = nil;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
In my opinion, "device" is unclear. I think it should be called "info" instead, that seems clearer.
Another thing is that you seem to be providing continuous sensor data by never sending an EOF, which means files will be read forever. Files generally don't work like that, so it leads to consequences. Since the syscall for reading from the file will never return until new information is received, a program that reads from this file will not be able to be killed, even by
SIGKILL
. You can see this if you try tocat
the file. It can also break your system's shell depending on how it's configured. Instead, I think you should just provide single data points, and people will just have to useitctl
if they want continuous data, because files aren't meant to work this way.Happy to change that.
Regarding the continuous data stream, isn't this how device files work under Linux? If I run
cat /dev/hidraw0
I get a live stream of data. I was hoping to get the same behaviour. I'm happy to try and fix any bug but think this is probably the best way of doing this. Alternatively, we can have to files, a live stream file (eg./tmp/itd/mnt/live/motion
) and a one-shot file (eg./tmp/itd/mnt/info/motion
). Would you be opposed to this?I'm not 100% sure what you mean with the
cat
example. This works perfectly for me:In the
itd
log I also see the Done method of the watcher getting called. Could you perhaps elaborate on the problem you see?Try this with something that returns data less commonly, such as
battery
. Every timecat
tries to read from the file, it executes a syscall. Since data isn't returned until ITD receives it from the watch, the syscall doesn't return until then either. What this means is that whatever program is reading the file will be executing kernel code, which prevents you from killing it.Linux does this kind of stuff with a char device file. Unfortunately, FUSE doesn't provide a way to make a char device. There seems to be a workaround, but it only works for the root user, so it would not work in ITD. I did test that, and I can confirm it doesn't work.
Okay, fair enough. Sorry for doubting you. How do you feel about keeping a stream-type file for motion? I'm not 100% sure how much sense the instantaneous motion makes.. Otherwise, I'm going to remove the entire channel stuff.
Yeah, instantaneous motion data doesn't make much sense, but the continuous motion data file also doesn't work all the time. InfiniTime will stop sending motion data if you have Raise To Wake and ShakeWake disabled and you put the watch to sleep with the button. This will cause programs to once again read forever without the ability to be killed, so I think it would be better to remove the continuous data entirely. I would love to have it, but if it breaks most programs, it's not worth it, especially since
itctl
can be used instead.