Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Prop mode #42

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions skullOS.Core/FileManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

public static void CreateSkullDirectory(bool usePersonalDir = true)
{
DirectoryInfo rootDirectory = null;

Check warning on line 11 in skullOS.Core/FileManager.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Converting null literal or possible null value to non-nullable type.

Check warning on line 11 in skullOS.Core/FileManager.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Converting null literal or possible null value to non-nullable type.
string pathToDir;
if (usePersonalDir)
{
Expand All @@ -23,14 +23,16 @@
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
rootDirectory = Directory.CreateDirectory(pathToDir + @"/skullOS",
unixCreateMode: UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute);
unixCreateMode: UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute |
UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
rootDirectoryPath = rootDirectory.FullName;

Check warning on line 35 in skullOS.Core/FileManager.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Dereference of a possibly null reference.

Check warning on line 35 in skullOS.Core/FileManager.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Dereference of a possibly null reference.
}

public static string GetSkullDirectory()
Expand All @@ -40,9 +42,12 @@

public static void CreateSubDirectory(string directoryName)
{
if (rootDirectoryPath != string.Empty)
if (rootDirectoryPath != string.Empty && RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Directory.CreateDirectory(@rootDirectoryPath + "/" + directoryName);
Directory.CreateDirectory(rootDirectoryPath + @"/" + directoryName,
unixCreateMode: UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute |
UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions skullOS.HardwareServices/CameraService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
private readonly ProcessSettings _processSettings;


public CameraService(VideoConnectionSettings cameraSettings = null)

Check warning on line 18 in skullOS.HardwareServices/CameraService.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 18 in skullOS.HardwareServices/CameraService.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Non-nullable field 'eventHandled' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 18 in skullOS.HardwareServices/CameraService.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 18 in skullOS.HardwareServices/CameraService.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Non-nullable field 'eventHandled' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
{
cameraSettings ??= new(busId: 0, captureSize: (2592, 1944), pixelFormat: VideoPixelFormat.JPEG);
Camera = VideoDevice.Create(cameraSettings);
Expand All @@ -25,14 +25,14 @@
_processSettings = ProcessSettingsFactory.CreateForLibcamerastill();
}

public async Task<string> TakePictureAsync(string fileLocation)
public async Task<string> TakePictureAsync(string fileLocation, int x = 2592, int y = 1944)
{
var builder = new CommandOptionsBuilder()
.WithTimeout(1)
.WithVflip()
.WithHflip()
.WithPictureOptions(quality: 100)
.WithResolution(2592, 1944);
.WithResolution(x, y);
var args = builder.GetArguments();

using var proc = new ProcessRunner(_processSettings);
Expand Down Expand Up @@ -93,7 +93,7 @@
cameraCommand.StartInfo.FileName = "raspivid";
cameraCommand.StartInfo.Arguments = args;
cameraCommand.EnableRaisingEvents = true;
cameraCommand.Exited += new EventHandler(VideoRecorded);

Check warning on line 96 in skullOS.HardwareServices/CameraService.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Nullability of reference types in type of parameter 'sender' of 'void CameraService.VideoRecorded(object sender, EventArgs e)' doesn't match the target delegate 'EventHandler' (possibly because of nullability attributes).

Check warning on line 96 in skullOS.HardwareServices/CameraService.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Nullability of reference types in type of parameter 'sender' of 'void CameraService.VideoRecorded(object sender, EventArgs e)' doesn't match the target delegate 'EventHandler' (possibly because of nullability attributes).
#if DEBUG
Console.Out.WriteLine(cameraCommand.StartInfo.Arguments);
#endif
Expand Down
4 changes: 3 additions & 1 deletion skullOS.HardwareServices/Interfaces/ICameraService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace skullOS.HardwareServices.Interfaces

namespace skullOS.HardwareServices.Interfaces
{
public interface ICameraService
{
Task<string> TakePictureAsync(string fileLocation, int x = 2592, int y = 1944);
}
}
4 changes: 4 additions & 0 deletions skullOS.HardwareServices/Interfaces/ILedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@
{
public interface ILedService
{
void BlinkLight(string light);
void TurnOff(int Pin);
void TurnOn(int Pin);
Dictionary<string, int> GetLeds();
}
}
4 changes: 3 additions & 1 deletion skullOS.HardwareServices/Interfaces/ISpeakerService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace skullOS.HardwareServices.Interfaces

namespace skullOS.HardwareServices.Interfaces
{
public interface ISpeakerService
{
Task PlayAudio(string filepath);
}
}
5 changes: 5 additions & 0 deletions skullOS.HardwareServices/LedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,10 @@ public void TurnOff(int Pin)
}
controller.Write(Pin, PinValue.Low);
}

public Dictionary<string, int> GetLeds()
{
return LEDs;
}
}
}
38 changes: 32 additions & 6 deletions skullOS.HardwareServices/SpeakerService.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
using Iot.Device.Media;
using skullOS.HardwareServices.Interfaces;
using skullOS.HardwareServices.Interfaces;
using System.Diagnostics;

namespace skullOS.HardwareServices
{
/// <summary>
/// Service to communicate with audio output
/// Requires `sudo apt install --no-install-recommends vlc-bin vlc-plugin-base` to have been ran first
/// </summary>
public class SpeakerService : ISpeakerService
{
public SoundDevice Speaker { get; private set; }
private TaskCompletionSource<bool> eventHandled;

public SpeakerService(SoundConnectionSettings micSettings)
public SpeakerService()

Check warning on line 14 in skullOS.HardwareServices/SpeakerService.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Non-nullable field 'eventHandled' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 14 in skullOS.HardwareServices/SpeakerService.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Non-nullable field 'eventHandled' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
{
micSettings ??= new SoundConnectionSettings();
Speaker = SoundDevice.Create(micSettings);

}

public async Task PlayAudio(string filepath)
{
eventHandled = new TaskCompletionSource<bool>();
using Process soundPlayback = new Process();

string args = " --play-and-exit " + filepath;
soundPlayback.StartInfo.UseShellExecute = false;
soundPlayback.StartInfo.FileName = "cvlc";
soundPlayback.StartInfo.Arguments = args;
soundPlayback.EnableRaisingEvents = true;
soundPlayback.Exited += SoundPlayback_Exited;
#if DEBUG
await Console.Out.WriteLineAsync(soundPlayback.StartInfo.FileName + soundPlayback.StartInfo.Arguments);
#endif
soundPlayback.Start();
await soundPlayback.WaitForExitAsync();
}

private void SoundPlayback_Exited(object? sender, EventArgs e)
{
eventHandled.TrySetResult(true);
}
}
}
50 changes: 50 additions & 0 deletions skullOS.Modules/Adventure.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using skullOS.Core;
using skullOS.HardwareServices;
using skullOS.HardwareServices.Interfaces;
using skullOS.Modules.Interfaces;
using Timer = System.Timers.Timer;

namespace skullOS.Modules
{
public class Adventure : Module, IAdventure
{
string directory = string.Empty;
static Timer takePicture;

Check warning on line 12 in skullOS.Modules/Adventure.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Non-nullable field 'takePicture' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 12 in skullOS.Modules/Adventure.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Non-nullable field 'takePicture' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
double interval = 30000;
ICameraService cameraService;

public Adventure()
{
var now = DateTime.Now.ToString("M");
FileManager.CreateSubDirectory("Timelapse - " + now);
directory = FileManager.GetSkullDirectory() + @"/Timelapse - " + now + @"/";
cameraService = new CameraService();


takePicture = new Timer(interval);
takePicture.AutoReset = true;
takePicture.Elapsed += TakePicture_Elapsed;
takePicture.Start();
}

private void TakePicture_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
cameraService.TakePictureAsync(directory, 1920, 1080);
}

public override void OnAction(object? sender, EventArgs e)
{
throw new NotImplementedException();
}

public override void OnEnable(string[] args)
{
throw new NotImplementedException();
}

public override string ToString()
{
return "Adventure";
}
}
}
3 changes: 3 additions & 0 deletions skullOS.Modules/Data/PropSettings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Sounds=True
Lights=True
Servos=True
6 changes: 6 additions & 0 deletions skullOS.Modules/Interfaces/IAdventure.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace skullOS.Modules.Interfaces
{
internal interface IAdventure
{
}
}
6 changes: 6 additions & 0 deletions skullOS.Modules/Interfaces/ISupport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace skullOS.Modules.Interfaces
{
internal interface ISupport
{
}
}
100 changes: 98 additions & 2 deletions skullOS.Modules/Prop.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,103 @@
namespace skullOS.Modules
using Iot.Device.ServoMotor;
using skullOS.Core;
using skullOS.HardwareServices;
using skullOS.HardwareServices.Interfaces;
using System.Device.Pwm.Drivers;
using Timer = System.Timers.Timer;

namespace skullOS.Modules
{
public class Prop : Module, IPropModule
{
public ISpeakerService SpeakerService { get; set; }
public ILedService LedService { get; set; }

static Timer PlayIdleSound;
double interval = 30000;
string[] sounds;
int numberOfIdles;

ServoMotor leftFlap;
ServoMotor rightFlap;

Dictionary<string, string> propSettings;
public Prop()

Check warning on line 24 in skullOS.Modules/Prop.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Non-nullable property 'SpeakerService' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
{
propSettings = SettingsLoader.LoadConfig(@"Data/PropSettings.txt");

if (propSettings.ContainsKey("Sounds"))
{
SpeakerService = new SpeakerService();
SpeakerService.PlayAudio(@"Resources/computer-startup-music.mp3"); //This one won't await :(
sounds = Directory.GetFiles(@"Resources/Haro/Idles");
numberOfIdles = sounds.Length;

PlayIdleSound = new Timer(interval);
PlayIdleSound.AutoReset = true;
PlayIdleSound.Elapsed += PlayIdleSound_Elapsed;
PlayIdleSound.Start();
}
if (propSettings.ContainsKey("Lights"))
{
//Left and right eye, these are next to each other so it should be easy to tell
Dictionary<string, int> pins = new Dictionary<string, int>
{
{ "LeftEye", 22 },
{"RightEye", 23 }
};
LedService = new LedService(pins);
foreach (var item in LedService.GetLeds())
{
int pin = item.Value;
LedService.TurnOn(pin);
}
}
if (propSettings.ContainsKey("Servos"))
{
var leftPWM = new SoftwarePwmChannel(5, 50);
leftFlap = new ServoMotor(leftPWM);
leftFlap.Start();
var rightPWM = new SoftwarePwmChannel(6, 50);
rightFlap = new ServoMotor(rightPWM);
rightFlap.Start();
}
}

private void PlayIdleSound_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
var random = new Random();
int selection = random.Next(0, numberOfIdles + 1);
SpeakerService.PlayAudio(sounds[selection]);
if (propSettings.ContainsKey("Servos"))
{
if (random.NextSingle() <= 0.5)
{
FlapEar(true);
}
else
{
FlapEar(false);
}
}
}

private async void FlapEar(bool useLeft = true)
{
if (useLeft)
{
leftFlap.WritePulseWidth(1500);
await Task.Delay(1500);
leftFlap.WritePulseWidth(0);
}
else
{
rightFlap.WritePulseWidth(1500);
await Task.Delay(1500);
rightFlap.WritePulseWidth(0);
}

}

public override void OnAction(object? sender, EventArgs e)
{
throw new NotImplementedException();
Expand All @@ -13,7 +109,7 @@
}
public override string ToString()
{
throw new NotImplementedException();
return "Prop";
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions skullOS.Modules/Resources/Sources.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
No battery - https://freesound.org/people/DAN2008/sounds/710280/
Haro Sounds - https://www.101soundboards.com/boards/44920-haro-sd-gundam-g-generation-genesis-combat-dialogue-nintendo-switch
Binary file not shown.
58 changes: 58 additions & 0 deletions skullOS.Modules/Support.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using skullOS.HardwareServices;
using skullOS.HardwareServices.Interfaces;
using skullOS.Modules.Interfaces;
using System.Device.Gpio;
using Timer = System.Timers.Timer;


namespace skullOS.Modules
{
public class Support : Module, ISupport
{
GpioController controller;
ISpeakerService speakerService;
static Timer LowBatteryAlert;

Check warning on line 14 in skullOS.Modules/Support.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Non-nullable field 'LowBatteryAlert' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 14 in skullOS.Modules/Support.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Non-nullable field 'LowBatteryAlert' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
double interval = 60000;
int pin = 4;

public Support()
{
LowBatteryAlert = new Timer(interval)
{
AutoReset = true,
};
LowBatteryAlert.Elapsed += LowBatteryAlert_Elapsed;

speakerService = new SpeakerService();
controller = new GpioController();
controller.OpenPin(pin);
controller.RegisterCallbackForPinValueChangedEvent(pin, PinEventTypes.Rising, OnLowBattery);
}

void OnLowBattery(object sender, PinValueChangedEventArgs args)
{
//Activate warning led - needs to be very dim to prevent it bleeding out of the casing
LowBatteryAlert.Start();
}

private void LowBatteryAlert_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
speakerService.PlayAudio(@"Resources\710280__dan2008__no-battery.mp3");
}

public override void OnAction(object? sender, EventArgs e)
{
throw new NotImplementedException();
}

public override void OnEnable(string[] args)
{
throw new NotImplementedException();
}

public override string ToString()
{
return "Support";
}
}
}
6 changes: 6 additions & 0 deletions skullOS.Modules/skullOS.Modules.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
<None Update="Data\CameraSettings.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Data\PropSettings.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\computer-startup-music.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Empty file removed skullOS/Data/AltInputSettings.txt
Empty file.
Loading
Loading