// init runs before anything else, and loads the images for the LED pane
func init() {
	images = make(map[string]util.Image)
	images["logo"] = util.LoadImage(util.ResolveImagePath("twitter-bird.png"))
	images["animated"] = util.LoadImage(util.ResolveImagePath("twitter-animated.gif"))
	images["error"] = util.LoadImage(util.ResolveImagePath("errorX.gif"))
	images["at"] = util.LoadImage(util.ResolveImagePath("at.gif"))
	images["tick"] = util.LoadImage(util.ResolveImagePath("tick.gif"))
}
func NewWeatherPane(conn *ninja.Connection) *WeatherPane {

	pane := &WeatherPane{
		siteModel: conn.GetServiceClient("$home/services/SiteModel"),
		image:     util.LoadImage(util.ResolveImagePath("weather/loading.gif")),
	}

	pane.tempTimeout = time.AfterFunc(0, func() {
		pane.temperature = false
	})

	if !enableWeatherPane {
		return pane
	}

	var err error
	pane.weather, err = owm.NewForecast("C")
	if err != nil {
		log.Warningf("Failed to load weather api:", err)
		enableWeatherPane = false
	} else {
		go pane.GetWeather()
	}

	return pane
}
func NewPairingLayout() *PairingLayout {

	layout := &PairingLayout{
		log:          logger.GetLogger("PaneLayout"),
		progressPane: NewUpdateProgressPane(util.ResolveImagePath("update-progress.gif"), util.ResolveImagePath("update-loop.gif")),
	}
	layout.ShowIcon(config.String("spinner-blue.gif", "led.loadingImage"))

	/*	go func() {
		time.Sleep(time.Second * 5)

		c, _ := colorful.Hex("#517AB8")

		layout.ShowColor(c)

	}()*/

	/*go func() {
		progress := 0.0
		for {
			time.Sleep(time.Millisecond * 30)
			layout.ShowUpdateProgress(progress)
			progress = progress + 0.01
			if progress >= 1 {
				layout.ShowUpdateProgress(1)
				break
			}
		}
	}()*/

	/*go func() {
		time.Sleep(time.Second * 1)
		layout.ShowDrawing()
		for {
			time.Sleep(time.Millisecond * 2)
			update := []uint8{uint8(rand.Intn(16)), uint8(rand.Intn(16)), uint8(rand.Intn(255)), uint8(rand.Intn(255)), uint8(rand.Intn(255))}
			frames := [][]uint8{update}
			layout.Draw(&frames)
		}
	}()*/

	return layout
}
func (p *WeatherPane) GetWeather() {

	enableWeatherPane = false

	for {
		site := &model.Site{}
		err := p.siteModel.Call("fetch", config.MustString("siteId"), site, time.Second*5)

		if err == nil && (site.Longitude != nil || site.Latitude != nil) {
			p.site = site
			globalSite = site

			if site.TimeZoneID != nil {
				if timezone, err = time.LoadLocation(*site.TimeZoneID); err != nil {
					log.Warningf("error while setting timezone (%s): %s", *site.TimeZoneID, err)
					timezone, _ = time.LoadLocation("Local")
				}
			}
			break
		}

		log.Infof("Failed to get site, or site has no location.")

		time.Sleep(time.Second * 2)
	}

	for {

		p.weather.DailyByCoordinates(
			&owm.Coordinates{
				Longitude: *p.site.Longitude,
				Latitude:  *p.site.Latitude,
			},
			1,
		)

		if len(p.weather.List) > 0 {

			filename := util.ResolveImagePath("weather/" + p.weather.List[0].Weather[0].Icon + ".png")

			if _, err := os.Stat(filename); os.IsNotExist(err) {
				enableWeatherPane = false
				fmt.Printf("Couldn't load image for weather: %s", filename)
				bugsnag.Notify(fmt.Errorf("Unknown weather icon: %s", filename), p.weather)
			} else {
				p.image = util.LoadImage(filename)
				enableWeatherPane = true
			}
		}

		time.Sleep(weatherUpdateInterval)

	}

}
func NewPairingCodePane(text string) *PairingCodePane {

	img := image.NewRGBA(image.Rect(0, 0, 16, 16))

	width := O4b03b.Font.DrawString(img, 0, 0, text, color.Black)
	//log.Printf("Text '%s' width: %d", text, width)

	return &PairingCodePane{
		text:      text,
		textWidth: width,
		image:     util.LoadImage(util.ResolveImagePath("code-underline.gif")),
	}
}
Example #6
0
// loadImages saves the PNG and GIF files in the images directory into the stateImages map
func loadImages() {
	files, err := ioutil.ReadDir("./images")

	if err != nil {
		panic("Couldn't load images: " + err.Error())
	}

	stateImages = make(map[string]util.Image)

	for _, f := range files {

		if strings.HasSuffix(f.Name(), ".gif") || strings.HasSuffix(f.Name(), ".png") {
			name := strings.TrimSuffix(strings.TrimSuffix(f.Name(), ".png"), ".gif")

			log.Infof("Found state image: " + name)
			stateImages[name] = util.LoadImage(util.ResolveImagePath(f.Name()))
			// also save names of images used as keys in images map
			stateImageNames = append(stateImageNames, name)
		}
	}
}
Example #7
0
func NewACPane(conn *ninja.Connection) *ACPane {

	pane := &ACPane{
		thermostat:  []*ninja.ServiceClient{},
		acstat:      []*ninja.ServiceClient{},
		mode:        "off",
		flash:       false,
		targetTemp:  666,
		currentTemp: 666,
		images: map[string]util.Image{
			"off":  util.LoadImage(util.ResolveImagePath("fan.gif")),
			"fan":  util.LoadImage(util.ResolveImagePath("fan-on.gif")),
			"cool": util.LoadImage(util.ResolveImagePath("fan-on-blue.gif")),
			"heat": util.LoadImage(util.ResolveImagePath("fan-on-red.gif")),
		},
	}

	pane.ignoreTapTimer = time.AfterFunc(0, func() {
		pane.ignoringTap = false
	})

	pane.sendTempTimer = time.AfterFunc(0, func() {
		for _, thermostat := range pane.thermostat {
			thermostat.Call("set", pane.targetTemp, nil, 0)
		}
	})

	listening := make(map[string]bool)

	isFlash := func(s string) bool {
		return s == "SUSPENDED"
	}

	onState := func(protocol, event string, cb func(params *json.RawMessage)) {
		ui.GetChannelServicesContinuous("aircon", protocol, func(thing *model.Thing) bool {
			return true
		}, func(devices []*ninja.ServiceClient, err error) {
			if err != nil {
				log.Infof("Failed to update %s device: %s", protocol, err)
			} else {
				log.Infof("Got %d %s devices", len(devices), protocol)

				for _, device := range devices {

					log.Debugf("Checking %s device %s", protocol, device.Topic)

					if _, ok := listening[device.Topic]; !ok {

						// New device
						log.Infof("Got new %s device: %s", protocol, device.Topic)

						if protocol == "thermostat" {
							pane.thermostat = append(pane.thermostat, device)
						}

						if protocol == "acstat" {
							pane.acstat = append(pane.acstat, device)
						}

						if protocol == "demandcontrol" {

							// only need to query for the initial notification - listener will pick up the rest

							go func() {
								var state StateChangeNotification
								err := device.Call("get", nil, &state, time.Second*10)
								if err != nil {
									log.Errorf("Failed to fetch state from demand control channel: %s", err)
								}

								// spew.Dump("Got demand state", state)

								pane.flash = isFlash(state.State)
							}()
						}

						listening[device.Topic] = true

						device.OnEvent(event, func(params *json.RawMessage, values map[string]string) bool {
							cb(params)

							return true
						})
					}
				}
			}
		})
	}

	onState("temperature", "state", func(params *json.RawMessage) {
		var temp float64
		err := json.Unmarshal(*params, &temp)
		if err != nil {
			log.Infof("Failed to unmarshal temp from %s error:%s", *params, err)
		}

		pane.currentTemp = int(temp)

		log.Infof("Got the temp %d", pane.currentTemp)
	})

	onState("thermostat", "state", func(params *json.RawMessage) {
		var temp float64
		err := json.Unmarshal(*params, &temp)
		if err != nil {
			log.Infof("Failed to unmarshal thermostat from %s error:%s", *params, err)
		}

		pane.targetTemp = int(temp)

		log.Infof("Got the thermostat %d", pane.targetTemp)
	})

	onState("acstat", "state", func(params *json.RawMessage) {
		var state channels.ACState
		err := json.Unmarshal(*params, &state)
		if err != nil {
			log.Infof("Failed to unmarshal acstat from %s error:%s", *params, err)
		}

		pane.mode = *state.Mode

		log.Infof("Got the ac mode %d", pane.mode)
	})

	onState("demandcontrol", "state", func(params *json.RawMessage) {

		// spew.Dump("demand/controlstate", params)

		var state StateChangeNotification
		err := json.Unmarshal(*params, &state)
		if err != nil {
			log.Infof("Failed to unmarshal demandstat state from %s error:%s", *params, err)
		}

		pane.flash = isFlash(state.State)

		log.Infof("Got the demandcontrol state %d", pane.mode)
	})

	go ui.StartSearchTasks(conn)

	return pane
}
Example #8
0
	"image/draw"
	"io/ioutil"
	"strings"
	"time"

	"fmt"
	"github.com/ninjasphere/gestic-tools/go-gestic-sdk"
	"github.com/ninjasphere/sphere-go-led-controller/fonts/O4b03b"
	"github.com/ninjasphere/sphere-go-led-controller/util"
)

var tapInterval = time.Millisecond * 500
var introDuration = time.Millisecond * 1500

// load a particular image - for a 'logo' in this case
var imageLogo = util.LoadImage(util.ResolveImagePath("logo.png"))
var border = util.LoadImage(util.ResolveImagePath("border-green.gif"))

var stateImages map[string]util.Image
var stateImageNames []string

// loadImages saves the PNG and GIF files in the images directory into the stateImages map
func loadImages() {
	files, err := ioutil.ReadDir("./images")

	if err != nil {
		panic("Couldn't load images: " + err.Error())
	}

	stateImages = make(map[string]util.Image)
	volumeDevices  []*ninja.ServiceClient
}

type MediaPaneImages struct {
	Volume     string
	VolumeUp   string
	VolumeDown string
	Mute       string
	Play       string
	Pause      string
	Stop       string
	Next       string
}

var mediaImages = MediaPaneImages{
	Volume:     util.ResolveImagePath(config.MustString("led.media.images.volume")),
	VolumeUp:   util.ResolveImagePath(config.MustString("led.media.images.volumeUp")),
	VolumeDown: util.ResolveImagePath(config.MustString("led.media.images.volumeDown")),
	Mute:       util.ResolveImagePath(config.MustString("led.media.images.mute")),
	Play:       util.ResolveImagePath(config.MustString("led.media.images.play")),
	Pause:      util.ResolveImagePath(config.MustString("led.media.images.pause")),
	Stop:       util.ResolveImagePath(config.MustString("led.media.images.stop")),
	Next:       util.ResolveImagePath(config.MustString("led.media.images.next")),
}

func NewMediaPane(conn *ninja.Connection) *MediaPane {
	log := logger.GetLogger("MediaPane")

	pane := &MediaPane{
		log:         log,
		conn:        conn,
// Load from a config file instead...
func getPaneLayout(conn *ninja.Connection) *ui.PaneLayout {
	layout, wake := ui.NewPaneLayout(false, conn)

	layout.AddPane(ui.NewClockPane())
	layout.AddPane(ui.NewWeatherPane(conn))
	layout.AddPane(ui.NewGesturePane())
	layout.AddPane(ui.NewGameOfLifePane())
	layout.AddPane(ui.NewMediaPane(conn))
	layout.AddPane(ui.NewCertPane(conn.GetMqttClient()))

	//layout.AddPane(ui.NewTextScrollPane("Exit Music (For A Film)"))
	lampPane := ui.NewOnOffPane(util.ResolveImagePath("lamp2-off.gif"), util.ResolveImagePath("lamp2-on.gif"), func(state bool) {
		log.Debugf("Lamp state: %t", state)
	}, conn, "lamp")
	layout.AddPane(lampPane)

	heaterPane := ui.NewOnOffPane(util.ResolveImagePath("heater-off.png"), util.ResolveImagePath("heater-on.gif"), func(state bool) {
		log.Debugf("Heater state: %t", state)
	}, conn, "heater")
	layout.AddPane(heaterPane)

	brightnessPane := ui.NewLightPane(false, util.ResolveImagePath("light-off.png"), util.ResolveImagePath("light-on.png"), conn)
	layout.AddPane(brightnessPane)

	colorPane := ui.NewLightPane(true, util.ResolveImagePath("light-off.png"), util.ResolveImagePath("light-on.png"), conn)
	layout.AddPane(colorPane)

	fanPane := ui.NewOnOffPane(util.ResolveImagePath("fan-off.png"), util.ResolveImagePath("fan-on.gif"), func(state bool) {
		log.Debugf("Fan state: %t", state)
	}, conn, "fan")

	layout.AddPane(fanPane)

	airconPane := ui.NewOnOffPane(util.ResolveImagePath("fan-off.png"), util.ResolveImagePath("fan-on.gif"), func(state bool) {
		log.Debugf("aircon state: %t", state)
	}, conn, "aircon")
	layout.AddPane(airconPane)

	if enableRemotePanes {
		if err := listenForRemotePanes(layout); err != nil {
			log.Fatalf("Failed to start listening for remote panes: %s", err)
		}
	}

	go func() {
		<-wake
	}()

	go layout.Wake()

	return layout
}
func (l *PairingLayout) ShowIcon(image string) {
	l.currentPane = NewImagePane(util.ResolveImagePath(image))
}
func (l *PairingLayout) ShowColor(c color.Color) {
	l.currentPane = NewPairingColorPane(util.ResolveImagePath("color-mask.gif"), c)
}