Volume 10

Chapter 64

364 - ToDo List 2016-05-27

The latest changes to the Spectrum Analyzer server seem to be working well so I now have to go back and clean up some of the mess I made along the way.

  1. Make Special Test come up rather than <none> <NONE> on start up
  2. Bin Shift does not seem to be working correctly
  3. Add Try/Except/Finally to the Port select on the receiver and the antenna.

363 - Setup dbForge Studio to my liking 2016-05-26

I make heavy use of the dbForge Studio application from DevArt. Its great for editing and designing MySQL tables and for maintance of the database used at SETI Net.

I am fussy about the layout of the tool and can never remember how to set it up the way I like. This is the process:

  1. Select 'Tools -> Options' from the main menu. The 'Options' window opens.
  2. Navigate to the 'Environments -> Documents -> Object editors' branch.
  3. Select the 'One main document view' radio-button.
  4. Navigate to the 'Database Explorer -> General' branch.
  5. Select the 'Retrieve data' radio-button.
  6. Click 'OK'

362 - Fix Freeze on RO Objects 2016-05-25

After much screwing around I *finally* ask the good folks at RemObjects Software for help. I make heavy use of their technology for remote process control of the SETI Net Spectrum Analyzer over HTTP and it was throwing fits..

The problem was that the RO Server (SpecAna.exe) would freeze up when I touched it with the mouse while it was exchanging messages with the client (SETI.exe). They quickly pointed out that the messages launched from background threads need to make use of the main thread and therefor must be made 'Thread Safe'.

This is the working example of message exchange in the server that solves the problem:


procedure TSpecAna.setPaused(value: Boolean);
const
WM_SETPAUSE_MESSAGE = WM_APP + 1; var OnOff: String; p: pChar; begin if value then OnOff := 'true' else OnOff := 'false'; GetMem(p, (Length(OnOff) + 1) * SizeOf(Char)); Move(OnOff[1], p^, (Length(OnOff) + 1) * SizeOf(Char)); PostMessage(Handle, WM_SETPAUSE_MESSAGE, 0, integer(p)); end; procedure TSpecAna.WMsetPause(var MESSAGE: TMessage) { message WM_SETPAUSE_MESSAGE }; var p: pChar; begin try p := pChar(Message.LParam); if p = 'true' then if p = 'true' then begin swPaused.State := tssOn; AudioIn.Paused := True end else begin swPaused.State := tssOff; AudioIn.Paused := False; end; Freemem(p); except on E: Exception do Memo.Lines.Add(E.ClassName + ': ' + E.MESSAGE); end; end;

Notice that this example does a clumsy job of sending a string in the message when it really should be a boolean. That is the next task.

The next day I asked the people on StackOverFlow how I could POST and recover boolean and integer. The answer came back.


This task is much simpler than string sending.

You don't need to allocate memory for these types, because message parameters are already Integer, and Boolean needs just simple casting.

PostMessage(Handle, WM_MY_MESSAGE, IntegerParam, Integer(BooleanParam));
  ....  
//in WM_MY_MESSAGE handler:  
   IntVar := Message.WParam; 
    BooleanVar := Boolean(Message.WParam);
                

That solves the problem.

361 - Rebuilding File Manager XML bindings 2016-12-30

These are the steps necessary to modify the SML schema file and then rebuild the XML data bindings - Updated.

Please Note: These instructions have been moved to the Schema page and are maintained there from now on.

360 - ToDo list 2016-04-09

Always a good idea to keep a list - don't you think.

  1. Sort out Status capture SpecAna causing server lockout. Might be as simple as increasing the timeout.
  2. Add new SpecAna Server parameters to the SML and show in the Status update
  3. Add new SpecAna Server parameters to the File Manager
  4. Looks like chirp is not working correctly - not showing up on Control Panel
  5. Add estimate to complet scan in minutes to the Status
  6. Start additional search filter functions. High amplitude, Antenna move off axis, hit width in bins (over about 10 Hz skip)
  7. Find better way to display SML in the JavaScript
  8. Clean up HowStuffWorks directory
  9. Set upper limit on frame buffer to 50,000 scans (about 3 GBytes).
  10. Fix Status Station SETI Net SETI Net
  11. Fix Status Recording On.
  12. Add Revert to enterSetup at Scan End check box.

359 - RemoteObjects Building Code First Client/Servers 2016-03-21

This is a work flow I use for building a code first client/server and making changes along the way..

Do these steps:

  1. Build new Client/Server - File|New|Other. Select VCL Standalone (Code First). OK. OK.
  2. Build the server then launch the server directly (not from the UI). Set Windows Firewall to allow this new project access.
  3. Set newProjectClient.exe as default project
  4. Select Tools|Remoting SDK & Data Abstract|'Connect to Remoting SDK Server' menu item
  5. Select 'Import a Service from the Web by its URL' the default is the servers URL. It should be http://localhost:8099/bin
  6. Hit Import - This should create a file in the client group called 'NewLibrary.remoteRODL'

After these steps the following files will have been generated for the client:

  • NewLibrary.remoteRODL
  • NewLibrary_Intf.pas
  • NewLibrary_ServerAccess.pas

Verify that the client will now compile correctly

Now add some service to the Server:

  1. Open the NewService_impl.pas file in the server
  2. Add the Sum function

const
  __ServiceName = 'NewService';

type

  [ROService(__ServiceName)]
  TNewService = class(TRORemoteDataModule)
  private
  public
    [ROServiceMethod]
    function Sum(const A: integer; const B: integer): integer;
   end;

implementation

{ %CLASSGROUP 'System.Classes.TPersistent' }
{$R *.dfm}

function TNewService.Sum(const A: integer; const B: integer): integer;
begin
  result := A + B;
end;

Note the [ROServiceMethod]

Each function must have this above it.

Then add the call to the service in the client as in:


var
  ClientForm: TClientForm;

implementation

uses NewLibrary_Intf;

{$R *.dfm}

procedure TClientForm.Button1Click(Sender: TObject);
var
  service: INewService;
begin
  Screen.Cursor := crHourGlass;
  try
    service := CoNewService.Create(ROMessage, ROChannel);
    Edit1.Text := '';
    Edit1.Repaint();
    Edit1.Text := IntToStr(service.Sum(555, 111));
  finally
    service := nil;
    Screen.Cursor := crDefault;
  end; { try/finally }
end;
end.

Later when you want to regenerate the _Intf.pas for the client you:

  • Ensure the server is running
  • Right click on NewLibrary.remoteRODL file
  • Select:  Update Interface file(s)

This will keep your autogenerated files up to date.

Tip: I open two instances of the RAD studio IDE and put client on the left and server on the right. That makes work flow much cleaner.

358 - Selecting Server Protocol and Message Type 2016-03-10

Channels

  • HTTP - More overhead, proxy friendly, savable to third party clients, allows Smart Services. Most common choice
  • Super HTTP - Same as HTTP plus keeps channel open, Callback events, Asynchronous capabilities, Allows Push
  • TCP - Raw TCP sockets, minimal overhead, not proxy-friendly, allows third party clients
  • Super TCP - Same as TCP plus keeps channel open, Callback events, Asynchronous capabilities, Allows Push
  • Local Channel - Como within same application
  • Named Pipes - Over LAN without TCP/IP
  • UDP - Lightweight packet-based. including the broadcast version
  • DLL Channel - Local App. talks to services in a DLL
  • Email - POP3/SMTP Como
  • WinMessage - Interprocess commo on same computer

Message Types

  • Bin - Proprietary. Supports Callback events
  • SOAP - Most complex and most flexible, XMLbased, high overhead.
  • XmlRpc - XML-based but simpler than SOAP
  • Post - Compatible with HTML forms
  • JSON - Capable of complex structures, supports Callback events

Channel Options

  • WinInet
  • Indy
  • Synapse
  • NetHttp
  • Compression
  • Envelopes
  • Keep-Alive
  • gzip encoding

After working with RemoteObjects I have decided on the following layout:

  • Messaage type - JSON
  • No Compression
  • No envelopes
  • Channel protocol - HTTP
  • Indy
  • Keep-Alive
  • No gzip encoding

This combination seems to be the simplest and most reliable way to start.

357 - Reorganizing for 64 Bit (again) 2016-03-07

In chapter 63 item 356 I said that I ran into a problem with moving the database to 64 bit. After struggling with it for a very long time I found that I must be on the bleeding edge of this technology and might as well wait for the answer to come to me. Trouble is I still need to come up with a 64 bit solution to building very large arrays.

The current approach is to leave the entire application 32 bit and only move the Spectrum Analyzer to 64 bit. This will leave the DLL for antenna control at 32 bits, (which works fine and why screw with it) and the SQL database system at 32 bits which also works fine and therefore doesn't require cutting myself to pieces on that edge.

So the first step is to build a 32 bit SETI application that collects all the calls to the Spectrum Analyzer into one group of Getters and Setters so that they can be dealt with collectively and added to a 32 bit SETI Client and 64 bit SpecAna Server .

These are the functions that must be served.

Interface for the Spectrum Analyzer
Getters Service Implementation
getSpecAnaBinShift SetupStateUpdate
getSpecAnaRunning

OffStateUpdate

SetupStateUpdate

ScanStateUpdate

HitStateUpdate

getSpecAnaHzPerBin SetupStateUpdate
getSpecAnaInUse SetupStateUpdate
getSpecAnaFFTSize SetupStateUpdate
getSpecAnaCapture SetupStateUpdate
getSpecAnaVisible SetupStateUpdate
getSpecAnaWaterRunning SetupStateUpdate
getSpecAnaWaterVisible SetupStateUpdate
getSpecAnaDetecting SetupStateUpdate
getSpecAnaETHit HitStateUpdate
getSpecAnaETRFFreq HitStateUpdate
getSpecAnaETAmplitude HitStateUpdate
getSpecAnaETAmbiant HitStateUpdate
getSpecAnaETBin HitStateUpdate
getSpecAnaETJPGFile HitStateUpdate
getSpecAnaETWAVFile HitStateUpdate
getSpecAnaVerticalRangeCaption SetupStateUpdate
getSpecAnaIntegeration SetupStateUpdate
getSpecAnaThreshold SetupStateUpdate
getSpecAnaSegmentSize SetupStateUpdate

 

Setters (Client Side)

Service Implementation

(Server Side)

SpecAnaHitReset HitReset
setSpecAnaSML setSML
setSpecAnaCapture setCapture
setSpecAnaWavJpgLocation setWavJpgLocation
   
   
setSpecAnaRunning setRunning
CollectSpecAnaSnapshot

CollectSnapShot