import Vapor import SwiftyGPIO var apns: APNSInterface? var tokenStorage: TokenStorage! // configures your application public func configure(_ app: Application) throws { let resourcesFolderUrl = URL(fileURLWithPath: app.directory.resourcesDirectory) let configUrl = resourcesFolderUrl.appendingPathComponent("config.json") let config: ServerConfiguration do { let data = try Data(contentsOf: configUrl) config = try JSONDecoder().decode(from: data) } catch { print("Failed to load config from \(configUrl.path): \(error)") return } Log.set(logFile: URL(fileURLWithPath: config.logPath)) tokenStorage = .init(in: resourcesFolderUrl) app.http.server.configuration.port = config.port apns = .init(config) guard apns != nil else { serverStatus = .failedToStart return } configureGPIO(config) // register routes try routes(app) serverStatus = .running log(info: "Server is running") } private extension JSONDecoder { func decode(from data: Data) throws -> T where T: Decodable { try self.decode(T.self, from: data) } } private func configureGPIO(_ config: ServerConfiguration) { let gpio = RaspberryGPIO( name: "GPIO\(config.buttonPin)", id: config.buttonPin, baseAddr: 0x7E000000) gpio.direction = .IN gpio.pull = .down gpio.bounceTime = config.bounceTime gpio.onChange { _ in log(info: "Push detected") sendPush() } log(info: "GPIO \(config.buttonPin) configured") } private func sendPush() { guard !tokenStorage.tokens.isEmpty else { log(info: "No tokens registered to send push") return } Task(priority: .userInitiated) { await apns?.sendPush(to: tokenStorage.tokens) } }