Technical : DigitMaps and the OutboundCallRoute
RonR:
I hope the following isn't intimidating and/or totally boring. I thought some might find it interesting to see how the default OBi DigitMaps and OutboundCallRoute work together from a more technical standpoint.
At first glance, it appears each outbound port (ITSPA, ITSPB, LINE, and OBiTALK) has its own DigitMap, each controlling the individual port it's associated with. However, appearances can be deceiving. When you place a call from the OBi's PHONE Port, the PHONE Port DigitMap is the only DigitMap the OBi firmware directly accesses. In reality, the ITSPA, ITSPB, LINE, and OBiTALK DigitMaps only come into play because they're actually part of the PHONE Port DigitMap through indirect references: (Msp1), (Msp2), (Mli), (Mpp), and (Mpli). The OutboundCallRoute also uses these indirect references to the very same DigitMaps.
Internally, the OBi expands these indirect references into single entities. In an OBi set to factory defaults, here's what the OBi actually sees when it processes the PHONE Port DigitMap and OutboundCallRoute to place your call:
PHONE Port DigitMap:
Code:
([1-9]x?*xxxxxxxS4|[1-9]x?*1xxxxxxxxxx|[1-9]x?*xx.|[1-9]|[1-9][0-9]|911|**0|***|#|**11xxxxxxxxxx|**1<1>[2-9]xxxxxxxxx|**1011xx.|**1xx.|**1xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?|**1xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?<*::>xx?x?x?x?|**1[^*]@@.|**21xxxxxxxxxx|**2<1>[2-9]xxxxxxxxx|**2011xx.|**2xx.|**2xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?|**2xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?<*::>xx?x?x?x?|**2[^*]@@.|**8xxxxxxxS4|**81xxxxxxxxxx|**8xx.|**9<ob>xxxxxxxxx|**9obxxxxxxxxx|xxxxxxxS4|1xxxxxxxxxx|xx.)
PHONE Port OutboundCallRoute:
Code:
{([1-9]x?*xxxxxxxS4|[1-9]x?*1xxxxxxxxxx|[1-9]x?*xx.):pp},{(<#:>|911):li},{**0:aa},{***:aa2},{(<**1:>1xxxxxxxxxx|<**1:1>[2-9]xxxxxxxxx|<**1:>011xx.|<**1:>xx.|<**1:>xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?|<**1:>xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?<*::>xx?x?x?x?|<**1:>[^*]@@.):sp1},{(<**2:>1xxxxxxxxxx|<**2:1>[2-9]xxxxxxxxx|<**2:>011xx.|<**2:>xx.|<**2:>xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?|<**2:>xx.<*:@>xx?x?<*:.>xx?x?<*:.>xx?x?<*:.>xx?x?<*::>xx?x?x?x?|<**2:>[^*]@@.):sp2},{(<**8:>xxxxxxxS4|<**8:>1xxxxxxxxxx|<**8:>xx.):li},{(<**9:ob>xxxxxxxxx|<**9:>obxxxxxxxxx):pp},{(xxxxxxxS4|1xxxxxxxxxx|xx.):pli}
By using indirect references to individual groups of rules relating to a particular port, and locating those groups on the page associated with the port they refer to, the PHONE Port DigitMap is infinitely more manageable. Just keep in mind, however, that from the OBi's point of view, it's all part of one PHONE Port DigitMap and one OutboundCallRoute.
If you study the PHONE Port DigitMap and OutboundCallRoute, you'll see there is basically a one-to-one relationship between them. This isn't by accident and it's why it's generally a good idea to leave them both unmodified unless you fully understand the ramifications of changing them. Any alterations you make here are likely to have a profound effect on any indirectly referenced DigitMap that's part of your modification.
When you place a call from the OBi's PHONE Port, the OBi first looks at the expanded PHONE Port DigitMap and locates the single rule that best matches the number you dialed. The resulting number from this process may be different because DigitMaps can transform as well as match. This resulting number is then processed through each element of the expanded OutboundCallRoute, one at a time, left to right, until a matching rule is found. The first match found is the one that dictates which port is to be used for the outbound call.
What's important to take away from all this is that when you make a change to a DigitMap, you must be looking at the whole picture, not just the small fragment on the page you're staring at. With a little effort, it's not difficult to follow the exact path a particular number will take through the PHONE Port DigitMap and OutboundCallRoute.
plugger2:
Quote from: RonR on March 27, 2011, 01:44:38 pm
At first glance, it appears each outbound port (ITSPA, ITSPB, LINE, and OBiTALK) has its own DigitMap, each controlling the individual port it's associated with. However, appearances can be deceiving. When you place a call from the OBi's PHONE Port, the PHONE Port DigitMap is the only DigitMap the OBi firmware directly accesses. In reality, the ITSPA, ITSPB, LINE, and OBiTALK DigitMaps only come into play because they're actually part of the PHONE Port DigitMap through indirect references: (Msp1), (Msp2), (Mli), (Mpp), and (Mpli). The OutboundCallRoute also uses these indirect references to the very same DigitMaps.
RonR,
Your "one step processing" model isn't entirely accurate. For example, if you send a call to a trunk group (say tg1) via the PHONE port OutboundCallRoute, and the trunk group list is (for example):
sp1,sp2,li
then the DigitMaps associated with each of sp1,sp2,li will be evaluated in turn looking for a fit. So it's not accurate to say
"When you place a call from the OBi's PHONE Port, the PHONE Port DigitMap is the only DigitMap the OBi firmware directly accesses."
Of course, unless you are using trunk groups, it is unlikely you will even notice this second-stage checking is even occurring, or encounter problems with it. But if you do run afoul of this (as I did when I started with trunk groups -- very useful feature, BTW), it's good to understand that what's happening under the hood with DigitMap checking is not a one-shot deal.
RonR:
plugger2,
I think you'll find that what I described is accurate. Normally, to introduce Trunk Group 1, you would do so by setting PrimaryLine to 'Trunk Group 1'. Then (Mpli) would point to TG1 and whatever it references (and whatever they reference, and ...) would be expanded into the PHONE Port DigitMap that's actually evaluated. No change to the OutboundCallRoute is necessary. The same would be true if you manually splice TGx or anything else anywhere in any DigitMap.
I'm confident the processing I described doesn't change regardless of what or where you add things. The end result is one huge PHONE Port DigitMap and and one huge OutboundCallRoute, both of which are evaluated as I described.
[I confess I don't know if the expansion of indirect references happens in the literal sense (i.e into a separate linear buffer for processing) or if the parser is written to do it on-the-fly, but the net result is the same either way.]
I hadn't thought about it until now, but it's pretty clear the OutboundCallRoute processing also takes into account whether the port a matching rule would normally select is available. If not, the evaluation process no doubt continues, which would take care of having multiple candidates when a Trunk Group is present. If you run off the end of the OutboundCallRoute without finding a matching rule on a port that's available, you get the error message that there are no routes available for your call.
plugger2:
RonR,
I understand what you are saying, but just so we are on the same page with respect to the actual behaviour, perhaps you can try this experiment:
Create a rule in your OutboundCallRoute that maps a test phone # to say, sp2. Something like
{XXXXXXX:sp2}
where XXXXXXX is your test number.
Now, create a trunk group (say trunk group 2) that has just sp2 in it's list (a rather boring trunk group, but to illustrate the point).
Finally, amend the digitMap for sp2 so that it blocks your test #.
(!XXXXXXX|[whatever else was here])
OK, now you can test what happens when you dial your test number when the OutgoingCallRoute clause is set to
{XXXXXXX:sp2}
as compared to
{XXXXXXX:tg2}
What you will see is that in the first example, the call is accepted by sp2 (the sp2 digitMap blocking of the call is ignored), but in the second instance, the digitMap of sp2 blocks the call.
Leaving aside for one moment the question of whether this inconsistency in behaviour of how and when to treat the sp2 digitMap is a bug or a feature, it does suggest (at least to me) that the processing of the routing is more dynamic than a single stage macro expansion, as you are suggesting above.
Having said that, if indeed the the result of trunk group "hunt" _was_ evaluated as a part of a one-shot macro expansion, as you are suggesting, it would strike me as a rather odd design decision to do it that way.
It would be odd because it would be unduly limiting to how the "hunt" could be conducted -- only information at hand on the availability of service on each port at one point in time could be used, which is at odds with the essential time sequential nature of the search.
Dynamic processing, more in the style of an interpreter, rather than in the static style of a macro processor, would be much more natural, and extensible. For example, using a dynamic processing model, it would be possible to do "deep" trunk group hunting (which is actually one of my fond hopes for the future as requested in the Feature Requests subforum http://www.obitalk.com/forum/index.php?topic=420.0), whereas using a static macro expansion model, it wouldn't.
But, odd or not, I suppose it is possible.
Perhaps an OBi engineer can chime in to clarify the nature of these deep philosophical questions. :-)
RonR:
Quote from: plugger2 on March 27, 2011, 09:18:23 pm
Create a rule in your OutboundCallRoute that maps a test phone # to say, sp2. Something like
{XXXXXXX:sp2}
where XXXXXXX is your test number.
Where in the OutboundCallRoute are you placing this? Placement is critical in the OutboundCallRoute as evaluation occurs left to right and stops on the first match. If all the rules prior to this one fail, then this one will unconditionally send XXXXXXX out the SP2 port.
Quote from: plugger2 on March 27, 2011, 09:18:23 pm
Now, create a trunk group (say trunk group 2) that has just sp2 in it's list (a rather boring trunk group, but to illustrate the point).
Where are you referencing TG2 from? A trunk group has to be referenced in another digit map or call routing rule in order to be used. Just putting something in TG2's TrunkList and DigitMap doesn't make TG2 magically spring to life. (Your later example of {XXXXXXX:tg2} isn't valid syntax, so it doesn't count.)
Quote from: plugger2 on March 27, 2011, 09:18:23 pm
Finally, amend the digitMap for sp2 so that it blocks your test #.
(!XXXXXXX|[whatever else was here])
That rule is only interesting if PrimaryLine is SP2 or you're dialing the number as **2XXXXXXX. Otherwise, none of the rules in the SP2 DigitMap will be evaluated.
Quote from: plugger2 on March 27, 2011, 09:18:23 pm
OK, now you can test what happens when you dial your test number when the OutgoingCallRoute clause is set to
{XXXXXXX:sp2}
as compared to
{XXXXXXX:tg2}
What you will see is that in the first example, the call is accepted by sp2 (the sp2 digitMap blocking of the call is ignored), but in the second instance, the digitMap of sp2 blocks the call.
Your first example simply sends XXXXXXX out the SP2 port. No DigitMaps anywhere are evaluated. Of course it's accepted. The second example isn't valid. The terminal specifier has to be PH, AA, LI, SPx, or PP. It can't be a trunk group. I'm guessing the OBi simply ignored it.
Quote from: plugger2 on March 27, 2011, 09:18:23 pm
Having said that, if indeed the the result of trunk group "hunt" _was_ evaluated as a part of a one-shot macro expansion, as you are suggesting, it would strike me as a rather odd design decision to do it that way.
It would be odd because it would be unduly limiting to how the "hunt" could be conducted -- only information at hand on the availability of service on each port at one point in time could be used, which is at odds with the essential time sequential nature of the search.
Dynamic processing, more in the style of an interpreter, rather than in the static style of a macro processor, would be much more natural, and extensible. For example, using a dynamic processing model, it would be possible to do "deep" trunk group hunting (which is actually one of my fond hopes for the future as requested in the Feature Requests subforum), whereas using a static macro expansion model, it wouldn't.
I can't figure out what kind of dynamic processing and "deep" trunk group hunting you're hoping for. The evaluation of the OutboundCallRoute is virtually instantaneous and the OBi always knows which of its ports are in use and which are available. How is anything limited, unduly or otherwise? With the current implementation, the OBi will use the first available port that's not in use from a trunk group list whose rule matches (and even in the order specified) and the call will be on its way. What else are you wanting to happen?
The PHONE Port DigitMap + OutboundCallRoute scheme currently implemented in the OBi is actually pretty elegant. Maybe my explanation of how it works isn't as clear as I'd hoped it would be.
Navigation
[0] Message Index
[#] Next page