 I guess, now it's time to watch our Bluetooth. I don't know if I introduced myself. So, my name is Maciej, and I'm from Poland. Currently, I work for, oh, for BBM. Oh, yeah, I might need to turn it on. Yeah, so I work for BBM. I am an iOS engineer here. And I also run a blog called Swift.in.io. You can look it up. We usually write about Swift. Surprise, surprise. And recently about unit testing. And today, I would like to speak about somewhat new feature of WatchOS 4. However, it was introduced on WWDC last year. And starting from WatchOS 4, core Bluetooth framework is supported. So we can connect to Bluetooth peripherals on our WatchOS application. And what we're going to do also during this talk is we're going to implement a simple application for WatchOS. But before we do that, let's get back a few centuries. So this bus relief shows Harold Gormson, which was a Denmark king. And he was well known for two things. One of them is he united Norway and Denmark. And it was somewhere around 935 to 985. And it was also famous for another feature. During one of the battles, he got injured. And his gun turned blue. And from this accident, he got a nickname. It was called Bluetooth. And in 1998, there was a special interest group created by five companies, IBM, Intel, Nokia, Toshiba, and Ericsson. And they wanted to work on a standard for wireless communications. And because they wanted to unite to unify Bluetooth, sorry, wireless transmission among devices, they named it after Bluetooth, after Harold Gormson Bluetooth. And the logo of the technology consists of two Nordic rooms, B and T. And in 2011, I guess, there was another version of standard created, which was called Bluetooth Low Energy. And it had a few ideas in mind. First of them is, of course, it needed to support low energy, it should work on very little power. It supported clients' home architecture, so it was very simple. Some devices wanting data would just connect to peripherals, to servers, they would return the data and they would disconnect, and slow energy. And the data is wrapped up in services, is grouped in characteristics, and it's available in that way. On iOS, WatchOS and macOS, we can connect via Bluetooth devices to Bluetooth devices by using core Bluetooth framework. And it works like that. If we wanted to have an application that connects to other peripherals, we'd have to use object called CB Central Manager. And we would connect to Bluetooth devices that would be visible in our application as CB Peripherals. If we wanted to write an application that acts as a peripheral, namely, it would be visible as a server exposing some data, we'd have to use CB Peripheral Manager. And clients wanting to read data from our peripheral would be visible in this application, which is CB Central's. Data is grouped into services and characteristics, and all of the characteristics and services can be identified by universally unique identifiers. We have a few classes, as I mentioned a while ago, and Kerbalto framework today will be using this set of classes to implement a simple application for WatchOS. So we'll use the CB Central Manager object, and we'll connect to another CB Peripheral to read some values for the bird. Bird will have an A, a color in which we'll show its appearance, and it will also have alpha value because we want to make it a bit translucent. And the data we'll expose will be exposed as UTF-8 encoded strings, and it will be just a string or hexadecimal value describing a color, or integer ranging from zero to one that will describe how translucent a bird should be. We need some UIDs to identify their or services or characteristics. So we'll have a simple enum bird service that will have UID of our service, which is this 128-bit value. We'll also have UIDs for other characteristics, such as characteristic for color and name alpha value, and some helper will need an array of characteristics. And we can generate those UIDs on iOS or on macOS. On macOS, it can be done by using UID Gen Console Tool and on iOS or other Apple environment platform. We can use NS UID Class to generate a simple universal unique identifier because this is what UIDs stand for if I haven't mentioned that. We already have a peripheral application. So we have a few controls to select a color from. We can type in a name for the bird and we can play with the transparency of a bird. And this application will act as a CV peripheral, as a peripheral, actually. So it would have to advertise under services. In our case, it will be bird service because our central application that we'll write for watchOS will have to sense the wireless medium for packets sent out by this application. So peripheral needs to advertise services. It will also have to respond to read requests for values of characteristics. And it will also notify our application if something changes in the system. So in the application. So whenever we select a different color on the interface or we type in a different theme or we select a value from the slider, our watchOS application will be notified about the change. We're going to implement bird central, bird up here. And it will have to scan for that service that peripheral will advertise. We'll have to discover characteristics of that particular service. We'll also have to read the value and subscribe for notifications upon a value update. And of course, at PBM, so we do everything in TDD, but actually I already implemented unit tests. So we have a suite of failing tests. We're going to implement everything and maybe for today we'll skip the refactoring part. Okay, so let me do the coding part. Or maybe I can show you the application itself from the peripheral. So it has a simple interface. When I select something, you probably can notice that the color of the application changes of the interface. I can type in the name or I can play with the alpha value of this bird. And now I'm going to switch to that place. Cool. So we have a project, we have 29 failing tests. We have this bird service in which I have all the UUIDs needed for the bird service and characteristics. And we also have this helper array of all the characteristics and it will be needed while we're going through the code. So I can run tests again so you will see that they actually are failing and I am not faking it. And let me introduce you to the project. It is available on GitHub and it contains a few targets. So there's Bluetooth demo. This is application for an iPhone. We also have peripheral target which is this application that we can use for exposing the data. We also have a target for watch OS application. And we have macOS app. Hence my macbook is a very old one. It doesn't support Bluetooth low energy. So this is why I'm going to show it to you by using another phone. So we have some common parts for all the applications, all the targets. We have this bird service I described to you. We have a bird central which will be pull which will be used by multiple targets. For example this, we have another iOS application and bird central will be hosted on the iOS application and on the watch OS application. So here we have a simple interface for the iOS application. It consists of a bird that has a name. It also has connection status and an image that we'll be playing with. We also have a watch OS application with a very similar interface. Hooray, hooray. And we have a set of tests. I'm not going through all of them. There are just for me to go with the implementation and to make sure that I implemented everything correctly. So let's start. First of all, we need to import core Bluetooth because this is our entry point to Bluetooth low energy communications. We have our bird central object that the one that will be reused by iOS application and watch OS application. And this bird central object communicates with other parts of the application such as view controller or interface controller in case of watch kit up. It will use delegate to say to the view controller or interface controller that's something happened in the system such as we discovered a new value please update an interface. We use CV central manager to kick off Bluetooth communications. Here, there is a wrapper on CV central manager because I needed to write unit test but basically this is a protocol that describes CV central manager and CV central manager confirms this protocol. And we have a set of properties that we use to store values read from a peripheral such as peripheral itself, services, service or characteristics. And there are also wrap in terms of protocol. All the interfaces described in terms of protocol. Bird central delegate is a protocol that needs to be implemented by everyone who wants to use bird central. And it contains a simple method. Central did perform action. And we have a few actions. We can connect to peripheral either successfully or unsuccessfully. We can disconnect from peripheral or we can read the value. And the value is of course name alpha from zero to one this time or a core. So let's start. So there's one method that gets called whenever state of Bluetooth interface changes in your system on your phone. It's called central manager did update state. And what we want to do at that time is we want to scan for services whenever interface is up. So you need to make sure that our state of central manager is powered on. And whenever it is, we want to scan for bird service. So your central manager to scan for peripheral with services. And the services we are interested in is a UID for our bird service. And we can just keep the options part. So let me run unit test. You'll be able to see that some of them will become green. Then whenever our central manager finds a peripheral, we get notified with central manager did discover peripheral. And we also can grab the advertisement data. So now it is 27, it was 29. Good progress. Whenever peripheral is found, we need to stop scanning because we already found what we were looking for. So we need to call stop scan on central manager. We also want to start the peripheral. It's very important because if we don't start reference to peripheral, we won't get updated upon connection. So let's start peripheral in a property. And we also want to connect to this particular peripheral. So we use another method in central manager called connect peripheral. We should be good with this method. Whenever our connection request fails, we get notified about that fact with central manager did fail to connect method. So in that case, there's no need to store the peripheral we stored in this method. So we can just clear it by setting this peripheral to neal. We might want to start scanning wireless medium one again to find another peripherals that provides such services. So we can start scan again. And we also can notify our delegate that we failed to connect. So because our delegate probably will update user interface for the case of this demo, we'll dispatch callbacks on the main thread asynchronously because this Bluetooth engine works on another thread. So we just need to use our central did perform action method. And this time we will just tell that our connection failed. It's been mentioned our unit tests. And let's focus on the successful connection. So this time what we want to do is we want to become peripherals delegate whenever we connect successfully. Because from now on we won't be using central manager in order to read values from the peripheral will invoke methods on peripheral object itself. And in order to catch the response we need to become a delegate of a peripheral. So we need to become delegate of a peripheral and we want to discover services of the peripheral. And again we are interested in our bird service. And we can also notify our delegate of bird central that we successfully connected to a peripheral. Let me run unit tests again. Whenever we disconnect from peripheral we also might want to do some cleanup. So let me create a reset method that will reset all the properties used to for storing some values. So let's clear the service itself. We can clear that peripheral. And there are also properties for all the characteristics. So let's clear them up as well. We also want to kick off scanning once again because we have just disconnected from the peripheral. And then we can notify our delegate again that we got disconnected. Whenever we successfully connect to the peripheral, I'm sorry, whenever we discover services for a peripheral we also get notified via one of the CV peripheral delegate methods. And when we discover services first let's check that our bird service is actually in the discovered services. Let's use a guard statement. And peripheral contains an array of services. So you might want to filter every characteristic characteristic that doesn't have a UID, certain characteristic service. You might want to filter service that doesn't contain a UID we are interested in. And the UID we're interested in is of course a UID of our bird service. And whenever we've got this filtered array we can grab the first item from it. If we have the service, we can store this service in our bird service protocol. Bird service is a type CV service. And what we want to do then is to discover all the characteristics of a service. We need again UIDs. So let's grab an array of characteristics we're interested in after UIDs. And the service we're interested in we need to also pass it to the method. Let's run test, hopefully they will decrease. Whenever a characteristic is discovered we can finally read its value and subscribe for notifications. So let's make sure that we don't have any error. And we also can set all characteristics to our properties. So now what we need to do is we need to iterate over all characteristics. And now we need to check the UID of a characteristic and we need to store them. So we have a few cases. We have name characteristic. We also have color characteristic and alpha characteristic. So we can store them in properties and of course switch needs to be exhaustive. And default case will just return. And oops, we need to return as I said. And we also want to subscribe for notifications. And we want to read value for this characteristic. Let's run unit tests and just grab something from here. Oh no, this is bad. So whenever we read a value from peripheral peripheral did update value for characteristic gets called. And what we need to do now is we need to first check again that there was no error. And then we need to notify our delegate that we read the value. And we will use for that bird central dot action dot value time. Sorry, bird central dot value time mentioned earlier that can be a name of our core. So again, we iterate, we have a switch statement and based on the UID, we'll create an appropriate type of value. So in the first case, it's name value and we have some computed properties that extract values here. Why can't get in? So it extract binary data from a characteristic. It converts it to a string or returns something. So we can reuse these. And in other cases, it will be polar or alpha. And the alpha computed property does some manipulation on the value that was from zero to 100 that then converts it to CGFloat from zero to one. And what we need to do in this method is to notify our delegate that something happened which is a value was read. And we can use our value variable. Okay, let's run unit tests. And I think that's it for the implementation. Let's see if I forgot about anything. And in the meantime, let me prepare a phone for the final installation of this application. Okay, a few more things. So whenever we connect to a peripheral, we need to become peripheral delegates. Probably this will do. Whenever we discover a characteristic, we should store the service. And if there is an error when we discover services, we should not store anything. They burn with me a while and hopefully the demo will go successfully. Does anyone know a good joke? Because this may take a while. Okay, tests are green. So let's try installing application on our watch. I mean, not on our, on my watch. And let's see if it will work. Okay, you can see the watch and maybe in a while, it will be installed. Okay, I think it takes a moment. So maybe I can show you a bit of tests if we have a time. So we have bird central tests class that contains all the test cases. We have our subject or system under test, which is bird central. And we create an instance of it in setup method. We also have some spies that can intercept calls to this central manager we interact with. A spy contains some properties that we can assert after calling some method on our SUT. And that's usually toggled from method not called to method called. And to be honest, writing tests and Swift is really difficult because we need to create all those spies or mocks by ourselves. Okay, I think it should be running by now or almost. The question couldn't be completed. Let me see if the application is there. It's installed. Oh, but I need to trust the application. Okay, do they trust it? Maybe it will run. Let's test it in field. So I have this phone over here. Oh, maybe I could show it there. Now I will start advertising services. And if everything will be done properly, this should connect. And actually it tells that it is connected and you have a bird. And we can change its color play with its transparency. And we can also set a name for it. So let's call this one James Bond. And I don't know if it's visible but it should have changed James Bond. Okay, that was difficult. So let me rub up. Quick recap. Starting from what we have for, we're able to write applications that connect to peripherals and only central role is supported on WatchOS. We, I wrote some unit tests that helped me implement the desired behavior of our application. The code of bird central, the class that we created is portable to iOS, WatchOS, MacOS, and TVOS, namely all the platforms that support Kerbalto framework. Code is available online. And I think that's it. Thanks. Are there any questions? Good, because I'm extremely tired. If anyone has any questions, just talk to me after the event. Okay, let's now win here. So, actually you can ask the question now. Okay. So the winner will win that this book. But you also need to post a photo later. So you spoke, so you can ask the question. Okay. So raise your hand and you can do the answer. Good. The best answer wins. And the first person to give the best answer. Okay, quiz. How can you create a universally unique identifier on MacOS? Please specify a tool that can be used. And on iOS, a class framework will do. C, U, I, D, iOS. But this is not the simplest way to create a universally unique identifier on iOS. And Taika Manek, you know, just speak up. Win a book on iOS animations. Is it C, D, C, I, T, J, X, or R, X? No. There is a really simple way of creating it. And actually, I mentioned that during this slide, sorry, where is this, here. So there is something called CBU, U, I, D. But this just creates an instance of CBU, U, I, D, object. But what we want to do is we want to generate this string that we could reuse in our application. You mentioned some things about NCU, U, I, D. Yeah. So this is on iOS. Do you also remember how to create a U, U, I, D on macOS? Yeah, I mentioned, I don't know much about it. Codgen? Codgen? Not Codgen. U, U, I, D, U, I, D. Exactly. Okay, Dom, you don't need this book, so how the book goes to this gentleman over there because he mentioned that as U, I, D first. Okay. I need to take a photo. Good. And I think that's it. Thank you very much.