Initial commit from private

This commit is contained in:
2019-07-15 20:51:25 -04:00
commit 264f03a22f
55 changed files with 2006 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (remote console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "publish",
"program": "dotnet",
"args": [
"/home/ckaczor/Weather/SerialReader/SerialReader.dll"
],
"cwd": "/home/ckaczor/Weather/SerialReader",
"stopAtEntry": false,
"console": "internalConsole",
"pipeTransport": {
"pipeCwd": "${workspaceFolder}",
"pipeProgram": "C:\\Program Files (x86)\\PuTTY\\PLINK.EXE",
"pipeArgs": [
"root@172.23.10.6"
],
"debuggerPath": "/home/ckaczor/vsdbg/vsdbg"
},
"internalConsoleOptions": "openOnSessionStart"
}
]
}

35
Weather/SerialReader/.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,35 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/SerialReader.csproj"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "publish",
"type": "shell",
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}"
},
"windows": {
"command": "${cwd}\\publish.bat"
},
"problemMatcher": [],
"group": "build"
}
]
}

View File

@@ -0,0 +1,174 @@
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using RabbitMQ.Client;
using System;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using Weather.Models;
namespace Weather.SerialReader
{
internal static class Program
{
private static IConfiguration _configuration;
private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
private static DateTime _lastLogTime = DateTime.MinValue;
private static long _messageCount;
private static bool _boardStarting;
private static void Main()
{
WriteLog("Starting");
Console.CancelKeyPress += OnCancelKeyPress;
_configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, false)
.AddEnvironmentVariables()
.Build();
var baudRate = int.Parse(_configuration["Weather:Port:BaudRate"]);
while (!CancellationTokenSource.Token.IsCancellationRequested)
{
try
{
WriteLog("Starting main loop");
Thread.Sleep(1000);
var port = GetPort();
if (port == null)
continue;
using var serialPort = new SerialPort(port, baudRate) { NewLine = "\r\n" };
WriteLog("Opening serial port");
serialPort.Open();
_boardStarting = false;
var factory = new ConnectionFactory
{
HostName = _configuration["Weather:Queue:Host"],
UserName = _configuration["Weather:Queue:User"],
Password = _configuration["Weather:Queue:Password"]
};
WriteLog("Connecting to queue server");
using var connection = factory.CreateConnection();
using var model = connection.CreateModel();
WriteLog("Declaring queue");
model.QueueDeclare(_configuration["Weather:Queue:Name"], true, false, false, null);
WriteLog("Starting serial read loop");
ReadSerial(serialPort, model);
}
catch (Exception exception)
{
WriteLog($"Exception: {exception}");
}
}
WriteLog("Exiting");
}
private static void ReadSerial(SerialPort serialPort, IModel model)
{
while (!CancellationTokenSource.Token.IsCancellationRequested)
{
try
{
var message = serialPort.ReadLine();
if (!_boardStarting)
{
_boardStarting = message.Contains("Board starting");
if (_boardStarting)
WriteLog("Board starting");
}
if (!_boardStarting)
{
WriteLog($"Message received but board not starting: {message}");
continue;
}
var weatherMessage = WeatherMessage.Parse(message);
var messageString = JsonConvert.SerializeObject(weatherMessage);
var body = Encoding.UTF8.GetBytes(messageString);
var properties = model.CreateBasicProperties();
properties.Persistent = true;
model.BasicPublish(string.Empty, _configuration["Weather:Queue:Name"], properties, body);
_messageCount++;
if ((DateTime.Now - _lastLogTime).TotalMinutes < 1)
continue;
WriteLog($"Number of messages received since {_lastLogTime} = {_messageCount}");
_lastLogTime = DateTime.Now;
_messageCount = 0;
}
catch (TimeoutException)
{
WriteLog("Serial port read timeout");
}
}
}
private static void OnCancelKeyPress(object sender, ConsoleCancelEventArgs args)
{
args.Cancel = true;
CancellationTokenSource.Cancel();
}
private static string GetPort()
{
var portPrefix = _configuration["Weather:Port:Prefix"];
while (!CancellationTokenSource.Token.IsCancellationRequested)
{
WriteLog($"Checking for port starting with: {portPrefix}");
var ports = SerialPort.GetPortNames();
var port = ports.FirstOrDefault(p => p.StartsWith(portPrefix));
if (port != null)
{
WriteLog($"Port found: {port}");
return port;
}
WriteLog("Port not found - waiting");
Thread.Sleep(1000);
}
return null;
}
private static void WriteLog(string message)
{
Console.WriteLine(message);
}
}
}

View File

@@ -0,0 +1,12 @@
{
"profiles": {
"SerialReader": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:62648/"
}
}
}

View File

@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
<AssemblyName>Weather.SerialReader</AssemblyName>
<RootNamespace>Weather.SerialReader</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.0.0-preview6.19304.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0-preview6.19304.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0-preview6.19304.6" />
<PackageReference Include="RabbitMQ.Client" Version="5.1.0" />
<PackageReference Include="System.IO.Ports" Version="4.6.0-preview5.19224.8" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Models\Models.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>IIS Express</ActiveDebugProfile>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Locals/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=EnumMember/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Property/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:Int64 x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/AutoNamingCompletedVersion/@EntryValue">2</s:Int64></wpf:ResourceDictionary>

View File

@@ -0,0 +1,11 @@
{
"Weather": {
"Port": {
"Prefix": "/dev/ttyACM",
"BaudRate": 9600
},
"Queue": {
"Name": "weather"
}
}
}

View File

@@ -0,0 +1,68 @@
---
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: weather-queue
namespace: home-monitor
labels:
app: weather-queue
spec:
replicas: 1
selector:
matchLabels:
app: weather-queue
serviceName: weather-queue
template:
metadata:
labels:
app: weather-queue
spec:
containers:
- name: weather-queue
image: rabbitmq:3.7.16-management-alpine
terminationMessagePath: "/dev/termination-log"
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
env:
- name: RABBITMQ_DEFAULT_USER
valueFrom:
secretKeyRef:
name: weather-queue-credentials
key: username
- name: RABBITMQ_DEFAULT_PASS
valueFrom:
secretKeyRef:
name: weather-queue-credentials
key: password
volumeMounts:
- name: data
mountPath: /var/lib/rabbitmq
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
nodeSelector:
kubernetes.io/hostname: weather
schedulerName: default-scheduler
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: local-path
resources:
requests:
storage: 1Gi
---
kind: Service
apiVersion: v1
metadata:
name: weather-queue
spec:
ports:
- name: client
port: 5672
- name: http
port: 15672
selector:
app: weather-queue
type: ClusterIP

View File

@@ -0,0 +1,45 @@
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: weather-serial-reader
namespace: home-monitor
labels:
app: weather-serial-reader
spec:
replicas: 1
selector:
matchLabels:
app: weather-serial-reader
template:
metadata:
labels:
app: weather-serial-reader
spec:
containers:
- name: weather-serial-reader
image: ckaczor/home-monitor-weather-serialreader:latest
terminationMessagePath: "/dev/termination-log"
terminationMessagePolicy: File
imagePullPolicy: Always
securityContext:
privileged: true
env:
- name: Weather__Queue__Host
value: weather-queue
- name: Weather__Queue__User
valueFrom:
secretKeyRef:
name: weather-queue-credentials
key: username
- name: Weather__Queue__Password
valueFrom:
secretKeyRef:
name: weather-queue-credentials
key: password
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
nodeSelector:
kubernetes.io/hostname: weather
schedulerName: default-scheduler