Skip to content

Commit

Permalink
Support the case where a PiJuice isn't present
Browse files Browse the repository at this point in the history
  • Loading branch information
mikegoatly committed Nov 14, 2023
1 parent 5718266 commit dc8f024
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 16 deletions.
72 changes: 72 additions & 0 deletions PiJuiceSharp/AbsentPiJuiceStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

namespace PiJuiceSharp
{
/// <summary>
/// A placeholder implementation of <see cref="IPiJuiceStatus"/> that returns default values for when no PiJuice
/// interface is present at all.
/// </summary>
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<string, object> 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)
{
}
}
}
19 changes: 19 additions & 0 deletions PiJuiceSharp/IPiJuiceStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

namespace PiJuiceSharp
{
public interface IPiJuiceStatus : IDisposable
{
float GetBatteryCurrent();
int GetBatteryTemperature();
float GetBatteryVoltage();
int GetChargeLevel();
Dictionary<string, object> 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);
}
}
18 changes: 16 additions & 2 deletions PiJuiceSharp/PiJuiceInterface.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Device.I2c;
using System.Diagnostics.CodeAnalysis;

namespace PiJuiceSharp
{
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion PiJuiceSharp/PiJuiceSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<EnableNETAnalyzers>True</EnableNETAnalyzers>
<AnalysisLevel>latest-all</AnalysisLevel>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<Version>0.2.0</Version>
<Version>0.3.0</Version>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
</PropertyGroup>

Expand Down
16 changes: 14 additions & 2 deletions PiJuiceSharp/PiJuiceStatus.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);
Expand Down
23 changes: 22 additions & 1 deletion PiJuiceSharp/StatusInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,31 @@
{
public enum BatteryStatus
{
/// <summary>
/// Battery is present, but not charging
/// </summary>
Normal = 0,

/// <summary>
/// Battery is charging from the its power input
/// </summary>
ChargingFromIn = 1,

/// <summary>
/// Battery is charging from the 5V IO pin
/// </summary>
ChargingFrom5vIo = 2,
NotPresent = 3

/// <summary>
/// The PiJuice board is present, but no battery is connected
/// </summary>
NotPresent = 3,

/// <summary>
/// No PiJuice board is present - no readings will be available. This is an extension to the
/// original PiJuice Python library.
/// </summary>
NoPiJuice = 8000,
}

public enum PowerInputStatus
Expand Down
4 changes: 1 addition & 3 deletions PiJuiceTest/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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<IPiJuiceStatus>(PiJuiceStatus.Create());
```

## PiJuice Status APIs

`GetStatus()` returns an object containing basic status information, defined as:

``` csharp
Expand All @@ -34,7 +47,8 @@ public enum BatteryStatus
Normal = 0,
ChargingFromIn = 1,
ChargingFrom5vIo = 2,
NotPresent = 3
NotPresent = 3,
NoPiJuice = 8000
}

public enum PowerInputStatus
Expand Down

0 comments on commit dc8f024

Please sign in to comment.