0

I have a small problem. I have a variableCTI_VARIABLES with this content:

cti_CallDirection=1@;cti_ContractNumber=00202417@;cti_TransferVDN=48195@;cti_IvrButton=1

Each different variable within this variable is marked "@;" separated by . I’m trying to separate them with the CUT() function. But it only returns the first one, because it accepts a single character as an argument. How can I do it when I want to separate by two characters?

Here is my dialplan code

exten => addheader,1,NoOp(CTI_VARIABLES: ${CTI_VARIABLES})
same => n,GotoIf($["${CTI_VARIABLES}" = ""]?noVariables)
same => n,Set(TOTAL_VARS=${FIELDQTY(CTI_VARIABLES,@\;)})
same => n,Set(COUNTER=1)
same => n,While($[${COUNTER} <= ${TOTAL_VARS}])
same => n,Set(CURRENT_VAR=${CUT(CTI_VARIABLES,@\;,${COUNTER})})
same => n,Set(VAR_NAME=${CUT(CURRENT_VAR,\=,1)})
same => n,Set(VAR_VALUE=${CUT(CURRENT_VAR,\=,2)})
same => n,Set(PJSIP_HEADER(add,${VAR_NAME})=${VAR_VALUE})
same => n,NoOp(${VAR_NAME}: ${VAR_VALUE})
same => n,Set(COUNTER=$[${COUNTER}+1])
same => n,EndWhile
same => n(noVariables),NoOp(No CTI Variables Set)

I also tried using the FIELDQTY() function with no luck:

TOTAL_VARS=${FIELDQTY(CTI_VARIABLES,\@\;)}
TOTAL_VARS=${FIELDQTY(CTI_VARIABLES,@;)}
desertnaut
60.8k32 gold badges155 silver badges183 bronze badges
asked Feb 8, 2024 at 6:39
1
  • I edited your question for clarity, although it's a bit unclear what problem you were facing when using CUT(). In your dialpan as presented, it should have returned names and values for all 4 iterations of the loop. I suspect your problem is that the names would have been prefixed with a semicolon, which would have to be cleaned up before use with PJSIP_HEADER(). I think my answer is a neater way around that issue. Commented Feb 8, 2024 at 18:36

3 Answers 3

2

Why you ever may need count something for this simple task?

So. Let me give you "the asterisk way":

; noop actually not needed, because MSet will show you all variables
exten => addheader,1,NoOp(CTI_VARIABLES: ${CTI_VARIABLES})
same => n,Set(MVAR=${STRREPLACE(CTI_VARIABLES,@;,,円)}); replace all @; to comma
same => n,MSet(${MVAR}); put all names/vars on channel
; actually if you know variable names, you not need all below
; same=>n,Dumpchan();uncomment this if you want to see result.
same => n(loop),ExecIf($[ "${MVAR}" == "" ]?Return()); exit
same => n,Set(VAR=${CUT(MVAR,,,1円)}); get next one
same => n,Set(MVAR=${CUT(MVAR,,,2円-)}); put from second back in string
; at this moment VAR has variable name and MVAR have other pairs without ${VAR}=${${VAR}}
same => n,Set(VAR_NAME=${CUT(VAR,=,1)}); get only name
same => n,Set(PJSIP_HEADER(add,${VAR_NAME})=${${VAR_NAME}); catch it from channel and put in header
same => n,Goto(loop); next one

Thats ALL

Short tips WHY all those are working.

MSet syntax is like this

[Syntax]
MSet(name1=value1[,name2=value2[,...]])

And it will set all variables in one command

if you are using

 ${${VAR}}

asterisk will take value of variable VAR and put value of variable with that name.

If cut have no delimiter, and you asking for second param, it return empty string.

So ACTUALLY perfect way is return all info you need from your CURL request or AGI or whatever source of those variables in format like this

cti_CallDirection=1,cti_ContractNumber=00202417,cti_TransferVDN=48195,cti_IvrButton=1

After that make single MSet and put READABLE dialplan for headers.

answered Feb 9, 2024 at 3:37
Sign up to request clarification or add additional context in comments.

1 Comment

Thank for your answer. I didn't have to count anything. This is just the solution I found. It is set as a single variable by AGI. All Variables are dynamic, that is, different variables come for different calls and I do not know their names.
0

The easy answer is to fix your AGI to output something more useful. Asterisk's dialplan syntax is pretty terrible for doing any real programming tasks, and a good philosophy is to avoid doing anything in dialplan that you can do elsewhere. Ideally in this case, you'd be populating individual variables with values.

But if that is not an option, then just replace the @; sequence with a single character before processing it.

STRREPLACE(CTI_VARIABLES,@;,;)

Now you can use CUT() on the semicolon.

Full diaplan (untested)

exten => addheader,1,NoOp(CTI_VARIABLES: ${CTI_VARIABLES})
same => n,GotoIf($["${CTI_VARIABLES}" = ""]?noVariables)
same => n,Set(CTI_VARIABLES=${STRREPLACE(CTI_VARIABLES,@;,;)})
same => n,Set(TOTAL_VARS=${FIELDQTY(CTI_VARIABLES,;)})
same => n,Set(COUNTER=1)
same => n,While($[${COUNTER} <= ${TOTAL_VARS}])
same => n,Set(CURRENT_VAR=${CUT(CTI_VARIABLES,;,${COUNTER})})
same => n,Set(VAR_NAME=${CUT(CURRENT_VAR,=,1)})
same => n,Set(VAR_VALUE=${CUT(CURRENT_VAR,=,2)})
same => n,Set(PJSIP_HEADER(add,${VAR_NAME})=${VAR_VALUE})
same => n,NoOp(${VAR_NAME}: ${VAR_VALUE})
same => n,Set(COUNTER=$[${COUNTER}+1])
same => n,EndWhile
same => n(noVariables),NoOp(No CTI Variables Set)

Note you shouldn't need to do any escaping unless you're dealing with commas; Asterisk's argument parsing is pretty basic.

answered Feb 8, 2024 at 18:23

5 Comments

Why are you replacing @; with ; if you can just replace @ with empty string? :)
Just in case there is @ in the data somewhere. I know there could be @; in the data but seems less likely
There is INC function available ;) Example: INC(MyVAR) - Increments MyVar
You not need count total vars. If CUT return empty string, that mean you are done.
Just copying the loop that was there. But your suggestion of MSET() is a much better solution anyway
-2

It appears that you are attempting to use the CUT function in your dialplan code to divide the variables within the CTI_VARIABLES string. yet the problem you have is that you have a two-character delimiter, "@;," yet CUT only allows one character as the delimiter. The REGEX function is used in the line CURRENT_VAR=${REGEX(${CTI_VARIABLES},([^@;]+)@;,,${COUNTER})} to extract each variable individually using the regex pattern ([^@;]+)@;. This pattern records one or more non-"@" or ";" characters, then follows them with "@;". One variable at a time is extracted in the while loop by using the ${COUNTER} option in the REGEX function. Setting the variable name, variable value, and adding them as PJSIP headers are done using the same code as before.

answered Feb 8, 2024 at 6:47

2 Comments

In addition to being completely unreadable, this appears to be generated content from a so-called "AI" system. You must have seen the large banner when you tried posting an answer telling you that such content is banned here. Do not post it.
I am pretty sure it will not work because regexp in asterisk should not support that, no?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.