//REF: https://github.com/travisgoodspeed/PyMetaWatch/blob/master/pymw.py public class MetaWatchProtocol { public static byte[] BuildMessage() { //TEST: return null; } enum ScreenMode { MODE_IDLE = 0, MODE_APPLICATION = 1, MODE_NOTIFICATION = 2, MODE_SCROLL = 3 }; enum StatusChange {STATUS_CHANGE_MODE = 0, STATUS_CHANGE_DISPLAYIMEOUT = 1}; enum Button { A=0, B=1, C=2, D=3, E=5, F=6 }; enum ButtonType { Immediate = 0, PressAndRelease = 1, HoldAndRelease = 2, LongHoldAndRelease = 3 }; // Time to pause between packets //#_TX_PACKET_WAIT_SEC = 0.025 #per Javier's empirical values. float _TX_PACKET_WAIT_SEC = 0.2f; //#_TX_PACKET_WAIT_SEC = 0.1 #per Goodspeed's less optimistic values. #region CRC class CRC_CCITT { // Implementation of CRC-16-CCITT bool inverted = true; static uint[] table = null; static uint[] flipmask = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}; public CRC_CCITT() { init(); } void init() { if (null != table) return; uint crc = 0xFFFF; // initial value const uint polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12) table = new uint[256]; uint c; for (uint idx = 0; idx < table.Length; idx++) { crc = 0; c = idx << 8; for(int j=0; j<8; j++) if (0x8000 == ((crc^c) & 0x8000)) crc = (crc<<1)^polynomial; else crc <<= 1; c <<= 1; crc &= 0xFFFF; table[idx] = crc; } } public uint update_crc(uint crc, uint c) { c = 0x00ff & (c % 256); if (inverted) c = flip(c); uint tmp = ((crc >> 8) ^ c) & 0xffff; crc = (((crc << 8) ^ table[tmp])) & 0xffff; return crc; } public uint checksum(byte[] bytes) { uint v = 0xFFFF; for(int i=0; i< bytes.Length - 2; i++) v = update_crc(v, (uint)bytes[i]); return v; } uint flip( uint c) { // MetaWatch/Fossil requires bitflipping return (flipmask[c & 0x0F] << 4) + flipmask[ (c & 0xF0) >> 4 ]; } } #endregion public string SetDisplayInverted(bool value) { return value ? "\x41\x00\x00\x01" : "\x41\x00\x00\x00"; } public byte[] Buzz() { return Buzz( 500, 500, 1); } public byte[] Buzz( int millisecOn, int millisecOff, int cycles ) { //Buzz the buzzer. return new byte[] { 0x23, 0x00, 0x01, (byte)(millisecOn >> 8), (byte)(millisecOn & 0xFF), (byte)(millisecOff >> 8), (byte)(millisecOff & 0xFF), (byte)(cycles & 0xFF ) }; } CRC_CCITT CRC = new CRC_CCITT(); public byte[] BuildMessage( byte[] cmd ) { byte[] sendbuf = new byte[4 + cmd.Length]; sendbuf[0] = 0x01; sendbuf[1] = (byte)((cmd.Length + 4) & 0xFF); Buffer.BlockCopy(cmd, 0, sendbuf, 2, cmd.Length); uint crc = CRC.checksum(sendbuf); //Little Endian sendbuf[sendbuf.Length-2] = (byte)(crc & 0xFF); sendbuf[sendbuf.Length-1] = (byte)(crc >> 8); return sendbuf; } }
void Talk() { BluetoothAdapter bluetooth = BluetoothAdapter.DefaultAdapter; if (!bluetooth.IsEnabled) bluetooth.Enable(); ICollection<BluetoothDevice> devices = bluetooth.BondedDevices; foreach (BluetoothDevice device in devices) { if (device.Name.Contains("Watch")) { BluetoothSocket socket = device.CreateRfcommSocketToServiceRecord(Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB")); socket.Connect(); try { MetaWatchProtocol protocol = new MetaWatchProtocol(); byte[] message = protocol.BuildMessage(protocol.Buzz()); socket.OutputStream.Write( message, 0, message.Length); socket.OutputStream.Flush(); } finally { socket.Close(); } } } }