github.com/martinohmann/rfoutlet@v1.2.1-0.20220707195255-8a66aa411105/cmd/sniff.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/martinohmann/rfoutlet/internal/config"
     8  	"github.com/martinohmann/rfoutlet/pkg/gpio"
     9  	log "github.com/sirupsen/logrus"
    10  	"github.com/spf13/cobra"
    11  )
    12  
    13  func NewSniffCommand() *cobra.Command {
    14  	options := &SniffOptions{
    15  		Pin: config.DefaultReceivePin,
    16  	}
    17  
    18  	cmd := &cobra.Command{
    19  		Use:   "sniff",
    20  		Short: "Sniff codes sent out to remote controlled outlets",
    21  		Long:  "The sniff command can be used to sniff codes sent out to remote controlled outlets.",
    22  		RunE: func(cmd *cobra.Command, _ []string) error {
    23  			return options.Run(cmd)
    24  		},
    25  	}
    26  
    27  	options.AddFlags(cmd)
    28  
    29  	return cmd
    30  }
    31  
    32  type SniffOptions struct {
    33  	Pin uint
    34  }
    35  
    36  func (o *SniffOptions) AddFlags(cmd *cobra.Command) {
    37  	cmd.Flags().UintVar(&o.Pin, "pin", o.Pin, "gpio pin to sniff on")
    38  }
    39  
    40  func (o *SniffOptions) Run(cmd *cobra.Command) error {
    41  	device, err := openGPIODevice(cmd)
    42  	if err != nil {
    43  		return err
    44  	}
    45  	defer device.Close()
    46  
    47  	receiver, err := gpio.NewReceiver(device.Chip, int(o.Pin))
    48  	if err != nil {
    49  		return fmt.Errorf("failed to create gpio receiver: %v", err)
    50  	}
    51  	defer receiver.Close()
    52  
    53  	ctx, cancel := context.WithCancel(context.Background())
    54  	defer cancel()
    55  
    56  	go handleSignals(cancel)
    57  
    58  	for {
    59  		select {
    60  		case res := <-receiver.Receive():
    61  			log.WithFields(log.Fields{
    62  				"pulseLength": res.PulseLength,
    63  				"protocol":    res.Protocol,
    64  				"bitlength":   res.BitLength,
    65  			}).Infof("received code %d", res.Code)
    66  		case <-ctx.Done():
    67  			return nil
    68  		}
    69  	}
    70  }