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  }