Next: , Previous: , Up: The Alarm System   [Contents]


2.6.2 The Controller

Usually we start designing by sketching interfaces, since we can always reasonably assume that a “hand-written” component will correctly implement any given interface. The below interface captures the two main kinds of incoming events for the controller: user-entered pincodes, and sensor trigger events. Timer timeout events are different since the controller has to initiate them.

interface IController {
  in void validPincode();
  in void sensorTriggered();

  behaviour {
    on validPincode: {}
    on sensorTriggered: {}
  }
}

The above minimal interface declares implicitly that any and every incoming event is “legal”, i.e., the caller does not have to track the controller’s state and avoid inappropriate calls. Said another way, the implemented interface will not hit an assertion via an illegal event.

A minimal Controller component would start up Unarmed; go from there to Armed upon a valid pincode; go from Armed to Alarming upon getting a sensorTriggered event; return to Armed state upon valid pincode; and return to Unarmed after another valid pincode. As an exercise you might want to build the minimal controller yourself before reading the below code.

component Controller {
  provides IController iController;

  behaviour {
    enum State { Unarmed, Armed, Alarming };
    State state = State.Unarmed;
    [state.Unarmed] {
      on iController.validPincode(): state = State.Armed;
      on iController.sensorTriggered(): {}
    }
    [state.Armed] {
      on iController.validPincode(): state = State.Unarmed;
      on iController.sensorTriggered():state = State.Alarming;
    }
    [state.Alarming] {
      on iController.validPincode(): state = State.Armed;
      on iController.sensorTriggered(): {}
    }
  }
}

The above honors its interface contract by always silently accepting and ignoring a sensorTriggered event when it is not in the Armed state.