Skip to content

Instantly share code, notes, and snippets.

@i39
Forked from chazcheadle/camera_mon.go
Created September 29, 2022 22:57
Show Gist options
  • Select an option

  • Save i39/72687d2b4c806e3ad223fa542f1a57ba to your computer and use it in GitHub Desktop.

Select an option

Save i39/72687d2b4c806e3ad223fa542f1a57ba to your computer and use it in GitHub Desktop.

Revisions

  1. @chazcheadle chazcheadle revised this gist Aug 27, 2016. 1 changed file with 69 additions and 14 deletions.
    83 changes: 69 additions & 14 deletions camera_mon.go
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    package main

    import (
    "encoding/json"
    "io"
    "io/ioutil"
    "os"
    "sort"
    @@ -19,11 +21,17 @@ type Camera struct {
    CameraName string `json:"camera_name"`
    ImageDir string `json:"image_dir"`
    LastImage string `json:"last_image"`
    Status string `json:"status"`
    Online bool `json:"online"`
    StatusCode string `json:"status_code"`
    Timestamp time.Time `json:"timestamp"`
    ErrorCount int `json:"error_count"`
    }

    type Data struct {
    Online bool
    Timestamp time.Time
    }

    // Create struct to be used by our custom sort function.
    type ByTime []os.FileInfo

    @@ -33,30 +41,58 @@ func (f ByTime) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
    func (f ByTime) Less(i, j int) bool { return f[i].ModTime().After(f[j].ModTime()) }

    var (
    mqttBroker = "tcp://HOST:PORT"
    image_dirs = []string{"/tmp/hab_camera-1", "/tmp/hab_camera-2"}

    mqttBroker = "tcp://HOSTNAME:8883"
    mqttClientId = "Camera-Monitor"

    errorThreshold = 2
    snapshotCount = 0
    )

    func copyFile(src, dst string) (err error) {
    in, err := os.Open(src)
    if err != nil {
    return
    }
    defer in.Close()
    out, err := os.Create(dst)
    if err != nil {
    return
    }
    defer func() {
    cerr := out.Close()
    if err == nil {
    err = cerr
    }
    }()
    if _, err = io.Copy(out, in); err != nil {
    return
    }
    err = out.Sync()
    return
    }

    func main() {

    cameras := Cameras{
    Cameras: []Camera{{"hab_camera-1", "Exterior (South)", "/tmp/hab_camera-1", "", "offline", time.Now(), 0}, {"hab_camera-2", "Exterior IR (South)", "/tmp/hab_camera-2", "", "offline", time$
    Cameras: []Camera{{"hab_camera-1", "Exterior (South)", "/tmp/hab_camera-1", "", false, "", time.Now(), 0}, {"hab_camera-2", "Exterior IR (South)", "/tmp/hab_camera-2", "", false, "", time.Now(), 0}},
    }

    opts := MQTT.NewClientOptions()
    opts.AddBroker(mqttBroker)
    opts.SetClientID(mqttClientId)

    c := MQTT.NewClient(opts)
    if token := c.Connect(); token.Wait() && token.Error() != nil {
    log.Warn("Could not connect to: ", mqttBroker)
    }

    ticker := time.NewTicker(time.Millisecond * 3000)
    go func() {
    for timestamp := range ticker.C {
    for index, cam := range cameras.Cameras {
    for index, cam := range cameras.Cameras {

    ticker := time.NewTicker(time.Millisecond * 3000)
    go func(index int, cam Camera) {
    for timestamp := range ticker.C {
    files, err := ioutil.ReadDir(cam.ImageDir)

    if err != nil {
    @@ -69,26 +105,45 @@ func main() {
    }

    if len(files) > 0 {
    // Check if the last image has been updated.
    if cameras.Cameras[index].LastImage == files[0].Name() {
    // Allow a threshold for unchanged images due to camera software performance.
    if cameras.Cameras[index].ErrorCount >= errorThreshold {
    cameras.Cameras[index].Status = "offline"
    cameras.Cameras[index].Online = false
    cameras.Cameras[index].StatusCode = "No new image found."
    } else {
    cameras.Cameras[index].ErrorCount++
    }
    } else {
    cameras.Cameras[index].Status = "online"
    cameras.Cameras[index].Online = true
    cameras.Cameras[index].ErrorCount = 0
    cameras.Cameras[index].StatusCode = ""
    if snapshotCount == 0 || snapshotCount > 4 {
    cerr := copyFile(cam.ImageDir+"/"+files[0].Name(), cam.ImageDir+"/out.jpg")
    if cerr != nil {
    log.Warn("File copy failed")
    log.Warn(cerr)
    }
    snapshotCount = 0
    }
    snapshotCount++
    }
    cameras.Cameras[index].LastImage = files[0].Name()
    cameras.Cameras[index].Timestamp = timestamp
    }

    token := c.Publish("test/cameras/" + cam.CameraID + "/status", 0, false, cameras.Cameras[index].Status)
    // Build message data packet and json.Marshal
    var data = &Data{}
    data.Timestamp = timestamp
    data.Online = cameras.Cameras[index].Online
    messageData, _ := json.Marshal(data)

    // Send MQTT message
    token := c.Publish("test/cameras/"+cam.CameraID, 0, true, messageData)
    token.Wait()
    }
    }
    }()

    }
    }(index, cam)
    }
    select {}
    }
    }
  2. @chazcheadle chazcheadle created this gist Aug 20, 2016.
    94 changes: 94 additions & 0 deletions camera_mon.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@
    package main

    import (
    "io/ioutil"
    "os"
    "sort"
    "time"

    log "github.com/Sirupsen/logrus"
    MQTT "github.com/eclipse/paho.mqtt.golang"
    )

    type Cameras struct {
    Cameras []Camera
    }

    type Camera struct {
    CameraID string `json:"camera_id"`
    CameraName string `json:"camera_name"`
    ImageDir string `json:"image_dir"`
    LastImage string `json:"last_image"`
    Status string `json:"status"`
    Timestamp time.Time `json:"timestamp"`
    ErrorCount int `json:"error_count"`
    }

    // Create struct to be used by our custom sort function.
    type ByTime []os.FileInfo

    // Len, Swap and Less functions for sorting files by ModTime.
    func (f ByTime) Len() int { return len(f) }
    func (f ByTime) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
    func (f ByTime) Less(i, j int) bool { return f[i].ModTime().After(f[j].ModTime()) }

    var (
    mqttBroker = "tcp://HOST:PORT"
    mqttClientId = "Camera-Monitor"

    errorThreshold = 2
    )

    func main() {

    cameras := Cameras{
    Cameras: []Camera{{"hab_camera-1", "Exterior (South)", "/tmp/hab_camera-1", "", "offline", time.Now(), 0}, {"hab_camera-2", "Exterior IR (South)", "/tmp/hab_camera-2", "", "offline", time$
    }

    opts := MQTT.NewClientOptions()
    opts.AddBroker(mqttBroker)
    opts.SetClientID(mqttClientId)
    c := MQTT.NewClient(opts)
    if token := c.Connect(); token.Wait() && token.Error() != nil {
    log.Warn("Could not connect to: ", mqttBroker)
    }

    ticker := time.NewTicker(time.Millisecond * 3000)
    go func() {
    for timestamp := range ticker.C {
    for index, cam := range cameras.Cameras {
    files, err := ioutil.ReadDir(cam.ImageDir)

    if err != nil {
    log.Fatal(err)
    }

    // Sort files by time if there happens to be more than one.
    if len(files) > 1 {
    sort.Sort(ByTime(files))
    }

    if len(files) > 0 {
    if cameras.Cameras[index].LastImage == files[0].Name() {
    // Allow a threshold for unchanged images due to camera software performance.
    if cameras.Cameras[index].ErrorCount >= errorThreshold {
    cameras.Cameras[index].Status = "offline"
    } else {
    cameras.Cameras[index].ErrorCount++
    }
    } else {
    cameras.Cameras[index].Status = "online"
    cameras.Cameras[index].ErrorCount = 0
    }
    cameras.Cameras[index].LastImage = files[0].Name()
    cameras.Cameras[index].Timestamp = timestamp
    }

    token := c.Publish("test/cameras/" + cam.CameraID + "/status", 0, false, cameras.Cameras[index].Status)
    token.Wait()
    }
    }
    }()

    select {}
    }