Phidgets3 example

In this mix SPARKL intermediates between a sensor and a motor service. The rotation sensor and the servo motor are harmonised as in the case of Phidgets2. Additionally, three LEDs (green, red and amber) are connected to an interface kit. Either of the LEDs light up depending on the position of the servo motor.

Explaining the mix

Figure: Phidgets3 - The mix


The Turn notify is triggered by rotating the sensor and the SetPosition consume is used to set the position of the motor.

A JavaScript service inverts the spinning of the servo motor.

Another JavaScript service is used to calculate the position of the servo motor, and light up either of the LEDs based on the motor's position.

The LightsOff notify is used to turn off the LEDs after a configured time period.

Tip: Get the code from the SPARKL public repository.
Table 1. Phidgets3 - The markup
Example Description
<folder name="Phidgets3">
  <service name="Sequencer"
    provision="sequencer"/>
  <service name="Connection"
    provision="tabserver_connection"/>
  <field name="green" 
    type="boolean"/>
  <field name="amber" 
    type="boolean"/>
  <field name="red" 
    type="boolean"/>
  <field name="positionA" 
    type="integer"/>
  <field name="position" 
    type="integer"/>
  <mix name="Mix">
    <folder name="Drive">
    ...
    </folder>
    <folder name="Inverter">
    ...
    </folder>
    <folder name="MeasureSpeed">
    ...
    </folder>
  </mix>
</folder>
In this mix we have:
  • Sequencer, a service provisioned using the Sequencer extension. It is responsible for planning and processing the transactions started by the firing of the notify operations
  • Connection, a service that accepts connections from browsers. It is a dependency for the services provisioned using Tabserver, such as Inverter and Measurer
  • Five fields sent between the operations
  • Three folders containing four services and six operations
Each folder sits inside the mix folder. They all contain one or two service(s), and the operations on those particular services.

The fields are direct children of the top level folder, as they are all referenced by operations from different folders.

The red, green and amber fields are of type boolean, their value can be either:

  • true
  • false
The fields position and positionA are used the same way as in the Phidgets2 example.
<folder name="Drive">
  <service name="Drive" 
    provision="phidget">
    <prop name="phidget.spec" 
      kind="PhidgetInterfaceKit" 
      domains="domain.local"/>
    <prop name="phidget.params" 
      sensor0="positionA" 
      output0="green" 
      output1="red" 
      output2="amber"/>
  </service>
  <service name="Servo" 
    provision="phidget">
    <prop name="phidget.spec" 
      kind="PhidgetAdvancedServo" 
      domains="domain.local"/>
    <prop name="phidget.params" 
      position0="position"/>
  </service>
  <notify name="Turn" 
    service="Sequencer" 
    clients="Drive" 
    fields="positionA"/>
  <consume name="LightUp" 
    service="Drive" 
    fields="amber green red"/>
  <consume name="SetPosition" 
    service="Servo" 
    fields="position"/>
</folder>
The Drive service, which we defined as a client for the Turn operation, and as a service for the LightUp operation, is a phidget service.

It comprises an interface kit, to which a rotation sensor and three LEDs are connected. The rotation sensor is mapped to the field position, and the LEDs are mapped to the fields green, red and amber.

The LightUp consume forms a goal.

Drive, the service implementing the consume, expects the fields green, red and amber.

When the Drive service receives the boolean fields, it checks their values.

  • If a field has the value true, Drive lights up the corresponding LED
  • If a field has the value false and the corresponding LED is on, Drive switches that LED off
<folder name="Inverter">
  <service name="Inverter" 
    provision="tabserver" 
    dependencies="Connection">
    <prop name="tabserver.browser.src" 
      src="Inverter?prop=tabserver.browser.src" 
      type="application/javascript"><![CDATA[
    ...JavaScript comes here...
    ]]></prop>
  </service>
  <request name="Invert" 
    service="Inverter" 
    fields="positionA">
  <reply name="Ok" 
    fields="position"/>
  </request>
</folder>
The Inverter service is provisioned using the Tabserver extension.

Inverter has a JavaScript configuration used to subtract the value of the field positionA from 999 in order to harmonise the movement of the servo motor with the rotation sensor.

The Invert operation is invoked to add the field position to the field set.

The Invert operation is implemented by Inverter.

See Figure 3 on the script.

<folder name="MeasureSpeed">
  <service name="Measurer" 
    provision="tabserver" 
    dependencies="Connection">
    <prop name="tabserver.browser.src" 
      src="Measurer?prop=tabserver.browser.src" 
      type="application/javascript"><![CDATA[
    ...JavaScript comes here...
    ]]></prop> 
  </service>
  <notify name="LightsOff" 
    service="Sequencer" 
    clients="Measurer" 
    fields="amber green red"/>
  <request name="Measure" 
    service="Measurer" 
    fields="position">
    <reply name="Ok" 
      fields="amber green red"/>
  </request>
</folder>
The Measure operation is implemented by Measurer, a JavaScript service. This service uses its JavaScript to generate the fields green, red and amber. These fields are of the type boolean and their value can be either true or false.

Based on the position of the servo motor, one of the three fields' value is set to true, the others' value is set to false.

The Measurer service is defined as a client service on the LightsOff operation.

The LightsOff operation starts a new transaction by outputting the fields green, red and amber to SPARKL. These fields will be, as before, used to satisfy the LightUp consume goal. The difference is, that the Measurer assigns the value false to all the fields output by LightsOff.

This operation, therefore, is used to switch the LEDs off. The LightsOff operation is invoked five seconds after the Measurer first assigned a value for the fields green, red and amber.

See Figure 4 on the script.

Figure: JavaScript content of the Inverter service

sparkl.service({
  "Invert" : function(request, reply) {
    var positionA = request.value("positionA");
    var position = 999 - positionA;
    console.log("Inverting " + positionA);
    reply["Ok"]
      .value("position", position)
      .send();
  }
});

Figure: JavaScript content of the Measurer service

sparkl.service({
  
  "Timeout" : null,
  
  "Measure" : function(request, reply) {
    var service = this;
    var green=false;
    var amber=false;
    var red=false;
    var position = request.value("position");

    console.log ("Measuring", + position);

    if (position>=700) {
      red=true;
    }
    else if (position<=300) {
      green=true;
    }
    else {
      amber=true;
    }
    
    clearTimeout(service["Timeout"]);
    service["Timeout"] = setTimeout(function() {
      service.notify("LightsOff")
        .values({
          "green" : false,
          "red"   : false,
          "amber" : false})
        .send();
    }, 5000);
    
    reply["Ok"]
      .values({
      "green" : green,
      "red"   : red,
      "amber" : amber})
      .send();
  }
});