How to properly create and notify a characteristic with GATT Server and BLE on Tizen (watch 3)

How to properly create and notify a characteristic with GATT Server and BLE on Tizen (watch 3)

BY 18 Sep 2020 Tizen .NET

Hello, I am currently trying to establish a connection via GATT with Android and Tizen on a watch 3, and everything seems to be working correctly, and I can see the service on nRF app, but I cannot see the value nor notify when I press the button on the watch.

 

I cannot find a way to see connected clients from the server side, and I cannot notify with null, as it throws an exception.

nRF SS:

 

Error thrown:

Here is the code of the Server running on Tizen watch:

 

using System.Text;

using Xamarin.Forms;
using Tizen.Network.Bluetooth;
using Tizen.Wearable.CircularUI.Forms;
using Tizen.NUI;
using System;

namespace TizenWearableApp1
{
    public class App : Application
    {
        BluetoothGattServer m_GattServer;
        private BluetoothGattService m_GattService;
        BluetoothLeAdvertiser m_Advertiser;
        BluetoothLeAdvertiseData m_AdvertiseData;
        BluetoothGattCharacteristic m_CharcTX;
        BluetoothLeDevice m_Device;
        Button b;

        const string SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"; // UART service UUID
        const string CHARAC_UUID_RX = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
        const string CHARAC_UUID_TX = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";

        public App()
        {
            b = new Button();
            b.Clicked += OnClick;
            b.Text = "Set Charc Val";
            // The root page of your application
            MainPage = new CirclePage
            {
                Content = new StackLayout
                {
                    VerticalOptions = LayoutOptions.Center,
                    Children =
                    {
                        b
                    }
                }
            };
        }

        private void OnClick(object sender, EventArgs e)
        {
            test++;
            //byte[] descriptorValue = UTF8Encoding.UTF8.GetBytes(test.ToString());
            IntDataType intType = IntDataType.UnsignedInt8;
            b.Text = m_GattService.GetCharacteristic(CHARAC_UUID_RX).GetValue(0).ToString();
            m_GattService.GetCharacteristic(CHARAC_UUID_TX).SetValue(intType, test, 1);
            m_GattServer.SendNotification(m_GattService.GetCharacteristic(CHARAC_UUID_TX), null);
        }

        public void bt_onoff_operation()
        {
            /// Launch the Bluetooth activation settings to allow the user to enable Bluetooth
            Tizen.Applications.AppControl myAppControl = new Tizen.Applications.AppControl();
            myAppControl.Operation = Tizen.Applications.AppControlOperations.SettingBluetoothEnable;
            Tizen.Applications.AppControl.SendLaunchRequest(myAppControl);
        }

        protected override void OnStart()
        {
            BluetoothAdapter.DiscoveryStateChanged += DiscoveryChanged;
            BluetoothAdapter.NameChanged += NameChanged;
            BluetoothAdapter.ScanResultChanged += ScanChanged;
            BluetoothAdapter.StateChanged += StateChanged;
            BluetoothAdapter.VisibilityDurationChanged += VisibilityChanged;
            BluetoothAdapter.VisibilityModeChanged += VisibilityModeChanged;
            BluetoothAdapter.Name = "ArielTESTTT";
            
            m_GattServer = BluetoothGattServer.CreateServer();
            m_GattServer.NotificationSent += GattNotificationSent;
            m_GattService = new BluetoothGattService(SERVICE_UUID, BluetoothGattServiceType.Secondary);

            byte[] characteristicValue = UTF8Encoding.UTF8.GetBytes("test1");
            byte[] characteristic2Value = UTF8Encoding.UTF8.GetBytes("test1");
            byte[] descriptorValue = UTF8Encoding.UTF8.GetBytes("test2");
            
            m_CharcTX = new BluetoothGattCharacteristic(CHARAC_UUID_TX, BluetoothGattPermission.Read, BluetoothGattProperty.Notify, characteristicValue);
            m_CharcTX.SetValue("test1");
            m_CharcTX.ReadRequested += ReadRequested;
            m_CharcTX.WriteRequested += WriteRequested;
            BluetoothGattDescriptor desc = new BluetoothGattDescriptor("2902", BluetoothGattPermission.Read, descriptorValue);
            desc.SetValue("test1");
            m_CharcTX.AddDescriptor(desc);
            m_CharcTX.Value = characteristicValue;

            m_CharcTX.WriteType = BluetoothGattWriteType.NoResponse;
            m_GattService.AddCharacteristic(m_CharcTX);
            m_GattService.GetCharacteristic(CHARAC_UUID_TX).NotificationStateChanged += NotificationStateChanged;
            m_GattServer.RegisterGattService(m_GattService);
            m_GattServer.Start();
            StartBLEAdvertise();
        }

        /// Register for GATT connection event handler
        public static void GattClient_ConnectionStateChanged(object sender, GattConnectionStateChangedEventArgs e)
        {
            if (e.Result != (int)BluetoothError.None)
            { 
            }           
            else if (!e.RemoteAddress.Equals(""))
            {
            }
            else if (e.IsConnected.Equals(false))
            {
            }
            else
            {
            }
        }


        private void NotificationStateChanged(object sender, NotificationStateChangedEventArg e)
        {
            int a = 0;
        }

        private void WriteRequested(object sender, WriteRequestedEventArgs e)
        {
            m_CharcTX.Value = e.Value;
        }

        private void GattNotificationSent(object sender, NotificationSentEventArg e)
        {
            int a = 0;
        }

        private void VisibilityModeChanged(object sender, VisibilityModeChangedEventArgs e)
        {
            int a = 0;
        }

        private void VisibilityChanged(object sender, VisibilityDurationChangedEventArgs e)
        {
            int a = 0;
        }

        private void StateChanged(object sender, StateChangedEventArgs e)
        {
            int a = 0;
        }

        private void ScanChanged(object sender, AdapterLeScanResultChangedEventArgs e)
        {
            int a = 0;
        }

        private void NameChanged(object sender, NameChangedEventArgs e)
        {
            int a = 0;
        }
        int test = 0;
        private void ReadRequested(object sender, ReadRequestedEventArgs e)
        {
            test++;
            byte[] descriptorValue = UTF8Encoding.UTF8.GetBytes(test.ToString());
            m_CharcTX.Value = descriptorValue;
            int a = 0;
        }

        private void StartBLEAdvertise()
        {
            AddAdvertiseData();
            BluetoothAvrcp avrcp;
            m_Advertiser = BluetoothAdapter.GetBluetoothLeAdvertiser();
            m_Advertiser.AdvertisingStateChanged += AdvertisingStateChanged;
            m_Advertiser.StartAdvertising(m_AdvertiseData);
        }

        private void AdvertisingStateChanged(object sender, AdvertisingStateChangedEventArgs e)
        {
            int a = 0;
            //throw new NotImplementedException();
        }

        void AddAdvertiseData()
        {
            m_AdvertiseData = new BluetoothLeAdvertiseData();

            // Add appearance
            m_AdvertiseData.PacketType = BluetoothLePacketType.BluetoothLeAdvertisingPacket;
            m_AdvertiseData.Appearance = 192;

            /// Add device name
            m_AdvertiseData.IncludeDeviceName = true;

            /// Add TX power level
            m_AdvertiseData.IncludeTxPowerLevel = false;

            /// Add manufacturer data
            ManufacturerData manufData = new ManufacturerData();
            manufData.Data = new byte[5] { 0x01, 0x02, 0x03, 0x04, 0x05 };
            manufData.Id = 117;
            manufData.DataLength = 5;
            m_AdvertiseData.AddAdvertisingManufacturerData(BluetoothLePacketType.BluetoothLeScanResponsePacket, manufData);

            /// Add service solicitation UUID
            string serviceSolicitationUuid = "180d";
            m_AdvertiseData.AddAdvertisingServiceSolicitationUuid(BluetoothLePacketType.BluetoothLeScanResponsePacket, serviceSolicitationUuid);

            /// Add service UUID
            string serviceUuid = "1805";
            m_AdvertiseData.AddAdvertisingServiceUuid(BluetoothLePacketType.BluetoothLeScanResponsePacket, serviceUuid);
            
            /// Add service data
            BluetoothServiceData serviceData = new BluetoothServiceData();
            serviceData.Uuid = "1805";
            serviceData.DataLength = 3;
            serviceData.Data = new byte[3] { 0x01, 0x02, 0x03 };
            m_AdvertiseData.AddAdvertisingServiceData(BluetoothLePacketType.BluetoothLeScanResponsePacket, serviceData);
            m_AdvertiseData.AdvertisingConnectable = true;
        }

        private void DiscoveryChanged(object sender, DiscoveryStateChangedEventArgs e)
        {
            e.DeviceFound.CreateBond();
            e.DeviceFound.CreateSocket("test");
        }

        private void EventHandlerStateChanged(object sender, StateChangedEventArgs e)
        {
            if (e.BTState == BluetoothState.Enabled)
            {
                StartBLEAdvertise();
            }
            else
            {
                bt_onoff_operation();
            }
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

 

Written by