V0.6.5 Arroyo Toad
Added configuration to send messages V0.6.5.a Arroyo Toad Problems with a detached head
This commit is contained in:
parent
c2539d2250
commit
9f86b58aba
43
.vscode/launch.json
vendored
43
.vscode/launch.json
vendored
@ -1,22 +1,23 @@
|
|||||||
{
|
{
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder:workspace}",
|
"cwd": "${workspaceFolder:workspace}",
|
||||||
"name": "Debug IoT-Simulator",
|
"name": "Debug IoT-Simulator",
|
||||||
"program": "${workspaceFolder:workspace}/.build/debug/IoT-Simulator",
|
"envFile": "${workspaceFolder}/env/debug/.debug.env",
|
||||||
"preLaunchTask": "swift: Build Debug IoT-Simulator"
|
"program": "${workspaceFolder}/.build/debug/App",
|
||||||
},
|
"preLaunchTask": "swift: Build Debug IoT-Simulator"
|
||||||
{
|
},
|
||||||
"type": "lldb",
|
{
|
||||||
"request": "launch",
|
"type": "lldb",
|
||||||
"args": [],
|
"request": "launch",
|
||||||
"cwd": "${workspaceFolder:workspace}",
|
"args": [],
|
||||||
"name": "Release IoT-Simulator",
|
"cwd": "${workspaceFolder:workspace}",
|
||||||
"program": "${workspaceFolder:workspace}/.build/release/IoT-Simulator",
|
"name": "Release IoT-Simulator",
|
||||||
"preLaunchTask": "swift: Build Release IoT-Simulator"
|
"program": "${workspaceFolder:workspace}/.build/release/IoT-Simulator",
|
||||||
}
|
"preLaunchTask": "swift: Build Release IoT-Simulator"
|
||||||
]
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
70
Sources/App/CustomCode/Utils/P256-keys-creation.swift
Normal file
70
Sources/App/CustomCode/Utils/P256-keys-creation.swift
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import Foundation
|
||||||
|
import FoundationNetworking
|
||||||
|
import Crypto
|
||||||
|
|
||||||
|
public func createPrivateP256Key() -> P256.Signing.PrivateKey {
|
||||||
|
return P256.Signing.PrivateKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func createPublickP256Key(privateKey: P256.Signing.PrivateKey ) -> P256.Signing.PublicKey {
|
||||||
|
return privateKey.publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
public func publicP256_2_Spki(publicKey: P256.Signing.PublicKey) -> String {
|
||||||
|
return publicKey.pemRepresentation
|
||||||
|
}
|
||||||
|
|
||||||
|
public func privateP256_2_pem(privateKey: P256.Signing.PrivateKey) -> String {
|
||||||
|
return privateKey.pemRepresentation
|
||||||
|
}
|
||||||
|
|
||||||
|
// UGLY: Refactor to make it easier to comprehend
|
||||||
|
public func fetchPrivateP256Key(deviceID: UInt) async throws -> P256.Signing.PrivateKey {
|
||||||
|
|
||||||
|
// UGLY: but fast
|
||||||
|
let privateKeyFolder = ProcessInfo.processInfo.environment["PRIVATE_KEY_FOLDER"] ?? "./Private/PrivateKeysP256"
|
||||||
|
|
||||||
|
let keyFilePath = "\(privateKeyFolder)/\(deviceID)-Kr.pem"
|
||||||
|
|
||||||
|
do {
|
||||||
|
let key = try pem2_P265_PrivateKey(filePath: keyFilePath)
|
||||||
|
// TODO: send public key to another server
|
||||||
|
|
||||||
|
|
||||||
|
return key
|
||||||
|
} catch {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let key = createPrivateP256Key()
|
||||||
|
|
||||||
|
let publicKey = key.publicKey.pemRepresentation
|
||||||
|
|
||||||
|
try privateP256_2_pem(privateKey: key).write(to: URL(filePath: keyFilePath), atomically: true, encoding: String.Encoding.utf8)
|
||||||
|
|
||||||
|
|
||||||
|
// UGLY: hardcoded
|
||||||
|
var httpRequest = URLRequest(url: URL(string: "http://public-key-db.internal/key")!)
|
||||||
|
httpRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
|
httpRequest.httpMethod = "POST"
|
||||||
|
|
||||||
|
let message = PublicKeyMessage(deviceID: deviceID, publicKey: publicKey)
|
||||||
|
let encoder = JSONEncoder()
|
||||||
|
let data = try encoder.encode(message)
|
||||||
|
httpRequest.httpBody = data
|
||||||
|
|
||||||
|
let _ = try await URLSession.shared.upload(for: httpRequest, from: data)
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func pem2_P265_PrivateKey(filePath: String) throws -> P256.Signing.PrivateKey {
|
||||||
|
|
||||||
|
let pemEncodedKey = try String(contentsOf: URL(filePath: filePath), encoding: .utf8)
|
||||||
|
return try P256.Signing.PrivateKey(pemRepresentation: pemEncodedKey)
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,31 +1,37 @@
|
|||||||
import Vapor
|
import Vapor
|
||||||
import Logging
|
import Logging
|
||||||
import NIOCore
|
import NIOCore
|
||||||
import NIOPosix
|
import NIOPosix
|
||||||
|
|
||||||
@main
|
@main
|
||||||
enum Entrypoint {
|
enum Entrypoint {
|
||||||
static func main() async throws {
|
static func main() async throws {
|
||||||
var env = try Environment.detect()
|
var env = try Environment.detect()
|
||||||
try LoggingSystem.bootstrap(from: &env)
|
try LoggingSystem.bootstrap(from: &env)
|
||||||
|
|
||||||
let app = try await Application.make(env)
|
let app = try await Application.make(env)
|
||||||
|
|
||||||
// This attempts to install NIO as the Swift Concurrency global executor.
|
// This attempts to install NIO as the Swift Concurrency global executor.
|
||||||
// You can enable it if you'd like to reduce the amount of context switching between NIO and Swift Concurrency.
|
// You can enable it if you'd like to reduce the amount of context switching between NIO and Swift Concurrency.
|
||||||
// Note: this has caused issues with some libraries that use `.wait()` and cleanly shutting down.
|
// Note: this has caused issues with some libraries that use `.wait()` and cleanly shutting down.
|
||||||
// If enabled, you should be careful about calling async functions before this point as it can cause assertion failures.
|
// If enabled, you should be careful about calling async functions before this point as it can cause assertion failures.
|
||||||
// let executorTakeoverSuccess = NIOSingletons.unsafeTryInstallSingletonPosixEventLoopGroupAsConcurrencyGlobalExecutor()
|
// let executorTakeoverSuccess = NIOSingletons.unsafeTryInstallSingletonPosixEventLoopGroupAsConcurrencyGlobalExecutor()
|
||||||
// app.logger.debug("Tried to install SwiftNIO's EventLoopGroup as Swift's global concurrency executor", metadata: ["success": .stringConvertible(executorTakeoverSuccess)])
|
// app.logger.debug("Tried to install SwiftNIO's EventLoopGroup as Swift's global concurrency executor", metadata: ["success": .stringConvertible(executorTakeoverSuccess)])
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await configure(app)
|
try await configure(app)
|
||||||
} catch {
|
} catch {
|
||||||
app.logger.report(error: error)
|
app.logger.report(error: error)
|
||||||
try? await app.asyncShutdown()
|
try? await app.asyncShutdown()
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
try await app.execute()
|
|
||||||
try await app.asyncShutdown()
|
do {
|
||||||
}
|
try await configureSimulator()
|
||||||
}
|
} catch {
|
||||||
|
print("\(error)")
|
||||||
|
}
|
||||||
|
try await app.execute()
|
||||||
|
try await app.asyncShutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
144
Sources/App/simulator-configuration.swift
Normal file
144
Sources/App/simulator-configuration.swift
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import Crypto
|
||||||
|
import Foundation
|
||||||
|
import FoundationNetworking
|
||||||
|
import IoT_Simulator_Core
|
||||||
|
import MessageUtils
|
||||||
|
|
||||||
|
public func configureSimulator() async throws {
|
||||||
|
|
||||||
|
guard
|
||||||
|
let configurationFilePath: String = ProcessInfo.processInfo.environment[
|
||||||
|
"CONFIGURATION_FILE"]
|
||||||
|
else {
|
||||||
|
throw ParsingError.ConfigFileNotExistent
|
||||||
|
}
|
||||||
|
|
||||||
|
let jsonData: Data = try Data(contentsOf: URL(filePath: configurationFilePath))
|
||||||
|
|
||||||
|
guard
|
||||||
|
let jsonObject: [String: Any] = try JSONSerialization.jsonObject(with: jsonData)
|
||||||
|
as? [String: Any]
|
||||||
|
else {
|
||||||
|
throw ParsingError.MalformedJSON(reason: "This is not a JSON file")
|
||||||
|
}
|
||||||
|
|
||||||
|
try await jsonConfigurationParser(jsonObject)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func jsonConfigurationParser(_ json: [String: Any]) async throws {
|
||||||
|
|
||||||
|
guard
|
||||||
|
let version = json["version"] as? Int,
|
||||||
|
let environments = json["environments"] as? [[String: Any]]
|
||||||
|
else {
|
||||||
|
throw ParsingError.MalformedJSON(reason: "Missing either version or environemnt")
|
||||||
|
}
|
||||||
|
|
||||||
|
for environmentJSON in environments {
|
||||||
|
|
||||||
|
let env = try json2env(environmentJSON)
|
||||||
|
|
||||||
|
IoTSimulatorCore.addEnv(environment: env)
|
||||||
|
|
||||||
|
if let devices = environmentJSON["devices"] as? [[String: Any]] {
|
||||||
|
for deviceJSON in devices {
|
||||||
|
let devices = try await json2edge_dev(deviceJSON)
|
||||||
|
|
||||||
|
for dev in devices {
|
||||||
|
try IoTSimulatorCore.addDevice(location: env.location, device: dev) { msg in
|
||||||
|
// UGLY: But fast
|
||||||
|
// TODO: add sending code here
|
||||||
|
let backendURL = ProcessInfo.processInfo.environment["BACKEND_URL"]!
|
||||||
|
|
||||||
|
var httpRequest = URLRequest(url: URL(string: backendURL)!)
|
||||||
|
httpRequest.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type")
|
||||||
|
httpRequest.httpMethod = "POST"
|
||||||
|
|
||||||
|
httpRequest.httpBody = msg
|
||||||
|
let _ = try await URLSession.shared.upload(for: httpRequest, from: msg)
|
||||||
|
|
||||||
|
} failure: {
|
||||||
|
print("Failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func json2env(_ json: [String: Any]) throws -> PhysicalEnvironment {
|
||||||
|
|
||||||
|
guard
|
||||||
|
let envName = json["name"] as? String
|
||||||
|
else {
|
||||||
|
throw ParsingError.MalformedJSON(reason: "Missing name of environment")
|
||||||
|
}
|
||||||
|
|
||||||
|
let environment = PhysicalEnvironment(envName)
|
||||||
|
|
||||||
|
if let physicalData = json["physicalData"] as? [[String: Any]] {
|
||||||
|
|
||||||
|
for physicalDatum in physicalData {
|
||||||
|
guard
|
||||||
|
let dataTypeString = physicalDatum["dataType"] as? String,
|
||||||
|
let value = physicalDatum["value"] as? Double,
|
||||||
|
let dataType = DataType(rawValue: dataTypeString)
|
||||||
|
else {
|
||||||
|
throw ParsingError.MalformedJSON(reason: "Physical Data is Misconfigured")
|
||||||
|
}
|
||||||
|
|
||||||
|
let datum = PhysicalData(dataType, Float(value))
|
||||||
|
environment.setPhysicalData(datum.type, datum)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return environment
|
||||||
|
}
|
||||||
|
|
||||||
|
private func json2edge_dev(_ json: [String: Any]) async throws -> [EdgeDevice] {
|
||||||
|
|
||||||
|
var devices: [EdgeDevice] = []
|
||||||
|
|
||||||
|
guard
|
||||||
|
let _dataType = json["dataType"] as? String,
|
||||||
|
let dataType = DataType(rawValue: _dataType)
|
||||||
|
else {
|
||||||
|
throw ParsingError.MalformedJSON(reason: "Data Type missing in one device")
|
||||||
|
}
|
||||||
|
|
||||||
|
if let number = json["number"] as? UInt {
|
||||||
|
for _ in 0..<number {
|
||||||
|
let deviceID = try DeviceFactory.getUnusedID()
|
||||||
|
let privateKey = try await fetchPrivateP256Key(deviceID: UInt(deviceID))
|
||||||
|
|
||||||
|
// TODO: Get ID from DeviceFactory and push ID inside
|
||||||
|
devices.append(
|
||||||
|
try await DeviceFactory.createEdgeDevice(
|
||||||
|
deviceID: deviceID,
|
||||||
|
dataType: dataType,
|
||||||
|
privateKey: privateKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// UGLY: Silent Bug, coul dhave both deviceID and number, but other properties would
|
||||||
|
// UGLY: be ignored
|
||||||
|
return devices
|
||||||
|
}
|
||||||
|
|
||||||
|
guard
|
||||||
|
let deviceID = json["deviceID"] as? UInt
|
||||||
|
else {
|
||||||
|
throw ParsingError.MalformedJSON(
|
||||||
|
reason: "Missing deviceID and number properties"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check for other optionals
|
||||||
|
|
||||||
|
return devices
|
||||||
|
|
||||||
|
}
|
||||||
3
env/debug/.debug.env
vendored
Normal file
3
env/debug/.debug.env
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
BACKEND_URL=http://iot-data-backend.internal/iot-data/api/v1/data
|
||||||
|
CONFIGURATION_FILE=./Config/debug.json
|
||||||
|
PRIVATE_KEY_FOLDER=./Private/PrivateKeysP256
|
||||||
3
env/debug/.debug.env.example
vendored
Normal file
3
env/debug/.debug.env.example
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
BACKEND_URL=http://iot-data-backend.internal/iot-data/api/v1/data
|
||||||
|
CONFIGURATION_FILE=./Config/debug.json
|
||||||
|
PRIVATE_KEY_FOLDER=./Private/PrivateKeysP256
|
||||||
Loading…
x
Reference in New Issue
Block a user