DND status indication - hints and BLF

  1. 12 years ago

    System:
    CentOS 6.2 (2.6.32-220.13.1.el6.x86_64)
    Asterisk 1.8.11.1
    FreePBX 2.10.0.4
    FOP2 2.26

    Hi,

    I've just recently installed FOP2 and it is working very well. I had a query regarding DND and presence indication - I am able to toggle DND successfully from an extension (*76) and it appears on FOP2 (also updates the relevant database entries and hints).

    When however setting DND from within FOP2 the database entries are updated as expected but the hints are not set - therefore BLF subscriptions on the phones show the extension as 'Idle'

    Is this the expected behaviour when setting the presence indication from within FOP2?

    Many thanks

    Sean

  2. admin

    2 May 2012 Administrator

    Did you run the generate_override_contexts.pl script ?

    If not, do it

    /usr/local/fop2/generate_override_contexts.pl -w

    Then try again.

  3. Hi Nicolas

    Yes I ran the generate_override_contexts.pl script when I first did the installation, and extensions_override_fop2.conf is working very nicely.

    My simple question is; does FOP2 actually set hints - and I think the answer is 'no' (but just wanted to double check)? I've got BLF buttons subscribed to hints which show a particular extension as "not in use" which has in fact been set to DND using FOP2.

    However executing a *76 (with the FOP2 mods included) does actually set the BLF hint (and also update the asterisk DB) as expected.

    Does that make sense?

  4. admin

    4 May 2012 Administrator

    Hi,

    Fop2 does not set hints, but you can modify what fop2 does but modifying FOP2Callbacks.pm

    Unfortunately the hint setting is a moving target, I cannot add it as standard feature, not everyone uses the same asterisk version, let alone FreePBX versions.

    In Fop2callbacks you could originate a call to a custom dialplan using Local/xxx and write it so it set states the way it is done in your current freepbx version.. that could work.

  5. Hi Nicholas,
    I am struggling with this issue as well. I would be happy to have even as much as simcity has working:

    However executing a *76 (with the FOP2 mods included) does actually set the BLF hint (and also update the asterisk DB) as expected

    I am afraid to break the FOP2 settings, which, presently, are working very well.

    I have had a look at extensions_override_fop2.conf and was toying with trying to add in a line like:
    [code]Set(DEVICE_STATE(Custom:DND_*76... something?? [/code]
    and adding into extensions_custom.conf something like:

    exten => _XX,hint,SIP/${EXTEN}&Custom:DND${EXTEN} 

    but this is a bit over my head.

    What I am trying to achieve is have the BLF on my Grandstream GXP2120 display red when dnd is on, and green when off.

    I can set the DND status using FOP2 and this works well, but there is no indication on the phone itself what the DND state is.

    I am asking on the FOP2 forum due to the fact that extensions_override_fop2.conf defines the [app-dnd-toggle] and it seems to me that if the Device_State setting is to be added in, it should be here?

    I would appreciate any assistance..

  6. admin

    8 Jun 2012 Administrator

    What I am trying to achieve is have the BLF on my Grandstream GXP2120 display red when dnd is on, and green when off.

    I can set the DND status using FOP2 and this works well, but there is no indication on the phone itself what the DND state is.

    I am asking on the FOP2 forum due to the fact that extensions_override_fop2.conf defines the [app-dnd-toggle] and it seems to me that if the Device_State setting is to be added in, it should be here?

    I would appreciate any assistance..

    Hi,

    extensions_override_fop2.conf is generated with the generate_override_contexts.pl script. This script will take the DND macros from your current FreePBX version and add to them 2 or 3 priorities to fire a UserEvent so FOP2 can reflect a change when you *dial* the feature code from the phone. All of this means that it is NOT the extensions_override_fop2.conf file what you need to change, as those contexts are not used when you change presence in FOP2, but when you dial the feature codes from your phone.

    What you need to modify is FOP2Callbacks.pm , that file will intercept a presence change in the FOP2 GUI and set and ASTDB entry for DND in Asterisk, and only set that astdb entry. So, you need to modify that code block to set the proper device state.

    I have not tried this, I am typing it directly in here, but you might want to follow this route and go from here, edit FOP2Callbacks.pm , notice that I am adding another command (setvar) to send to AMI when you set/unset the presence in fop2, somwhere neer the beginning of the file:

    if($parameters[3] ne "") {
    
        $return  = "Action: Command\r\n";
        $return .= "Command: database put DND ".$parameters[2]." YES\r\n";
        $return .= "\r\n";
        push @allreturn, $return;
    
        # New command to set a device state variable
        $return  = "Action: SetVar\r\n";
        $return .= "Variable: DEVICE_STATE(Custom:DND".$parameters[2].")\r\n";
        $return .= "Value: BUSY\r\n";
        $return .= "\r\n";
        push @allreturn, $return;
        
     } else { 
    
        $return  = "Action: Command\r\n";
        $return .= "Command: database del DND ".$parameters[2]."\r\n";
        $return .= "\r\n";
        push @allreturn, $return;
    
        # New command to set a device state variable
        $return  = "Action: SetVar\r\n";
        $return .= "Variable: DEVICE_STATE(Custom:DND".$parameters[2].")\r\n";
        $return .= "Value: NOT_INUSE\r\n";
        $return .= "\r\n";
        push @allreturn, $return;
    }

    After modifying FOP2Callbacks.pm , you might want to see if there are no syntax errors by running it like this:

    perl FOP2Callbacks.pm

    It should not output anything on screen. Then restart FOP2 and try to change presence from it. I am not sure if the above is correct, it might have a syntax error, or perhaps there is an additional DEVICE_STATE that needs to be set for your phone. But you will get the idea.

    If you have it working, please let us know.

    Best regards,

  7. I have followed these intructions, with no luck. I updated the callback.pm file as i think you intended:

    package FOP2Callbacks;
    
    # Example module to customize and tweak FOP2 behaviour
    my %redirected;
    
    sub flashCommand {
        # This function is called when certain commands are sent from a flash client
    
        $command  = shift;
        @parameters = @_;
    
        my $return = "";
        my @allreturn = ();
    
        
        if($command eq "setastdb") {
    
            # DND Integration from FOP2 to FreePBX ASTDB DND
    
            # This is for debug
            # my $cont=0;
            # foreach my $param (@parameters) {
            #     $cont++;
            #     print "Parametro $cont = $param\n";
            # }
            
            if($parameters[3] ne "") {
    
                $return  = "Action: Command\r\n";
                $return .= "Command: database put DND ".$parameters[2]." YES\r\n";
                $return .= "\r\n";
                push @allreturn, $return;
    
      	  # New command to set a device state variable
      	  $return  = "Action: SetVar\r\n";
      	  $return .= "Variable: DEVICE_STATE(Custom:DND".$parameters[2].")\r\n";
      	  $return .= "Value: BUSY\r\n";
      	  $return .= "\r\n";
      	  push @allreturn, $return;
    
            } else { 
    
                $return  = "Action: Command\r\n";
                $return .= "Command: database del DND ".$parameters[2]."\r\n";
                $return .= "\r\n";
                push @allreturn, $return;
    
       	 # New command to set a device state variable
       		 $return  = "Action: SetVar\r\n";
       		 $return .= "Variable: DEVICE_STATE(Custom:DND".$parameters[2].")\r\n";
       		 $return .= "Value: NOT_INUSE\r\n";
       		 $return .= "\r\n";
       		 push @allreturn, $return;
    
            }
    
            return @allreturn;
    
        } elsif($command eq "pickupActive") {
    
             #my $cont=0;
             #foreach my $param (@parameters) {
             #    $cont++;
             #    print "comando $comando -- Parametro $cont = $param\n";
             #}
             $redirected{$parameters[0]}=1;
             #print "seteo redirected de ".$parameters[1]."\n";
             return @allreturn;
    
        } elsif($command eq "auth") {
            #print "llego un auth, no devuelvo nada\n";
            #foreach my $param (@parameters) {
            #     $cont++;
            #     print "Parametro $cont = $param\n";
            #}
            return @allreturn;
        }
    }
    
    sub amiCommand {
    
        # Received an event from Asterisk Manager Interfase
    
        $command  = shift;
    
        if($command eq "LEAVE") {
    
            # Used with fop2-dummy context for writing a line
            # to queue_log so redirects OUT of a queue are not
            # counted as abandoned calls
    
            %event = @_;
            my $return = "";
            my @allreturn = ();
    
            if( defined ( $redirected { $event{Channel} } )) {
                # Este abandono es en realidad una redireccion
                delete $redirected { $event{Channel} };
    
                my $tiempo = time();
                $tiempo = $tiempo + 30;
                my $uniid  = $event{Uniqueid};
                my $queue  = $event{Queue};
    
                $return = "Action: Originate\r\n";
                $return .= "Channel: Local/dummy\@fop2-dummy/n\r\n";
                $return .= "Application: QueueLog\r\n";
                $return .= "Data: $queue,$uniid,NONE,NOTABANDON,0,0,0\r\n";
                $return .= "Async: true\r\n";
                $return .= "\r\n";
    
                push @allreturn, $return;
                return @allreturn;
            }
    
        } elsif($command eq "HANGUP") {
            # Garbage Collect
            %event = @_;
            if( defined ( $redirected { $event{Channel} } )) {
                # Este abandono es en realidad una redireccion
                delete $redirected { $event{Channel} };
            }
        
        } 
    }
    
    1;

    It compiled without error. I restarted fop2.
    It has not changed the result.

    I cannot see, in the CLI, any reaction at all when I change the presence state in the FOP2.
    When I set the DND presence via *76, I can see the CLI react (ie, it scrolls through various steps it is taking). This does not happen when I set DND via FOP2. FOP2 does recognise the DND setting if I set it using *76, OR using the FOP2 interface.

    I think the problem is related to the fact that, once the dnd status is toggled, the CLI still shows:

    == Extension Changed 216[ext-local] new state Idle for Notify User 216

    Should this not be showing as "Busy" ?

    I have active watchers watching for the status, but they are all showing idle: (this is from core show hints)

    216@ext-local : SIP/216 State:Idle Watchers 6

    However, if I try to dial that extension from another phone, the system reports that the user is 'on the phone', so it is responding to the DND setting.

  8. I also tried changing the device state codes set by your script to "InUse" and "Idle" (Rather than "BUSY" and "NOT_INUSE") to match the status names I see in the CLI, checked perl no errors, restart fop2 - however this had no appreciable effect.

    I have BLF's set to watch the status of 216, and they accurately reflect when the phone is in use, but they stubbornly continue to show the extension as idle when DND is set.

  9. admin

    11 Jun 2012 Administrator

    Check the dialplan macros, and the variables that are set for Device State, and try to replicate those in FOP2Calbacks.pm. What I wrote was taken from that macro, but if you look at them, there are more custom states being set. Perhaps you must add them all, or the other one that is also listed. This is just an extract of the dialplan:

    exten => sstate,1,Set(DEVICE_STATE(Custom:DND${AMPUSER})=${STATE})
    exten => sstate,n(begin),Set(DEVICE_STATE(Custom:DEVDND${CUT(DEVICES,&,${ITER})})=${STATE})

    What I wrote tries to replicate the variable set for Custom:DND, but perhpas the phone is subscribed to DEVDND as the 2nd appearance. But I am not sure if DEVDND expect the device name or the extension number. If it is the device, then you should use another parameter in FOP2Callbacks.pm , you will have to uncomment the debug print lines to know what index to use, probably 4 or 5, so you can add another block like:

     # New command to set a device state variable
    $return  = "Action: SetVar\r\n";
     $return .= "Variable: DEVICE_STATE(Custom:DEVDND".$parameters[4].")\r\n";
     $return .= "Value: BUSY\r\n";
     $return .= "\r\n";
     push @allreturn, $return;

    In any case, start FOP2 in debug mode level 3 and inspect the commands being sent via AMI and the asterisk responses:

    service fop2 stop
    cd /usr/local/fop2
    script capture.log
    ./fop2_server -X 3

    log into fop2 and set presence to something, wait a while, set back to available, and then stop the capture:

    ctrl-C
    exit
    service fop2 start

    You will have the capture.log file to review, and see if the device state variables are being set and what are the manager responses.

    Best regards,

  10. Hi Nicolas, thank you for your ongoing help with this.
    I have made significant progress, but there is still an issue, if you can bear with me explaining where I have got to.

    Firstly, for the benefit of others out there, I have discovered that there is a default setting in FreePBX that needs to be changed before you can get custom hints to work.
    Specifically, you need to go to the "Advanced Settings" page, and change "Enable Custom Device States" to "True"
    Once I did this, I started seeing signs of progress (core show hints started showing lots of monitored hints)

    Then I revisited the instructions Nicolas gave earlier, and re-set my /usr/local/fop2/FOP2Callbacks.pm changes to match my earlier post (I had made some changes since then trying different things, none of which worked)
    I then reloaded asterisk (core reload) and restarted fop2 (service fop2 restart)

    At this stage, BLF started to work for DND set via the FOP2 interface.
    This is a huge step forward and I am already very grateful and happy to have it working this far.

    The next issue, though, is that the BLF continues to ignore changes made by dialling *76 on the phone.
    It is important to note that FOP2 DOES pick up these changes, and updates its status accordingly - however the BLF lamp does not change unless the DND status is changed via the FOP2 interface.
    (this tells me that Nicolas' changes to FOP2Callbacks.pm are working well - it is now the underlying settings that are not working. )

    Presently, the BLF lamp will get 'out-of-sync' if the DND status is set via the *76 - it will continue to show Red unavailable if it was set to DND via FOP2 then turned off via *76, even though FOP2 recognises the change back to avaialable.

    I have read what Nicolas said about how the FOP2Callbacks.pm works, and it seems it is only called when the FOP2 user interface is used. So, either we need somehow to have FOP2Callbacks.pm called when *76 is used, or we need to have the system set the presence correctly when FOP2Callbacks.pm is not called.

    I have had another look at app-dnd-toggle in extensions_additional.conf and compared it with app-dnd-toggle in extensions_override_fop2.conf
    It seems that, with the fop2 override, the exten => *76,n,Set(STATE=BUSY or NOT_INUSE) lines are omitted:

    From extensions_additional.conf

    app-dnd-toggle
    ..
    exten => *76,1,Answer
    exten => *76,n,Wait(1)
    exten => *76,n,Macro(user-callerid,)
    exten => *76,n,GotoIf($["${DB(DND/${AMPUSER})}" = ""]?activate:deactivate)
    exten => *76,n(activate),Set(DB(DND/${AMPUSER})=YES)
    exten => *76,n,Set(STATE=BUSY)
    exten => *76,n,Gosub(app-dnd-toggle,sstate,1())
    exten => *76,n(hook_on),Playback(do-not-disturb&activated)
    exten => *76,n,Macro(hangupcall,)

    From extensions_override_fop2.conf

    app-dnd-toggle
    ...
    exten => *76,1,Answer
    exten => *76,n,Wait(1)
    exten => *76,n,Macro(user-callerid,)
    exten => *76,n,GotoIf($["${DB(DND/${AMPUSER})}" = ""]?activate:deactivate)
    exten => *76,n(activate),Set(DB(DND/${AMPUSER})=YES)
    ; added for fop2
    exten => *76,n,Set(CHAN=${CUT(CHANNEL,-,1)})
    exten => *76,n,Set(DB(fop2state/${CHAN})=Do not Disturb)
    exten => *76,n,UserEvent(FOP2ASTDB,Family: fop2state,Channel: ${CHAN},Value: Do not Disturb)
    ; end fop2 addition
    exten => *76,n(hook_on),Playback(do-not-disturb&activated)
    exten => *76,n,Macro(hangupcall,)

    I suspect this may be the reason the state is not getting set correctly when set via *76 ?
    I did try re-inserting these lines into extensions_override_fop2.conf but it did not work. I am thinking perhaps the State being set is the device state, rather than the extension state, and it seems the system is happily reading the extension state.

    Are you able to suggest what I can do to make the *76 change behave in the same way as when set via FOP2 ?

    Thanks again

  11. admin

    12 Jun 2012 Administrator

    The fix is to have the correct macro in extensions_override_fop2.conf. Not sure if you updated FreePBX *after* creating the override contexts, and it also seems your macros are kind of short, or for an old FreePBX version? Try to generate the contexts again running

    /usr/local/fop2/generate_override_contexts.pl -w

    Then compare the two macros again, there should be equal except for the ; added for fop2 and ;end addition blocks.

    Also, just for your viewing pleasure, this is a copy of the macro for FreePBX 2.8 , kind of old I know, but it is what I have around:

    [app-dnd-toggle]
    include => app-dnd-toggle-custom
    exten => *76,1,Answer
    exten => *76,n,Wait(1)
    exten => *76,n,Macro(user-callerid,)
    exten => *76,n,GotoIf($["${DB(DND/${AMPUSER})}" = ""]?activate:deactivate)
    exten => *76,n(activate),Set(DB(DND/${AMPUSER})=YES)
    ; added for fop2
    exten => *76,n,Set(CHAN=${CUT(CHANNEL,-,1)})
    exten => *76,n,Set(DB(fop2state/${CHAN})=Do not Disturb)
    exten => *76,n,UserEvent(FOP2ASTDB,Family: fop2state,Channel: ${CHAN},Value: Do not Disturb)
    ; end fop2 addition
    exten => *76,n,Set(STATE=BUSY)
    exten => *76,n,Gosub(app-dnd-toggle,sstate,1)
    exten => *76,n(hook_on),Playback(do-not-disturb&activated)
    exten => *76,n,Macro(hangupcall,)
    exten => *76,n(deactivate),Noop(Deleting: DND/${AMPUSER} ${DB_DELETE(DND/${AMPUSER})})
    ; added for fop2
    exten => *76,n,Set(CHAN=${CUT(CHANNEL,-,1)})
    exten => *76,n,dbDel(fop2state/${CHAN})
    exten => *76,n,UserEvent(FOP2ASTDB,Family: fop2state,Channel: ${CHAN},Value: )
    ; end fop2 addition
    exten => *76,n,Set(STATE=NOT_INUSE)
    exten => *76,n,Gosub(app-dnd-toggle,sstate,1)
    exten => *76,n(hook_off),Playback(do-not-disturb&de-activated)
    exten => *76,n,Macro(hangupcall,)
    exten => sstate,1,Set(DEVICE_STATE(Custom:DND${AMPUSER})=${STATE})
    exten => sstate,n,Set(DEVICES=${DB(AMPUSER/${AMPUSER}/device)})
    exten => sstate,n,GotoIf($["${DEVICES}" = "" ]?return)
    exten => sstate,n,Set(LOOPCNT=${FIELDQTY(DEVICES,&)})
    exten => sstate,n,Set(ITER=1)
    exten => sstate,n(begin),Set(DEVICE_STATE(Custom:DEVDND${CUT(DEVICES,&,${ITER})})=${STATE})
    exten => sstate,n,Set(ITER=$[${ITER} + 1])
    exten => sstate,n,GotoIf($[${ITER} <= ${LOOPCNT}]?begin)
    exten => sstate,n(return),Return()
  12. That did it!

    When I re-generated the override contexts, they included the "set state" lines which had previously been missing.

    All is working now. It even works using *78 and *79 to directly activate and deactivate DND, rather than *76 (toggle).

    Awesome, thank you! :D

  13. admin

    13 Jun 2012 Administrator

    Good to know. Can you post your final/working FOP2Callbacks.pm changes to the forum?

  14. This is the working content of FOP2Callbacks.pm

    Here is the full file:

    package FOP2Callbacks;
    
    # Example module to customize and tweak FOP2 behaviour
    my %redirected;
    
    sub flashCommand {
        # This function is called when certain commands are sent from a flash client
    
        $command  = shift;
        @parameters = @_;
    
        my $return = "";
        my @allreturn = ();
    
        
        if($command eq "setastdb") {
    
            # DND Integration from FOP2 to FreePBX ASTDB DND
    
            # This is for debug
            # my $cont=0;
            # foreach my $param (@parameters) {
            #     $cont++;
            #     print "Parametro $cont = $param\n";
            # }
            
            if($parameters[3] ne "") {
    
                $return  = "Action: Command\r\n";
                $return .= "Command: database put DND ".$parameters[2]." YES\r\n";
                $return .= "\r\n";
                push @allreturn, $return;
    
      	  # New command to set a device state variable
      	  $return  = "Action: SetVar\r\n";
      	  $return .= "Variable: DEVICE_STATE(Custom:DND".$parameters[2].")\r\n";
      	  $return .= "Value: BUSY\r\n";
      	  $return .= "\r\n";
      	  push @allreturn, $return;
    
            } else { 
    
                $return  = "Action: Command\r\n";
                $return .= "Command: database del DND ".$parameters[2]."\r\n";
                $return .= "\r\n";
                push @allreturn, $return;
    
       	 # New command to set a device state variable
       		 $return  = "Action: SetVar\r\n";
       		 $return .= "Variable: DEVICE_STATE(Custom:DND".$parameters[2].")\r\n";
       		 $return .= "Value: NOT_INUSE\r\n";
       		 $return .= "\r\n";
       		 push @allreturn, $return;
    
            }
    
            return @allreturn;
    
        } elsif($command eq "pickupActive") {
    
             #my $cont=0;
             #foreach my $param (@parameters) {
             #    $cont++;
             #    print "comando $comando -- Parametro $cont = $param\n";
             #}
             $redirected{$parameters[0]}=1;
             #print "seteo redirected de ".$parameters[1]."\n";
             return @allreturn;
    
        } elsif($command eq "auth") {
            #print "llego un auth, no devuelvo nada\n";
            #foreach my $param (@parameters) {
            #     $cont++;
            #     print "Parametro $cont = $param\n";
            #}
            return @allreturn;
        }
    }
    
    sub amiCommand {
    
        # Received an event from Asterisk Manager Interfase
    
        $command  = shift;
    
        if($command eq "LEAVE") {
    
            # Used with fop2-dummy context for writing a line
            # to queue_log so redirects OUT of a queue are not
            # counted as abandoned calls
    
            %event = @_;
            my $return = "";
            my @allreturn = ();
    
            if( defined ( $redirected { $event{Channel} } )) {
                # Este abandono es en realidad una redireccion
                delete $redirected { $event{Channel} };
    
                my $tiempo = time();
                $tiempo = $tiempo + 30;
                my $uniid  = $event{Uniqueid};
                my $queue  = $event{Queue};
    
                $return = "Action: Originate\r\n";
                $return .= "Channel: Local/dummy\@fop2-dummy/n\r\n";
                $return .= "Application: QueueLog\r\n";
                $return .= "Data: $queue,$uniid,NONE,NOTABANDON,0,0,0\r\n";
                $return .= "Async: true\r\n";
                $return .= "\r\n";
    
                push @allreturn, $return;
                return @allreturn;
            }
    
        } elsif($command eq "HANGUP") {
            # Garbage Collect
            %event = @_;
            if( defined ( $redirected { $event{Channel} } )) {
                # Este abandono es en realidad una redireccion
                delete $redirected { $event{Channel} };
            }
        
        } 
    }
    
    1;

    The only changes are the insertion of these two sections:

      	  # New command to set a device state variable
      	  $return  = "Action: SetVar\r\n";
      	  $return .= "Variable: DEVICE_STATE(Custom:DND".$parameters[2].")\r\n";
      	  $return .= "Value: BUSY\r\n";
      	  $return .= "\r\n";
      	  push @allreturn, $return;

    and:

       	 # New command to set a device state variable
       		 $return  = "Action: SetVar\r\n";
       		 $return .= "Variable: DEVICE_STATE(Custom:DND".$parameters[2].")\r\n";
       		 $return .= "Value: NOT_INUSE\r\n";
       		 $return .= "\r\n";
       		 push @allreturn, $return;
  15. This is the full content of the now working extensions_override_fop2.conf:

    [app-dnd-off]
    include => app-dnd-off-custom
    exten => *79,1,Answer
    exten => *79,n,Wait(1)
    exten => *79,n,Macro(user-callerid,)
    ; added for fop2
    exten => *79,n,Set(CHAN=${CUT(CHANNEL,-,1)})
    exten => *79,n,dbDel(fop2state/${CHAN})
    exten => *79,n,UserEvent(FOP2ASTDB,Family: fop2state,Channel: ${CHAN},Value: )
    ; end fop2 addition
    exten => *79,n,Noop(Deleting: DND/${AMPUSER} ${DB_DELETE(DND/${AMPUSER})})
    exten => *79,n,Set(STATE=NOT_INUSE)
    exten => *79,n,Gosub(app-dnd-off,sstate,1())
    exten => *79,n(hook_1),Playback(do-not-disturb&de-activated)
    exten => *79,n,Macro(hangupcall,)
    exten => sstate,1,Set(DEVICE_STATE(Custom:DND${AMPUSER})=${STATE})
    exten => sstate,n,Set(DEVICES=${DB(AMPUSER/${AMPUSER}/device)})
    exten => sstate,n,GotoIf($["${DEVICES}" = "" ]?return)
    exten => sstate,n,Set(LOOPCNT=${FIELDQTY(DEVICES,&)})
    exten => sstate,n,Set(ITER=1)
    exten => sstate,n(begin),Set(DEVICE_STATE(Custom:DEVDND${CUT(DEVICES,&,${ITER})})=${STATE})
    exten => sstate,n,Set(ITER=$[${ITER} + 1])
    exten => sstate,n,GotoIf($[${ITER} <= ${LOOPCNT}]?begin)
    exten => sstate,n(return),Return()
    
    [app-dnd-on]
    include => app-dnd-on-custom
    exten => *78,1,Answer
    exten => *78,n,Wait(1)
    exten => *78,n,Macro(user-callerid,)
    ; added for fop2
    exten => *78,n,Set(DB(DND/${AMPUSER})=YES)
    exten => *78,n,Set(CHAN=${CUT(CHANNEL,-,1)})
    exten => *78,n,Set(DB(fop2state/${CHAN})=Do not Disturb)
    exten => *78,n,UserEvent(FOP2ASTDB,Family: fop2state,Channel: ${CHAN},Value: Do not Disturb)
    ; end fop2 addition
    exten => *78,n,Set(DB(DND/${AMPUSER})=YES)
    exten => *78,n,Set(STATE=BUSY)
    exten => *78,n,Gosub(app-dnd-on,sstate,1())
    exten => *78,n(hook_1),Playback(do-not-disturb&activated)
    exten => *78,n,Macro(hangupcall,)
    exten => sstate,1,Set(DEVICE_STATE(Custom:DND${AMPUSER})=${STATE})
    exten => sstate,n,Set(DEVICES=${DB(AMPUSER/${AMPUSER}/device)})
    exten => sstate,n,GotoIf($["${DEVICES}" = "" ]?return)
    exten => sstate,n,Set(LOOPCNT=${FIELDQTY(DEVICES,&)})
    exten => sstate,n,Set(ITER=1)
    exten => sstate,n(begin),Set(DEVICE_STATE(Custom:DEVDND${CUT(DEVICES,&,${ITER})})=${STATE})
    exten => sstate,n,Set(ITER=$[${ITER} + 1])
    exten => sstate,n,GotoIf($[${ITER} <= ${LOOPCNT}]?begin)
    exten => sstate,n(return),Return()
    
    [app-dnd-toggle]
    include => app-dnd-toggle-custom
    exten => *76,1,Answer
    exten => *76,n,Wait(1)
    exten => *76,n,Macro(user-callerid,)
    exten => *76,n,GotoIf($["${DB(DND/${AMPUSER})}" = ""]?activate:deactivate)
    exten => *76,n(activate),Set(DB(DND/${AMPUSER})=YES)
    ; added for fop2
    exten => *76,n,Set(CHAN=${CUT(CHANNEL,-,1)})
    exten => *76,n,Set(DB(fop2state/${CHAN})=Do not Disturb)
    exten => *76,n,UserEvent(FOP2ASTDB,Family: fop2state,Channel: ${CHAN},Value: Do not Disturb)
    ; end fop2 addition
    exten => *76,n,Set(STATE=BUSY)
    exten => *76,n,Gosub(app-dnd-toggle,sstate,1())
    exten => *76,n(hook_on),Playback(do-not-disturb&activated)
    exten => *76,n,Macro(hangupcall,)
    exten => *76,n(deactivate),Noop(Deleting: DND/${AMPUSER} ${DB_DELETE(DND/${AMPUSER})})
    ; added for fop2
    exten => *76,n,Set(CHAN=${CUT(CHANNEL,-,1)})
    exten => *76,n,dbDel(fop2state/${CHAN})
    exten => *76,n,UserEvent(FOP2ASTDB,Family: fop2state,Channel: ${CHAN},Value: )
    ; end fop2 addition
    exten => *76,n,Set(STATE=NOT_INUSE)
    exten => *76,n,Gosub(app-dnd-toggle,sstate,1())
    exten => *76,n(hook_off),Playback(do-not-disturb&de-activated)
    exten => *76,n,Macro(hangupcall,)
    exten => sstate,1,Set(DEVICE_STATE(Custom:DND${AMPUSER})=${STATE})
    exten => sstate,n,Set(DEVICES=${DB(AMPUSER/${AMPUSER}/device)})
    exten => sstate,n,GotoIf($["${DEVICES}" = "" ]?return)
    exten => sstate,n,Set(LOOPCNT=${FIELDQTY(DEVICES,&)})
    exten => sstate,n,Set(ITER=1)
    exten => sstate,n(begin),Set(DEVICE_STATE(Custom:DEVDND${CUT(DEVICES,&,${ITER})})=${STATE})
    exten => sstate,n,Set(ITER=$[${ITER} + 1])
    exten => sstate,n,GotoIf($[${ITER} <= ${LOOPCNT}]?begin)
    exten => sstate,n(return),Return()
    
    [app-cf-off]
    include => app-cf-off-custom
    exten => *73,1,Answer
    exten => *73,n,Wait(1)
    exten => *73,n,Macro(user-callerid,)
    exten => *73,n,Set(fromext=${AMPUSER})
    exten => *73,n,Noop(Deleting: CF/${fromext} ${DB_DELETE(CF/${fromext})})
    ; added for fop2
    exten => *73,n,Set(CHAN=${DB(DEVICE/${fromext}/dial)})
    exten => *73,n,UserEvent(FOP2CUST,Family: astdbcust,Channel: ${CHAN},Value: )
    ; end fop2 addition
    exten => *73,n,Set(STATE=NOT_INUSE)
    exten => *73,n,Gosub(app-cf-off,sstate,1())
    exten => *73,n(hook_1),Playback(call-fwd-unconditional&de-activated)
    exten => *73,n,Macro(hangupcall,)
    exten => _*73.,1,Answer
    exten => _*73.,n,Wait(1)
    exten => _*73.,n,Set(fromext=${EXTEN:3})
    exten => _*73.,n,Noop(Deleting: CF/${fromext} ${DB_DELETE(CF/${fromext})})
    ; added for fop2
    exten => _*73.,n,Set(CHAN=${DB(DEVICE/${fromext}/dial)})
    exten => _*73.,n,UserEvent(FOP2CUST,Family: astdbcust,Channel: ${CHAN},Value: )
    ; end fop2 addition
    exten => _*73.,n,Set(STATE=NOT_INUSE)
    exten => _*73.,n,Gosub(app-cf-off,sstate,1())
    exten => _*73.,n(hook_2),Playback(call-fwd-unconditional&for&extension)
    exten => _*73.,n,SayDigits(${fromext})
    exten => _*73.,n,Playback(cancelled)
    exten => _*73.,n,Macro(hangupcall,)
    exten => sstate,1,Set(DEVICE_STATE(Custom:CF${fromext})=${STATE})
    exten => sstate,n,Set(DEVICES=${DB(AMPUSER/${fromext}/device)})
    exten => sstate,n,GotoIf($["${DEVICES}" = "" ]?return)
    exten => sstate,n,Set(LOOPCNT=${FIELDQTY(DEVICES,&)})
    exten => sstate,n,Set(ITER=1)
    exten => sstate,n(begin),Set(DEVICE_STATE(Custom:DEVCF${CUT(DEVICES,&,${ITER})})=${STATE})
    exten => sstate,n,Set(ITER=$[${ITER} + 1])
    exten => sstate,n,GotoIf($[${ITER} <= ${LOOPCNT}]?begin)
    exten => sstate,n(return),Return()
    
    [app-cf-on]
    include => app-cf-on-custom
    exten => *72,1,Answer
    exten => *72,n,Wait(1)
    exten => *72,n,Macro(user-callerid,)
    exten => *72,n,Read(fromext,call-fwd-unconditional&please-enter-your&extension&then-press-pound,,,,)
    exten => *72,n,Set(fromext=${IF($["foo${fromext}"="foo"]?${AMPUSER}:${fromext})})
    exten => *72,n,Wait(1)
    exten => *72,n(startread),Read(toext,ent-target-attendant&then-press-pound,,,,)
    exten => *72,n,GotoIf($["foo${toext}"="foo"]?startread)
    exten => *72,n,Wait(1)
    exten => *72,n,Set(DB(CF/${fromext})=${toext})
    ; added for fop2
    exten => *72,n,Set(CHAN=${DB(DEVICE/${fromext}/dial)})
    exten => *72,n,UserEvent(FOP2CUST,Family: astdbcust,Channel: ${CHAN},Value: ${toext} )
    ; end fop2 addition
    exten => *72,n,Set(STATE=BUSY)
    exten => *72,n,Gosub(app-cf-on,sstate,1())
    exten => *72,n(hook_1),Playback(call-fwd-unconditional&for&extension)
    exten => *72,n,SayDigits(${fromext})
    exten => *72,n,Playback(is-set-to)
    exten => *72,n,SayDigits(${toext})
    exten => *72,n,Macro(hangupcall,)
    exten => _*72.,1,Answer
    exten => _*72.,n,Wait(1)
    exten => _*72.,n,Macro(user-callerid,)
    exten => _*72.,n,Set(fromext=${AMPUSER})
    exten => _*72.,n,Set(toext=${EXTEN:3})
    exten => _*72.,n,Set(DB(CF/${fromext})=${toext})
    ; added for fop2
    exten => _*72.,n,Set(CHAN=${DB(DEVICE/${fromext}/dial)})
    exten => _*72.,n,UserEvent(FOP2CUST,Family: astdbcust,Channel: ${CHAN},Value: ${toext} )
    ; end fop2 addition
    exten => _*72.,n,Set(STATE=BUSY)
    exten => _*72.,n,Gosub(app-cf-on,sstate,1())
    exten => _*72.,n(hook_2),Playback(call-fwd-unconditional&for&extension)
    exten => _*72.,n,SayDigits(${fromext})
    exten => _*72.,n,Playback(is-set-to)
    exten => _*72.,n,SayDigits(${toext})
    exten => _*72.,n,Macro(hangupcall,)
    exten => sstate,1,Set(DEVICE_STATE(Custom:CF${fromext})=${STATE})
    exten => sstate,n,Set(DEVICES=${DB(AMPUSER/${fromext}/device)})
    exten => sstate,n,GotoIf($["${DEVICES}" = "" ]?return)
    exten => sstate,n,Set(LOOPCNT=${FIELDQTY(DEVICES,&)})
    exten => sstate,n,Set(ITER=1)
    exten => sstate,n(begin),Set(DEVICE_STATE(Custom:DEVCF${CUT(DEVICES,&,${ITER})})=${STATE})
    exten => sstate,n,Set(ITER=$[${ITER} + 1])
    exten => sstate,n,GotoIf($[${ITER} <= ${LOOPCNT}]?begin)
    exten => sstate,n(return),Return()
    
    ;[fop2-park]
    ; Old fop2-park for asterisk 1.2 or some older 1.4
    ;exten => _X.,1,Set(ARRAY(RETURN_EXTENSION,RETURN_CONTEXT)=${CUT(EXTEN,:,1)},${CUT(EXTEN,:,2)})
    ;exten => _X.,n,ParkAndAnnounce(PARKED,,Console/dsp,${RETURN_CONTEXT},${RETURN_EXTENSION},1)
    ;exten => _X.,n,Goto(${RETURN_CONTEXT},${RETURN_EXTENSION},1)
    ;exten => _X.,n,Hangup
    
    [fop2-park]
    exten => _X.,1,Set(ARRAY(RETURN_EXTENSION,RETURN_CONTEXT,PARKBUTTON)=${CUT(EXTEN,:,1)},${CUT(EXTEN,:,2)},${CUT(EXTEN,:,3)})
    exten => _X.,2,GotoIf($["${PARKBUTTON}" = "PARK/default"?5)
    exten => _X.,3,GotoIf($["${PARKBUTTON}" = ""?5)
    exten => _X.,4,Set(PARKINGLOT=${PARKBUTTON:5})
    exten => _X.,5,Park(,${RETURN_CONTEXT},${RETURN_EXTENSION},1,s)
    
    [fop2-dummy]
    exten => dummy,1,Answer
    exten => dummy,2,Wait(1)
    exten => dummy,3,Hangup
    
  16. I am running Asterisk 1.8.9.3
    and FreePBX 2.10.0.8
    on CentOS_64 bit : Linux 2.6.18-274.3.1.el5 x86_64

    Works for me!

or Sign Up to reply!