Networking

We have described the use of Node.js for an echo server in the previous section. For this demonstration of real-time updating we use the socket-io and node-static packages and recommend for the Raspberry Pi version 0.10.25 of Node.js (for which we provide annotated installation instructions). Our example is based on André Mussche's server-side Node.js tutorial that warrants a few additional notes in the next section. You will find any .pas units that are not provided with Smart Mobile Studio in the GitHub pages that André links to from his tutorial. Our client-server demo is intended to be run on a local network comprising PCs and/or Raspberry Pi computers rather than on Heroku.

Server-side Node.js by André Mussche

You can try the demo by pointing browsers at http://smsnodejstest.herokuapp.com/index.html. Be prepared for a short delay if the server has not been used recently.

In order to reproduce the demo, you should find the following points helpful.
  • When testing locally, port 80 may already be in use so try another such as 8079.
  • In order to use socketio.pas in the client, copy it to the project folder and add it to the project. (Right click on Unit1 in the Project manager, select menu item Add > Add External Source(s)..., select the file and click the Open button).
  • The code in socket.io.Core.pas is commented out. You can remove it from the uses clause in the file socket.io.pas that is used by the server.
  • Since the tutorial was written, original versions of Node.js files have been superseded. We used this client version of socket.io.js. Rename it to socketio, put it in the client project folder and it will be copied to the lib folder; socketioclient.pas includes the line {$R 'file:socketio.js'}. Remember to copy the lib folder if you copy the client HTML file to another location for download by the server.
  • The server will not display a message (other than 'Server running at ...') until a button in a client is clicked.
  • The initial message to the client upon connection is not handled by the client.
  • For those of you trying Heroku, see our notes on getting started. (This page is downloaded by our server on Heroku that we wrote in Smart Pascal with the help of André's tutorial).

Smart Pascal Code of Server

Replace the code of a new Node.js project named ButtonSizeServer with the following. (This is for a server stated to be running at the IP address 192.168.0.4 but it will run at other addresses provided that Node.js is installed on the computer). You can compare this code with a JavaScript version.

unit Unit1;

interface

type
  TServer = class
  private
    ConnectionNum := 0;
  public
    procedure Run;
  end;

implementation

uses
  NodeJS.Core, NodeJS.http, Node_Static, socket.io;

procedure TServer.Run;
begin
  var fileserver := TNodeStaticServer.Create('./public');
  //start http server
  var server: JServer := http.createServer(
    procedure(request: JServerRequest; response: JServerResponse)
    begin
      Console.log('http request: ' + request.url);
      if request.url = '/' then
        request.url := '/ButtonSizeClient.html';
      fileserver.serve(request, response);
    end);
  server.listen(8079, '');
  Console.log('Server running at http://192.168.0.4:8079');

  var value := 0;
  var io := socketio().listen(server);
  io.sockets.on('connection',    // waiting for connections
    procedure(socket: JSocketIO)
    begin
      ConnectionNum += 1;
      socket.emit('dataConnection', [ConnectionNum]);  // pushes connection number to client upon connection
      socket.on('requestFromClient',  // waiting for a special request from the client
        procedure(data: Variant; callback: JSocketIODataFunction)
        begin
          Console.log('Received from client: ' + data);
          value := data;
          if value > 500 then
            value := 80;
          io.sockets.emit('dataFromServer', [value]);  //send to all clients
        end);
    end);
end;

end.    

Smart Pascal Code of Client Form

The form consists of only a label (elongated) in the top left corner and a button immediately under it. The OnClick event of the button is W3Button1Click.

unit Form1;

interface

uses
  SmartCL.System, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms,
  SmartCL.Fonts, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Button,
  SmartCL.Controls.Label, socketioclient;

type
  TForm1 = class(TW3Form)
    procedure W3Button1Click(Sender: TObject);
  private
    FSocket: JSocketIO;
    {$I 'Form1:intf'}
  protected
    procedure InitializeObject; override;
  end;

implementation

procedure TForm1.W3Button1Click(Sender: TObject);
begin
  FSocket.emit('requestFromClient', [W3Button1.Width + 20],
               lambda end); // Concise code for empty callback
end;

procedure TForm1.InitializeObject;
begin
  inherited;
  {$I 'Form1:impl'}
  FSocket := socketio.connect('http://192.168.0.4:8079');
  FSocket.on('dataConnection',
    procedure(aData: variant)
    begin
      W3Label1.Caption := 'Connection number: ' + aData;
    end);
  FSocket.on('dataFromServer',
    procedure(aData: variant)
    begin
      W3Button1.Width := aData;
    end);
end;

initialization
  Forms.RegisterForm({$I %FILE%}, TForm1);
end.    

Set-up with the server on a PC

  1. Install a recent version of Node.js, change directory to that which will contain ButtonSizeServer.js, and install the required modules with npm install socket.io and npm install node-static.
  2. A folder named public on the server should be created in the output folder (or wherever you are going to put ButtonSizeServer.js.
  3. Copy ButtonSizeServer.js to where you will use it (if you are not running it from the output folder).
  4. Copy ButtonSizeClient.html and the lib folder to the public folder.
  5. Change directory in the Command Prompt to that containing ButtonSizeServer.js.
  6. Start the server with node ButtonSizeServer.
  7. Point browsers at http://192.168.0.4/ButtonSizeClient.html and click the button in each.

Set-up with the server on a Raspberry Pi

  1. Install v0.10.25 of Node.js as detailed here.
  2. In the LXTerminal, change directory to where you will copy ButtonSizeServer.js. We show instructions for use of the /var/www folder on a Pi with IP address 192.168.0.6.
  3. Type the command /opt/node/bin/npm install io-socket and wait for much logging of the installation.
  4. Type the command /opt/node/bin/npm install node-static (much quicker).
  5. Change the appropriate line in the server code to Console.log('Server running at http://192.168.0.4:8079'); and recompile.
  6. Copy ButtonSizeServer.js to the /var/www folder.
  7. Create a folder named public within the /var/www folder.
  8. Copy ButtonSizeClient.html and its lib folder to the public folder.
  9. Start the server with node ButtonSizeServer.
  10. Point browsers at http://192.168.0.6/ButtonSizeClient.html and click the button in each.

 

Programming - a skill for life!

Developing graphical web pages including 3D, input from keyboard and mouse and storing and loading data