github.com/simpleiot/simpleiot@v0.18.3/client/file.go (about) 1 package client 2 3 import ( 4 "crypto/md5" 5 "fmt" 6 "log" 7 8 "encoding/base64" 9 10 "github.com/nats-io/nats.go" 11 "github.com/simpleiot/simpleiot/data" 12 ) 13 14 // File represents a file that a user uploads or is present in some location 15 type File struct { 16 ID string `node:"id"` 17 Parent string `node:"parent"` 18 Description string `point:"description"` 19 Name string `point:"name"` 20 Data string `point:"data"` 21 Size string `point:"size"` 22 Binary bool `point:"binary"` 23 Hash string `point:"hash"` 24 } 25 26 // GetContents reads the file contents and does any decoding necessary if it is a binary file 27 func (f *File) GetContents() ([]byte, error) { 28 var ret []byte 29 var err error 30 31 if f.Binary { 32 ret, err = base64.StdEncoding.DecodeString(f.Data) 33 } else { 34 ret = []byte(f.Data) 35 } 36 37 return ret, err 38 } 39 40 // FileClient is used to manage files 41 type FileClient struct { 42 nc *nats.Conn 43 config File 44 stop chan struct{} 45 newPoints chan NewPoints 46 newEdgePoints chan NewPoints 47 } 48 49 // NewFileClient ... 50 func NewFileClient(nc *nats.Conn, config File) Client { 51 return &FileClient{ 52 nc: nc, 53 config: config, 54 stop: make(chan struct{}), 55 newPoints: make(chan NewPoints), 56 newEdgePoints: make(chan NewPoints), 57 } 58 } 59 60 // Run the main logic for the file client 61 func (f *FileClient) Run() error { 62 63 exitFileClient: 64 65 for { 66 select { 67 case <-f.stop: 68 break exitFileClient 69 70 case points := <-f.newPoints: 71 // Update local configuration 72 err := data.MergePoints(points.ID, points.Points, &f.config) 73 if err != nil { 74 return fmt.Errorf("merging points: %w", err) 75 } 76 77 for _, p := range points.Points { 78 if p.Type == data.PointTypeData { 79 // update md5 hash 80 var fileData []byte 81 82 fileData, err := f.config.GetContents() 83 if err != nil { 84 log.Println("Error decoding file contents: ", err) 85 break 86 } 87 88 hash := md5.Sum(fileData) 89 hashS := fmt.Sprintf("%x", hash) 90 91 pts := data.Points{ 92 {Type: data.PointTypeHash, Text: hashS}, 93 {Type: data.PointTypeSize, Value: float64(len(fileData))}, 94 } 95 96 e := SendNodePoints(f.nc, f.config.ID, pts, true) 97 if e != nil { 98 log.Println("File: error sending hash point: ", err) 99 } 100 } 101 } 102 } 103 } 104 105 return nil 106 } 107 108 // Stop stops the File Client 109 func (f *FileClient) Stop(error) { 110 close(f.stop) 111 } 112 113 // Points is called when the client's node points are updated 114 func (f *FileClient) Points(nodeID string, points []data.Point) { 115 f.newPoints <- NewPoints{ 116 ID: nodeID, 117 Points: points, 118 } 119 } 120 121 // EdgePoints is called when the client's node edge points are updated 122 func (f *FileClient) EdgePoints( 123 _ string, _ string, _ []data.Point, 124 ) { 125 // Do nothing 126 }