generator-server
This is a commit of skeleton code for the generator server
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.exe | ||
.idea/* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package main | ||
|
||
type StampedReading struct { | ||
Timestamp int | ||
Value interface{} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"math/rand" | ||
"net/http" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
func main() { | ||
dataReadChan := make(chan map[string]StampedReading) // Channel to handle data readings | ||
dataBuffer := make(map[string][]StampedReading) // Map to store readings in until they are sent | ||
|
||
go dataReadLoop(dataReadChan) // Start our async read loop | ||
dataSendTick := time.NewTicker(time.Second * 10) // Ticker to send data | ||
|
||
// Non-blocking channel reads | ||
for { | ||
select { | ||
|
||
case reading := <-dataReadChan: | ||
// We got a data packet | ||
fmt.Printf("New reading: %v\n", reading) | ||
|
||
// Put our reading in the map | ||
for metric, value := range reading { | ||
if record, found := dataBuffer[metric]; !found { | ||
dataBuffer[metric] = []StampedReading{value} | ||
} else { | ||
dataBuffer[metric] = append(record, value) | ||
} | ||
} | ||
|
||
case <-dataSendTick.C: | ||
// Time to send some data | ||
if len(dataBuffer) > 0 { // Only send if we have data | ||
if err := sendData(dataBuffer); err != nil { // Something went wrong | ||
fmt.Printf("Error sending data: %v\n", err) | ||
} else { // Data sent, clear the map | ||
dataBuffer = make(map[string][]StampedReading) | ||
} | ||
} else { // There was no data to send | ||
fmt.Println("Got data send signal but buffer is empty") | ||
// TODO: manage the map so that it doesn't run out of memory and kill everything if we don't send data | ||
} | ||
|
||
} | ||
} | ||
} | ||
|
||
func dataReadLoop(x chan map[string]StampedReading) { | ||
for { | ||
// Send our read packets down the channel | ||
// TODO: error handling | ||
x <- readData() | ||
time.Sleep(time.Second) | ||
} | ||
} | ||
|
||
func readData() map[string]StampedReading { | ||
// TODO: modbus | ||
return map[string]StampedReading{ | ||
"oil.temp": { | ||
Timestamp: int(time.Now().Unix()), | ||
Value: rand.Intn(150), | ||
}, | ||
"fuel.temp": { | ||
Timestamp: int(time.Now().Unix()), | ||
Value: rand.Intn(150), | ||
}, | ||
} | ||
} | ||
|
||
func sendData(data map[string][]StampedReading) error { | ||
|
||
url := "http://localhost:8081/data" | ||
jsonStr, err := json.Marshal(data) | ||
if err != nil { | ||
fmt.Printf("Error marshalling data: %v\n", err) | ||
return err | ||
} | ||
|
||
fmt.Printf("Sending json: %v\n", string(jsonStr)) | ||
|
||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr)) | ||
fillHeader(req) | ||
|
||
client := &http.Client{} | ||
resp, err := client.Do(req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
defer func() { | ||
if err := resp.Body.Close(); err != nil { | ||
fmt.Printf("Error: %v", err) | ||
} | ||
}() | ||
|
||
fmt.Println("response Status:", resp.Status) | ||
if resp.StatusCode != 200 { | ||
fmt.Printf("Received a non-200 response: %v\n", resp.StatusCode) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func fillHeader(req *http.Request) { // Sets the uuid and timestamp for a request | ||
req.Header.Set("Content-Type", "application/json") | ||
req.Header.Set("uuid", "0000001bcd3f") // TODO: get this from somewhere | ||
req.Header.Set("time", strconv.FormatInt(time.Now().Unix(), 10)) | ||
} |