Skip to content

Commit

Permalink
Add color, delete button support to C# lib
Browse files Browse the repository at this point in the history
  • Loading branch information
Emill committed Aug 6, 2018
1 parent a0066d2 commit 2fc9ddf
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 18 deletions.
Expand Up @@ -37,7 +37,12 @@ public enum RemovedReason : byte
InternetBackendError,
InvalidData,

CouldntLoadDevice
CouldntLoadDevice,

DeletedByThisClient,
DeletedByOtherClient,

ButtonBelongsToOtherPartner
};

public enum ClickType : byte
Expand Down Expand Up @@ -71,7 +76,8 @@ public enum ScanWizardResult : byte
WizardButtonIsPrivate,
WizardBluetoothUnavailable,
WizardInternetBackendError,
WizardInvalidData
WizardInvalidData,
WizardButtonBelongsToOtherPartner
};

public enum BluetoothControllerState : byte
Expand Down
Expand Up @@ -27,11 +27,12 @@ namespace FliclibDotNetClient
Bdaddr[] verifiedButtons);

/// <summary>
/// Callback for GetButtonUUID
/// Callback for GetButtonInfo
/// </summary>
/// <param name="bdAddr">The Bluetooth device address for the request</param>
/// <param name="uuid">The UUID of the button. Will be null if the button was not verified bufore.</param>
public delegate void GetButtonUUIDResponseCallback(Bdaddr bdAddr, string uuid);
/// <param name="color">The color of the button. Will be null if the button was not verified before.</param>
public delegate void GetButtonInfoResponseCallback(Bdaddr bdAddr, string uuid, string color);

/// <summary>
/// NewVerifiedButtonEventArgs
Expand Down Expand Up @@ -66,6 +67,22 @@ public class BluetoothControllerStateChangeEventArgs : EventArgs
public BluetoothControllerState State { get; internal set; }
}

/// <summary>
/// ButtonDeletedEventArgs
/// </summary>
public class ButtonDeletedEventArgs : EventArgs
{
/// <summary>
/// Bluetooth device address of removed button
/// </summary>
public Bdaddr BdAddr { get; internal set; }

/// <summary>
/// Whether or not the button was deleted by this client
/// </summary>
public bool DeletedByThisClient { get; internal set; }
}

/// <summary>
/// Flic client class
///
Expand All @@ -92,7 +109,7 @@ public sealed class FlicClient : IDisposable
private readonly ConcurrentDictionary<uint, ButtonConnectionChannel> _connectionChannels = new ConcurrentDictionary<uint, ButtonConnectionChannel>();
private readonly ConcurrentDictionary<uint, ScanWizard> _scanWizards = new ConcurrentDictionary<uint, ScanWizard>();
private readonly ConcurrentQueue<GetInfoResponseCallback> _getInfoResponseCallbackQueue = new ConcurrentQueue<GetInfoResponseCallback>();
private readonly Queue<GetButtonUUIDResponseCallback> _getButtonUUIDResponseCallbackQueue = new Queue<GetButtonUUIDResponseCallback>();
private readonly Queue<GetButtonInfoResponseCallback> _getButtonInfoResponseCallbackQueue = new Queue<GetButtonInfoResponseCallback>();
private readonly SortedDictionary<long, Action> _timers = new SortedDictionary<long, Action>();

/// <summary>
Expand All @@ -115,6 +132,11 @@ public sealed class FlicClient : IDisposable
/// This event will be raised when the number of concurrent connections has decreased from the maximum by one (only sent by the Linux server implementation).
/// </summary>
public event EventHandler<SpaceForNewConnectionEventArgs> GotSpaceForNewConnection;

/// <summary>
/// Raised when a button is deleted, or when this client tries to delete a non-existing button.
/// </summary>
public event EventHandler<ButtonDeletedEventArgs> ButtonDeleted;

private FlicClient()
{
Expand Down Expand Up @@ -239,17 +261,17 @@ public void GetInfo(GetInfoResponseCallback callback)
/// </summary>
/// <param name="bdAddr">Bluetooth device address</param>
/// <param name="callback">Callback to be invoked when the response arrives</param>
public void GetButtonUUID(Bdaddr bdAddr, GetButtonUUIDResponseCallback callback)
public void GetButtonInfo(Bdaddr bdAddr, GetButtonInfoResponseCallback callback)
{
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}

lock (_getButtonUUIDResponseCallbackQueue)
lock (_getButtonInfoResponseCallbackQueue)
{
_getButtonUUIDResponseCallbackQueue.Enqueue(callback);
SendPacket(new CmdGetButtonUUID { BdAddr = bdAddr });
_getButtonInfoResponseCallbackQueue.Enqueue(callback);
SendPacket(new CmdGetButtonInfo { BdAddr = bdAddr });
}
}

Expand Down Expand Up @@ -706,16 +728,16 @@ private void DispatchPacket(byte[] packet)
BluetoothControllerStateChange.RaiseEvent(this, new BluetoothControllerStateChangeEventArgs { State = pkt.State });
}
break;
case EventPacket.EVT_GET_BUTTON_UUID_RESPONSE_OPCODE:
case EventPacket.EVT_GET_BUTTON_INFO_RESPONSE_OPCODE:
{
var pkt = new EvtGetButtonUUIDResponse();
var pkt = new EvtGetButtonInfoResponse();
pkt.Parse(packet);
GetButtonUUIDResponseCallback callback;
lock (_getButtonUUIDResponseCallbackQueue)
GetButtonInfoResponseCallback callback;
lock (_getButtonInfoResponseCallbackQueue)
{
callback = _getButtonUUIDResponseCallbackQueue.Dequeue();
callback = _getButtonInfoResponseCallbackQueue.Dequeue();
}
callback(pkt.BdAddr, pkt.Uuid);
callback(pkt.BdAddr, pkt.Uuid, pkt.Color);
}
break;
case EventPacket.EVT_SCAN_WIZARD_FOUND_PRIVATE_BUTTON_OPCODE:
Expand Down Expand Up @@ -755,6 +777,13 @@ private void DispatchPacket(byte[] packet)
wizard.OnCompleted(eventArgs);
}
break;
case EventPacket.EVT_BUTTON_DELETED_OPCODE:
{
var pkt = new EvtButtonDeleted();
pkt.Parse(packet);
ButtonDeleted.RaiseEvent(this, new ButtonDeletedEventArgs { BdAddr = pkt.BdAddr, DeletedByThisClient = pkt.DeletedByThisClient });
}
break;
}
}
}
Expand Down
Expand Up @@ -122,7 +122,7 @@ protected override void Write(BinaryWriter writer)
}
}

internal class CmdGetButtonUUID : CommandPacket
internal class CmdGetButtonInfo : CommandPacket
{
internal Bdaddr BdAddr;

Expand Down Expand Up @@ -155,6 +155,17 @@ protected override void Write(BinaryWriter writer)
}
}

internal class CmdDeleteButton : CommandPacket
{
internal Bdaddr BdAddr;

protected override void Write(BinaryWriter writer)
{
Opcode = 11;
BdAddr.WriteBytes(writer);
}
}

internal abstract class EventPacket
{
internal const int EVT_ADVERTISEMENT_PACKET_OPCODE = 0;
Expand All @@ -171,11 +182,12 @@ internal abstract class EventPacket
internal const int EVT_GOT_SPACE_FOR_NEW_CONNECTION_OPCODE = 11;
internal const int EVT_BLUETOOTH_CONTROLLER_STATE_CHANGE_OPCODE = 12;
internal const int EVT_PING_RESPONSE_OPCODE = 13;
internal const int EVT_GET_BUTTON_UUID_RESPONSE_OPCODE = 14;
internal const int EVT_GET_BUTTON_INFO_RESPONSE_OPCODE = 14;
internal const int EVT_SCAN_WIZARD_FOUND_PRIVATE_BUTTON_OPCODE = 15;
internal const int EVT_SCAN_WIZARD_FOUND_PUBLIC_BUTTON_OPCODE = 16;
internal const int EVT_SCAN_WIZARD_BUTTON_CONNECTED_OPCODE = 17;
internal const int EVT_SCAN_WIZARD_COMPLETED_OPCODE = 18;
internal const int EVT_BUTTON_DELETED_OPCODE = 19;

internal void Parse(byte[] arr)
{
Expand Down Expand Up @@ -342,10 +354,11 @@ protected override void ParseInternal(BinaryReader reader)
}
}

internal class EvtGetButtonUUIDResponse : EventPacket
internal class EvtGetButtonInfoResponse : EventPacket
{
internal Bdaddr BdAddr;
internal string Uuid;
internal string Color;

protected override void ParseInternal(BinaryReader reader)
{
Expand All @@ -365,6 +378,23 @@ protected override void ParseInternal(BinaryReader reader)
{
Uuid = null;
}

if (reader.PeekChar() == -1)
{
// For old protocol
return;
}
int colorLen = reader.ReadByte();
var bytes = new byte[colorLen];
for (var i = 0; i < colorLen; i++)
{
bytes[i] = reader.ReadByte();
}
for (var i = colorLen; i < 16; i++)
{
reader.ReadByte();
}
Color = colorLen == 0 ? null : Encoding.UTF8.GetString(bytes);
}
}

Expand Down Expand Up @@ -423,4 +453,16 @@ protected override void ParseInternal(BinaryReader reader)
Result = (ScanWizardResult)reader.ReadByte();
}
}

internal class EvtButtonDeleted : EventPacket
{
internal Bdaddr BdAddr;
internal bool DeletedByThisClient;

protected override void ParseInternal(BinaryReader reader)
{
BdAddr = new Bdaddr(reader);
DeletedByThisClient = reader.ReadBoolean();
}
}
}

0 comments on commit 2fc9ddf

Please sign in to comment.