Skip to content

Commit

Permalink
Add command to generate Swift code for service and characteristic types
Browse files Browse the repository at this point in the history
  • Loading branch information
brutella committed May 2, 2016
1 parent aedb073 commit 30e563b
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 27 deletions.
1 change: 1 addition & 0 deletions characteristic/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ const (
FormatUInt32 = "uint32"
FormatInt32 = "int32"
FormatUInt64 = "uint64"
FormatData = "data"
FormatTLV8 = "tlv8"
)
11 changes: 7 additions & 4 deletions cmd/import.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build ignore

// Imports HomeKit metadata from a file and creates files for every characteristic and service.
// It finishes by running `go fmt` in the characterist and service packages.
//
Expand All @@ -9,6 +11,7 @@ package main
import (
"encoding/json"
"github.com/brutella/hc/gen"
"github.com/brutella/hc/gen/golang"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -48,10 +51,10 @@ func main() {
// Create characteristic files
for _, char := range metadata.Characteristics {
log.Printf("Processing %s Characteristic", char.Name)
if b, err := gen.CharacteristicGoCode(char); err != nil {
if b, err := golang.CharacteristicGoCode(char); err != nil {
log.Println(err)
} else {
filePath := filepath.Join(CharPkgPath, gen.FileName(char))
filePath := filepath.Join(CharPkgPath, golang.FileName(char))
log.Println("Creating file", filePath)
if f, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666); err != nil {
log.Fatal(err)
Expand All @@ -66,10 +69,10 @@ func main() {
// Create service files
for _, svc := range metadata.Services {
log.Printf("Processing %s Service", svc.Name)
if b, err := gen.ServiceGoCode(svc, metadata.Characteristics); err != nil {
if b, err := golang.ServiceGoCode(svc, metadata.Characteristics); err != nil {
log.Println(err)
} else {
filePath := filepath.Join(SvcPkgPath, gen.ServiceFileName(svc))
filePath := filepath.Join(SvcPkgPath, golang.ServiceFileName(svc))
log.Println("Creating file", filePath)
if f, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666); err != nil {
log.Fatal(err)
Expand Down
56 changes: 56 additions & 0 deletions cmd/swift_decl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// +build ignore

// Creates swift code for all HomeKit service and characteristic types and logs
// that to the console.

package main

import (
"encoding/json"
"github.com/brutella/hc/gen"
"github.com/brutella/hc/gen/swift"
"io/ioutil"
"log"
"os"
"path/filepath"
)

var LibPath = os.ExpandEnv("$GOPATH/src/github.com/brutella/hc")
var GenPath = filepath.Join(LibPath, "gen")
var MetadataPath = filepath.Join(GenPath, "metadata.json")

func main() {

log.Println("Import data from", MetadataPath)

// Open metadata file
f, err := os.Open(MetadataPath)
if err != nil {
log.Fatal(err)
}

// Read content
b, err := ioutil.ReadAll(f)
if err != nil {
log.Fatal(err)
}

// Import json
metadata := gen.Metadata{}
err = json.Unmarshal(b, &metadata)
if err != nil {
log.Fatal(err)
}

if b, err := swift.CharacteristicEnumDecl(metadata); err != nil {
log.Fatal(err)
} else {
log.Println(string(b))
}

if b, err := swift.ServiceEnumDecl(metadata); err != nil {
log.Fatal(err)
} else {
log.Println(string(b))
}
}
36 changes: 19 additions & 17 deletions gen/characteristic.go → gen/golang/characteristic.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gen
package golang

import (
"bytes"
Expand All @@ -9,6 +9,8 @@ import (
"sort"
"strings"
"text/template"

"github.com/brutella/hc/gen"
)

// CharStructTemplate is template for a characteristic struct.
Expand Down Expand Up @@ -59,7 +61,7 @@ type Characteristic struct {
Consts []ConstDecl
}

func NewCharacteristic(char *CharacteristicMetadata) *Characteristic {
func NewCharacteristic(char *gen.CharacteristicMetadata) *Characteristic {
data := Characteristic{
EmbeddedStructName: embeddedStructNames[char.Format],
FormatTypeName: formatConstants[char.Format],
Expand Down Expand Up @@ -137,12 +139,12 @@ func (v ByValue) Swap(i, j int) {
}

// FileName returns the filename for a characteristic
func FileName(char *CharacteristicMetadata) string {
func FileName(char *gen.CharacteristicMetadata) string {
return fmt.Sprintf("%s.go", underscored(char.Name))
}

// CharacteristicGoCode returns the o code for a characteristic file
func CharacteristicGoCode(char *CharacteristicMetadata) ([]byte, error) {
func CharacteristicGoCode(char *gen.CharacteristicMetadata) ([]byte, error) {
var err error
var buf bytes.Buffer

Expand Down Expand Up @@ -192,7 +194,7 @@ var embeddedStructNames = map[string]string{
}

// isReadable returns true the characteristic contains the readable property
func isReadable(char *CharacteristicMetadata) bool {
func isReadable(char *gen.CharacteristicMetadata) bool {
for _, perm := range char.Properties {
if perm == "read" {
return true
Expand All @@ -203,7 +205,7 @@ func isReadable(char *CharacteristicMetadata) bool {
}

// defaultValue returns the default value of a characteristic, based on the characteristic format and properties (readable)
func defaultValue(char *CharacteristicMetadata) interface{} {
func defaultValue(char *gen.CharacteristicMetadata) interface{} {
if isReadable(char) == false {
return nil
}
Expand Down Expand Up @@ -241,11 +243,11 @@ func minifyUUID(s string) string {
}

// Return the name of the characteristic type name
func typeName(char *CharacteristicMetadata) string {
func typeName(char *gen.CharacteristicMetadata) string {
return "Type" + camelCased(char.Name)
}

func structName(char *CharacteristicMetadata) string {
func structName(char *gen.CharacteristicMetadata) string {
return camelCased(char.Name)
}

Expand All @@ -267,7 +269,7 @@ func camelCased(s string) string {
return strings.Replace(lowered, " ", "", -1)
}

func permissionDecl(char *CharacteristicMetadata) string {
func permissionDecl(char *gen.CharacteristicMetadata) string {
var perms []string
for _, perm := range char.Properties {
switch perm {
Expand All @@ -288,7 +290,7 @@ func permissionDecl(char *CharacteristicMetadata) string {
return "[]string{" + strings.Join(perms, ",") + "}"
}

func unitName(char *CharacteristicMetadata) string {
func unitName(char *gen.CharacteristicMetadata) string {
switch char.Unit {
case "percentage":
return "UnitPercentage"
Expand All @@ -301,7 +303,7 @@ func unitName(char *CharacteristicMetadata) string {
}
}

func constraints(char *CharacteristicMetadata) map[string]interface{} {
func constraints(char *gen.CharacteristicMetadata) map[string]interface{} {
if char.Constraints != nil {
if constraints, ok := char.Constraints.(map[string]interface{}); ok == true {
return constraints
Expand All @@ -310,34 +312,34 @@ func constraints(char *CharacteristicMetadata) map[string]interface{} {
return nil
}

func constraintWithKey(char *CharacteristicMetadata, key string) interface{} {
func constraintWithKey(char *gen.CharacteristicMetadata, key string) interface{} {
if constr := constraints(char); constr != nil {
return constr[key]
}
return nil
}

func constrainedValues(char *CharacteristicMetadata) map[string]interface{} {
func constrainedValues(char *gen.CharacteristicMetadata) map[string]interface{} {
if values := constraintWithKey(char, "ValidValues"); values != nil {
return values.(map[string]interface{})
}

return nil
}

func minValue(char *CharacteristicMetadata) interface{} {
func minValue(char *gen.CharacteristicMetadata) interface{} {
return constraintWithKey(char, "MinimumValue")
}

func maxValue(char *CharacteristicMetadata) interface{} {
func maxValue(char *gen.CharacteristicMetadata) interface{} {
return constraintWithKey(char, "MaximumValue")
}

func stepValue(char *CharacteristicMetadata) interface{} {
func stepValue(char *gen.CharacteristicMetadata) interface{} {
return constraintWithKey(char, "StepValue")
}

func constDecls(char *CharacteristicMetadata) []ConstDecl {
func constDecls(char *gen.CharacteristicMetadata) []ConstDecl {
if values := constrainedValues(char); values != nil {
name := camelCased(char.Name)
typ := constTypes[char.Format]
Expand Down
14 changes: 8 additions & 6 deletions gen/service.go → gen/golang/service.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package gen
package golang

import (
"bytes"
"fmt"
"text/template"

"github.com/brutella/hc/gen"
)

// ServiceStructTemplate is template for a service struct.
Expand Down Expand Up @@ -45,12 +47,12 @@ type Service struct {
}

// FileName returns the filename for a characteristic
func ServiceFileName(svc *ServiceMetadata) string {
func ServiceFileName(svc *gen.ServiceMetadata) string {
return fmt.Sprintf("%s.go", underscored(svc.Name))
}

// ServiceGoCode returns the o code for a characteristic file
func ServiceGoCode(svc *ServiceMetadata, chars []*CharacteristicMetadata) ([]byte, error) {
func ServiceGoCode(svc *gen.ServiceMetadata, chars []*gen.CharacteristicMetadata) ([]byte, error) {
var err error
var buf bytes.Buffer

Expand All @@ -71,11 +73,11 @@ func ServiceGoCode(svc *ServiceMetadata, chars []*CharacteristicMetadata) ([]byt
}

// Return the name of the characteristic type name
func serviceTypeName(svc *ServiceMetadata) string {
func serviceTypeName(svc *gen.ServiceMetadata) string {
return "Type" + camelCased(svc.Name)
}

func requiredCharacteristics(svc *ServiceMetadata, chars []*CharacteristicMetadata) []*Characteristic {
func requiredCharacteristics(svc *gen.ServiceMetadata, chars []*gen.CharacteristicMetadata) []*Characteristic {
var required = []*Characteristic{}
for _, uuid := range svc.RequiredCharacteristics {
char := charWithUUID(uuid, chars)
Expand All @@ -86,7 +88,7 @@ func requiredCharacteristics(svc *ServiceMetadata, chars []*CharacteristicMetada
return required
}

func charWithUUID(uuid string, chars []*CharacteristicMetadata) *CharacteristicMetadata {
func charWithUUID(uuid string, chars []*gen.CharacteristicMetadata) *gen.CharacteristicMetadata {
for _, char := range chars {
if char.UUID == uuid {
return char
Expand Down
Loading

0 comments on commit 30e563b

Please sign in to comment.