Example #1
0
func main() {
	// Install HAP devices
	x10Accessories := X10Devices()
	particleAccessories := ParticleDevices()

	accessories := append(x10Accessories, particleAccessories...)

	bridge := accessory.NewLightBulb(model.Info{
		Name:         "Bridge",
		Manufacturer: "Evan",
	})
	t, err := hap.NewIPTransport("10000000", bridge.Accessory, accessories...)
	if err != nil {
		log.Fatal(err)
	}

	t.Start()

	// Setup REST API
	m := martini.Classic()
	m.Get("/", func() string {
		return "Hello world!"
	})
	m.RunOnAddr(":5591")
}
Example #2
0
func main() {
	switchInfo := model.Info{
		Name: "Lamp",
	}
	sw := accessory.NewSwitch(switchInfo)

	config := hap.Config{Pin: "12344321", Port: "12345", StoragePath: "./db"}
	t, err := hap.NewIPTransport(config, sw.Accessory)

	if err != nil {
		log.Fatal(err)
	}

	// Log to console when client (e.g. iOS app) changes the value of the on characteristic
	sw.OnStateChanged(func(on bool) {
		if on == true {
			log.Println("[INFO] Client changed switch to on")
		} else {
			log.Println("[INFO] Client changed switch to off")
		}
	})

	// Periodically toggle the switch's on characteristic
	go func() {
		for {
			on := !sw.IsOn()
			if on == true {
				log.Println("[INFO] Switch on")
			} else {
				log.Println("[INFO] Switch off")
			}
			sw.SetOn(on)
			time.Sleep(5 * time.Second)
		}
	}()

	hap.OnTermination(func() {
		t.Stop()
	})

	t.Start()
}
Example #3
0
func NewHomeKitService(thermostat *Thermostat) *HomeKitService {
	thermostatInfo := model.Info{
		Name: "Thermostat",
	}

	hkThermostat := accessory.NewThermostat(thermostatInfo, temp, 17, 25, 0.5)
	hkThermostat.SetTargetMode(model.HeatCoolModeHeat)
	hkThermostat.OnTargetTempChange(func(temp float64) {
		log.Println("[INFO] HomeKit requested thermostat to change to", temp)
		thermostat.targetTemp = temp
	})

	hkThermostat.OnTargetModeChange(func(mode model.HeatCoolModeType) {
		log.Println("[INFO] HomeKit requested thermostat to change to", mode)

		switch mode {
		case model.HeatCoolModeHeat:
			log.Println("[INFO] HomeKit setting thermostat to default on temp of", defaultOnTemp)
			thermostat.targetTemp = defaultOnTemp
		case model.HeatCoolModeOff:
			log.Println("[INFO] HomeKit setting thermostat to default off temp of", defaultOffTemp)
			thermostat.targetTemp = defaultOffTemp
		case model.HeatCoolModeAuto, model.HeatCoolModeCool:
			hkThermostat.SetTargetMode(model.HeatCoolModeHeat)
		}

	})

	transport, err := hap.NewIPTransport("24282428", hkThermostat.Accessory)
	if err != nil {
		log.Fatal(err)
	}

	t := HomeKitService{
		thermostat:   thermostat,
		done:         make(chan bool),
		hkThermostat: hkThermostat,
		transport:    transport,
	}

	return &t
}
Example #4
0
func setupHomeKit() {
	aInfo := accessory.Info{
		Name:         "Hive Bridge",
		Manufacturer: "British Gas PLC",
	}
	a := accessory.New(aInfo, accessory.TypeBridge)

	tInfo := accessory.Info{
		Name:         "Heating",
		Manufacturer: "British Gas PLC",
	}
	t := accessory.NewThermostat(tInfo, 20.0, hive.MinTemp, hive.MaxTemp, 0.5)
	t.Thermostat.TargetTemperature.OnValueRemoteUpdate(targetTempChangeRequest)
	thermostat = t

	bInfo := accessory.Info{
		Name:         "Heating Boost",
		Manufacturer: "British Gas PLC",
	}
	b := accessory.NewSwitch(bInfo)
	b.Switch.On.OnValueRemoteUpdate(heatingBoostStateChangeRequest)
	heatingBoostSwitch = b

	sInfo := accessory.Info{
		Name:         "Hot Water",
		Manufacturer: "British Gas PLC",
	}
	h := accessory.NewSwitch(sInfo)
	h.Switch.On.OnValueRemoteUpdate(hotWaterStateChangeRequest)
	hotWaterSwitch = h

	config := hap.Config{
		Pin: pin,
	}

	var err error
	transport, err = hap.NewIPTransport(config, a, t.Accessory, b.Accessory, h.Accessory)
	if err != nil {
		log.Fatal(err)
	}
}
Example #5
0
func main() {
	info := model.Info{
		Name:         "Personal Light Bulb",
		Manufacturer: "Matthias",
	}

	light := accessory.NewLightBulb(info)
	light.OnStateChanged(func(on bool) {
		if on == true {
			turnLightOn()
		} else {
			turnLightOff()
		}
	})

	t, err := hap.NewIPTransport("32191123", light.Accessory)
	if err != nil {
		log.Fatal(err)
	}

	t.Start()
}
Example #6
0
func main() {
	info := model.Info{
		Name:         "My Door Sensor",
		SerialNumber: "XXX-YYY-ZZZ",
		Manufacturer: "Me",
		Model:        "1",
		Firmware:     "1.0",
	}

	doorSensor := accessory.NewContactSensor(info)

	t, err := hap.NewIPTransport(hap.Config{Pin: "32191123"}, doorSensor.Accessory)
	if err != nil {
		log.Fatal(err)
	}

	// Periodically toggle the contact sensor's state characteristic
	go func() {
		for {
			var state model.ContactSensorStateType
			if doorSensor.State() == model.ContactDetected {
				state = model.ContactNotDetected
			} else {
				state = model.ContactDetected
			}
			doorSensor.SetState(state)
			time.Sleep(5 * time.Second)
		}
	}()

	hap.OnTermination(func() {
		t.Stop()
	})

	t.Start()
}
Example #7
0
func GetHKLight(light common.Light) *HKLight {
	hkLight, found := lights[light.ID()]
	if found {
		return hkLight
	}

	label, _ := light.GetLabel()
	log.Printf("[INFO] Creating New HKLight for %s", label)

	info := model.Info{
		Name:         label,
		Manufacturer: "LIFX",
	}

	lightBulb := accessory.NewLightBulb(info)

	power, _ := light.GetPower()
	lightBulb.SetOn(power)

	color, _ := light.GetColor()
	hue, saturation, brightness := ConvertLIFXColor(color)

	lightBulb.SetBrightness(int(brightness))
	lightBulb.SetSaturation(saturation)
	lightBulb.SetHue(hue)

	transport, err := hap.NewIPTransport(pin, lightBulb.Accessory)
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		transport.Start()
	}()

	hkLight = &HKLight{lightBulb.Accessory, nil, transport, lightBulb}
	lights[light.ID()] = hkLight

	lightBulb.OnIdentify(func() {
		timeout := 1 * time.Second

		for i := 0; i < 4; i++ {
			ToggleLight(light)
			time.Sleep(timeout)
		}
	})

	lightBulb.OnStateChanged(func(power bool) {
		log.Printf("[INFO] Changed State for %s", label)
		light.SetPower(power)
	})

	updateColor := func(light common.Light) {
		// HAP: [0...360]
		// LIFX: [0...MAX_UINT16]
		hue := lightBulb.GetHue()

		// HAP: [0...100]
		// LIFX: [0...MAX_UINT16]
		saturation := lightBulb.GetSaturation()

		// HAP: [0...100]
		// LIFX: [0...MAX_UINT16]
		brightness := lightBulb.GetBrightness()

		// [HSBKKelvinMin..HSBKKelvinMax]
		kelvin := HSBKKelvinDefault

		lifxHue := math.MaxUint16 * float64(hue) / float64(characteristic.MaxHue)
		lifxSaturation := math.MaxUint16 * float64(saturation) / float64(characteristic.MaxSaturation)
		lifxBrightness := math.MaxUint16 * float64(brightness) / float64(characteristic.MaxBrightness)

		color := common.Color{
			uint16(lifxHue),
			uint16(lifxSaturation),
			uint16(lifxBrightness),
			kelvin,
		}

		light.SetColor(color, 500*time.Millisecond)
	}

	lightBulb.OnHueChanged(func(value float64) {
		log.Printf("[INFO] Changed Hue for %s to %d", label, value)
		updateColor(light)
	})

	lightBulb.OnSaturationChanged(func(value float64) {
		log.Printf("[INFO] Changed Saturation for %s to %d", label, value)
		updateColor(light)
	})

	lightBulb.OnBrightnessChanged(func(value int) {
		log.Printf("[INFO] Changed Brightness for %s to %d", label, value)
		updateColor(light)
	})

	return hkLight
}
Example #8
0
func lightForBulb(bulb *lifx.Bulb) *lifxLight {
	label := bulb.GetLabel()
	light, found := lights[label]
	if found == true {
		fmt.Println("Found")
		return light
	}

	fmt.Println("Create new switch for blub")

	info := model.Info{
		Name:         label,
		Manufacturer: "LIFX",
	}

	light_bulb := accessory.NewLightBulb(info)
	light_bulb.OnIdentify(func() {
		timeout := 1 * time.Second
		toggleBulb(bulb)
		time.Sleep(timeout)
		toggleBulb(bulb)
		time.Sleep(timeout)
		toggleBulb(bulb)
		time.Sleep(timeout)
		toggleBulb(bulb)
	})

	light_bulb.OnStateChanged(func(on bool) {
		if on == true {
			client.LightOn(bulb)
			log.Println("Switch is on")
		} else {
			client.LightOff(bulb)
			log.Println("Switch is off")
		}
	})

	updateColors := func(client *lifx.Client, bulb *lifx.Bulb) {
		// TODO define max variables in Gohap

		// HAP: [0...360]
		// LIFX: [0...MAX_UINT16]
		hue := light_bulb.GetHue()

		// HAP: [0...100]
		// LIFX: [0...MAX_UINT16]
		saturation := light_bulb.GetSaturation()
		// HAP: [0...100]
		// LIFX: [0...MAX_UINT16]
		brightness := light_bulb.GetBrightness()
		// [2500..9000]
		kelvin := HSBKKelvinDefault

		lifx_brightness := math.MaxUint16 * float64(brightness) / 100
		lifx_saturation := math.MaxUint16 * float64(saturation) / 100
		lifx_hue := math.MaxUint16 * float64(hue) / 360

		log.Println("Brightness", lifx_brightness)
		log.Println("Hue", lifx_saturation)
		log.Println("Saturation", lifx_hue)
		client.LightColour(bulb, uint16(lifx_hue), uint16(lifx_saturation), uint16(lifx_brightness), uint16(kelvin), 0x0500)
	}

	light_bulb.OnBrightnessChanged(func(value int) {
		log.Println("Brightness", value)
		updateColors(client, bulb)
	})

	light_bulb.OnSaturationChanged(func(value float64) {
		log.Println("Saturation", value)
		updateColors(client, bulb)
	})

	light_bulb.OnHueChanged(func(value float64) {
		log.Println("Hue", value)
		updateColors(client, bulb)
	})

	transport, err := hap.NewIPTransport(pin, light_bulb.Accessory)
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		transport.Start()
	}()

	light = &lifxLight{transport, light_bulb, light_bulb.Accessory}
	lights[label] = light

	return light
}
Example #9
0
func handleNewLight(light common.Light) (err error) {
	id := light.ID()

	_, exists := lights[id]
	if exists {
		log.Debugf("A light with the ID '%s' has already been added", id)
		return nil
	}

	subscription, err := light.NewSubscription()
	if err != nil {
		log.WithField(`error`, err).Error(`Subscribing to light events`)
		return err
	}

	label, _ := light.GetLabel()

	log.Infof("Adding light [%s]", label)

	info := model.Info{
		Name:         label,
		Manufacturer: "LIFX",
	}

	haLight := accessory.NewLightBulb(info)

	lights[id] = lightMeta{
		light:        light,
		subscription: subscription,
		haLight:      haLight,
	}

	// Get the initial state of the light and communicate it via HomeKit
	updateHaPowerState(light, haLight)
	updateHaColors(light, haLight)

	events := subscription.Events()
	go func() {
		for {
			select {
			case event := <-events:
				switch event := event.(type) {
				case common.EventUpdateColor:
					log.Infof("Light: %s, Event: Update Color", id)
					updateHaColors(light, haLight)
				case common.EventUpdateLabel:
					// TODO: Find out how to update the name of a homekit device
					log.Infof("Light: %s, Event: Update Label", id)
				case common.EventUpdatePower:
					log.Infof("Light: %s, Event: Update Power", id)
					updateHaPowerState(light, haLight)
				default:
					log.Debugf("Unhandled event on light: %+v", event)
					continue
				}
			}
		}
	}()

	haLight.OnIdentify(func() {
		timeout := 1 * time.Second

		for i := 0; i < 4; i++ {
			toggleLight(light)
			time.Sleep(timeout)
		}
	})

	haLight.OnStateChanged(func(on bool) {
		go func() {
			light.SetPower(on)
		}()
	})

	haLight.OnBrightnessChanged(func(value int) {
		go func() {
			updateLightColors(light, haLight)
		}()
	})

	haLight.OnSaturationChanged(func(value float64) {
		go func() {
			updateLightColors(light, haLight)
		}()
	})

	haLight.OnHueChanged(func(value float64) {
		go func() {
			updateLightColors(light, haLight)
		}()
	})

	transport, err := hap.NewIPTransport(pin, haLight.Accessory)
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		transport.Start()
	}()

	return nil
}
Example #10
0
// This app can connect to the UVR1611 data bus and provide the sensor values to HomeKit clients
//
// Optimizations: To improve the performance on a Raspberry Pi B+, the interrupt handler of the
// gpio pin is removed every time after successfully decoding a packet. This allows other goroutines
// (e.g. HAP server) to do their job more quickly.
func main() {

	var (
		pin     = flag.String("pin", "", "Accessory pin required for pairing")
		mode    = flag.String("conn", "mock", "Connection type; mock, gpio, replay")
		file    = flag.String("file", "", "Log file from which to replay packets")
		port    = flag.String("port", "P8_07", "GPIO port; default P8_07")
		timeout = flag.Int("timeout", 120, "Timeout in seconds until accessories are not reachable")
	)

	flag.Parse()
	sensors = map[string]*hkuvr1611.Sensor{}

	info := InfoForAccessoryName("UVR1611")
	uvrAccessory = accessory.New(info, accessory.TypeBridge)

	timer_duration := time.Duration(*timeout) * time.Second
	timer = time.AfterFunc(timer_duration, func() {
		log.Println("[INFO] Not Reachable")
		if transport != nil {
			sensors = map[string]*hkuvr1611.Sensor{}
			transport.Stop()
			transport = nil
		}
	})

	var conn Connection
	callback := func(packet uvr1611.Packet) {
		sensors := HandlePacket(packet)
		if transport == nil {
			config := hap.Config{Pin: *pin}
			if t, err := hap.NewIPTransport(config, uvrAccessory, sensors...); err != nil {
				log.Fatal(err)
			} else {
				go func() {
					t.Start()
				}()
				transport = t
			}
		}
		timer.Reset(timer_duration)
	}

	switch *mode {
	case "mock":
		conn = mock.NewConnection(callback)
	case "replay":
		conn = mock.NewReplayConnection(*file, callback)
	case "gpio":
		conn = gpio.NewConnection(*port, callback)
	default:
		log.Fatal("Incorrect -conn flag")
	}

	hap.OnTermination(func() {
		if transport != nil {
			transport.Stop()
		}
		conn.Close()
		timer.Stop()
		os.Exit(1)
	})

	select {}
}