![]() | |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
Can the following be done in D3/NT? We have just installed a Shoretel phone system, and I've integrated it into our order taking application in D3. What I do is the following: I've written a VB.NET program that reads the Caller ID when a salesperson answers the phone and writes it to a little DOS text file. I've also created an MD in D3 that points to that DOS subdirectory, so it can treat the DOS text file as a regular mv record. When the salesperson picks up the phone, the VB.NET program executes and writes the Caller ID to the DOS file. Then in the D3 order taking program, the sales person hits a key which causes the program to read that text file and search for that phone number in the Customer file. If it finds the exact phone number, it displays the customers record. If it doesn't find the exact phone number (the customer may have many extensions or DID numbers), we update this new number into the Customer file, so the next time the customer calls using that DID number we have it on record. All this works fine. However, I'd like to avoid forcing the salesperson to hit a key to start the search. I'd like the D3 program to "sense" that the DOS record exists, and start the ball rolling by itself without user action. The problem is that at that moment the D3 order taking program is sitting on an INPUT statement. You can't "tell" an INPUT statement anything, nor can the system "tell" it anything. It's just waiting for user input. So I have no way to force the D3 program to "poll" for the existence of the DOS record while it's sitting at that INPUT statement. I tried using the "INPUT x FOR 20 THEN ... ELSE..." version of the INPUT statement to "poll" the DOS file every 2 seconds. While this works technically, it causes other problems. The "INPUT ...FOR" version requires that the user finish typing their input within those 2 seconds, otherwise it reverts the cursor back to position 1. So if a person is typing "HELLO" and the 2 seconds are up before the "O", the input becomes "OELL". This clearly won't work. So I'm wondering if anyone has another way of "polling" while a D3 program is sitting at an INPUT statement. Any ideas would be appreciated. Thanks in advance. Sholom |
#3
| |||
| |||
|
|
Sholom, that's a very cool app. We have a client integrating with a virtual PBX now, what I'm starting to brand as NebulaVBX. I may face the exact same situation. I just blogged about some phone integration yesterday that is somewhat related to what you're talking about: no.spam.pleaseNebula-RnD.com/blog/tech/mv/2011/02/sms1.html I don't have a solid answer to your question yet. I don't believe D3NT has an interrupt as you describe, and of course we don't have multiple threads to handle background reads while the user is at input. But I think there is a logical error here where the service rep is passed a phone call for which they need information, and yet they're already typing something. If they are available for a call, they should probably be in a wait loop rather than at an input statement. If they are typing something that shouldn't be interrupted, that activity should be processed to its fruition and then a check can be made for some new activity. So in this case it seems you'd either want to check for a new call after each input statement (hopefully you have one input routine for the whole screen) and/or you can check in some "central" place like a bottom line option input area which gets hit frequently when the user is not in data entry mode. BTW, if the OSFI file that you're reading is not on the same system look into the OnNetError command for D3v9. Most or all CRUD statements in BASIC also have an ONERR clause (poorly documented) which prevents falling to debug if a network resource is unavailable. Any thoughts on that so far? HTH T Sholom wrote: Can the following be done in D3/NT? We have just installed a Shoretel phone system, and I've integrated it into our order taking application in D3. What I do is the following: I've written a VB.NET program that reads the Caller ID when a salesperson answers the phone and writes it to a little DOS text file. I've also created an MD in D3 that points to that DOS subdirectory, so it can treat the DOS text file as a regular mv record. When the salesperson picks up the phone, the VB.NET program executes and writes the Caller ID to the DOS file. Then in the D3 order taking program, the sales person hits a key which causes the program to read that text file and search for that phone number in the Customer file. If it finds the exact phone number, it displays the customers record. If it doesn't find the exact phone number (the customer may have many extensions or DID numbers), we update this new number into the Customer file, so the next time the customer calls using that DID number we have it on record. All this works fine. However, I'd like to avoid forcing the salesperson to hit a key to start the search. I'd like the D3 program to "sense" that the DOS record exists, and start the ball rolling by itself without user action. The problem is that at that moment the D3 order taking program is sitting on an INPUT statement. You can't "tell" an INPUT statement anything, nor can the system "tell" it anything. It's just waiting for user input. So I have no way to force the D3 program to "poll" for the existence of the DOS record while it's sitting at that INPUT statement. I tried using the "INPUT x FOR 20 THEN ... ELSE..." version of the INPUT statement to "poll" the DOS file every 2 seconds. While this works technically, it causes other problems. The "INPUT ...FOR" version requires that the user finish typing their input within those 2 seconds, otherwise it reverts the cursor back to position 1. So if a person is typing "HELLO" and the 2 seconds are up before the "O", the input becomes "OELL". This clearly won't work. So I'm wondering if anyone has another way of "polling" while a D3 program is sitting at an INPUT statement. Any ideas would be appreciated. Thanks in advance. Sholom |
#4
| |||
| |||
|
|
Sholom, that's a very cool app. We have a client integrating with a virtual PBX now, what I'm starting to brand as NebulaVBX. I may face the exact same situation. I just blogged about some phone integration yesterday that is somewhat related to what you're talking about: no.spam.pleaseNebula-RnD.com/blog/tech/mv/2011/02/sms1.html I don't have a solid answer to your question yet. I don't believe D3NT has an interrupt as you describe, and of course we don't have multiple threads to handle background reads while the user is at input. But I think there is a logical error here where the service rep is passed a phone call for which they need information, and yet they're already typing something. If they are available for a call, they should probably be in a wait loop rather than at an input statement. If they are typing something that shouldn't be interrupted, that activity should be processed to its fruition and then a check can be made for some new activity. So in this case it seems you'd either want to check for a new call after each input statement (hopefully you have one input routine for the whole screen) and/or you can check in some "central" place like a bottom line option input area which gets hit frequently when the user is not in data entry mode. BTW, if the OSFI file that you're reading is not on the same system look into the OnNetError command for D3v9. Most or all CRUD statements in BASIC also have an ONERR clause (poorly documented) which prevents falling to debug if a network resource is unavailable. Any thoughts on that so far? HTH T Sholom wrote: Can the following be done in D3/NT? We have just installed a Shoretel phone system, and I've integrated it into our order taking application in D3. What I do is the following: I've written a VB.NET program that reads the Caller ID when a salesperson answers the phone and writes it to a little DOS text file. I've also created an MD in D3 that points to that DOS subdirectory, so it can treat the DOS text file as a regular mv record. When the salesperson picks up the phone, the VB.NET program executes and writes the Caller ID to the DOS file. Then in the D3 order taking program, the sales person hits a key which causes the program to read that text file and search for that phone number in the Customer file. If it finds the exact phone number, it displays the customers record. If it doesn't find the exact phone number (the customer may have many extensions or DID numbers), we update this new number into the Customer file, so the next time the customer calls using that DID number we have it on record. All this works fine. However, I'd like to avoid forcing the salesperson to hit a key to start the search. I'd like the D3 program to "sense" that the DOS record exists, and start the ball rolling by itself without user action. The problem is that at that moment the D3 order taking program is sitting on an INPUT statement. You can't "tell" an INPUT statement anything, nor can the system "tell" it anything. It's just waiting for user input. So I have no way to force the D3 program to "poll" for the existence of the DOS record while it's sitting at that INPUT statement. I tried using the "INPUT x FOR 20 THEN ... ELSE..." version of the INPUT statement to "poll" the DOS file every 2 seconds. While this works technically, it causes other problems. The "INPUT ...FOR" version requires that the user finish typing their input within those 2 seconds, otherwise it reverts the cursor back to position 1. So if a person is typing "HELLO" and the 2 seconds are up before the "O", the input becomes "OELL". This clearly won't work. So I'm wondering if anyone has another way of "polling" while a D3 program is sitting at an INPUT statement. Any ideas would be appreciated. Thanks in advance. Sholom |
#5
| |||
| |||
|
|
I think the INPUT x FOR ... instruction is the closest we'll get to interrupts. Perhaps TL can add an option that doesn't return the cursor to position 1. Hmmm. Just thinking. I wonder if I can write a routine that analyzes what's in x and then I'll position the cursor myself. I'll have to play with that idea. Sholom |
#6
| |||
| |||
|
|
I think the INPUT x FOR ... instruction is the closest we'll get to interrupts. Perhaps TL can add an option that doesn't return the cursor to position 1. Hmmm. Just thinking. I wonder if I can write a routine that analyzes what's in x and then I'll position the cursor myself. I'll have to play with that idea. Sholom On 2/16/2011 2:52 PM, Tony Gravagno wrote: Sholom, that's a very cool app. *We have a client integrating with a virtual PBX now, what I'm starting to brand as NebulaVBX. *I may face the exact same situation. *I just blogged about some phone integration yesterday that is somewhat related to what you're talking about: no.spam.pleaseNebula-RnD.com/blog/tech/mv/2011/02/sms1.html I don't have a solid answer to your question yet. *I don't believe D3NT has an interrupt as you describe, and of course we don't have multiple threads to handle background reads while the user is at input. But I think there is a logical error here where the service rep is passed a phone call for which they need information, and yet they're already typing something. *If they are available for a call, they should probably be in a wait loop rather than at an input statement. If they are typing something that shouldn't be interrupted, that activity should be processed to its fruition and then a check can be made for some new activity. *So in this case it seems you'd either want to check for a new call after each input statement (hopefully you have one input routine for the whole screen) and/or you can check in some "central" place like a bottom line option input area which gets hit frequently when the user is not in data entry mode. BTW, if the OSFI file that you're reading is not on the same system look into the OnNetError command for D3v9. *Most or all CRUD statements in BASIC also have an ONERR clause (poorly documented) which prevents falling to debug if a network resource is unavailable. Any thoughts on that so far? HTH T Sholom wrote: Can the following be done in D3/NT? We have just installed a Shoretel phone system, and I've integrated it into our order taking application in D3. What I do is the following: I've written a VB.NET program that reads the Caller ID when a salesperson answers the phone and writes it to a little DOS text file. I've also created an MD in D3 that points to that DOS subdirectory, so it can treat the DOS text file as a regular mv record. When the salesperson picks up the phone, the VB.NET program executes and writes the Caller ID to the DOS file. Then in the D3 order taking program, the sales person hits a key which causes the program to read that text file and search for that phone number in the Customer file. If it finds the exact phone number, it displays the customers record. If it doesn't find the exact phone number (the customer may have many extensions or DID numbers), we update this new number into the Customer file, so the next time the customer calls using that DID number we have it on record. All this works fine. However, I'd like to avoid forcing the salesperson to hit a key to start the search. I'd like the D3 program to "sense" that the DOS record exists, and start the ball rolling by itself without user action. The problem is that at that moment the D3 order taking program is sitting on an INPUT statement. You can't "tell" an INPUT statement anything, nor can the system "tell" it anything. It's just waiting for user input. So I have no way to force the D3 program to "poll" for the existence of the DOS record while it's sitting at that INPUT statement.. I tried using the "INPUT x FOR 20 THEN ... ELSE..." version of the INPUT statement to "poll" the DOS file every 2 seconds. While this works technically, it causes other problems. The "INPUT ...FOR" version requires that the user finish typing their input within those 2 seconds, otherwise it reverts the cursor back to position 1. So if a person is typing "HELLO" and the 2 seconds are up before the "O", the input becomes "OELL". This clearly won't work. So I'm wondering if anyone has another way of "polling" while a D3 program is sitting at an INPUT statement. Any ideas would be appreciated. Thanks in advance. Sholom- Hide quoted text - - Show quoted text - |
#7
| ||||
| ||||
|
|
The sales rep is (almost) always sitting at that INPUT statement. |
|
It's the "customer code" prompt on the order screen. So the rep might be sitting at his/her desk doing paperwork, while the cursor is at that prompt. When the phone rings, they are at that prompt, ready to enter the customer code. They haven't typed anything yet. When they hit the magic key, that's when I can get the process started. |

|
I don't understand what you mean by a "wait loop". Please explain. |
|
Another thing I'm wondering about - even if I could do this background polling, what would it take in system resources? What would be the cost if I had 10-15 people polling every 2-3 seconds? That could potentially be an additional 450 disk accesses every minute, minute after minute. I have no idea what effect that might have until I actually try it? |

#8
| |||
| |||
|
|
G'day Sholom, You haven't mentioned what telnet app you are using ... if it was something like Accuterm then your VB.NET process should be able to use automation to pump stuff into the accuterm session, navigate to your order entry process etc .... indeed, you may be able to do away with the intermediate DOS file, as the information could be passed staight down the Telnet pipe. |
|
As to not returning to position 1 after an input, I thought most people already had generalized I/O routines that used something like the IN statement, making it reasonably trivial to "interrupt" input, and also do other "interesting" stuff (eg: this is where/how we drive our macro/keybroad automation routines from our classic R5 product) |
#9
| |||
| |||
|
|
On Feb 17, 8:33 am, sh<sham... (AT) prupipe (DOT) com> wrote: I think the INPUT x FOR ... instruction is the closest we'll get to interrupts. Perhaps TL can add an option that doesn't return the cursor to position 1. Hmmm. Just thinking. I wonder if I can write a routine that analyzes what's in x and then I'll position the cursor myself. I'll have to play with that idea. Sholom I do what you are looking to do using the IN xxx FOR...... statement. It takes one character at a time, so doesn't set you back to the start of the input. Obviously, there is a bit of coding to string the input together but it allows for better control. Geoff |
#10
| |||
| |||
|
|
Sholom wrote: The sales rep is (almost) always sitting at that INPUT statement. If they're not at the right prompt, I'd suggest that they shouldn't get a phone call. In other words, the user is either in an Available or Busy state and they must indicate their state to the server, if only perhaps by closing a call or leaving the main menu and going to the top of a specific program. If their state is Busy, no call is passed to them and no data is written for their process to pick up. I understand that "things happen" in the real world but for our purposes now, you can only manipulate the user's screen if you think they're not active. It's the "customer code" prompt on the order screen. So the rep might be sitting at his/her desk doing paperwork, while the cursor is at that prompt. When the phone rings, they are at that prompt, ready to enter the customer code. They haven't typed anything yet. When they hit the magic key, that's when I can get the process started. That's where I'm confused. If the server is providing the data then what are they typing when they get a phone call? That's exactly the time when they shouldn't be touching the keyboard. No magic key should be required because when they're in the Available state you should have freedom to control their screen. If they are Busy, you probably don't want to send them a call. If I were approaching this, and answering calls as fast as possible was a priority, I'd use a PBX mechanism to call all Available phones, and when the first rep answers the phone, the call is terminated for all others, the live customer is transferred to the rep that answered, and simultaneously the reps screen is loaded with data. I can do this with my VBX anyway. ![]() I don't understand what you mean by a "wait loop". Please explain. Until you have a better option I was thinking about something like this (not verified) : REQUEST = "" AVAILABLE = 1 LOOP IN X FOR 20 THEN IF X = 8 THEN ; * handle backspace REQUEST = REQUEST[1,LEN(REQUEST)-1] END ELSE IF X # "" THEN REQUEST := CHAR(X) END IF REQUEST # "" AND AVAILABLE THEN AVAILABLE = 0 * user is doing something, tell phone system no transfers GOSUB CHANGE.USER.STATUS END IF REQUEST = "" AND NOT(AVAILABLE) THEN AVAILABLE = 1 GOSUB CHANGE.USER.STATUS END END READ CALL.DATA FROM F.CALLS,@PIB ELSE CALL.DATA = NULL UNTIL X = 13 OR CALL.DATA # "" DO REPEAT ; * stay in loop if no crlf * Process request, or ignore it and handle call data D3 actually does have an in-memory interprocess communications mechanism but I was told about a year ago that it's not supported, even though it's documented. That's a shame, it's one of D3's neat but never-used features. I'll see if I can get some verification on the status of this. Another thing I'm wondering about - even if I could do this background polling, what would it take in system resources? What would be the cost if I had 10-15 people polling every 2-3 seconds? That could potentially be an additional 450 disk accesses every minute, minute after minute. I have no idea what effect that might have until I actually try it? I get concerned about such things too but 10-15 people polling even every 1 second is negligible. I wouldn't have 15 network processes hitting a socket every second, but servers-side disk IO is OK. This is probably a bad idea but if you only have that small number of people, you might consider using a LOCK statement which "may" not have the same overhead as file IO -- I really don't know. For example, rather than using the READ statement above, try to get a LOCK on a rep number, from 1 to 15: LOCK REP.ID THEN * Nothing to do, we own this lock UNLOCK REP.ID END ELSE * Phone handler set a lock for this sales rep READ CALL.DATA FROM F.CALLS,REP.ID ELSE NULL * Tell handler we have this call DELETE F.CALLS, CALL.DATA * Handler should release lock when it sees rec is gone END I hope even a bad idea helps to point you to a good solution. ![]() Regards, T |
![]() |
| Thread Tools | |
| Display Modes | |
| |