SIFT (Simple Interface for Functional Things)
![Join the chat at https://gitter.im/upwrd/sift](https://badges.gitter.im/upwrd/sift.svg)
SIFT is a framework that enables developers to control connected devices without
having to understand their implementation details.
A SIFT server:
- Regularly scans available networks to discover new connected devices
- Once discovered, actively gathers the state of connected devices to produce
a synchronized internal collection of device states
- Allows developers to query the state of connected devices, and to subscribe
to notifications when they are updated or removed
- Allows developers to control controllable devices
Note: SIFT is in early development. The API may change in future updates.
Getting Started
SIFT requires Golang 1.4+ and python 2.7.
# install
go get github.com/upwrd/sift
pip install -r $GOPATH/github.com/upwrd/sift/requirements.txt
# run interactive setup & example apps:
go run github.com/upward/sift/main/interactive.go
Examples
Movies and Chill
Automatically turn down the lights when watching a movie
package main
import (
"github.com/upwrd/sift"
"github.com/upwrd/sift/types"
"github.com/upwrd/sift/notif"
)
func main() {
server, _ := sift.NewServer(sift.DefaultDBFilepath)
server.AddDefaults()
go server.Serve()
token := server.Login()
mediaFilter := notif.ComponentFilter{Type: types.ComponentTypeMediaPlayer}
lightsFilter := notif.ComponentFilter{Type: types.ComponentTypeLightEmitter}
listener := server.Listen(token, lightsFilter, mediaFilter)
for range listener {
db, _ := server.DB()
lightsQuery := `
SELECT c1.device_id, c1.name, num_playing_mpls_in_room
FROM light_emitter_state l1
JOIN component c1 ON l1.id=c1.id
JOIN device d1 ON c1.device_id=d1.id
JOIN (SELECT d.location_id loc,
SUM (CASE WHEN m.play_state="PLAYING" THEN 1 ELSE 0 END) as num_playing_mpls_in_room
FROM media_player_state m
JOIN component c ON m.id=c.id
JOIN device d ON c.device_id=d.id
GROUP BY d.location_id)
ON d1.location_id=loc;`
type result struct {
DeviceID int64 `db:"device_id"`
Name string
NumPlayingMediaPlayersInRoom int `db:"num_playing_mpls_in_room"`
}
results := []result{}
db.Select(&results, lightsQuery)
for _, result := range results {
var intent types.SetLightEmitterIntent
if result.NumPlayingMediaPlayersInRoom > 0 {
intent.BrightnessInPercent = lightsLow
} else {
intent.BrightnessInPercent = lightsHigh
}
target := types.ComponentID{
DeviceID: types.DeviceID(result.DeviceID),
Name: result.Name,
}
server.EnactIntent(target, intent)
}
}
}
Data Model
To learn more about the SIFT data types and structure, see:
https://github.com/upwrd/sift/tree/master/types
Compatibility
Device | Networks | Components | Notes |
---|
Connected By TCP Lighting | IPv4 | Light Emitters | Must press the sync button on the Connected By TCP Hub on first run. |
Google Chromecast | IPv4 | Media Players | Does not work with all Chromecast apps, most notably Netflix :( |
To learn how to add support for new devices and device types, see
https://github.com/upwrd/sift/tree/master/adapter
Licensing
Copyright 2016 Upward Automation, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
A copy of the license is available in the repository's
LICENSE file.