How to Create a PSoC BLE App: Lesson 7 Deep Dive into App

Just another WordPress site

How to Create a PSoC BLE App: Lesson 7 Deep Dive into App

Welcome back. I’m Alan Hawse. This is Cypress Academy. Now we’re going to dig through the IOS app. And I’m going to show you the three pieces. The first piece is the storyboard The storyboard is the view in the MVC. It controls the buttons that trigger each of the actions. It controls the two switches. One to turn on the LED, and one to turn on the notifications. And it contains the label that represents the capsense value. You start by copying the buttons onto your canvas. Or the labels onto your canvas. Or the switches onto your canvas. I’ve already done all of that in this example There’s a switch. And you can just drag it on your screen. The first button is entitled Start Bluetooth. And then Search for Device. And then Connect to Device. And then Discover Services. You can see that the first one is blue. That means it’s enabled. And you enable it through the Property Inspector. User Interaction is enabled. So these buttons are not enabled. They’re gray, which means if you touch them they don’t do anything. And as you recall from the demo, the first one will be blue. It’ll be active. And then after the actions are done, I’ll turn it off and I’ll turn on the other one. And I do that with software which I’m going to show you in the next step So now I’ll go to the Assistant’s Editor And you can see that each of the buttons are connected into the view controller. So the Start Bluetooth button is connected to this IBOutlet called Start Bluetooth button. The Search for Device is connected to the Search button. The Connect to Device is connected to the Connect Device button, et cetera. And you can see that each of the buttons have an action. The Start Bluetooth Device has the Start Bluetooth action. So that’s how the connection is made between the view and the view controller. Now I’m going to show you some more detail on the view controller. The first thing I’ve done is to find a global structure which I call RCNotifications. This structure just has a number of members. Bluetooth ready. Found device. Connection complete. These are just strings that I’ll use to send notifications with. They’re in reverse Internet order, org.elkhorn- creek.simplecapsense.bluetoothready. This is so you don’t accidently collide with another notification that’s going on in your system. Elkhorn Creek is actually in my backyard in Kentucky And so I do a lot of my personal projects with Elkhorn-Creek.org Inside of the view controller, the very first thing that I do is, when the view loads up for the first time, I tell the NSNotificationCenter, which is the Apple-provided IOS app that lets you listen for notifications from other models in your system, that I want to listen for the RCNotifications.bluetoothready message. And when that message happens, I want to call self.BluetoothOn So essentially what happens is when the model sends out the message, RCNotifications.Bluetoothready, I’ll call the self.BluetoothOn. Self.BluetoothOn, what that function does is turns on the next button in the sequence So each of these buttons will send a message back to the model. The model will talk to the CBCentralManager, which will do its thing Then the model will be notified by the CBCentralManager through the delegation system that something has happened. When that happens, it’ll send an NSNotification that the view controller is listening to. So let’s go slowly through these. The first one as you’ll recall is the Start Bluetooth Action. That’s the first button at the top of the screen. When that happens, what you want is you want the model which we’re going to look at, to turn on the CentralManager. So let’s flip to the model. So I’ll click on the Bluetooth Neighborhood which is the class I created to represent the peripheral and to represent all of the Bluetooth world And when the function is called, Startup CentralManager from the view

controller. All it does is, it says “give me a new CBCentralManager object.” That object represents the CentralManager that’s inside of the IOS. And then I’ll store that in a local variable which I’m calling CentralManager, which is of type CBCentralManager. So what happens is, it tells IOS go get it going. So the hardware will turn on. It’ll start its thing. And then once it’s going, it’ll send the message back to the model called CentralManagerDidUpdateState So when that function is called by the CBCentralManager, I’ll look at the different states that it gives me back. It can give me Powered Off. It can give me Unknown. It can give me Unsupported It can give me Resetting. All of those things are bad. The state that we’re looking for is Powered On. Once the CBCentralManager is powered on, I send the NSNotificationCenter a message called RCNotifications.BluetoothReady. What that does is, it says anybody who knows about this model, you should be aware that I’ve changed. And what’s changed is the CBCentralManager is on And it’s ready to have commands sent to it Back in the view controller, when that happens you registered that you want to call the function self.BluetoothOn. So that calls self.BluetoothOn, which enables the Search button which is the next button down on the screen. Then when the user presses the Search button, it calls the action searchAction which tells the model – the first thing it does is it tells the model I want to discover the device. So back in the model, you can see the discovered device function. And what it does is, it says CentralManager, start scanning for peripherals with services. And the service that I’m interested in is the BLEParameters.capsenseLedService. Now you remember, when we set up the BLE component, we created the custom service. And it had the UUID which I call blah, blah, blah, blah, blah F0. Well, I copied that blah, blah, blah, blah F0 into another global structure which I call BLEParameters. And the first of the global structure parameters is the capsenseLedService which is a CBUUID core Bluetooth universally unique identifier that matches the hex code blah, blah, blah, blah, blah F0. And essentially, what this does is, it tells the CBCentralManager there’s a lot of Bluetooth devices out there. And there may very well be a lot of Bluetooth devices out there. What it says is I’m not interested in talking to those devices I’m only interested in a device that is advertising that it supports this service. So what happens then is the CBCentralManager starts listening. And as soon as it hears a device like that, it calls me back. And it calls the function CentralManager didDiscoverPeripheral. And that calls me back with an object of CBPeripheral type. Now the CBPeripheral is an object that represents a peripheral out in the world And it doesn’t know much about that peripheral other than what it heard in the advertising packet. So what I do is, if I’m not already connected, then I say that I found a new peripheral that’s advertising those services. I save in a local variable that peripheral So now I have a local reference to a peripheral that’s advertising the correct services And then I post a notification. I send out a notification to the view controller that I’ve now found a working device And then I tell the CBCentralManager stop scanning. Not interested in talking to anybody else. So what you could do, as if you were talking to more devices, you could have an array of these peripherals. I’m not doing that here. The first one I hear, that’s the only one I’m going to talk to. Okay, inside of the storyboard when the user presses Connect to Device, it triggers an action inside of the view controller called the connectDeviceButton. So it actually calls the Connect Device action. Which turns off the Connect button. And tells the BLE object, our model, to actually make the connection to the device. Inside of our model, this says the

Connect to Device function tells the Central Manager, go ahead and make a connection to that peripheral. Once the back and forth of the BLE radio protocol is complete, the Central Manager calls you back with, yep, I did connect to the peripheral Once that happens, you can notify the view controller that you now have a complete connection. And I do that with the post notification of RCNotifications.ConnectionComplete. Inside of the view controller, when it hears that message, connection complete, it calls the connection complete method. The connection complete method turns on the services Discovery button. And turns on the Disconnect button. Then once the user presses the Discover Services button, we go through another round It calls the Discover Services action and disables the Discover Services button. Back in the model, in the Bluetooth neighborhood, when you call Discover Services, we’ve switched from calling CBCentral methods to calling CBPeripheral methods. Once you have a connection established to make your communication to the specific peripheral happen, you don’t call the central to make those happen. You call the peripheral to make those happen. So the first thing you do is you tell the peripheral I’m interested in what services you’ve got to provide That tells IOSBLE to go do the service discovery process. The BLE service discovery process talks with the BLE stack inside of the Cypress PSoC4 BLE. And they work out the back and forth communication to figure out what are the services that are available for use. When that process is complete, it calls this function peripheral did discover services And what it does is it adds a list of CB services. And it attaches those CB services to your peripheral object. You can then iterate over all of the services And you can look at each individual service In our case, the service that we’re looking for is the capsenseLed service. Which I put into that global structure that I call BLE parameters, and I say if the service UUID matches the capsenseLed service, then I want to save that service because I know that’s the service that’s going to have the two characteristics I declared the capsenseLed service in the global structure BLE parameters. And as you’ll recall, I called it blah, blah, blah, blah, blah F0 So here it is. That’s the capsenseLed service. Once that’s complete, the Discover Characteristics button is now turned blue because the user interaction is available. So the user, you or me or whoever, can press the Discover Characteristics button When you press that button, it calls this Discovery Characteristics action. And what that does is it tells the model I’m interested in all of the characteristics that are associated with the capsense service. So back in the model again, in the Bluetooth neighborhood, you can say that I say have this function discover characteristics. Which gets called from the view controller. And that function calls the CB peripheral method Discovery Characteristics for Service. And we’re specifically interested in the characteristics that are associated with the capsenseLed service. That triggers the peripheral. It talks back and forth between the IOS and the peripheral When that talking back and forth with BLE is complete, it calls this function peripheral did discover characteristics. And what will happen is, is your CB service will now have an array of CB characteristics associated with it. You can then scan through that array of characteristics and look at each characteristic If the characteristic’s UUID matches the UUID of the characteristic you’re interested in, you can save it. And in our case, we’re interested in the two characteristics. The capsense characteristic and the LED characteristic. And in my global table, I said the LED characteristic UUID is blah, blah, blah, blah, blah F1. And the capsense characteristic UUID is blah, blah, blah, blah, bah F2 Once I’ve scanned through all of the characteristics I found, I save a reference to the characteristic if it’s the capsense characteristic, and I save a reference to the LED characteristic

if it’s there. Once you’ve got all this back and forth done, you’ve got the BLE turned on – the Central Manager turned on. You found a device. You connected to the device. You found all the services on the device You found the service, the specific service that matches the capsenseLed service. You discovered the characteristics that are associated with the capsenseLed service Specifically the LED service and the capsense service. You now have a complete connection. And you can talk to individual characteristics. So I send out the notification. All of my characteristics scan is done. I have a complete connection. Now if you remember, on the storyboard you’ve got two characteristics You’ve got the red LED which has got a switch associated with it And you’ve got the capsense which has a label which starts as questions marks, and notify. So let’s start with the red LED. When the red LED switch is switched, it calls this function LED switch action. When the switch action is called, I ask the switch is it on or is it off? If it’s on, then I write the LED characteristic with one. And if it’s off, I write the LED characteristic with zero. Now notice that one and zero, those are magic numbers which if you’re doing a project for me, I’ll slap your hand. But we’re expedient in this case These right LED characteristics, they’re just functions that are part of the model And inside of the model I do a BLE command when I get that call And that BLE command is called right value So I take either the one or the zero. I turn it into bytes with this NSData function. And then I write those bytes into the LED characteristic And I ask for a write with response. You remember, when we configured the BLE characteristic inside of the Creator component, I said it was a read characteristic and a write characteristic Write always means write with response. So I write with a response. That’s it. The IOS CB peripheral and all the magic that’s inside of the cell phone, and all of the magic that is PSoC4 BLE talk back and forth. And then they trigger down in the firmware that write. So that’s pretty cool. Now the other thing we’ve got going on is the capsense value. Now we’re interested in capsense a read from the device, essentially. And specifically the read that we’re interested in is the notification. So for us to get notifications back from our board, we need to tell our board that we’re interested in notification So when this switch is switched, it calls an action in our view controller called the Capsense Notify Action. And all the Capsense Notify Action does it calls the model and it says please write the capsense notify. And tell it whatever the sender on is. Now that switch when it’s on, it’s true. And when it’s off, it’s false So when it’s on, we want notifications. And when it’s off, we want no notifications. So when we look down inside of our model, we see that the write capsense function that we called from our view controller takes in a Bool in, either the on or off. And then sends out a notification. Set Notify is a member function of the peripheral class. And what it does is communicates with the peripheral that says please turn on notifications so that I’ll be notified when the capsense changes What happens then is, the capsense LED board that we built will start sending out changes. The iPhone hears those changes because it’s connected. And when it hears the change, it calls this function Peripheral Did Update Value for Characteristic So when that happens, you look and see which characteristic changed. In this case, we were interested in the capsense characteristic. So we got a note from the IOS that said a value inside the characteristic changed. You say which characteristic was it? It matches the capsense characteristic. Then you have to unwind bytes. And so you do this little IOS rigmarole where you turn bytes that come in NSdata into an integer. Then you save the value. And then you send out a notification to your view controller The capsense has changed. Then inside of the view controller,

I told you that we registered a notification called Add Observer for Name RCNotifications Update Capsense. And when you get this notification, you want to update the capsense value on the screen And all that you do down in your view controller is you ask your model what’s the value. You turn it into text And then you put it on the screen. That simple. So your board sends out the notification. It works its way through the Cypress BLE stack out over the radio into the iPhone through the iPhone BLE stack. Then it calls your app back. Says this characteristic changed. Then your characteristic sends a notification The view controller reads the value that it saved locally. Turns it into text and puts it on the screen. That’s it. So once again, the model is the CBCentralManager, as well as the peripheral that represents your board. The view controller takes button clicks and tells the model to do things. And when it gets notifications back from the board, it makes the display. That’s all there is to it. I’ll post this project. And I’ll post the firmware. And you’re welcome to send me questions at [email protected]