Skip to content

Instantly share code, notes, and snippets.

@chazcheadle
Created August 27, 2016 04:12
Show Gist options
  • Select an option

  • Save chazcheadle/94f9543b36cad8ea4a0f9c9ba7451cd2 to your computer and use it in GitHub Desktop.

Select an option

Save chazcheadle/94f9543b36cad8ea4a0f9c9ba7451cd2 to your computer and use it in GitHub Desktop.
Publish JSON endpoint to list available camera resources (HTTP 200) loaded from a YAML config file written in Golang
cameras:
Exterior (South):
camera_id: hab_camera-1
url : http://HOST:8091/?action=stream
low_image : http://HOST:8091/low.png
type : mjpeg-streamer
Exterior IR (South):
camera_id: hab_camera-2
url : http://HOST:8090/?action=stream
low_image : http://HOST:8090/low.png
type : mjpeg-streamer
Exterior (North):
camera_id: hab_camera-3
url : http://HOST:8092/?action=stream
low_image : http://HOST:8092/low.png
type : mjpeg-streamer
Garden (East):
camera_id: hab_camera-4
url : http://HOST:8081
low_image : http://HOST:8081/low.png
type : motion
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"sync"
"gopkg.in/yaml.v2"
log "github.com/Sirupsen/logrus"
)
type config struct {
Cameras map[string]camera
}
type camera struct {
CameraId string `yaml:"camera_id" json:"camera_id"`
Url string `yaml:"url" json:"url"`
Low string `yaml:"low_image" json:"low"`
Type string `yaml:"type" json:"type"`
}
func testCameras(conf *config) (availableCameras *config) {
var wg sync.WaitGroup
wg.Add(len(conf.Cameras))
for name, settings := range conf.Cameras {
Url := settings.Url
go func(name string, Url string) {
defer wg.Done()
// Make sure the URL is properly formatted.
_, err := url.Parse(Url)
if err != nil {
log.Warn("Invalid URL: ", Url)
delete(conf.Cameras, name)
} else {
response, err := http.Get(Url)
if err != nil {
log.Warn("Unable to get response from: ", Url)
log.Warn(err)
delete(conf.Cameras, name)
} else if response.StatusCode != http.StatusOK {
fmt.Println("Not OK")
delete(conf.Cameras, name)
}
}
}(name, Url)
}
wg.Wait()
return conf
}
// Get configuration of cameras from yaml file.
func getConfig() (*config, error) {
confFile := "/opt/chab/modules/camera/cameras.yml"
if len(os.Args[1:]) > 0 {
confFile = os.Args[1]
}
conf := &config{}
f, err := os.Open(confFile)
defer f.Close()
if err != nil {
log.Info("Could not open %s.", confFile)
log.Info("Error: ", err)
}
d, err := ioutil.ReadAll(f)
if err != nil {
log.Info("Error reading %s.", confFile)
log.Info("Error: ", err)
}
err = yaml.Unmarshal(d, conf)
if err != nil {
log.Info("Error: ", err)
log.Info("Could not parse ", confFile)
}
return conf, err
}
func structToArray(availableCameras *config) (cameraList []byte) {
cameraList, _ = json.Marshal(availableCameras)
return cameraList
}
func main() {
// Get configuration.
conf, err := getConfig()
if err != nil {
log.Fatal("Failed to get configuration\n", err)
}
// Test cameras.
availableCameras := testCameras(conf)
cameraList := structToArray(availableCameras)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Write(cameraList)
})
http.ListenAndServe(":3000", nil)
}
@chazcheadle
Copy link
Author

TODO: Change wait group to NewTicker?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment