-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
129 lines (110 loc) · 3.74 KB
/
main.go
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
package main
import (
"flag"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"github.com/mgutz/logxi/v1"
)
var (
arduinos = flag.String("arduinos", "", "A list of the preferred arduino devices to be used")
tecthulhus = flag.String("tecthulhus", "http://127.0.0.1:12345", "A list of either a serial devices usb://dev/ttyAMA10, or http://IP:port numbers/ for the tecthulhu REST/JSon servers to watch")
concAddress = flag.String("concentrator", "", "The TCP/IP address of a Niantic concetrator if available")
homeTecthulhu = flag.String("home", "Team NorCal", "The name of the portal which we wish to subscribe to and use to drive our arduinos")
logLevel = flag.String("loglevel", "warning", "Set the desired log level")
)
// create Logger interface
var logW = log.NewLogger(log.NewConcurrentWriter(os.Stdout), "pi-gateway")
func main() {
flag.Parse()
if len(*tecthulhus) == 0 && len(*concAddress) == 0 {
logW.Fatal("No tecthulhu/concentrator TCP/IP addresses or Serial USB modules were specified")
os.Exit(-1)
}
// Wait until intialization is over before applying the log level
logW.SetLevel(log.LevelInfo)
// Retrieve the log level from the command line and translate it into the internal format
switch strings.ToLower(*logLevel) {
case "trace":
logW.SetLevel(log.LevelTrace)
case "debug":
logW.SetLevel(log.LevelDebug)
case "info":
logW.SetLevel(log.LevelInfo)
case "warning", "warn":
logW.SetLevel(log.LevelWarn)
case "error", "err":
logW.SetLevel(log.LevelError)
case "fatal":
logW.SetLevel(log.LevelFatal)
default:
logW.Error("unrecognized log level specified")
}
quitC := make(chan bool, 1)
// AUdio comes with 2 mixed channels of audio, ambientC is a looped
// playback that will interrupt ambient playback as a new file name
// is recieved, and sfxC is a single effect that will interrupt
// any other playing sfx file
ambientC := make(chan string, 1)
sfxC := make(chan []string, 1)
initAudio(ambientC, sfxC, quitC)
// portals encapsulate a JSon data feed from ingress nodes, that
// contains up to approximately 4 seconds of status updates
//
statusC := make(chan *portalStatus, 1)
errorC := make(chan error, 1)
portals := strings.Split(*tecthulhus, ",")
if len(*concAddress) != 0 {
conc := &concentrator{
url: *concAddress,
statusC: statusC,
errorC: errorC,
}
go conc.startPortals(quitC)
} else {
tec := &tecthulhu{
url: portals[0],
statusC: statusC,
errorC: errorC,
}
go tec.startPortals(quitC)
}
// Create a channel over which notifications will be sent for new
// arduino devices that are detected, the gateway listens
// for these and uses them for sending updates to the portal state
//
go plugAndPlay(quitC)
// The gateway bridges the status reports from portals down to arduinos
// using the serial protocols defined by the arduino team
//
go startGateway(*homeTecthulhu, statusC, ambientC, sfxC, quitC)
// If someone presses ctrl C then close our quitc channel to shutdown the system
// in an orderly way especially when dealing with device handles for the serial IO
//
sigC := make(chan os.Signal, 1)
signal.Notify(sigC, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
select {
case <-quitC:
case <-sigC:
close(quitC)
}
}()
// Having started all of the IO interfaces concurrently simply loop
// waiting for any changes in state while the processing occurs
// in other threads
for {
select {
case err := <-errorC:
logW.Warn(err.Error())
case <-quitC:
for _, dev := range getRunningDevices(*homeTecthulhu) {
stopRunningDevice(*homeTecthulhu, dev.devName)
logW.Warn(fmt.Sprintf("closing portal %s attached to device %s acting as a %s", *homeTecthulhu, dev.devName, dev.role))
}
return
}
}
}