This repository was archived by the owner on Apr 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
146 lines (117 loc) · 3.33 KB
/
Copy pathmain.go
File metadata and controls
146 lines (117 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main
import (
"./ducksboard/_obj/ducksboard"
"flag"
"fmt"
"log"
"net/http"
"time"
)
// Run Update() at a regular interval
func LoopUpdate(config *Config, quit chan bool) {
Update(config)
if config.Refresh < 60 {
log.Println("Refresh interval is less than 60 seconds. Exiting to avoid abuse...")
quit <- true
}
for {
log.Printf("Sleeping for %d seconds\n", config.Refresh)
time.Sleep(config.Refresh * 1e9)
Update(config)
}
}
func buildImageReq(push_rq *ducksboard.PushRequest, image *ConfigImage) (http_req *http.Request, err error) {
rq_val := ducksboard.Image{Timestamp: time.UTC().Seconds()}
rq_val.Value.Source = image.Source
rq_val.Value.Caption = image.Caption
push_rq.Value = rq_val
push_rq.WidgetID = image.Widget
http_req, err = push_rq.Request()
return
}
func Update(config *Config) {
// a single HTTP client is used
http_client := new(http.Client)
// this is the channel that receives http requests to ducksboard
var clientRequests = make(chan *http.Request)
// Push routines talk back on this channel
var push_complete = make(chan int)
for i := 0; i < MAX_PUSH_CONNECTIONS; i++ {
go Push(http_client, push_complete, clientRequests)
}
// a single PushRequest is re-used
push_rq := ducksboard.NewPushRequest(config.API_key)
// Image Updates
log.Printf("Pushing image widgets\n")
for _, image := range config.Sources.Image {
http_req, err := buildImageReq(push_rq, &image)
if err != nil {
log.Printf("error building image push request, %s", err)
continue
}
clientRequests <- http_req
}
// USGS Updates
usgs := NewUSGS_Source(config)
log.Printf("Fetching USGS data\n")
err := usgs.FetchData(http_client)
if err != nil {
log.Printf("error fetching data: %s", err)
return
}
log.Printf("Pushing USGS widgets\n")
for _, widget_id := range usgs.Widgets() {
val, ts, err := usgs.WidgetValue(widget_id)
if err != nil {
log.Printf("error getting value for widget, %s\n", err)
} else {
// push_rq := ducksboard.NewPushRequest(widget_id,config.API_key)
rq_val := ducksboard.Counter{Value: int(val)}
t, err := time.Parse(time.RFC3339, ts)
if err == nil {
rq_val.Timestamp = t.Seconds()
}
push_rq.Value = rq_val
push_rq.WidgetID = widget_id
http_req, err := push_rq.Request()
if err != nil {
log.Printf("error generating push request, %s", err)
continue
}
clientRequests <- http_req
}
}
// all requests have been placed in the channel
close(clientRequests)
// block until all Push routines to complete
for i := 0; i < MAX_PUSH_CONNECTIONS; i++ {
<-push_complete
}
}
// execute HTTP request
func Push(client *http.Client, quit chan int, queue chan *http.Request) {
for r := range queue {
resp, err := client.Do(r)
// Body is always non-nil: this works regardless of error
resp.Body.Close()
if err != nil {
log.Printf("error performing push: %s", err)
} else if resp.StatusCode != 200 {
log.Printf("got non-OK response from Ducksboard API: %s", resp.Status)
}
}
quit <- 1
return
}
func main() {
var config_file = flag.String("f", "config.json", "configuration file")
flag.Parse()
config, err := ParseConfig(*config_file)
if err != nil {
log.Fatal(fmt.Sprintf("Invalid config: %s\n", err))
}
// this is the channel that main() blocks on
var quit = make(chan bool)
go LoopUpdate(config, quit)
<-quit
}