github.com/simpleiot/simpleiot@v0.18.3/client/example_manager_test.go (about) 1 package client_test 2 3 import ( 4 "log" 5 6 "github.com/nats-io/nats.go" 7 "github.com/simpleiot/simpleiot/client" 8 "github.com/simpleiot/simpleiot/data" 9 "github.com/simpleiot/simpleiot/server" 10 ) 11 12 // exNode is decoded data from the client node 13 type exNode struct { 14 ID string `node:"id"` 15 Parent string `node:"parent"` 16 Description string `point:"description"` 17 Port int `point:"port"` 18 Role string `edgepoint:"role"` 19 } 20 21 // exNodeClient contains the logic for this client 22 type exNodeClient struct { 23 nc *nats.Conn 24 config exNode 25 stop chan struct{} 26 stopped chan struct{} 27 newPoints chan client.NewPoints 28 newEdgePoints chan client.NewPoints 29 chGetConfig chan chan exNode 30 } 31 32 // newExNodeClient is passed to the NewManager() function call -- when 33 // a new node is detected, the Manager will call this function to construct 34 // a new client. 35 func newExNodeClient(nc *nats.Conn, config exNode) client.Client { 36 return &exNodeClient{ 37 nc: nc, 38 config: config, 39 stop: make(chan struct{}), 40 newPoints: make(chan client.NewPoints), 41 newEdgePoints: make(chan client.NewPoints), 42 } 43 } 44 45 // Run the main logic for this client and blocks until stopped 46 func (tnc *exNodeClient) Run() error { 47 for { 48 select { 49 case <-tnc.stop: 50 close(tnc.stopped) 51 return nil 52 case pts := <-tnc.newPoints: 53 err := data.MergePoints(pts.ID, pts.Points, &tnc.config) 54 if err != nil { 55 log.Println("error merging new points:", err) 56 } 57 log.Printf("New config: %+v\n", tnc.config) 58 case pts := <-tnc.newEdgePoints: 59 err := data.MergeEdgePoints(pts.ID, pts.Parent, pts.Points, &tnc.config) 60 if err != nil { 61 log.Println("error merging new points:", err) 62 } 63 case ch := <-tnc.chGetConfig: 64 ch <- tnc.config 65 } 66 } 67 } 68 69 // Stop sends a signal to the Run function to exit 70 func (tnc *exNodeClient) Stop(_ error) { 71 close(tnc.stop) 72 } 73 74 // Points is called by the Manager when new points for this 75 // node are received. 76 func (tnc *exNodeClient) Points(id string, points []data.Point) { 77 tnc.newPoints <- client.NewPoints{id, "", points} 78 } 79 80 // EdgePoints is called by the Manager when new edge points for this 81 // node are received. 82 func (tnc *exNodeClient) EdgePoints(id, parent string, points []data.Point) { 83 tnc.newEdgePoints <- client.NewPoints{id, parent, points} 84 } 85 86 func ExampleNewManager() { 87 nc, root, stop, err := server.TestServer() 88 89 if err != nil { 90 log.Println("Error starting test server:", err) 91 } 92 93 defer stop() 94 95 testConfig := testNode{"", "", "fancy test node", 8118, "admin"} 96 97 // Convert our custom struct to a data.NodeEdge struct 98 ne, err := data.Encode(testConfig) 99 if err != nil { 100 log.Println("Error encoding node:", err) 101 } 102 103 ne.Parent = root.ID 104 105 // hydrate database with test node 106 err = client.SendNode(nc, ne, "test") 107 108 if err != nil { 109 log.Println("Error sending node:", err) 110 } 111 112 // Create a new manager for nodes of type "testNode". The manager looks for new nodes under the 113 // root and if it finds any, it instantiates a new client, and sends point updates to it 114 m := client.NewManager(nc, newExNodeClient, nil) 115 err = m.Run() 116 117 if err != nil { 118 log.Println("Error running:", err) 119 } 120 121 // Now any updates to the node will trigger Points/EdgePoints callbacks in the above client 122 }