Developing applications for Apple Watch (iPhone and iPad) using Wolfram Language (Mathematica)

Original author: Stephen Wolfram
  • Transfer

Translation of Stephen Wolfram's post, Instant Apps for the Apple Watch with the Wolfram Language .
I express my deep gratitude to Kirill Guzenko for help with the translation.


My goal is to take programming to the next level with Wolfram Language . And last year (see the article on Habrahabr " Stephen Wolfram: The Frontiers of Computational Thinking (report from the SXSW festival) ") we expanded the methods of using and deploying the language - on a working computer, in the cloud, mobile and embedded platforms, etc. A what about wearable gadgets? And in particular about the Apple Watch? A few days ago, I decided to see what can be done here. So I freed up my day for this thing and started writing code.

The idea was to write code using the Wolfram Programming Cloudbut instead of creating a web application or web API, I needed to get an app for Apple Watch. And, which is quite convenient - the first, preliminary, version of our Wolfram Cloud app is now available in the App Store:



It allows you to download applications from Wolfram Cloud directly to iPhone, iPad and Apple Watch.



In a way, it was adventure programming. The Apple Watch was just coming out, and the Wolfram Cloud app was just a preliminary version. However, for the past almost 30 years I have been creating the Wolfram Language advanced development environment. And I'm glad to note the fact that you do not need a lot of time to start receiving interesting Wolfram Language applications that run on the Apple Watch. And in less than a day of work - with the help of a small team - I developed 25 applications compatible with the watch:



I created all these applications by going through several steps - first programming them in the Wolfram Programming Cloud (on the website or in the desktop version), then deploying them in the Wolfram Cloud and connecting to the Apple Watch through the Wolfram Cloud app. And, although the applications were designed for the Apple Watch, you can, in fact, also use them through a browser or on your phone. There are links to web versions of applications that are presented in this post. To get these applications on your phone or watch, just go to this page and follow the instructions.



This page also contains all the source code for these applications in Wolfram Language, and you can use any system for working with Wolfram Language - Wolfram Programming Cloud (including free), Mathematica and so on - to experiment with the code yourself and possibly post your version of any application.

My first Apple Watch app


So how does it all work? For the first time working with the Apple Watch, I decided to write a simple test application that produces one random number. The main Wolfram Language code for this task is very simple:

In [1]: = RandomInteger [1000]

Let the numbers on the watch be large and bold, and in general, with a random color:

In [2]: = Style [RandomInteger [1000], Bold, 30, RandomColor []]

We can immediately upload all this to the cloud with:

In [3]: = CloudDeploy [Delayed [Style [RandomInteger [1000], Bold, 250, RandomColor []], "PNG"], Permissions -> "Public"]

And, if you follow this link to the web browser, you will see a web application that creates a web page with a random number. ( Delayed in the code delays calculations until no one has entered the page or until it has been updated, so you will receive a new random number each time.)

How to send all this to the Apple Watch? First of all, all this should get on the iPhone first. And it is easy. Because everything that you uploaded to the Wolfram Cloud is fully accessible on the iPhone through the Wolfram Cloud app. To make this application easy to find, it’s worth adding an icon and a name. And if in the end it all works on the clock, then you should place it on a black background:

In [4]: ​​= CloudDeploy [Delayed [ExpressionCell [Style [RandomInteger [1000], Bold, 250, RandomColor []], Background -> Black], "PNG"], "WatchApps / RandomNumber", IconRules -> WordCloud [ RandomInteger [10, 20]]]

And now, if you follow this link through a browser, you will see an open version of the application there. Inside the Wolfram Cloud app on the iPhone, the application appears in the WatchApps folder:

Deploy that RandomNumber app, and it will appear on your phone

Now, if you click on the application icon, you will run the Wolfram Language code in the Wolfram Cloud and again a random number will be displayed on the phone:

The RandomNumber app works fine on the phone, but of course is sized for the Apple Watch screen

If you want to start the application again and get a new random number, just pull down at the top of the screen.

To get the application on the watch, return to the list of applications and click on the clock icon at the top and select the application. This will display it on the watch in the list of those applications that are associated with the phone:

That's all it takes to get the app onto your watch

Now just click on the RandomNumber app. In this case, the Wolfram Language code will be launched in the Wolfram Cloud, and after that a random number will be displayed on the clock:

And here it is running on the watch - it's that easy

Random applications


With Wolfram Language it is very simple to create all sorts of "random" applications. Here is the key part of the Coin Flip app coin flip app :

In [5]: = RandomChoice [{image: heads, image: tails}]

That's all it takes to deploy the app on the Internet, on mobile devices and watches:

In [6]: = CloudDeploy [Delayed [ExpressionCell [RandomChoice [{image: heads, image: tails}], Background -> Black], "PNG"], "WatchApps / CoinFlip", IconRules -> image: heads]

Someone might say that it is not practical to use all this complex set of technologies for such tasks. In the end, it's easy to just drop a regular coin. But this assumes that you have it somewhere (I, for example, do not have them). In addition, the Coin Flip app will produce a better pseudo-random sequence.

How about playing rock-paper-scissors with your watch? The main code for this task is again quite simple:

In [7]: = RandomChoice [{image: rock, image: paper, image: scissors}]

There isa huge amount of knowledge built into the Wolfram Language - and somewhere in the far corner there is knowledge that makes it very easy to create an application with the output of random Pokemon Random Pokemon app :

In [8]: = EntityValue [EntityValue ["Pokemon", "RandomEntity"], {"Image", "Name"}]

Here's how it works on the clock:

Stats pop quiz: How many random displays will it take, on average, before you catch 'em all?

Let's now try something with more complex Wolfram code Language Here, for example, is the inventor of the words Word Inventor app , which creates a word from random vowels and consonants, alternating them (the resulting words often sound like the names of Pokémon or some kind of technical startups).

In [9]: = vowels = {"a", "e", "i", "o", "u"};  consonants = Complement [CharacterRange ["a", "z"], vowels];  Style [StringJoin [Flatten [Table [{RandomChoice [consonants], RandomChoice [vowels]}, {3}]]], 40]

Clock that shows time


For lack of other things, people will presumably want to use the watch for its intended purpose. And since we are in the modern world with the Internet - even a watch can not do without a couple of cats. Below is the Kitty Clock code for Wolfram Language:

In [10]: = ClockGauge [Now, PlotTheme -> "Minimal", GaugeMarkers -> {image: graycat, image: orangecat, None}, Background -> Black, TicksStyle -> White]

But on the watch itself it looks like this:

You can has kitty clock ...

With this watch you can get crazy things. Based on our recent (see article on Habrahabr " 3/14/15 9:26:53 Celebrating the" Day of the Pi "century, as well as a story on how to get your very personal piece of pi ") and the very popular site My Pi Day , created in honor of Pi Day , below is a slightly more complex code for Pi watches, in which the current time is displayed in the context of finding these numbers in the Pi number:

In [11]: = pi = Characters [ToString [N [Pi, 65000]]];  time = Characters [DateString [{"Hour12", "Minute"}]];  pos = First [SequencePosition [pi, time]];  Style [Grid [Partition [Join [Take [pi, 14], Characters ["..."], Take [pi, pos - {13, 1}], Style [#, Orange] & / @ Take [pi, pos], Take [pi, pos + {5, 4}]], 10], Spacings -> {0, 0}], 40, Background -> Black, FontColor -> White]

Or add some more information:

And now you can know exactly what digit of pi any time of day begins at

Where are you at?


You can enable GPS tracking of your current location both on the Apple Watch and on your phone in order to find out your location. This makes it very easy to create Lat-Long app geolocation applications that show the width and longitude of your location on the watch (this example shows the coordinates of our headquarters):

In [12]: = Style [Column [{DMSString [Latitude [Here], {1, "NS"}], DMSString [Longitude [Here], {1, "EW"}]}], 30, White, Background -> Black]

I'm not quite sure that the program below can be useful (prove your location via Skype?). Actually, here is the Here & Now QR app , which shows your current coordinates and time in the form of a QR code:

In [13]: = BarcodeImage [StringJoin [DMSString [Here], "|", DateString [Now]], "QR"]

Wolfram Language knows about many things, and one of them is geography . Here is the code that allows you to find the 10 volcanoes closest to you:

In [14]: = v = GeoNearest ["Volcano", Here, 10]

If you add a little more code, they will be shown on the map, and then this whole thing can be collected in the Nearest Volcanoes app :

In [15]: = GeoGraphics [{GeoPath [{Here, #}] & / @ v, GeoMarker [Here], GeoMarker [#, image: volcano-icon] & / @ v}, GeoRange -> 1.5 GeoDistance [Here , First [v]]]

Here is the code of the 3D Topography app , which shows a three-dimensional scaled map within a radius of 10 miles relative to your location:

In [16]: = ListPlot3D [GeoElevationData [GeoDisk [Here, Quantity [10, "Miles"]]], MeshFunctions -> {# 3 &}, Mesh -> 30, Background -> Black, Axes -> False, ViewPoint -> {2, 0, 3}]

Data arriving at the device


Once we made contact with Wolfram Cloud, we were able to use the real-time data contained in the Wolfram Knowledgebase. Among other things, there is data on the current position ( x , y , z , t ) of the International Space Station :

In [17]: = entity: International Space Station (satellite) ["Position"]

Given my location and using a bit of graphics in Wolfram Language, you can create an ISS Locator app :

In [18]: = Module [{pos, line, rise}, {pos, line, rise} = SatelliteData [entity: International Space Station (satellite), {"Position", "SatelliteLocationLine", "RiseTime"}];  Style [Labeled [GeoGraphics [{{Pink, AbsoluteThickness [3], GeoPath @@ line}, {Red, PointSize [.04], Point [pos]}, {Opacity [.1], Black, GeoVisibleRegion [pos]} }, GeoGridLines -> Automatic, GeoCenter -> pos, GeoRange -> "World", GeoProjection -> "Orthographic", ImageSize -> {272, 340 - 38}], Style [TemplateApply ["Next rise:` `", NumberForm [UnitConvert [DateDifference [Now, rise], "Minutes"], 3]], White, 20]], Background -> Black]]

As another example of using real-time data , you can give the Apple Quanting app code , which gives the stock price of Apple:

In [19]: = Style [TradingChart [{"AAPL", DatePlus [-90]}, {"Volume", Style ["MESASineWave", {RGBColor [1, 1, 1], RGBColor [0.46, 0.62, 0.8200000000000001 ]}], Style ["BollingerBands", RGBColor [1, 1, 1]], Style ["DoubleExponentialMovingAverage", RGBColor [1, 0.85, 0.21]]}, PerformanceGoal -> "Speed", Axes -> False, Frame -> False], Background -> Black]

Below is the code for the Market Word Cloud app, which shows the symbol of the company’s shares, the size of which is set according to changes in the price of the previous day (today Apple’s stock price has grown and Google’s stock price has fallen):

In [20]: = WordCloud [With [{c = FinancialData [#, "FractionalChange"]}, Abs [c] -> Style [#, ColorData [{"RedGreenSplit", 0.01 {-1, 1}}, c ]]] & / @ {"AAPL", "XOM", "GOOG", "MSFT", "BRK-A", "WFC", "JNJ", "GE", "WMT", "JPM"}, Background -> Black]

Below is the full currency conversion code based on your current location Currency Converter app / a>:

In [21]: = With [{home = $ GeoLocationCountry ["CurrencyUnit"]}, Style [QuantityForm [Grid [{#, "=", CurrencyConvert [#, home]} & / @ Cases [{Quantity [1, "USDollars"], Quantity [1, "Euros"], Quantity [1, "Yen"], Quantity [1, "BritishPounds"]}, Except [home]], Alignment -> Left], "Abbreviation"], White, Background -> Black, 30]]

With Wolfram Language, it’s not at all difficult to create a wide variety of applications. Here is the code for the
Sunrise / Sunset app , which displays information about sunset and dawn wherever you are:

In [22]: = {Sunrise [], Sunset []}

Setting up a more convenient display for the clock requires a little more code:

In [23]: = With [{sunfmt = Style [DateString [#, {# 2, "", "Hour12Short", ":", "Minute", "AMPMLowerCase"}], 54] &, tfmt = Round [ DateDifference [Now, #, {"Hour", "Minute"}], 5] &}, Rasterize @ Style [Column [{sunfmt [Sunrise [], "rise"], tfmt [Sunrise []], sunfmt [Sunset [], "set"], tfmt [Sunset []]}, Alignment -> Right], FontSize -> 32, Background -> Black, White]]

Wolfram Language contains real-time weather data :

In [24]: = AirTemperatureData []

Which we can display in in the form of beautiful built-in icons:

In [25]: = IconData ["AirTemperature", AirTemperatureData []]

Here is the temperature data for the last week:

In [26]: = AirTemperatureData [Here, {Now - Quantity [1, "Weeks"], Now}]

And if we add a little code, we can present it as an application with a graph of the temperature change. Temperature History app :

In [27]: = With [{temps = DeleteMissing [AirTemperatureData [Here, {Now - Quantity [1, "Weeks"], Now}] ["Values"]]}, QuantityForm [Style [Column [{Grid [{ {"Current", Last [temps]}, {"High", Max [temps]}, {"Low", Min [temps]}}, Alignment -> {{Right, Left}}], ListLinePlot [temps, ImageSize -> 312, PlotStyle -> None, Filling -> Bottom, FillingStyle -> Automatic, ColorFunction -> Function [{x, y}, Blend [{RGBColor [0.45, 0.72, 0], RGBColor [1, 0.85, 0 ]}, y]], PlotTheme -> "NoAxes"]}, Alignment -> Right], Background -> Black, 24, White], "Abbreviation"]]

Sometimes the easiest way to get the result in Wolfram Language is to simply contact Wolfram | Alpha . Here's what Wolfram | Alpha will show if you ask the system about the time it takes to get a good tan (it determines your current location): And so, we have a real-time application, the Sunburn Time app , in which Wolfram | Alpha is called from using the design in Wolfram Language (the application gives the different time it takes to get a good tan depending on the type of skin).

Wolfram | Alpha recognizes your location, knows the current UV index there, and computes how long you could safely stay out in the sun depending on your skin type



In [28]: = times = Style [QuantityForm [#, {}], 24, White, FontFamily -> "Source Sans Pro"] & / @ Rest [WolframAlpha ["sunburn time", {{"TypicalTimeToSunburn", 1 }, "ComputableData"}] [[All, 2]]];  In [29]: = Panel [Grid [Transpose [{{image: skintonesI, image: skintonesII, image: skintonesIII, image: skintonesIV, image: skintonesV, image: skintonesVI}, times}], Dividers -> {False, Center }, FrameStyle -> Gray, Spacings -> 5, Alignment -> {Center, Center}], Background -> Black]

Reports and data loading


Wolfram Language has access not only to data streams from its sources, but also to private ones; in particular - to the data from Wolfram Data Drop (see the article on Habrahabr " Wolfram Data Drop - the new Wolfram Research service ")

As a lover of collecting and analyzing personal data , I made a databin in Wolfram Data Drop, which tells me the number of unprocessed and unread messages Email. I created a scheduled task that runs in the cloud and generates a report of my unread messages. Now let's create the SW Email Backlog app , which, on demand, will send this report and display it on the watch:

Lighter orange is total number of messages;  darker orange is unread messages ...

Yes, the number of unprocessed and unread posts has recently increased at least in part due to the fact that now some additional time is spent on working on this blog.

Now everywhere you can meet databins of Wolfram Data Drop and, of course, you can make your own . From any databin, you can immediately make a clock application with a panel for displaying information. As, for example, the Company Fridge app , which receives information from a small temperature sensor located in the refrigerator in our headquarters (the cycle is caused by the compressor, and the peaks correspond to the opening of the refrigerator):

In[30]:= DateListPlot[Databin["4r4-gP4o", -300, "temp"], PlotStyle -> RGBColor[0, 0.501961, 1], Background -> Black, DateTicksFormat -> {"Hour12Short", "AMPMLowerCase"}, FrameStyle -> Directive[Black, FontColor -> White, 18], FrameLabel -> Automatic, TargetUnits -> Quantity[1, "DegreesFahrenheitDifference"], AspectRatio -> 1.11, ImageSize -> 312]["temp"]

Typically, a databin receives data from a single source or device. However, you can create a databin that receives data from an application that runs on several different devices at once.

As a simple example, let's create an application that simply shows where in the world this application was launched. Here is the complete code for the Data Droplets app, ready to be uploaded :

In[31]:= CloudDeploy[Delayed[With[{db = Databin[DatabinAdd["4rwD7T5G", 0], -20]["GeoLocations"]}, GeoGraphics[{Red, PointSize[.02], MapThread[{Opacity[#], Point[#2]} &, {Subdivide[0.15, 1, Length[db] - 1], db}]}, GeoRange -> All, GeoProjection -> "LambertAzimuthal", Background -> Black, PlotLabel -> Style["Recent Data Droplets", White, 24]]], "PNG"], "WatchApps/DataDroplets"]

This application does two things. First, when it is running, it adds the location of the device on which the application is running to the central databin in Wolfram Data Drop. And secondly, it displays a world map with the labels of the last 20 places from which the application was launched:

Data Droplets app on the watch--just touch the screen...

Realizing the application


The main reason to run applications on your watch is to be able to receive information directly from your wrist. However, you can use these applications to work with some external systems, for example, through the API.

As one very simple example, below is the full code of an application ready for unloading, which sends the owner of the application a card with a radius of one mile from its position, and sends it when the application starts:

In[32]:= CloudDeploy[Delayed[SendMail[GeoGraphics[{Opacity[.4, Red], PointSize[.05], Point[Here]}, GeoRange -> Quantity[1, "Miles"]]]; Style["Sent!", 200], "PNG"], "WatchApps/MailMyLocation", IconRules -> image:maillocationicon]

Email sent by the MailMyLocation app--log where you've been, share your location, remember where you parked...

Applications for creating other applications


Until this time, all the applications that we talked about were created from fixed fragments of Wolfram Language code that were deployed to Apple Watch. However, the Wolfram Language is a symbolic language, so manipulating application code is as easy as any other data. This means that using Wolfram Language to create and deploy applications on the fly will be very simple.

Here is a simple example for you. Let's say we want to make a clock app that gives a countdown of days until our next birthday. It would be very inconvenient to enter the date of your birthday right on the watch. But instead, the application can be placed on the phone, where the date of birth is entered, and after that it can create another application for the clock in real time, in which the countdown is for your date of birth.

Below we will enter the date of birth in the standard “ smart field ” for Wolfram Language , which works with any date format:

Run the generator app on your phone and enter your birthday...

And as soon as we click the Submit button, this application will launch the Wolfram Language code in the Wolfram Cloud, which will generate a new application with the date we specified earlier, and then this application will be deployed and launched already on our watch.

...And it deploys the generated app to the watch, ready to run

Below is the full code that required to create a Birthday Countdown app that generates new, customized apps.

In[33]:= CloudDeploy[FormFunction[{"Birthday" -> "Date"}, (CloudDeploy[Delayed[ExpressionCell[With[{count = Floor[UnitConvert[Mod[# - Today, ="1 yr"], "Day"]] &}, Style[Framed[Pane[QuantityForm[count[#Birthday], "Abbreviation"], {250, 250}, Alignment -> Center], RoundingRadius -> 50, FrameStyle -> Thick], 40, Hue[.52]]], Background -> Black], "PNG"], "WatchApps/BirthdayCountdown", IconRules -> image:cakeicon]; Style["BirthdayCountdown app generated & deployed", Larger, Background -> LightYellow]) &, "PNG"], "WatchApps/CountdownGenerator", IconRules -> image:cakeandgearicon]

And here is the result of the generated application for counting down to my birthday :

As of this writing, there are 123 days until my next birthday. How many days until your own?

You can make a wide variety of applications like the ones presented above. Here is an example application where you need to make a list of different places, after which you will create an application that displays different times for the respective places:

Enter a list of cities on your phone, and get an array of clocks for them

You can also use application generation to put yourself in the application. Here is the code for deploying other applications, the You Clock app . It allows you to take a picture of yourself with your phone and create an application that uses this picture as a clock:

In[34]:= CloudDeploy[FormFunction[{"image" -> "Image"}, (With[{hand = ImageRotate[ImagePad[ImageResize[#image, 100, Resampling -> "Gaussian"], {{0, 0}, {50, 0}}], -Pi/2]}, CloudDeploy[Delayed[ClockGauge[Now, PlotTheme -> "Minimal", GaugeMarkers -> {hand, hand, None}, Background -> Black, TicksStyle -> White, ImageSize -> 312], "PNG"], "WatchApps/YouClock", IconRules -> "YouClock"]]; Style["YouClock app deployed", 50]) &, "PNG"], "WatchApps/YouClockGenerator", IconRules -> "YCG"]

And here I am as the hands of a clock

In fact, you can approach this process even more generally: you can create applications that generate other applications, and they, in turn, also create your own apps!

More than i expected


When I decided to use Wolfram Language to create applications on the Apple Watch, I did not yet know how this would happen. Will the entire application deployment cycle for watches run smoothly enough? Will those applications that are so easy to create using the Wolfram Language look good on the watch?

I'm glad to say that everything went much better than I expected. Apple Watch appeared recently, so there were some questions about the deployment of applications on them, but they were resolved very quickly. But it became clear that many good applications for Apple Watch can be created even with a small amount of Wolfram Language code (tweet-a-watch-app? See article on Habrahabr "Компания Wolfram Research открыла сервис Tweet-a-Program: интересных программ на языке Wolfram Language, длина которых не превышает 140 символов"). При этом, меня весьма впечатлил тот факт, что менее, чем за один день работы, мне удалось разработать 25 полноценных приложений.

Конечно, все это стало возможно именно благодаря всей совокупности технологий Wolfram Language, которые разрабатывались почти 30 лет. И очень приятно наблюдать, как хорошо работают разработанные нами средства автоматизации, которые позволили претворить в жизнь ещё одну интересную идею — приложения для часов.

It's great to program in the Wolfram Language and watch the results of what happened - as in the case of writing applications for the Apple Watch. But in the end, more important is how convenient it is for the implementation of many different goals and ideas. The code presented here is a good help to figure it out. There are many areas of activity. You can create many useful, and just funny applications. The important thing is that Wolfram Language makes it easy to create applications for the Apple Watch that it can turn into everyday routine - this is another place where Wolfram Language functionality can be brought.

Also popular now: