Skip to content

Commit

Permalink
updated to send frame over dbus instead of using png file
Browse files Browse the repository at this point in the history
  • Loading branch information
gferraro committed Oct 11, 2021
1 parent 0cbb793 commit bb49ee9
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 109 deletions.
37 changes: 18 additions & 19 deletions cmd/thermal-recorder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ const (
)

var (
version = "<not set>"
processor *motion.MotionProcessor
header *headers.HeaderInfo
version = "<not set>"
processor *motion.MotionProcessor
headerInfo *headers.HeaderInfo = nil

frameLogIntervalFirstMin = 15
frameLogInterval = 60 * 5
Expand Down Expand Up @@ -110,8 +110,6 @@ func runMain() error {
}
log.Println("started d-bus service")

deleteSnapshot(conf.OutputDir)

log.Println("host initialisation")
if _, err := host.Init(); err != nil {
return err
Expand Down Expand Up @@ -149,33 +147,34 @@ func handleConn(conn net.Conn, conf *Config) error {
leptondController.SetAutoFFC(true)
totalFrames := 0
reader := bufio.NewReader(conn)
header, err := headers.ReadHeaderInfo(reader)
var err error
headerInfo, err = headers.ReadHeaderInfo(reader)
if err != nil {
return err
}

log.Printf("connection from %s %s (%dx%d@%dfps)", header.Brand(), header.Model(), header.ResX(), header.ResY(), header.FPS())
conf.LoadMotionConfig(header.Model())
log.Printf("connection from %s %s (%dx%d@%dfps)", headerInfo.Brand(), headerInfo.Model(), headerInfo.ResX(), headerInfo.ResY(), headerInfo.FPS())
conf.LoadMotionConfig(headerInfo.Model())
logConfig(conf)

parseFrame := frameParser(header.Brand(), header.Model())
parseFrame := frameParser(headerInfo.Brand(), headerInfo.Model())
if parseFrame == nil {
return fmt.Errorf("unable to handle frames for %s %s", header.Brand(), header.Model())
return fmt.Errorf("unable to handle frames for %s %s", headerInfo.Brand(), headerInfo.Model())
}

cptvRecorder := NewCPTVFileRecorder(conf, header, header.Brand(), header.Model(), header.CameraSerial(), header.Firmware())
cptvRecorder := NewCPTVFileRecorder(conf, headerInfo, headerInfo.Brand(), headerInfo.Model(), headerInfo.CameraSerial(), headerInfo.Firmware())
defer cptvRecorder.Stop()
var recorder recorder.Recorder = cptvRecorder

if conf.Throttler.Activate {
minRecordingLength := conf.Recorder.MinSecs + conf.Recorder.PreviewSecs
recorder = throttle.NewThrottledRecorder(cptvRecorder, &conf.Throttler, minRecordingLength, new(throttle.ThrottledEventRecorder), header)
recorder = throttle.NewThrottledRecorder(cptvRecorder, &conf.Throttler, minRecordingLength, new(throttle.ThrottledEventRecorder), headerInfo)
}

// Constant Recorder
var constantRecorder *CPTVFileRecorder
if conf.Recorder.ConstantRecorder {
constantRecorder = NewCPTVFileRecorder(conf, header, header.Brand(), header.Model(), header.CameraSerial(), header.Firmware())
constantRecorder = NewCPTVFileRecorder(conf, headerInfo, headerInfo.Brand(), headerInfo.Model(), headerInfo.CameraSerial(), headerInfo.Firmware())
constantRecorder.SetAsConstantRecorder()
}

Expand All @@ -186,14 +185,14 @@ func handleConn(conn net.Conn, conf *Config) error {
&conf.Location,
nil,
recorder,
header,
headerInfo,
constantRecorder,
)

log.Print("reading frames")
frameLogIntervalFirstMin *= header.FPS()
frameLogInterval *= header.FPS()
rawFrame := make([]byte, header.FrameSize())
frameLogIntervalFirstMin *= headerInfo.FPS()
frameLogInterval *= headerInfo.FPS()
rawFrame := make([]byte, headerInfo.FrameSize())
for {
_, err := io.ReadFull(reader, rawFrame[:5])
if err != nil {
Expand All @@ -202,7 +201,7 @@ func handleConn(conn net.Conn, conf *Config) error {
message := string(rawFrame[:5])
if message == clearBuffer {
log.Print("clearing motion buffer")
processor.Reset(header)
processor.Reset(headerInfo)
continue
}

Expand All @@ -214,7 +213,7 @@ func handleConn(conn net.Conn, conf *Config) error {
totalFrames++

if totalFrames%frameLogIntervalFirstMin == 0 &&
totalFrames <= 60*header.FPS() || totalFrames%frameLogInterval == 0 {
totalFrames <= 60*headerInfo.FPS() || totalFrames%frameLogInterval == 0 {
log.Printf("%d frames for this connection", totalFrames)
}

Expand Down
33 changes: 21 additions & 12 deletions cmd/thermal-recorder/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ package main

import (
"errors"
"fmt"
"github.com/TheCacophonyProject/go-cptv/cptvframe"
"github.com/TheCacophonyProject/thermal-recorder/headers"

"github.com/godbus/dbus"
"github.com/godbus/dbus/introspect"
"log"
Expand All @@ -32,7 +32,6 @@ const (
)

type service struct {
dir string
}

func startService(dir string) error {
Expand All @@ -48,9 +47,7 @@ func startService(dir string) error {
return errors.New("name already taken")
}

s := &service{
dir: dir,
}
s := &service{}
conn.Export(s, dbusPath, dbusName)
conn.Export(genIntrospectable(s), dbusPath, "org.freedesktop.DBus.Introspectable")
log.Println("introspect done")
Expand All @@ -72,21 +69,33 @@ func genIntrospectable(v interface{}) introspect.Introspectable {
}

// TakeSnapshot will save the next frame as a still
func (s *service) TakeSnapshot() (*cptvframe.Frame, *dbus.Error) {
f, err := newSnapshot(s.dir)
func (s *service) TakeSnapshot(lastFrame int) (*cptvframe.Frame, *dbus.Error) {
f, err := newSnapshot(lastFrame)
if err != nil {
return nil, &dbus.Error{
Name: dbusName + ".StayOnForError",
Body: []interface{}{err.Error()},
}
}

return f, nil
}
func (s *service) CameraInfo() (map[string]interface{}, *dbus.Error) {

func (s *service) CameraInfo() *dbus.Error {
return &dbus.Error{
Name: dbusName + ".HeaderFailed",
Body: []interface{}{fmt.Errorf("No headers available")},
if headerInfo == nil {
return nil, &dbus.Error{
Name: dbusName + ".NoHeaderInfo",
Body: nil,
}
}
camera_specs := map[string]interface{}{
headers.XResolution: headerInfo.ResX(),
headers.YResolution: headerInfo.ResY(),
headers.FrameSize: headerInfo.FrameSize(),
headers.Model: headerInfo.Model(),
headers.Brand: headerInfo.Brand(),
headers.FPS: headerInfo.FPS(),
headers.Serial: headerInfo.CameraSerial(),
headers.Firmware: headerInfo.Firmware(),
}
return camera_specs, nil
}
79 changes: 9 additions & 70 deletions cmd/thermal-recorder/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,11 @@ package main
import (
"errors"
"github.com/TheCacophonyProject/go-cptv/cptvframe"
"log"
"os"
"path"
"sync"
"time"
)

const (
snapshotName = "still.png"
allowedSnapshotPeriod = 500 * time.Millisecond
)

Expand All @@ -37,83 +33,26 @@ var (
mu sync.Mutex
)

func getHeaders() *headers.HeaderInfo {
return header
}

func newSnapshot(dir string) (*cptvframe.Frame, error) {
func newSnapshot(lastFrame int) (*cptvframe.Frame, error) {
mu.Lock()
defer mu.Unlock()

if time.Since(previousSnapshotTime) < allowedSnapshotPeriod {
return nil, nil
}

if processor == nil {
return nil, errors.New("reading from camera has not started yet")
}
f := processor.GetRecentFrame()
if f == nil {
return nil, errors.New("no frames yet")
if lastFrame >= 0 && uint32(lastFrame) == processor.CurrentFrame {
return nil, errors.New("no new frames yet")
}
return f, nil
// g16 := image.NewGray16(image.Rect(0, 0, lepton3.FrameCols, lepton3.FrameRows))
// // Max and min are needed for normalization of the frame
// var valMax uint16
// var valMin uint16 = math.MaxUint16
// var id int
// for _, row := range f.Pix {
// for _, val := range row {
// id += int(val)
// valMax = maxUint16(valMax, val)
// valMin = minUint16(valMin, val)
// }
// }
//
// // Check if frame had already been processed
// if id == previousSnapshotID {
// return nil
// }
// previousSnapshotID = id
//
// var norm = math.MaxUint16 / (valMax - valMin)
// for y, row := range f.Pix {
// for x, val := range row {
// g16.SetGray16(x, y, color.Gray16{Y: (val - valMin) * norm})
// }
// }
//
// out, err := os.Create(path.Join(dir, snapshotName))
// if err != nil {
// return err
// }
// defer out.Close()
//
// if err := png.Encode(out, g16); err != nil {
// return err
// }
//
// // the time will be changed only if the attempt is successful
// previousSnapshotTime = time.Now()
// return nil
}

func deleteSnapshot(dir string) {
if err := os.Remove(path.Join(dir, snapshotName)); err != nil && !os.IsNotExist(err) {
log.Printf("error with deleting snapshot image %s", err)
}
}

func maxUint16(a, b uint16) uint16 {
if a > b {
return a
frameNum, f := processor.GetRecentFrame()
if f == nil {
return nil, errors.New("no frames yet")
}
return b
}

func minUint16(a, b uint16) uint16 {
if a < b {
return a
if f.Status.FrameCount == 0 {
f.Status.FrameCount = int(frameNum)
}
return b
return f, nil
}
6 changes: 3 additions & 3 deletions headers/headerinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ func ReadHeaderInfo(reader *bufio.Reader) (*HeaderInfo, error) {
if err != nil {
return nil, err
}

return &HeaderInfo{
header := &HeaderInfo{
resX: toInt(h[XResolution]),
resY: toInt(h[YResolution]),
fps: toInt(h[FPS]),
Expand All @@ -105,7 +104,8 @@ func ReadHeaderInfo(reader *bufio.Reader) (*HeaderInfo, error) {
model: toStr(h[Model]),
serial: toInt(h[Serial]),
firmware: toStr(h[Firmware]),
}, nil
}
return header, nil
}

func toInt(v interface{}) int {
Expand Down
17 changes: 12 additions & 5 deletions motion/motionprocessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ package motion

import (
"errors"
"reflect"
"time"

"github.com/TheCacophonyProject/go-cptv/cptvframe"
"github.com/TheCacophonyProject/window"
"math"
"reflect"
"time"

config "github.com/TheCacophonyProject/go-config"
"github.com/TheCacophonyProject/thermal-recorder/loglimiter"
Expand Down Expand Up @@ -59,6 +59,7 @@ func NewMotionProcessor(
log: loglimiter.New(minLogInterval),
constantRecorder: constantRecorder,
constantRecording: !isNullOrNullPointer(constantRecorder),
CurrentFrame: 0,
}
}

Expand Down Expand Up @@ -89,6 +90,7 @@ type MotionProcessor struct {
constantRecording bool
constantRecorder recorder.Recorder
crFrames int
CurrentFrame uint32
}

type RecordingListener interface {
Expand All @@ -109,6 +111,11 @@ func (mp *MotionProcessor) Process(rawFrame []byte) error {
mp.stopConstantRecorder()
return err
}
if mp.CurrentFrame == math.MaxUint32 {
mp.CurrentFrame = 0
} else {
mp.CurrentFrame += 1
}
mp.process(frame)
mp.processConstantRecorder(frame)
return nil
Expand Down Expand Up @@ -190,8 +197,8 @@ func (mp *MotionProcessor) ProcessFrame(srcFrame *cptvframe.Frame) {
mp.process(frame)
}

func (mp *MotionProcessor) GetRecentFrame() *cptvframe.Frame {
return mp.frameLoop.CopyRecent()
func (mp *MotionProcessor) GetRecentFrame() (uint32, *cptvframe.Frame) {
return mp.CurrentFrame, mp.frameLoop.CopyRecent()
}

func (mp *MotionProcessor) canStartWriting() error {
Expand Down

0 comments on commit bb49ee9

Please sign in to comment.