diff --git a/PiJuiceSharp/AbsentPiJuiceStatus.cs b/PiJuiceSharp/AbsentPiJuiceStatus.cs new file mode 100644 index 0000000..abbc227 --- /dev/null +++ b/PiJuiceSharp/AbsentPiJuiceStatus.cs @@ -0,0 +1,72 @@ + +namespace PiJuiceSharp +{ + /// + /// A placeholder implementation of that returns default values for when no PiJuice + /// interface is present at all. + /// + public sealed class AbsentPiJuiceStatus : IPiJuiceStatus + { + public void Dispose() + { + } + + public float GetBatteryCurrent() + { + return 0F; + } + + public int GetBatteryTemperature() + { + return 0; + } + + public float GetBatteryVoltage() + { + return 0F; + } + + public int GetChargeLevel() + { + return 0; + } + + public Dictionary GetFaultStatus() + { + return new(); + } + + public float GetGpioCurrent() + { + return 0F; + } + + public float GetGpioVoltage() + { + return 0F; + } + + public LedBlinkState GetLedBlinkState(Led led) + { + return new(); + } + + public Color GetLedState(Led led) + { + return new(); + } + + public StatusInfo GetStatus() + { + return new StatusInfo(false, false, BatteryStatus.NoPiJuice, PowerInputStatus.NotPresent, PowerInputStatus.NotPresent); + } + + public void SetLedBlinkState(Led led, LedBlinkState state) + { + } + + public void SetLedState(Led led, Color color) + { + } + } +} \ No newline at end of file diff --git a/PiJuiceSharp/IPiJuiceStatus.cs b/PiJuiceSharp/IPiJuiceStatus.cs new file mode 100644 index 0000000..908d689 --- /dev/null +++ b/PiJuiceSharp/IPiJuiceStatus.cs @@ -0,0 +1,19 @@ + +namespace PiJuiceSharp +{ + public interface IPiJuiceStatus : IDisposable + { + float GetBatteryCurrent(); + int GetBatteryTemperature(); + float GetBatteryVoltage(); + int GetChargeLevel(); + Dictionary GetFaultStatus(); + float GetGpioCurrent(); + float GetGpioVoltage(); + LedBlinkState GetLedBlinkState(Led led); + Color GetLedState(Led led); + StatusInfo GetStatus(); + void SetLedBlinkState(Led led, LedBlinkState state); + void SetLedState(Led led, Color color); + } +} \ No newline at end of file diff --git a/PiJuiceSharp/PiJuiceInterface.cs b/PiJuiceSharp/PiJuiceInterface.cs index e4b9dfd..1eb5e7c 100644 --- a/PiJuiceSharp/PiJuiceInterface.cs +++ b/PiJuiceSharp/PiJuiceInterface.cs @@ -1,4 +1,5 @@ using System.Device.I2c; +using System.Diagnostics.CodeAnalysis; namespace PiJuiceSharp { @@ -8,14 +9,27 @@ public sealed class PiJuiceInterface : IDisposable private readonly I2cDevice i2cDevice; private readonly int address; - - public PiJuiceInterface(int busId = 1, int deviceAddress = 0x14) + private PiJuiceInterface(int busId = 1, int deviceAddress = 0x14) { var settings = new I2cConnectionSettings(busId, deviceAddress); this.i2cDevice = I2cDevice.Create(settings); this.address = deviceAddress; } + public static bool TryConnect([NotNullWhen(true)] out PiJuiceInterface? piJuiceInterface) + { + try + { + piJuiceInterface = new PiJuiceInterface(); + return true; + } + catch (IOException) + { + piJuiceInterface = null; + return false; + } + } + public void Dispose() { this.i2cDevice?.Dispose(); diff --git a/PiJuiceSharp/PiJuiceSharp.csproj b/PiJuiceSharp/PiJuiceSharp.csproj index dc3fe02..a224475 100644 --- a/PiJuiceSharp/PiJuiceSharp.csproj +++ b/PiJuiceSharp/PiJuiceSharp.csproj @@ -24,7 +24,7 @@ True latest-all True - 0.2.0 + 0.3.0 True diff --git a/PiJuiceSharp/PiJuiceStatus.cs b/PiJuiceSharp/PiJuiceStatus.cs index 14eee33..d793b18 100644 --- a/PiJuiceSharp/PiJuiceStatus.cs +++ b/PiJuiceSharp/PiJuiceStatus.cs @@ -1,7 +1,7 @@  namespace PiJuiceSharp { - public sealed class PiJuiceStatus : IDisposable + public sealed class PiJuiceStatus : IPiJuiceStatus { private const byte STATUS_CMD = 0x40; private const byte CHARGE_LEVEL_CMD = 0x41; @@ -15,11 +15,23 @@ public sealed class PiJuiceStatus : IDisposable private const byte LED_BLINK_CMD = 0x68; private readonly PiJuiceInterface piJuiceInterface; - public PiJuiceStatus(PiJuiceInterface piJuiceInterface) + private PiJuiceStatus(PiJuiceInterface piJuiceInterface) { this.piJuiceInterface = piJuiceInterface; } + public static IPiJuiceStatus Create() + { +#pragma warning disable CA2000 // Dispose objects before losing scope - the PiJuiceInterface is disposed by the returned object + if (PiJuiceInterface.TryConnect(out PiJuiceInterface? piJuiceInterface)) + { + return new PiJuiceStatus(piJuiceInterface); + } +#pragma warning restore CA2000 // Dispose objects before losing scope + + return new AbsentPiJuiceStatus(); + } + public StatusInfo GetStatus() { byte d = this.piJuiceInterface.Read(STATUS_CMD); diff --git a/PiJuiceSharp/StatusInfo.cs b/PiJuiceSharp/StatusInfo.cs index 380e5ee..6b391b6 100644 --- a/PiJuiceSharp/StatusInfo.cs +++ b/PiJuiceSharp/StatusInfo.cs @@ -2,10 +2,31 @@ { public enum BatteryStatus { + /// + /// Battery is present, but not charging + /// Normal = 0, + + /// + /// Battery is charging from the its power input + /// ChargingFromIn = 1, + + /// + /// Battery is charging from the 5V IO pin + /// ChargingFrom5vIo = 2, - NotPresent = 3 + + /// + /// The PiJuice board is present, but no battery is connected + /// + NotPresent = 3, + + /// + /// No PiJuice board is present - no readings will be available. This is an extension to the + /// original PiJuice Python library. + /// + NoPiJuice = 8000, } public enum PowerInputStatus diff --git a/PiJuiceTest/Program.cs b/PiJuiceTest/Program.cs index cdc2b96..96543e0 100644 --- a/PiJuiceTest/Program.cs +++ b/PiJuiceTest/Program.cs @@ -2,9 +2,7 @@ using static System.Console; -var piJuiceInterface = new PiJuiceInterface(); - -var piJuiceStatus = new PiJuiceStatus(piJuiceInterface); +IPiJuiceStatus piJuiceStatus = PiJuiceStatus.Create(); #region Console writing function static void WriteHeader(string header) diff --git a/README.md b/README.md index 01cdcd2..000a095 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,15 @@ ![PiJuiceSharp logo](/docs/favicon-256.png) -An implementation of the PiJuice client library based on the original [PiJuice Python library](https://github.com/PiSupply/PiJuice/blob/master/Software/Source/pijuice.py) in pure .NET. Currently packaged as a .NET 6 library with only a dependency on `System.Device.Gpio`. +An implementation of the PiJuice client library based on the original [PiJuice Python library](https://github.com/PiSupply/PiJuice/blob/master/Software/Source/pijuice.py) +in pure .NET. Currently packaged as a .NET 6 library with only a dependency on `System.Device.Gpio`. -This library currently only supports a subset of the Status APIs, and other APIs such as the RTC and Power Management are not yet implemented. Implementing others should be fairly straightforward, but I just don't have a need for them at the moment - contributions are welcome if you need to extend it! +Only a subset of the Status APIs are currently supported, and other APIs such as the RTC and Power Management are not yet implemented. +Implementing others should be fairly straightforward, but I just don't have a need for them at the moment - contributions are welcome if you +need to extend it! + +This library is safe to use even if you don't know that the device will have a PiJuice attached. When a PiJuice isn't present, +default values will be returned for all APIs, and a value of `NoPiJuice` for `GetStatus().BatteryStatus`. ## Installation @@ -14,18 +20,25 @@ You can install the library from [NuGet](https://www.nuget.org/packages/PiJuiceS dotnet add package PiJuiceSharp ``` -## PiJuice Status APIs +## PiJuiceStatus You can use the `PiJuiceStatus` class to get various point-in-time status values of the PiJuice board. -To construct a `PiJuiceStatus`, you need to pass in an instance of `PiJuiceInterface`. +To construct a `PiJuiceStatus`, call `PiJuiceStatus.Create()`. This returns an implementation of `IPiJuiceStatus` which will be either a +fully connected `PiJuiceStatus` instance or an `AbsentPiJuiceStatus` instance which handles the case when no PiJuice was present. ``` csharp -var piJuiceInterface = new PiJuiceInterface(); +var piJuiceStatus = PiJuiceStatus.Create(); +``` + +If you're using dependency injection, you can configure the `IPiJuiceStatus` interface as a singleton: -var piJuiceStatus = new PiJuiceStatus(piJuiceInterface); +``` csharp +services.AddSingleton(PiJuiceStatus.Create()); ``` +## PiJuice Status APIs + `GetStatus()` returns an object containing basic status information, defined as: ``` csharp @@ -34,7 +47,8 @@ public enum BatteryStatus Normal = 0, ChargingFromIn = 1, ChargingFrom5vIo = 2, - NotPresent = 3 + NotPresent = 3, + NoPiJuice = 8000 } public enum PowerInputStatus