Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
blocks:app-note:interacting-from-a-custom-web-page [2019-12-02 14:47]
admin created
blocks:app-note:interacting-from-a-custom-web-page [2023-08-01 21:07] (current)
admin [Installation]
Line 1: Line 1:
-====== Interacting with Blocks from a Custom Web Page ======+====== Advanced Interaction from a Custom Web Page ======
  
-This application note shows how your custom web page can talk to Blocks server in various ways, including:+The application note titled "[[blocks:app-note:basic-interaction-from-a-custom-web-page|Basic Interaction from Custom Web Page]]" desicribes a simple form of interaction (starting a named task). However, some applications ned a tighter integration, with direct read/write. and rea-ltime access to the inner workings of Blocls. This application note shows how such advanced integration can be accomplished, including:
  
-  * Making a simple HTTP request to Blocks, triggering a custom action on the server and passing a result back to the web page.+  * Making HTTP requests to Blocks, triggering a custom action on the server and passing a result back to the web page.
   * Setting any property in your Blocks system from the web page.   * Setting any property in your Blocks system from the web page.
   * Subscribing to property changes to keep your web page in the loop, regardless of how the property was changed.   * Subscribing to property changes to keep your web page in the loop, regardless of how the property was changed.
Line 13: Line 13:
 ===== Installation ===== ===== Installation =====
  
-Follow these steps to install this example on your own Blocks computer.+You need a computer with a running blocks server and a web browser to run this application note. Here's the {{ :blocks:app-note:custom-web-page:interactingfromcustomwebpage_v2.zip| Blocks root}} for this application noteSee the the [[blocks:app-note:start|general setup section]] for details on downloading and installation. Once that general setup is done, follow these steps to run the application note:
  
-  - Install the enclosed {{:blocks:app-note:custom-web-page:pixilab-blocks-root.zip|Blocks root folder}} in your home directory (or use a PIXILAB-Blocks-config.yml file in your home directory to point at this root folder, as described [[blocks:server_configuration_file|here]]). 
   - Start Blocks.   - Start Blocks.
-  - Open the editor using the Admin button.+  - Open the Blocks editor using the Admin button
 +  - Log in using the proper credentials (default user name is //admin// and the password is //pixi//).
   - Open a second browser window to the same address as the editor window, but replace /edit/xxx with /spot. This opens a test spot display.   - Open a second browser window to the same address as the editor window, but replace /edit/xxx with /spot. This opens a test spot display.
   - Double-click TheSpot in the editor and reassign it to the ID shown in your separate spot window. This will be your test spot, controlled from the custom app.   - Double-click TheSpot in the editor and reassign it to the ID shown in your separate spot window. This will be your test spot, controlled from the custom app.
Line 32: Line 32:
 Type some text into the text area titled "Text to append", then click the "Append" button. Now look into the script/files directory inside the blocks root installed above, and you'll find a text file named test.txt, with the text you just typed appended. Type some text into the text area titled "Text to append", then click the "Append" button. Now look into the script/files directory inside the blocks root installed above, and you'll find a text file named test.txt, with the text you just typed appended.
  
-Finally, press the "Generate" button. After a brief pause, a QR code appears below the field with the text entered into the field next to the Generate button. This image is stored in the file located at public/custom/qt.png, from where the custom web page retrieves it.+Finally, press the "Generate" button. After a brief pause, a QR code appears below the field with the text entered into the field next to the Generate button. This image is stored in the file located at public/custom/qr.png, from where the custom web page retrieves it.
  
  
Line 86: Line 86:
 </code> </code>
  
-This call returns a pubSubPeer that manages the websocket connection to the server. The constructor call takes an optional callback function, in the example above called //onServerConnectionChange//, which in the example looks like this:+This call returns a pubSubPeer that manages the websocket connection to the server.  
 + 
 +The example shown above assumes that the custom web page is served by the Blocks server. If it is served from some other server, you must add a //second// parameter that is the URL for accessing the websocket endpoint on your Blocks server, like this; 
 + 
 +<code> 
 +const pubSubPeer = new PIXILAB_BLOCKS.PubSubPeer( 
 + onServerConnectionChange, 
 + "ws://<nameOrIp><:nonStandardPort>/rpc/pub-sub" 
 +); 
 +</code> 
 + 
 +Replace <nameOrIp> with the IP number or resolvable name to your Blocks server. If you're running on a non-standard port, append the port number separated by a colon. Hence, if your Blocks server rus on 10.1.0.10 using the standard port, the call would look like this: 
 + 
 +<code> 
 +const pubSubPeer = new PIXILAB_BLOCKS.PubSubPeer( 
 + onServerConnectionChange, 
 + "ws://10.1.0.10/rpc/pub-sub" 
 +); 
 +</code> 
 + 
 +The first parameter of the PubSubPeer constructor call is an optional callback function, in the example above called //onServerConnectionChange//, which in the sample code looks like this:
  
 <code> <code>
Line 105: Line 125:
  
   - The full path to the property to set. This is the same path as used in, e.g., a Task trigger. In the example, this is "Spot.TheSpot.block", setting the current block of the Spot named TheSpot.   - The full path to the property to set. This is the same path as used in, e.g., a Task trigger. In the example, this is "Spot.TheSpot.block", setting the current block of the Spot named TheSpot.
-  The value  to set the property to. In this example, the value is a string specifying a block name, as taken from the dropdown list, including "Main/Block1" and "Main/Block2". The name must include both the group name and the block name, separated by a slash.+  The value  to set the property to. In this example, the value is a string specifying a block name, as taken from the dropdown list, including "Main/Block1" and "Main/Block2". The name must include both the group name and the block name, separated by a slash.
  
 :!: The type of the second parameter must match the value type of the property. For instance, if the property is numeric (such as the volume level of a Spot), you must pass a number here. :!: The type of the second parameter must match the value type of the property. For instance, if the property is numeric (such as the volume level of a Spot), you must pass a number here.
Line 112: Line 132:
 === pubSubPeer.add === === pubSubPeer.add ===
  
-This is similar to the //set// function, and takes the same two parameters. However, it may only be used with numeric values. You can use it to increase or decrease (by passing a negative valuenumeric property, such as a volume value. This is often simpler for such incremental adjustments than maintaining a subscription to the value in order to do the calculation on the client side based on the current value and then using the //set// function to change the value.+This is similar to the //set// function, and takes the same two parameters. When used with numeric property, the value you specify will be added to the current value. Pass a negative value to subtract. When used with string property, the value will be //appended// (concatenated) to the current string value.  
 + 
 +The //add// methid is often simpler for such incremental adjustments than maintaining a subscription to the value in order to do the calculation on the client side based on the current value and then using the //set// function to change the value.
  
  
Line 119: Line 141:
 Subscribe to the value of the specified property. It accepts the following parameters: Subscribe to the value of the specified property. It accepts the following parameters:
  
-  The full path to the property to subscribe to (see above). +  The full path to the property to subscribe to (see above). 
-  - A callback function that will be called whenever the value of the property changes.+  - An object containing a single function named dataReceived, that will be called whenever the value of the property changes.
  
-The //subscribe// function returns the current value of the property if already known. If not, it returns //undefined// and you'll be notified by the callback function once the value is known.+The //subscribe// function returns the current value of the property if already known. If not, it returns //undefined// and you'll be notified by the dataReceived function being called once the value arrives.
  
 :!: You should pay attention to any initial value returned by the //subscribe// function, treating it the same way as any value change provided through the callback function. See main.js for an example of how this can be accomplished. :!: You should pay attention to any initial value returned by the //subscribe// function, treating it the same way as any value change provided through the callback function. See main.js for an example of how this can be accomplished.
Line 129: Line 151:
 === pubSubPeer.unsubscribe === === pubSubPeer.unsubscribe ===
  
-This function allows you to terminate any value subscription initiated by the //subscribe// fuynction if you're no longer interested in changes of a property. It takes the following parameters:+This function allows you to terminate any value subscription initiated by the //subscribe// function if you're no longer interested in changes of a property. It takes the following parameters:
  
-  The full path to the property to subscribe to (see above). +  The full path to the property to subscribe to (see above). 
-  - The same callback function as passed to the //subscribe// function.+  - The very same object as passed to the //subscribe// function.
  
-The main.js example script does not use this function.+The main.js example shows how to use this function, as triggered by the //Unscubscribe// button.
  
  
Line 214: Line 236:
  
 Once these three steps are done, the promise is resolved with the name of the generated image file, now available under /public on the Blocks server. If any error occurs, the promise is instead rejected, passing an error code back as the HTTP POST request's result. Upon receiving the result, the custom web page's //main.js// script proceeds by displaying the resulting image. Note that the //fetch// function, called to make the HTTP request from the client side, also returns a //Promise// object, eventually resolved with the result of the operation once its //then// function is called. Once these three steps are done, the promise is resolved with the name of the generated image file, now available under /public on the Blocks server. If any error occurs, the promise is instead rejected, passing an error code back as the HTTP POST request's result. Upon receiving the result, the custom web page's //main.js// script proceeds by displaying the resulting image. Note that the //fetch// function, called to make the HTTP request from the client side, also returns a //Promise// object, eventually resolved with the result of the operation once its //then// function is called.
 +