Skip to content

Commit

Permalink
Refactor to resource specific routes
Browse files Browse the repository at this point in the history
  • Loading branch information
kellyp committed Feb 29, 2024
1 parent 9a77945 commit e0ec9d1
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 221 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ DerivedData/

build/

default.profraw

#####
# Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups)
Expand Down
12 changes: 12 additions & 0 deletions prefab.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
A28EE47D2B8C29010042FAA0 /* Routes+Homes.swift in Sources */ = {isa = PBXBuildFile; fileRef = A28EE47C2B8C29010042FAA0 /* Routes+Homes.swift */; };
A28EE47F2B8C29610042FAA0 /* Routes+Rooms.swift in Sources */ = {isa = PBXBuildFile; fileRef = A28EE47E2B8C29610042FAA0 /* Routes+Rooms.swift */; };
A28EE4812B8C29AE0042FAA0 /* Routes+Accessories.swift in Sources */ = {isa = PBXBuildFile; fileRef = A28EE4802B8C29AE0042FAA0 /* Routes+Accessories.swift */; };
CB78182B2B7D802B0077671A /* prefabApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB78182A2B7D802B0077671A /* prefabApp.swift */; };
CB78182D2B7D802B0077671A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB78182C2B7D802B0077671A /* ContentView.swift */; };
CB78182F2B7D802B0077671A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CB78182E2B7D802B0077671A /* Assets.xcassets */; };
Expand Down Expand Up @@ -90,6 +93,9 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
A28EE47C2B8C29010042FAA0 /* Routes+Homes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Routes+Homes.swift"; sourceTree = "<group>"; };
A28EE47E2B8C29610042FAA0 /* Routes+Rooms.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Routes+Rooms.swift"; sourceTree = "<group>"; };
A28EE4802B8C29AE0042FAA0 /* Routes+Accessories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Routes+Accessories.swift"; sourceTree = "<group>"; };
CB7818272B7D802B0077671A /* Prefab.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Prefab.app; sourceTree = BUILT_PRODUCTS_DIR; };
CB78182A2B7D802B0077671A /* prefabApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = prefabApp.swift; sourceTree = "<group>"; };
CB78182C2B7D802B0077671A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -219,6 +225,9 @@
CB9C51872B7D8493007C1AD4 /* Data.swift */,
CB9C51882B7D8493007C1AD4 /* Server.swift */,
CB9C51892B7D8493007C1AD4 /* Routes.swift */,
A28EE4802B8C29AE0042FAA0 /* Routes+Accessories.swift */,
A28EE47C2B8C29010042FAA0 /* Routes+Homes.swift */,
A28EE47E2B8C29610042FAA0 /* Routes+Rooms.swift */,
);
path = http;
sourceTree = "<group>";
Expand Down Expand Up @@ -431,7 +440,10 @@
files = (
CB78182D2B7D802B0077671A /* ContentView.swift in Sources */,
CB9C518A2B7D8493007C1AD4 /* Data.swift in Sources */,
A28EE47F2B8C29610042FAA0 /* Routes+Rooms.swift in Sources */,
A28EE4812B8C29AE0042FAA0 /* Routes+Accessories.swift in Sources */,
CB9C518C2B7D8493007C1AD4 /* Routes.swift in Sources */,
A28EE47D2B8C29010042FAA0 /* Routes+Homes.swift in Sources */,
CB9C518B2B7D8493007C1AD4 /* Server.swift in Sources */,
CB9C518F2B7D849D007C1AD4 /* HomeBase.swift in Sources */,
CB78182B2B7D802B0077671A /* prefabApp.swift in Sources */,
Expand Down
125 changes: 125 additions & 0 deletions prefab/http/Routes+Accessories.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// Routes+Accessories.swift
// Prefab
//
// Created by kelly on 2/25/24.
//

import Foundation
import HomeKit
import Hummingbird
import OSLog

extension Server {
func getAccessories(_ request: HBRequest) throws -> String {
let homeName = try getRequiredParam(param: "home", request: request)
let roomName = try getRequiredParam(param: "room", request: request)
let home = homeBase.homes.first(where: {$0.name == homeName.removingPercentEncoding})
if (home == nil) {
throw HBHTTPError(.notFound)
}
let room = home?.rooms.first(where: {$0.name == roomName.removingPercentEncoding})
if (room == nil) {
throw HBHTTPError(.notFound)
}

let accessories = room?.accessories.map{ (hmAccessory: HMAccessory) -> Accessory in Accessory(home: home!.name, room: room!.name, name: hmAccessory.name)}
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(accessories)
let json = String(data: jsonData, encoding: String.Encoding.utf8)

return json!
}


func getAccessory(_ request: HBRequest) throws -> String {
let homeName = try getRequiredParam(param: "home", request: request)
let roomName = try getRequiredParam(param: "room", request: request)
let accessoryName = try getRequiredParam(param: "accessory", request: request)

let home = homeBase.homes.first(where: {$0.name == homeName.removingPercentEncoding})
if (home == nil) {
throw HBHTTPError(.notFound)
}
let room = home?.rooms.first(where: {$0.name == roomName.removingPercentEncoding})
if (room == nil) {
throw HBHTTPError(.notFound)
}
let hkAccessory = room?.accessories.first(where: { (hmAccessory: HMAccessory) -> Bool in hmAccessory.name == accessoryName.removingPercentEncoding})
if (hkAccessory == nil) {
throw HBHTTPError(.notFound)
}

let group = DispatchGroup()
for service in hkAccessory!.services {
for char in service.characteristics {
group.enter()
// Error handling for read
char.readValue{ (error: Error?) -> Void in group.leave() }
}
}
group.wait()

let accessory = Accessory(
home: home!.name, room: room!.name, name: hkAccessory!.name, category: hkAccessory!.category.categoryType, isReachable: hkAccessory!.isReachable, supportsIdentify: hkAccessory!.supportsIdentify, isBridged: hkAccessory!.isBridged, services: hkAccessory!.services.map{ (service: HMService) -> Service in Service(uniqueIdentifier: service.uniqueIdentifier, name: service.name, type: service.serviceType, isPrimary: service.isPrimaryService, isUserInteractive: service.isUserInteractive, associatedType: service.associatedServiceType, characteristics: service.characteristics.map{ (char: HMCharacteristic) -> Characteristic in Characteristic(uniqueIdentifier: char.uniqueIdentifier, description: char.localizedDescription, properties: char.properties, type: char.characteristicType, metadata: CharacteristicMetadata(manufacturerDescription: char.metadata?.manufacturerDescription, validValues: char.metadata?.validValues?.map{ (number: NSNumber) -> String in return number.stringValue}, minimumValue: char.metadata?.minimumValue?.stringValue, maximumValue: char.metadata?.maximumValue?.stringValue, stepValue: char.metadata?.stepValue?.stringValue, maxLength: char.metadata?.maxLength?.stringValue, format: char.metadata?.format, units: char.metadata?.units), value: "\(char.value ?? "")" )}) }, firmwareVersion: hkAccessory!.firmwareVersion, manufacturer: hkAccessory!.manufacturer, model: hkAccessory!.model )

let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(accessory)
let json = String(data: jsonData, encoding: String.Encoding.utf8)

return json!
}



func updateAccessory(_ request: HBRequest) throws -> String {
var updateAccessoryInput: UpdateAccessoryInput
do {
updateAccessoryInput = try JSONDecoder().decode(UpdateAccessoryInput.self, from: request.body.buffer!)
} catch {
throw HBHTTPError(
.badRequest,
message: "Invalid update object."
)
}

let homeName = try getRequiredParam(param: "home", request: request)
let roomName = try getRequiredParam(param: "room", request: request)
let accessoryName = try getRequiredParam(param: "accessory", request: request)

let home = homeBase.homes.first(where: {$0.name == homeName.removingPercentEncoding})
if (home == nil) {
throw HBHTTPError(.notFound)
}
let room = home?.rooms.first(where: {$0.name == roomName.removingPercentEncoding})
if (room == nil) {
throw HBHTTPError(.notFound)
}
let hkAccessory = room?.accessories.first(where: { (hmAccessory: HMAccessory) -> Bool in hmAccessory.name == accessoryName.removingPercentEncoding})
if (hkAccessory == nil) {
throw HBHTTPError(.notFound)
}

let hkService = hkAccessory?.services.first(where: { (hmService: HMService) -> Bool in hmService.uniqueIdentifier.uuidString == updateAccessoryInput.serviceId})
if (hkAccessory == nil) {
Logger().debug("Service not found \(updateAccessoryInput.serviceId)")
throw HBHTTPError(.notFound)
}

let hkChar = hkService?.characteristics.first(where: { (hmChar: HMCharacteristic) -> Bool in hmChar.uniqueIdentifier.uuidString == updateAccessoryInput.characteristicId})
if (hkAccessory == nil) {
Logger().debug("Characteristic not found \(updateAccessoryInput.characteristicId)")
throw HBHTTPError(.notFound)
}


Logger().debug("Writing \(updateAccessoryInput.value) to \(hkChar)")

let group = DispatchGroup()
group.enter()
hkChar?.writeValue(try GetValue(value: updateAccessoryInput.value, format: hkChar?.metadata?.format ?? ""), completionHandler: { (error: Error?) -> Void in defer {group.leave()}; Logger().error("\(String(describing: error))") })
group.wait()

return "" //json!
}
}
32 changes: 32 additions & 0 deletions prefab/http/Routes+Homes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Routes+Homes.swift
// Prefab
//
// Created by kelly on 2/25/24.
//

import Foundation
import Hummingbird

extension Server {
func getHomes(_ request: HBRequest) throws -> String {
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(homeBase.homes.map{Home(name: $0.name)})
let json = String(data: jsonData, encoding: String.Encoding.utf8)

return json ?? "[]"
}

func getHome(_ request: HBRequest) throws -> String {
let homeName = try getRequiredParam(param: "home", request: request)
let home = homeBase.homes.first(where: {$0.name == homeName.removingPercentEncoding})
if (home == nil) {
throw HBHTTPError(.notFound)
}
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(Home(name: home!.name))
let json = String(data: jsonData, encoding: String.Encoding.utf8)

return json!
}
}
43 changes: 43 additions & 0 deletions prefab/http/Routes+Rooms.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// Routes+Rooms.swift
// Prefab
//
// Created by kelly on 2/25/24.
//

import Foundation
import Hummingbird

extension Server {
func getRooms(_ request: HBRequest) throws -> String {
let homeName = try getRequiredParam(param: "home", request: request)
let home = homeBase.homes.first(where: {$0.name == homeName.removingPercentEncoding})
if (home == nil) {
throw HBHTTPError(.notFound)
}
let rooms = home?.rooms.map{Room(home: home!.name, name: $0.name)}
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(rooms)
let json = String(data: jsonData, encoding: String.Encoding.utf8)

return json!
}

func getRoom(_ request: HBRequest) throws -> String {
let homeName = try getRequiredParam(param: "home", request: request)
let roomName = try getRequiredParam(param: "room", request: request)
let home = homeBase.homes.first(where: {$0.name == homeName.removingPercentEncoding})
if (home == nil) {
throw HBHTTPError(.notFound)
}
let room = home?.rooms.first(where: {$0.name == roomName.removingPercentEncoding})
if (room == nil) {
throw HBHTTPError(.notFound)
}
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(Room(home: home!.name, name: room!.name))
let json = String(data: jsonData, encoding: String.Encoding.utf8)

return json!
}
}
Loading

0 comments on commit e0ec9d1

Please sign in to comment.