Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
d45957fbc3
|
|||
|
62a0930a2c
|
|||
|
fb9b41a8be
|
|||
|
d675ac2e39
|
|||
|
97f0ec38be
|
|||
|
ebadb523de
|
|||
|
7e214fc9a1
|
|||
|
eb35d0e780
|
|||
|
b9b0fe8b48
|
|||
| d01b515be4 | |||
| 6b821d47b9 | |||
| 41dab0cd30 |
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.build/*
|
||||||
|
mqtt_password.txt
|
||||||
69
.github/workflows/release.yml
vendored
Normal file
69
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#
|
||||||
|
name: Create and publish a Docker image
|
||||||
|
|
||||||
|
# Configures this workflow to run every time a change is pushed to the branch called `release`.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ['release']
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
|
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
|
||||||
|
jobs:
|
||||||
|
build-and-push-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
#
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
|
||||||
|
- name: Log in to the Container registry
|
||||||
|
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=sha
|
||||||
|
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
|
||||||
|
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
|
||||||
|
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
|
||||||
|
- name: Build and push Docker image
|
||||||
|
id: push
|
||||||
|
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|
||||||
|
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
|
||||||
|
- name: Generate artifact attestation
|
||||||
|
uses: actions/attest-build-provenance@v1
|
||||||
|
with:
|
||||||
|
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||||
|
subject-digest: ${{ steps.push.outputs.digest }}
|
||||||
|
push-to-registry: true
|
||||||
|
|
||||||
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,3 +7,5 @@ DerivedData/
|
|||||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
.dewPoint-env
|
.dewPoint-env
|
||||||
.topics
|
.topics
|
||||||
|
mqtt_password.txt
|
||||||
|
.env
|
||||||
|
|||||||
67
.swiftpm/xcode/xcshareddata/xcschemes/Bootstrap.xcscheme
Normal file
67
.swiftpm/xcode/xcshareddata/xcschemes/Bootstrap.xcscheme
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Bootstrap"
|
||||||
|
BuildableName = "Bootstrap"
|
||||||
|
BlueprintName = "Bootstrap"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Bootstrap"
|
||||||
|
BuildableName = "Bootstrap"
|
||||||
|
BlueprintName = "Bootstrap"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
67
.swiftpm/xcode/xcshareddata/xcschemes/Client.xcscheme
Normal file
67
.swiftpm/xcode/xcshareddata/xcschemes/Client.xcscheme
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Client"
|
||||||
|
BuildableName = "Client"
|
||||||
|
BlueprintName = "Client"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Client"
|
||||||
|
BuildableName = "Client"
|
||||||
|
BlueprintName = "Client"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
67
.swiftpm/xcode/xcshareddata/xcschemes/ClientLive.xcscheme
Normal file
67
.swiftpm/xcode/xcshareddata/xcschemes/ClientLive.xcscheme
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ClientLive"
|
||||||
|
BuildableName = "ClientLive"
|
||||||
|
BlueprintName = "ClientLive"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ClientLive"
|
||||||
|
BuildableName = "ClientLive"
|
||||||
|
BlueprintName = "ClientLive"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "DewPointEnvironment"
|
||||||
|
BuildableName = "DewPointEnvironment"
|
||||||
|
BlueprintName = "DewPointEnvironment"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "DewPointEnvironment"
|
||||||
|
BuildableName = "DewPointEnvironment"
|
||||||
|
BlueprintName = "DewPointEnvironment"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
67
.swiftpm/xcode/xcshareddata/xcschemes/EnvVars.xcscheme
Normal file
67
.swiftpm/xcode/xcshareddata/xcschemes/EnvVars.xcscheme
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EnvVars"
|
||||||
|
BuildableName = "EnvVars"
|
||||||
|
BlueprintName = "EnvVars"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EnvVars"
|
||||||
|
BuildableName = "EnvVars"
|
||||||
|
BlueprintName = "EnvVars"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
67
.swiftpm/xcode/xcshareddata/xcschemes/Models.xcscheme
Normal file
67
.swiftpm/xcode/xcshareddata/xcschemes/Models.xcscheme
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Models"
|
||||||
|
BuildableName = "Models"
|
||||||
|
BlueprintName = "Models"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Models"
|
||||||
|
BuildableName = "Models"
|
||||||
|
BlueprintName = "Models"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Bootstrap"
|
||||||
|
BuildableName = "Bootstrap"
|
||||||
|
BlueprintName = "Bootstrap"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Client"
|
||||||
|
BuildableName = "Client"
|
||||||
|
BlueprintName = "Client"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ClientLive"
|
||||||
|
BuildableName = "ClientLive"
|
||||||
|
BlueprintName = "ClientLive"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "DewPointEnvironment"
|
||||||
|
BuildableName = "DewPointEnvironment"
|
||||||
|
BlueprintName = "DewPointEnvironment"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EnvVars"
|
||||||
|
BuildableName = "EnvVars"
|
||||||
|
BlueprintName = "EnvVars"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "Models"
|
||||||
|
BuildableName = "Models"
|
||||||
|
BlueprintName = "Models"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controller"
|
||||||
|
BuildableName = "dewPoint-controller"
|
||||||
|
BlueprintName = "dewPoint-controller"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ClientTests"
|
||||||
|
BuildableName = "ClientTests"
|
||||||
|
BlueprintName = "ClientTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controllerTests"
|
||||||
|
BuildableName = "dewPoint-controllerTests"
|
||||||
|
BlueprintName = "dewPoint-controllerTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "TopicsLive"
|
||||||
|
BuildableName = "TopicsLive"
|
||||||
|
BlueprintName = "TopicsLive"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ClientTests"
|
||||||
|
BuildableName = "ClientTests"
|
||||||
|
BlueprintName = "ClientTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controllerTests"
|
||||||
|
BuildableName = "dewPoint-controllerTests"
|
||||||
|
BlueprintName = "dewPoint-controllerTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controller"
|
||||||
|
BuildableName = "dewPoint-controller"
|
||||||
|
BlueprintName = "dewPoint-controller"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controller"
|
||||||
|
BuildableName = "dewPoint-controller"
|
||||||
|
BlueprintName = "dewPoint-controller"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controller"
|
||||||
|
BuildableName = "dewPoint-controller"
|
||||||
|
BlueprintName = "dewPoint-controller"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ClientTests"
|
||||||
|
BuildableName = "ClientTests"
|
||||||
|
BlueprintName = "ClientTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controllerTests"
|
||||||
|
BuildableName = "dewPoint-controllerTests"
|
||||||
|
BlueprintName = "dewPoint-controllerTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "ClientTests"
|
||||||
|
BuildableName = "ClientTests"
|
||||||
|
BlueprintName = "ClientTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controllerTests"
|
||||||
|
BuildableName = "dewPoint-controllerTests"
|
||||||
|
BlueprintName = "dewPoint-controllerTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controller"
|
||||||
|
BuildableName = "dewPoint-controller"
|
||||||
|
BlueprintName = "dewPoint-controller"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "dewPoint-controller"
|
||||||
|
BuildableName = "dewPoint-controller"
|
||||||
|
BlueprintName = "dewPoint-controller"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
# Build the executable
|
||||||
|
FROM swift:5.10 AS build
|
||||||
|
WORKDIR /build
|
||||||
|
COPY ./Package.* ./
|
||||||
|
RUN swift package resolve
|
||||||
|
COPY . .
|
||||||
|
RUN swift build --enable-test-discovery -c release -Xswiftc -g
|
||||||
|
|
||||||
|
# Run image
|
||||||
|
FROM swift:5.10-slim
|
||||||
|
WORKDIR /run
|
||||||
|
COPY --from=build /build/.build/release/dewPoint-controller /run
|
||||||
|
CMD ["/bin/bash", "-xc", "./dewPoint-controller"]
|
||||||
24
Makefile
24
Makefile
@@ -1,28 +1,24 @@
|
|||||||
|
|
||||||
bootstrap-env:
|
bootstrap-env:
|
||||||
@cp Bootstrap/dewPoint-env-example .dewPoint-env
|
@cp Bootstrap/dewPoint-env-example .dewPoint-env
|
||||||
|
|
||||||
bootstrap-topics:
|
bootstrap-topics:
|
||||||
@cp Bootstrap/topics-example .topics
|
@cp Bootstrap/topics-example .topics
|
||||||
|
|
||||||
bootstrap: bootstrap-env bootstrap-topics
|
bootstrap: bootstrap-env bootstrap-topics
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@swift build
|
@swift build
|
||||||
|
|
||||||
run:
|
run:
|
||||||
@swift run dewPoint-controller
|
@swift run dewPoint-controller
|
||||||
|
|
||||||
start-mosquitto:
|
start-mosquitto:
|
||||||
@docker run \
|
@docker-compose start mosquitto
|
||||||
--name mosquitto \
|
|
||||||
-d \
|
|
||||||
-p 1883:1883 \
|
|
||||||
-p 8883:8883 \
|
|
||||||
-p 8080:8080 \
|
|
||||||
-p 8081:8081 \
|
|
||||||
-v "$(PWD)/mosquitto/config:/mosquitto/config" \
|
|
||||||
eclipse-mosquitto
|
|
||||||
|
|
||||||
stop-mosquitto:
|
stop-mosquitto:
|
||||||
@docker rm -f mosquitto || true
|
@docker-compose rm -f mosquitto || true
|
||||||
|
|
||||||
|
test-docker:
|
||||||
|
@docker-compose run -i test
|
||||||
|
@docker-compose kill mosquitto-test
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
"pins": [
|
"pins": [
|
||||||
{
|
{
|
||||||
"package": "mqtt-nio",
|
"package": "mqtt-nio",
|
||||||
"repositoryURL": "https://github.com/adam-fowler/mqtt-nio.git",
|
"repositoryURL": "https://github.com/swift-server-community/mqtt-nio.git",
|
||||||
"state": {
|
"state": {
|
||||||
"branch": null,
|
"branch": null,
|
||||||
"revision": "976a4b6019e1dd365a0da793babadd5cc958ce2b",
|
"revision": "ca8af7a30c4690456ce7de276cd0f037489ba707",
|
||||||
"version": "2.1.1"
|
"version": "2.5.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
"repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
|
"repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
|
||||||
"state": {
|
"state": {
|
||||||
"branch": null,
|
"branch": null,
|
||||||
"revision": "5e68c1ded15619bb281b273fa8c2d8fd7f7b2b7d",
|
"revision": "b5260a31c2a72a89fa684f5efb3054d8725a2316",
|
||||||
"version": "2.16.1"
|
"version": "2.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -42,8 +42,8 @@
|
|||||||
"repositoryURL": "https://github.com/apple/swift-nio-transport-services.git",
|
"repositoryURL": "https://github.com/apple/swift-nio-transport-services.git",
|
||||||
"state": {
|
"state": {
|
||||||
"branch": null,
|
"branch": null,
|
||||||
"revision": "e7f5278a26442dc46783ba7e063643d524e414a0",
|
"revision": "8ab824b140d0ebcd87e9149266ddc353e3705a3e",
|
||||||
"version": "1.11.3"
|
"version": "1.11.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// swift-tools-version:5.5
|
// swift-tools-version:5.10
|
||||||
|
|
||||||
import PackageDescription
|
import PackageDescription
|
||||||
|
|
||||||
let package = Package(
|
let package = Package(
|
||||||
name: "dewPoint-controller",
|
name: "dewPoint-controller",
|
||||||
platforms: [
|
platforms: [
|
||||||
.macOS(.v10_14)
|
.macOS(.v12)
|
||||||
],
|
],
|
||||||
products: [
|
products: [
|
||||||
.executable(name: "dewPoint-controller", targets: ["dewPoint-controller"]),
|
.executable(name: "dewPoint-controller", targets: ["dewPoint-controller"]),
|
||||||
@@ -17,7 +17,7 @@ let package = Package(
|
|||||||
.library(name: "ClientLive", targets: ["ClientLive"]),
|
.library(name: "ClientLive", targets: ["ClientLive"]),
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/adam-fowler/mqtt-nio.git", from: "2.0.0"),
|
.package(url: "https://github.com/swift-server-community/mqtt-nio.git", from: "2.0.0"),
|
||||||
.package(url: "https://github.com/apple/swift-nio", from: "2.0.0"),
|
.package(url: "https://github.com/apple/swift-nio", from: "2.0.0"),
|
||||||
.package(url: "https://github.com/swift-psychrometrics/swift-psychrometrics", from: "0.1.0")
|
.package(url: "https://github.com/swift-psychrometrics/swift-psychrometrics", from: "0.1.0")
|
||||||
],
|
],
|
||||||
@@ -79,6 +79,7 @@ let package = Package(
|
|||||||
name: "ClientLive",
|
name: "ClientLive",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"Client",
|
"Client",
|
||||||
|
"EnvVars",
|
||||||
.product(name: "MQTTNIO", package: "mqtt-nio")
|
.product(name: "MQTTNIO", package: "mqtt-nio")
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ private func loadEnvVars(
|
|||||||
|
|
||||||
logger?.debug("Loading env vars...")
|
logger?.debug("Loading env vars...")
|
||||||
|
|
||||||
|
// TODO: Need to have the env file path passed in / dynamic.
|
||||||
let envFilePath = URL(fileURLWithPath: #file)
|
let envFilePath = URL(fileURLWithPath: #file)
|
||||||
.deletingLastPathComponent()
|
.deletingLastPathComponent()
|
||||||
.deletingLastPathComponent()
|
.deletingLastPathComponent()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Logging
|
|||||||
import Models
|
import Models
|
||||||
import MQTTNIO
|
import MQTTNIO
|
||||||
import NIO
|
import NIO
|
||||||
|
import NIOFoundationCompat
|
||||||
import Psychrometrics
|
import Psychrometrics
|
||||||
|
|
||||||
/// Represents a type that can be initialized by a ``ByteBuffer``.
|
/// Represents a type that can be initialized by a ``ByteBuffer``.
|
||||||
@@ -11,10 +12,13 @@ protocol BufferInitalizable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension Double: BufferInitalizable {
|
extension Double: BufferInitalizable {
|
||||||
|
|
||||||
/// Attempt to create / parse a double from a byte buffer.
|
/// Attempt to create / parse a double from a byte buffer.
|
||||||
init?(buffer: inout ByteBuffer) {
|
init?(buffer: inout ByteBuffer) {
|
||||||
guard let string = buffer.readString(length: buffer.readableBytes, encoding: .utf8)
|
guard let string = buffer.readString(
|
||||||
|
length: buffer.readableBytes,
|
||||||
|
encoding: String.Encoding.utf8
|
||||||
|
)
|
||||||
else { return nil }
|
else { return nil }
|
||||||
self.init(string)
|
self.init(string)
|
||||||
}
|
}
|
||||||
@@ -57,7 +61,7 @@ extension Result where Success == MQTTPublishInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension Optional where Wrapped == ByteBuffer {
|
extension Optional where Wrapped == ByteBuffer {
|
||||||
|
|
||||||
func parse<T>(as type: T.Type) -> T? where T: BufferInitalizable {
|
func parse<T>(as type: T.Type) -> T? where T: BufferInitalizable {
|
||||||
switch self {
|
switch self {
|
||||||
case var .some(buffer):
|
case var .some(buffer):
|
||||||
@@ -69,14 +73,14 @@ extension Optional where Wrapped == ByteBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileprivate struct TemperatureAndHumiditySensorKeyPathEnvelope {
|
fileprivate struct TemperatureAndHumiditySensorKeyPathEnvelope {
|
||||||
|
|
||||||
let humidityTopic: KeyPath<Topics.Sensors, String>
|
let humidityTopic: KeyPath<Topics.Sensors, String>
|
||||||
let temperatureTopic: KeyPath<Topics.Sensors, String>
|
let temperatureTopic: KeyPath<Topics.Sensors, String>
|
||||||
let temperatureState: WritableKeyPath<State.Sensors, Temperature?>
|
let temperatureState: WritableKeyPath<State.Sensors, Temperature?>
|
||||||
let humidityState: WritableKeyPath<State.Sensors, RelativeHumidity?>
|
let humidityState: WritableKeyPath<State.Sensors, RelativeHumidity?>
|
||||||
|
|
||||||
func addListener(to client: MQTTNIO.MQTTClient, topics: Topics, state: State) {
|
func addListener(to client: MQTTNIO.MQTTClient, topics: Topics, state: State) {
|
||||||
|
|
||||||
let temperatureTopic = topics.sensors[keyPath: temperatureTopic]
|
let temperatureTopic = topics.sensors[keyPath: temperatureTopic]
|
||||||
client.logger.trace("Adding listener for topic: \(temperatureTopic)")
|
client.logger.trace("Adding listener for topic: \(temperatureTopic)")
|
||||||
client.addPublishListener(named: temperatureTopic) { result in
|
client.addPublishListener(named: temperatureTopic) { result in
|
||||||
@@ -86,7 +90,7 @@ fileprivate struct TemperatureAndHumiditySensorKeyPathEnvelope {
|
|||||||
state.sensors[keyPath: temperatureState] = temperature
|
state.sensors[keyPath: temperatureState] = temperature
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let humidityTopic = topics.sensors[keyPath: humidityTopic]
|
let humidityTopic = topics.sensors[keyPath: humidityTopic]
|
||||||
client.logger.trace("Adding listener for topic: \(humidityTopic)")
|
client.logger.trace("Adding listener for topic: \(humidityTopic)")
|
||||||
client.addPublishListener(named: humidityTopic) { result in
|
client.addPublishListener(named: humidityTopic) { result in
|
||||||
@@ -155,7 +159,7 @@ extension State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension Client.SensorPublishRequest {
|
extension Client.SensorPublishRequest {
|
||||||
|
|
||||||
func dewPointData(topics: Topics, units: PsychrometricEnvironment.Units?) -> (DewPoint, String)? {
|
func dewPointData(topics: Topics, units: PsychrometricEnvironment.Units?) -> (DewPoint, String)? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .mixed(sensor):
|
case let .mixed(sensor):
|
||||||
@@ -172,7 +176,7 @@ extension Client.SensorPublishRequest {
|
|||||||
return (dp, topics.sensors.supplyAirSensor.dewPoint)
|
return (dp, topics.sensors.supplyAirSensor.dewPoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func enthalpyData(altitude: Length, topics: Topics, units: PsychrometricEnvironment.Units?) -> (EnthalpyOf<MoistAir>, String)? {
|
func enthalpyData(altitude: Length, topics: Topics, units: PsychrometricEnvironment.Units?) -> (EnthalpyOf<MoistAir>, String)? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .mixed(sensor):
|
case let .mixed(sensor):
|
||||||
@@ -189,7 +193,7 @@ extension Client.SensorPublishRequest {
|
|||||||
return (enthalpy, topics.sensors.supplyAirSensor.enthalpy)
|
return (enthalpy, topics.sensors.supplyAirSensor.enthalpy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setHasProcessed(state: State) {
|
func setHasProcessed(state: State) {
|
||||||
switch self {
|
switch self {
|
||||||
case .mixed:
|
case .mixed:
|
||||||
@@ -205,7 +209,7 @@ extension Client.SensorPublishRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension MQTTNIO.MQTTClient {
|
extension MQTTNIO.MQTTClient {
|
||||||
|
|
||||||
func publishDewPoint(
|
func publishDewPoint(
|
||||||
request: Client.SensorPublishRequest,
|
request: Client.SensorPublishRequest,
|
||||||
state: State,
|
state: State,
|
||||||
@@ -221,7 +225,8 @@ extension MQTTNIO.MQTTClient {
|
|||||||
return publish(
|
return publish(
|
||||||
to: topic,
|
to: topic,
|
||||||
payload: ByteBufferAllocator().buffer(string: "\(roundedDewPoint)"),
|
payload: ByteBufferAllocator().buffer(string: "\(roundedDewPoint)"),
|
||||||
qos: .atLeastOnce
|
qos: .atLeastOnce,
|
||||||
|
retain: true
|
||||||
)
|
)
|
||||||
.map { (self, request, state, topics) }
|
.map { (self, request, state, topics) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import NIO
|
|||||||
import Psychrometrics
|
import Psychrometrics
|
||||||
|
|
||||||
extension Client {
|
extension Client {
|
||||||
|
|
||||||
// The state passed in here needs to be a class or we get escaping errors in the `addListeners` method.
|
// The state passed in here needs to be a class or we get escaping errors in the `addListeners` method.
|
||||||
public static func live(
|
public static func live(
|
||||||
client: MQTTNIO.MQTTClient,
|
client: MQTTNIO.MQTTClient,
|
||||||
@@ -39,3 +39,120 @@ extension Client {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import Logging
|
||||||
|
import NIOTransportServices
|
||||||
|
import EnvVars
|
||||||
|
|
||||||
|
public class AsyncClient {
|
||||||
|
//public static let eventLoopGroup = NIOTSEventLoopGroup()
|
||||||
|
public static let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
||||||
|
public let client: MQTTClient
|
||||||
|
public private(set) var shuttingDown: Bool
|
||||||
|
|
||||||
|
var logger: Logger { client.logger }
|
||||||
|
|
||||||
|
public init(envVars: EnvVars, logger: Logger) {
|
||||||
|
let config = MQTTClient.Configuration.init(
|
||||||
|
version: .v3_1_1,
|
||||||
|
userName: envVars.userName,
|
||||||
|
password: envVars.password,
|
||||||
|
useSSL: false,
|
||||||
|
useWebSockets: false,
|
||||||
|
tlsConfiguration: nil,
|
||||||
|
webSocketURLPath: nil
|
||||||
|
)
|
||||||
|
self.client = .init(
|
||||||
|
host: envVars.host,
|
||||||
|
identifier: envVars.identifier,
|
||||||
|
eventLoopGroupProvider: .shared(Self.eventLoopGroup),
|
||||||
|
logger: logger,
|
||||||
|
configuration: config
|
||||||
|
)
|
||||||
|
self.shuttingDown = false
|
||||||
|
}
|
||||||
|
|
||||||
|
public func connect() async {
|
||||||
|
do {
|
||||||
|
try await self.client.connect()
|
||||||
|
self.client.addCloseListener(named: "AsyncClient") { [self] result in
|
||||||
|
guard !self.shuttingDown else { return }
|
||||||
|
Task {
|
||||||
|
self.logger.debug("Connection closed.")
|
||||||
|
self.logger.debug("Reconnecting...")
|
||||||
|
await self.connect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("Connection successful.")
|
||||||
|
} catch {
|
||||||
|
logger.trace("Connection Failed.\n\(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func shutdown() async {
|
||||||
|
self.shuttingDown = true
|
||||||
|
try? await self.client.disconnect()
|
||||||
|
try? await self.client.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func addSensorListeners() async {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to save the recieved values somewhere.
|
||||||
|
func addPublishListener<T>(
|
||||||
|
topic: String,
|
||||||
|
decoding: T.Type
|
||||||
|
) async throws where T: BufferInitalizable {
|
||||||
|
_ = try await self.client.subscribe(to: [.init(topicFilter: topic, qos: .atLeastOnce)])
|
||||||
|
Task {
|
||||||
|
let listener = self.client.createPublishListener()
|
||||||
|
for await result in listener {
|
||||||
|
switch result {
|
||||||
|
case let .success(packet):
|
||||||
|
var buffer = packet.payload
|
||||||
|
guard let value = T.init(buffer: &buffer) else {
|
||||||
|
logger.debug("Could not decode buffer: \(buffer)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.debug("Recieved value: \(value)")
|
||||||
|
case let .failure(error):
|
||||||
|
logger.trace("Error:\n\(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func publish(string: String, to topic: String) async throws {
|
||||||
|
try await self.client.publish(
|
||||||
|
to: topic,
|
||||||
|
payload: ByteBufferAllocator().buffer(string: string),
|
||||||
|
qos: .atLeastOnce
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func publish(double: Double, to topic: String) async throws {
|
||||||
|
let rounded = round(double * 100) / 100
|
||||||
|
try await publish(string: "\(rounded)", to: topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishDewPoint(_ request: Client.SensorPublishRequest) async throws {
|
||||||
|
// fix
|
||||||
|
guard let (dewPoint, topic) = request.dewPointData(topics: .init(), units: nil) else { return }
|
||||||
|
try await self.publish(double: dewPoint.rawValue, to: topic)
|
||||||
|
logger.debug("Published dewpoint: \(dewPoint.rawValue), to: \(topic)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishEnthalpy(_ request: Client.SensorPublishRequest) async throws {
|
||||||
|
// fix
|
||||||
|
guard let (enthalpy, topic) = request.enthalpyData(altitude: .seaLevel, topics: .init(), units: nil) else { return }
|
||||||
|
try await self.publish(double: enthalpy.rawValue, to: topic)
|
||||||
|
logger.debug("Publihsed enthalpy: \(enthalpy.rawValue), to: \(topic)")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func publishSensor(_ request: Client.SensorPublishRequest) async throws {
|
||||||
|
try await publishDewPoint(request)
|
||||||
|
try await publishEnthalpy(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
45
Tests/ClientTests/AsyncClientTests.swift
Normal file
45
Tests/ClientTests/AsyncClientTests.swift
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import XCTest
|
||||||
|
import EnvVars
|
||||||
|
import Logging
|
||||||
|
import Models
|
||||||
|
@testable import ClientLive
|
||||||
|
import Psychrometrics
|
||||||
|
|
||||||
|
final class AsyncClientTests: XCTestCase {
|
||||||
|
|
||||||
|
static let hostname = ProcessInfo.processInfo.environment["MOSQUITTO_SERVER"] ?? "localhost"
|
||||||
|
|
||||||
|
static let logger: Logger = {
|
||||||
|
var logger = Logger(label: "AsyncClientTests")
|
||||||
|
logger.logLevel = .trace
|
||||||
|
return logger
|
||||||
|
}()
|
||||||
|
|
||||||
|
func createClient(identifier: String) -> AsyncClient {
|
||||||
|
let envVars = EnvVars.init(
|
||||||
|
appEnv: .testing,
|
||||||
|
host: Self.hostname,
|
||||||
|
port: "1883",
|
||||||
|
identifier: identifier,
|
||||||
|
userName: nil,
|
||||||
|
password: nil
|
||||||
|
)
|
||||||
|
return .init(envVars: envVars, logger: Self.logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testConnectAndShutdown() async throws {
|
||||||
|
let client = createClient(identifier: "testConnectAndShutdown")
|
||||||
|
await client.connect()
|
||||||
|
await client.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPublishingSensor() async throws {
|
||||||
|
let client = createClient(identifier: "testPublishingSensor")
|
||||||
|
await client.connect()
|
||||||
|
let topic = Topics().sensors.mixedAirSensor.dewPoint
|
||||||
|
try await client.addPublishListener(topic: topic, decoding: Temperature.self)
|
||||||
|
try await client.publishSensor(.mixed(.init(temperature: 71.123, humidity: 50.5, needsProcessed: true)))
|
||||||
|
try await client.publishSensor(.mixed(.init(temperature: 72.123, humidity: 50.5, needsProcessed: true)))
|
||||||
|
await client.shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -79,8 +79,10 @@ final class ClientLiveTests: XCTestCase {
|
|||||||
Thread.sleep(forTimeInterval: 2)
|
Thread.sleep(forTimeInterval: 2)
|
||||||
|
|
||||||
XCTAssertEqual(state.sensors.returnAirSensor.temperature, .celsius(75.1234))
|
XCTAssertEqual(state.sensors.returnAirSensor.temperature, .celsius(75.1234))
|
||||||
|
try mqttClient.disconnect().wait()
|
||||||
try client.shutdown().wait()
|
try mqttClient.syncShutdownGracefully()
|
||||||
|
|
||||||
|
// try client.shutdown().wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_client2_returnSensor_publish() throws {
|
func test_client2_returnSensor_publish() throws {
|
||||||
@@ -111,7 +113,10 @@ final class ClientLiveTests: XCTestCase {
|
|||||||
try client.publishSensor(.return(state.sensors.returnAirSensor)).wait()
|
try client.publishSensor(.return(state.sensors.returnAirSensor)).wait()
|
||||||
XCTAssertFalse(state.sensors.returnAirSensor.needsProcessed)
|
XCTAssertFalse(state.sensors.returnAirSensor.needsProcessed)
|
||||||
|
|
||||||
try client.shutdown().wait()
|
try mqttClient.disconnect().wait()
|
||||||
|
try mqttClient.syncShutdownGracefully()
|
||||||
|
|
||||||
|
// try client.shutdown().wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// func test_fetch_humidity() throws {
|
// func test_fetch_humidity() throws {
|
||||||
|
|||||||
@@ -1,17 +1,33 @@
|
|||||||
# run this with docker-compose -f docker/docker-compose.yml run test
|
# run this with docker-compose -f docker/docker-compose.yml run test
|
||||||
version: "3.3"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
server:
|
||||||
|
image: swift-mqtt-dewpoint:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .env
|
||||||
|
|
||||||
test:
|
test:
|
||||||
image: swift:5.3
|
image: swift:latest
|
||||||
working_dir: /dewPoint-controller
|
#build:
|
||||||
|
#context: ./
|
||||||
|
platform: linux/amd64
|
||||||
|
working_dir: /app
|
||||||
|
networks:
|
||||||
|
- test
|
||||||
volumes:
|
volumes:
|
||||||
- .:/dewPoint-controller
|
- .:/app
|
||||||
depends_on:
|
depends_on:
|
||||||
- mosquitto
|
- mosquitto-test
|
||||||
environment:
|
environment:
|
||||||
- MOSQUITTO_SERVER=mosquitto
|
- MOSQUITTO_SERVER=mosquitto-test
|
||||||
command: /bin/bash -xcl "swift test --enable-test-discovery --sanitize=thread"
|
command: /bin/bash -xc "swift package clean && swift test"
|
||||||
|
|
||||||
|
mosquitto-test:
|
||||||
|
image: eclipse-mosquitto
|
||||||
|
networks:
|
||||||
|
- test
|
||||||
|
volumes:
|
||||||
|
- ./mosquitto/config:/mosquitto/config
|
||||||
|
- ./mosquitto/certs:/mosquitto/certs
|
||||||
|
|
||||||
mosquitto:
|
mosquitto:
|
||||||
image: eclipse-mosquitto
|
image: eclipse-mosquitto
|
||||||
@@ -23,3 +39,9 @@ services:
|
|||||||
- "8883:8883"
|
- "8883:8883"
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
- "8081:8081"
|
- "8081:8081"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
test:
|
||||||
|
driver: bridge
|
||||||
|
external: false
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user