218 lines
7.1 KiB
Go
218 lines
7.1 KiB
Go
// =============================================================================
|
|
// Auth: Alex Celani
|
|
// File: led.go
|
|
// Revn: 06-26-2022 1.2
|
|
// Func: receive data as an endpoint, send response back to middleman
|
|
//
|
|
// TODO:
|
|
// =============================================================================
|
|
// CHANGE LOG
|
|
// -----------------------------------------------------------------------------
|
|
// 05-04-2022: init
|
|
// 05-09-2022: began commenting
|
|
// 05-10-2022: finished commenting
|
|
// added alter() and forward()
|
|
// made passed value to alter()/forward() a slice
|
|
// changed refs to recv byte array to slice of n bytes
|
|
// 06-20-2022: changed name to reflect first draft of node.go
|
|
//*06-22-2022: bug squashing and commenting
|
|
// 06-23-2022: updated to produce three different colors
|
|
// 06-26-2022: commented
|
|
//
|
|
// =============================================================================
|
|
|
|
package main
|
|
|
|
import (
|
|
"net" // ResolveTCPAddr, conn.Write,Read,Close
|
|
// ListenTCP, listener.Accept
|
|
"os" // Args, Stderr, Exit
|
|
"fmt" // Fprintf, Println
|
|
"strings" // ToLower
|
|
"github.com/stianeikeland/go-rpio" // talk to RasPi pins
|
|
)
|
|
|
|
|
|
// quick error checking
|
|
func check( err error ) {
|
|
// if user checks an error, it better be nil
|
|
if err != nil {
|
|
// put error in string, print in stderr
|
|
fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() )
|
|
os.Exit( 2 ) // quit
|
|
}
|
|
}
|
|
|
|
|
|
// parse incoming message, keep only second word
|
|
func parse( recv string ) string {
|
|
// split message over spaces
|
|
keywords := strings.Split( recv, " " )
|
|
return keywords[1] // return the second word
|
|
}
|
|
|
|
|
|
// function to handle incoming connections
|
|
func handleClient( conn net.Conn ) {
|
|
defer conn.Close() // barring any error, still close connection
|
|
|
|
var buf [512]byte // declare large byte array, store messages
|
|
|
|
// iterate forever to always read over connection
|
|
for {
|
|
// read n bytes from connection into buffer
|
|
n, err := conn.Read( buf[0:] )
|
|
if err != nil { // erroring on read will simply leave the
|
|
return // function so it can start again later
|
|
}
|
|
|
|
// print recv'd message
|
|
// string() only works on byte SLICES so [:] is required
|
|
fmt.Println( "recv: ", string( buf[:n] ) )
|
|
|
|
// split command into words for ease of parsing
|
|
command := strings.Split( string( buf[:n] ), " " )
|
|
|
|
if command[1] != "led" { // confirm message belongs here
|
|
os.Exit( 2 ) // if not, exit
|
|
}
|
|
|
|
var resp string // declare response variable
|
|
|
|
|
|
// TODO convert to switches?
|
|
// len is 3 for "asK" commands
|
|
if len( command ) == 3 {
|
|
if command[2] == "color" {
|
|
// if user wants color, return color
|
|
resp = color
|
|
} else if command[2] == "status" {
|
|
// if user wants status, return status
|
|
resp = status
|
|
} else {
|
|
// there are only those two fields
|
|
resp = "usage unknown"
|
|
}
|
|
// len is 4 for tell commands
|
|
} else if len( command ) == 4 {
|
|
// if user wants to set color
|
|
if command[2] == "color" {
|
|
color = command[3] // set current color
|
|
resp = color // return current color
|
|
switch color {
|
|
case "blue": // does user want blue?
|
|
// turn blue on, turn rest off
|
|
pinB.High()
|
|
pinR.Low()
|
|
pinG.Low()
|
|
case "red": // does user want red?
|
|
// turn red on, turn rest off
|
|
pinB.Low()
|
|
pinR.High()
|
|
pinG.Low()
|
|
case "green": // does user want green?
|
|
// turn green on, turn rest off
|
|
pinB.Low()
|
|
pinR.Low()
|
|
pinG.High()
|
|
default: // color unknown
|
|
// turn off
|
|
pinB.Low()
|
|
pinR.Low()
|
|
pinG.Low()
|
|
}
|
|
// if user wants to set status
|
|
} else if command[2] == "status" {
|
|
status = command[3] // set current status
|
|
resp = status // return current status
|
|
switch status {
|
|
case "on": // does user want on?
|
|
// default to red
|
|
pinB.Low()
|
|
pinR.High()
|
|
pinG.Low()
|
|
default: // anything else, like off
|
|
// default to off
|
|
pinB.Low()
|
|
pinR.Low()
|
|
pinG.Low()
|
|
}
|
|
// user entered something else entirely
|
|
} else {
|
|
resp = "usage unknown"
|
|
}
|
|
// no other lengths are valid
|
|
} else {
|
|
os.Exit( 2 ) // exit in this case
|
|
}
|
|
|
|
fmt.Println( "answer: ", resp ) // print response
|
|
|
|
// write that response back to original client
|
|
_, err = conn.Write( []byte( resp ) )
|
|
if err != nil { // erroring on write will simply leave the
|
|
return // function so it can start again later
|
|
}
|
|
|
|
fmt.Println( "sent: ", resp ) // print response
|
|
}
|
|
}
|
|
|
|
|
|
//var params = make( map[string]string )
|
|
//var states = make( map[string]string )
|
|
var pinR rpio.Pin // declare red led pin
|
|
var pinG rpio.Pin // declare green led pin
|
|
var pinB rpio.Pin // declare blue led pin
|
|
var color string // declare color variable
|
|
var status string // declare status variable
|
|
|
|
|
|
func main() {
|
|
|
|
// initialize pins to GPIO 11, 9, and 25
|
|
pinR = rpio.Pin( 11 )
|
|
pinG = rpio.Pin( 9 )
|
|
pinB = rpio.Pin( 25 )
|
|
|
|
if err := rpio.Open(); err != nil {
|
|
// on error, print error and exit
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Unmap gpio memory when done
|
|
defer rpio.Close()
|
|
|
|
// Set pins to output mode
|
|
pinR.Output()
|
|
pinG.Output()
|
|
pinB.Output()
|
|
|
|
// ip:port
|
|
// ip doesn't exist, implies localhost
|
|
service := ":1202" // capture ip address and host
|
|
|
|
// "resolve" ip & host according to TCP rules
|
|
tcpAddr, err := net.ResolveTCPAddr( "tcp", service )
|
|
check( err ) // check error
|
|
|
|
// bind and "listen" to ip and port, according to tcp rules
|
|
listener, err := net.ListenTCP( "tcp", tcpAddr )
|
|
check( err ) // check error
|
|
|
|
// iterate forever
|
|
// TODO i mean i can totally make this more user friendly
|
|
for {
|
|
// accept a connection that makes its way to bound port
|
|
conn, err := listener.Accept()
|
|
if err != nil { // if connection fails...
|
|
continue // don't quit program, not fatal error
|
|
}
|
|
|
|
// asynchronous function to handle connection to client
|
|
go handleClient( conn )
|
|
}
|
|
}
|
|
|