Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions BuildTools/.swiftformat
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
--exclude ../OpenHABCore/Sources/OpenHABCore/GeneratedSources
--exclude ../OsLogRewriter/.build
--exclude ../build
--exclude ../CommonUI/.build
--symlinks ignore

# disabled rules
Expand Down
1 change: 1 addition & 0 deletions BuildTools/.swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ excluded:
- ../OsLogRewriter/.build
- ../build
- ../BonjourDiscoveryTool
- ../CommonUI/.build

nesting:
type_level: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,18 @@ public struct Client: APIProtocol {
method: .post
)
suppressMutabilityWarning(&request)
try converter.setHeaderFieldAsURI(
in: &request.headerFields,
name: "X-OpenHAB-Source",
value: input.headers.X_hyphen_OpenHAB_hyphen_Source
)
try converter.setQueryItemAsURI(
in: &request,
style: .form,
explode: true,
name: "source",
value: input.query.source
)
let body: OpenAPIRuntime.HTTPBody?
switch input.body {
case let .plainText(value):
Expand All @@ -1448,6 +1460,12 @@ public struct Client: APIProtocol {
headerFields: &request.headerFields,
contentType: "text/plain"
)
case let .json(value):
body = try converter.setRequiredRequestBodyAsJSON(
value,
headerFields: &request.headerFields,
contentType: "application/json; charset=utf-8"
)
}
return (request, body)
},
Expand Down Expand Up @@ -1862,6 +1880,18 @@ public struct Client: APIProtocol {
name: "Accept-Language",
value: input.headers.Accept_hyphen_Language
)
try converter.setHeaderFieldAsURI(
in: &request.headerFields,
name: "X-OpenHAB-Source",
value: input.headers.X_hyphen_OpenHAB_hyphen_Source
)
try converter.setQueryItemAsURI(
in: &request,
style: .form,
explode: true,
name: "source",
value: input.query.source
)
let body: OpenAPIRuntime.HTTPBody?
switch input.body {
case let .plainText(value):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,10 +558,14 @@ extension APIProtocol {
/// - Remark: Generated from `#/paths//items/{itemname}/post(sendItemCommand)`.
public func sendItemCommand(
path: Operations.sendItemCommand.Input.Path,
query: Operations.sendItemCommand.Input.Query = .init(),
headers: Operations.sendItemCommand.Input.Headers = .init(),
body: Operations.sendItemCommand.Input.Body
) async throws -> Operations.sendItemCommand.Output {
try await sendItemCommand(Operations.sendItemCommand.Input(
path: path,
query: query,
headers: headers,
body: body
))
}
Expand Down Expand Up @@ -632,11 +636,13 @@ extension APIProtocol {
/// - Remark: Generated from `#/paths//items/{itemname}/state/put(updateItemState)`.
public func updateItemState(
path: Operations.updateItemState.Input.Path,
query: Operations.updateItemState.Input.Query = .init(),
headers: Operations.updateItemState.Input.Headers = .init(),
body: Operations.updateItemState.Input.Body
) async throws -> Operations.updateItemState.Output {
try await updateItemState(Operations.updateItemState.Input(
path: path,
query: query,
headers: headers,
body: body
))
Expand Down Expand Up @@ -7964,22 +7970,60 @@ public enum Operations {
}
}
public var path: Operations.sendItemCommand.Input.Path
/// - Remark: Generated from `#/paths/items/{itemname}/POST/query`.
public struct Query: Sendable, Hashable {
/// the source of the command
///
/// - Remark: Generated from `#/paths/items/{itemname}/POST/query/source`.
public var source: Swift.String?
/// Creates a new `Query`.
///
/// - Parameters:
/// - source: the source of the command
public init(source: Swift.String? = nil) {
self.source = source
}
}
public var query: Operations.sendItemCommand.Input.Query
/// - Remark: Generated from `#/paths/items/{itemname}/POST/header`.
public struct Headers: Sendable, Hashable {
/// the source of the command; takes priority over the query parameter or JSON body if multiple are set
///
/// - Remark: Generated from `#/paths/items/{itemname}/POST/header/X-OpenHAB-Source`.
public var X_hyphen_OpenHAB_hyphen_Source: Swift.String?
/// Creates a new `Headers`.
///
/// - Parameters:
/// - X_hyphen_OpenHAB_hyphen_Source: the source of the command; takes priority over the query parameter or JSON body if multiple are set
public init(X_hyphen_OpenHAB_hyphen_Source: Swift.String? = nil) {
self.X_hyphen_OpenHAB_hyphen_Source = X_hyphen_OpenHAB_hyphen_Source
}
}
public var headers: Operations.sendItemCommand.Input.Headers
/// - Remark: Generated from `#/paths/items/{itemname}/POST/requestBody`.
@frozen public enum Body: Sendable, Hashable {
/// - Remark: Generated from `#/paths/items/{itemname}/POST/requestBody/content/text\/plain`.
case plainText(OpenAPIRuntime.HTTPBody)
/// - Remark: Generated from `#/paths/items/{itemname}/POST/requestBody/content/application\/json`.
case json(Swift.String)
}
public var body: Operations.sendItemCommand.Input.Body
/// Creates a new `Input`.
///
/// - Parameters:
/// - path:
/// - query:
/// - headers:
/// - body:
public init(
path: Operations.sendItemCommand.Input.Path,
query: Operations.sendItemCommand.Input.Query = .init(),
headers: Operations.sendItemCommand.Input.Headers = .init(),
body: Operations.sendItemCommand.Input.Body
) {
self.path = path
self.query = query
self.headers = headers
self.body = body
}
}
Expand Down Expand Up @@ -9009,18 +9053,42 @@ public enum Operations {
}
}
public var path: Operations.updateItemState.Input.Path
/// - Remark: Generated from `#/paths/items/{itemname}/state/PUT/query`.
public struct Query: Sendable, Hashable {
/// the source of the event
///
/// - Remark: Generated from `#/paths/items/{itemname}/state/PUT/query/source`.
public var source: Swift.String?
/// Creates a new `Query`.
///
/// - Parameters:
/// - source: the source of the event
public init(source: Swift.String? = nil) {
self.source = source
}
}
public var query: Operations.updateItemState.Input.Query
/// - Remark: Generated from `#/paths/items/{itemname}/state/PUT/header`.
public struct Headers: Sendable, Hashable {
/// language
///
/// - Remark: Generated from `#/paths/items/{itemname}/state/PUT/header/Accept-Language`.
public var Accept_hyphen_Language: Swift.String?
/// the source of the event; takes priority over the query parameter or JSON body if multiple are set
///
/// - Remark: Generated from `#/paths/items/{itemname}/state/PUT/header/X-OpenHAB-Source`.
public var X_hyphen_OpenHAB_hyphen_Source: Swift.String?
/// Creates a new `Headers`.
///
/// - Parameters:
/// - Accept_hyphen_Language: language
public init(Accept_hyphen_Language: Swift.String? = nil) {
/// - X_hyphen_OpenHAB_hyphen_Source: the source of the event; takes priority over the query parameter or JSON body if multiple are set
public init(
Accept_hyphen_Language: Swift.String? = nil,
X_hyphen_OpenHAB_hyphen_Source: Swift.String? = nil
) {
self.Accept_hyphen_Language = Accept_hyphen_Language
self.X_hyphen_OpenHAB_hyphen_Source = X_hyphen_OpenHAB_hyphen_Source
}
}
public var headers: Operations.updateItemState.Input.Headers
Expand All @@ -9034,14 +9102,17 @@ public enum Operations {
///
/// - Parameters:
/// - path:
/// - query:
/// - headers:
/// - body:
public init(
path: Operations.updateItemState.Input.Path,
query: Operations.updateItemState.Input.Query = .init(),
headers: Operations.updateItemState.Input.Headers = .init(),
body: Operations.updateItemState.Input.Body
) {
self.path = path
self.query = query
self.headers = headers
self.body = body
}
Expand Down
4 changes: 2 additions & 2 deletions OpenHABCore/Sources/OpenHABCore/Util/NetworkTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -528,11 +528,11 @@ public extension NetworkTracker {
}

func send(to item: String, command: String) async throws {
try await service().sendItemCommand(itemname: item, command: command)
try await service().sendItemCommand(itemname: item, command: command, sourcePrefix: nil, deviceId: nil)
}

func updateState(item: OpenHABItem, state: String) async throws {
try await service().updateItemState(itemname: item.name, with: state)
try await service().updateItemState(itemname: item.name, with: state, sourcePrefix: nil, deviceId: nil)
}

func getStaticItems() async throws -> [OpenHABItem] {
Expand Down
32 changes: 26 additions & 6 deletions OpenHABCore/Sources/OpenHABCore/Util/OpenAPIService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public enum OpenAPIServiceConfiguration {
protocol OpenAPIServiceProtocol: AnyObject, Sendable {
func getRootVersion() async throws -> Int
@discardableResult func getRoot() async throws -> OpenHABServerProperties
func sendItemCommand(itemname: String, command: String) async throws
func updateItemState(itemname: String, with: String) async throws
func sendItemCommand(itemname: String, command: String, sourcePrefix: String?, deviceId: String?) async throws
func updateItemState(itemname: String, with: String, sourcePrefix: String?, deviceId: String?) async throws
func getItems() async throws -> [OpenHABItem]
func getItems(
query: Operations.getItems.Input.Query
Expand Down Expand Up @@ -115,6 +115,24 @@ public actor OpenAPIService {
// config.timeoutIntervalForResource = config.timeoutIntervalForRequest + 25
return config
}

private func sourceComponent(deviceId: String?) -> String? {
let base = "org.openhab.ios"
guard let deviceId else { return base }
let trimmed = deviceId.trimmingCharacters(in: .whitespacesAndNewlines)
// Actor must not include the delegation separator per openHAB source spec.
if trimmed.isEmpty || trimmed.contains("=>") {
return base
}
return "\(base)$\(trimmed)"
Comment thread
timbms marked this conversation as resolved.
}

private func buildSource(sourcePrefix: String?, deviceId: String?) -> String? {
let base = sourceComponent(deviceId: deviceId)
guard let sourcePrefix, !sourcePrefix.isEmpty else { return base }
guard let base else { return sourcePrefix }
return "\(sourcePrefix)=>\(base)"
}
}

public extension OpenAPIService {
Expand Down Expand Up @@ -333,17 +351,19 @@ public extension OpenAPIService {
// MARK: State changes and commands

public extension OpenAPIService {
func updateItemState(itemname: String, with state: String) async throws {
func updateItemState(itemname: String, with state: String, sourcePrefix: String? = nil, deviceId: String? = nil) async throws {
let path = Operations.updateItemState.Input.Path(itemname: itemname)
let body = Operations.updateItemState.Input.Body.plainText(.init(state))
let response = try await client.updateItemState(path: path, body: body)
let query = Operations.updateItemState.Input.Query(source: buildSource(sourcePrefix: sourcePrefix, deviceId: deviceId))
let response = try await client.updateItemState(path: path, query: query, body: body)
_ = try response.accepted
}

func sendItemCommand(itemname: String, command: String) async throws {
func sendItemCommand(itemname: String, command: String, sourcePrefix: String? = nil, deviceId: String? = nil) async throws {
let path = Operations.sendItemCommand.Input.Path(itemname: itemname)
let body = Operations.sendItemCommand.Input.Body.plainText(.init(command))
let response = try await client.sendItemCommand(path: path, body: body)
let query = Operations.sendItemCommand.Input.Query(source: buildSource(sourcePrefix: sourcePrefix, deviceId: deviceId))
let response = try await client.sendItemCommand(path: path, query: query, body: body)
_ = try response.ok
}
}
Expand Down
46 changes: 44 additions & 2 deletions OpenHABCore/Sources/OpenHABCore/openapi/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2962,6 +2962,14 @@
"summary": "Sends a command to an item.",
"operationId": "sendItemCommand",
"parameters": [
{
"name": "X-OpenHAB-Source",
"in": "header",
"description": "the source of the command; takes priority over the query parameter or JSON body if multiple are set",
"schema": {
"type": "string"
}
},
{
"name": "itemname",
"in": "path",
Expand All @@ -2971,14 +2979,32 @@
"pattern": "[a-zA-Z_0-9]+",
"type": "string"
}
},
{
"name": "source",
"in": "query",
"description": "the source of the command",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "valid item command (e.g. ON, OFF, UP, DOWN, REFRESH)",
"description": "Valid item command (e.g., ON, OFF) either as plain text or JSON",
"content": {
"text/plain": {
"schema": {
"type": "string"
"type": "string",
"example": "ON"
}
},
"application/json": {
"schema": {
"type": "string",
"example": {
"value": "ON",
"source": "org.openhab.ios"
}
Comment thread
timbms marked this conversation as resolved.
}
}
},
Expand Down Expand Up @@ -3209,6 +3235,14 @@
"type": "string"
}
},
{
"name": "X-OpenHAB-Source",
"in": "header",
"description": "the source of the event; takes priority over the query parameter or JSON body if multiple are set",
"schema": {
"type": "string"
}
},
{
"name": "itemname",
"in": "path",
Expand All @@ -3218,6 +3252,14 @@
"pattern": "[a-zA-Z_0-9]+",
"type": "string"
}
},
{
"name": "source",
"in": "query",
"description": "the source of the event",
"schema": {
"type": "string"
}
}
],
"requestBody": {
Expand Down
4 changes: 2 additions & 2 deletions OpenHABCore/Tests/OpenHABCoreTests/NetworkTrackerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ final actor MockOpenAPIService: OpenAPIServiceProtocol {
self.mockServerProperties = mockServerProperties
}

func sendItemCommand(itemname: String, command: String) async throws {
func sendItemCommand(itemname: String, command: String, sourcePrefix: String?, deviceId: String?) async throws {
if shouldFail {
throw networkTrackerError
}
}

func updateItemState(itemname: String, with: String) async throws {
func updateItemState(itemname: String, with: String, sourcePrefix: String?, deviceId: String?) async throws {
if shouldFail {
throw networkTrackerError
}
Expand Down
Loading