How can I bind the given input to another proctype function?

断了今生、忘了曾经 提交于 2019-12-24 10:46:27

问题


I need some help according to follow problem which I have to implemented it using jSpin and promela language.

A home alarm system can be activated and deactivated using a personal ID key or password, after activation the system enters a waiting period of about 30 seconds, time that allows users to evacuate the secured area after which the alarm is armed, also when an intrusion is detected the alarm has a built in waiting period or delay of 15 seconds to allow the intruder to enter the password or swipe the card key thus identifying himself, in case that the identification is not made within the allocated 15 seconds the alarm will go off and will be on until an id card or password is used to deactivate it.

Here is what I tried:

mtype = {sigact, sigdeact};
chan signal = [0] of {mtype};
chan password = [0] of { int }; 
/*chan syntax for declaring and initializing message passing channels*/

int count;
bool alarm_off = true; /*The initial state of the alarm is off*/    
active proctype alarm()    
{
    off:
       if 
         :: count >= 30 -> atomic {signal!sigdeact; count = 0;alarm_off = false; goto on;}
         :: else -> atomic {count++; alarm_off = true; goto off;}
       fi;

    on:
        if
          :: count >=15 -> atomic { signal!sigact; count = 0;
    alarm_off = false; goto off;}
          :: else -> atomic {signal!sigact; alarm_off = true; goto pending;}
        fi;

    pending:

        if
           :: count >= 30 -> atomic {count = 0; alarm_off = false; goto on;}
           :: count < 30 -> atomic {count++; alarm_off = false; goto pending;}
        fi;
}

active proctype user()
{    
   password ! 1234 //1234 is the password I sent. 
   input:  atomic { signal?sigact ->  alarm_off = true; goto off; }   
}

In the user proctype I send the password

password ! 1234

How can I verify if the password is 1234 and how can I adapt it to own cases ( on, off , pending) based on the verification ?


回答1:


As the code in the example doesn't appear to follow the specification, at least in the way I understand it, I wrote an example from scratch.

Please note that the following model (source code) is purposely very verbose and redundant in its structure, so that its easier to recognise its logic blocks and --hopefully-- understand it. In practice, one would use some inline function to handle input. I also didn't use SIGACT, SIGDEACT which appeared in the original model, since I could not figure out who was supposed to read those messages neither from the original model (source code) nor from the specification.

#define ALARM_OFF        1
#define ALARM_COUNTDOWN  2
#define ALARM_ARMED      4
#define ALARM_INTRUSION  8
#define ALARM_FIRED     16

#define INPUT_SET_PASSWORD   1
#define INPUT_CHECK_PASSWORD 2
#define INPUT_INTRUDER       4

mtype = { SIGACT, SIGDEACT };

init {
    chan alarm_out = [1] of { mtype };
    chan alarm_in =  [1] of { byte, short };

    run alarm(alarm_in, alarm_out);
    run user(alarm_in);
    run event(alarm_in);
}

proctype alarm(chan input, output)
{
    byte count;
    byte state   = ALARM_OFF;
    short passwd = 1234;
    short tmp    = 0;

off:
    if
        :: nempty(input) ->
            if
                :: input?INPUT_SET_PASSWORD(tmp) ->
                    passwd = tmp;
                :: input?INPUT_CHECK_PASSWORD(tmp) ->
                if
                    :: tmp == passwd ->
                        atomic {
                            state = ALARM_COUNTDOWN;
                            count = 0;
                            goto countdown;
                        }
                    :: else ->
                        skip;
                fi;
                :: input?INPUT_INTRUDER(tmp) ->
                    skip;
            fi;
        :: empty(input) -> skip;
    fi;
    goto off;

countdown:
    if
        :: count < 30 ->
            if
                :: nempty(input) ->
                    if
                        :: input?INPUT_SET_PASSWORD(tmp) ->
                            skip; // error: cannot be done now (?)
                        :: input?INPUT_CHECK_PASSWORD(tmp) ->
                            if
                                :: tmp == passwd ->
                                    atomic {
                                        state = ALARM_OFF;
                                        count = 0;
                                        goto off;
                                    }
                                :: else ->
                                    skip; // error: incorrect password (?)
                            fi;
                        :: input?INPUT_INTRUDER(tmp) ->
                            skip;
                    fi;
                :: empty(input) ->
                    skip;
            fi;
        :: else ->
            atomic {
                state = ALARM_ARMED;
                count = 0;
                goto armed;
            }
    fi;
    count++;
    goto countdown;

armed:
    if
        :: nempty(input) ->
            if
                :: input?INPUT_SET_PASSWORD(tmp) ->
                    skip; // error: cannot be done now (?)
                :: input?INPUT_CHECK_PASSWORD(tmp) ->
                    if
                        :: tmp == passwd ->
                            atomic {
                                state = ALARM_OFF;
                                count = 0;
                                goto off;
                            }
                        :: else ->
                            skip; // error: incorrect password (?)
                                  // maybe it should be handled like
                                  // INPUT_INTRUDER(tmp)
                    fi;
                :: input?INPUT_INTRUDER(tmp) ->
                    atomic {
                        state = ALARM_INTRUSION;
                        count = 0;
                        goto intruder_detected;
                    }
            fi;
        :: empty(input) ->
            skip;
    fi;
    goto armed;

intruder_detected:
    if
        :: count < 15 ->
            if
                :: nempty(input) ->
                    if
                        :: input?INPUT_SET_PASSWORD(tmp) ->
                            skip; // error: cannot be done now (?)
                        :: input?INPUT_CHECK_PASSWORD(tmp);
                            if
                                :: tmp == passwd ->
                                    atomic {
                                        state = ALARM_ARMED;
                                        count = 0;
                                        goto armed;
                                    }
                                :: else ->
                                    skip; // error: incorrect password (?)
                            fi;
                        :: input?INPUT_INTRUDER(tmp) ->
                            skip;
                    fi;
                :: empty(input) ->
                    skip;
            fi;
        :: count >= 15 ->
            atomic {
                state = ALARM_FIRED;
                count = 0;
                goto alarm_fired;
            }
    fi;
    count++;
    goto intruder_detected;

alarm_fired:
    if
        :: nempty(input) ->
            if
                :: input?INPUT_SET_PASSWORD(tmp) ->
                    skip; // error: cannot be done now (?)
                :: input?INPUT_CHECK_PASSWORD(tmp);
                    if
                        :: tmp == passwd ->
                            atomic {
                                state = ALARM_OFF;
                                count = 0;
                                goto off;
                            }
                        :: else ->
                            skip; // error: incorrect password (?)
                                  // warn user but keep alarm on
                    fi;
                :: input?INPUT_INTRUDER(tmp) ->
                    skip;
            fi;
        :: empty(input) ->
            skip;
    fi;
    goto alarm_fired;
};

proctype user(chan output)
{
    output ! INPUT_CHECK_PASSWORD(1234);
};

proctype event(chan output)
{
    output ! INPUT_INTRUDER(0);
};

So, basically you have to check both the input (if any!) and the value of count in order to perform a transition in the internal FSM of the alarm system.

In the example I added a proctype of name event which will randomly send a single INPUT_INTRUDER input signal to the alarm system. This, in combination with the user typing his own password, can be used to trigger the chain of events which would cause the alarm to fire.



来源:https://stackoverflow.com/questions/47272662/how-can-i-bind-the-given-input-to-another-proctype-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!