{"id":1891,"date":"2015-05-13T13:00:54","date_gmt":"2015-05-13T03:00:54","guid":{"rendered":"http:\/\/www.malcolmgroves.com\/blog\/?p=1891"},"modified":"2015-06-02T13:25:48","modified_gmt":"2015-06-02T03:25:48","slug":"app-tethering-sharing-persistent-resources-part-1","status":"publish","type":"post","link":"http:\/\/www.malcolmgroves.com\/blog\/?p=1891","title":{"rendered":"App Tethering : Sharing Persistent Resources Part 1"},"content":{"rendered":"<p><a href=\"http:\/\/www.malcolmgroves.com\/blog\/?p=1854\">In the last post, we went through one method of discovery, AutoConnect, and then built a couple of apps that used AutoConnect to find, authenticate and pair with each other.<\/a><\/p>\n<p>That&#8217;s fine, but there&#8217;s not a lot of point in having two apps connected to each other unless they can interact. In App Tethering, that interaction comes in two forms: sharing resources and sharing actions. In this article we&#8217;re going to start looking at sharing resources.<!--more--><\/p>\n<p>Resources in App Tethering are simply\u00a0pieces of data you wish to share with remote apps. The key things to understand about Resources are:<\/p>\n<ul>\n<li>All resources have a type, either:\n<ul>\n<li>Data &#8211; strings, booleans and numbers (eg. Integer, Single, Double)<\/li>\n<li>Streams &#8211; everything else. Could be an image, could be a dataset, could be a file, whatever. If you can get it into a TStream somehow, you can share it.<\/li>\n<\/ul>\n<\/li>\n<li>All resources have a lifetime:\n<ul>\n<li>Persistent &#8211; a resource you create at design-time, rather like creating a persistent TField in a database app. The implications are a little different though, the biggest being that a remote app can subscribe to a persistent resource and be notified whenever it changes. You don&#8217;t know if zero, one or 100 apps are subscribed to your resource, you simply update the value locally and move on.<\/li>\n<li>Transient &#8211; a transient resource is one you send from code. Rather than a resource that remote apps can subscribe to, you send a transient resource to a specific remote app. If you want to send it to three remote apps, you send it three times.<\/li>\n<\/ul>\n<\/li>\n<li>All resources are one way\n<ul>\n<li>This one took me a little while to realise, but let&#8217;s say you have a persistent resource in App1, and App2 is subscribed to it. If the value changes in App1, App2 will be notified and receive the new value. However, if App2 changes that value, it does not flow back to App1. The resource is one way. (We&#8217;ll look at how to deal with this shortly).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>To be honest, that&#8217;s probably enough to get started, so let&#8217;s update our two apps from last post to share a\u00a0resource.<\/p>\n<p>Open up your App1 and App2 projects from last time, and bring up both main forms. As a first step, we&#8217;re going to share a string resource from App1 to App2. Bring up App1&#8217;s main form and select the TTetheringAppProfile component. You&#8217;ll notice it has a Resources property, so bring up the property editor for that and create a new resource. Set its name to SomeText. Also note its ResType property is set to Data (not Stream), its IsPublic property is set to True (meaning it will be available to remote apps) and its Kind property is set to Shared.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1893\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.1.png\" alt=\"\" width=\"340\" height=\"373\" srcset=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.1.png 340w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.1-273x300.png 273w\" sizes=\"auto, (max-width: 340px) 100vw, 340px\" \/><\/p>\n<p>The last one, Kind, might need some explaining. Remember I said that resources were one way: there is a sender and one or more receivers. Setting a resource&#8217;s Kind property to Shared means you&#8217;re the sender. When we get to App2 we&#8217;ll see the receiver side, but let&#8217;s finish off App1 first.<\/p>\n<p>Congrats, you just created a persistent resource. However, we need some way to get a value into this resource, so go back to the form in App1 and drop down a TEdit. Right-click on it and select the Add Item | TEditButton menu. This will add a button on the right end of the edit. Select that button and set its Text property to Update. Then select the TEdit and set it&#8217;s TextPrompt to SomeText. Your form should look like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1896\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.21.png\" alt=\"\" width=\"399\" height=\"171\" srcset=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.21.png 399w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.21-300x129.png 300w\" sizes=\"auto, (max-width: 399px) 100vw, 399px\" \/><\/p>\n<p>Double-click on the\u00a0Update button and put the following code in the OnClick event.<\/p>\n<p>For Delphi:<\/p>\n<pre class=\"lang:delphi decode:true\">procedure TForm3.EditButton1Click(Sender: TObject);\r\nbegin\r\n TetheringAppProfile1.Resources.FindByName('SomeText').Value := Edit1.Text;\r\nend;<\/pre>\n<p>For C++:<\/p>\n<pre class=\"lang:c++ decode:true \">void __fastcall TForm1::EditButton1Click(TObject *Sender)\r\n{\r\n  TetheringAppProfile1-&gt;Resources-&gt;FindByName(\"SomeText\")-&gt;Value = \r\n    TResourceValue::_op_Implicit(Edit1-&gt;Text);\r\n}<\/pre>\n<p>If we ran App1 now, typed some text into the edit box and clicked Update, our persistent resource would be updated and any subscribed remote apps would be notified. However, right now we have no remote apps subscribed, so let&#8217;s fix that.<\/p>\n<p>Bring up the main form of App2. Drop down another Label and then go to the TetheringAppProfile component and add a new resource to its Resources property. Make sure its name is the same as the one we just added to App1, that is, SomeText. Leave the ResType set to Data and IsPublic set to True, but change the Kind property to Mirror. This will cause a subscription to be setup between this local resource and the remote shared resource of the same name in App1. Anytime the value changes in App1, we&#8217;ll be notified.<\/p>\n<p>How will we be notified? The Resource has an OnResourceReceived event where we can put code that will run when we are notified\u00a0of a change. Note, don&#8217;t confuse this with the OnResourceReceived event of the TetheringAppProfile component. We&#8217;ll cover that one\u00a0later. What we&#8217;re talking about here is the OnResourceReceived event of the persistent resource we just created.<\/p>\n<p>Add an event handler for the resource&#8217;s OnResourceReceived event with the following code.<\/p>\n<p>For Delphi:<\/p>\n<pre class=\"lang:delphi decode:true\">procedure TForm4.TetheringAppProfile1Resources0ResourceReceived(\r\nconst Sender: TObject; const AResource: TRemoteResource);\r\nbegin\r\n  Label2.Text := AResource.Value.AsString;\r\nend;<\/pre>\n<p>For C++:<\/p>\n<pre class=\"lang:c++ decode:true \">void __fastcall TForm2::TetheringAppProfile1Resources0ResourceReceived(TObject * const Sender,\r\nTRemoteResource * const AResource)\r\n{\r\n  Label2-&gt;Text = AResource-&gt;Value.AsString;\r\n}<\/pre>\n<p>AResource is a parameter passed into our event handler containing the new value of the resource and we are extracting its value as a string and putting it into the Text property of the label we dropped on the form.<\/p>\n<p>Now we should be able to run both App1 and App2, click the connect button, then type some text into the edit box and click Share and have it appear in the label in App2. Change the text in the edit again and click Share and it should be updated again. I&#8217;ll give you a minute to have a little play.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1898\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.3.png\" alt=\"\" width=\"484\" height=\"449\" srcset=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.3.png 484w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.3-300x278.png 300w\" sizes=\"auto, (max-width: 484px) 100vw, 484px\" \/><\/p>\n<p>While in this demo I&#8217;m simply displaying the resources in the UI, that doesn&#8217;t mean you have to. Maybe you are receiving the updated resource and inserting it into a database. Or posting it via REST to salesforce. Doesn&#8217;t matter. Once you have it in code you can do whatever you want with it.<\/p>\n<p>Close all your apps down, then run App1 again and start a few copies of App2. Click Connect in App1 and it should find all the App2&#8217;s running. Note the code in App1 that displays the ID of App2 doesn&#8217;t handle the case of multiple App2&#8217;s, but you should see all the App2&#8217;s showing the Identifier of App1 in their label. Now share some text from App1 and you should see all your App2&#8217;s receive it. For the little amount of work we&#8217;ve actually done building these apps, I think that&#8217;s pretty cool.<\/p>\n<p>Before we wrap up for this post, let&#8217;s look at the flow of events and network traffic for this example. It&#8217;s pretty simple, but humour me.<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<div><u><b>App 1<\/b><\/u><\/div>\n<\/td>\n<td>\n<div><u><b>Network<\/b><\/u><\/div>\n<\/td>\n<td>\n<div><u><b>App 2<\/b><\/u><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<div>Resources.FindByName(&#8216;SomeText&#8217;).Value := Edit1.Text<\/div>\n<div><\/div>\n<\/td>\n<td><img loading=\"lazy\" decoding=\"async\" class=\"alignleft noshadow size-full wp-image-1860\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/04\/rightarrow.png\" alt=\"UDP Point to Point\" width=\"40\" height=\"20\" \/>Resource Updated\u00a0(UDP Point to Point)<\/td>\n<td>Resource[0].OnResourceReceived<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>I told you it was simple, but a few\u00a0things I want to call your attention to that will matter later on:<\/p>\n<ul>\n<li>The notification is still going out on the network via UDP Point-to-Point.<\/li>\n<li>The new value is actually carried in the notification message itself (there is no further chatter between them as App2 requests the value, etc)<\/li>\n<li>App2 doesn&#8217;t send back any acknowledgement. It&#8217;s basically send and forget.<\/li>\n<\/ul>\n<p>Here&#8217;s a network dump of the actual network packet:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1902\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.4.png\" alt=\"\" width=\"600\" height=\"189\" srcset=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.4.png 600w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.4-300x95.png 300w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2015\/05\/tethering3.4-535x169.png 535w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>This is from an earlier run when the text I sent was &#8220;Hello Peers&#8221;, but you can see on the right hand side that it is a TetheringNotification, it contains the Identifier of the TetheringManager. It then has the constant NOT_UPDRES, short\u00a0for NOTification of UPDated RESource, followed by the Identifier of the resource that was updated. Lastly, it has some metadata about the resource (ResourceType, DataType) and finally\u00a0the new value of the resource itself, in this case &#8220;Hello Peers&#8221;.<\/p>\n<p>Why is this important? <a href=\"http:\/\/www.malcolmgroves.com\/blog\/?p=1935\">Well, next post we&#8217;ll continue on the path of Persistent Resources, looking at Streams, and the network behaviour for them looks very different indeed<\/a>.<\/p>\n<p>You can get the source for the sample apps at this stage of the series, in both <a href=\"https:\/\/github.com\/malcolmgroves\/tethering_series_cpp\/releases\/tag\/3.PersistentResourcesPart1\" target=\"_blank\">C++<\/a> and <a href=\"https:\/\/github.com\/malcolmgroves\/tethering_series_delphi\/releases\/tag\/3.PersistentResourcesPart1\" target=\"_blank\">Delphi<\/a>, but to really understand what is going on there is no substitute for building the apps yourself. They aren&#8217;t that big.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last post, we went through one method of discovery, AutoConnect, and then built a couple of apps that used AutoConnect to find, authenticate and pair with each other. That&#8217;s fine, but there&#8217;s not a lot of point in having two apps connected to each other unless they can interact. In App Tethering, that [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[113,119],"tags":[48],"class_list":["post-1891","post","type-post","status-publish","format-standard","hentry","category-apptethering","category-distributed-systems","tag-embarcadero"],"_links":{"self":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1891","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1891"}],"version-history":[{"count":19,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1891\/revisions"}],"predecessor-version":[{"id":2023,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1891\/revisions\/2023"}],"wp:attachment":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1891"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1891"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1891"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}