func NewLedController(conn *ninja.Connection) (*LedController, error) {

	s, err := util.GetLEDConnection()

	if err != nil {
		log.Fatalf("Failed to get connection to LED matrix: %s", err)
	}

	// Send a blank image to the led matrix
	util.WriteLEDMatrix(image.NewRGBA(image.Rect(0, 0, 16, 16)), s)

	controller := &LedController{
		conn:          conn,
		pairingLayout: ui.NewPairingLayout(),
		serial:        s,
		waiting:       make(chan bool),
	}

	conn.MustExportService(controller, "$node/"+config.Serial()+"/led-controller", &model.ServiceAnnouncement{
		Schema: "/service/led-controller",
	})

	conn.MustExportService(controller, "$home/led-controller", &model.ServiceAnnouncement{
		Schema: "/service/led-controller",
	})

	if config.HasString("siteId") {
		log.Infof("Have a siteId, checking if homecloud is running")
		// If we have just started, and we have a site, and homecloud is running... enable control!
		go func() {
			siteModel := conn.GetServiceClient("$home/services/SiteModel")
			for {

				if controller.commandReceived {
					log.Infof("Command has been received, stopping search for homecloud.")
					break
				}

				err := siteModel.Call("fetch", config.MustString("siteId"), nil, time.Second*5)

				if err != nil {
					log.Infof("Fetched site to enableControl. Got err: %s", err)
				} else if err == nil && !controller.commandReceived {
					controller.EnableControl()
					break
				}
				time.Sleep(time.Second * 5)
			}
		}()
	}

	return controller, nil
}
예제 #2
0
func (c *client) pair() error {

	var boardType string
	if config.HasString("boardType") {
		boardType = config.MustString("boardType")
	} else {
		boardType = fmt.Sprintf("custom-%s-%s", runtime.GOOS, runtime.GOARCH)
	}

	log.Debugf("Board type: %s", boardType)

	client := &http.Client{
		Timeout: time.Second * 60, // It's 20sec on the server so this *should* be ok
	}

	if config.Bool(false, "cloud", "allowSelfSigned") {
		log.Warningf("Allowing self-signed certificate (should only be used to connect to development cloud)")
		client.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
	}

	var creds *credentials

	for {
		url := fmt.Sprintf(config.MustString("cloud", "activation"), config.Serial(), getLocalIP(), boardType)

		log.Debugf("Activating at URL: %s", url)

		var err error
		creds, err = activate(client, url)

		if err != nil {
			log.Warningf("Activation error : %s", err)
			log.Warningf("Sleeping for 3sec")
			time.Sleep(time.Second * 3)
		} else if creds != nil {
			break
		}
	}

	log.Infof("Got credentials. User: %s", creds.UserID)

	return saveCreds(creds)
}
예제 #3
0
func (c *client) start() {

	if !config.IsPaired() {
		log.Infof("Client is unpaired. Attempting to pair.")
		if err := c.pair(); err != nil {
			log.Fatalf("An error occurred while pairing. Restarting. error: %s", err)
		}

		log.Infof("Pairing was successful.")
		// We reload the config so the creds can be picked up
		config.MustRefresh()

		if !config.IsPaired() {
			log.Fatalf("Pairing appeared successful, but I did not get the credentials. Restarting.")
		}

	}

	log.Infof("Client is paired. User: %s", config.MustString("userId"))

	if !config.NoCloud() {

		mesh, err := refreshMeshInfo()

		if err == errorUnauthorised {
			log.Warningf("UNAUTHORISED! Unpairing.")
			c.unpair()
			return
		}

		if err != nil {
			log.Warningf("Failed to refresh mesh info: %s", err)
		} else {
			log.Debugf("Got mesh info: %+v", mesh)
		}

		config.MustRefresh()

		if !config.HasString("masterNodeId") {
			log.Warningf("We don't have any mesh information. Which is unlikely. But we can't do anything without it, so restarting client.")
			time.Sleep(time.Second * 10)
			os.Exit(0)
		}

	}

	if config.MustString("masterNodeId") == config.Serial() {
		log.Infof("I am the master, starting HomeCloud.")

		cmd := exec.Command("start", "sphere-homecloud")
		cmd.Output()
		go c.exportNodeDevice()

		c.master = true
	} else {
		log.Infof("I am a slave. The master is %s", config.MustString("masterNodeId"))

		// TODO: Remove this when we are running drivers on slaves
		cmd := exec.Command("stop", "sphere-director")
		cmd.Output()

		c.masterReceiveTimeout = time.AfterFunc(orphanTimeout, func() {
			c.setOrphaned()
		})

	}

	go func() {

		log.Infof("Starting search for peers")

		for {
			c.findPeers()
			time.Sleep(time.Second * 30)
		}
	}()
}
func NewPaneLayout(fakeGestures bool, conn *ninja.Connection) (*PaneLayout, chan (bool)) {

	// Wait till we're paired and have a site
	for {
		config.MustRefresh()
		if config.HasString("siteId") {
			break
		}
		time.Sleep(time.Second * 2)
	}

	go startSearchTasks(conn)

	pane := &PaneLayout{
		gestures: &Tick{
			name: "Gestures/sec",
		},
		wake: make(chan bool),
		log:  logger.GetLogger("PaneLayout"),
	}
	pane.gestures.start()

	if !fakeGestures {
		g, err := gestic.Open()

		if err != nil {
			pane.log.Warningf("Error enabling gestures: %s\n", err)
		} else {
			//defer g.Close()

			pane.log.Infof("Succesfully connected to GestIC device")

			gestures := g.DataStream()

			go func() {
				for gesture := range gestures {
					//pane.log.Debugf("Gesture latency: %s", time.Since(gesture.Time).String())
					go pane.OnGesture(&gesture)
				}
			}()
		}
	}

	// Check for sleep timeout
	go func() {
		for {
			time.Sleep(time.Millisecond * 50)
			if pane.awake && time.Since(pane.lastGesture) > sleepTimeout {
				pane.Sleep()
			}
		}
	}()

	/*if fakeGestures {
		go func() {
			for {
				time.Sleep(time.Millisecond * 5000)
				gesture := gestic.NewGestureData()
				gesture.Gesture.GestureVal = 2
				pane.OnGesture(gesture)
			}
		}()

		go func() {
			for {
				time.Sleep(time.Millisecond * 10)
				gesture := gestic.NewGestureData()
				gesture.Coordinates.X = 100
				gesture.Coordinates.Y = 100
				gesture.Coordinates.Z = 100
				pane.OnGesture(gesture)
			}
		}()
	}*/

	return pane, pane.wake
}