Files
home-sensors/internal/filewrite/filewrite.go
T

107 lines
2.5 KiB
Go

// Package filewite adds a function to write the data stream to a file
package filewrite
import (
"context"
"fmt"
"os"
"path"
"time"
"github.com/chathaway-codes/home-sensors/v2/internal/h264video"
"github.com/chathaway-codes/home-sensors/v2/internal/watcher/config"
"github.com/rs/zerolog/log"
)
var Default = &Mod{}
type FileWrite struct {
cfg *config.Config
cancelFunc func()
ctx context.Context
video *h264video.Video
}
func New(video *h264video.Video, cfg *config.Config) (*FileWrite, error) {
ctx, cancelFunc := context.WithCancel(context.Background())
return &FileWrite{
cfg: cfg,
cancelFunc: cancelFunc,
video: video,
ctx: ctx,
}, nil
}
// Run launches the commands and begins creating data. It will block until Done is called.
func (v *FileWrite) Run() {
if v.cfg.LocalCopy == "" {
// Feature is disabled; close right away
return
}
// Confirm that the target directory is a directory
stat, err := os.Stat(v.cfg.LocalCopy)
log := log.With().Str("directory", v.cfg.LocalCopy).Logger()
if err != nil {
log.Fatal().Err(err).Msg("failed to open path")
}
if !stat.IsDir() {
log.Fatal().Msg("path is not directory")
}
// Start snooping
videoCh, codec, done := v.video.Join()
defer done()
// TODO: what do with codec?
log.Info().Str("codec", codec).Msg("got video codec")
now := time.Now()
fileName := path.Join(v.cfg.LocalCopy, fmt.Sprintf("%s.h264", now.Format("2006-01-02T15:04:05")))
writer, err := os.Create(fileName)
if err != nil {
log.Fatal().Err(err).Str("file", fileName).Msg("failed to create file")
}
for bytes := range videoCh {
select {
case <-v.ctx.Done():
return
default:
// do nothing
}
_, err := writer.Write(bytes)
if err != nil {
log.Fatal().Str("file", fileName).Err(err).Msg("failed to write bytes")
}
// Split it every half hour or so
if time.Since(now) > time.Minute*30 {
now = time.Now()
if err := writer.Close(); err != nil {
log.Fatal().Err(err).Msg("failed to close file")
}
fileName := path.Join(v.cfg.LocalCopy, fmt.Sprintf("%s.h264", now.Format("2006-01-02T15:04:05")))
writer, err = os.Create(fileName)
if err != nil {
log.Fatal().Err(err).Str("file", fileName).Msg("failed to create file")
}
}
}
}
// Done stops the processing.
func (v *FileWrite) Done() {
v.cancelFunc()
}
type Mod struct{}
func (m *Mod) Get(video *h264video.Video) (*FileWrite, error) {
cfg, err := config.Default.Get()
if err != nil {
return nil, err
}
return New(video, cfg)
}