This commit is contained in:
2022-06-27 12:59:58 -04:00
parent 580b3d68ae
commit e180cd8ea8
31 changed files with 2045 additions and 7 deletions
+6 -7
View File
@@ -1,15 +1,14 @@
# Binaries for programs and plugins # Binaries for programs and plugins
*.exe node
*.exe~ led
*.dll colonel
*.so sentinel
*.dylib
# Test binary, built with `go test -c` # Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it) # Dependency directories (remove the comment below to include it)
# vendor/ # vendor/
.gitignore
+8
View File
@@ -0,0 +1,8 @@
all: clean build
clean:
rm speak reply
build:
go build speak.go
go build reply.go
+23
View File
@@ -0,0 +1,23 @@
# ==============================================================================
# Auth: Alex Celani
# File: convo.txt
# Revn: 05-10-2022 0.1
# Func: elaborate on how the convo Golang networks programs should run
#
# TODO: create
# ==============================================================================
# CHANGE LOG
# ------------------------------------------------------------------------------
# 05-10-2022: init
#
# ==============================================================================
uh
just send a bunch of information back and forth
A sends data to B, B receives, processes, and responds
A receives, processes, and responds
Repeat until some cutoff condition
Executable
BIN
View File
Binary file not shown.
+84
View File
@@ -0,0 +1,84 @@
// =============================================================================
// Auth: Alex Celani
// File: reply.go
// Revn: 05-13-2022 0.1
// Func: host connection, reply to speak.go
//
// TODO: create
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-13-2022: init
//
// =============================================================================
package main
import (
"net"
"os"
"fmt"
"time"
)
func check( err error ) {
if err != nil {
fmt.Println( "Fatal: ", err.Error() )
os.Exit( 1 )
}
}
func handle( conn net.Conn ) {
table := map[string]string{ "hello":"hello",
"how are you":"fine and yourself",
"well enough for the weather":"aye it scalds",
"i lost my begonias":"exit" }
var buffer [512]byte
for {
n, err := conn.Read( buffer[:] )
check( err )
fmt.Println( "\t\t\t", string( buffer[:n] ) )
time.Sleep( 2 * time.Second )
response, present := table[string( buffer[:n] )]
if present {
_, err = conn.Write( []byte( response ) )
check( err )
if response == "exit" {
break
} else {
fmt.Println( response )
}
} else {
fmt.Println( "excuse me good sir" )
os.Exit( 2 )
}
}
}
func main() {
service := ":1200"
addr, err := net.ResolveTCPAddr( "tcp", service )
check( err )
listener, err := net.ListenTCP( "tcp", addr )
conn, err := listener.Accept()
check( err )
handle( conn )
os.Exit( 0 )
}
Executable
BIN
View File
Binary file not shown.
+85
View File
@@ -0,0 +1,85 @@
// =============================================================================
// Auth: Alex Celani
// File: speak.go
// Revn: 05-11-2022 0.1
// Func: initiate conversation
//
// TODO: create
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-11-2022: init
// 05-17-2022: changed an entry in the response table
//
// =============================================================================
package main
import (
"net"
"os"
"fmt"
"time"
)
func check( err error ) {
if err != nil {
fmt.Println( "fatal: ", err.Error() )
os.Exit( 1 )
}
}
func handle( conn net.Conn ) {
table := map[string]string{ "hello":"how are you",
"fine and yourself":"well enough for the weather",
"aye it scalds":"i lost my begonias" }
var buffer [512]byte
for {
n, err := conn.Read( buffer[:] )
check( err )
if string( buffer[:n] ) == "exit" {
break
}
fmt.Println( "\t\t\t", string( buffer[:n] ) )
time.Sleep( 2 * time.Second )
response, present := table[string( buffer[:n] )]
if present {
_, err = conn.Write( []byte( response ) )
check( err )
fmt.Println( response )
} else {
fmt.Println( "excuse me good sir" )
os.Exit( 2 )
}
}
}
func main() {
service := ":1200"
addr, err := net.ResolveTCPAddr( "tcp", service )
check( err )
conn, err := net.DialTCP( "tcp", nil, addr )
check( err )
_, err = conn.Write( []byte( "hello" ) )
check( err )
fmt.Println( "hello" )
handle( conn )
os.Exit( 0 )
}
+9
View File
@@ -0,0 +1,9 @@
all: clean build
clean:
rm colonel sentinel node
build:
go build colonel.go
go build sentinel.go
go build node.go
+96
View File
@@ -0,0 +1,96 @@
// =============================================================================
// Auth: Alex Celani
// File: colonel.go
// Revn: 06-20-2022 1.0
// Func: Send message to another machine and then receive a single
// response. Extremely tight bounds, not robust at all
//
// TODO: comment
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
//*06-20-2022: changed name to reflect first draft of colonel.go
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read
"os" // Exit, Stdin, Stderr, Args
"fmt" // Println, Print, Fprintf
"bufio" // NewScanner, NewScanner.Scan,Text
"strings" // ToLower
"time" // Now, Sub
)
// quick function to take user input
func input( ps1 string ) string {
fmt.Print( ps1 ) // print prompt
scanner := bufio.NewScanner( os.Stdin ) // link to stdin
scanner.Scan() // pull data
return strings.ToLower( scanner.Text() ) // return lower text
}
// 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
}
}
func main() {
// if len is not 2 ( ./name host:port ), print usage and quit
if len( os.Args ) != 2 {
fmt.Fprintf( os.Stderr, "Usage: %s host:port", os.Args[0] )
os.Exit( 1 )
}
service := os.Args[1] // capture ip address and host
// "resolve" ip & host according to TCP rules
tcpAddr, err := net.ResolveTCPAddr( "tcp", service )
check( err ) // check error
// "dial" ( establish connection ) to destination ip & port
// according to TCP rules
// laddr = nil -> local address is localhost
conn, err := net.DialTCP( "tcp", nil, tcpAddr )
check( err ) // check error
var in string = input( ">> " ) // get user input
start := time.Now() // start round trip timer
// convert user input to bytes and send over connection
_, err = conn.Write( []byte( in ) )
check( err ) // check error
var buf [512]byte // init byte array
// read from connection into byte array
// amount of bytes read stored in n
//n, err := conn.Read( buf[0:] )
n, err := conn.Read( buf[:] )
check( err ) // check error
t := time.Now() // stop round trip timer
// convert read bytes into string and print
fmt.Println( string( buf[:n] ) )
fmt.Println() // newline to clean up a little
fmt.Println( "rtt: ", t.Sub( start ) ) // print elapsed time
os.Exit( 0 ) // exeunt
}
+130
View File
@@ -0,0 +1,130 @@
// =============================================================================
// Auth: Alex Celani
// File: node.go
// Revn: 06-22-2022 1.0
// 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
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, conn.Write,Read,Close
// ListenTCP, listener.Accept
"os" // Args, Stderr, Exit
"fmt" // Fprintf, Println
"strings" // ToLower
)
// 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
// init map of fields to their values
reply := map[string]string{ "soc" : "30",
"batt" : "30",
"temp" : "65",
"humid" : "35",
"sun" : "10",
"list" : "soc batt temp humid sun list" }
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] ) )
// send input to parse
recv := parse( string( buf[:n] ) )
fmt.Println( "parse: ", recv ) // print
// declare variables to grab values from field map
var resp string
var prs bool
// get values from map, prs is false if key (recv) DNE in map
resp, prs = reply[recv]
if !prs { // if key was not present
resp = "field does not exist" // response is DNE
}
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
}
}
func main() {
// 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 )
}
}
BIN
View File
Binary file not shown.
+157
View File
@@ -0,0 +1,157 @@
// =============================================================================
// Auth: Alex Celani
// File: sent.go
// Revn: 06-22-2022 1.0
// Func: Receive message, play with it, send to a third place, receive
// response, send off to first place
//
// TODO: comment
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
// 05-05-2022: commented
// 05-10-2022: added argument 'n' to alter() for halving purposes
// changed passed value to alter()/forward() a slice
// 06-20-2022: changed name to reflect first draft of sentinel.go
//*06-22-2022: bug fixing and commenting
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close
// ListenTCP, listener.Accept
"os" // Exit, Stderr, Stdin, Args
"fmt" // Println, Fprintf
"strings" // ToLower, ToUpper
)
// quick error checking
func check( err error ){
// if user checks an error, it better be nil
if err != nil {
// put error in string, print to stderr
fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() )
os.Exit( 1 ) // quit
}
}
// function to send message to third party and get response
func send( toSend string ) string {
// ip:port
// ip doesn't exist, implies localhost
service := "192.168.1.3:1202" // capture ip address and host
// "resolve" ip & host according to TCP rules
tcpAddr, err := net.ResolveTCPAddr( "tcp", service )
check( err ) // check error
// "dial" ( establish connection ) to destination ip & port
// according to TCP rules
// laddr = nil -> local address is localhost
conn, err := net.DialTCP( "tcp", nil, tcpAddr )
check( err ) // check error
defer conn.Close() // barring any error, still close connection
// convert user input to bytes and send over connection
_, err = conn.Write( []byte( toSend ) )
check( err ) // check error
var buf [512]byte // init byte array
// read from connection into byte array
// amount of bytes read stored in n
//n, err := conn.Read( buf[0:] )
n, err := conn.Read( buf[0:] )
check( err ) // check error
return string( buf[:n] ) // return only written bytes
}
// remove the first word from the string
// actually mad inefficient tbh, but it works
func parse( recv string ) string {
// split string over spaces
keywords := strings.Split( recv, " " )
var command string // declare return variable
// iterate over all but the first word
for _, keyword := range keywords[1:] {
command = command + keyword // add word to returnable
command = command + " " // separate by spaces
}
// remove the trailing space
command = command[:len( command ) - 1]
return command // return
}
// 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
}
// instantiate receipt variable
var recv string = string( buf[:n] )
// print recv'd message
// string() only works on byte SLICES so [:] is required
fmt.Println( "recv: ", recv )
// parse the input in some way
recv = parse( recv )
fmt.Println( "parse: ", recv ) // print parse
resp := send( recv ) // send message off
fmt.Println( "node: ", 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
}
}
}
func main() {
// ip:port
// ip doesn't exist, implies localhost
service := ":1201" // 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 )
}
}
+157
View File
@@ -0,0 +1,157 @@
// =============================================================================
// Auth: Alex Celani
// File: sentinel.go
// Revn: 06-22-2022 1.0
// Func: Receive message, play with it, send to a third place, receive
// response, send off to first place
//
// TODO: comment
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
// 05-05-2022: commented
// 05-10-2022: added argument 'n' to alter() for halving purposes
// changed passed value to alter()/forward() a slice
// 06-20-2022: changed name to reflect first draft of sentinel.go
//*06-22-2022: bug fixing and commenting
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close
// ListenTCP, listener.Accept
"os" // Exit, Stderr, Stdin, Args
"fmt" // Println, Fprintf
"strings" // ToLower, ToUpper
)
// quick error checking
func check( err error ){
// if user checks an error, it better be nil
if err != nil {
// put error in string, print to stderr
fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() )
os.Exit( 1 ) // quit
}
}
// function to send message to third party and get response
func send( toSend string ) string {
// 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
// "dial" ( establish connection ) to destination ip & port
// according to TCP rules
// laddr = nil -> local address is localhost
conn, err := net.DialTCP( "tcp", nil, tcpAddr )
check( err ) // check error
defer conn.Close() // barring any error, still close connection
// convert user input to bytes and send over connection
_, err = conn.Write( []byte( toSend ) )
check( err ) // check error
var buf [512]byte // init byte array
// read from connection into byte array
// amount of bytes read stored in n
//n, err := conn.Read( buf[0:] )
n, err := conn.Read( buf[0:] )
check( err ) // check error
return string( buf[:n] ) // return only written bytes
}
// remove the first word from the string
// actually mad inefficient tbh, but it works
func parse( recv string ) string {
// split string over spaces
keywords := strings.Split( recv, " " )
var command string // declare return variable
// iterate over all but the first word
for _, keyword := range keywords[1:] {
command = command + keyword // add word to returnable
command = command + " " // separate by spaces
}
// remove the trailing space
command = command[:len( command ) - 1]
return command // return
}
// 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
}
// instantiate receipt variable
var recv string = string( buf[:n] )
// print recv'd message
// string() only works on byte SLICES so [:] is required
fmt.Println( "recv: ", recv )
// parse the input in some way
recv = parse( recv )
fmt.Println( "parse: ", recv ) // print parse
resp := send( recv ) // send message off
fmt.Println( "node: ", 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
}
}
}
func main() {
// ip:port
// ip doesn't exist, implies localhost
service := ":1201" // 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 )
}
}
+9
View File
@@ -0,0 +1,9 @@
all: clean build
clean:
rm colonel sentinel
build:
go build colonel.go
go build sentinel.go
+78
View File
@@ -0,0 +1,78 @@
// =============================================================================
// Auth: Alex Celani
// File: colonel.go
// Revn: 06-22-2022 1.0
// Func: Send message to another machine and then receive a single
// response
//
// TODO: comment
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
// 06-20-2022: changed name to reflect first draft of colonel.go
//*06-22-2022: bug fixing and commenting
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read
"os" // Exit, Stdin, Stderr, Args
"fmt" // Println, Print, Fprintf
"bufio" // NewScanner, NewScanner.Scan,Text
"strings" // ToLower
)
// quick function to take user input
func input( ps1 string ) string {
fmt.Print( ps1 ) // print prompt
scanner := bufio.NewScanner( os.Stdin ) // link to stdin
scanner.Scan() // pull data
return strings.ToLower( scanner.Text() ) // return lower text
}
// 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
}
}
func main() {
// if len is not 2 ( ./name host:port ), print usage and quit
if len( os.Args ) != 2 {
fmt.Fprintf( os.Stderr, "Usage: %s host:port", os.Args[0] )
os.Exit( 1 )
}
service := os.Args[1] // capture ip address and host
// "resolve" ip & host according to TCP rules
tcpAddr, err := net.ResolveTCPAddr( "tcp", service )
check( err ) // check error
// "dial" ( establish connection ) to destination ip & port
// according to TCP rules
// laddr = nil -> local address is localhost
conn, err := net.DialTCP( "tcp", nil, tcpAddr )
check( err ) // check error
var in string = input( ">> " ) // get user input
// convert user input to bytes and send over connection
_, err = conn.Write( []byte( in ) )
check( err ) // check error
os.Exit( 0 ) // exeunt
}
+119
View File
@@ -0,0 +1,119 @@
// =============================================================================
// Auth: Alex Celani
// File: sentinel.go
// Revn: 06-22-2022 1.0
// Func: Receive message, play with it, send to a third place, receive
// response, send off to first place
//
// TODO: comment
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
// 05-05-2022: commented
// 05-10-2022: added argument 'n' to alter() for halving purposes
// changed passed value to alter()/forward() a slice
// 06-20-2022: changed name to reflect first draft of sentinel.go
//*06-22-2022: bug fixing and comments
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close
// ListenTCP, listener.Accept
"os" // Exit, Stderr, Stdin, Args
"fmt" // Println, Fprintf
"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 to stderr
fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() )
os.Exit( 1 ) // quit
}
}
// 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
}
// instantiate receipt variable
var recv string = string( buf[:n] )
// print recv'd message
// string() only works on byte SLICES so [:] is required
fmt.Println( "recv: ", recv )
// toggle pin on successful receipt
pin.Toggle()
}
}
// declare pin
var (
// Use mcu pin 10, corresponds to physical pin 19 on the pi
pin = rpio.Pin(10)
)
func main() {
// Open and map memory to access gpio, check for errors
// inline open gpio pin and check the error var
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 pin to output mode
pin.Output()
// ip:port
// ip doesn't exist, implies localhost
service := ":1201" // 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 )
}
}
+9
View File
@@ -0,0 +1,9 @@
all: clean build
clean:
rm colonel sentinel led
build:
go build colonel.go
go build sentinel.go
go build led.go
+55
View File
@@ -0,0 +1,55 @@
// =============================================================================
// Auth: Alex Celani
// File: boot.go
// Revn: 06-23-2022 0.1
// Func: Blink a light when the pi boots (or on login, but who cares)
//
// TODO: create
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 06-23-2022: init
//
// =============================================================================
package main
import (
"github.com/stianeikeland/go-rpio"
"os"
"time"
)
/*
Toggles a LED on physical pin 19 (mcu pin 10)
Connect a LED with resistor from pin 19 to ground.
*/
// Use mcu pin 10, corresponds to physical pin 19 on the pi
var pin rpio.Pin
func main() {
pin = rpio.Pin( 10 )
// Open and map memory to access gpio, check for errors
if err := rpio.Open(); err != nil {
os.Exit(1)
}
// Unmap gpio memory when done
defer rpio.Close()
// Set pin to output mode
pin.Output()
// Toggle pin 20 times
for i := 0; i < 4; i++ {
pin.Toggle()
time.Sleep(time.Second / 10)
}
}
+100
View File
@@ -0,0 +1,100 @@
// =============================================================================
// Auth: Alex Celani
// File: colonel.go
// Revn: 06-23-2022 1.1
// Func: Send message to another machine and then receive a single
// response. Extremely tight bounds, not robust at all
//
// TODO: comment
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
//*06-20-2022: changed name to reflect first draft of colonel.go
// 06-23-2022: made input an infinite loop
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read
"os" // Exit, Stdin, Stderr, Args
"fmt" // Println, Print, Fprintf
"bufio" // NewScanner, NewScanner.Scan,Text
"strings" // ToLower
"time" // Now, Sub
)
// quick function to take user input
func input( ps1 string ) string {
fmt.Print( ps1 ) // print prompt
scanner := bufio.NewScanner( os.Stdin ) // link to stdin
scanner.Scan() // pull data
return strings.ToLower( scanner.Text() ) // return lower text
}
// 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
}
}
func main() {
// if len is not 2 ( ./name host:port ), print usage and quit
if len( os.Args ) != 2 {
fmt.Fprintf( os.Stderr, "Usage: %s host:port", os.Args[0] )
os.Exit( 1 )
}
service := os.Args[1] // capture ip address and host
// "resolve" ip & host according to TCP rules
tcpAddr, err := net.ResolveTCPAddr( "tcp", service )
check( err ) // check error
// "dial" ( establish connection ) to destination ip & port
// according to TCP rules
// laddr = nil -> local address is localhost
conn, err := net.DialTCP( "tcp", nil, tcpAddr )
check( err ) // check error
for { // loop forever
var in string = input( ">> " ) // get user input
start := time.Now() // start round trip timer
// convert user input to bytes and send over connection
_, err = conn.Write( []byte( in ) )
check( err ) // check error
var buf [512]byte // init byte array
// read from connection into byte array
// amount of bytes read stored in n
//n, err := conn.Read( buf[0:] )
n, err := conn.Read( buf[:] )
check( err ) // check error
t := time.Now() // stop round trip timer
// convert read bytes into string and print
fmt.Println( "<<", string( buf[:n] ) )
fmt.Println() // newline to clean up a little
fmt.Println( "rtt: ", t.Sub( start ) ) // print time
}
os.Exit( 0 ) // exeunt
}
+5
View File
@@ -0,0 +1,5 @@
color;blue green red purple teal yellow white
status;on off
&&
color;blue
status;off
+33
View File
@@ -0,0 +1,33 @@
# ==============================================================================
# Auth: Alex Celani
# File: XXX.xx
# Revn: MM-DD-YYYY 0.0
# Func:
#
# TODO: create
# ==============================================================================
# CHANGE LOG
# ------------------------------------------------------------------------------
# MM-DD-YYYY: init
#
# ==============================================================================
literally
combine draft1 with draft2
sentinel:: your whole job, tbh, is to forward to the correct node
and there's really only one node
change stuff like "plant humid" into "plant.humid" or
"lamp color" into "lamp.color"
node:: move real parsing here
control RBG common anode led
node name -> led
fields ->^v led.color
^ on
^ off
v status
^v bright
v list
+217
View File
@@ -0,0 +1,217 @@
// =============================================================================
// 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 )
}
}
+156
View File
@@ -0,0 +1,156 @@
// =============================================================================
// Auth: Alex Celani
// File: sentinel.go
// Revn: 06-26-2022 1.2
// Func: Receive message, determine recipient, forward, get response,
// forward back
//
// TODO:
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
// 05-05-2022: commented
// 05-10-2022: added argument 'n' to alter() for halving purposes
// changed passed value to alter()/forward() a slice
// 06-20-2022: changed name to reflect first draft of sentinel.go
//*06-22-2022: bug fixing and commenting
// 06-23-2022: removed call to parse
// 06-26-2022: refined a new route() function to check for destination
// validity
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close
// ListenTCP, listener.Accept
"os" // Exit, Stderr, Stdin, Args
"fmt" // Println, Fprintf
"strings" // ToLower, ToUpper
)
// quick error checking
func check( err error ){
// if user checks an error, it better be nil
if err != nil {
// put error in string, print to stderr
fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() )
os.Exit( 1 ) // quit
}
}
// read the given message and route to the right endpoint
func route( recv []string ) bool {
return recv[1] == "led" // only option right now is led
}
// function to send message to third party and get response
func send( toSend string ) string {
// 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
// "dial" ( establish connection ) to destination ip & port
// according to TCP rules
// laddr = nil -> local address is localhost
conn, err := net.DialTCP( "tcp", nil, tcpAddr )
check( err ) // check error
defer conn.Close() // barring any error, still close connection
// convert user input to bytes and send over connection
_, err = conn.Write( []byte( toSend ) )
check( err ) // check error
var buf [512]byte // init byte array
// read from connection into byte array
// amount of bytes read stored in n
//n, err := conn.Read( buf[0:] )
n, err := conn.Read( buf[0:] )
check( err ) // check error
return string( buf[:n] ) // return only written bytes
}
// 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
}
// instantiate receipt variable
var recv string = string( buf[:n] )
// print recv'd message
// string() only works on byte SLICES so [:] is required
fmt.Println( "recv: ", recv )
keywords := strings.Split( recv, " " )
// parse the input in some way
var resp string // declare response variable
if route( keywords ) { // is destination valid?
resp = send( recv ) // send message and get response
// if user wants a list of endpoints
} else if keywords[1] == "list" {
resp = "led" // return list of endpoints
}
fmt.Println( "node: ", 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
}
}
}
func main() {
// ip:port
// ip doesn't exist, implies localhost
service := ":1201" // 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 )
}
}
+136
View File
@@ -0,0 +1,136 @@
# ====================================================================
# Auth: dodd
# File: sentinel.txt
# Revn: 05-10-2022 0.2
# Func: jot down some ideas about what the hub is and how it works
#
# TODO:
# ====================================================================
# CHANGE LOG
# --------------------------------------------------------------------
# 04-27-2022: init
# 05-10-2022: changed name from hub to sentinel
#
# ====================================================================
elevator pitch:: execute a command in terminal
terminal sends request to external hub device
hub pings one or more homemade smarthome devices
smarthome devices repond to hub
hub sends information back to terminal
terminal displays requested data
idea:: filter network model
"
/----\ /----\
/ v / v
|A| |B| |C| ( but with more C nodes )
^ / ^ /
\----/ \----/
"
terminal program is node A
hub is node B
other devices are nodes C
cat feeder
ball lamp
door monitor
etc
design::
how -> networking language
_python_ --> easy to write, will work
moves challenge to the project
_c/c++_ --> segmentation fault (core dumped). pass
_golang_ --> will need to learn networks pretty well
I'm already getting pretty good experience
with golang tho
_rust_ --> can't even get the fucking syntax to highlight
everything important is going to need to be hardcoded? ports,
ip addresses
probably would want to be connection-oriented protocol
TCP/IP
usage:: terminal commands
ask:: -> ask deviceC property
==> send message to deviceC asking for status report
on property
==> fail gracefully if property doesnt exist for given
device
--> ask cat-feeder fill example command
--> cat-feeder.fill 50% example response
--> ask ball-lamp soc example command
--> ball-lamp.soc 20% example response
tell:: -> tell deviceC command argument
==> send message to deviceC instructing it to commit
an action
==> fail gracefully if command doesn't exist for
device or if argument is invalid
--> tell door arm on example command
--> door.arm on example response
--> tell ball-lamp color blue example command
--> ball-lamp.color blue example response
list:: -> list [deviceC] -v
==> return a list of devices (deviceC not specified)
==> ping deviceC to see what properties it has and
their direction
==> including verbose -v flag shows devices and their
properties
==> including -v and a device is treated like only
specifying the device
--> list example command
--> door example response
ball-lamp
cat-feeder
office-light
--> list ball-lamp example command
--> ball-lamp example response
\--^ on
\--^ off
\--^ color
\-- white
\-- red
\-- green
\-- blue
\-- rainbow
\--^ bright[ness]
\-- [1 - 100]
\--v soc
\--v batt[ery]
--> list -v example command
--> door example response
\--^ arm
\--v status
\--v soc
\--v batt[ery]
ball-lamp
\--^ on
\--^ off
\--^ color
\-- white
\-- red
\-- green
\-- blue
\-- rainbow
\--^ bright[ness]
\-- [1 - 100]
\--v soc
\--v batt[ery]
(etc)
stats:: -> stats
==> request statistics from all online devices
===> uptime, battery, current status on all
properties, en masse
+9
View File
@@ -0,0 +1,9 @@
all: clean build
clean:
rm messagerA messagerB messagerC
build:
go build messagerA.go
go build messagerB.go
go build messagerC.go
BIN
View File
Binary file not shown.
+95
View File
@@ -0,0 +1,95 @@
// =============================================================================
// Auth: Alex Celani
// File: messagerA.go
// Revn: 05-04-2022 0.1
// Func: Send message to another machine and then receive a single
// response
//
// TODO: comment
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read
"os" // Exit, Stdin, Stderr, Args
"fmt" // Println, Print, Fprintf
"bufio" // NewScanner, NewScanner.Scan,Text
"strings" // ToLower
"time" // Now, Sub
)
// quick function to take user input
func input( ps1 string ) string {
fmt.Print( ps1 ) // print prompt
scanner := bufio.NewScanner( os.Stdin ) // link to stdin
scanner.Scan() // pull data
return strings.ToLower( scanner.Text() ) // return lower text
}
// 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
}
}
func main() {
// if len is not 2 ( ./name host:port ), print usage and quit
if len( os.Args ) != 2 {
fmt.Fprintf( os.Stderr, "Usage: %s host:port", os.Args[0] )
os.Exit( 1 )
}
service := os.Args[1] // capture ip address and host
// "resolve" ip & host according to TCP rules
tcpAddr, err := net.ResolveTCPAddr( "tcp", service )
check( err ) // check error
// "dial" ( establish connection ) to destination ip & port
// according to TCP rules
// laddr = nil -> local address is localhost
conn, err := net.DialTCP( "tcp", nil, tcpAddr )
check( err ) // check error
var in string = input( ">> " ) // get user input
start := time.Now() // start round trip timer
// convert user input to bytes and send over connection
_, err = conn.Write( []byte( in ) )
check( err ) // check error
var buf [512]byte // init byte array
// read from connection into byte array
// amount of bytes read stored in n
//n, err := conn.Read( buf[0:] )
n, err := conn.Read( buf[:] )
check( err ) // check error
t := time.Now() // stop round trip timer
// convert read bytes into string and print
fmt.Println( string( buf[:n] ) )
fmt.Println() // newline to clean up a little
fmt.Println( "rtt: ", t.Sub( start ) ) // print elapsed time
os.Exit( 0 ) // exeunt
}
BIN
View File
Binary file not shown.
+151
View File
@@ -0,0 +1,151 @@
// =============================================================================
// Auth: Alex Celani
// File: messagerB.go
// Revn: 05-10-2022 0.3
// Func: Receive message, play with it, send to a third place, receive
// response, send off to first place
//
// TODO: comment
// =============================================================================
// CHANGE LOG
// -----------------------------------------------------------------------------
// 05-04-2022: init
// 05-05-2022: commented
// 05-10-2022: added argument 'n' to alter() for halving purposes
// changed passed value to alter()/forward() a slice
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close
// ListenTCP, listener.Accept
"os" // Exit, Stderr, Stdin, Args
"fmt" // Println, Fprintf
"strings" // ToLower, ToUpper
)
// quick error checking
func check( err error ){
// if user checks an error, it better be nil
if err != nil {
// put error in string, print to stderr
fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() )
os.Exit( 1 ) // quit
}
}
// function to send message to third party and get response
func quickSend( send string ) string {
// 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
// "dial" ( establish connection ) to destination ip & port
// according to TCP rules
// laddr = nil -> local address is localhost
conn, err := net.DialTCP( "tcp", nil, tcpAddr )
check( err ) // check error
defer conn.Close() // barring any error, still close connection
// convert user input to bytes and send over connection
_, err = conn.Write( []byte( send ) )
check( err ) // check error
var buf [512]byte // init byte array
// read from connection into byte array
// amount of bytes read stored in n
//n, err := conn.Read( buf[0:] )
n, err := conn.Read( buf[0:] )
check( err ) // check error
return string( buf[:n] ) // return only written bytes
}
// function to change received message before passing it along
func alter( recv []byte, n int ) string {
var send string = string( recv[:n/2] )
send = strings.ToUpper( send )
fmt.Println( "to c: ", send )
return send
}
// function to convert message to string before forwarding
func forward( recv []byte ) string {
return string( recv[:] )
}
// 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[:] ) )
// var send string = string( buf[:n/2] )
// send = strings.ToUpper( send )
send := alter( buf[:], n ) // send message to get changed
// send := forward( buf[:] )
recv := quickSend( send ) // send message off
fmt.Println( "из c: ", recv ) // print response
// write that response back to original client
_, err = conn.Write( []byte( recv ) )
if err != nil { // erroring on write will simply leave the
return // function so it can start again later
}
}
}
func main() {
// ip:port
// ip doesn't exist, implies localhost
service := ":1201" // 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 )
}
}
BIN
View File
Binary file not shown.
+118
View File
@@ -0,0 +1,118 @@
// =============================================================================
// Auth: Alex Celani
// File: messagerC.go
// Revn: 05-10-2022 0.3
// Func:
//
// TODO: create
// =============================================================================
// 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
//
// =============================================================================
package main
import (
"net" // ResolveTCPAddr, conn.Write,Read,Close
// ListenTCP, listener.Accept
"os" // Args, Stderr, Exit
"fmt" // Fprintf, Println
"strings" // ToLower
)
// 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
}
}
// function to change received message before passing it along
func alter( recv []byte ) string {
var send string = string( recv[:] )
send = send + " " + send
send = strings.ToLower( send )
return send
}
// function to convert message to string before forwarding
func forward( recv []byte ) string {
return string( recv[:] )
}
// 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] ) )
send := alter( buf[:n] ) // send message ot get changed
// send := forward( buf[:] )
// write that response back to original client
_, err = conn.Write( []byte( send ) )
if err != nil { // erroring on write will simply leave the
return // function so it can start again later
}
fmt.Println( "sent: ", send ) // print response
}
}
func main() {
// 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 )
}
}