gobot.io/x/gobot@v1.16.0/master.go (about)

     1  package gobot
     2  
     3  import (
     4  	"os"
     5  	"os/signal"
     6  	"sync/atomic"
     7  
     8  	multierror "github.com/hashicorp/go-multierror"
     9  )
    10  
    11  // JSONMaster is a JSON representation of a Gobot Master.
    12  type JSONMaster struct {
    13  	Robots   []*JSONRobot `json:"robots"`
    14  	Commands []string     `json:"commands"`
    15  }
    16  
    17  // NewJSONMaster returns a JSONMaster given a Gobot Master.
    18  func NewJSONMaster(gobot *Master) *JSONMaster {
    19  	jsonGobot := &JSONMaster{
    20  		Robots:   []*JSONRobot{},
    21  		Commands: []string{},
    22  	}
    23  
    24  	for command := range gobot.Commands() {
    25  		jsonGobot.Commands = append(jsonGobot.Commands, command)
    26  	}
    27  
    28  	gobot.robots.Each(func(r *Robot) {
    29  		jsonGobot.Robots = append(jsonGobot.Robots, NewJSONRobot(r))
    30  	})
    31  	return jsonGobot
    32  }
    33  
    34  // Master is the main type of your Gobot application and contains a collection of
    35  // Robots, API commands that apply to the Master, and Events that apply to the Master.
    36  type Master struct {
    37  	robots  *Robots
    38  	trap    func(chan os.Signal)
    39  	AutoRun bool
    40  	running atomic.Value
    41  	Commander
    42  	Eventer
    43  }
    44  
    45  // NewMaster returns a new Gobot Master
    46  func NewMaster() *Master {
    47  	m := &Master{
    48  		robots: &Robots{},
    49  		trap: func(c chan os.Signal) {
    50  			signal.Notify(c, os.Interrupt)
    51  		},
    52  		AutoRun:   true,
    53  		Commander: NewCommander(),
    54  		Eventer:   NewEventer(),
    55  	}
    56  	m.running.Store(false)
    57  	return m
    58  }
    59  
    60  // Start calls the Start method on each robot in its collection of robots. On
    61  // error, call Stop to ensure that all robots are returned to a sane, stopped
    62  // state.
    63  func (g *Master) Start() (err error) {
    64  	if rerr := g.robots.Start(!g.AutoRun); rerr != nil {
    65  		err = multierror.Append(err, rerr)
    66  		return
    67  	}
    68  
    69  	g.running.Store(true)
    70  
    71  	if g.AutoRun {
    72  		c := make(chan os.Signal, 1)
    73  		g.trap(c)
    74  
    75  		// waiting for interrupt coming on the channel
    76  		<-c
    77  
    78  		// Stop calls the Stop method on each robot in its collection of robots.
    79  		g.Stop()
    80  	}
    81  
    82  	return err
    83  }
    84  
    85  // Stop calls the Stop method on each robot in its collection of robots.
    86  func (g *Master) Stop() (err error) {
    87  	if rerr := g.robots.Stop(); rerr != nil {
    88  		err = multierror.Append(err, rerr)
    89  	}
    90  
    91  	g.running.Store(false)
    92  	return
    93  }
    94  
    95  // Running returns if the Master is currently started or not
    96  func (g *Master) Running() bool {
    97  	return g.running.Load().(bool)
    98  }
    99  
   100  // Robots returns all robots associated with this Gobot Master.
   101  func (g *Master) Robots() *Robots {
   102  	return g.robots
   103  }
   104  
   105  // AddRobot adds a new robot to the internal collection of robots. Returns the
   106  // added robot
   107  func (g *Master) AddRobot(r *Robot) *Robot {
   108  	*g.robots = append(*g.robots, r)
   109  	return r
   110  }
   111  
   112  // Robot returns a robot given name. Returns nil if the Robot does not exist.
   113  func (g *Master) Robot(name string) *Robot {
   114  	for _, robot := range *g.Robots() {
   115  		if robot.Name == name {
   116  			return robot
   117  		}
   118  	}
   119  	return nil
   120  }