From 777a8846e21020bd9a504a750b21a7ae4ee07f11 Mon Sep 17 00:00:00 2001 From: David K Date: Tue, 21 Nov 2023 18:11:02 +0000 Subject: [PATCH] #17 Services & Modules Hardware Services implemented, modules laid out, camera implemented but not tested Still need to work out what I'm doing about the api --- ServoSkull.sln | 18 ++++- skullOS.API/Program.cs | 1 + skullOS.HardwareServices/BuzzerService.cs | 14 ++++ skullOS.HardwareServices/CameraService.cs | 80 +++++++++++++++++++ .../Interfaces/IBuzzerService.cs | 6 ++ .../Interfaces/ICameraService.cs | 6 ++ .../Interfaces/ILedService.cs | 6 ++ .../Interfaces/IMicrophoneService.cs | 6 ++ .../Interfaces/IProgrammableLedService.cs | 6 ++ .../Interfaces/ISpeakerService.cs | 6 ++ skullOS.HardwareServices/LedService.cs | 14 ++++ skullOS.HardwareServices/MicrophoneService.cs | 16 ++++ .../ProgrammableLedService.cs | 16 ++++ skullOS.HardwareServices/SpeakerService.cs | 16 ++++ .../skullOS.HardwareServices.csproj | 14 ++++ skullOS.Modules/Camera.cs | 41 ++++++++++ skullOS.Modules/Downlink.cs | 12 +++ skullOS.Modules/Interfaces/ICameraModule.cs | 6 ++ skullOS.Modules/Module.cs | 7 ++ skullOS.Modules/Prop.cs | 12 +++ skullOS.Modules/QrCodeReader.cs | 12 +++ skullOS.Modules/Uplink.cs | 12 +++ skullOS.Modules/skullOS.Modules.csproj | 14 ++++ 23 files changed, 340 insertions(+), 1 deletion(-) create mode 100644 skullOS.HardwareServices/BuzzerService.cs create mode 100644 skullOS.HardwareServices/CameraService.cs create mode 100644 skullOS.HardwareServices/Interfaces/IBuzzerService.cs create mode 100644 skullOS.HardwareServices/Interfaces/ICameraService.cs create mode 100644 skullOS.HardwareServices/Interfaces/ILedService.cs create mode 100644 skullOS.HardwareServices/Interfaces/IMicrophoneService.cs create mode 100644 skullOS.HardwareServices/Interfaces/IProgrammableLedService.cs create mode 100644 skullOS.HardwareServices/Interfaces/ISpeakerService.cs create mode 100644 skullOS.HardwareServices/LedService.cs create mode 100644 skullOS.HardwareServices/MicrophoneService.cs create mode 100644 skullOS.HardwareServices/ProgrammableLedService.cs create mode 100644 skullOS.HardwareServices/SpeakerService.cs create mode 100644 skullOS.HardwareServices/skullOS.HardwareServices.csproj create mode 100644 skullOS.Modules/Camera.cs create mode 100644 skullOS.Modules/Downlink.cs create mode 100644 skullOS.Modules/Interfaces/ICameraModule.cs create mode 100644 skullOS.Modules/Module.cs create mode 100644 skullOS.Modules/Prop.cs create mode 100644 skullOS.Modules/QrCodeReader.cs create mode 100644 skullOS.Modules/Uplink.cs create mode 100644 skullOS.Modules/skullOS.Modules.csproj diff --git a/ServoSkull.sln b/ServoSkull.sln index 581a923..17c152f 100644 --- a/ServoSkull.sln +++ b/ServoSkull.sln @@ -50,11 +50,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Pinout.md = Pinout.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "skullOS.API", "skullOS.API\skullOS.API.csproj", "{5E1EC385-4B61-4E8C-82C7-46695A33AC72}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "skullOS.API", "skullOS.API\skullOS.API.csproj", "{5E1EC385-4B61-4E8C-82C7-46695A33AC72}" ProjectSection(ProjectDependencies) = postProject {464B162B-62FC-49CC-A6AB-72DBE959DD8C} = {464B162B-62FC-49CC-A6AB-72DBE959DD8C} EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "skullOS.Modules", "skullOS.Modules\skullOS.Modules.csproj", "{DE800E5A-E68B-4BCA-AC99-4BC9DB44FD56}" + ProjectSection(ProjectDependencies) = postProject + {3CBE1B63-957B-43B6-939D-070EAC517C7C} = {3CBE1B63-957B-43B6-939D-070EAC517C7C} + {464B162B-62FC-49CC-A6AB-72DBE959DD8C} = {464B162B-62FC-49CC-A6AB-72DBE959DD8C} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "skullOS.HardwareServices", "skullOS.HardwareServices\skullOS.HardwareServices.csproj", "{3CBE1B63-957B-43B6-939D-070EAC517C7C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -109,6 +117,14 @@ Global {5E1EC385-4B61-4E8C-82C7-46695A33AC72}.Debug|Any CPU.Build.0 = Debug|Any CPU {5E1EC385-4B61-4E8C-82C7-46695A33AC72}.Release|Any CPU.ActiveCfg = Release|Any CPU {5E1EC385-4B61-4E8C-82C7-46695A33AC72}.Release|Any CPU.Build.0 = Release|Any CPU + {DE800E5A-E68B-4BCA-AC99-4BC9DB44FD56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE800E5A-E68B-4BCA-AC99-4BC9DB44FD56}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE800E5A-E68B-4BCA-AC99-4BC9DB44FD56}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE800E5A-E68B-4BCA-AC99-4BC9DB44FD56}.Release|Any CPU.Build.0 = Release|Any CPU + {3CBE1B63-957B-43B6-939D-070EAC517C7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CBE1B63-957B-43B6-939D-070EAC517C7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CBE1B63-957B-43B6-939D-070EAC517C7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CBE1B63-957B-43B6-939D-070EAC517C7C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/skullOS.API/Program.cs b/skullOS.API/Program.cs index 77be0d3..79eb2a0 100644 --- a/skullOS.API/Program.cs +++ b/skullOS.API/Program.cs @@ -15,6 +15,7 @@ public static void Main(string[] args) builder.Services.AddSwaggerGen(); builder.WebHost.UseUrls("http://*:5000;https://*:5001"); + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/skullOS.HardwareServices/BuzzerService.cs b/skullOS.HardwareServices/BuzzerService.cs new file mode 100644 index 0000000..b76ae94 --- /dev/null +++ b/skullOS.HardwareServices/BuzzerService.cs @@ -0,0 +1,14 @@ +using Iot.Device.Buzzer; +using skullOS.HardwareServices.Interfaces; + +namespace skullOS.HardwareServices +{ + public class BuzzerService : IBuzzerService + { + public Buzzer Buzzer { get; private set; } + public BuzzerService(int pinNumber) + { + Buzzer = new Buzzer(pinNumber); + } + } +} diff --git a/skullOS.HardwareServices/CameraService.cs b/skullOS.HardwareServices/CameraService.cs new file mode 100644 index 0000000..a4eed87 --- /dev/null +++ b/skullOS.HardwareServices/CameraService.cs @@ -0,0 +1,80 @@ +using Iot.Device.Media; +using skullOS.HardwareServices.Interfaces; +using System.Diagnostics; + +namespace skullOS.HardwareServices +{ + public class CameraService : ICameraService + { + public VideoDevice Camera { get; private set; } + private Process? cameraCommand; + private TaskCompletionSource eventHandled; + + public CameraService(VideoConnectionSettings cameraSettings = null) + { + cameraSettings ??= new(busId: 0, captureSize: (2592, 1944), pixelFormat: VideoPixelFormat.JPEG); + Camera = VideoDevice.Create(cameraSettings); + Camera.Settings.HorizontalFlip = true; + Camera.Settings.VerticalFlip = true; + } + + #region SharpCamera code(https://github.com/David032/sharpCamera) for recording video + public void RecordVideo(string outputDirectory, int duration) + { + try + { + using (cameraCommand = new Process()) + { + string args = "-o " + outputDirectory + "/" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".h264 -t " + (duration * 1000); + cameraCommand.StartInfo.UseShellExecute = false; + cameraCommand.StartInfo.FileName = "raspivid"; + cameraCommand.StartInfo.Arguments = args; + +#if DEBUG + Console.Out.WriteLine(cameraCommand.StartInfo.Arguments); +#endif + + cameraCommand.Start(); + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + public async Task RecordVideoAsync(string outputDirectory, int duration) + { + eventHandled = new TaskCompletionSource(); + using (cameraCommand = new Process()) + { + try + { + string args = "-o " + outputDirectory + "/" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".h264 -t " + (duration * 1000); + cameraCommand.StartInfo.UseShellExecute = false; + cameraCommand.StartInfo.FileName = "raspivid"; + cameraCommand.StartInfo.Arguments = args; + cameraCommand.EnableRaisingEvents = true; + cameraCommand.Exited += new EventHandler(VideoRecorded); +#if DEBUG + Console.Out.WriteLine(cameraCommand.StartInfo.Arguments); +#endif + cameraCommand.Start(); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + return; + } + + await Task.WhenAny(eventHandled.Task, Task.Delay(duration * 1000)); + } + } + + private void VideoRecorded(object sender, EventArgs e) + { + eventHandled.TrySetResult(true); + } + #endregion + } +} diff --git a/skullOS.HardwareServices/Interfaces/IBuzzerService.cs b/skullOS.HardwareServices/Interfaces/IBuzzerService.cs new file mode 100644 index 0000000..eefdaf4 --- /dev/null +++ b/skullOS.HardwareServices/Interfaces/IBuzzerService.cs @@ -0,0 +1,6 @@ +namespace skullOS.HardwareServices.Interfaces +{ + public interface IBuzzerService + { + } +} \ No newline at end of file diff --git a/skullOS.HardwareServices/Interfaces/ICameraService.cs b/skullOS.HardwareServices/Interfaces/ICameraService.cs new file mode 100644 index 0000000..0a0c4e9 --- /dev/null +++ b/skullOS.HardwareServices/Interfaces/ICameraService.cs @@ -0,0 +1,6 @@ +namespace skullOS.HardwareServices.Interfaces +{ + public interface ICameraService + { + } +} \ No newline at end of file diff --git a/skullOS.HardwareServices/Interfaces/ILedService.cs b/skullOS.HardwareServices/Interfaces/ILedService.cs new file mode 100644 index 0000000..e303888 --- /dev/null +++ b/skullOS.HardwareServices/Interfaces/ILedService.cs @@ -0,0 +1,6 @@ +namespace skullOS.HardwareServices.Interfaces +{ + public interface ILedService + { + } +} \ No newline at end of file diff --git a/skullOS.HardwareServices/Interfaces/IMicrophoneService.cs b/skullOS.HardwareServices/Interfaces/IMicrophoneService.cs new file mode 100644 index 0000000..f67d02e --- /dev/null +++ b/skullOS.HardwareServices/Interfaces/IMicrophoneService.cs @@ -0,0 +1,6 @@ +namespace skullOS.HardwareServices.Interfaces +{ + public interface IMicrophoneService + { + } +} \ No newline at end of file diff --git a/skullOS.HardwareServices/Interfaces/IProgrammableLedService.cs b/skullOS.HardwareServices/Interfaces/IProgrammableLedService.cs new file mode 100644 index 0000000..9458832 --- /dev/null +++ b/skullOS.HardwareServices/Interfaces/IProgrammableLedService.cs @@ -0,0 +1,6 @@ +namespace skullOS.HardwareServices.Interfaces +{ + public interface IProgrammableLedService + { + } +} \ No newline at end of file diff --git a/skullOS.HardwareServices/Interfaces/ISpeakerService.cs b/skullOS.HardwareServices/Interfaces/ISpeakerService.cs new file mode 100644 index 0000000..6a26b68 --- /dev/null +++ b/skullOS.HardwareServices/Interfaces/ISpeakerService.cs @@ -0,0 +1,6 @@ +namespace skullOS.HardwareServices.Interfaces +{ + public interface ISpeakerService + { + } +} \ No newline at end of file diff --git a/skullOS.HardwareServices/LedService.cs b/skullOS.HardwareServices/LedService.cs new file mode 100644 index 0000000..f5aa191 --- /dev/null +++ b/skullOS.HardwareServices/LedService.cs @@ -0,0 +1,14 @@ +using skullOS.HardwareServices.Interfaces; + +namespace skullOS.HardwareServices +{ + public class LedService : ILedService + { + public Dictionary LEDs { get; private set; } + + public LedService(Dictionary leds) + { + LEDs = leds; + } + } +} diff --git a/skullOS.HardwareServices/MicrophoneService.cs b/skullOS.HardwareServices/MicrophoneService.cs new file mode 100644 index 0000000..bcfbc0a --- /dev/null +++ b/skullOS.HardwareServices/MicrophoneService.cs @@ -0,0 +1,16 @@ +using Iot.Device.Media; +using skullOS.HardwareServices.Interfaces; + +namespace skullOS.HardwareServices +{ + public class MicrophoneService : IMicrophoneService + { + public SoundDevice Microphone { get; private set; } + + public MicrophoneService(SoundConnectionSettings micSettings = null) + { + micSettings ??= new SoundConnectionSettings(); + Microphone = SoundDevice.Create(micSettings); + } + } +} diff --git a/skullOS.HardwareServices/ProgrammableLedService.cs b/skullOS.HardwareServices/ProgrammableLedService.cs new file mode 100644 index 0000000..b978e6f --- /dev/null +++ b/skullOS.HardwareServices/ProgrammableLedService.cs @@ -0,0 +1,16 @@ +using Iot.Device.Ws28xx; +using skullOS.HardwareServices.Interfaces; +using System.Device.Spi; + +namespace skullOS.HardwareServices +{ + public class ProgrammableLedService : IProgrammableLedService + { + public Ws2812b LedArray { get; private set; } + + public ProgrammableLedService(SpiDevice spi, int width = 9) + { + LedArray = new Ws2812b(spi, width); + } + } +} diff --git a/skullOS.HardwareServices/SpeakerService.cs b/skullOS.HardwareServices/SpeakerService.cs new file mode 100644 index 0000000..13e7571 --- /dev/null +++ b/skullOS.HardwareServices/SpeakerService.cs @@ -0,0 +1,16 @@ +using Iot.Device.Media; +using skullOS.HardwareServices.Interfaces; + +namespace skullOS.HardwareServices +{ + public class SpeakerService : ISpeakerService + { + public SoundDevice Speaker { get; private set; } + + public SpeakerService(SoundConnectionSettings micSettings) + { + micSettings ??= new SoundConnectionSettings(); + Speaker = SoundDevice.Create(micSettings); + } + } +} diff --git a/skullOS.HardwareServices/skullOS.HardwareServices.csproj b/skullOS.HardwareServices/skullOS.HardwareServices.csproj new file mode 100644 index 0000000..bf60ebb --- /dev/null +++ b/skullOS.HardwareServices/skullOS.HardwareServices.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + + + + + + + + diff --git a/skullOS.Modules/Camera.cs b/skullOS.Modules/Camera.cs new file mode 100644 index 0000000..0d942f3 --- /dev/null +++ b/skullOS.Modules/Camera.cs @@ -0,0 +1,41 @@ +using skullOS.Core; +using skullOS.HardwareServices; +using skullOS.Modules.Interfaces; + +namespace skullOS.Modules +{ + public enum CameraMode + { + Image, + ShortVideo, + ContinuousVideo + } + + public class Camera : Module, ICameraModule + { + public CameraService CameraService; + public MicrophoneService MicrophoneService; + public CameraMode CameraMode = CameraMode.Image; + + public Camera() + { + FileManager.CreateSubDirectory("Captures"); + CameraService = new CameraService(); + MicrophoneService = new MicrophoneService(); + } + + public void TakePicture() + { + // Console.WriteLine($"({DateTime.Now}) Picture taken!"); //Maybe think about a better logging solution? + CameraService.Camera.Capture($"{FileManager.GetSkullDirectory()}/Captures/{DateTime.Now:yyyyMMddHHmmss}.jpg"); + } + + public void RecordShortVideo() + { + string audioLocation = $"{FileManager.GetSkullDirectory()}/Captures/{DateTime.Now:yyyyMMddHHmmss}.mp3"; + string videoLocation = $"{FileManager.GetSkullDirectory()}/Captures/{DateTime.Now:yyyyMMddHHmmss}"; + CameraService.RecordVideoAsync(FileManager.GetSkullDirectory() + "/Captures", 30); + MicrophoneService.Microphone.Record(30, audioLocation); + } + } +} diff --git a/skullOS.Modules/Downlink.cs b/skullOS.Modules/Downlink.cs new file mode 100644 index 0000000..c08798b --- /dev/null +++ b/skullOS.Modules/Downlink.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace skullOS.Modules +{ + internal class Downlink + { + } +} diff --git a/skullOS.Modules/Interfaces/ICameraModule.cs b/skullOS.Modules/Interfaces/ICameraModule.cs new file mode 100644 index 0000000..f16fe06 --- /dev/null +++ b/skullOS.Modules/Interfaces/ICameraModule.cs @@ -0,0 +1,6 @@ +namespace skullOS.Modules.Interfaces +{ + internal interface ICameraModule + { + } +} \ No newline at end of file diff --git a/skullOS.Modules/Module.cs b/skullOS.Modules/Module.cs new file mode 100644 index 0000000..4448987 --- /dev/null +++ b/skullOS.Modules/Module.cs @@ -0,0 +1,7 @@ +namespace skullOS.Modules +{ + public abstract class Module + { + + } +} diff --git a/skullOS.Modules/Prop.cs b/skullOS.Modules/Prop.cs new file mode 100644 index 0000000..3f14fa6 --- /dev/null +++ b/skullOS.Modules/Prop.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace skullOS.Modules +{ + internal class Prop + { + } +} diff --git a/skullOS.Modules/QrCodeReader.cs b/skullOS.Modules/QrCodeReader.cs new file mode 100644 index 0000000..e7472a6 --- /dev/null +++ b/skullOS.Modules/QrCodeReader.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace skullOS.Modules +{ + internal class QrCodeReader + { + } +} diff --git a/skullOS.Modules/Uplink.cs b/skullOS.Modules/Uplink.cs new file mode 100644 index 0000000..0ae4a23 --- /dev/null +++ b/skullOS.Modules/Uplink.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace skullOS.Modules +{ + internal class Uplink + { + } +} diff --git a/skullOS.Modules/skullOS.Modules.csproj b/skullOS.Modules/skullOS.Modules.csproj new file mode 100644 index 0000000..2cc93ab --- /dev/null +++ b/skullOS.Modules/skullOS.Modules.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + + + + + + + +