server.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package main
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "encoding/base64"
  6. "encoding/binary"
  7. "fmt"
  8. "github.com/imroc/req"
  9. "net"
  10. "time"
  11. )
  12. type serverLog struct {
  13. ID uint16 `json:"id"`
  14. Stamp time.Time `json:"stamp"`
  15. Log string `json:"log"`
  16. }
  17. type serverMsg struct {
  18. id uint16
  19. acc uint32
  20. light bool
  21. }
  22. var serverLogs = []serverLog{{0, time.Now(), "Server started..."}}
  23. func sendData(msg *serverMsg) {
  24. defer logPanic()
  25. c := config.Influx
  26. if c == nil {
  27. return
  28. }
  29. var light int
  30. if light = 0; msg.light { light = 1 }
  31. now := time.Now().UnixNano()
  32. data := fmt.Sprintf("accelerometer,board=%d value=%d %d\n", msg.id, msg.acc, now)
  33. data += fmt.Sprintf("light,board=%d value=%d %d", msg.id, light, now)
  34. auth := base64.StdEncoding.EncodeToString([]byte(c.Username+":"+c.Password))
  35. head := req.Header{
  36. "Authorization": "Basic " + auth,
  37. }
  38. r, err := req.Post(fmt.Sprintf("http://%s/write?db=%s", c.Domain, c.Database), head, data)
  39. if err != nil {
  40. errCheckPanic(err, "Failed send to influx server")
  41. }
  42. if r.Response().StatusCode > 300 {
  43. fmt.Printf("Influx server returned code %d\n", r.Response().StatusCode)
  44. }
  45. }
  46. func serveConnection(conn net.Conn) {
  47. defer logPanic()
  48. defer fmt.Printf("Connection closed %s\n", conn.RemoteAddr().String())
  49. defer conn.Close()
  50. fmt.Printf("Connection from %s\n", conn.RemoteAddr().String())
  51. buf := make([]byte, 4)
  52. for {
  53. _, err := conn.Read(buf)
  54. errCheckPanic(err, "Connection failed with %s", conn.RemoteAddr().String())
  55. id := binary.LittleEndian.Uint16(buf[:2])
  56. board, ok := config.Boards[id]
  57. if !ok {
  58. fmt.Printf("Connection with ID %d is not registerd\n", id)
  59. break
  60. }
  61. board.LastSeen = time.Now()
  62. msglen := binary.LittleEndian.Uint16(buf[2:])
  63. fmt.Printf("Connection from ID %d message length %d\n %x\n", id, msglen, buf)
  64. payload := make([]byte, msglen)
  65. _, err = conn.Read(payload)
  66. errCheckPanic(err, "Connection failed %s device #%d", conn.RemoteAddr().String(), id)
  67. fmt.Printf("Payload: %x\n", payload)
  68. message := make([]byte, msglen-16)
  69. block, err := aes.NewCipher(board.KEY)
  70. errCheckPanic(err, "Decryption failed %s device #%d", conn.RemoteAddr().String(), id)
  71. mode := cipher.NewCBCDecrypter(block, payload[:16])
  72. mode.CryptBlocks(message, payload[16:])
  73. fmt.Printf("Message: %x\n", message)
  74. msg := serverMsg{
  75. id,
  76. binary.LittleEndian.Uint32(message[:4]),
  77. message[4] != 0x00,
  78. }
  79. sendData(&msg)
  80. smessage := fmt.Sprintf("ACC: %d, LIGHT: %t", msg.acc, msg.light)
  81. serverLogs = append([]serverLog{{id, board.LastSeen, smessage}}, serverLogs...)
  82. if len(serverLogs) > 150 {
  83. serverLogs = serverLogs[:len(serverLogs)-1]
  84. }
  85. fmt.Printf("Message: %x\n%s\n", message, smessage)
  86. }
  87. }
  88. func serve(address string) {
  89. ln, err := net.Listen("tcp", address)
  90. errCheckExit(err,"Failed accept connection")
  91. defer ln.Close()
  92. fmt.Printf("Service socket ready at %s\n", address)
  93. for {
  94. conn, err := ln.Accept()
  95. errCheckExit(err,"Failed accept connection %s", conn.RemoteAddr().String())
  96. go serveConnection(conn)
  97. }
  98. }