From 8d3ceb177ef351d234ee096b873d3abd63bb2869 Mon Sep 17 00:00:00 2001 From: Brook Patten Date: Tue, 16 Feb 2016 21:35:48 -0500 Subject: [PATCH 1/8] merged changes to core from pebblesharp.mono.bluez --- .../AppMessage/AppMessagePacket.cs | 522 ++++++++++++++++++ PebbleSharp.Core/ApplicationManifest.cs | 2 +- PebbleSharp.Core/ApplicationMetadata.cs | 27 +- .../Apps/AppFetchRequestPacket.cs | 39 ++ .../Apps/AppFetchResponsePacket.cs | 26 + PebbleSharp.Core/Apps/AppRunStatePacket.cs | 28 + PebbleSharp.Core/BlobDB/AppMetaData.cs | 65 +++ PebbleSharp.Core/BlobDB/BlobDBClient.cs | 60 ++ .../BlobDB/BlobDBCommandPacket.cs | 54 ++ .../BlobDB/BlobDBResponsePacket.cs | 32 ++ PebbleSharp.Core/BlobDB/TimelineAction.cs | 60 ++ PebbleSharp.Core/BlobDB/TimelineAttribute.cs | 37 ++ PebbleSharp.Core/BlobDB/TimelineItem.cs | 97 ++++ PebbleSharp.Core/Bundles/AppBundle.cs | 15 +- PebbleSharp.Core/Bundles/BundleBase.cs | 35 +- PebbleSharp.Core/Enums.cs | 247 +++++++-- PebbleSharp.Core/FirmwareVersion.cs | 4 +- PebbleSharp.Core/Install/InstallClient.cs | 207 +++++++ PebbleSharp.Core/Pebble.cs | 315 +++-------- PebbleSharp.Core/PutBytes/PutBytesClient.cs | 93 ++++ .../PutBytes/PutBytesResponsePacket.cs | 23 + .../Responses/AppVersionResponse.cs | 68 +++ .../Responses/FirmwareVersionResponse.cs | 2 +- PebbleSharp.Core/UUID.cs | 25 + 24 files changed, 1772 insertions(+), 311 deletions(-) create mode 100644 PebbleSharp.Core/AppMessage/AppMessagePacket.cs create mode 100644 PebbleSharp.Core/Apps/AppFetchRequestPacket.cs create mode 100644 PebbleSharp.Core/Apps/AppFetchResponsePacket.cs create mode 100644 PebbleSharp.Core/Apps/AppRunStatePacket.cs create mode 100644 PebbleSharp.Core/BlobDB/AppMetaData.cs create mode 100644 PebbleSharp.Core/BlobDB/BlobDBClient.cs create mode 100644 PebbleSharp.Core/BlobDB/BlobDBCommandPacket.cs create mode 100644 PebbleSharp.Core/BlobDB/BlobDBResponsePacket.cs create mode 100644 PebbleSharp.Core/BlobDB/TimelineAction.cs create mode 100644 PebbleSharp.Core/BlobDB/TimelineAttribute.cs create mode 100644 PebbleSharp.Core/BlobDB/TimelineItem.cs create mode 100644 PebbleSharp.Core/Install/InstallClient.cs create mode 100644 PebbleSharp.Core/PutBytes/PutBytesClient.cs create mode 100644 PebbleSharp.Core/PutBytes/PutBytesResponsePacket.cs create mode 100644 PebbleSharp.Core/Responses/AppVersionResponse.cs diff --git a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs new file mode 100644 index 0000000..30c81a3 --- /dev/null +++ b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs @@ -0,0 +1,522 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; +using PebbleSharp.Core.Responses; + +namespace PebbleSharp.Core.NonPortable.AppMessage +{ + //modeled after https://github.com/pebble/libpebble2/blob/master/libpebble2/services/appmessage.py + [Endpoint(Endpoint.ApplicationMessage)] + public class AppMessagePacket: ResponseBase + { + //TODO: the key names are in the manifest.... do we need them for anything? + + //byte layout is as follows + //command (always 1?) byte + //transactionid byte + //uuid byte[16] + //tuplecount byte + //tuple + // k uint key + // t byte type + // l ushort length + + //1:250:34:162:123:154:11:7:71:175:173:135:178:194:147:5:186:182:1:0:0:0:0:2:1:0:1 + //sample message + //1: command + //250: transaction id + //34:162:123:154:11:7:71:175:173:135:178:194:147:5:186:182: //uuid + //1: //tuple count + //0:0:0:0: //first tuple, key + //2: //type + //1:0: //length + //1 //value + + //sample outbound message + //1: + //0: + //11:7:71:175:173:135:178:194:147:5:186:182:255:255:255:255: + //1: + //0:0:0:0: + //2: + //4:0: + //87:195:209:30: + + public byte Command { get; set; } + + public byte TransactionId { get; set; } + public UUID ApplicationId { get; set; } + + public AppMessagePacket() + { + Values = new List(); + } + + + + public AppMessagePacket(byte[] bytes) + { + Load(bytes); + } + + protected override void Load(byte[] bytes) + { + Values = new List(); + int index = 0; + var command = bytes[index]; + index++; + + Command = command; + //if (command == Command) + { + TransactionId = bytes[index]; + index++; + + ApplicationId = new UUID(bytes.Skip(index).Take(16).ToArray()); + index += 16; + + int tupleCount = bytes[index]; + index++; + + for (int i = 0; i < tupleCount; i++) + { + uint k; + byte t; + ushort l; + + k = BitConverter.ToUInt32(bytes, index); + index += 4; + + t = bytes[index]; + index++; + + l = BitConverter.ToUInt16(bytes, index); + index += 2; + + IAppMessageDictionaryEntry entry = null; + if (t == (byte)PackedType.Bytes) + { + entry = new AppMessageBytes() { Value = bytes.Skip(index).Take(l).ToArray() }; + } + else if (t == (byte)PackedType.Signed) + { + if (l == 1) + { + entry = new AppMessageInt8() { Value = Convert.ToSByte(bytes[index]) }; + } + else if (l == 2) + { + entry = new AppMessageInt16() { Value = BitConverter.ToInt16(bytes, index) }; + } + else if (l == 4) + { + entry = new AppMessageInt32() { Value = BitConverter.ToInt32(bytes, index) }; + } + else + { + throw new InvalidOperationException("Invalid signed integer length"); + } + } + else if (t == (byte)PackedType.String) + { + entry = new AppMessageString() { Value = System.Text.Encoding.UTF8.GetString(bytes, index, l) }; + } + else if (t == (byte)PackedType.Unsigned) + { + if (l == 1) + { + entry = new AppMessageUInt8() { Value = bytes[index] }; + } + else if (l == 2) + { + entry = new AppMessageUInt16() { Value = BitConverter.ToUInt16(bytes, index) }; + } + else if (l == 4) + { + entry = new AppMessageUInt32() { Value = BitConverter.ToUInt32(bytes, index) }; + } + else + { + throw new InvalidOperationException("Invalid signed integer length"); + } + } + else + { + throw new InvalidOperationException("Unknown tuple type"); + } + index += l; + entry.Key = k; + Values.Add(entry); + } + } + } + + public IList Values { get; set; } + + public byte[] GetBytes() + { + if (Values != null && Values.Any()) + { + var bytes = new List(); + bytes.Add(Command); + bytes.Add(TransactionId); + bytes.AddRange(ApplicationId.Data); + bytes.Add((byte)Values.Count); + foreach (var tuple in Values) + { + bytes.AddRange(tuple.PackedBytes); + } + return bytes.ToArray(); + } + else + { + return new byte[0]; + } + } + } + + public interface IAppMessageDictionaryEntry + { + uint Key { get; set; } + PackedType PackedType { get; } + ushort Length { get; } + byte[] ValueBytes { get; set; } + byte[] PackedBytes { get; } + } + + public enum Command:byte + { + Push=1 + } + + public enum PackedType:byte + { + Bytes=0, + String =1, + Unsigned =2, + Signed = 3 + } + + public abstract class AppMessageDictionaryEntry : IAppMessageDictionaryEntry + { + public uint Key { get; set; } + public abstract PackedType PackedType { get; } + public abstract ushort Length { get; } + + public virtual T Value { get; set; } + public abstract byte[] ValueBytes { get; set; } + + public byte[] PackedBytes + { + get + { + var bytes = new List(); + bytes.AddRange(BitConverter.GetBytes(Key)); + bytes.Add((byte)PackedType); + bytes.AddRange(BitConverter.GetBytes(Length)); + bytes.AddRange(ValueBytes); + return bytes.ToArray(); + } + } + } + + public class AppMessageUInt8 : AppMessageDictionaryEntry + { + public override PackedType PackedType + { + get { return PackedType.Unsigned; } + } + + public override ushort Length + { + get { return sizeof(byte); } + } + + public override byte[] ValueBytes + { + get { return new byte[] {Value}; } + set + { + if (value.Length == Length) + { + Value = value[0]; + } + else + { + throw new InvalidOperationException("Incorrect # of bytes"); + } + } + } + + public override string ToString() + { + return Value.ToString(); + } + } + + public class AppMessageUInt16 : AppMessageDictionaryEntry + { + public override PackedType PackedType + { + get { return PackedType.Unsigned; } + } + + public override ushort Length + { + get { return sizeof(UInt16); } + } + + public override byte[] ValueBytes + { + get { return BitConverter.GetBytes(Value); } + set + { + if (value.Length == Length) + { + Value = BitConverter.ToUInt16(value,0); + } + else + { + throw new InvalidOperationException("Incorrect # of bytes"); + } + } + } + + public override string ToString() + { + return Value.ToString(); + } + } + + public class AppMessageUInt32 : AppMessageDictionaryEntry + { + public override PackedType PackedType + { + get { return PackedType.Unsigned; } + } + + public override ushort Length + { + get { return sizeof(UInt32); } + } + + public override byte[] ValueBytes + { + get { return BitConverter.GetBytes(Value); } + set + { + if (value.Length == Length) + { + Value = BitConverter.ToUInt32(value, 0); + } + else + { + throw new InvalidOperationException("Incorrect # of bytes"); + } + } + } + + public override string ToString() + { + return Value.ToString(); + } + } + + public class AppMessageInt8 : AppMessageDictionaryEntry + { + public override PackedType PackedType + { + get { return PackedType.Signed; } + } + + public override ushort Length + { + get { return sizeof(sbyte); } + } + + public override byte[] ValueBytes + { + get { return new byte[] { Convert.ToByte(Value) }; } + set + { + if (value.Length == Length) + { + Value = Convert.ToSByte(value); + } + else + { + throw new InvalidOperationException("Incorrect # of bytes"); + } + } + } + + public override string ToString() + { + return Value.ToString(); + } + } + + public class AppMessageInt16 : AppMessageDictionaryEntry + { + public override PackedType PackedType + { + get { return PackedType.Signed; } + } + + public override ushort Length + { + get { return sizeof(Int16); } + } + + public override byte[] ValueBytes + { + get { return BitConverter.GetBytes(Value); } + set + { + if (value.Length == Length) + { + Value = BitConverter.ToInt16(value, 0); + } + else + { + throw new InvalidOperationException("Incorrect # of bytes"); + } + } + } + + public override string ToString() + { + return Value.ToString(); + } + } + + public class AppMessageInt32 : AppMessageDictionaryEntry + { + public override PackedType PackedType + { + get { return PackedType.Signed; } + } + + public override ushort Length + { + get { return sizeof(Int32); } + } + + public override byte[] ValueBytes + { + get { return BitConverter.GetBytes(Value); } + set + { + if (value.Length == Length) + { + Value = BitConverter.ToInt32(value, 0); + } + else + { + throw new InvalidOperationException("Incorrect # of bytes"); + } + } + } + + public override string ToString() + { + return Value.ToString(); + } + } + + public class AppMessageString : AppMessageDictionaryEntry + { + public override PackedType PackedType + { + get { return PackedType.String; } + } + + public override ushort Length + { + get { return (ushort)ValueBytes.Length; } + } + + public override string Value + { + get + { + return base.Value; + } + set + { + if(value!=null && value.EndsWith("\0")) + { + base.Value = value.Substring(0, value.Length - 1); + } + else + { + base.Value = value; + } + } + } + + public override byte[] ValueBytes + { + get { return System.Text.UTF8Encoding.UTF8.GetBytes(Value+"\0"); } + set + { + if (value.Length <= ushort.MaxValue) + { + Value = System.Text.UTF8Encoding.UTF8.GetString(value); + } + else + { + throw new OverflowException("Specified string is too large for length to fit in a ushort"); + } + } + } + + public override string ToString() + { + return Value.ToString(); + } + } + + public class AppMessageBytes : AppMessageDictionaryEntry + { + public override PackedType PackedType + { + get { return PackedType.Bytes; } + } + + public override ushort Length + { + get { return (ushort)Value.Length; } + } + + public override byte[] ValueBytes + { + get { return Value; } + set + { + if (value.Length <= ushort.MaxValue) + { + Value = value; + } + else + { + throw new OverflowException("Specified array is too large for length to fit in a ushort"); + } + } + } + + public override string ToString() + { + var s = new StringBuilder(); + foreach(var b in Value) + { + s.Append(b.ToString()); + s.Append(","); + } + return s.ToString(); + } + } +} diff --git a/PebbleSharp.Core/ApplicationManifest.cs b/PebbleSharp.Core/ApplicationManifest.cs index 14d016b..e0f9c46 100644 --- a/PebbleSharp.Core/ApplicationManifest.cs +++ b/PebbleSharp.Core/ApplicationManifest.cs @@ -12,7 +12,7 @@ public struct ApplicationManifest public string Filename { get; private set; } /// The firmware version required to run this application. - [DataMember(Name = "reqFwVer", IsRequired = true)] + [DataMember(Name = "reqFwVer", IsRequired = false)] public int RequiredFirmwareVersion { get; private set; } /// The time at which the application binary was created. (?) diff --git a/PebbleSharp.Core/ApplicationMetadata.cs b/PebbleSharp.Core/ApplicationMetadata.cs index 72928f2..79cde3f 100644 --- a/PebbleSharp.Core/ApplicationMetadata.cs +++ b/PebbleSharp.Core/ApplicationMetadata.cs @@ -23,6 +23,27 @@ public string StructVersion get { return string.Format("{0}.{1}", StructMajorVersion, StructMinorVersion); } } + /* + source: https://github.com/pebble/libpebble2/blob/d9ecce4a345f31217fb510f2f4e840f7cdda235b/libpebble2/util/bundle.py + python struct packing: https://docs.python.org/2/library/struct.html + STRUCT_DEFINITION = [ + '8s', # header = char[8] + '2B', # struct version = byte[2] + '2B', # sdk version = byte[2] + '2B', # app version =byte[2] + 'H', # size = ushort + 'I', # offset = uint + 'I', # crc = uint + '32s', # app name = char[32] + '32s', # company name = char[32] + 'I', # icon resource id = uint + 'I', # symbol table address = uint + 'I', # flags = uint + 'I', # num relocation list entries = uint + '16s' # uuid = char[16] + ] + */ + // The data as stored in the binary [Serializable(Order = 0, Size = 8)] public string Header { get; set; } @@ -54,11 +75,11 @@ public string StructVersion public uint SymbolTableAddress { get; set; } [Serializable(Order = 14)] public uint Flags { get; set; } + //[Serializable(Order = 15)] + //public uint RelocationListStart { get; set; } [Serializable(Order = 15)] - public uint RelocationListStart { get; set; } - [Serializable(Order = 16)] public uint RelocationListItemCount { get; set; } - [Serializable(Order = 17)] + [Serializable(Order = 16)] public UUID UUID { get; set; } public override string ToString() diff --git a/PebbleSharp.Core/Apps/AppFetchRequestPacket.cs b/PebbleSharp.Core/Apps/AppFetchRequestPacket.cs new file mode 100644 index 0000000..8787326 --- /dev/null +++ b/PebbleSharp.Core/Apps/AppFetchRequestPacket.cs @@ -0,0 +1,39 @@ +using System; +using System.Linq; +using PebbleSharp.Core.Responses; +namespace PebbleSharp.Core +{ + [Endpoint(Endpoint.AppFetch)] + public class AppFetchRequestPacket:ResponseBase + { + public byte Command { get; set; } + public UUID UUID { get; set; } + public int AppId { get; set; } + + public AppFetchRequestPacket() + { + } + + protected override void Load(byte[] payload) + { + Command = payload[0]; + UUID = new UUID(payload.Skip(1).Take(16).ToArray()); + + + //this packet is defined as little endian, which is slightly abnormal since + //it is coming from the pebble + //(most packets from he pebble are big endian / network endian) + //TODO: refactor Util conversions to respect per packet endian attributes + if (BitConverter.IsLittleEndian) + { + AppId = BitConverter.ToInt32(payload, 17); + } + else + { + //this will actually flip it because it thinks it is big endian. + AppId = Util.GetInt32(payload, 17); + } + } + } +} + diff --git a/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs b/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs new file mode 100644 index 0000000..727d897 --- /dev/null +++ b/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using PebbleSharp.Core.Responses; +namespace PebbleSharp.Core +{ + [Endpoint(Endpoint.AppFetch) + public class AppFetchResponsePacket + { + public byte Command { get; set; } + public AppFetchStatus Response { get; set; } + + public AppFetchResponsePacket() + { + Command = 1; + } + + public byte[] GetBytes() + { + var bytes = new List(); + bytes.Add(Command); + bytes.Add((byte)Response); + return bytes.ToArray(); + } + } +} + diff --git a/PebbleSharp.Core/Apps/AppRunStatePacket.cs b/PebbleSharp.Core/Apps/AppRunStatePacket.cs new file mode 100644 index 0000000..a42f954 --- /dev/null +++ b/PebbleSharp.Core/Apps/AppRunStatePacket.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using PebbleSharp.Core.Responses; +namespace PebbleSharp.Core +{ + [Endpoint( Endpoint.AppRunState)] + public class AppRunStatePacket + { + public AppRunState Command { get; set; } + public UUID UUID { get; set; } + + public AppRunStatePacket() + { + } + + public byte[] GetBytes() + { + var bytes = new List(); + bytes.Add((byte)Command); + if (Command == AppRunState.Start || Command == AppRunState.Stop) + { + bytes.AddRange(UUID.Data); + } + return bytes.ToArray(); + } + } +} + diff --git a/PebbleSharp.Core/BlobDB/AppMetaData.cs b/PebbleSharp.Core/BlobDB/AppMetaData.cs new file mode 100644 index 0000000..4b6a087 --- /dev/null +++ b/PebbleSharp.Core/BlobDB/AppMetaData.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using PebbleSharp.Core.Bundles; + +namespace PebbleSharp.Core.BlobDB +{ + public class AppMetaData + { + public UUID UUID { get; set; } + public UInt32 Flags { get; set; } + public UInt32 Icon { get; set; } + public byte AppVersionMajor { get; set; } + public byte AppVersionMinor { get; set; } + public byte SdkVersionMajor { get; set; } + public byte SdkVersionMinor { get; set; } + public byte AppFaceBackgroundColor { get; set; } + public byte AppFaceTemplateId { get; set; } + public string Name { get; set; }/*Fixed length 96*/ + + public byte[] GetBytes() + { + var bytes = new List(); + bytes.AddRange(this.UUID.Data); + bytes.AddRange(BitConverter.GetBytes(Flags)); + bytes.AddRange(BitConverter.GetBytes(Icon)); + bytes.Add(AppVersionMajor); + bytes.Add(AppVersionMinor); + bytes.Add(SdkVersionMajor); + bytes.Add(SdkVersionMinor); + bytes.Add(AppFaceBackgroundColor); + bytes.Add(AppFaceTemplateId); + var name = Name; + + //TODO: build "fixed" type strings into pebblesharp core + if (name.Length > 96) + { + name = name.Substring(0, 96); + } + name = name.PadRight(96, '\0'); + + var nameBytes = Util.GetBytes(name, false); + + bytes.AddRange(nameBytes); + return bytes.ToArray(); + } + + public static AppMetaData FromAppBundle(AppBundle bundle, byte appFaceTemplateId = 0, byte appFaceBackgroundColor = 0) + { + var meta = new PebbleSharp.Core.BlobDB.AppMetaData(); + meta.AppFaceTemplateId = appFaceTemplateId; + meta.AppFaceBackgroundColor = appFaceBackgroundColor; + meta.AppVersionMajor = bundle.AppMetadata.AppMajorVersion; + meta.AppVersionMinor = bundle.AppMetadata.AppMinorVersion; + meta.SdkVersionMajor = bundle.AppMetadata.SDKMajorVersion; + meta.SdkVersionMinor = bundle.AppMetadata.SDKMinorVersion; + meta.Flags = bundle.AppMetadata.Flags; + meta.Icon = bundle.AppMetadata.IconResourceID; + meta.UUID = bundle.AppMetadata.UUID; + meta.Name = bundle.AppMetadata.AppName; + + return meta; + } + } +} + diff --git a/PebbleSharp.Core/BlobDB/BlobDBClient.cs b/PebbleSharp.Core/BlobDB/BlobDBClient.cs new file mode 100644 index 0000000..7228f4e --- /dev/null +++ b/PebbleSharp.Core/BlobDB/BlobDBClient.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; + +namespace PebbleSharp.Core.BlobDB +{ + public class BlobDBClient + { + private Pebble _pebble; + private Random _random; + + public BlobDBClient(Pebble pebble) + { + _pebble = pebble; + _random = new Random(); + } + public async Task Insert(BlobDatabase database, byte[] key, byte[] value) + { + var insertCommand = new BlobDBCommandPacket() + { + Token = GenerateToken(), + Database = database, + Command = BlobCommand.Insert, + Key = key, + Value = value + }; + return await Send(insertCommand); + } + public async Task Delete(BlobDatabase database, byte[] key) + { + var deleteCommand = new BlobDBCommandPacket() + { + Token = GenerateToken(), + Database = database, + Command = BlobCommand.Delete, + Key = key, + }; + return await Send(deleteCommand); + } + public async Task Clear(BlobDatabase database) + { + var clearCommand = new BlobDBCommandPacket() + { + Token = GenerateToken(), + Database = database, + Command = BlobCommand.Clear + }; + return await Send(clearCommand); + } + private async Task Send(BlobDBCommandPacket command) + { + return await _pebble.SendBlobDBMessage(command); + } + public ushort GenerateToken() + { + //this is how libpebble2 does it...random.randrange(1, 2**16 - 1, 1) + return (ushort)_random.Next(1, (2 ^ 16) - 1); + } + } +} + diff --git a/PebbleSharp.Core/BlobDB/BlobDBCommandPacket.cs b/PebbleSharp.Core/BlobDB/BlobDBCommandPacket.cs new file mode 100644 index 0000000..8e66259 --- /dev/null +++ b/PebbleSharp.Core/BlobDB/BlobDBCommandPacket.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using PebbleSharp.Core; +using PebbleSharp.Core.Responses; + +namespace PebbleSharp.Core.BlobDB +{ + [Endpoint(Endpoint.BlobDB)] + public class BlobDBCommandPacket + { + public BlobCommand Command {get;set;} + public ushort Token { get; set; } + public BlobDatabase Database { get; set; } + + //only used for insert and delete commands + public byte[] Key { get; set; } + public byte KeyLength + { + get + { + return (byte)Key.Length; + } + } + + //only used for insert + public byte[] Value { get; set; } + public ushort ValueLength + { + get + { + return (ushort)Value.Length; + } + } + + public byte[] GetBytes() + { + var bytes = new List(); + bytes.Add((byte)Command); + bytes.AddRange(BitConverter.GetBytes(Token)); + bytes.Add((byte)this.Database); + if (this.Command == BlobCommand.Insert || this.Command == BlobCommand.Delete) + { + bytes.Add(this.KeyLength); + bytes.AddRange(this.Key); + if (this.Command == BlobCommand.Insert) + { + bytes.AddRange(BitConverter.GetBytes(this.ValueLength)); + bytes.AddRange(this.Value); + } + } + return bytes.ToArray(); + } + } +} \ No newline at end of file diff --git a/PebbleSharp.Core/BlobDB/BlobDBResponsePacket.cs b/PebbleSharp.Core/BlobDB/BlobDBResponsePacket.cs new file mode 100644 index 0000000..a09c91a --- /dev/null +++ b/PebbleSharp.Core/BlobDB/BlobDBResponsePacket.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using PebbleSharp.Core; +using PebbleSharp.Core.Responses; + +namespace PebbleSharp.Core.BlobDB +{ + [Endpoint(Endpoint.BlobDB)] + public class BlobDBResponsePacket :ResponseBase + { + public ushort Token { get; private set;} + public BlobStatus Response { get; private set; } + + public byte[] Payload { get; private set; } + //token = Uint16() + //response = Uint8(enum=BlobStatus) + + protected override void Load( byte[] payload ) + { + if (payload.Length == 0) + { + SetError("BlobDB Command failed"); + } + Payload = payload; + Token = BitConverter.ToUInt16(payload, 0); + Response = (BlobStatus)payload[2]; + } + } + + +} + diff --git a/PebbleSharp.Core/BlobDB/TimelineAction.cs b/PebbleSharp.Core/BlobDB/TimelineAction.cs new file mode 100644 index 0000000..c20dae5 --- /dev/null +++ b/PebbleSharp.Core/BlobDB/TimelineAction.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +namespace PebbleSharp.Core +{ + public class TimelineAction + { + public enum TimelineActionType:byte + { + AncsDismiss = 0x01, + Generic = 0x02, + Response = 0x03, + Dismiss = 0x04, + HTTP = 0x05, + Snooze = 0x06, + OpenWatchapp = 0x07, + Empty = 0x08, + Remove = 0x09, + OpenPin = 0x0a, + } + public byte ActionId { get; set; } + public TimelineActionType ActionType { get; set; } + public byte AttributeCount + { + get + { + if (Attributes != null) + { + return (byte)Attributes.Count; + } + else + { + return 0; + } + } + } + public IList Attributes { get; set; } + + public TimelineAction() + { + + } + + public byte[] GetBytes() + { + var bytes = new List(); + bytes.Add(ActionId); + bytes.Add((byte)ActionType); + bytes.Add(AttributeCount); + if (Attributes != null) + { + foreach (var attribute in Attributes) + { + bytes.AddRange(attribute.GetBytes()); + } + } + return bytes.ToArray(); + } + } +} + diff --git a/PebbleSharp.Core/BlobDB/TimelineAttribute.cs b/PebbleSharp.Core/BlobDB/TimelineAttribute.cs new file mode 100644 index 0000000..af83525 --- /dev/null +++ b/PebbleSharp.Core/BlobDB/TimelineAttribute.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +namespace PebbleSharp.Core +{ + public class TimelineAttribute + { + public byte AttributeId { get; set; } + public ushort Length + { + get + { + if (Content != null) + { + return (ushort)Content.Length; + } + else + { + return 0; + } + } + } + public byte[] Content { get; set; } + public TimelineAttribute() + { + } + + public byte[] GetBytes() + { + var bytes = new List(); + bytes.Add(AttributeId); + bytes.AddRange(BitConverter.GetBytes(Length)); + bytes.AddRange(Content); + return bytes.ToArray(); + } + } +} + diff --git a/PebbleSharp.Core/BlobDB/TimelineItem.cs b/PebbleSharp.Core/BlobDB/TimelineItem.cs new file mode 100644 index 0000000..74eed12 --- /dev/null +++ b/PebbleSharp.Core/BlobDB/TimelineItem.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; + +namespace PebbleSharp.Core +{ + public class TimelineItem + { + public enum TimelineItemType:byte + { + Notification=1, + Pin=2, + Reminder=3 + } + + public UUID ItemId { get; set; } + public UUID ParentId { get; set; } + public DateTime TimeStamp { get; set; } + public ushort Duration { get; set; } + public TimelineItemType ItemType { get; set; } + public ushort Flags { get; set; } + public byte Layout { get; set; } + public ushort DataLength { get; private set; } + public byte AttributeCount + { + get + { + if (Attributes != null) + { + return (byte)Attributes.Count; + } + else + { + return 0; + } + } + } + public byte ActionCount + { + get + { + if (Actions != null) + { + return (byte)Actions.Count; + } + else + { + return 0; + } + } + } + public IList Attributes { get; set; } + public IList Actions { get; set; } + + public TimelineItem() + { + } + + public byte[] GetBytes() + { + var bytes = new List(); + bytes.AddRange(ItemId.Data); + bytes.AddRange(ParentId.Data); + bytes.AddRange(BitConverter.GetBytes(Util.GetTimestampFromDateTime(this.TimeStamp))); + bytes.AddRange(BitConverter.GetBytes(Duration)); + bytes.Add((byte)this.ItemType); + bytes.AddRange(BitConverter.GetBytes(this.Flags)); + bytes.Add(Layout); + + var attributeBytes = new List(); + if (Attributes != null) + { + foreach (var attribute in Attributes) + { + attributeBytes.AddRange(attribute.GetBytes()); + } + } + + var actionBytes = new List(); + if (Actions != null) + { + foreach (var action in Actions) + { + actionBytes.AddRange(action.GetBytes()); + } + } + + this.DataLength = (ushort)(attributeBytes.Count + actionBytes.Count); + bytes.AddRange(BitConverter.GetBytes(DataLength)); + bytes.Add(AttributeCount); + bytes.Add(ActionCount); + bytes.AddRange(attributeBytes); + bytes.AddRange(actionBytes); + return bytes.ToArray(); + } + } +} + diff --git a/PebbleSharp.Core/Bundles/AppBundle.cs b/PebbleSharp.Core/Bundles/AppBundle.cs index 367fc7d..6455778 100644 --- a/PebbleSharp.Core/Bundles/AppBundle.cs +++ b/PebbleSharp.Core/Bundles/AppBundle.cs @@ -1,6 +1,7 @@ using System; using System.IO; using PebbleSharp.Core.Serialization; +using System.Runtime.Serialization.Json; namespace PebbleSharp.Core.Bundles { @@ -9,13 +10,14 @@ public class AppBundle : BundleBase public byte[] App { get; private set; } public ApplicationMetadata AppMetadata { get; private set; } - + public PebbleSharp.Core.NonPortable.AppInfo AppInfo { get; private set; } + protected override void LoadData( IZip zip ) { if ( string.IsNullOrWhiteSpace( Manifest.Application.Filename ) ) throw new InvalidOperationException( "Bundle does not contain pebble app" ); - using ( Stream binStream = zip.OpenEntryStream( Manifest.Application.Filename ) ) + using ( Stream binStream = zip.OpenEntryStream( this.PlatformSubdirectory()+Manifest.Application.Filename ) ) { if ( binStream == null ) throw new Exception( string.Format( "App file {0} not found in archive", Manifest.Application.Filename ) ); @@ -23,6 +25,15 @@ protected override void LoadData( IZip zip ) App = Util.GetBytes( binStream ); AppMetadata = BinarySerializer.ReadObject( App ); + } + //note, appinfo.json is NOT under the platform subdir + using (Stream appinfoStream = zip.OpenEntryStream("appinfo.json")) + { + if (appinfoStream != null) + { + var serializer = new DataContractJsonSerializer(typeof(PebbleSharp.Core.NonPortable.AppInfo)); + AppInfo = (PebbleSharp.Core.NonPortable.AppInfo)serializer.ReadObject(appinfoStream); + } } } diff --git a/PebbleSharp.Core/Bundles/BundleBase.cs b/PebbleSharp.Core/Bundles/BundleBase.cs index 4f44f40..2405369 100644 --- a/PebbleSharp.Core/Bundles/BundleBase.cs +++ b/PebbleSharp.Core/Bundles/BundleBase.cs @@ -10,35 +10,40 @@ public abstract class BundleBase public virtual bool HasResources { get; private set; } public BundleManifest Manifest { get; private set; } public virtual byte[] Resources { get; private set; } + public Platform Platform { get; private set;} protected abstract void LoadData(IZip zip); + protected string PlatformSubdirectory() + { + var platformSubdirectory = (Platform == Platform.UNKNOWN ? "" : Platform.ToString().ToLower()+"/"); + return platformSubdirectory; + } + + private BundleManifest LoadManifest(IZip zip) + { + using (var manifestStream = zip.OpenEntryStream(PlatformSubdirectory() + "manifest.json")) + { + var serializer = new DataContractJsonSerializer(typeof(BundleManifest)); + return (BundleManifest)serializer.ReadObject(manifestStream); + } + } + /// /// Create a new PebbleBundle from a .pwb file and parse its metadata. /// /// The stream to the bundle. /// The zip library implementation. - public void Load(Stream bundle, IZip zip) + public void Load(IZip zip, Platform platform) { - //TODO: This needs to be refactored, probably put into a Load method - if (false == zip.Open(bundle)) - throw new InvalidOperationException("Failed to open pebble bundle"); - - using (Stream manifestStream = zip.OpenEntryStream("manifest.json")) - { - if (manifestStream == null) - { - throw new InvalidOperationException("manifest.json not found in archive - not a valid Pebble bundle."); - } - var serializer = new DataContractJsonSerializer(typeof(BundleManifest)); - Manifest = (BundleManifest)serializer.ReadObject(manifestStream); - } + Platform = platform; + Manifest = LoadManifest (zip); HasResources = (Manifest.Resources.Size != 0); if (HasResources) { - using (Stream resourcesBinary = zip.OpenEntryStream(Manifest.Resources.Filename)) + using (Stream resourcesBinary = zip.OpenEntryStream(PlatformSubdirectory()+Manifest.Resources.Filename)) { if (resourcesBinary == null) throw new PebbleException("Could not find resource entry in the bundle"); diff --git a/PebbleSharp.Core/Enums.cs b/PebbleSharp.Core/Enums.cs index fc07815..7577d9b 100644 --- a/PebbleSharp.Core/Enums.cs +++ b/PebbleSharp.Core/Enums.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace PebbleSharp.Core { @@ -17,61 +18,44 @@ public enum MediaControl : byte SendNowPlaying = 9 } - /// - /// Endpoints (~"commands") used by Pebble to indicate particular instructions - /// or instruction types. - /// - public enum Endpoint : ushort - { - Firmware = 1, - Time = 11, - FirmwareVersion = 16, - PhoneVersion = 17, - SystemMessage = 18, - MusicControl = 32, - PhoneControl = 33, - ApplicationMessage = 48, - Launcher = 49, - AppCustomize = 50, - Logs = 2000, - Ping = 2001, - LogDump = 2002, - Reset = 2003, - App = 2004, - Mfg = 2004, - AppLogs = 2006, - Notification = 3000, - Resource = 4000, - SysReg = 5000, - FctReg = 5001, - AppManager = 6000, - RunKeeper = 7000, - PutBytes = 48879, - DataLog = 6778, - CoreDump = 9000, - MaxEndpoint = 65535 //ushort.MaxValue - } + /// + /// Endpoints (~"commands") used by Pebble to indicate particular instructions + /// or instruction types. + /// + public enum Endpoint : ushort + { + Firmware = 1, + Time = 11, + FirmwareVersion = 16, + PhoneVersion = 17, + SystemMessage = 18, + MusicControl = 32, + PhoneControl = 33, + ApplicationMessage = 48, + Launcher = 49, + AppCustomize = 50, + AppRunState = 52, + Logs = 2000, + Ping = 2001, + LogDump = 2002, + Reset = 2003, + App = 2004, + Mfg = 2004, + AppLogs = 2006, + Notification = 3000, + Resource = 4000, + SysReg = 5000, + FctReg = 5001, + AppManager = 6000, + AppFetch = 6001, + RunKeeper = 7000, + PutBytes = 48879, + DataLog = 6778, + CoreDump = 9000, + BlobDB = 45531,//0xb1db + MaxEndpoint = 65535, //ushort.MaxValue - [Flags] - public enum RemoteCaps : uint - { - Unknown = 0, - IOS = 1, - Android = 2, - OSX = 3, - Linux = 4, - Windows = 5, - Telephony = 16, - SMS = 32, - GPS = 64, - BTLE = 128, - // 240? No, that doesn't make sense. But it's apparently true. - CameraFront = 240, - CameraRear = 256, - Accelerometer = 512, - Gyro = 1024, - Compass = 2048 - } + } public enum LogLevel { @@ -91,4 +75,159 @@ public enum AppMessage : byte Ack = 0xFF, Nack = 0x7F } + + public enum BlobDatabase:byte + { + Test = 0, + Pin = 1, + App = 2, + Reminder = 3, + Notification = 4 + } + + public enum BlobStatus:byte + { + Success = 0x01, + GeneralFailure = 0x02, + InvalidOperation = 0x03, + InvalidDatabaseID = 0x04, + InvalidData = 0x05, + KeyDoesNotExist = 0x06, + DatabaseFull = 0x07, + DataStale = 0x08 + } + + public enum BlobCommand:byte + { + Insert=0x01, + Delete=0x04, + Clear=0x05, + } + + public enum AppRunState : byte + { + Start=0x01, + Stop=0x02, + Request=0x03, + } + + public enum AppFetchStatus : byte + { + Start = 0x01, + Busy = 0x02, + InvalidUUID = 0x03, + NoData = 0x04 + } + + + public enum TransferType : byte + { + Firmware = 1, + Recovery = 2, + SysResources = 3, + Resources = 4, + Binary = 5, + File=6, + Worker=7 + } + + public enum SystemMessage : byte + { + FirmwareAvailible = 0, + FirmwareStart = 1, + FirmwareComplete = 2, + FirmwareFail = 3, + FirmwareUpToDate = 4, + FirmwareOutOfDate = 5, + BluetoothStartDiscoverable = 6, + BluetoothEndDiscoverable = 7 + } + + public enum PutBytesType : byte + { + Init=0x01, + Put=0x02, + Commit=0x03, + Abort=0x04, + Install=0x05, + } + + public enum PutBytesResult : byte + { + Ack=0x01, + Nack=0x02 + } + + public enum ResetCommand + { + Reset = 0x00, + DumpCore = 0x01, + FactoryReset = 0x02, + PRF = 0x03 + } + + public enum Hardware:byte + { + UNKNOWN = 0, + TINTIN_EV1 = 1, + TINTIN_EV2 = 2, + TINTIN_EV2_3 = 3, + TINTIN_EV2_4 = 4, + TINTIN_V1_5 = 5, + BIANCA = 6, + SNOWY_EVT2 = 7, + SNOWY_DVT = 8, + SPALDING_EVT = 9, + BOBBY_SMILES = 10, + SPALDING = 11, + TINTIN_BB = 0xFF, + TINTIN_BB2 = 0xFE, + SNOWY_BB = 0xFD, + SNOWY_BB2 = 0xFC, + SPALDING_BB2 = 0xFB, + } + + public enum Platform : byte + { + UNKNOWN, + APLITE, + BASALT, + CHALK + } + + public static class HardwareHelpers + { + private static Dictionary Platforms; + + private static void Initialize() + { + if (Platforms == null) + { + Platforms = new Dictionary(); + Platforms.Add(Hardware.UNKNOWN, Platform.UNKNOWN); + Platforms.Add(Hardware.TINTIN_EV1, Platform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2,Platform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2_3, Platform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2_4,Platform.APLITE); + Platforms.Add(Hardware.TINTIN_V1_5,Platform.APLITE); + Platforms.Add(Hardware.BIANCA,Platform.APLITE); + Platforms.Add(Hardware.SNOWY_EVT2,Platform.BASALT); + Platforms.Add(Hardware.SNOWY_DVT,Platform.BASALT); + Platforms.Add(Hardware.BOBBY_SMILES,Platform.BASALT); + Platforms.Add(Hardware.SPALDING_EVT,Platform.CHALK); + Platforms.Add(Hardware.SPALDING,Platform.CHALK); + Platforms.Add(Hardware.TINTIN_BB,Platform.APLITE); + Platforms.Add(Hardware.TINTIN_BB2,Platform.APLITE); + Platforms.Add(Hardware.SNOWY_BB,Platform.BASALT); + Platforms.Add(Hardware.SNOWY_BB2,Platform.BASALT); + Platforms.Add(Hardware.SPALDING_BB2,Platform.CHALK); + } + } + + public static Platform GetPlatform(this Hardware hardware) + { + Initialize(); + return Platforms[hardware]; + } + } } \ No newline at end of file diff --git a/PebbleSharp.Core/FirmwareVersion.cs b/PebbleSharp.Core/FirmwareVersion.cs index 67b7576..00588b3 100644 --- a/PebbleSharp.Core/FirmwareVersion.cs +++ b/PebbleSharp.Core/FirmwareVersion.cs @@ -5,7 +5,7 @@ namespace PebbleSharp.Core public class FirmwareVersion { public FirmwareVersion( DateTime timestamp, string version, string commit, - bool isRecovery, byte hardwarePlatform, byte metadataVersion ) + bool isRecovery, Hardware hardwarePlatform, byte metadataVersion ) { Timestamp = timestamp; Version = version; @@ -19,7 +19,7 @@ public FirmwareVersion( DateTime timestamp, string version, string commit, public string Version { get; private set; } public string Commit { get; private set; } public bool IsRecovery { get; private set; } - public byte HardwarePlatform { get; private set; } + public Hardware HardwarePlatform { get; private set; } public byte MetadataVersion { get; private set; } public override string ToString() diff --git a/PebbleSharp.Core/Install/InstallClient.cs b/PebbleSharp.Core/Install/InstallClient.cs new file mode 100644 index 0000000..5d7c0ea --- /dev/null +++ b/PebbleSharp.Core/Install/InstallClient.cs @@ -0,0 +1,207 @@ +using System; +using System.Threading.Tasks; +using System.Linq; +using System.Collections.Generic; +using PebbleSharp.Core.Responses; +using PebbleSharp.Core.Bundles; +using PebbleSharp.Core.BlobDB; + +namespace PebbleSharp.Core.Install +{ + public class InstallClient + { + private Pebble _pebble; + public InstallClient(Pebble pebble) + { + _pebble = pebble; + } + public async Task InstallAppAsync( AppBundle bundle, IProgress progress = null ) + { + + string version = _pebble.Firmware.Version; + version = version.Replace("v", ""); + var components = version.Split(new char[] { '.','-' }, StringSplitOptions.RemoveEmptyEntries); + + int i; + IList versionComponents = components.Where(x=>int.TryParse(x,out i)).Select(x => int.Parse(x)).ToList(); + if (versionComponents[0] < 3) + { + await InstallAppLegacyV2 (bundle, progress); + } + else + { + await InstallAppAsyncV3 (bundle, progress); + } + } + + + private async Task InstallAppAsyncV3(AppBundle bundle,IProgress progress) + { + //https://github.com/pebble/libpebble2/blob/master/libpebble2/services/install.py + + var meta = AppMetaData.FromAppBundle(bundle); + + var bytes = meta.GetBytes(); + var result = await _pebble.BlobDBClient.Delete(BlobDatabase.App, meta.UUID.Data); + + result = await _pebble.BlobDBClient.Insert(BlobDatabase.App, meta.UUID.Data, bytes); + + if (result.Response == BlobStatus.Success) + { + var startPacket = new AppRunStatePacket(); + startPacket.Command = AppRunState.Start; + startPacket.UUID = meta.UUID; + //app_fetch = self._pebble.send_and_read(AppRunState(data=AppRunStateStart(uuid=app_uuid)), AppFetchRequest) + + var runStateResult = await _pebble.SendMessageAsync(Endpoint.AppRunState, startPacket.GetBytes()); + + if (!runStateResult.Success) + { + throw new InvalidOperationException("Pebble replied invalid run state"); + } + + if (!meta.UUID.Equals(runStateResult.UUID)) + { + var response = new AppFetchResponsePacket(); + response.Response = AppFetchStatus.InvalidUUID; + await _pebble.SendMessageNoResponseAsync(Endpoint.AppFetch, response.GetBytes()); + throw new InvalidOperationException("The pebble requested the wrong UUID"); + } + + var putBytesResponse = await _pebble.PutBytesClient.PutBytes(bundle.App, TransferType.Binary, appInstallId:(uint)runStateResult.AppId); + if (!putBytesResponse) + { + throw new InvalidOperationException("Putbytes failed"); + } + + if (bundle.HasResources) + { + putBytesResponse = await _pebble.PutBytesClient.PutBytes(bundle.Resources, TransferType.Resources, appInstallId:(uint)runStateResult.AppId); + if (!putBytesResponse) + { + throw new InvalidOperationException("Putbytes failed"); + } + } + + //TODO: add worker to manifest and transfer it if necassary + //if (bundle.HasWorker) + //{ + //await PutBytesV3(bundle.Worker, TransferType.Worker, runStateResult.AppId); + //} + + } + else + { + throw new DataMisalignedException("BlobDB Insert Failed"); + } + } + + private async Task InstallAppLegacyV2(AppBundle bundle, IProgress progress= null) + { + if ( bundle == null ) + throw new ArgumentNullException( "bundle" ); + + if ( progress != null ) + progress.Report( new ProgressValue( "Removing previous install(s) of the app if they exist", 1 ) ); + ApplicationMetadata metaData = bundle.AppMetadata; + UUID uuid = metaData.UUID; + + AppbankInstallResponse appbankInstallResponse = await RemoveAppByUUID( uuid ); + if ( appbankInstallResponse.Success == false ) + return; + + if ( progress != null ) + progress.Report( new ProgressValue( "Getting current apps", 20 ) ); + AppbankResponse appBankResult = await GetAppbankContentsAsync(); + + if ( appBankResult.Success == false ) + throw new PebbleException( "Could not obtain app list; try again" ); + AppBank appBank = appBankResult.AppBank; + + byte firstFreeIndex = 1; + foreach ( App app in appBank.Apps ) + if ( app.Index == firstFreeIndex ) + firstFreeIndex++; + if ( firstFreeIndex == appBank.Size ) + throw new PebbleException( "All app banks are full" ); + + if ( progress != null ) + progress.Report( new ProgressValue( "Transferring app to Pebble", 40 ) ); + + if ( await _pebble.PutBytesClient.PutBytes( bundle.App, TransferType.Binary,index:firstFreeIndex ) == false ) + throw new PebbleException( "Failed to send application binary pebble-app.bin" ); + + if ( bundle.HasResources ) + { + if ( progress != null ) + progress.Report( new ProgressValue( "Transferring app resources to Pebble", 60 ) ); + if ( await _pebble.PutBytesClient.PutBytes( bundle.Resources, TransferType.Resources,index:firstFreeIndex ) == false ) + throw new PebbleException( "Failed to send application resources app_resources.pbpack" ); + } + + if ( progress != null ) + progress.Report( new ProgressValue( "Adding app", 80 ) ); + await AddApp( firstFreeIndex ); + if ( progress != null ) + progress.Report( new ProgressValue( "Done", 100 ) ); + } + + + + public async Task InstallFirmwareAsync( FirmwareBundle bundle, IProgress progress = null ) + { + if ( bundle == null ) throw new ArgumentNullException( "bundle" ); + + if ( progress != null ) + progress.Report( new ProgressValue( "Starting firmware install", 1 ) ); + if ( ( await _pebble.SendSystemMessageAsync( SystemMessage.FirmwareStart ) ).Success == false ) + { + return false; + } + + if ( bundle.HasResources ) + { + if ( progress != null ) + progress.Report( new ProgressValue( "Transfering firmware resources", 25 ) ); + if ( await _pebble.PutBytesClient.PutBytes( bundle.Resources, TransferType.SysResources,index:0 ) == false ) + { + return false; + } + } + + if ( progress != null ) + progress.Report( new ProgressValue( "Transfering firmware", 50 ) ); + if ( await _pebble.PutBytesClient.PutBytes( bundle.Firmware, TransferType.Firmware,index:0 ) == false ) + { + return false; + } + + if ( progress != null ) + progress.Report( new ProgressValue( "Completing firmware install", 75 ) ); + bool success = ( await _pebble.SendSystemMessageAsync( SystemMessage.FirmwareComplete ) ).Success; + + if ( progress != null ) + progress.Report( new ProgressValue( "Done installing firmware", 100 ) ); + + return success; + } + + public async Task RemoveAppByUUID( UUID uuid ) + { + byte[] data = Util.CombineArrays( new byte[] { 2 }, uuid.Data ); + return await _pebble.SendMessageAsync( Endpoint.AppManager, data ); + } + + public async Task AddApp( byte index ) + { + byte[] data = Util.CombineArrays( new byte[] { 3 }, Util.GetBytes( (uint)index ) ); + await _pebble.SendMessageNoResponseAsync( Endpoint.AppManager, data ); + } + + public async Task GetAppbankContentsAsync() + { + return await _pebble.SendMessageAsync( Endpoint.AppManager, new byte[] { 1 } ); + } + } +} + diff --git a/PebbleSharp.Core/Pebble.cs b/PebbleSharp.Core/Pebble.cs index 178f387..6ce8fca 100644 --- a/PebbleSharp.Core/Pebble.cs +++ b/PebbleSharp.Core/Pebble.cs @@ -3,9 +3,13 @@ using System.Diagnostics; using System.Globalization; using System.Linq; +using System.Text; using System.Threading.Tasks; using PebbleSharp.Core.Bundles; +using PebbleSharp.Core.NonPortable.AppMessage; using PebbleSharp.Core.Responses; +using PebbleSharp.Core.BlobDB; +using PebbleSharp.Core.Install; namespace PebbleSharp.Core { @@ -16,19 +20,15 @@ namespace PebbleSharp.Core /// public abstract class Pebble { - public enum SessionCaps : uint - { - GAMMA_RAY = 0x80000000 - } - - public const byte PEBBLE_CLIENT_VERSION = 2; - - private readonly PebbleProtocol _PebbleProt; + public FirmwareVersion Firmware { get; private set;} + private readonly PebbleProtocol _PebbleProt; private readonly Dictionary> _callbackHandlers; private readonly ResponseManager _responseManager = new ResponseManager(); - private uint _RemoteCaps = (uint)( RemoteCaps.Telephony | RemoteCaps.SMS | RemoteCaps.Android ); - private uint _SessionCaps = (uint)SessionCaps.GAMMA_RAY; + + public BlobDBClient BlobDBClient { get; private set;} + public PutBytesClient PutBytesClient { get; private set;} + public InstallClient InstallClient { get; private set;} /// /// Create a new Pebble @@ -40,15 +40,18 @@ public enum SessionCaps : uint /// protected Pebble( IBluetoothConnection connection, string pebbleId ) { - ResponseTimeout = TimeSpan.FromSeconds( 5 ); + ResponseTimeout = TimeSpan.FromSeconds( 5 ); PebbleID = pebbleId; + this.BlobDBClient = new BlobDBClient(this); + this.PutBytesClient = new PutBytesClient(this); + this.InstallClient = new InstallClient(this); _callbackHandlers = new Dictionary>(); _PebbleProt = new PebbleProtocol( connection ); _PebbleProt.RawMessageReceived += RawMessageReceived; - RegisterCallback( OnApplicationMessageReceived ); + RegisterCallback( OnApplicationMessageReceived ); } /// @@ -68,25 +71,6 @@ public IBluetoothConnection Connection public TimeSpan ResponseTimeout { get; set; } - /// - /// Set the capabilities you want to tell the Pebble about. - /// Should be called before connecting. - /// - /// - /// - public void SetCaps( uint? sessionCap = null, uint? remoteCaps = null ) - { - if ( sessionCap != null ) - { - _SessionCaps = (uint)sessionCap; - } - - if ( remoteCaps != null ) - { - _RemoteCaps = (uint)remoteCaps; - } - } - /// /// Connect with the Pebble. /// @@ -104,20 +88,21 @@ public async Task ConnectAsync() if ( response != null ) { - byte[] prefix = { PEBBLE_CLIENT_VERSION, 0xFF, 0xFF, 0xFF, 0xFF }; - byte[] session = Util.GetBytes( _SessionCaps ); - byte[] remote = Util.GetBytes( _RemoteCaps ); - - byte[] msg = Util.CombineArrays( prefix, session, remote ); - //\x01\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x002 - await SendMessageNoResponseAsync( Endpoint.PhoneVersion, msg ); + var message = new AppVersionResponse(); + await SendMessageNoResponseAsync( Endpoint.PhoneVersion, message.GetBytes() ); IsAlive = true; + + //get the firmware details, we'll need to know the platform and version for possible future actions + var firmwareResponse = await this.GetFirmwareVersionAsync(); + this.Firmware = firmwareResponse.Firmware; } else { Disconnect(); } - } + } + + /// /// Disconnect from the Pebble, if a connection existed. @@ -247,93 +232,7 @@ public async Task BadPingAsync() return await SendMessageAsync( Endpoint.Ping, cookie ); } - public async Task InstallAppAsync( AppBundle bundle, IProgress progress = null ) - { - if ( bundle == null ) - throw new ArgumentNullException( "bundle" ); - - if ( progress != null ) - progress.Report( new ProgressValue( "Removing previous install(s) of the app if they exist", 1 ) ); - ApplicationMetadata metaData = bundle.AppMetadata; - UUID uuid = metaData.UUID; - - AppbankInstallResponse appbankInstallResponse = await RemoveAppByUUID( uuid ); - if ( appbankInstallResponse.Success == false ) - return; - - if ( progress != null ) - progress.Report( new ProgressValue( "Getting current apps", 20 ) ); - AppbankResponse appBankResult = await GetAppbankContentsAsync(); - - if ( appBankResult.Success == false ) - throw new PebbleException( "Could not obtain app list; try again" ); - AppBank appBank = appBankResult.AppBank; - - byte firstFreeIndex = 1; - foreach ( App app in appBank.Apps ) - if ( app.Index == firstFreeIndex ) - firstFreeIndex++; - if ( firstFreeIndex == appBank.Size ) - throw new PebbleException( "All app banks are full" ); - - if ( progress != null ) - progress.Report( new ProgressValue( "Transferring app to Pebble", 40 ) ); - - if ( await PutBytes( bundle.App, firstFreeIndex, TransferType.Binary ) == false ) - throw new PebbleException( "Failed to send application binary pebble-app.bin" ); - - if ( bundle.HasResources ) - { - if ( progress != null ) - progress.Report( new ProgressValue( "Transferring app resources to Pebble", 60 ) ); - if ( await PutBytes( bundle.Resources, firstFreeIndex, TransferType.Resources ) == false ) - throw new PebbleException( "Failed to send application resources app_resources.pbpack" ); - } - - if ( progress != null ) - progress.Report( new ProgressValue( "Adding app", 80 ) ); - await AddApp( firstFreeIndex ); - if ( progress != null ) - progress.Report( new ProgressValue( "Done", 100 ) ); - } - - public async Task InstallFirmwareAsync( FirmwareBundle bundle, IProgress progress = null ) - { - if ( bundle == null ) throw new ArgumentNullException( "bundle" ); - - if ( progress != null ) - progress.Report( new ProgressValue( "Starting firmware install", 1 ) ); - if ( ( await SendSystemMessageAsync( SystemMessage.FirmwareStart ) ).Success == false ) - { - return false; - } - - if ( bundle.HasResources ) - { - if ( progress != null ) - progress.Report( new ProgressValue( "Transfering firmware resources", 25 ) ); - if ( await PutBytes( bundle.Resources, 0, TransferType.SysResources ) == false ) - { - return false; - } - } - - if ( progress != null ) - progress.Report( new ProgressValue( "Transfering firmware", 50 ) ); - if ( await PutBytes( bundle.Firmware, 0, TransferType.Firmware ) == false ) - { - return false; - } - - if ( progress != null ) - progress.Report( new ProgressValue( "Completing firmware install", 75 ) ); - bool success = ( await SendSystemMessageAsync( SystemMessage.FirmwareComplete ) ).Success; - - if ( progress != null ) - progress.Report( new ProgressValue( "Done installing firmware", 100 ) ); - - return success; - } + public async Task GetFirmwareVersionAsync() { @@ -349,15 +248,6 @@ public async Task GetTimeAsync() return await SendMessageAsync( Endpoint.Time, new byte[] { 0 } ); } - /// - /// Fetch the contents of the Appbank. - /// - /// - public async Task GetAppbankContentsAsync() - { - return await SendMessageAsync( Endpoint.AppManager, new byte[] { 1 } ); - } - /// /// Remove an app from the Pebble, using an App instance retrieved from the Appbank. /// @@ -372,13 +262,13 @@ public async Task RemoveAppAsync( App app ) return await SendMessageAsync( Endpoint.AppManager, msg ); } - private async Task SendSystemMessageAsync( SystemMessage message ) + public async Task SendSystemMessageAsync( SystemMessage message ) { byte[] data = { 0, (byte)message }; return await SendMessageAsync( Endpoint.SystemMessage, data ); } - private async Task SendMessageAsync( Endpoint endpoint, byte[] payload ) + public async Task SendMessageAsync( Endpoint endpoint, byte[] payload ) where T : class, IResponse, new() { return await Task.Run( () => @@ -412,7 +302,7 @@ private async Task SendMessageAsync( Endpoint endpoint, byte[] payload ) } ); } - private Task SendMessageNoResponseAsync( Endpoint endpoint, byte[] payload ) + public Task SendMessageNoResponseAsync( Endpoint endpoint, byte[] payload ) { return Task.Run( () => { @@ -435,101 +325,75 @@ private Task SendMessageNoResponseAsync( Endpoint endpoint, byte[] payload ) private void RawMessageReceived( object sender, RawMessageReceivedEventArgs e ) { - Debug.WriteLine( "Received {0} message: {1}", (Endpoint)e.Endpoint, BitConverter.ToString( e.Payload ) ); + var endpoint = (Endpoint)e.Endpoint; + IResponse response = _responseManager.HandleResponse( endpoint, e.Payload ); - IResponse response = _responseManager.HandleResponse( (Endpoint)e.Endpoint, e.Payload ); + if (response != null) + { + if (e.Endpoint == (ushort)Endpoint.PhoneVersion) + { + var message = new AppVersionResponse(); + SendMessageNoResponseAsync(Endpoint.PhoneVersion, message.GetBytes()).Wait(); + } - if ( response != null ) - { - //Check for callbacks - List callbacks; - if ( _callbackHandlers.TryGetValue( response.GetType(), out callbacks ) ) - { - foreach ( CallbackContainer callback in callbacks ) - callback.Invoke( response ); - } - } - } + //Check for callbacks + List callbacks; + if (_callbackHandlers.TryGetValue(response.GetType(), out callbacks)) + { + foreach (CallbackContainer callback in callbacks) + callback.Invoke(response); + } + + } - private void OnApplicationMessageReceived( ApplicationMessageResponse response ) - { - SendMessageNoResponseAsync( Endpoint.ApplicationMessage, new byte[] { 0xFF, response.TID } ); } - public override string ToString() + public async Task SendBlobDBMessage(BlobDBCommandPacket command) + { + //TODO: I'm not sure we should assume that the first blobdb response we get is the one that + //corresponds to this request, we probably need to do extra work here to match up the token + var bytes = command.GetBytes(); + + return await SendMessageAsync(Endpoint.BlobDB,bytes ); + } + + public async Task SendApplicationMessage(AppMessagePacket data) { - return string.Format( "Pebble {0} on {1}", PebbleID, Connection ); + //DebugMessage(data.GetBytes()); + return await SendMessageAsync(Endpoint.ApplicationMessage, data.GetBytes()); } - private async Task RemoveAppByUUID( UUID uuid ) + //self._pebble.send_packet(AppRunState(data=AppRunStateStart(uuid=app_uuid))) + public async Task LaunchApp(UUID uuid) { - byte[] data = Util.CombineArrays( new byte[] { 2 }, uuid.Data ); - return await SendMessageAsync( Endpoint.AppManager, data ); + var data = new AppMessagePacket(); + data.ApplicationId = uuid; + data.Command = (byte)Command.Push; + data.TransactionId = 1; + data.Values.Add(new AppMessageUInt8() { Key=1,Value = 1 });//this one is key 0, doesn't actually do anything + + await SendMessageNoResponseAsync(Endpoint.Launcher, data.GetBytes()); } - private async Task PutBytes( byte[] binary, byte index, TransferType transferType ) + private void OnApplicationMessageReceived( AppMessagePacket response ) { - byte[] length = Util.GetBytes( binary.Length ); + SendMessageNoResponseAsync( Endpoint.ApplicationMessage, new byte[] { 0xFF, response.Values!=null ? response.TransactionId :(byte)0} ); + } - //Get token - byte[] header = Util.CombineArrays( new byte[] { 1 }, length, new[] { (byte)transferType, index } ); - - var rawMessageArgs = await SendMessageAsync( Endpoint.PutBytes, header ); - if ( rawMessageArgs.Success == false ) - return false; - - byte[] tokenResult = rawMessageArgs.Response; - byte[] token = tokenResult.Skip( 1 ).ToArray(); - - const int BUFFER_SIZE = 2000; - //Send at most 2000 bytes at a time - for ( int i = 0; i <= binary.Length / BUFFER_SIZE; i++ ) - { - byte[] data = binary.Skip( BUFFER_SIZE * i ).Take( BUFFER_SIZE ).ToArray(); - byte[] dataHeader = Util.CombineArrays( new byte[] { 2 }, token, Util.GetBytes( data.Length ) ); - var result = await SendMessageAsync( Endpoint.PutBytes, Util.CombineArrays( dataHeader, data ) ); - if ( result.Success == false ) - { - await AbortPutBytesAsync( token ); - return false; - } - } - - //Send commit message - uint crc = Crc32.Calculate( binary ); - byte[] crcBytes = Util.GetBytes( crc ); - byte[] commitMessage = Util.CombineArrays( new byte[] { 3 }, token, crcBytes ); - var commitResult = await SendMessageAsync( Endpoint.PutBytes, commitMessage ); - if ( commitResult.Success == false ) + private void DebugMessage(byte[] bytes) + { + StringBuilder payloadDebugger = new StringBuilder(); + foreach (var b in bytes) { - await AbortPutBytesAsync( token ); - return false; + payloadDebugger.Append(string.Format("{0}:", b)); } - - //Send complete message - byte[] completeMessage = Util.CombineArrays( new byte[] { 5 }, token ); - var completeResult = await SendMessageAsync( Endpoint.PutBytes, completeMessage ); - if ( completeResult.Success == false ) - { - await AbortPutBytesAsync( token ); - } - return completeResult.Success; + Console.WriteLine(payloadDebugger.ToString()); } - private async Task AbortPutBytesAsync( byte[] token ) - { - if ( token == null ) throw new ArgumentNullException( "token" ); - - byte[] data = Util.CombineArrays( new byte[] { 4 }, token ); - - return await SendMessageAsync( Endpoint.PutBytes, data ); - } - - private async Task AddApp( byte index ) + public override string ToString() { - byte[] data = Util.CombineArrays( new byte[] { 3 }, Util.GetBytes( (uint)index ) ); - await SendMessageNoResponseAsync( Endpoint.AppManager, data ); + return string.Format( "Pebble {0} on {1}", PebbleID, Connection ); } private class CallbackContainer @@ -557,25 +421,10 @@ public void Invoke( IResponse response ) } } - private enum TransferType : byte - { - Firmware = 1, - Recovery = 2, - SysResources = 3, - Resources = 4, - Binary = 5 - } + public void Reset(ResetCommand command) + { + _PebbleProt.SendMessage((ushort)Endpoint.Reset, new byte[] { (byte)command }); + } - private enum SystemMessage : byte - { - FirmwareAvailible = 0, - FirmwareStart = 1, - FirmwareComplete = 2, - FirmwareFail = 3, - FirmwareUpToDate = 4, - FirmwareOutOfDate = 5, - BluetoothStartDiscoverable = 6, - BluetoothEndDiscoverable = 7 - } } } \ No newline at end of file diff --git a/PebbleSharp.Core/PutBytes/PutBytesClient.cs b/PebbleSharp.Core/PutBytes/PutBytesClient.cs new file mode 100644 index 0000000..940b292 --- /dev/null +++ b/PebbleSharp.Core/PutBytes/PutBytesClient.cs @@ -0,0 +1,93 @@ +using System; +using System.Threading.Tasks; +using System.Linq; +using PebbleSharp.Core.Responses; +namespace PebbleSharp.Core +{ + public class PutBytesClient + { + private Pebble _pebble; + + public PutBytesClient(Pebble pebble) + { + _pebble = pebble; + } + + public async Task PutBytes( byte[] binary, TransferType transferType,byte index=byte.MaxValue,uint appInstallId=uint.MinValue) + { + byte[] length = Util.GetBytes( binary.Length ); + + //Get token + byte[] header; + + if (index != byte.MaxValue) + { + header = Util.CombineArrays(new byte[] { (byte)PutBytesType.Init }, length, new[] { (byte)transferType, index }); + } + else if (appInstallId != uint.MinValue) + { + //System.Console.WriteLine("Installing AppId: " + appInstallId); + byte hackedTransferType = (byte)transferType; + hackedTransferType |= (1 << 7); //just put that bit anywhere... + var appIdBytes = Util.GetBytes(appInstallId); + header = Util.CombineArrays(new byte[] { ((byte)PutBytesType.Init) }, length, new[] { hackedTransferType},appIdBytes); + } + else + { + throw new ArgumentException("Must specifiy either index or appInstallId"); + } + + var rawMessageArgs = await _pebble.SendMessageAsync( Endpoint.PutBytes, header ); + if (rawMessageArgs.Result == PutBytesResult.Nack) + { + return false; + } + + var token = rawMessageArgs.Token; + + const int BUFFER_SIZE = 2000; + //Send at most 2000 bytes at a time + for ( int i = 0; i <= binary.Length / BUFFER_SIZE; i++ ) + { + byte[] data = binary.Skip( BUFFER_SIZE * i ).Take( BUFFER_SIZE ).ToArray(); + byte[] dataHeader = Util.CombineArrays( new byte[] { (byte)PutBytesType.Put }, Util.GetBytes(token), Util.GetBytes( data.Length ) ); + var result = await _pebble.SendMessageAsync( Endpoint.PutBytes, Util.CombineArrays( dataHeader, data ) ); + if (result.Result == PutBytesResult.Nack) + { + await AbortPutBytesAsync(token); + return false; + } + } + + //Send commit message + uint crc = Crc32.Calculate( binary ); + byte[] crcBytes = Util.GetBytes( crc ); + byte[] commitMessage = Util.CombineArrays( new byte[] { (byte)PutBytesType.Commit }, Util.GetBytes(token), crcBytes ); + var commitResult = await _pebble.SendMessageAsync( Endpoint.PutBytes, commitMessage ); + if ( commitResult.Result == PutBytesResult.Nack ) + { + await AbortPutBytesAsync( token ); + return false; + } + + //Send install message + byte[] completeMessage = Util.CombineArrays( new byte[] { (byte)PutBytesType.Install }, Util.GetBytes(token) ); + var completeResult = await _pebble.SendMessageAsync( Endpoint.PutBytes, completeMessage ); + if (completeResult.Result == PutBytesResult.Nack) + { + await AbortPutBytesAsync(token); + } + + return completeResult.Success; + } + + + private async Task AbortPutBytesAsync( uint token ) + { + byte[] data = Util.CombineArrays( new byte[] { (byte)PutBytesType.Abort }, Util.GetBytes(token) ); + + return await _pebble.SendMessageAsync( Endpoint.PutBytes, data ); + } + } +} + diff --git a/PebbleSharp.Core/PutBytes/PutBytesResponsePacket.cs b/PebbleSharp.Core/PutBytes/PutBytesResponsePacket.cs new file mode 100644 index 0000000..3c26a37 --- /dev/null +++ b/PebbleSharp.Core/PutBytes/PutBytesResponsePacket.cs @@ -0,0 +1,23 @@ +using System; +namespace PebbleSharp.Core.Responses +{ + [Endpoint( Endpoint.PutBytes )] + public class PutBytesResponsePacket : ResponseBase + { + public PutBytesResult Result { get; set; } + public uint Token { get; set; } + + protected override void Load( byte[] payload ) + { + Result = (PutBytesResult)payload[0]; + if (Result == PutBytesResult.Ack) + { + Token = Util.GetUInt32(payload, 1); + } + else + { + SetError(payload); + } + } + } +} \ No newline at end of file diff --git a/PebbleSharp.Core/Responses/AppVersionResponse.cs b/PebbleSharp.Core/Responses/AppVersionResponse.cs new file mode 100644 index 0000000..04c542e --- /dev/null +++ b/PebbleSharp.Core/Responses/AppVersionResponse.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +namespace PebbleSharp.Core +{ + public class AppVersionResponse + { + /* + source: https://github.com/pebble/libpebble2/blob/c1a3a052d07b357abf03f86aa4ab01cf47f33ada/libpebble2/protocol/system.py + protocol_version = Uint32() # Unused as of v3.0 + session_caps = Uint32() # Unused as of v3.0 + platform_flags = Uint32() + response_version = Uint8(default=2) + major_version = Uint8() + minor_version = Uint8() + bugfix_version = Uint8() + protocol_caps = Uint64()*/ + + public uint ProtocolVersion { get; set; } + public uint SessionCaps { get; set; } + public uint PlatformFlags { get; set; } + public byte ResponseVersion { get; set; } + public byte MajorVersion { get; set; } + public byte MinorVersion { get; set; } + public byte BugfixVersion { get; set; } + public ulong ProtocolCaps { get; set; } + + /* + source: https://github.com/pebble/libpebble2/blob/d9ecce4a345f31217fb510f2f4e840f7cdda235b/libpebble2/communication/__init__.py + packet = PhoneAppVersion(message=AppVersionResponse( + protocol_version=0xFFFFFFFF, + session_caps=0x80000000, + platform_flags=50, + response_version=2, + major_version=3, + minor_version=0, + bugfix_version=0, + protocol_caps=0xFFFFFFFFFFFFFFFF + )) + */ + + public AppVersionResponse() + { + ProtocolVersion = 0xFFFFFFFF; + SessionCaps = 0x80000000; + PlatformFlags = 50; + ResponseVersion = 2; + MajorVersion = 3; + MinorVersion = 6; + BugfixVersion = 0; + ProtocolCaps = 0xFFFFFFFFFFFFFFFF; + } + + public byte[] GetBytes() + { + var bytes = new List(); + bytes.AddRange(BitConverter.GetBytes(ProtocolVersion)); + bytes.AddRange(BitConverter.GetBytes(SessionCaps)); + bytes.AddRange(BitConverter.GetBytes(PlatformFlags)); + bytes.Add(ResponseVersion); + bytes.Add(MajorVersion); + bytes.Add(MinorVersion); + bytes.Add(BugfixVersion); + bytes.AddRange(BitConverter.GetBytes(ProtocolCaps)); + return bytes.ToArray(); + } + } +} + diff --git a/PebbleSharp.Core/Responses/FirmwareVersionResponse.cs b/PebbleSharp.Core/Responses/FirmwareVersionResponse.cs index 725cfa7..0093e69 100644 --- a/PebbleSharp.Core/Responses/FirmwareVersionResponse.cs +++ b/PebbleSharp.Core/Responses/FirmwareVersionResponse.cs @@ -34,7 +34,7 @@ private static FirmwareVersion ParseVersion( byte[] data ) bool isRecovery = BitConverter.ToBoolean(data, 44); byte hardwarePlatform = data[45]; byte metadataVersion = data[46]; - return new FirmwareVersion(timestamp, version, commit, isRecovery, hardwarePlatform, metadataVersion); + return new FirmwareVersion(timestamp, version, commit, isRecovery, (Hardware)hardwarePlatform, metadataVersion); } } } \ No newline at end of file diff --git a/PebbleSharp.Core/UUID.cs b/PebbleSharp.Core/UUID.cs index 7813a03..6d457f8 100644 --- a/PebbleSharp.Core/UUID.cs +++ b/PebbleSharp.Core/UUID.cs @@ -15,6 +15,11 @@ public UUID( byte[] data ) _data = data; } + public UUID(string s) + { + _data = FromString(s); + } + public byte[] Data { get { return _data; } @@ -40,6 +45,18 @@ public override int GetHashCode() return ( _data != null ? _data.GetHashCode() : 0 ); } + public byte[] FromString(string s) + { + if (s.Length != 36) + { + throw new ArgumentException("Invalid uuid string"); + } + //22a27b9a-0b07-47af-ad87-b2c29305bab6 + s = s.Replace("-", ""); + var result= StringToByteArray(s); + return result; + } + public override string ToString() { return @@ -49,5 +66,13 @@ public override string ToString() _data[10], _data[11], _data[12], _data[13], _data[14], _data[15] ); } + + public static byte[] StringToByteArray(string hex) + { + return Enumerable.Range(0, hex.Length) + .Where(x => x % 2 == 0) + .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) + .ToArray(); + } } } \ No newline at end of file From 8f9b76da2fe9a4183fbc22ea6918c5f7e521e5bc Mon Sep 17 00:00:00 2001 From: Brook Patten Date: Tue, 16 Feb 2016 22:11:51 -0500 Subject: [PATCH 2/8] updated project with new files --- PebbleSharp.Core/PebbleSharp.Core.csproj | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/PebbleSharp.Core/PebbleSharp.Core.csproj b/PebbleSharp.Core/PebbleSharp.Core.csproj index e88aded..cd14a25 100644 --- a/PebbleSharp.Core/PebbleSharp.Core.csproj +++ b/PebbleSharp.Core/PebbleSharp.Core.csproj @@ -76,6 +76,20 @@ + + + + + + + + + + + + + + - + {ae0f69ff-97c2-4e55-a3c9-b73e68668dda} PebbleSharp.Core - + {c6f33ca9-eed4-4553-ae74-cd77e6bf3d75} PebbleSharp.WinRT diff --git a/Demo/PebbleSharp.WPF/ViewModels/PebbleAppsViewModel.cs b/Demo/PebbleSharp.WPF/ViewModels/PebbleAppsViewModel.cs index 953300e..e4ddbbc 100644 --- a/Demo/PebbleSharp.WPF/ViewModels/PebbleAppsViewModel.cs +++ b/Demo/PebbleSharp.WPF/ViewModels/PebbleAppsViewModel.cs @@ -4,6 +4,7 @@ using System.Windows.Input; using GalaSoft.MvvmLight.Command; using Microsoft.Win32; +using PebbleSharp.Core; using PebbleSharp.Core.Bundles; using PebbleSharp.WPF.Messages; using PebbleSharp.Net45; @@ -91,12 +92,13 @@ private async void OnInstallApp() var bundle = new AppBundle(); using (var zip = new Zip()) { - bundle.Load(openDialog.OpenFile(), zip); + zip.Open(openDialog.OpenFile()); + bundle.Load(zip,_pebble.Firmware.HardwarePlatform.GetSoftwarePlatform()); } if ( _pebble.IsAlive == false ) return; - await _pebble.InstallAppAsync( bundle ); + await _pebble.InstallClient.InstallAppAsync( bundle ); await LoadAppsAsync(); } } diff --git a/Demo/PebbleSharp.WPF/ViewModels/PebbleInfoViewModel.cs b/Demo/PebbleSharp.WPF/ViewModels/PebbleInfoViewModel.cs index a9002b6..101f45c 100644 --- a/Demo/PebbleSharp.WPF/ViewModels/PebbleInfoViewModel.cs +++ b/Demo/PebbleSharp.WPF/ViewModels/PebbleInfoViewModel.cs @@ -101,12 +101,13 @@ private async void OnUpdateFirmware() var bundle = new FirmwareBundle(); using (var zip = new Zip()) { - bundle.Load(openDialog.OpenFile(), zip); + zip.Open(openDialog.OpenFile()); + bundle.Load(zip,_pebble.Firmware.HardwarePlatform.GetSoftwarePlatform()); } if (_pebble.IsAlive == false) return; - await _pebble.InstallFirmwareAsync(bundle); + await _pebble.InstallClient.InstallFirmwareAsync(bundle); } } diff --git a/PebbleCmd/AppMessageTest.pbw b/PebbleCmd/AppMessageTest.pbw new file mode 100644 index 0000000000000000000000000000000000000000..0cfda7fefdc8321d5de00811108352e08bdc1b3b GIT binary patch literal 20584 zcmeHP4{RG(8Gmk)Hg(fB{YRs1-CnMXNZQ!FICkQ+Wu%>Pk|yb_HZ2`=YtHsLzU1t) zeCMWVn$n=50RU@Nd8=n$*K3SnESb}ZLFh`$0RUXpN}X#Ln)qFkC`N=2zz;^9y4-uU?-oJ1u03|8%fh%Tt z06Y018Cr%JS>con5n1R+@UqPH5!{9mI2EO2-&QW6UuRP))ot|l@UlWsB2ps7C5Nm5 z;j|@X6M`1Sg1Y7(oVRGD4JG-Q(dr&EXc##fI5tm$#XVxwxpm*%kIgJS~l^ zFU*CTbYL#Ug#}Si1fCf7VTO4GP}00CWzrG7X&5Yx3LNQtgc!;vxv)6Iy~&erka~{2@gtXF^XepDS`Xt zYG$NvgLA%fK3E;v_7Lvr2(8B*F+3z?Fqh_a>xqd82~Lzam&8(%w9Yygqp z2V)g1#jH-b9_y%rf(021i4-gWmsALdqQk@RObP=c7a3>=i$xy5bgq&`EfG!>4KRbY zo92(#t-&TyIL?EmYt~`d4|$k+T!2|uj|byIByKn4KuPofMo$Lgr$t)c8)lmPFURs4Pyu6d=hWjPSzyNbI~EE zNhueNeqb+{(j~}n`GC34qNJzrw(D#qwGmLFl zz?E)Bga_9Zy|pE9UzxQ18*}DIq@*l~yjzs|YME`k0gSinz70GNUW<8fO+%u@McszS zTgzBGhgqBNGcQMO4YN$U7wu*;eY=nR~e zL!ASaIWheC1@qdzaq95%7auQs>GTwoitFFr*$%dWZ`19AOQW`}J5XzX9-G#E=9JA#>V0rcaz%O6~hVfjE^sf%qFeqD-yQi}{I2@>o zqwILjA9PfstSg6VnM*6XS9X4P)d*nK1=lj@iQ&LVdkMeXTpV0_k@o6zR66Iv-o)u*)b%E}Fu zaIC-w1E;h_>?zGzx$sYp61I2Qbu#*I+I`*kJv0*dNT9a2CCCEqn_5e-7LI?_*!X+l zcujKz{eXW^tBv0e=U3pItlnO2Da-|B&udHc<7ur@KdLa-<60??H-eFd98+6uxmWG7#_0O|xt5O5Dyj0x{ zGPt8XrXzGm&`sX7CW>mJrf<#nb{md+>~4|4FY9DF6l;5*U6 zb>|DL0z$3edje1k%MGv>LECgsnpM&pZY)NK)VpAS;Yo?j_J4@(R5%6Sy#$N+Hgcqe zGC&!i3{VCr1C#;E0A+wOKpCJ6PzERil!4jD!1S2Gg|YQ@cf%w}T?*BR8HgMN;}zM+ zt3i^*DAN;7BhI2M&?}$&;^q?&2qJZv4VB=MLJWelW{%D}&FAAhkd5ji@pZ^GL^lsX zj)`fGMZ*55-|O;uoBS?s6WiqCA`!nU=4+^EEZMH2a#M z3!)yP5P=M!p7R@K^yt6BB}hhV+Caz+?lF^r&;{u;u3t)nt#t*!&7u(l94;qH+hp`6G|L z@8_GQk38K4YM1}FoR0m{I;jDgz+ z=*^(P+X~QM*>|JDdVZb+=uNEI7NGa}*e1WPrI9>fZ#|kmtK##HIm=7P`px{xGQ9&n z4vi8CqD%G*%tD=c&6(b+mDhX{QaC1M_B*zUwToY?V`-lsy$mmonDHe$Mb|HWorHyO zX!PC%7Q#%?v0_V#e`1oy*#>d8n}2XptY7@Q5?kN#w5>nwCMgCe{uP4-aDFtk%FcsL z--5*ug + + PreserveNewest + diff --git a/PebbleCmd/Program.cs b/PebbleCmd/Program.cs index c970c02..35ea11a 100644 --- a/PebbleCmd/Program.cs +++ b/PebbleCmd/Program.cs @@ -4,7 +4,11 @@ using System.Threading.Tasks; using PebbleSharp.Core; using PebbleSharp.Core.Responses; +using System.IO; using PebbleSharp.Net45; +using PebbleSharp.Core; +using PebbleSharp.Core.Bundles; +using PebbleSharp.Core.AppMessage; namespace PebbleCmd { @@ -44,7 +48,9 @@ private static async Task ShowPebbleMenu( Pebble pebble ) "Set Current Time", "Get Firmware Info", "Send Ping", - "Media Commands" ); + "Media Commands", + "Install App", + "Send App Message"); while ( true ) { switch ( menu.ShowMenu() ) @@ -72,8 +78,125 @@ private static async Task ShowPebbleMenu( Pebble pebble ) case 5: ShowMediaCommands( pebble ); break; + case 6: + InstallApp(pebble); + break; + case 7: + SendAppMessage(pebble); + break; + } + } + } + + private static string SelectApp() + { + string exePath = System.Reflection.Assembly.GetExecutingAssembly ().CodeBase; + //TODO: there has to be a better way to come up with a canonical path, but this combo seems to work on both windows and 'nix + if (exePath.StartsWith("file:")) + { + exePath = exePath.Substring(5); + } + if (exePath.StartsWith("///")) + { + exePath = exePath.Substring(3); + } + string exeDir = Path.GetDirectoryName (exePath); + var dir = new DirectoryInfo (exeDir); + var files = dir.GetFiles ("*.pbw"); + + if (files.Any()) + { + if (files.Count() == 1) + { + return files.Single().FullName; + } + else + { + var fileMenu = new Menu(files.Select(x => x.Name).ToArray()); + int index = fileMenu.ShowMenu(); + return files[index].FullName; + } + } + else + { + Console.WriteLine("No .pbw files found"); + return null; + } + } + + private static void InstallApp(Pebble pebble) + { + var progress = new Progress(pv => Console.WriteLine(pv.ProgressPercentage + " " + pv.Message)); + + string appPath = SelectApp(); + + if (!string.IsNullOrEmpty(appPath) && File.Exists(appPath)) + { + using (var stream = new FileStream(appPath, FileMode.Open)) + { + using (var zip = new Zip()) + { + zip.Open(stream); + var bundle = new AppBundle(); + stream.Position = 0; + bundle.Load(zip,pebble.Firmware.HardwarePlatform.GetSoftwarePlatform()); + pebble.InstallClient.InstallAppAsync(bundle, progress).Wait(); + + //for firmware v3, launch is done as part of the install + //Console.WriteLine("App Installed, launching..."); + //var uuid=new UUID(bundle.AppInfo.UUID); + //pebble.LaunchApp(uuid); + //Console.WriteLine ("Launched"); + } } } + else + { + Console.WriteLine("No .pbw"); + } + } + + private static void SendAppMessage(Pebble pebble) + { + string uuidAppPath = SelectApp(); + + if (!string.IsNullOrEmpty(uuidAppPath) && File.Exists(uuidAppPath)) + { + using (var stream = new FileStream(uuidAppPath, FileMode.Open)) + { + using (var zip = new Zip()) + { + zip.Open(stream); + var bundle = new AppBundle(); + stream.Position = 0; + bundle.Load(zip,pebble.Firmware.HardwarePlatform.GetSoftwarePlatform()); + + System.Console.Write("Enter Message:"); + var messageText = System.Console.ReadLine(); + + //format a message + var rand = new Random().Next(); + AppMessagePacket message = new AppMessagePacket(); + message.Values.Add(new AppMessageUInt32() { Value = (uint)rand }); + message.Values.Add(new AppMessageString() { Value = messageText }); + message.ApplicationId = bundle.AppMetadata.UUID; + message.TransactionId = 255; + + + //send it + Console.WriteLine("Sending Status "+rand+" to " + bundle.AppMetadata.UUID.ToString()); + pebble.SendApplicationMessage(message).Wait(); + Console.WriteLine("Response received"); + } + } + + + + } + else + { + Console.WriteLine("No .pbw"); + } } private static void ShowMediaCommands( Pebble pebble ) diff --git a/PebbleSharp.Core.Tests/AbstractTests/BaseCrc32Tests.cs b/PebbleSharp.Core.Tests/AbstractTests/BaseCrc32Tests.cs index d21766b..746025d 100644 --- a/PebbleSharp.Core.Tests/AbstractTests/BaseCrc32Tests.cs +++ b/PebbleSharp.Core.Tests/AbstractTests/BaseCrc32Tests.cs @@ -15,7 +15,7 @@ public abstract class BaseCrc32Tests protected void RunGeneratesCorrectChecksumForApp() { var bundle = new AppBundle(); - bundle.Load(ResourceManager.GetAppBundle(), GetZip()); + bundle.Load(GetZip(),SoftwarePlatform.UNKNOWN); Assert.AreEqual(bundle.Manifest.Application.CRC, Crc32.Calculate(bundle.App)); } @@ -23,7 +23,7 @@ protected void RunGeneratesCorrectChecksumForApp() protected void RunGeneratesCorrectChecksumForFirmware() { var bundle = new FirmwareBundle(); - bundle.Load(ResourceManager.GetFirmwareBundle(), GetZip()); + bundle.Load(GetZip(),SoftwarePlatform.UNKNOWN); Assert.AreEqual(bundle.Manifest.Firmware.CRC, Crc32.Calculate(bundle.Firmware)); } diff --git a/PebbleSharp.Core.Tests/AbstractTests/BasePebbleBundleTests.cs b/PebbleSharp.Core.Tests/AbstractTests/BasePebbleBundleTests.cs index 7b91500..6979aad 100644 --- a/PebbleSharp.Core.Tests/AbstractTests/BasePebbleBundleTests.cs +++ b/PebbleSharp.Core.Tests/AbstractTests/BasePebbleBundleTests.cs @@ -18,7 +18,9 @@ protected void RunCanLoadInformationFromAppBundle() { Stream testBundle = ResourceManager.GetAppBundle(); var bundle = new AppBundle(); - bundle.Load( testBundle, GetZip() ); + var zip = GetZip(); + zip.Open(testBundle); + bundle.Load(zip,SoftwarePlatform.APLITE ); var manifest = bundle.Manifest; Assert.IsNotNull( manifest ); @@ -40,7 +42,6 @@ protected void RunCanLoadInformationFromAppBundle() Assert.AreEqual( (uint)0, bundle.AppMetadata.IconResourceID ); Assert.AreEqual( (uint)552, bundle.AppMetadata.Offset ); Assert.AreEqual( (uint)2, bundle.AppMetadata.RelocationListItemCount ); - Assert.AreEqual( (uint)3860, bundle.AppMetadata.RelocationListStart ); Assert.AreEqual( 3, bundle.AppMetadata.SDKMajorVersion ); Assert.AreEqual( 1, bundle.AppMetadata.SDKMinorVersion ); Assert.AreEqual( "3.1", bundle.AppMetadata.SDKVersion ); @@ -57,7 +58,9 @@ protected void RunCanLoadInformationFromFirmwareBundle() Stream testBundle = ResourceManager.GetFirmwareBundle(); var bundle = new FirmwareBundle(); - bundle.Load( testBundle, GetZip() ); + var zip = GetZip(); + zip.Open(testBundle); + bundle.Load( zip,SoftwarePlatform.APLITE ); Assert.IsNotNull( bundle.Firmware ); diff --git a/PebbleSharp.Core.Tests/PebbleTests.cs b/PebbleSharp.Core.Tests/PebbleTests.cs index d310842..d5c3616 100644 --- a/PebbleSharp.Core.Tests/PebbleTests.cs +++ b/PebbleSharp.Core.Tests/PebbleTests.cs @@ -32,7 +32,7 @@ public async Task InstallFirmwareAsyncRequiresBundle() var bluetoothConnection = new Mock(); var pebble = new TestPebble( bluetoothConnection.Object, TEST_PEBBLE_ID ); - await pebble.InstallFirmwareAsync( null ); + await pebble.InstallClient.InstallFirmwareAsync( null ); } [TestMethod] @@ -75,7 +75,7 @@ public async Task InstallFirmwareAsyncTest() var pebble = new TestPebble( bluetoothConnection.Object, TEST_PEBBLE_ID ); - bool success = await pebble.InstallFirmwareAsync( bundle.Object ); + bool success = await pebble.InstallClient.InstallFirmwareAsync( bundle.Object ); Assert.IsTrue( success ); bluetoothConnection.Verify(); } diff --git a/PebbleSharp.Core/AppInfo.cs b/PebbleSharp.Core/AppInfo.cs new file mode 100644 index 0000000..2d78c3f --- /dev/null +++ b/PebbleSharp.Core/AppInfo.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Runtime.Serialization; + +namespace PebbleSharp.Core +{ + [DataContract] + public class AppInfo + { + //does exist in sdk3 + [DataMember(Name = "versionCode", IsRequired = false)] + public int VersionCode { get; private set; } + + [DataMember(Name = "sdkVersion", IsRequired = true)] + public string SdkVersion { get; private set; } + + //[DataMember(Name = "capabilities", IsRequired = true)] + //public string[] Capabilities { get; private set; } + + [DataMember(Name = "shortName", IsRequired = true)] + public string ShortName { get; private set; } + + /// The manifest for the resources contained in this bundle. + //resources + + //appKeys + //[DataMember(Name = "appKeys", IsRequired = true)] + //public Dictionary AppKeys { get; set; } + + [DataMember(Name = "uuid", IsRequired = true)] + public string UUID { get; private set; } + + [DataMember(Name = "versionLabel", IsRequired = true)] + public string VersionLabel { get; private set; } + + [DataMember(Name = "longName", IsRequired = true)] + public string LongName { get; private set; } + + //watchapp + + [DataMember(Name = "projectType", IsRequired = true)] + public string ProjectType { get; private set; } + } +} \ No newline at end of file diff --git a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs index 30c81a3..db8a4b7 100644 --- a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs +++ b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; using PebbleSharp.Core.Responses; -namespace PebbleSharp.Core.NonPortable.AppMessage +namespace PebbleSharp.Core.AppMessage { //modeled after https://github.com/pebble/libpebble2/blob/master/libpebble2/services/appmessage.py [Endpoint(Endpoint.ApplicationMessage)] @@ -465,7 +464,7 @@ public override byte[] ValueBytes { if (value.Length <= ushort.MaxValue) { - Value = System.Text.UTF8Encoding.UTF8.GetString(value); + Value = System.Text.UTF8Encoding.UTF8.GetString(value,0,value.Length); } else { diff --git a/PebbleSharp.Core/Apps/AppFetchRequestPacket.cs b/PebbleSharp.Core/Apps/AppFetchRequestPacket.cs index 8787326..5b60ca1 100644 --- a/PebbleSharp.Core/Apps/AppFetchRequestPacket.cs +++ b/PebbleSharp.Core/Apps/AppFetchRequestPacket.cs @@ -30,8 +30,7 @@ protected override void Load(byte[] payload) } else { - //this will actually flip it because it thinks it is big endian. - AppId = Util.GetInt32(payload, 17); + AppId = BitConverter.ToInt32(payload.Skip(16).Take(4).ToArray().Reverse().ToArray(),0); } } } diff --git a/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs b/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs index 727d897..f1aceca 100644 --- a/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs +++ b/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs @@ -3,7 +3,7 @@ using PebbleSharp.Core.Responses; namespace PebbleSharp.Core { - [Endpoint(Endpoint.AppFetch) + [Endpoint(Endpoint.AppFetch)] public class AppFetchResponsePacket { public byte Command { get; set; } diff --git a/PebbleSharp.Core/Bundles/AppBundle.cs b/PebbleSharp.Core/Bundles/AppBundle.cs index 6455778..865226e 100644 --- a/PebbleSharp.Core/Bundles/AppBundle.cs +++ b/PebbleSharp.Core/Bundles/AppBundle.cs @@ -10,7 +10,7 @@ public class AppBundle : BundleBase public byte[] App { get; private set; } public ApplicationMetadata AppMetadata { get; private set; } - public PebbleSharp.Core.NonPortable.AppInfo AppInfo { get; private set; } + public PebbleSharp.Core.AppInfo AppInfo { get; private set; } protected override void LoadData( IZip zip ) { @@ -31,8 +31,8 @@ protected override void LoadData( IZip zip ) { if (appinfoStream != null) { - var serializer = new DataContractJsonSerializer(typeof(PebbleSharp.Core.NonPortable.AppInfo)); - AppInfo = (PebbleSharp.Core.NonPortable.AppInfo)serializer.ReadObject(appinfoStream); + var serializer = new DataContractJsonSerializer(typeof(PebbleSharp.Core.AppInfo)); + AppInfo = (PebbleSharp.Core.AppInfo)serializer.ReadObject(appinfoStream); } } } diff --git a/PebbleSharp.Core/Bundles/BundleBase.cs b/PebbleSharp.Core/Bundles/BundleBase.cs index 2405369..7c59f78 100644 --- a/PebbleSharp.Core/Bundles/BundleBase.cs +++ b/PebbleSharp.Core/Bundles/BundleBase.cs @@ -10,13 +10,13 @@ public abstract class BundleBase public virtual bool HasResources { get; private set; } public BundleManifest Manifest { get; private set; } public virtual byte[] Resources { get; private set; } - public Platform Platform { get; private set;} + public SoftwarePlatform Platform { get; private set;} protected abstract void LoadData(IZip zip); protected string PlatformSubdirectory() { - var platformSubdirectory = (Platform == Platform.UNKNOWN ? "" : Platform.ToString().ToLower()+"/"); + var platformSubdirectory = (Platform == SoftwarePlatform.UNKNOWN ? "" : Platform.ToString().ToLower()+"/"); return platformSubdirectory; } @@ -34,7 +34,7 @@ private BundleManifest LoadManifest(IZip zip) /// /// The stream to the bundle. /// The zip library implementation. - public void Load(IZip zip, Platform platform) + public void Load(IZip zip, SoftwarePlatform platform) { Platform = platform; Manifest = LoadManifest (zip); diff --git a/PebbleSharp.Core/Enums.cs b/PebbleSharp.Core/Enums.cs index 7577d9b..1ca3159 100644 --- a/PebbleSharp.Core/Enums.cs +++ b/PebbleSharp.Core/Enums.cs @@ -68,7 +68,7 @@ public enum LogLevel Verbose = 250 } - public enum AppMessage : byte + public enum AppMessageCommand : byte { Push = 0x01, Request = 0x02, @@ -187,7 +187,7 @@ public enum Hardware:byte SPALDING_BB2 = 0xFB, } - public enum Platform : byte + public enum SoftwarePlatform : byte { UNKNOWN, APLITE, @@ -197,34 +197,34 @@ public enum Platform : byte public static class HardwareHelpers { - private static Dictionary Platforms; + private static Dictionary Platforms; private static void Initialize() { if (Platforms == null) { - Platforms = new Dictionary(); - Platforms.Add(Hardware.UNKNOWN, Platform.UNKNOWN); - Platforms.Add(Hardware.TINTIN_EV1, Platform.APLITE); - Platforms.Add(Hardware.TINTIN_EV2,Platform.APLITE); - Platforms.Add(Hardware.TINTIN_EV2_3, Platform.APLITE); - Platforms.Add(Hardware.TINTIN_EV2_4,Platform.APLITE); - Platforms.Add(Hardware.TINTIN_V1_5,Platform.APLITE); - Platforms.Add(Hardware.BIANCA,Platform.APLITE); - Platforms.Add(Hardware.SNOWY_EVT2,Platform.BASALT); - Platforms.Add(Hardware.SNOWY_DVT,Platform.BASALT); - Platforms.Add(Hardware.BOBBY_SMILES,Platform.BASALT); - Platforms.Add(Hardware.SPALDING_EVT,Platform.CHALK); - Platforms.Add(Hardware.SPALDING,Platform.CHALK); - Platforms.Add(Hardware.TINTIN_BB,Platform.APLITE); - Platforms.Add(Hardware.TINTIN_BB2,Platform.APLITE); - Platforms.Add(Hardware.SNOWY_BB,Platform.BASALT); - Platforms.Add(Hardware.SNOWY_BB2,Platform.BASALT); - Platforms.Add(Hardware.SPALDING_BB2,Platform.CHALK); + Platforms = new Dictionary(); + Platforms.Add(Hardware.UNKNOWN, SoftwarePlatform.UNKNOWN); + Platforms.Add(Hardware.TINTIN_EV1, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2,SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2_3, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2_4,SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_V1_5,SoftwarePlatform.APLITE); + Platforms.Add(Hardware.BIANCA,SoftwarePlatform.APLITE); + Platforms.Add(Hardware.SNOWY_EVT2,SoftwarePlatform.BASALT); + Platforms.Add(Hardware.SNOWY_DVT,SoftwarePlatform.BASALT); + Platforms.Add(Hardware.BOBBY_SMILES,SoftwarePlatform.BASALT); + Platforms.Add(Hardware.SPALDING_EVT,SoftwarePlatform.CHALK); + Platforms.Add(Hardware.SPALDING,SoftwarePlatform.CHALK); + Platforms.Add(Hardware.TINTIN_BB,SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_BB2,SoftwarePlatform.APLITE); + Platforms.Add(Hardware.SNOWY_BB,SoftwarePlatform.BASALT); + Platforms.Add(Hardware.SNOWY_BB2,SoftwarePlatform.BASALT); + Platforms.Add(Hardware.SPALDING_BB2,SoftwarePlatform.CHALK); } } - public static Platform GetPlatform(this Hardware hardware) + public static SoftwarePlatform GetSoftwarePlatform(this Hardware hardware) { Initialize(); return Platforms[hardware]; diff --git a/PebbleSharp.Core/Pebble.cs b/PebbleSharp.Core/Pebble.cs index 6ce8fca..7475a10 100644 --- a/PebbleSharp.Core/Pebble.cs +++ b/PebbleSharp.Core/Pebble.cs @@ -6,7 +6,7 @@ using System.Text; using System.Threading.Tasks; using PebbleSharp.Core.Bundles; -using PebbleSharp.Core.NonPortable.AppMessage; +using PebbleSharp.Core.AppMessage; using PebbleSharp.Core.Responses; using PebbleSharp.Core.BlobDB; using PebbleSharp.Core.Install; @@ -388,7 +388,6 @@ private void DebugMessage(byte[] bytes) payloadDebugger.Append(string.Format("{0}:", b)); } - Console.WriteLine(payloadDebugger.ToString()); } public override string ToString() diff --git a/PebbleSharp.Core/PebbleSharp.Core.csproj b/PebbleSharp.Core/PebbleSharp.Core.csproj index cd14a25..b343d77 100644 --- a/PebbleSharp.Core/PebbleSharp.Core.csproj +++ b/PebbleSharp.Core/PebbleSharp.Core.csproj @@ -36,6 +36,7 @@ + @@ -60,6 +61,7 @@ + diff --git a/PebbleSharp.Driod/Class1.cs b/PebbleSharp.Driod/Class1.cs deleted file mode 100644 index c0f26c5..0000000 --- a/PebbleSharp.Driod/Class1.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace PebbleSharp.Driod -{ - public class Class1 - { - } -} diff --git a/PebbleSharp.Driod/PebbleSharp.Driod.csproj b/PebbleSharp.Driod/PebbleSharp.Driod.csproj deleted file mode 100644 index 0562a70..0000000 --- a/PebbleSharp.Driod/PebbleSharp.Driod.csproj +++ /dev/null @@ -1,63 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {B5DE313A-A480-4CBD-B68A-3AAA197F26F9} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - Properties - PebbleSharp.Driod - PebbleSharp.Driod - 512 - Resources\Resource.Designer.cs - Off - True - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/PebbleSharp.Driod/Properties/AssemblyInfo.cs b/PebbleSharp.Driod/Properties/AssemblyInfo.cs deleted file mode 100644 index d3c173b..0000000 --- a/PebbleSharp.Driod/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle( "PebbleSharp.Driod" )] -[assembly: AssemblyDescription( "" )] -[assembly: AssemblyConfiguration( "" )] -[assembly: AssemblyCompany( "" )] -[assembly: AssemblyProduct( "PebbleSharp.Driod" )] -[assembly: AssemblyCopyright( "Copyright © 2014" )] -[assembly: AssemblyTrademark( "" )] -[assembly: AssemblyCulture( "" )] -[assembly: ComVisible( false )] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion( "1.0.0.0" )] -[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/PebbleSharp.Driod/Resources/AboutResources.txt b/PebbleSharp.Driod/Resources/AboutResources.txt deleted file mode 100644 index 194ae28..0000000 --- a/PebbleSharp.Driod/Resources/AboutResources.txt +++ /dev/null @@ -1,50 +0,0 @@ -Images, layout descriptions, binary blobs and string dictionaries can be included -in your application as resource files. Various Android APIs are designed to -operate on the resource IDs instead of dealing with images, strings or binary blobs -directly. - -For example, a sample Android app that contains a user interface layout (main.xml), -an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) -would keep its resources in the "Resources" directory of the application: - -Resources/ - drawable-hdpi/ - icon.png - - drawable-ldpi/ - icon.png - - drawable-mdpi/ - icon.png - - layout/ - main.xml - - values/ - strings.xml - -In order to get the build system to recognize Android resources, set the build action to -"AndroidResource". The native Android APIs do not operate directly with filenames, but -instead operate on resource IDs. When you compile an Android application that uses resources, -the build system will package the resources for distribution and generate a class called -"Resource" that contains the tokens for each one of the resources included. For example, -for the above Resources layout, this is what the Resource class would expose: - -public class Resource { - public class drawable { - public const int icon = 0x123; - } - - public class layout { - public const int main = 0x456; - } - - public class strings { - public const int first_string = 0xabc; - public const int second_string = 0xbcd; - } -} - -You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main -to reference the layout/main.xml file, or Resource.strings.first_string to reference the first -string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/PebbleSharp.Driod/Resources/Resource.Designer.cs b/PebbleSharp.Driod/Resources/Resource.Designer.cs deleted file mode 100644 index 66d9ce7..0000000 --- a/PebbleSharp.Driod/Resources/Resource.Designer.cs +++ /dev/null @@ -1,60 +0,0 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.34014 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("PebbleSharp.Driod.Resource", IsApplication=false)] - -namespace PebbleSharp.Driod -{ - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public partial class Attribute - { - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7f020001 - public static int ApplicationName = 2130837505; - - // aapt resource value: 0x7f020000 - public static int Hello = 2130837504; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - } -} -#pragma warning restore 1591 diff --git a/PebbleSharp.Driod/Resources/Values/Strings.xml b/PebbleSharp.Driod/Resources/Values/Strings.xml deleted file mode 100644 index 8fd1763..0000000 --- a/PebbleSharp.Driod/Resources/Values/Strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - Hello World, Click Me! - $projectname$ - diff --git a/PebbleSharp.iOS/Class1.cs b/PebbleSharp.iOS/Class1.cs deleted file mode 100644 index 39e8c7a..0000000 --- a/PebbleSharp.iOS/Class1.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace PebbleSharp.iOS -{ - public class Class1 - { - } -} diff --git a/PebbleSharp.iOS/PebbleSharp.iOS.csproj b/PebbleSharp.iOS/PebbleSharp.iOS.csproj deleted file mode 100644 index 180283c..0000000 --- a/PebbleSharp.iOS/PebbleSharp.iOS.csproj +++ /dev/null @@ -1,49 +0,0 @@ - - - - Debug - iPhoneSimulator - 8.0.30703 - 2.0 - {491B3193-8359-4441-B53A-5D4E8900449D} - {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Library - PebbleSharp.iOS - Resources - PebbleSharp.iOS - - - true - full - false - bin\iPhone\Debug - DEBUG - prompt - 4 - false - true - iPhone Developer - - - none - true - bin\iPhone\Release - prompt - 4 - false - iPhone Developer - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/PebbleSharp.iOS/Properties/AssemblyInfo.cs b/PebbleSharp.iOS/Properties/AssemblyInfo.cs deleted file mode 100644 index 6bc8ddf..0000000 --- a/PebbleSharp.iOS/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle( "PebbleSharp.iOS" )] -[assembly: AssemblyDescription( "" )] -[assembly: AssemblyConfiguration( "" )] -[assembly: AssemblyCompany( "" )] -[assembly: AssemblyProduct( "PebbleSharp.iOS" )] -[assembly: AssemblyCopyright( "Copyright © 2014" )] -[assembly: AssemblyTrademark( "" )] -[assembly: AssemblyCulture( "" )] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible( false )] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid( "ffc977f9-d531-48db-8efb-d6afb2bf31ac" )] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion( "1.0.0.0" )] -[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/PebbleSharp.sln b/PebbleSharp.sln index 85aeaa0..768ae25 100644 --- a/PebbleSharp.sln +++ b/PebbleSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PebbleSharp.Core", "PebbleSharp.Core\PebbleSharp.Core.csproj", "{AE0F69FF-97C2-4E55-A3C9-B73E68668DDA}" EndProject @@ -31,7 +31,7 @@ Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Demo\PebbleSharp.Universal\PebbleSharp.Universal.Shared\PebbleSharp.Universal.Shared.projitems*{5732948c-77a3-415c-8204-f6647dec222a}*SharedItemsImports = 13 Demo\PebbleSharp.Universal\PebbleSharp.Universal.Shared\PebbleSharp.Universal.Shared.projitems*{3ad18d88-6c9a-4f70-98fd-bfa10d8e1148}*SharedItemsImports = 4 - PebbleSharp.Universal\PebbleSharp.Universal.Shared\PebbleSharp.Universal.Shared.projitems*{89e8645d-fd7b-4195-8d1f-7e0717424e4b}*SharedItemsImports = 4 + Demo\PebbleSharp.Universal\PebbleSharp.Universal.Shared\PebbleSharp.Universal.Shared.projitems*{89e8645d-fd7b-4195-8d1f-7e0717424e4b}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU From 239d6a437a6a9a220a3aa76fb275b8e163046672 Mon Sep 17 00:00:00 2001 From: Brook Patten Date: Wed, 17 Feb 2016 21:45:47 -0500 Subject: [PATCH 4/8] finished import changes to get simple app message demo working --- .vs/PebbleSharp/v14/.suo | Bin 0 -> 8192 bytes PebbleCmd/AppMessageTest.pbw | Bin 20584 -> 20573 bytes PebbleCmd/Program.cs | 14 ++- .../AppMessage/AppMessagePacket.cs | 7 +- PebbleSharp.Core/PebbleSharp.Core.csproj | 2 - .../Responses/ApplicationMessageResponse.cs | 115 ------------------ .../Responses/PutBytesResponse.cs | 17 --- 7 files changed, 16 insertions(+), 139 deletions(-) create mode 100644 .vs/PebbleSharp/v14/.suo delete mode 100644 PebbleSharp.Core/Responses/ApplicationMessageResponse.cs delete mode 100644 PebbleSharp.Core/Responses/PutBytesResponse.cs diff --git a/.vs/PebbleSharp/v14/.suo b/.vs/PebbleSharp/v14/.suo new file mode 100644 index 0000000000000000000000000000000000000000..699b6aeadbe3cef65d38de2dc080645497276c80 GIT binary patch literal 8192 zcmeHMU2GIp6h2!(EFeEtixhv5piv*tZg;z_i9l^@(gW zNJ@A>6JitTgYkvL2NFz-f~lqwND4u%KQ)*b1BMb~qBP~_$x^=W&YkXbncW#m(`BJ| za_5|T&z*bjJ%4lNPT!9U&VKrN$vH_YD`c8n8!41~Ed3q}F7rjv*mrGYWP~K*K&MI` zNnoACaV2Gm)XLj{EwY`ebX|&N#;DGxIXu<3_Ok!#mY+O@7}s;JF*pd0ad}JXz|?3+t)=LO`Kq#3+OX@GYyp4PsMMp~fZC+iQYK}3q&;|Y9Q--c z7kWA;{yuxQqrJAj_P**)RW1dY8bY$SNb&TOwebe5}ymmp|b$*(>U8xC4VI_ znf`xx*&A0bY5!kE!$Qf0|33`A6X^dco|zV)Hs#`G`d_a7-(0sD2TZ>=`)6P;^nbSL z|D?0b(S1g1>YlF>;Jc$h>y_^i>f4O_vEzy~y547d>W zA>A$kT&!`^e)3gbciOt0;*VEKp}EY3`42-mZHThTJTgUj5a>U;>CE4ode8n!?hdcY9JOAf50ap#+ zSZ*i(ciz9__n*rDZYKUQ|4h>HCa74g0ksu9Nu1Fn&<>*Ah${wIFPm{<(&DeGl_R{&!Odb5G=$AOX;unSID1b6}o z;c>vv@bTcoN5xzi{J$7$>XE)``u}P*=1lr>5gt>}pYOP8A=lX<&?U-xbs z8vOozVE>8Qqkm?SNl%XVZ>)CP@T(UOMN8fZTy2h@sT))g*3_H{?KRk$0c$fo_sr~IIoO9k!~_`g&MiVqiQjp9Z1 zVT=#|!@LsEBg!#n6GntEz7ga6in|wmVT=oa>I0<|kh3%a4}(J)Y9;6q%(n@x0GNq$@mIUiI>sXP3YG(M#_iXy5prou`e>*{t4lz~fH- z6PbTn^PklItr@N173VJR`1nZsz^|RZ4F6npq=HAGH@w%5-!|(vEOhL|qq^ZA2(7;-r<{-^`yLn1WZyWR7xy|;V1 z-2;s6)Q*${wNccFs7+B@rJ+Jp4XT@90u^3ps-|tyKWIv6L;tCoHZ@Huu2LiRDjN6A z?%v+|FqEdMkgOSNZr{$#`|X?G%)VQ_=iBb~lF~{<%3I%mY|EF<;7v&vLZmK&Ha3+K zq`2(uS7d33iLog*Du{wA@Cws{_b|-fTFfX3IjwfFNgkS*jj2>8uPAIE-@_{^1Ks;s zHI@Jz=p8ao;%tnJjkBV{j}QQEU?-ne1X&^o^+YL?5jb)Z2(W?1Xfs>qi~1Vtf{kpv zj^&yf>!N{Jpt;`H5M`qwGCn3JQ>-+Yw<4OBm$vgEcNBBx{;eSugIBn%wTf}OyC3-bocBX8R?#}EElgHY+X`{5UCZg zEGa$;*46bZbub@Tob~H*BqPOCpb)DvR(OfSEViaZTGRxOyA36rQ3RkjZS}MN!84<+RA*cv?>4 zex-^TsoCIO=w1j`cW?Uw?rH08!EJFoC}%L6<_+tKiAfnw)C4PGS>p4Psl{>{rbgCV z5H)q@tD>D~cwV zN!tzc$LrT(izuAn!P2$sF>IUyOf7a`*3{zt2_cp+A@>Ua&hd)S2m6Q2k$31B202ts z>kXACkBMD8hchX%(uGAerVZDwBg6qiMBk9fnEXB<1ovkYl`yP&aSwDUDLy8|1weFO z(YTliDJn89TvjkvDQzQ~8x8KVWC~ao;6hl=s9yJo+wF$ceZ(|&e}b3r*6n0X(mcxz zx-Cjsj(c<;n9?CAaG&yN4`XyQweE#x$?r-JPqw1fXlx!!CWqn+2@-4$WB-_Uw7KmZ zTp4D>c(`x5n_B|+l||csFlS**mK0g!y`tRbVYcxmFy3zX7Vraj9p=Fk4T>_$c}+#FW?iArx*WMRtTN+Xw42HN-LR3{B$ZF^V?~c+SS{RrzM2gM=kYV}>2E)MIb2zW zkWs;TfHxKg)>|%w_>ZU{b#Lm}*xgN>OIf=MEh-C^AhhmRXVk(SPuw{u7nRu^?aV=^ z;j|p;JgCeoLr3mfu=xiko_+1j!(~4@H4Wut?N4`x!9MV9h

lrP1cD9caOGXhc0; z`DpUB`CtCq)kBYbZtsqYlA|jU<>7gW7b8o~_HIV!jzdXpPHnz6fvOfnPgZ z1$}|9x(gkyZhtcTbL@{W%uslB2g-(W%+}#>W!1s(Z(sz5@v$7~UmdAtPKv+aF|L}i*?)R`Dru>I<7j60SxpzR$PCPx1vX}Mx&S3jUIN0{l z?!hqbMcMZO6$3wi*2(83-P`Vpe6-u!g?kgg<|+MKQ($~{QEpP7@0-+1F{(PDmseD5 zsDR@l{ABoqzSws{cUOGoLsyBfci9y(`eXh6&imU&!k*s2un$mk`l>chg3SFNx-YQ? zTK=lLB29ols(TWjhx0$eIa$2}`ZAac%D$;DHIAqC&l<<`FxMk`DUA4@F|y2BgH5M@ z2XiC)YykEh9MCB^|2EWZP`jX(d@?K7H-VG{WV;?UIwOw&`oHYQxZP%Ez=rw*0d8oGl;GzG}-a zYCga;$3L(2*zzImaa(>$8@A%ZYDzp@pwzkeK0vvmqImT1|kcA zcvUfTYLH+t3&g%1xu6lZBLhT&xDS3X^6^m!0Fk=PhDx%M5Qo65m7mL>7P4spNI~_H z*gE7HxJ`p3G3E37VomiNWYc`j@X-*6*0DU_T-Ow5gUwt+w7EGRCz&f-ZKDcm{$N8x zV<-^v2cZk19-_j?W%QE)AKzC#=L6bU}uT?U&OaH9#N4=nc8C zf#lm_=@?P=g_`}1^`R!BELkbVnUQK@nj#z|**AZ^&qs7QKAPzx_~e8{WGsfEiE)xm zR8=c+=bQpG&mjNi^D(Uq`hvbdV=&TY>C=Gpk3|H1m_;ihN-HZdlVO ztFWSa8Ib`A^X=uLan}VKF1}FoR0m=YnfHFWCpbSt3CQTs=UyLe zat7yFNO`FIZ3O4%b$#;2oea+Z_WFho?|E;{KVNune4_Hgg|CFBo_dG|=V@@B2IpyT z{>}&IEjLPo^Kk38K4YM1}Fo!$-u3H^H$K{Qw8T& z-*@!xSKy!KNhQH~3u~?g=Nm%)W`8Kq6q>8CdDpzk60&}?zo*RTfRE8JB0+S?ers8G z`%KN^S7{YAzYaUZN@v(F)^cjk_AZ^g_W7}k@D_<#->g$~{o?mX4?!7CIFk5uY zX$g5BMe%P-3OHTxPp~)s(!{Ah+Yd@?eb+Z^{TVk&F+lOJ7xDn-$C9h;9N5hCkQ1W# zof_mnck^X*>?C7D{I_I~Y+k;Mj$H}ZKu-7Jw1luxoWipKTn+U$z%A)0&KKno&X2hp zY_Ica>3FQghWOv;cxI~&bSpZFoo0SAqpo)g07Z0^%_pN4!{2w{B{au6$l1RE|CwA4 literal 20584 zcmeHP4{RG(8Gmk)Hg(fB{YRs1-CnMXNZQ!FICkQ+Wu%>Pk|yb_HZ2`=YtHsLzU1t) zeCMWVn$n=50RU@Nd8=n$*K3SnESb}ZLFh`$0RUXpN}X#Ln)qFkC`N=2zz;^9y4-uU?-oJ1u03|8%fh%Tt z06Y018Cr%JS>con5n1R+@UqPH5!{9mI2EO2-&QW6UuRP))ot|l@UlWsB2ps7C5Nm5 z;j|@X6M`1Sg1Y7(oVRGD4JG-Q(dr&EXc##fI5tm$#XVxwxpm*%kIgJS~l^ zFU*CTbYL#Ug#}Si1fCf7VTO4GP}00CWzrG7X&5Yx3LNQtgc!;vxv)6Iy~&erka~{2@gtXF^XepDS`Xt zYG$NvgLA%fK3E;v_7Lvr2(8B*F+3z?Fqh_a>xqd82~Lzam&8(%w9Yygqp z2V)g1#jH-b9_y%rf(021i4-gWmsALdqQk@RObP=c7a3>=i$xy5bgq&`EfG!>4KRbY zo92(#t-&TyIL?EmYt~`d4|$k+T!2|uj|byIByKn4KuPofMo$Lgr$t)c8)lmPFURs4Pyu6d=hWjPSzyNbI~EE zNhueNeqb+{(j~}n`GC34qNJzrw(D#qwGmLFl zz?E)Bga_9Zy|pE9UzxQ18*}DIq@*l~yjzs|YME`k0gSinz70GNUW<8fO+%u@McszS zTgzBGhgqBNGcQMO4YN$U7wu*;eY=nR~e zL!ASaIWheC1@qdzaq95%7auQs>GTwoitFFr*$%dWZ`19AOQW`}J5XzX9-G#E=9JA#>V0rcaz%O6~hVfjE^sf%qFeqD-yQi}{I2@>o zqwILjA9PfstSg6VnM*6XS9X4P)d*nK1=lj@iQ&LVdkMeXTpV0_k@o6zR66Iv-o)u*)b%E}Fu zaIC-w1E;h_>?zGzx$sYp61I2Qbu#*I+I`*kJv0*dNT9a2CCCEqn_5e-7LI?_*!X+l zcujKz{eXW^tBv0e=U3pItlnO2Da-|B&udHc<7ur@KdLa-<60??H-eFd98+6uxmWG7#_0O|xt5O5Dyj0x{ zGPt8XrXzGm&`sX7CW>mJrf<#nb{md+>~4|4FY9DF6l;5*U6 zb>|DL0z$3edje1k%MGv>LECgsnpM&pZY)NK)VpAS;Yo?j_J4@(R5%6Sy#$N+Hgcqe zGC&!i3{VCr1C#;E0A+wOKpCJ6PzERil!4jD!1S2Gg|YQ@cf%w}T?*BR8HgMN;}zM+ zt3i^*DAN;7BhI2M&?}$&;^q?&2qJZv4VB=MLJWelW{%D}&FAAhkd5ji@pZ^GL^lsX zj)`fGMZ*55-|O;uoBS?s6WiqCA`!nU=4+^EEZMH2a#M z3!)yP5P=M!p7R@K^yt6BB}hhV+Caz+?lF^r&;{u;u3t)nt#t*!&7u(l94;qH+hp`6G|L z@8_GQk38K4YM1}FoR0m{I;jDgz+ z=*^(P+X~QM*>|JDdVZb+=uNEI7NGa}*e1WPrI9>fZ#|kmtK##HIm=7P`px{xGQ9&n z4vi8CqD%G*%tD=c&6(b+mDhX{QaC1M_B*zUwToY?V`-lsy$mmonDHe$Mb|HWorHyO zX!PC%7Q#%?v0_V#e`1oy*#>d8n}2XptY7@Q5?kN#w5>nwCMgCe{uP4-aDFtk%FcsL z--5*ug= 0 && result < pebbles.Count ) { var selectedPebble = pebbles[result]; + selectedPebble.RegisterCallback(ReceiveAppMessage); Console.WriteLine( "Connecting to Pebble " + selectedPebble.PebbleID ); await selectedPebble.ConnectAsync(); Console.WriteLine( "Connected" ); @@ -177,15 +178,17 @@ private static void SendAppMessage(Pebble pebble) //format a message var rand = new Random().Next(); AppMessagePacket message = new AppMessagePacket(); - message.Values.Add(new AppMessageUInt32() { Value = (uint)rand }); - message.Values.Add(new AppMessageString() { Value = messageText }); + message.Command = (byte)Command.Push; + message.Values.Add(new AppMessageUInt32() { Key=0,Value = (uint)rand }); + message.Values.Add(new AppMessageString() { Key=1,Value = messageText }); message.ApplicationId = bundle.AppMetadata.UUID; message.TransactionId = 255; //send it Console.WriteLine("Sending Status "+rand+" to " + bundle.AppMetadata.UUID.ToString()); - pebble.SendApplicationMessage(message).Wait(); + var task = pebble.SendApplicationMessage(message); + task.Wait(); Console.WriteLine("Response received"); } } @@ -231,5 +234,10 @@ private static void DisplayResult( T result, Func successData ) Console.WriteLine( result.ErrorDetails.ToString() ); } } + + private static void ReceiveAppMessage(AppMessagePacket response) + { + System.Console.WriteLine("Recieved App Message"); + } } } diff --git a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs index db8a4b7..395c807 100644 --- a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs +++ b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs @@ -446,7 +446,7 @@ public override string Value } set { - if(value!=null && value.EndsWith("\0")) + if (value != null && value.EndsWith("\0")) { base.Value = value.Substring(0, value.Length - 1); } @@ -459,7 +459,10 @@ public override string Value public override byte[] ValueBytes { - get { return System.Text.UTF8Encoding.UTF8.GetBytes(Value+"\0"); } + get + { + return System.Text.UTF8Encoding.UTF8.GetBytes(Value+"\0"); + } set { if (value.Length <= ushort.MaxValue) diff --git a/PebbleSharp.Core/PebbleSharp.Core.csproj b/PebbleSharp.Core/PebbleSharp.Core.csproj index b343d77..47dc1a4 100644 --- a/PebbleSharp.Core/PebbleSharp.Core.csproj +++ b/PebbleSharp.Core/PebbleSharp.Core.csproj @@ -60,7 +60,6 @@ - @@ -69,7 +68,6 @@ - diff --git a/PebbleSharp.Core/Responses/ApplicationMessageResponse.cs b/PebbleSharp.Core/Responses/ApplicationMessageResponse.cs deleted file mode 100644 index 8eb45c4..0000000 --- a/PebbleSharp.Core/Responses/ApplicationMessageResponse.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace PebbleSharp.Core.Responses -{ - [Endpoint( Endpoint.ApplicationMessage )] - [Endpoint( Endpoint.Launcher )] - public class ApplicationMessageResponse : ResponseBase - { - private readonly Dictionary _ParsedData = new Dictionary(); - public Dictionary ParsdData - { - get { return _ParsedData; } - } - - private UUID _UUID; - public UUID TargetUUID - { - get { return _UUID; } - } - - private byte _Tid; - public byte TID - { - get { return _Tid; } - } - - protected override void Load( byte[] payload ) - { - var data = payload; - - byte command; - var index = data.UnpackLE( 0, out command, out _Tid ); - - if ( command == 1 ) - { - byte tupleCount; - index = data.UnpackLE( index, out _UUID, out tupleCount ); - - for ( int i = 0; i < tupleCount; i++ ) - { - uint k; - byte t; - ushort l; - index = data.UnpackLE( index, out k, out t, out l ); - - object v = null; - switch ( t ) - { - case 0: - var byteArray = new byte[l]; - Array.Copy( data, index, byteArray, 0, l ); - v = byteArray; - index += l; - break; - case 1: - break; - case 2: - switch ( l ) - { - case 1: - byte @byte; - index = data.UnpackLE( index, out @byte ); - v = @byte; - break; - case 2: - ushort @ushort; - index = data.UnpackLE( index, out @ushort ); - v = @ushort; - break; - case 4: - uint @uint; - index = data.UnpackLE( index, out @uint ); - v = @uint; - break; - default: - throw new InvalidOperationException(); - } - break; - case 3: - switch ( l ) - { - case 1: - sbyte @sbyte; - index = data.UnpackLE( index, out @sbyte ); - v = @sbyte; - break; - case 2: - short unsignedShort; - index = data.UnpackLE( index, out unsignedShort ); - v = unsignedShort; - break; - case 4: - int unsignedInt; - index = data.UnpackLE( index, out unsignedInt ); - v = unsignedInt; - break; - default: - throw new InvalidOperationException(); - } - break; - default: - throw new InvalidOperationException(); - } - _ParsedData[k.ToString()] = v; - //TODO: App keys - } - } - else - { - - } - } - } -} \ No newline at end of file diff --git a/PebbleSharp.Core/Responses/PutBytesResponse.cs b/PebbleSharp.Core/Responses/PutBytesResponse.cs deleted file mode 100644 index 94d8233..0000000 --- a/PebbleSharp.Core/Responses/PutBytesResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace PebbleSharp.Core.Responses -{ - [Endpoint( Endpoint.PutBytes )] - public class PutBytesResponse : ResponseBase - { - public byte[] Response { get; private set; } - - protected override void Load( byte[] payload ) - { - if (payload.Length == 0 || payload[0] != 1) - { - SetError("PutBytes failed"); - } - Response = payload; - } - } -} \ No newline at end of file From 5826cfd41c3ca350120cfb387d9a8d1eb7e62b8f Mon Sep 17 00:00:00 2001 From: Brook Patten Date: Wed, 17 Feb 2016 21:46:54 -0500 Subject: [PATCH 5/8] removed suo --- .vs/PebbleSharp/v14/.suo | Bin 8192 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .vs/PebbleSharp/v14/.suo diff --git a/.vs/PebbleSharp/v14/.suo b/.vs/PebbleSharp/v14/.suo deleted file mode 100644 index 699b6aeadbe3cef65d38de2dc080645497276c80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeHMU2GIp6h2!(EFeEtixhv5piv*tZg;z_i9l^@(gW zNJ@A>6JitTgYkvL2NFz-f~lqwND4u%KQ)*b1BMb~qBP~_$x^=W&YkXbncW#m(`BJ| za_5|T&z*bjJ%4lNPT!9U&VKrN$vH_YD`c8n8!41~Ed3q}F7rjv*mrGYWP~K*K&MI` zNnoACaV2Gm)XLj{EwY`ebX|&N#;DGxIXu<3_Ok!#mY+O@7}s;JF*pd0ad}JXz|?3+t)=LO`Kq#3+OX@GYyp4PsMMp~fZC+iQYK}3q&;|Y9Q--c z7kWA;{yuxQqrJAj_P**)RW1dY8bY$SNb&TOwebe5}ymmp|b$*(>U8xC4VI_ znf`xx*&A0bY5!kE!$Qf0|33`A6X^dco|zV)Hs#`G`d_a7-(0sD2TZ>=`)6P;^nbSL z|D?0b(S1g1>YlF>;Jc$h>y_^i>f4O_vEzy~y547d>W zA>A$kT&!`^e)3gbciOt0;*VEKp}EY3`42-mZHThTJTgUj5a>U;>CE4ode8n!?hdcY9JOAf50ap#+ zSZ*i(ciz9__n*rDZYKUQ|4h>HCa74g0ksu9Nu1Fn&<>*Ah${wIFPm{<(&DeGl_R{&!Odb5G=$AOX;unSID1b6}o z;c>vv@bTcoN5xzi{J$7$>XE)``u}P*=1lr>5gt>}pYOP8A=lX<&?U-xbs z8vOozVE>8Qqkm?SNl%XVZ>)CP@T(UOMN8fZTy2h@sT))g*3_H{?KRk$0c$fo_sr~IIoO9k!~_`g&MiVqiQjp9Z1 zVT=#|!@LsEBg!#n6GntEz7ga6in|wmVT=oa>I0<|kh3%a4}(J)Y9;6q%(n@x0GNq$@mIUiI>sXP3YG(M#_iXy5prou`e>*{t4lz~fH- z6PbTn^PklItr@N173VJR`1nZsz^|RZ4F6npq=HAGH@w%5-!|(vEOhL Date: Wed, 17 Feb 2016 21:57:38 -0500 Subject: [PATCH 6/8] resolved build issues in wpf --- Demo/PebbleSharp.WPF/PebbleSharp.WPF.csproj | 2 +- .../ViewModels/PebbleAppsViewModel.cs | 2 +- PebbleCmd/Program.cs | 1 - .../PebbleSharp.Core.Tests.csproj | 1 - .../PebbleSharp.Mono.BlueZ5.csproj | 56 +++++++++++++++++ .../Properties/AssemblyInfo.cs | 36 +++++++++++ PebbleSharp.Mono.BlueZ5/Readme.txt | 4 ++ .../bin/Debug/PebbleSharp.Mono.BlueZ5.dll | Bin 0 -> 4096 bytes .../bin/Debug/PebbleSharp.Mono.BlueZ5.pdb | Bin 0 -> 7680 bytes ...gnTimeResolveAssemblyReferencesInput.cache | Bin 0 -> 6851 bytes ...rp.Mono.BlueZ5.csproj.FileListAbsolute.txt | 5 ++ ...lueZ5.csprojResolveAssemblyReference.cache | Bin 0 -> 1922 bytes .../obj/Debug/PebbleSharp.Mono.BlueZ5.dll | Bin 0 -> 4096 bytes .../obj/Debug/PebbleSharp.Mono.BlueZ5.pdb | Bin 0 -> 7680 bytes ...le_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs | 0 ...le_5937a670-0e60-4077-877b-f7221da3dda1.cs | 0 ...le_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs | 0 PebbleSharp.sln | 58 ++++++++++++++++++ 18 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 PebbleSharp.Mono.BlueZ5/PebbleSharp.Mono.BlueZ5.csproj create mode 100644 PebbleSharp.Mono.BlueZ5/Properties/AssemblyInfo.cs create mode 100644 PebbleSharp.Mono.BlueZ5/Readme.txt create mode 100644 PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.dll create mode 100644 PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.pdb create mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache create mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csproj.FileListAbsolute.txt create mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csprojResolveAssemblyReference.cache create mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.dll create mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.pdb create mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs create mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs create mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs diff --git a/Demo/PebbleSharp.WPF/PebbleSharp.WPF.csproj b/Demo/PebbleSharp.WPF/PebbleSharp.WPF.csproj index 0a85a13..fb80187 100644 --- a/Demo/PebbleSharp.WPF/PebbleSharp.WPF.csproj +++ b/Demo/PebbleSharp.WPF/PebbleSharp.WPF.csproj @@ -70,6 +70,7 @@ App.xaml Code + @@ -100,7 +101,6 @@ - Code diff --git a/Demo/PebbleSharp.WPF/ViewModels/PebbleAppsViewModel.cs b/Demo/PebbleSharp.WPF/ViewModels/PebbleAppsViewModel.cs index e4ddbbc..7349898 100644 --- a/Demo/PebbleSharp.WPF/ViewModels/PebbleAppsViewModel.cs +++ b/Demo/PebbleSharp.WPF/ViewModels/PebbleAppsViewModel.cs @@ -59,7 +59,7 @@ private async Task LoadAppsAsync() return; Loading = true; - var appBankContents = await _pebble.GetAppbankContentsAsync(); + var appBankContents = await _pebble.InstallClient.GetAppbankContentsAsync(); _apps.Clear(); if ( appBankContents.Success ) foreach ( var app in appBankContents.AppBank.Apps ) diff --git a/PebbleCmd/Program.cs b/PebbleCmd/Program.cs index 257e2af..4beaa3c 100644 --- a/PebbleCmd/Program.cs +++ b/PebbleCmd/Program.cs @@ -6,7 +6,6 @@ using PebbleSharp.Core.Responses; using System.IO; using PebbleSharp.Net45; -using PebbleSharp.Core; using PebbleSharp.Core.Bundles; using PebbleSharp.Core.AppMessage; diff --git a/PebbleSharp.Core.Tests/PebbleSharp.Core.Tests.csproj b/PebbleSharp.Core.Tests/PebbleSharp.Core.Tests.csproj index e8d1edc..3a8e0e5 100644 --- a/PebbleSharp.Core.Tests/PebbleSharp.Core.Tests.csproj +++ b/PebbleSharp.Core.Tests/PebbleSharp.Core.Tests.csproj @@ -58,7 +58,6 @@ - diff --git a/PebbleSharp.Mono.BlueZ5/PebbleSharp.Mono.BlueZ5.csproj b/PebbleSharp.Mono.BlueZ5/PebbleSharp.Mono.BlueZ5.csproj new file mode 100644 index 0000000..77a17df --- /dev/null +++ b/PebbleSharp.Mono.BlueZ5/PebbleSharp.Mono.BlueZ5.csproj @@ -0,0 +1,56 @@ + + + + + Debug + AnyCPU + {26FE7CCB-5422-4A25-9080-163EB91C3150} + Library + Properties + PebbleSharp.Mono.BlueZ5 + PebbleSharp.Mono.BlueZ5 + v4.5.2 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PebbleSharp.Mono.BlueZ5/Properties/AssemblyInfo.cs b/PebbleSharp.Mono.BlueZ5/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3b393ef --- /dev/null +++ b/PebbleSharp.Mono.BlueZ5/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("PebbleSharp.Mono.BlueZ5")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PebbleSharp.Mono.BlueZ5")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("26fe7ccb-5422-4a25-9080-163eb91c3150")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PebbleSharp.Mono.BlueZ5/Readme.txt b/PebbleSharp.Mono.BlueZ5/Readme.txt new file mode 100644 index 0000000..59d3a03 --- /dev/null +++ b/PebbleSharp.Mono.BlueZ5/Readme.txt @@ -0,0 +1,4 @@ +This Bluetooth wrapper is available here: https://github.com/brookpatten/PebbleSharp.Mono.BlueZ + +It has not been merged to PebbleSharp yet because it depends on changes to Mono and dbus-sharp that have not been released yet. +Once those changes are released and more widely available I will merge it here. \ No newline at end of file diff --git a/PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.dll b/PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.dll new file mode 100644 index 0000000000000000000000000000000000000000..6bd481c8ebc2644eb35fcb7e9d5d5b7b41c4d4e0 GIT binary patch literal 4096 zcmeHKPiz!b82_gKDE|t@3KXjj6jY#{?Dh{(MBH|_g#s#;$i6G|<;68~xH5B*K@NN$=DJgc%jyy zMIeFbHCI>;6ggI!Mq^)1Xc0&d4Mc{LT*q|0<***_vay z(4)n)?pSxckDb+%1^g+GsurqY(JHz4iLO_?MF@xr_dk5 zxP@&8EXTl@0p`l87NXTW_+9Cy%|YxNFytJ#1l*YBM)ZLa^bJ(6Y^-S@SK>bUUfDn~ zxN9JtZYT|ON8)cJo>Z8#OX9;4FG&6f{Q~}8i9eK_cj$_A-zw+gO01?^n6VkSfm(sr z&~D(36qmS9;(m#TC4NETNr`pfN6D1*d5KFBYqXZyNux)o1NbpI4%|)|;JtJnxLe|9 zB~D8Iak>b8T5`@xoTazHnWxWyJ-R`4m%<9k(1AD+UW*X6(TOdL=5ji0tGuL>pD;ah5wG9# zMBcDU8PkudR@kmSBl5aCU-gpF-JI};aP)|aPE-)u44Iag5UyuBcGW5rCLMd$%oSbT zzo$4QysT>$77Gz~!L+2sxUlpENqNhCkGZHx)?Y42I)##J=H~7x$`^FIRJ9o|+P;|= zJSXNcOw05m(sar5MP4f_Y2`HWRjss8+KgpUXeDMXk>%V-%leKR@>8asvmMVjvtGyw zCm6PU;W~x1a4(oyu}mCPMz|GuuoayRaNbZ#rF~IR%mC}zFDz9n>9Lnd%C(hd-Sf}&c4`z zSZ91+w=nwR+3t8R?x}T{Esk>zKcW$Z+O*NZOl2c>lo#VUoQ1tw7s768sR&c1SFrTb zC^l^iTd5U^Dz!Pl@NUH6M97D(<1V_6dt*GEO8@-bo}u4{nvY#+{r2%+U!QN~jFJbZ zPI=hpQ- zt4uA2@cs)V=aP<_vaAu^w1e|Y2>G3`^zJVBkS~elULF>XA`{#iyrLpW1vff2_oWCE zB=5H1?Ql9lbUE^Vx?I}>$pmhkbHIZ%4r&-Ltx=4Jfro-u7kyFp)1QH#z*p$=d3Fro z`-k^^6jB%{@T!vwKPKK30zPe;B}c05lvWu?b#Oh%b@HL-U=+Z|bw9$Xf|z`0nc(N{ z;puCs6Ql6gLk4K_TkgYED$|`i4wn8h6JOvLPWn~5XpdBF}Y@A@b4hcBG$`~ zRO&(f67|TnTI_G>iY;BQ1Jb4+S$nbuyfaFu*x%V9?Ug|d{%7dezp~2zl83hfe*x9! BRssM3 literal 0 HcmV?d00001 diff --git a/PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.pdb b/PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.pdb new file mode 100644 index 0000000000000000000000000000000000000000..e3ac9f3eb3f134718e3d0ea6b62eb95db7ae630e GIT binary patch literal 7680 zcmeaxOfJeV&QB{*aMpL$)>iNhc2h9dGce%gl5z=V00Jg3V&Dfd13-Kr;Db=3m16=>45YXj{{LqI(*OT61IbY^oI?Ox{PT>)|8S0S z6u(W;Gi0nbJQ~Ib6#Z~n%k8I|pw|S+i?ZJvvn62)L2@9B4DJLPqYEKRkFtkI2w=(9cWEO)X~7FD^>f&qz&7Ni9ms$xqH^0QC{sfEZMG zNC7bj2m&!X5OV=BNDc&8Ar!-C%Mlt7gMtEe`>_E=V04a_4cJ0vc!`1HxSZ1v6x|FQ z3=Dmo4DHdNTnhrAJ^&1Z1)v0^WBBd>h^xCx4_Yx+go}0Fn5R*f>E=5V9Rw6BH@Zr$BI zz(w@0^cPh9iS5kUKJ(swxRdh1hZryWGSAHH?D^Rt7LUbZ|GrKVtZLAXucDsh|5nbftoMK$Zs#9p=7^lZB%sl$$hJm?Qq zX#>V)&yAIYZGpcJv9n5Li|Jrl#cL?0w?K({%v-LItjL-aLb2&84fYMJ>neVB^Q5l2 z?$o>dY84MI^`Bjpw!u%OFPK^6l9^ga&eU|<(o|L$mFE67)%$9?b)jRjEkzR|gkH@^ z*5XRb&R{_j9McR#xB!aI2ICCM+=Zd{!sQ1{KDxTQ$W_~>9R$3%u$O3y-G$pym`o`l zUxD>pgHMohy(P>ld#>gV>n*vcsT(CV?2tZn`0<|4#bkTK)}a1iX@5& z6q6t($Ze1@G6kY|QtmOQmlYt=M^v&}Kz3`!)}9jrT9K&(E!wqh)&RO%*{AZ_wgJ>j7_WhF{F<+c#wS?Y@LH$= zsAv`FQkf}X9|qibz>N%(n)@vI1-dj1;{JK7`&WRj^&|x|W^qP3a4hZnMP^VzZ`PO4 zPB@C&WENTz(3>@uvP-$OsmJs zgNa7L-#y>CMS!D`!1YO`4|5-2tVm!2)+?Eh^Z<|!qeLoFO$`(krU%zQANyg{Ui#RW zlV1bUUX)%UNE$%)qXgMv+IXvV+YjC&Kr^F6`^B++pl_mf3xVEo_cugK;7fc+J%-dH z)Jt~Q%-#R?+k@hUqsI0W|DBER9d@g2F!FaIc*kBYJ`5`hSZBPp2ogo!hrRhB-?Mh> zStapF*ECCXV#^Qf~@b9X=`K z)MzjH9>n}f;mR`ZDR}~;GbeAktFds06}?S3Jg4L-^e>!LudY#cPRTPE4~M4z0Gg&w z%Jc{cB33a^Nd~&YWTg%6_LzGL2{~R*$d5gY@VAf{pt>GOc9f_|EuhLNpYQ|BEk7kN XU+@|IYxsuyum7YB-*7>NyFU3Z)wtl| literal 0 HcmV?d00001 diff --git a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csproj.FileListAbsolute.txt b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..e02a7c4 --- /dev/null +++ b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csproj.FileListAbsolute.txt @@ -0,0 +1,5 @@ +C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\bin\Debug\PebbleSharp.Mono.BlueZ5.dll +C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\bin\Debug\PebbleSharp.Mono.BlueZ5.pdb +C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\obj\Debug\PebbleSharp.Mono.BlueZ5.csprojResolveAssemblyReference.cache +C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\obj\Debug\PebbleSharp.Mono.BlueZ5.dll +C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\obj\Debug\PebbleSharp.Mono.BlueZ5.pdb diff --git a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csprojResolveAssemblyReference.cache b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csprojResolveAssemblyReference.cache new file mode 100644 index 0000000000000000000000000000000000000000..afab1d253d958961d574f28f04c0d5c520b31e62 GIT binary patch literal 1922 zcmcIk?M@Rx6kS?c+NEIq{z6?7e`p|+)`Fr5FRR&%)!Y-d9$!gp}IqxKe{3uyeakHns~!sp`CWN#^a!hv5<-h57}n!v&+?%Js=8iAm?ZcwbqWdo zhT_p053SNu<9=#gl^k#lx=EXMRRr5w9f}Bajeh8h?=XoSnd&Z=85qwim%U15x^|J) z`pI68E~t6^pZ$NoUw$=BRr!|@>yrc(gl4|NMYW2s*L^v_lD=r31Z(Ju2_7FUKYKFx z05NDtLkM0Q0|`10W^iimU=8{3P3ips+gjZ@yE|NDOYG@jT;LX1*0c72MN(GDp{PhT z8l+sQR&-w<6UjD2`ZZUp7v0xeZh5ZcqY^K~!Ni10OEJu4XlO(sGN<#yy8S(_M|06Y zxx+%_##5O4N6-hmdSoG`pfP!?GpHRFsZEnY!#|5cpNkYiktV&}G>!F31Wkhc)xSck zs|42wt`poKxQS39^8DG!oR8*_fq78QQ#j-+N{xo(#%`)e!~&uQA0@=`7G^>tf&)k+ zOb!f;h6%Z~pz~mv)mdsq0^?+yiBBSg{^pfRrHRrE1+Mq&M_=`R_I%&3-ojfSGo{5k ztxo%eKS51V!RJZ0T@p3zlJ2-9GQ}m`bxCBJOPX^@WU5QL=aR^DmvrAH(V@7c2QG;Y K%_Rj6Y5Ffe13Ur% literal 0 HcmV?d00001 diff --git a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.dll b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.dll new file mode 100644 index 0000000000000000000000000000000000000000..6bd481c8ebc2644eb35fcb7e9d5d5b7b41c4d4e0 GIT binary patch literal 4096 zcmeHKPiz!b82_gKDE|t@3KXjj6jY#{?Dh{(MBH|_g#s#;$i6G|<;68~xH5B*K@NN$=DJgc%jyy zMIeFbHCI>;6ggI!Mq^)1Xc0&d4Mc{LT*q|0<***_vay z(4)n)?pSxckDb+%1^g+GsurqY(JHz4iLO_?MF@xr_dk5 zxP@&8EXTl@0p`l87NXTW_+9Cy%|YxNFytJ#1l*YBM)ZLa^bJ(6Y^-S@SK>bUUfDn~ zxN9JtZYT|ON8)cJo>Z8#OX9;4FG&6f{Q~}8i9eK_cj$_A-zw+gO01?^n6VkSfm(sr z&~D(36qmS9;(m#TC4NETNr`pfN6D1*d5KFBYqXZyNux)o1NbpI4%|)|;JtJnxLe|9 zB~D8Iak>b8T5`@xoTazHnWxWyJ-R`4m%<9k(1AD+UW*X6(TOdL=5ji0tGuL>pD;ah5wG9# zMBcDU8PkudR@kmSBl5aCU-gpF-JI};aP)|aPE-)u44Iag5UyuBcGW5rCLMd$%oSbT zzo$4QysT>$77Gz~!L+2sxUlpENqNhCkGZHx)?Y42I)##J=H~7x$`^FIRJ9o|+P;|= zJSXNcOw05m(sar5MP4f_Y2`HWRjss8+KgpUXeDMXk>%V-%leKR@>8asvmMVjvtGyw zCm6PU;W~x1a4(oyu}mCPMz|GuuoayRaNbZ#rF~IR%mC}zFDz9n>9Lnd%C(hd-Sf}&c4`z zSZ91+w=nwR+3t8R?x}T{Esk>zKcW$Z+O*NZOl2c>lo#VUoQ1tw7s768sR&c1SFrTb zC^l^iTd5U^Dz!Pl@NUH6M97D(<1V_6dt*GEO8@-bo}u4{nvY#+{r2%+U!QN~jFJbZ zPI=hpQ- zt4uA2@cs)V=aP<_vaAu^w1e|Y2>G3`^zJVBkS~elULF>XA`{#iyrLpW1vff2_oWCE zB=5H1?Ql9lbUE^Vx?I}>$pmhkbHIZ%4r&-Ltx=4Jfro-u7kyFp)1QH#z*p$=d3Fro z`-k^^6jB%{@T!vwKPKK30zPe;B}c05lvWu?b#Oh%b@HL-U=+Z|bw9$Xf|z`0nc(N{ z;puCs6Ql6gLk4K_TkgYED$|`i4wn8h6JOvLPWn~5XpdBF}Y@A@b4hcBG$`~ zRO&(f67|TnTI_G>iY;BQ1Jb4+S$nbuyfaFu*x%V9?Ug|d{%7dezp~2zl83hfe*x9! BRssM3 literal 0 HcmV?d00001 diff --git a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.pdb b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.pdb new file mode 100644 index 0000000000000000000000000000000000000000..e3ac9f3eb3f134718e3d0ea6b62eb95db7ae630e GIT binary patch literal 7680 zcmeaxOfJeV&QB{*aMpL$)>iNhc2h9dGce%gl5z=V00Jg3V&Dfd13-Kr;Db=3m16=>45YXj{{LqI(*OT61IbY^oI?Ox{PT>)|8S0S z6u(W;Gi0nbJQ~Ib6#Z~n%k8I|pw|S+i?ZJvvn62)L2@9B4DJLPqYEKRkFtkI2w=(9cWEO)X~7FD^>f&qz&7Ni9ms$xqH^0QC{sfEZMG zNC7bj2m&!X5OV=BNDc&8Ar!-C%Mlt7gMtEe`>_E=V04a_4cJ0vc!`1HxSZ1v6x|FQ z3=Dmo4DHdNTnhrAJ^&1Z1)v0^WBBd>h^xCx4_ Date: Fri, 19 Feb 2016 19:06:51 -0500 Subject: [PATCH 7/8] resolved issues in pr 35 --- .../AppMessage/AppMessagePacket.cs | 268 ++++++++---------- .../Apps/AppFetchResponsePacket.cs | 5 +- PebbleSharp.Core/BlobDB/BlobDBClient.cs | 11 +- .../BlobDB/BlobDBCommandPacket.cs | 14 +- PebbleSharp.Core/Bundles/AppBundle.cs | 2 +- PebbleSharp.Core/Bundles/FirmwareBundle.cs | 2 +- PebbleSharp.Core/Enums.cs | 50 ++-- PebbleSharp.Core/FirmwareVersion.cs | 20 ++ PebbleSharp.Core/Install/InstallClient.cs | 21 +- PebbleSharp.Core/Pebble.cs | 6 +- PebbleSharp.Core/ResponseManager.cs | 1 + PebbleSharp.Core/UUID.cs | 8 +- .../bin/Debug/PebbleSharp.Mono.BlueZ5.dll | Bin 4096 -> 0 bytes .../bin/Debug/PebbleSharp.Mono.BlueZ5.pdb | Bin 7680 -> 0 bytes ...gnTimeResolveAssemblyReferencesInput.cache | Bin 6851 -> 0 bytes ...rp.Mono.BlueZ5.csproj.FileListAbsolute.txt | 5 - ...lueZ5.csprojResolveAssemblyReference.cache | Bin 1922 -> 0 bytes .../obj/Debug/PebbleSharp.Mono.BlueZ5.dll | Bin 4096 -> 0 bytes .../obj/Debug/PebbleSharp.Mono.BlueZ5.pdb | Bin 7680 -> 0 bytes ...le_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs | 0 ...le_5937a670-0e60-4077-877b-f7221da3dda1.cs | 0 ...le_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs | 0 22 files changed, 197 insertions(+), 216 deletions(-) delete mode 100644 PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.dll delete mode 100644 PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.pdb delete mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache delete mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csproj.FileListAbsolute.txt delete mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csprojResolveAssemblyReference.cache delete mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.dll delete mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.pdb delete mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs delete mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs delete mode 100644 PebbleSharp.Mono.BlueZ5/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs diff --git a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs index 395c807..15e17a2 100644 --- a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs +++ b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs @@ -54,8 +54,6 @@ public AppMessagePacket() Values = new List(); } - - public AppMessagePacket(byte[] bytes) { Load(bytes); @@ -69,87 +67,85 @@ protected override void Load(byte[] bytes) index++; Command = command; - //if (command == Command) - { - TransactionId = bytes[index]; - index++; + + TransactionId = bytes[index]; + index++; - ApplicationId = new UUID(bytes.Skip(index).Take(16).ToArray()); - index += 16; + ApplicationId = new UUID(bytes.Skip(index).Take(16).ToArray()); + index += 16; - int tupleCount = bytes[index]; - index++; + int tupleCount = bytes[index]; + index++; - for (int i = 0; i < tupleCount; i++) - { - uint k; - byte t; - ushort l; + for (int i = 0; i < tupleCount; i++) + { + uint k; + byte t; + ushort l; - k = BitConverter.ToUInt32(bytes, index); - index += 4; + k = BitConverter.ToUInt32(bytes, index); + index += 4; - t = bytes[index]; - index++; + t = bytes[index]; + index++; - l = BitConverter.ToUInt16(bytes, index); - index += 2; + l = BitConverter.ToUInt16(bytes, index); + index += 2; - IAppMessageDictionaryEntry entry = null; - if (t == (byte)PackedType.Bytes) + IAppMessageDictionaryEntry entry = null; + if (t == (byte)PackedType.Bytes) + { + entry = new AppMessageBytes() { Value = bytes.Skip(index).Take(l).ToArray() }; + } + else if (t == (byte)PackedType.Signed) + { + if (l == 1) { - entry = new AppMessageBytes() { Value = bytes.Skip(index).Take(l).ToArray() }; + entry = new AppMessageInt8() { Value = Convert.ToSByte(bytes[index]) }; } - else if (t == (byte)PackedType.Signed) + else if (l == 2) { - if (l == 1) - { - entry = new AppMessageInt8() { Value = Convert.ToSByte(bytes[index]) }; - } - else if (l == 2) - { - entry = new AppMessageInt16() { Value = BitConverter.ToInt16(bytes, index) }; - } - else if (l == 4) - { - entry = new AppMessageInt32() { Value = BitConverter.ToInt32(bytes, index) }; - } - else - { - throw new InvalidOperationException("Invalid signed integer length"); - } + entry = new AppMessageInt16() { Value = BitConverter.ToInt16(bytes, index) }; } - else if (t == (byte)PackedType.String) + else if (l == 4) { - entry = new AppMessageString() { Value = System.Text.Encoding.UTF8.GetString(bytes, index, l) }; + entry = new AppMessageInt32() { Value = BitConverter.ToInt32(bytes, index) }; } - else if (t == (byte)PackedType.Unsigned) + else + { + throw new PebbleException("Invalid signed integer length"); + } + } + else if (t == (byte)PackedType.String) + { + entry = new AppMessageString() { Value = System.Text.Encoding.UTF8.GetString(bytes, index, l) }; + } + else if (t == (byte)PackedType.Unsigned) + { + if (l == 1) { - if (l == 1) - { - entry = new AppMessageUInt8() { Value = bytes[index] }; - } - else if (l == 2) - { - entry = new AppMessageUInt16() { Value = BitConverter.ToUInt16(bytes, index) }; - } - else if (l == 4) - { - entry = new AppMessageUInt32() { Value = BitConverter.ToUInt32(bytes, index) }; - } - else - { - throw new InvalidOperationException("Invalid signed integer length"); - } + entry = new AppMessageUInt8() { Value = bytes[index] }; + } + else if (l == 2) + { + entry = new AppMessageUInt16() { Value = BitConverter.ToUInt16(bytes, index) }; + } + else if (l == 4) + { + entry = new AppMessageUInt32() { Value = BitConverter.ToUInt32(bytes, index) }; } else { - throw new InvalidOperationException("Unknown tuple type"); + throw new PebbleException("Invalid signed integer length"); } - index += l; - entry.Key = k; - Values.Add(entry); } + else + { + throw new PebbleException("Unknown tuple type"); + } + index += l; + entry.Key = k; + Values.Add(entry); } } @@ -203,7 +199,11 @@ public abstract class AppMessageDictionaryEntry : IAppMessageDictionaryEntry { public uint Key { get; set; } public abstract PackedType PackedType { get; } - public abstract ushort Length { get; } + + public virtual ushort Length + { + get { return (ushort) System.Runtime.InteropServices.Marshal.SizeOf(); } + } public virtual T Value { get; set; } public abstract byte[] ValueBytes { get; set; } @@ -220,6 +220,11 @@ public byte[] PackedBytes return bytes.ToArray(); } } + + public new virtual string ToString() + { + return System.Convert.ToString(Value); + } } public class AppMessageUInt8 : AppMessageDictionaryEntry @@ -229,31 +234,25 @@ public override PackedType PackedType get { return PackedType.Unsigned; } } - public override ushort Length - { - get { return sizeof(byte); } - } - public override byte[] ValueBytes { get { return new byte[] {Value}; } set { - if (value.Length == Length) + if (value == null) + { + throw new ArgumentNullException("value"); + } + else if (value.Length == Length) { Value = value[0]; } else { - throw new InvalidOperationException("Incorrect # of bytes"); + throw new PebbleException("Incorrect # of bytes"); } } } - - public override string ToString() - { - return Value.ToString(); - } } public class AppMessageUInt16 : AppMessageDictionaryEntry @@ -263,31 +262,25 @@ public override PackedType PackedType get { return PackedType.Unsigned; } } - public override ushort Length - { - get { return sizeof(UInt16); } - } - public override byte[] ValueBytes { get { return BitConverter.GetBytes(Value); } set { - if (value.Length == Length) + if (value == null) + { + throw new ArgumentNullException("value"); + } + else if (value.Length == Length) { Value = BitConverter.ToUInt16(value,0); } else { - throw new InvalidOperationException("Incorrect # of bytes"); + throw new PebbleException("Incorrect # of bytes"); } } } - - public override string ToString() - { - return Value.ToString(); - } } public class AppMessageUInt32 : AppMessageDictionaryEntry @@ -297,31 +290,25 @@ public override PackedType PackedType get { return PackedType.Unsigned; } } - public override ushort Length - { - get { return sizeof(UInt32); } - } - public override byte[] ValueBytes { get { return BitConverter.GetBytes(Value); } set { - if (value.Length == Length) + if (value == null) + { + throw new ArgumentNullException("value"); + } + else if (value.Length == Length) { Value = BitConverter.ToUInt32(value, 0); } else { - throw new InvalidOperationException("Incorrect # of bytes"); + throw new PebbleException("Incorrect # of bytes"); } } } - - public override string ToString() - { - return Value.ToString(); - } } public class AppMessageInt8 : AppMessageDictionaryEntry @@ -331,31 +318,25 @@ public override PackedType PackedType get { return PackedType.Signed; } } - public override ushort Length - { - get { return sizeof(sbyte); } - } - public override byte[] ValueBytes { get { return new byte[] { Convert.ToByte(Value) }; } set { - if (value.Length == Length) + if (value == null) + { + throw new ArgumentNullException("value"); + } + else if (value.Length == Length) { Value = Convert.ToSByte(value); } else { - throw new InvalidOperationException("Incorrect # of bytes"); + throw new PebbleException("Incorrect # of bytes"); } } } - - public override string ToString() - { - return Value.ToString(); - } } public class AppMessageInt16 : AppMessageDictionaryEntry @@ -365,31 +346,25 @@ public override PackedType PackedType get { return PackedType.Signed; } } - public override ushort Length - { - get { return sizeof(Int16); } - } - public override byte[] ValueBytes { get { return BitConverter.GetBytes(Value); } set { - if (value.Length == Length) + if (value == null) + { + throw new ArgumentNullException("value"); + } + else if (value.Length == Length) { Value = BitConverter.ToInt16(value, 0); } else { - throw new InvalidOperationException("Incorrect # of bytes"); + throw new PebbleException("Incorrect # of bytes"); } } } - - public override string ToString() - { - return Value.ToString(); - } } public class AppMessageInt32 : AppMessageDictionaryEntry @@ -399,31 +374,25 @@ public override PackedType PackedType get { return PackedType.Signed; } } - public override ushort Length - { - get { return sizeof(Int32); } - } - public override byte[] ValueBytes { get { return BitConverter.GetBytes(Value); } set { - if (value.Length == Length) + if (value == null) + { + throw new ArgumentNullException("value"); + } + else if (value.Length == Length) { Value = BitConverter.ToInt32(value, 0); } else { - throw new InvalidOperationException("Incorrect # of bytes"); + throw new PebbleException("Incorrect # of bytes"); } } } - - public override string ToString() - { - return Value.ToString(); - } } public class AppMessageString : AppMessageDictionaryEntry @@ -465,7 +434,11 @@ public override byte[] ValueBytes } set { - if (value.Length <= ushort.MaxValue) + if (value == null) + { + throw new ArgumentNullException("value"); + } + else if (value.Length <= ushort.MaxValue) { Value = System.Text.UTF8Encoding.UTF8.GetString(value,0,value.Length); } @@ -475,11 +448,6 @@ public override byte[] ValueBytes } } } - - public override string ToString() - { - return Value.ToString(); - } } public class AppMessageBytes : AppMessageDictionaryEntry @@ -499,7 +467,11 @@ public override byte[] ValueBytes get { return Value; } set { - if (value.Length <= ushort.MaxValue) + if (value == null) + { + throw new ArgumentNullException("value"); + } + else if (value.Length <= ushort.MaxValue) { Value = value; } @@ -512,13 +484,7 @@ public override byte[] ValueBytes public override string ToString() { - var s = new StringBuilder(); - foreach(var b in Value) - { - s.Append(b.ToString()); - s.Append(","); - } - return s.ToString(); + return BitConverter.ToString(Value).Replace("-", "").ToLower(); } } } diff --git a/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs b/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs index f1aceca..7ba66c1 100644 --- a/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs +++ b/PebbleSharp.Core/Apps/AppFetchResponsePacket.cs @@ -16,10 +16,7 @@ public AppFetchResponsePacket() public byte[] GetBytes() { - var bytes = new List(); - bytes.Add(Command); - bytes.Add((byte)Response); - return bytes.ToArray(); + return new byte[]{Command,(byte)Response}; } } } diff --git a/PebbleSharp.Core/BlobDB/BlobDBClient.cs b/PebbleSharp.Core/BlobDB/BlobDBClient.cs index 7228f4e..c590f94 100644 --- a/PebbleSharp.Core/BlobDB/BlobDBClient.cs +++ b/PebbleSharp.Core/BlobDB/BlobDBClient.cs @@ -6,13 +6,18 @@ namespace PebbleSharp.Core.BlobDB public class BlobDBClient { private Pebble _pebble; - private Random _random; + private static Random _random; - public BlobDBClient(Pebble pebble) + static BlobDBClient() + { + _random = new Random(); + } + + internal BlobDBClient(Pebble pebble) { _pebble = pebble; - _random = new Random(); } + public async Task Insert(BlobDatabase database, byte[] key, byte[] value) { var insertCommand = new BlobDBCommandPacket() diff --git a/PebbleSharp.Core/BlobDB/BlobDBCommandPacket.cs b/PebbleSharp.Core/BlobDB/BlobDBCommandPacket.cs index 8e66259..efb0b0d 100644 --- a/PebbleSharp.Core/BlobDB/BlobDBCommandPacket.cs +++ b/PebbleSharp.Core/BlobDB/BlobDBCommandPacket.cs @@ -37,15 +37,15 @@ public byte[] GetBytes() var bytes = new List(); bytes.Add((byte)Command); bytes.AddRange(BitConverter.GetBytes(Token)); - bytes.Add((byte)this.Database); - if (this.Command == BlobCommand.Insert || this.Command == BlobCommand.Delete) + bytes.Add((byte)Database); + if (Command == BlobCommand.Insert || Command == BlobCommand.Delete) { - bytes.Add(this.KeyLength); - bytes.AddRange(this.Key); - if (this.Command == BlobCommand.Insert) + bytes.Add(KeyLength); + bytes.AddRange(Key); + if (Command == BlobCommand.Insert) { - bytes.AddRange(BitConverter.GetBytes(this.ValueLength)); - bytes.AddRange(this.Value); + bytes.AddRange(BitConverter.GetBytes(ValueLength)); + bytes.AddRange(Value); } } return bytes.ToArray(); diff --git a/PebbleSharp.Core/Bundles/AppBundle.cs b/PebbleSharp.Core/Bundles/AppBundle.cs index 865226e..2358849 100644 --- a/PebbleSharp.Core/Bundles/AppBundle.cs +++ b/PebbleSharp.Core/Bundles/AppBundle.cs @@ -15,7 +15,7 @@ public class AppBundle : BundleBase protected override void LoadData( IZip zip ) { if ( string.IsNullOrWhiteSpace( Manifest.Application.Filename ) ) - throw new InvalidOperationException( "Bundle does not contain pebble app" ); + throw new PebbleException("Bundle does not contain pebble app"); using ( Stream binStream = zip.OpenEntryStream( this.PlatformSubdirectory()+Manifest.Application.Filename ) ) { diff --git a/PebbleSharp.Core/Bundles/FirmwareBundle.cs b/PebbleSharp.Core/Bundles/FirmwareBundle.cs index 6380116..167c287 100644 --- a/PebbleSharp.Core/Bundles/FirmwareBundle.cs +++ b/PebbleSharp.Core/Bundles/FirmwareBundle.cs @@ -10,7 +10,7 @@ public class FirmwareBundle : BundleBase protected override void LoadData(IZip zip) { if (string.IsNullOrWhiteSpace(Manifest.Firmware.Filename)) - throw new InvalidOperationException("Bundle does not contain firmware"); + throw new PebbleException("Bundle does not contain firmware"); using (Stream binStream = zip.OpenEntryStream(Manifest.Firmware.Filename)) { diff --git a/PebbleSharp.Core/Enums.cs b/PebbleSharp.Core/Enums.cs index 1ca3159..fbd3e71 100644 --- a/PebbleSharp.Core/Enums.cs +++ b/PebbleSharp.Core/Enums.cs @@ -187,9 +187,11 @@ public enum Hardware:byte SPALDING_BB2 = 0xFB, } + //note that the names of these values are important, .ToString() + //is used to locate the correct platform specific subdirectory in appbundles public enum SoftwarePlatform : byte { - UNKNOWN, + UNKNOWN, APLITE, BASALT, CHALK @@ -199,34 +201,30 @@ public static class HardwareHelpers { private static Dictionary Platforms; - private static void Initialize() - { - if (Platforms == null) - { - Platforms = new Dictionary(); - Platforms.Add(Hardware.UNKNOWN, SoftwarePlatform.UNKNOWN); - Platforms.Add(Hardware.TINTIN_EV1, SoftwarePlatform.APLITE); - Platforms.Add(Hardware.TINTIN_EV2,SoftwarePlatform.APLITE); - Platforms.Add(Hardware.TINTIN_EV2_3, SoftwarePlatform.APLITE); - Platforms.Add(Hardware.TINTIN_EV2_4,SoftwarePlatform.APLITE); - Platforms.Add(Hardware.TINTIN_V1_5,SoftwarePlatform.APLITE); - Platforms.Add(Hardware.BIANCA,SoftwarePlatform.APLITE); - Platforms.Add(Hardware.SNOWY_EVT2,SoftwarePlatform.BASALT); - Platforms.Add(Hardware.SNOWY_DVT,SoftwarePlatform.BASALT); - Platforms.Add(Hardware.BOBBY_SMILES,SoftwarePlatform.BASALT); - Platforms.Add(Hardware.SPALDING_EVT,SoftwarePlatform.CHALK); - Platforms.Add(Hardware.SPALDING,SoftwarePlatform.CHALK); - Platforms.Add(Hardware.TINTIN_BB,SoftwarePlatform.APLITE); - Platforms.Add(Hardware.TINTIN_BB2,SoftwarePlatform.APLITE); - Platforms.Add(Hardware.SNOWY_BB,SoftwarePlatform.BASALT); - Platforms.Add(Hardware.SNOWY_BB2,SoftwarePlatform.BASALT); - Platforms.Add(Hardware.SPALDING_BB2,SoftwarePlatform.CHALK); - } - } + static HardwareHelpers() + { + Platforms = new Dictionary(); + Platforms.Add(Hardware.UNKNOWN, SoftwarePlatform.UNKNOWN); + Platforms.Add(Hardware.TINTIN_EV1, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2_3, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_EV2_4, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_V1_5, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.BIANCA, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.SNOWY_EVT2, SoftwarePlatform.BASALT); + Platforms.Add(Hardware.SNOWY_DVT, SoftwarePlatform.BASALT); + Platforms.Add(Hardware.BOBBY_SMILES, SoftwarePlatform.BASALT); + Platforms.Add(Hardware.SPALDING_EVT, SoftwarePlatform.CHALK); + Platforms.Add(Hardware.SPALDING, SoftwarePlatform.CHALK); + Platforms.Add(Hardware.TINTIN_BB, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.TINTIN_BB2, SoftwarePlatform.APLITE); + Platforms.Add(Hardware.SNOWY_BB, SoftwarePlatform.BASALT); + Platforms.Add(Hardware.SNOWY_BB2, SoftwarePlatform.BASALT); + Platforms.Add(Hardware.SPALDING_BB2, SoftwarePlatform.CHALK); + } public static SoftwarePlatform GetSoftwarePlatform(this Hardware hardware) { - Initialize(); return Platforms[hardware]; } } diff --git a/PebbleSharp.Core/FirmwareVersion.cs b/PebbleSharp.Core/FirmwareVersion.cs index 00588b3..1920580 100644 --- a/PebbleSharp.Core/FirmwareVersion.cs +++ b/PebbleSharp.Core/FirmwareVersion.cs @@ -1,4 +1,6 @@ using System; +using System.Collections; +using System.Collections.Generic; namespace PebbleSharp.Core { @@ -22,6 +24,24 @@ public FirmwareVersion( DateTime timestamp, string version, string commit, public Hardware HardwarePlatform { get; private set; } public byte MetadataVersion { get; private set; } + public IList ParseVersionComponents() + { + var components = new List(); + if (!string.IsNullOrWhiteSpace(Version)) + { + string cleanedVersion = Version.Replace("v", ""); + foreach (var component in cleanedVersion.Split(new char[] {'.', '-'}, StringSplitOptions.RemoveEmptyEntries)) + { + int v; + if (int.TryParse(component, out v)) + { + components.Add(v); + } + } + } + return components; + } + public override string ToString() { const string format = "Version {0}, commit {1} ({2})\n" diff --git a/PebbleSharp.Core/Install/InstallClient.cs b/PebbleSharp.Core/Install/InstallClient.cs index 5d7c0ea..44397ee 100644 --- a/PebbleSharp.Core/Install/InstallClient.cs +++ b/PebbleSharp.Core/Install/InstallClient.cs @@ -11,19 +11,15 @@ namespace PebbleSharp.Core.Install public class InstallClient { private Pebble _pebble; - public InstallClient(Pebble pebble) + + internal InstallClient(Pebble pebble) { _pebble = pebble; } + public async Task InstallAppAsync( AppBundle bundle, IProgress progress = null ) { - - string version = _pebble.Firmware.Version; - version = version.Replace("v", ""); - var components = version.Split(new char[] { '.','-' }, StringSplitOptions.RemoveEmptyEntries); - - int i; - IList versionComponents = components.Where(x=>int.TryParse(x,out i)).Select(x => int.Parse(x)).ToList(); + IList versionComponents = _pebble.Firmware.ParseVersionComponents(); if (versionComponents[0] < 3) { await InstallAppLegacyV2 (bundle, progress); @@ -34,7 +30,6 @@ public async Task InstallAppAsync( AppBundle bundle, IProgress pr } } - private async Task InstallAppAsyncV3(AppBundle bundle,IProgress progress) { //https://github.com/pebble/libpebble2/blob/master/libpebble2/services/install.py @@ -57,7 +52,7 @@ private async Task InstallAppAsyncV3(AppBundle bundle,IProgress p if (!runStateResult.Success) { - throw new InvalidOperationException("Pebble replied invalid run state"); + throw new PebbleException("Pebble replied invalid run state"); } if (!meta.UUID.Equals(runStateResult.UUID)) @@ -65,13 +60,13 @@ private async Task InstallAppAsyncV3(AppBundle bundle,IProgress p var response = new AppFetchResponsePacket(); response.Response = AppFetchStatus.InvalidUUID; await _pebble.SendMessageNoResponseAsync(Endpoint.AppFetch, response.GetBytes()); - throw new InvalidOperationException("The pebble requested the wrong UUID"); + throw new PebbleException("The pebble requested the wrong UUID"); } var putBytesResponse = await _pebble.PutBytesClient.PutBytes(bundle.App, TransferType.Binary, appInstallId:(uint)runStateResult.AppId); if (!putBytesResponse) { - throw new InvalidOperationException("Putbytes failed"); + throw new PebbleException("Putbytes failed"); } if (bundle.HasResources) @@ -79,7 +74,7 @@ private async Task InstallAppAsyncV3(AppBundle bundle,IProgress p putBytesResponse = await _pebble.PutBytesClient.PutBytes(bundle.Resources, TransferType.Resources, appInstallId:(uint)runStateResult.AppId); if (!putBytesResponse) { - throw new InvalidOperationException("Putbytes failed"); + throw new PebbleException("Putbytes failed"); } } diff --git a/PebbleSharp.Core/Pebble.cs b/PebbleSharp.Core/Pebble.cs index 7475a10..5bf157e 100644 --- a/PebbleSharp.Core/Pebble.cs +++ b/PebbleSharp.Core/Pebble.cs @@ -42,9 +42,9 @@ protected Pebble( IBluetoothConnection connection, string pebbleId ) { ResponseTimeout = TimeSpan.FromSeconds( 5 ); PebbleID = pebbleId; - this.BlobDBClient = new BlobDBClient(this); - this.PutBytesClient = new PutBytesClient(this); - this.InstallClient = new InstallClient(this); + BlobDBClient = new BlobDBClient(this); + PutBytesClient = new PutBytesClient(this); + InstallClient = new InstallClient(this); _callbackHandlers = new Dictionary>(); diff --git a/PebbleSharp.Core/ResponseManager.cs b/PebbleSharp.Core/ResponseManager.cs index 28695da..dc9e690 100644 --- a/PebbleSharp.Core/ResponseManager.cs +++ b/PebbleSharp.Core/ResponseManager.cs @@ -40,6 +40,7 @@ static ResponseManager() responseMatches.Add( new ResponseMatch( func, endpointAttribute.GetPredicate() ) ); } } + } public IResponseTransaction GetTransaction() where T : class, IResponse, new() diff --git a/PebbleSharp.Core/UUID.cs b/PebbleSharp.Core/UUID.cs index 6d457f8..5f19268 100644 --- a/PebbleSharp.Core/UUID.cs +++ b/PebbleSharp.Core/UUID.cs @@ -45,9 +45,13 @@ public override int GetHashCode() return ( _data != null ? _data.GetHashCode() : 0 ); } - public byte[] FromString(string s) + public static byte[] FromString(string s) { - if (s.Length != 36) + if (string.IsNullOrEmpty(s)) + { + throw new ArgumentNullException("s"); + } + else if (s.Length != 36) { throw new ArgumentException("Invalid uuid string"); } diff --git a/PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.dll b/PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.dll deleted file mode 100644 index 6bd481c8ebc2644eb35fcb7e9d5d5b7b41c4d4e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmeHKPiz!b82_gKDE|t@3KXjj6jY#{?Dh{(MBH|_g#s#;$i6G|<;68~xH5B*K@NN$=DJgc%jyy zMIeFbHCI>;6ggI!Mq^)1Xc0&d4Mc{LT*q|0<***_vay z(4)n)?pSxckDb+%1^g+GsurqY(JHz4iLO_?MF@xr_dk5 zxP@&8EXTl@0p`l87NXTW_+9Cy%|YxNFytJ#1l*YBM)ZLa^bJ(6Y^-S@SK>bUUfDn~ zxN9JtZYT|ON8)cJo>Z8#OX9;4FG&6f{Q~}8i9eK_cj$_A-zw+gO01?^n6VkSfm(sr z&~D(36qmS9;(m#TC4NETNr`pfN6D1*d5KFBYqXZyNux)o1NbpI4%|)|;JtJnxLe|9 zB~D8Iak>b8T5`@xoTazHnWxWyJ-R`4m%<9k(1AD+UW*X6(TOdL=5ji0tGuL>pD;ah5wG9# zMBcDU8PkudR@kmSBl5aCU-gpF-JI};aP)|aPE-)u44Iag5UyuBcGW5rCLMd$%oSbT zzo$4QysT>$77Gz~!L+2sxUlpENqNhCkGZHx)?Y42I)##J=H~7x$`^FIRJ9o|+P;|= zJSXNcOw05m(sar5MP4f_Y2`HWRjss8+KgpUXeDMXk>%V-%leKR@>8asvmMVjvtGyw zCm6PU;W~x1a4(oyu}mCPMz|GuuoayRaNbZ#rF~IR%mC}zFDz9n>9Lnd%C(hd-Sf}&c4`z zSZ91+w=nwR+3t8R?x}T{Esk>zKcW$Z+O*NZOl2c>lo#VUoQ1tw7s768sR&c1SFrTb zC^l^iTd5U^Dz!Pl@NUH6M97D(<1V_6dt*GEO8@-bo}u4{nvY#+{r2%+U!QN~jFJbZ zPI=hpQ- zt4uA2@cs)V=aP<_vaAu^w1e|Y2>G3`^zJVBkS~elULF>XA`{#iyrLpW1vff2_oWCE zB=5H1?Ql9lbUE^Vx?I}>$pmhkbHIZ%4r&-Ltx=4Jfro-u7kyFp)1QH#z*p$=d3Fro z`-k^^6jB%{@T!vwKPKK30zPe;B}c05lvWu?b#Oh%b@HL-U=+Z|bw9$Xf|z`0nc(N{ z;puCs6Ql6gLk4K_TkgYED$|`i4wn8h6JOvLPWn~5XpdBF}Y@A@b4hcBG$`~ zRO&(f67|TnTI_G>iY;BQ1Jb4+S$nbuyfaFu*x%V9?Ug|d{%7dezp~2zl83hfe*x9! BRssM3 diff --git a/PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.pdb b/PebbleSharp.Mono.BlueZ5/bin/Debug/PebbleSharp.Mono.BlueZ5.pdb deleted file mode 100644 index e3ac9f3eb3f134718e3d0ea6b62eb95db7ae630e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7680 zcmeaxOfJeV&QB{*aMpL$)>iNhc2h9dGce%gl5z=V00Jg3V&Dfd13-Kr;Db=3m16=>45YXj{{LqI(*OT61IbY^oI?Ox{PT>)|8S0S z6u(W;Gi0nbJQ~Ib6#Z~n%k8I|pw|S+i?ZJvvn62)L2@9B4DJLPqYEKRkFtkI2w=(9cWEO)X~7FD^>f&qz&7Ni9ms$xqH^0QC{sfEZMG zNC7bj2m&!X5OV=BNDc&8Ar!-C%Mlt7gMtEe`>_E=V04a_4cJ0vc!`1HxSZ1v6x|FQ z3=Dmo4DHdNTnhrAJ^&1Z1)v0^WBBd>h^xCx4_Yx+go}0Fn5R*f>E=5V9Rw6BH@Zr$BI zz(w@0^cPh9iS5kUKJ(swxRdh1hZryWGSAHH?D^Rt7LUbZ|GrKVtZLAXucDsh|5nbftoMK$Zs#9p=7^lZB%sl$$hJm?Qq zX#>V)&yAIYZGpcJv9n5Li|Jrl#cL?0w?K({%v-LItjL-aLb2&84fYMJ>neVB^Q5l2 z?$o>dY84MI^`Bjpw!u%OFPK^6l9^ga&eU|<(o|L$mFE67)%$9?b)jRjEkzR|gkH@^ z*5XRb&R{_j9McR#xB!aI2ICCM+=Zd{!sQ1{KDxTQ$W_~>9R$3%u$O3y-G$pym`o`l zUxD>pgHMohy(P>ld#>gV>n*vcsT(CV?2tZn`0<|4#bkTK)}a1iX@5& z6q6t($Ze1@G6kY|QtmOQmlYt=M^v&}Kz3`!)}9jrT9K&(E!wqh)&RO%*{AZ_wgJ>j7_WhF{F<+c#wS?Y@LH$= zsAv`FQkf}X9|qibz>N%(n)@vI1-dj1;{JK7`&WRj^&|x|W^qP3a4hZnMP^VzZ`PO4 zPB@C&WENTz(3>@uvP-$OsmJs zgNa7L-#y>CMS!D`!1YO`4|5-2tVm!2)+?Eh^Z<|!qeLoFO$`(krU%zQANyg{Ui#RW zlV1bUUX)%UNE$%)qXgMv+IXvV+YjC&Kr^F6`^B++pl_mf3xVEo_cugK;7fc+J%-dH z)Jt~Q%-#R?+k@hUqsI0W|DBER9d@g2F!FaIc*kBYJ`5`hSZBPp2ogo!hrRhB-?Mh> zStapF*ECCXV#^Qf~@b9X=`K z)MzjH9>n}f;mR`ZDR}~;GbeAktFds06}?S3Jg4L-^e>!LudY#cPRTPE4~M4z0Gg&w z%Jc{cB33a^Nd~&YWTg%6_LzGL2{~R*$d5gY@VAf{pt>GOc9f_|EuhLNpYQ|BEk7kN XU+@|IYxsuyum7YB-*7>NyFU3Z)wtl| diff --git a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csproj.FileListAbsolute.txt b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csproj.FileListAbsolute.txt deleted file mode 100644 index e02a7c4..0000000 --- a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csproj.FileListAbsolute.txt +++ /dev/null @@ -1,5 +0,0 @@ -C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\bin\Debug\PebbleSharp.Mono.BlueZ5.dll -C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\bin\Debug\PebbleSharp.Mono.BlueZ5.pdb -C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\obj\Debug\PebbleSharp.Mono.BlueZ5.csprojResolveAssemblyReference.cache -C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\obj\Debug\PebbleSharp.Mono.BlueZ5.dll -C:\Users\brook_000\Desktop\PebbleSharp\PebbleSharp\PebbleSharp.Mono.BlueZ5\obj\Debug\PebbleSharp.Mono.BlueZ5.pdb diff --git a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csprojResolveAssemblyReference.cache b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.csprojResolveAssemblyReference.cache deleted file mode 100644 index afab1d253d958961d574f28f04c0d5c520b31e62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1922 zcmcIk?M@Rx6kS?c+NEIq{z6?7e`p|+)`Fr5FRR&%)!Y-d9$!gp}IqxKe{3uyeakHns~!sp`CWN#^a!hv5<-h57}n!v&+?%Js=8iAm?ZcwbqWdo zhT_p053SNu<9=#gl^k#lx=EXMRRr5w9f}Bajeh8h?=XoSnd&Z=85qwim%U15x^|J) z`pI68E~t6^pZ$NoUw$=BRr!|@>yrc(gl4|NMYW2s*L^v_lD=r31Z(Ju2_7FUKYKFx z05NDtLkM0Q0|`10W^iimU=8{3P3ips+gjZ@yE|NDOYG@jT;LX1*0c72MN(GDp{PhT z8l+sQR&-w<6UjD2`ZZUp7v0xeZh5ZcqY^K~!Ni10OEJu4XlO(sGN<#yy8S(_M|06Y zxx+%_##5O4N6-hmdSoG`pfP!?GpHRFsZEnY!#|5cpNkYiktV&}G>!F31Wkhc)xSck zs|42wt`poKxQS39^8DG!oR8*_fq78QQ#j-+N{xo(#%`)e!~&uQA0@=`7G^>tf&)k+ zOb!f;h6%Z~pz~mv)mdsq0^?+yiBBSg{^pfRrHRrE1+Mq&M_=`R_I%&3-ojfSGo{5k ztxo%eKS51V!RJZ0T@p3zlJ2-9GQ}m`bxCBJOPX^@WU5QL=aR^DmvrAH(V@7c2QG;Y K%_Rj6Y5Ffe13Ur% diff --git a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.dll b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.dll deleted file mode 100644 index 6bd481c8ebc2644eb35fcb7e9d5d5b7b41c4d4e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmeHKPiz!b82_gKDE|t@3KXjj6jY#{?Dh{(MBH|_g#s#;$i6G|<;68~xH5B*K@NN$=DJgc%jyy zMIeFbHCI>;6ggI!Mq^)1Xc0&d4Mc{LT*q|0<***_vay z(4)n)?pSxckDb+%1^g+GsurqY(JHz4iLO_?MF@xr_dk5 zxP@&8EXTl@0p`l87NXTW_+9Cy%|YxNFytJ#1l*YBM)ZLa^bJ(6Y^-S@SK>bUUfDn~ zxN9JtZYT|ON8)cJo>Z8#OX9;4FG&6f{Q~}8i9eK_cj$_A-zw+gO01?^n6VkSfm(sr z&~D(36qmS9;(m#TC4NETNr`pfN6D1*d5KFBYqXZyNux)o1NbpI4%|)|;JtJnxLe|9 zB~D8Iak>b8T5`@xoTazHnWxWyJ-R`4m%<9k(1AD+UW*X6(TOdL=5ji0tGuL>pD;ah5wG9# zMBcDU8PkudR@kmSBl5aCU-gpF-JI};aP)|aPE-)u44Iag5UyuBcGW5rCLMd$%oSbT zzo$4QysT>$77Gz~!L+2sxUlpENqNhCkGZHx)?Y42I)##J=H~7x$`^FIRJ9o|+P;|= zJSXNcOw05m(sar5MP4f_Y2`HWRjss8+KgpUXeDMXk>%V-%leKR@>8asvmMVjvtGyw zCm6PU;W~x1a4(oyu}mCPMz|GuuoayRaNbZ#rF~IR%mC}zFDz9n>9Lnd%C(hd-Sf}&c4`z zSZ91+w=nwR+3t8R?x}T{Esk>zKcW$Z+O*NZOl2c>lo#VUoQ1tw7s768sR&c1SFrTb zC^l^iTd5U^Dz!Pl@NUH6M97D(<1V_6dt*GEO8@-bo}u4{nvY#+{r2%+U!QN~jFJbZ zPI=hpQ- zt4uA2@cs)V=aP<_vaAu^w1e|Y2>G3`^zJVBkS~elULF>XA`{#iyrLpW1vff2_oWCE zB=5H1?Ql9lbUE^Vx?I}>$pmhkbHIZ%4r&-Ltx=4Jfro-u7kyFp)1QH#z*p$=d3Fro z`-k^^6jB%{@T!vwKPKK30zPe;B}c05lvWu?b#Oh%b@HL-U=+Z|bw9$Xf|z`0nc(N{ z;puCs6Ql6gLk4K_TkgYED$|`i4wn8h6JOvLPWn~5XpdBF}Y@A@b4hcBG$`~ zRO&(f67|TnTI_G>iY;BQ1Jb4+S$nbuyfaFu*x%V9?Ug|d{%7dezp~2zl83hfe*x9! BRssM3 diff --git a/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.pdb b/PebbleSharp.Mono.BlueZ5/obj/Debug/PebbleSharp.Mono.BlueZ5.pdb deleted file mode 100644 index e3ac9f3eb3f134718e3d0ea6b62eb95db7ae630e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7680 zcmeaxOfJeV&QB{*aMpL$)>iNhc2h9dGce%gl5z=V00Jg3V&Dfd13-Kr;Db=3m16=>45YXj{{LqI(*OT61IbY^oI?Ox{PT>)|8S0S z6u(W;Gi0nbJQ~Ib6#Z~n%k8I|pw|S+i?ZJvvn62)L2@9B4DJLPqYEKRkFtkI2w=(9cWEO)X~7FD^>f&qz&7Ni9ms$xqH^0QC{sfEZMG zNC7bj2m&!X5OV=BNDc&8Ar!-C%Mlt7gMtEe`>_E=V04a_4cJ0vc!`1HxSZ1v6x|FQ z3=Dmo4DHdNTnhrAJ^&1Z1)v0^WBBd>h^xCx4_ Date: Fri, 19 Feb 2016 20:48:29 -0500 Subject: [PATCH 8/8] remaining pr issues addressed, updated .gitignore to github vs default --- .gitignore | 277 +++++++++++++++--- .../Messages/PebbleDisconnected.cs | 21 ++ .../AppMessage/AppMessagePacket.cs | 2 +- PebbleSharp.Core/Install/InstallClient.cs | 2 +- 4 files changed, 266 insertions(+), 36 deletions(-) create mode 100644 Demo/PebbleSharp.WPF/Messages/PebbleDisconnected.cs diff --git a/.gitignore b/.gitignore index aa202a2..f6a27f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,34 +1,243 @@ -/PebbleSharp.Core/bin -/PebbleSharp.Core/obj -/PebbleSharp.Core.Tests/bin -/PebbleSharp.Core.Tests/obj -/PebbleSharp.Net45/bin -/PebbleSharp.Net45/obj -/PebbleSharp.Net45.Tests/bin/Debug -/PebbleSharp.WinRT/bin/Debug -/PebbleSharp.WinRT/obj/Debug -/PebbleSharp.Net45.Tests/obj/Debug -/PebbleSharp.Mobile/PebbleSharp.Mobile.WinPhone -/PebbleSharp.Mobile/PebbleSharp.Mobile.iOS -/PebbleSharp.Mobile/PebbleSharp.Mobile.Android/obj/Debug -/Demo/PebbleSharp.WPF -/PebbleSharp.Driod/obj/Debug -/PebbleSharp.iOS/obj/Debug -/PebbleSharp.Mobile/PebbleSharp.Mobile -/PebbleSharp.sln.DotSettings.user -/PebbleSharp.v12.suo -/PebbleSharp.Universal/PebbleSharp.Universal.Windows/bin -/PebbleSharp.Universal/PebbleSharp.Universal.Windows/obj -/PebbleSharp.Universal/PebbleSharp.Universal.WindowsPhone/bin -/PebbleSharp.Universal/PebbleSharp.Universal.WindowsPhone/obj -/PebbleSharp.WinRT.Tests/bin -/PebbleSharp.WinRT.Tests/obj -/PebbleSharp.Universal/PebbleSharp.Universal.WindowsPhone/PebbleSharp.Universal.WindowsPhone.csproj.user -/Demo/PebbleSharp.Universal/PebbleSharp.Universal.Windows/bin -/Demo/PebbleSharp.Universal/PebbleSharp.Universal.Windows/obj -/Demo/PebbleSharp.Universal/PebbleSharp.Universal.WindowsPhone/bin -/Demo/PebbleSharp.Universal/PebbleSharp.Universal.WindowsPhone/obj -/Demo/PebbleSharp.Universal/PebbleSharp.Universal.WindowsPhone/PebbleSharp.Universal.WindowsPhone.csproj.user -/PebbleCmd/bin/Debug -/PebbleCmd/obj/Debug -/PebbleSharp.Core.Tests/PebbleSharp.Core.Tests.csproj.user +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Microsoft Azure ApplicationInsights config file +ApplicationInsights.config + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.imlobj \ No newline at end of file diff --git a/Demo/PebbleSharp.WPF/Messages/PebbleDisconnected.cs b/Demo/PebbleSharp.WPF/Messages/PebbleDisconnected.cs new file mode 100644 index 0000000..269673f --- /dev/null +++ b/Demo/PebbleSharp.WPF/Messages/PebbleDisconnected.cs @@ -0,0 +1,21 @@ +using System; +using PebbleSharp.Core; + +namespace PebbleSharp.WPF.Messages +{ + public class PebbleDisconnected + { + private readonly Pebble _pebble; + + public PebbleDisconnected( Pebble pebble ) + { + if (pebble == null) throw new ArgumentNullException("pebble"); + _pebble = pebble; + } + + public Pebble Pebble + { + get { return _pebble; } + } + } +} \ No newline at end of file diff --git a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs index 15e17a2..599baed 100644 --- a/PebbleSharp.Core/AppMessage/AppMessagePacket.cs +++ b/PebbleSharp.Core/AppMessage/AppMessagePacket.cs @@ -202,7 +202,7 @@ public abstract class AppMessageDictionaryEntry : IAppMessageDictionaryEntry public virtual ushort Length { - get { return (ushort) System.Runtime.InteropServices.Marshal.SizeOf(); } + get { return (ushort) System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)); } } public virtual T Value { get; set; } diff --git a/PebbleSharp.Core/Install/InstallClient.cs b/PebbleSharp.Core/Install/InstallClient.cs index 44397ee..804c219 100644 --- a/PebbleSharp.Core/Install/InstallClient.cs +++ b/PebbleSharp.Core/Install/InstallClient.cs @@ -87,7 +87,7 @@ private async Task InstallAppAsyncV3(AppBundle bundle,IProgress p } else { - throw new DataMisalignedException("BlobDB Insert Failed"); + throw new PebbleException("BlobDB Insert Failed"); } }