//Domain 'elevator_r1' Notebook //State Model 'Cabin' Descriptions //State Model 'Cabin' //Object: Cabin //Description: //None //State: 1. Transferring Passengers //Description: Select one myXfer related by self->XFER[R21]; Generate XFER1: Cabin_arrived () to myXfer; Select one myDoor related by self->DOOR[R4]; Generate DOOR1: Unlock () to myDoor; // ... //State: 2. Securing Doors //Description: Select one myDoor related by self->DOOR[R4]; myDoor.Lock_enabled = TRUE; Generate DOOR2: Lock () to myDoor; // ... //State: 3. Moving to Floor //Description: Select one myXfer related by self->XFER[R21]; Generate TRAN1: Move_to_floor (Floor_number:myXfer.Destination_floor, Shaft_ID:self.Shaft_to TRAN; // ... //State Model 'Door' Descriptions //State Model 'Door' //Object: Door //Description: //None //State: 1. Closed //Description: // If self.Lock_enabled // Generate Lock to self If (self.Lock_enabled) // If cabin set the lock, then it wants to go // this means that an XFER must exist Generate DOOR2: Lock () to self; Else // There's no XFER, check the work list Generate XFER_A4: Ready_to_go (Shaft_ID:self.Shaft_ID) to XFER assigner; End if; // ... //State: 2. Opening //Description: // Tell PIO to start opening the door // -- Generate PIO1: Open_door (Shaft_ID:self.Shaft_ID) to PIO; // ... //State: 3. Open //Description: // Set open timer to Open_wait_time // -- Create event instance norm_timeout of DOOR9:Normal_open_timeout() to self; d_timer = TIM::timer_start(microseconds:self.Open_wait_time * 1000, event_inst: norm_timeout); // ... //State: 4. Closing //Description: // Tell PIO to start closing the door // -- Generate PIO2: Close_door (Shaft_ID:self.Shaft_ID) to PIO; // ... //State: 5. Locked //Description: // Tell the Cabin we're ready to go // -- Select one myCabin related by self->CAB[R4]; Generate CAB3: Doors_secure () to myCabin; // ... //State: 6. Registering_block //Description: // If we've tried to close the door unsuccessfully too many // consecutive times, take the door out of service. // // Otherwise, set the open wait time to this Bank's block clear time // and reopen the doors for a while // -- Select one myBank related by self->CAB[R4]->SHAFT[R2]->BANK[R1]; self.Retries = self.Retries + 1; If (self.Retries > myBank.Max_close_attempts) Generate DOOR8: Cant_close_door () to self; Else self.Open_wait_time = myBank.Block_clear_time; Generate DOOR6: Open () to self; End if; // ... //State: 7. Out of Service //Description: // pending out of service strategy // -- //State: 8. Expediting_Close //Description: // Cancel the open timer and start closing the door // -- dtimer_exists = TIM::timer_cancel (timer_inst_ref:self.Open_timer); Generate DOOR10: Done () to self; // ... //State: 9. Unlocking //Description: // Reset Lock, Retries and Door open timer // -- self.Lock_enabled = FALSE; self.Retries = 0; Select one myBank related by self->CAB[R4]->SHAFT[R2]->BANK[R1]; self.Open_wait_time = myBank.Pass_load_time; Generate DOOR10: Done () to self; // ... //State Model 'Transfer' Descriptions //State Model 'Transfer' //Object: Transfer //Description: //None //State: 1. Creating //Description: // ... //State: 2. Waiting for Service //Description: // Generate New_transfer to Cabin // -- Select one myCab related by self->CAB[R21]; Generate CAB1: New_transfer () to myCab; // ... //State: 3. Completed //Description: // If there is a call matching the shaft service direction // Generate Clear to that call // If my->Shaft_Level.Stop_Requested // Generate Clear_Stop to Shaft_Level // // Delete this associative instance and relationship // -- Select one mySLEV related by self->SLEV[R21]; Select one mySHAFT related by mySLEV->SHAFT[R28]; If (mySLEV.Stop_requested) mySLEV.Stop_requested = FALSE; Generate UI1:Clear_stop (Floor_number:mySLEV.Floor_number, Shaft_ID:mySLEV.Shaft_ID to UI; End if; Select any upRequest related by mySHAFT->BLEV[R20] where (selected.Floor_number == self.Destination_floor); If (not_empty upRequest) Unrelate mySHAFT from upRequest across R20; Generate UI2: Clear_direction (Bank_ID:mySHAFT.Bank_ID, Floor_number:mySLEV.Floor_number, Direction:"up") to UI; End if; Select any dnRequest related by mySHAFT->BLEV[R19] where (selected.Floor_number == self.Destination_floor); If (not_empty dnRequest) Unrelate mySHAFT from dnRequest across R19; Generate UI2: Clear_direction (Bank_ID:mySHAFT.Bank_ID, Floor_number:mySLEV.Floor_number, Direction:"down") to UI; End if; Generate XFER_A4: Ready_to_go (Shaft_ID:self.Shaft_ID) to XFER assigner; Select one myCabin related by self->CAB[R21]; Unrelate mySLEV from myCabin across R21 using self; // ... //State Model 'Transfer Assigner' Descriptions //State Model 'Transfer Assigner' //Object: Transfer //Description: //None //State: 0. NO ASSIGNMENTS REQUESTED //Description: // ... //State: 1. Searching Ahead for Calls in the Service Direction //Description: // Search in the service direction and find the closest: // a) Shaft Level with stop requested OR // b) Call in the current service direction // If either exists at a Shaft Level // Generate Dest_selected (Shaft_ID, Floor_number) to self // Else // Generate No_dest () to self //-- // --------------------- // INIT SEARCH Select any cabinShaft from instances of SHAFT where (selected.ID == rcvd_evt.Shaft_ID); Select one cabinBank related by cabinShaft->BANK[R1]; Select one theCabin related by cabinShaft->CAB[R2]; cabinLocation = theCabin.Current_floor; // where the cabin is now serviceDir = cabinShaft.Service_direction; // current service direction destFloor = cabinLocation; // result of unsuccessful search // establish floor increment - and end condition for search finc = 0; //scope If (serviceDir == "up") finc = 1; Elif (serviceDir == "down") finc = -1; End if; // BEGIN SEARCH fn = cabinLocation + finc; floorSelected = FALSE; While (fn >= cabinBank.Bottom_floor AND fn <= cabinBank.Top_floor) // until we pass the top or bottom floor Select any thisShaftLevel from instances of SLEV where (selected.Floor_number == fn AND selected.Shaft_ID == cabinShaft.ID) // Does this floor have an Elevator Stop pending? If (thisShaftLevel.Stop_requested) // found an elevator stop - let's go! destFloor = fn; floorSelected = TRUE; Break; End if; // Has this floor been called in the service direction? Select any thisBlev from instances of BLEV where (selected.Bank_ID == cabinBank.ID AND selected.Floor_number == fn); If (serviceDir == "up") Select one callRequested related by thisBlev->SHAFT[R20]; If (not_empty callRequested) destFloor = fn; floorSelected = TRUE; Break; End if; Elif (serviceDir == "down") Select one callRequested related by thisBlev->SHAFT[R19]; If (not_empty callRequested) destFloor = fn; floorSelected = TRUE; Break; End if; End if; fn = fn +finc; End while; // SEARCH COMPLETE - HANDLE RESULT Select one safeStop related by theCabin->STOP_WIN[R22]; If (floorSelected AND (destFloor <= safeStop.Nearest_upper_floor AND destFloor >= safeStop.Nearest_lower_floor)) Generate XFER_A5: Dest_selected (Selected_floor_number:destFloor, Shaft_ID:cabinShaft.ID, Bank_ID:cabinBank.ID) to XFER assigner; Else Generate XFER_A6: No_dest (Current_floor_number:cabinLocation, Shaft_ID:cabinShaft.ID, Bank_ID:cabinBank.ID) to XFER assigner; End if; //State: 2. Searching Ahead for Calls Opposite the Service Direction //Description: // Select the Shaft_Level farthest from the cabin in the service direction // with a Call opposite the service direction. // // If such a Shaft Level exists // Toggle the Shaft.Service_direction // Generate Dest_selected (Shaft_ID, Floor_number) to self // Else // Generate No_dest () to self //-- // --------------------- // INIT SEARCH Select any cabinShaft from instances of SHAFT where (selected.ID == rcvd_evt.Shaft_ID); Select one cabinBank related by cabinShaft->BANK[R1]; Select one theCabin related by cabinShaft->CAB[R2]; cabinLocation = theCabin.Current_floor; serviceDir = cabinShaft.Service_direction; destFloor = cabinLocation; // establish floor increment - and initial value of search finc = 0; //scope fn = 0; searchDir = "init"; If (serviceDir == "up") finc = -1; fn = cabinBank.Top_floor; searchDir = "down"; Else // down finc = 1; fn = cabinBank.Bottom_floor; searchDir = "up"; End if; // BEGIN SEARCH floorSelected = FALSE; While (fn != cabinLocation) // until reach the cabin's current position Select any thisShaftLevel from instances of SLEV where (selected.Floor_number == fn AND selected.Shaft_ID == cabinShaft.ID); // Has this floor been called OPPOSITE the service direction? Select any thisBlev from instances of BLEV where (selected.Bank_ID == cabinBank.ID AND selected.Floor_number == fn); If (serviceDir == "up") Select one callRequested related by thisBlev->SHAFT[R19]; If (not_empty callRequested) destFloor = fn; floorSelected = TRUE; Break; End if; Elif (serviceDir == "down") Select one callRequested related by thisBlev->SHAFT[R20]; If (not_empty callRequested) destFloor = fn; floorSelected = TRUE; Break; End if; End if; fn = fn +finc; End while; // SEARCH COMPLETE - HANDLE RESULT Select one safeStop related by theCabin->STOP_WIN[R22]; If (floorSelected AND (destFloor <= safeStop.Nearest_upper_floor AND destFloor >= safeStop.Nearest_lower_floor)) cabinShaft.Service_direction = searchDir; // toggle service direction Generate XFER_A5: Dest_selected (Selected_floor_number:destFloor, Shaft_ID:cabinShaft.ID, Bank_ID:cabinBank.ID) to XFER assigner; Else Generate XFER_A6: No_dest (Current_floor_number:cabinLocation, Shaft_ID:cabinShaft.ID, Bank_ID:cabinBank.ID) to XFER assigner; End if; //State: 3. Searching Behind for Calls Opposite the Service Direction //Description: // Search opposite the service direction and find the closest: // a) elevator stop OR // b) call opposite the service direction // If either exists at a Shaft Level // Toggle Shaft.Service_direction // Generate Dest_selected (Shaft_ID, Floor_number) to self // Else // Generate No_dest (Shaft_ID, Floor_number) to self //-- // --------------------- // INIT SEARCH Select any cabinShaft from instances of SHAFT where (selected.ID == rcvd_evt.Shaft_ID); Select one cabinBank related by cabinShaft->BANK[R1]; Select one theCabin related by cabinShaft->CAB[R2]; cabinLocation = theCabin.Current_floor; // where the cabin is now serviceDir = cabinShaft.Service_direction; // current service direction destFloor = cabinLocation; // result of unsuccessful search // establish floor increment - and end condition for search finc = 0; //scope searchDir = "init"; If (serviceDir == "up") // setup for search outward from cabin finc = -1; searchDir = "down"; Else // down finc = 1; searchDir = "up"; End if; // BEGIN SEARCH fn = cabinLocation + finc; floorSelected = FALSE; While (fn >= cabinBank.Bottom_floor AND fn <= cabinBank.Top_floor) // until we pass the top or bottom floor Select any thisShaftLevel from instances of SLEV where (selected.Floor_number == fn AND selected.Shaft_ID == cabinShaft.ID); // Does this floor have an Elevator Stop pending? If (thisShaftLevel.Stop_requested) // found an elevator stop - let's go! destFloor = fn; floorSelected = TRUE; Break; End if; // Has this floor been called opposite the service direction? Select any thisBlev from instances of BLEV where (selected.Bank_ID == cabinBank.ID AND selected.Floor_number == fn); If (serviceDir == "up") Select one callRequested related by thisBlev->SHAFT[R19]; If (not_empty callRequested) destFloor = fn; floorSelected = TRUE; Break; End if; Elif (serviceDir == "down") Select one callRequested related by thisBlev->SHAFT[R20]; If (not_empty callRequested) destFloor = fn; floorSelected = TRUE; Break; End if; End if; fn = fn + finc; End while; // SEARCH COMPLETE - HANDLE RESULT Select one safeStop related by theCabin->STOP_WIN[R22]; If (floorSelected AND (destFloor <= safeStop.Nearest_upper_floor AND destFloor >= safeStop.Nearest_lower_floor)) cabinShaft.Service_direction = searchDir; // toggle the service direction Generate XFER_A5: Dest_selected (Selected_floor_number:destFloor, Shaft_ID:cabinShaft.ID, Bank_ID:cabinBank.ID) to XFER assigner; Else Generate XFER_A6: No_dest (Current_floor_number:cabinLocation, Shaft_ID:cabinShaft.ID, Bank_ID:cabinBank.ID) to XFER assigner; End if; // ... //State: 4. Searching Behind for Calls in the Service Direction //Description: // Select the Shaft_Level farthest from the Cabin in the service direction // with a Call matching the service direction. // // If such a Shaft Level exists // Generate Dest_selected (Shaft_ID, Floor_number) to self // Else // Generate No_dest () to self //-- // --------------------- // INIT SEARCH Select any cabinShaft from instances of SHAFT where (selected.ID == rcvd_evt.Shaft_ID); Select one cabinBank related by cabinShaft->BANK[R1]; Select one theCabin related by cabinShaft->CAB[R2]; cabinLocation = theCabin.Current_floor; // where the cabin is now serviceDir = cabinShaft.Service_direction; // current service direction destFloor = cabinLocation; // result of unsuccessful search // establish floor increment - and initial value of search finc = 0; //scope fn = 0; searchDir = "init"; If (serviceDir == "up") finc = 1; fn = cabinBank.Bottom_floor; searchDir = "up"; Else // down finc = -1; fn = cabinBank.Top_floor; searchDir = "down"; End if; // BEGIN SEARCH floorSelected = FALSE; While (fn != cabinLocation) // until reach the cabin's current position Select any thisShaftLevel from instances of SLEV where (selected.Floor_number == fn AND selected.Shaft_ID == cabinShaft.ID); // Does this floor have a Call in the ServiceDir direction? Select any thisBlev from instances of BLEV where (selected.Bank_ID == cabinBank.ID AND selected.Floor_number == fn); If (serviceDir == "up") Select one callRequested related by thisBlev->SHAFT[R20]; If (not_empty callRequested) destFloor = fn; floorSelected = TRUE; Break; End if; Elif (serviceDir == "down") Select one callRequested related by thisBlev->SHAFT[R19]; If (not_empty callRequested) destFloor = fn; floorSelected = TRUE; Break; End if; End if; fn = fn + finc; End while; // SEARCH COMPLETE - HANDLE RESULT Select one safeStop related by theCabin->STOP_WIN[R22]; If (floorSelected AND (destFloor <= safeStop.Nearest_upper_floor AND destFloor >= safeStop.Nearest_lower_floor)) Generate XFER_A5: Dest_selected (Selected_floor_number:destFloor, Shaft_ID:cabinShaft.ID, Bank_ID:cabinBank.ID) to XFER assigner; Else Generate XFER_A3: Done () to XFER assigner; // last stage of search - nothing else to do End if; // ... //State: 5. CREATING TRANSFER //Description: // See if there is already an existing Transfer for this Shaft // If there isn't then // we need to create a new transfer for the // destination floor our algorithm selected. // If a transfer does exist already AND it directs the cabin to // a floor different than the newly selected destination // delete the existing transfer and then create one for the new destination // But if the transfer exists and specifies the same floor as our "new" destination // don't do anything, just quit // -- // if unchanged, the following assertions result in no action taken // that's the case where the selected floor matches the existing transfer // so if we picked the same destination we already had, we just skip out of // of here without doing anything newXfer = FALSE; swapXfer = FALSE; Select any existingXfer from instances of XFER where (selected.Shaft_ID == rcvd_evt.Shaft_ID); If (empty existingXfer) newXfer = TRUE; // nothing there - just create a new xfer Elif (existingXfer.Destination_floor != rcvd_evt.Selected_floor_number) swapXfer = TRUE; // xfer exists with different floor - swap it with the new xfer End if; // If it's a swap, first delete the existing Xfer If (swapXfer) // all this just to delete a stupid relationship Select one theShaft_Level related by existingXfer->SLEV[R21]; Select one theCabin related by existingXfer->CAB[R21]; Unrelate theShaft_Level from theCabin across R21 using existingXfer; Delete object instance existingXfer; End if; // if either is true, we create a new transfer If (newXfer OR swapXfer) Select any theCabin from instances of CAB where (selected.Shaft_ID == rcvd_evt.Shaft_ID); Select any theShaftLevel from instances of SLEV where (selected.Shaft_ID == rcvd_evt.Shaft_ID AND selected.Floor_number == rcvd_evt.Selected_floor_number); Create object instance newXfer_instance of XFER; Relate theShaftLevel to theCabin across R21 using newXfer_instance; Generate XFER2: Created () to newXfer_instance; End if; Generate XFER_A3: Done () to XFER assigner; // ... //State Model 'Bank_Level' Descriptions //State Model 'Bank_Level' //Object: Bank_Level //Description: //None //State: 1. Waiting for Cabin Call Request //Description: // ... //State: 2. Selecting Shaft to Service Call //Description: // Apply algorithm to select Shaft based on: // Closest stopping floor to current level // Service direction // Notify transfer assigner of new request // (no algorithm has been specified yet, so we just select any Shaft in this Bank) Select any shaftChoice from instances of SHAFT where (selected.Bank_ID == self.Bank_ID); If (rcvd_evt.Direction == "up") Relate self to shaftChoice across R20; Elif (rcvd_evt.Direction == "down") Relate self to shaftChoice across R19; End if; Generate XFER_A1: Floor_requested (Shaft_ID: shaftChoice.ID) to XFER assigner; Generate BLEV4: Done () to self; // ... //State Model 'Shaft_Level' Descriptions //State Model 'Shaft_Level' //Object: Shaft_Level //Description: //None //State: 1. Waiting_for_Stop_Request //Description: // ... //State: 2. Stop_Requested //Description: self.Stop_requested = TRUE; Generate XFER_A1:Floor_requested (Shaft_ID:self.Shaft_ID) to XFER assigner; Generate SLEV3: Done () to self; // ... //State Model 'Stop_Window' Descriptions //State Model 'Stop_Window' //Object: Stop_Window //Description: //None //State: 1. Update Stop Window //Description: // Does nothing // Bridge to Transport Domain TBD // Enables illustration of update on OCM // ... //State Model 'Main_INIT' Descriptions //State Model 'Main_INIT' //Object: Main_INIT //Description: //None //State: 0. Waiting to GO //Description: // ... //State: 1. Global scenario setup //Description: // Create the Building Create object instance theBuilding of BLDNG; theBuilding.Name = "Gengar"; totalFloors = 7; // Create the Bank in the Building Create object instance theBank of BANK; theBank.Pass_load_time = 10; theBank.Block_clear_time = 5; theBank.Top_floor = totalFloors; theBank.Bottom_floor = 1; theBank.Max_close_attempts = 10; Relate theBank to theBuilding across R24; // Create the Shaft Create object instance theShaft of SHAFT; theShaft.Service_direction = "up"; theShaft.In_service = TRUE; Relate theShaft to theBank across R1; // Create the Cabin Create object instance theCabin of CAB; theCabin.Current_floor = 1; Relate theCabin to theShaft across R2; // Create the Stop Window Create object instance theSwin of STOP_WIN; theSwin.Nearest_upper_floor = totalFloors; theSwin.Nearest_lower_floor = 1; Relate theSwin to theCabin across R22; // Create the Door Create object instance theDoor of DOOR; theDoor.Retries = 0; theDoor.Open_wait_time = 0; theDoor.Lock_enabled = FALSE; Relate theDoor to theCabin across R4; // Create the Floors, Bank Levels and Shaft Levels fn = 1; While (fn <= totalFloors) // Add a Floor to the Building Create object instance thisFloor of FLOOR; thisFloor.Number = fn; thisFloor.Name = "noname"; Relate thisFloor to theBuilding across R23; // Add a Shaft Level for this Floor Create object instance thisSlev of SLEV; thisSlev.Floor_number = fn; thisSlev.Stop_requested = FALSE; Relate thisSlev to theShaft across R28; // Add a Bank Level for this Floor Create object instance thisBlev of BLEV; thisBlev.Floor_number = fn; Relate thisBlev to theBank across R25; fn = fn + 1; End while; Generate INIT2:Done () to self; // ... //State: 2. Specifics for Scenario 2 //Description: // Scenario #1 Select any theBank from instances of BANK; Select any theShaft from instances of SHAFT; Select any theCabin from instances of CAB; theCabin.Current_floor = 7; // ...