2022-01-23 20:49:06 +01:00
|
|
|
import Vapor
|
|
|
|
|
2022-01-24 17:17:06 +01:00
|
|
|
extension PublicAPI {
|
|
|
|
|
|
|
|
var path: PathComponent {
|
|
|
|
.init(stringLiteral: rawValue)
|
|
|
|
}
|
|
|
|
|
|
|
|
var pathParameter: PathComponent {
|
|
|
|
.parameter(rawValue)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-29 10:26:30 +01:00
|
|
|
private func keyTransmission(_ req: Request) -> EventLoopFuture<KeyResult> {
|
2022-01-24 17:17:06 +01:00
|
|
|
guard let keyId = req.parameters.get(PublicAPI.postKeyIdParameter.rawValue, as: UInt16.self) else {
|
2022-01-29 10:26:30 +01:00
|
|
|
return req.eventLoop.makeSucceededFuture(.invalidKeyIndex)
|
2022-01-24 17:17:06 +01:00
|
|
|
}
|
|
|
|
guard let body = req.body.data else {
|
2022-01-29 10:26:30 +01:00
|
|
|
return req.eventLoop.makeSucceededFuture(.noBodyData)
|
2022-01-24 17:17:06 +01:00
|
|
|
}
|
|
|
|
guard body.readableBytes == KeyManagement.keySize else {
|
2022-01-29 10:26:30 +01:00
|
|
|
return req.eventLoop.makeSucceededFuture(.invalidPayloadSize)
|
2022-01-24 17:17:06 +01:00
|
|
|
}
|
|
|
|
guard let key = body.getData(at: 0, length: KeyManagement.keySize) else {
|
2022-01-29 10:26:30 +01:00
|
|
|
return req.eventLoop.makeSucceededFuture(.corruptkeyData)
|
2022-01-24 17:17:06 +01:00
|
|
|
}
|
2022-01-29 10:26:30 +01:00
|
|
|
return keyManager.sendKeyToDevice(key, keyId: keyId, on: req.eventLoop)
|
2022-01-24 17:17:06 +01:00
|
|
|
}
|
2022-01-23 20:49:06 +01:00
|
|
|
|
|
|
|
func routes(_ app: Application) throws {
|
|
|
|
|
2022-01-24 17:17:06 +01:00
|
|
|
/**
|
|
|
|
Get the connection status of the device.
|
|
|
|
|
|
|
|
The response is a string of either "1" (connected) or "0" (disconnected)
|
|
|
|
*/
|
|
|
|
app.get(PublicAPI.getDeviceStatus.path) { req -> String in
|
|
|
|
keyManager.deviceStatus
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Get the response from the device.
|
|
|
|
|
|
|
|
The response is a string of an integer `rawValue` of a `KeyResult`
|
|
|
|
*/
|
|
|
|
app.get(PublicAPI.getDeviceResponse.path) { req -> String in
|
|
|
|
keyManager.deviceResponse
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Post a request to remove the information about the last key transmission.
|
|
|
|
|
|
|
|
- The request always succeeds and returns the string "Success"
|
|
|
|
*/
|
|
|
|
app.post(PublicAPI.clearKeyRequest.path) { req -> String in
|
|
|
|
keyManager.clearClientRequest()
|
|
|
|
return "Success"
|
|
|
|
}
|
|
|
|
|
2022-01-29 10:26:30 +01:00
|
|
|
|
2022-01-24 17:17:06 +01:00
|
|
|
/**
|
|
|
|
Post a key to the device for unlocking.
|
|
|
|
|
|
|
|
The corresponding integer key id for the key data must be contained in the url path.
|
|
|
|
|
|
|
|
The request returns a string containing a `rawValue` of a `KeyPostResponse`
|
|
|
|
A success of this method does not yet signal successful unlocking.
|
|
|
|
The client should request the status by inquiring the device response.
|
|
|
|
*/
|
2022-01-29 10:26:30 +01:00
|
|
|
app.post(PublicAPI.postKey.path, PublicAPI.postKeyIdParameter.pathParameter) { req in
|
|
|
|
keyTransmission(req).map { String($0.rawValue) }
|
2022-01-23 20:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Start a new websocket connection for the client to receive table updates from the server
|
|
|
|
- Returns: Nothing
|
|
|
|
- Note: The first (and only) message from the client over the connection must be a valid session token.
|
|
|
|
*/
|
2022-01-24 17:17:06 +01:00
|
|
|
app.webSocket(PublicAPI.socket.path) { req, socket in
|
|
|
|
socket.onBinary { _, data in
|
|
|
|
keyManager.processDeviceResponse(data)
|
2022-01-23 20:49:06 +01:00
|
|
|
}
|
2022-01-24 17:17:06 +01:00
|
|
|
socket.onText { _, text in
|
|
|
|
keyManager.authenticateDevice(psk: text)
|
2022-01-23 20:49:06 +01:00
|
|
|
}
|
|
|
|
|
2022-01-24 17:17:06 +01:00
|
|
|
_ = socket.onClose.always { _ in
|
|
|
|
keyManager.didCloseDeviceSocket()
|
2022-01-23 20:49:06 +01:00
|
|
|
}
|
2022-01-24 17:17:06 +01:00
|
|
|
keyManager.createNewDeviceConnection(socket)
|
2022-01-23 20:49:06 +01:00
|
|
|
}
|
|
|
|
}
|