github.com/simpleiot/simpleiot@v0.18.3/node/onewire-io.go (about) 1 package node 2 3 import ( 4 "fmt" 5 goio "io" 6 "log" 7 "os" 8 "strconv" 9 "strings" 10 "time" 11 12 "github.com/nats-io/nats.go" 13 "github.com/simpleiot/simpleiot/client" 14 "github.com/simpleiot/simpleiot/data" 15 ) 16 17 type oneWireIO struct { 18 nc *nats.Conn 19 ioNode *oneWireIONode 20 path string 21 sub *nats.Subscription 22 lastSent time.Time 23 } 24 25 func newOneWireIO(nc *nats.Conn, node *oneWireIONode, chPoint chan<- pointWID) (*oneWireIO, error) { 26 io := &oneWireIO{ 27 nc: nc, 28 path: fmt.Sprintf("/sys/bus/w1/devices/%v/temperature", node.id), 29 ioNode: node, 30 } 31 32 var err error 33 io.sub, err = nc.Subscribe("p."+io.ioNode.nodeID, func(msg *nats.Msg) { 34 points, err := data.PbDecodePoints(msg.Data) 35 if err != nil { 36 // FIXME, send over channel 37 log.Println("Error decoding node data:", err) 38 return 39 } 40 41 for _, p := range points { 42 chPoint <- pointWID{io.ioNode.nodeID, p} 43 } 44 }) 45 46 if err != nil { 47 return nil, err 48 } 49 50 return io, nil 51 } 52 53 // Stop io 54 func (io *oneWireIO) stop() { 55 if io.sub != nil { 56 err := io.sub.Unsubscribe() 57 if err != nil { 58 log.Println("Error unsubscribing from IO:", err) 59 } 60 } 61 } 62 63 func (io *oneWireIO) point(p data.Point) error { 64 // handle IO changes 65 switch p.Type { 66 case data.PointTypeID: 67 io.ioNode.id = p.Text 68 case data.PointTypeDescription: 69 io.ioNode.description = p.Text 70 case data.PointTypeUnits: 71 io.ioNode.units = p.Text 72 case data.PointTypeValue: 73 io.ioNode.value = p.Value 74 case data.PointTypeDisabled: 75 io.ioNode.disabled = data.FloatToBool(p.Value) 76 case data.PointTypeErrorCount: 77 io.ioNode.errorCount = int(p.Value) 78 case data.PointTypeErrorCountReset: 79 io.ioNode.errorCountReset = data.FloatToBool(p.Value) 80 if io.ioNode.errorCountReset { 81 p := data.Points{ 82 {Type: data.PointTypeErrorCount, Value: 0}, 83 {Type: data.PointTypeErrorCountReset, Value: 0}, 84 } 85 86 err := client.SendNodePoints(io.nc, io.ioNode.nodeID, p, true) 87 if err != nil { 88 log.Println("Send point error:", err) 89 } 90 } 91 92 default: 93 log.Println("1-wire: unhandled io point:", p) 94 } 95 96 return nil 97 } 98 99 func (io *oneWireIO) read() error { 100 if io.ioNode.disabled { 101 return nil 102 } 103 104 d, err := os.ReadFile(io.path) 105 if err != nil { 106 return err 107 } 108 109 if len(d) <= 0 { 110 return goio.EOF 111 } 112 113 vRaw, err := strconv.Atoi(strings.TrimSpace(string(d))) 114 if err != nil { 115 return err 116 } 117 118 v := float64(vRaw) / 1000 119 120 if io.ioNode.units == "F" { 121 v = v*1.8 + 32 122 } 123 124 if v != io.ioNode.value || time.Since(io.lastSent) > time.Minute*10 { 125 io.ioNode.value = v 126 err = client.SendNodePoint(io.nc, io.ioNode.nodeID, data.Point{ 127 Type: data.PointTypeValue, 128 Value: v, 129 }, false) 130 io.lastSent = time.Now() 131 } 132 133 return err 134 }