Skip to content

Commit e1e2eab

Browse files
committed
implement simple API
1 parent 432bd15 commit e1e2eab

File tree

8 files changed

+97
-4
lines changed

8 files changed

+97
-4
lines changed

.run/fhomed --homekit --debug.run.xml renamed to .run/fhomed (HomeKit + webserver).run.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<component name="ProjectRunConfigurationManager">
2-
<configuration default="false" name="fhomed --homekit --debug" type="GoApplicationRunConfiguration" factoryName="Go Application" focusToolWindowBeforeRun="true">
2+
<configuration default="false" name="fhomed (HomeKit + webserver)" type="GoApplicationRunConfiguration" factoryName="Go Application" focusToolWindowBeforeRun="true">
33
<module name="fhome" />
44
<working_directory value="$PROJECT_DIR$" />
5-
<parameters value="--homekit --debug" />
5+
<parameters value="--homekit --webserver --debug" />
66
<kind value="PACKAGE" />
77
<package value="github.com/bartekpacia/fhome/cmd/fhomed" />
88
<directory value="$PROJECT_DIR$" />

api/client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ func (c *Client) SendAction(ctx context.Context, actionName string) (*Message, e
332332

333333
// SendEvent sends an event containing value to the cell.
334334
//
335+
// This is a more specific variant of SendAction.
336+
//
335337
// Events are named "Xevents" in F&Home's terminology.
336338
func (c *Client) SendEvent(ctx context.Context, cellID int, value string) error {
337339
actionName := ActionEvent

cmd/fhome/commands.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ var configCommand = cli.Command{
140140
log.Println()
141141
}
142142
} else if cmd.Bool("glance") {
143-
// We want to see real values of the system resources.
143+
// We want to see the real values of the system resources.
144144
// To do that, we need to send the "statustouches" action and
145145
// wait for its response.
146146

cmd/fhomed/requests/devices.http

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GET http://localhost:9001/api/devices
2+
Authorization: Passphrase: my-passphrase

cmd/fhomed/requests/toggle.http

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
POST http://localhost:9001/api/devices/291
2+
Authorization: Passphrase: my-passphrase
3+
# 291 = bartek sufit 1

cmd/fhomed/webserver/api.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package webserver
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"github.com/bartekpacia/fhome/api"
7+
"net/http"
8+
"strconv"
9+
)
10+
11+
type Api struct {
12+
fhomeClient *api.Client
13+
}
14+
15+
func NewApi(fhomeClient *api.Client) *Api {
16+
return &Api{
17+
fhomeClient: fhomeClient,
18+
}
19+
}
20+
21+
func (a *Api) Mux() http.Handler {
22+
mux := http.NewServeMux()
23+
24+
mux.HandleFunc("GET /devices", a.getDevices)
25+
mux.HandleFunc("POST /devices/{id}", a.toggleDevice)
26+
27+
authMux := withPassphrase(mux, "my-passphrase")
28+
return authMux
29+
}
30+
31+
func (a *Api) getDevices(w http.ResponseWriter, r *http.Request) {
32+
userConfig, err := a.fhomeClient.GetUserConfig(r.Context())
33+
if err != nil {
34+
http.Error(w, "failed to get user config"+err.Error(), http.StatusInternalServerError)
35+
return
36+
}
37+
38+
response := make([]device, 0)
39+
40+
for _, cell := range userConfig.Cells {
41+
response = append(response, device{
42+
Name: cell.Name,
43+
ID: cell.ObjectID,
44+
})
45+
}
46+
47+
w.Header().Set("Content-Type", "application/json")
48+
err = json.NewEncoder(w).Encode(response)
49+
if err != nil {
50+
http.Error(w, "failed to encode user into json"+err.Error(), http.StatusInternalServerError)
51+
return
52+
}
53+
}
54+
55+
func (a *Api) toggleDevice(w http.ResponseWriter, r *http.Request) {
56+
objectID, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
57+
if err != nil {
58+
http.Error(w, err.Error(), http.StatusBadRequest)
59+
return
60+
}
61+
62+
err = a.fhomeClient.SendEvent(r.Context(), int(objectID), api.ValueToggle)
63+
if err != nil {
64+
msg := fmt.Sprintf("failed to send event to object with %d: %v\n", objectID, err)
65+
http.Error(w, msg, http.StatusInternalServerError)
66+
return
67+
}
68+
}
69+
70+
func withPassphrase(next http.Handler, passphrase string) http.Handler {
71+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
72+
if r.Header.Get("Authorization") != "Passphrase: "+passphrase {
73+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
74+
return
75+
}
76+
77+
next.ServeHTTP(w, r)
78+
})
79+
}
80+
81+
type device struct {
82+
Name string
83+
ID int
84+
}

cmd/fhomed/webserver/templates/index.html.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<h2>{{$panel.Name}} ({{len $panel.Cells }} objects) </h2>
1717
<ul>
1818
{{range $j, $cell := $panel.Cells}}
19-
<li>{{$cell.Name}}</li>
19+
<li>{{$cell.Name}} / {{$cell.ID}}</li>
2020
{{end}}
2121
</ul>
2222
{{end}}

cmd/fhomed/webserver/webserver.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ func Run(ctx context.Context, client *api.Client, homeConfig *api.Config, email
5454
})
5555

5656
mux.Handle("GET /public", http.StripPrefix("/public/", http.FileServer(http.FS(assets))))
57+
app := NewApi(client)
58+
mux.Handle("/api/", http.StripPrefix("/api", app.Mux()))
5759
addr := fmt.Sprint("0.0.0.0:", port)
5860
httpServer := http.Server{Addr: addr, Handler: mux}
5961

0 commit comments

Comments
 (0)