12 Commits
0.1.0 ... 0.1.3

Author SHA1 Message Date
d45957fbc3 feat: Updates to build arm images in ci
Some checks failed
Create and publish a Docker image / build-and-push-image (push) Failing after 6s
2024-11-05 12:26:43 -05:00
62a0930a2c feat: Updates image tags
Some checks failed
Create and publish a Docker image / build-and-push-image (push) Failing after 7s
2024-11-05 12:16:17 -05:00
fb9b41a8be feat: Using slim image to cut down on size of docker container application 2024-11-05 12:11:31 -05:00
d675ac2e39 fix: Updates tag name when building images 2024-11-05 11:42:26 -05:00
97f0ec38be fix: Updates tag name when building images 2024-11-05 11:39:15 -05:00
ebadb523de fix: Updates tag name when building images 2024-11-05 11:35:34 -05:00
7e214fc9a1 fix: Updates tag name when building images 2024-11-05 11:27:48 -05:00
eb35d0e780 feat: updates for docker image 2024-11-05 11:16:29 -05:00
b9b0fe8b48 feat: working on docker build 2024-11-05 10:11:44 -05:00
d01b515be4 Working on async version. 2022-04-19 16:19:08 -04:00
6b821d47b9 Fixed docker tests 2022-04-17 20:05:36 -04:00
41dab0cd30 Working on docker 2022-04-17 18:58:58 -04:00
21 changed files with 1077 additions and 48 deletions

2
.dockerignore Normal file
View File

@@ -0,0 +1,2 @@
.build/*
mqtt_password.txt

69
.github/workflows/release.yml vendored Normal file
View 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
View File

@@ -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

View 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>

View 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>

View 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>

View 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 = "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>

View 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>

View 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>

View File

@@ -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>

View File

@@ -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
View 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"]

View File

@@ -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

View File

@@ -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"
} }
}, },
{ {

View File

@@ -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")
] ]
), ),

View File

@@ -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()

View File

@@ -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) }
} }

View File

@@ -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)
}
}

View 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()
}
}

View File

@@ -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 {

View File

@@ -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