// 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")), } }
// 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) } } }
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 }
"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) }