NEC Projector Feedback and buffers
TUTech
Junior Member
I'm trying to get the feedback to work on an NEC Projector. Trying to light the ON/OFF buttons on the control panel. Sometimes the remote control gets used to turn the projector on or off.
This is what I have. It does compile, but doesn't do anything.
It is being controlled as an actual device, not a virtual.
DEFINE_DEVICE
Projector = 5001:1:0
DEFINE_CONSTANT
(*Projector power status*)
PROS_ON = 1
PROS_OFF = 2
DEFINE_VARIABLE
PRO_Buffer[100]
PRO_Status
DEFINE_START
CREATE_BUFFER Projector,PRO_Buffer
DEFINE_PROGRAM
SEND_STRING Projector,”$00,$81,$00,$00,$00,$81” //Running Sense
WAIT 10
IF (PRO_Buffer =’ $81$01@$01$02$E5’)
PRO_Status = PROS_ON
[TP,9] = (PRO_Status = PROS_ON) //Turn on “ON” button
IF (PRO_Buffer =’ $81$01@$01$00$E3’)
PRO_Status = PROS_OFF
[TP,10] = (PRO_Status = PROS_OFF) //Turn on “OFF” button
CLEAR_BUFFER PRO_BUFFER
1)The response that I am supposed to get is $22$00$01$xx$00 CKS, the above responses are consistent when using "Control a Device"
2)I know they are Hex, but as far as the buffer and NetLinx is concerned they are just characters?
3)Should the whole thing go into a DATA_EVENT?
4)Most of the examples on the forum show using DATA.TEXT which is followed by a comment that you should NOT use DATA.TEXT on an actual device?
5)I could use FIND_STRING, but is it necessary?
6)I tried using single quotes inside of double quotes, but it won't compile.
Thanks
This is what I have. It does compile, but doesn't do anything.
It is being controlled as an actual device, not a virtual.
DEFINE_DEVICE
Projector = 5001:1:0
DEFINE_CONSTANT
(*Projector power status*)
PROS_ON = 1
PROS_OFF = 2
DEFINE_VARIABLE
PRO_Buffer[100]
PRO_Status
DEFINE_START
CREATE_BUFFER Projector,PRO_Buffer
DEFINE_PROGRAM
SEND_STRING Projector,”$00,$81,$00,$00,$00,$81” //Running Sense
WAIT 10
IF (PRO_Buffer =’ $81$01@$01$02$E5’)
PRO_Status = PROS_ON
[TP,9] = (PRO_Status = PROS_ON) //Turn on “ON” button
IF (PRO_Buffer =’ $81$01@$01$00$E3’)
PRO_Status = PROS_OFF
[TP,10] = (PRO_Status = PROS_OFF) //Turn on “OFF” button
CLEAR_BUFFER PRO_BUFFER
1)The response that I am supposed to get is $22$00$01$xx$00 CKS, the above responses are consistent when using "Control a Device"
2)I know they are Hex, but as far as the buffer and NetLinx is concerned they are just characters?
3)Should the whole thing go into a DATA_EVENT?
4)Most of the examples on the forum show using DATA.TEXT which is followed by a comment that you should NOT use DATA.TEXT on an actual device?
5)I could use FIND_STRING, but is it necessary?
6)I tried using single quotes inside of double quotes, but it won't compile.
Thanks
Comments
-
I've recently built a NEC Projector module as well and yours is probably similar. When you ask the projector for an update it returns a string of about 133 hex symbols (as a text string).
I dump all that into a buffer and then execute a set of find_String commands once the buffer sees a checksum.
I had the best luck running that through a function to convert to a hex array. Here is the function that I found on these forums.WHILE(LENGTH_ARRAY(cInString)) { cTempByte = GET_BUFFER_CHAR(cInString); //Grab one byte from the input cStringRXCleanHex[nCounter] = FORMAT('$%02X,',cTempByte) nCounter++ }
Now in the main define program I have this:ACTIVE (FIND_STRING(cStringRXCleanHex[2],"'BF'",1) AND FIND_STRING(cStringRXCleanHex[6],"'02'",1)) : //Projector Information Request Result { nStatus[1] = atoi(cStringRXCleanHex[7]) // Processing Status nStatus[7] = atoi(cStringRXCleanHex[8]) //Picture Status nStatus[4] = atoi(cStringRXCleanHex[9]) //Input nStatus[6] = atoi(cStringRXCleanHex[12]) //Picture Mute }
I personally liked this method because I don't have to parse through each returned Hex in the string and instead just dump it into an array. No counting needed and the array ID lines up with the returned string. -
Some code Best Practice for you.
I would not put this kind of thing in Define_program. You'll see a lot of debate on the forum as to when to use Def_Prog (or even if at all - of which I am in that camp). But either way I'd not put anything processor intensive in Def_Program. the best practice is to limit it to feedback only, not string processing.
You might want to look at using the Data_Event in Define_Event.define_event data_event[dvProj]{ string:{ If(find_string(MyBuffer,"$01,02'etc..",1)){ Proj_power=1; } If(find_string(MyBuffer,"$99,$98,etc...",1)){ Proj_power=0; } fn_Update_Proj_Power_fb() // make a function or call to update the TP button feedback } }
This is just a simple example but you'll get the idea. -
I would not put this kind of thing in Define_program. You'll see a lot of debate on the forum as to when to use Def_Prog (or even if at all - of which I am in that camp). But either way I'd not put anything processor intensive in Def_Program. the best practice is to limit it to feedback only, not string processing.
Yes I noticed, a lot of debate!!
I made a Data_Event. It worked, except the Send_String to send the Running Sense. I had to put it in the Define Programming. I also had to make the ON/OFF button mutually exclusive or else they would both turn on and stay on. -
This is what I ended up with...
DEFINE_MUTUALLY_EXCLUSIVE
([TP,9],[TP,10])
DEFINE_START
CREATE_BUFFER Projector,PBUFFER
CLEAR_BUFFER PBUFFER
DEFINE_EVENT
DATA_EVENT [Projector]
{
STRING:
{
IF(LENGTH_STRING(PBUFFER))
{
SELECT
{
ACTIVE(FIND_STRING(PBUFFER,"$81,$01,'@',$01,$02,$E5",1)):
{PROJ_Status=PROS_ON
[TP,9] = (PROJ_Status=PROS_ON)}
ACTIVE(FIND_STRING(PBUFFER,"$81,$01,'@',$01,$00,$E3",1)):
{PROJ_Status=PROS_OFF
[TP,10] = (PROJ_Status=PROS_OFF)}
}}
PBUFFER=""
}
}
DEFINE_PROGRAM
WAIT 300
SEND_STRING Projector,"$00,$81,$00,$00,$00,$81" //Running Sense -
I use data.text all the time from serial/IP devices, and it hasn't failed me yet. I think its faster than create_buffer as well, and requires less code so use it as needed. The only caveat is that since its a small buffer, around 2000 bytes, for devices that have feedback with much longer strings, you may need to combine buffers to get the full response. I've noticed some odd things occurring with create_buffer in terms of timing so I've stayed away from it.
Paul -
I've definitely broken "create_buffer" with some things I've tried to do, and have learned the hard way to stay away from it. I always just manually add data.text to whatever buffer I've defined for a device:
... string: { devicebuffer = "devicebuffer,data.text" }...then my buffer processing picks up whatever got put in the buffer and works with it. -
ACTIVE(FIND_STRING(PBUFFER,"$81,$01,'@',$01,$02,$E5",1)): {PROJ_Status=PROS_ON [b][i][TP,9] = (PROJ_Status=PROS_ON)}[/i][/b] ACTIVE(FIND_STRING(PBUFFER,"$81,$01,'@',$01,$00,$E3",1)): {PROJ_Status=PROS_OFF [b][i]][TP,10] = (PROJ_Status=PROS_OFF)}[/i][/b] }} PBUFFER="" } }
A side issue for you...
the two feedback statements are a bit unnecessary. Since you've already done the string operatoion to determine the status of the projector and set the stat variable to "on" or "off" you don't need to redo the check in the statement where you check again and make the TP button go on or off. Just go ahead and turn the button on or off.ACTIVE(FIND_STRING(PBUFFER,"$81,$01,'@',$01,$02,$E5",1)):{ PROJ_Status=PROS_ON [b][i]OFF[TP,10] ON[TP,9][/i][/b] } ACTIVE(FIND_STRING(PBUFFER,"$81,$01,'@',$01,$00,$E3",1)): {PROJ_Status=PROS_OFF [b][i]]ON[TP,10][/i][/b] [b][i]]OFF[TP,9][/i][/b] }} PBUFFER="" } }
or you could do this as well.DATA_EVENT [Projector] { STRING: { IF(LENGTH_STRING(data.text)) { SELECT { ACTIVE(FIND_STRING(data.text,"$81,$01,'@',$01,$02,$E 5",1)):{ PROJ_Status=PROS_ON } ACTIVE(FIND_STRING(data.text,"$81,$01,'@',$01,$00,$E 3",1)):{ PROJ_Status=PROS_OFF } } PBUFFER="" [TP,9] = (PROJ_Status) [TP,10] = (!PROJ_Status) } }
or even better you could put this into a function or call so you could also update the button feedback outside the data event of the projector as in the case of a TP coming online and needing current feedback.DEFINE_FUNCTINO fn_Update_TP_Proj_Power_Button_FB(){ [TP,9] = (PROJ_Status) [TP,10] = (!PROJ_Status) } ... DEFINE_EVENT ... // bla bla bla } } PBUFFER="" fn_Update_TP_Proj_Power_Button_FB() // update the feedback } } DATA_EVENT[TP]{ online:{ // when the TP comes online update teh feedback fn_Update_TP_Proj_Power_Button_FB() } }
-or-
-or-
-or-
there's a lot of layers to this onion.
-
I use data.text all the time from serial/IP devices, and it hasn't failed me yet. I think its faster than create_buffer as well, and requires less code so use it as needed. The only caveat is that since its a small buffer, around 2000 bytes, for devices that have feedback with much longer strings, you may need to combine buffers to get the full response. I've noticed some odd things occurring with create_buffer in terms of timing so I've stayed away from it.
Paul
Perhaps you haven't seen the issue, but it exists. If your device sends back "Long string of text," you might get two events, one with "Long string," and the other "of text." I have not seen it happen with IP communications, but have seen it a lot with RS-232. It determines the "end" of data by looking for a pause in the flow ... I couldn't tell you how long a pause it looks for, but I can tell you that if your devices pauses or hiccups, you are going to get a broken response if you aren't buffering it somehow. Probably the more modern your equipment is, the less likely there will be an issue, but test it extensively if you want to be sure. -
data.text has bitten me in the arse a few times with the scenario Dave describes - particularly web page returns. Web servers are notroiously weird when it comes to sending back data. Packets are broken up to 2K chunks and sent back at the pleasure of the web server's whims and the intervening switches et all.
The end result is a pretty stuttery message. AMX just doesn't handle this very well. I find myself doing both what Paul does by appending incoming data.text event messages to the end of my buffer and waiting patiently for the darned thing to quick spewing (looking for a true end terminatior) or letting Create_Buffer do it for me.
I've found that Create_Buffer seems to do a pretty okay job of this kind of thing. I'm not sure just why. But, I've seen cases whwere data.text gets a bit confussed and will drop chunks within the 2K data packages. Not always, nor even predictibly.
Honestly, I usuallly try data.text first and bail in favor of Create_Buffer if I find it starting to misbehave.
But, that's just me. -
Thanks Eric,
That answers my question about data.text. It would work unless I a really long response or got an error in the return.
One HEX character ($FF) is 255 bytes. Does Data.text see it as 255 or two characters?
That makes sense about the button feedback. It was more than necessary, but I was glad I had something that worked!! LOL. I used that method somewhere else in the code where I had 5 variables so that's why I came up with it.
I wrote another block using ON[TP,9] OFF[TP,10] etc. I'll have to wait until the room is available to test it.
I'm working on this room a block at a time.
One more question.
Shouldn't the request for status (Wait 300 Send_string "Running Sense") be in the same DATA_EVENT? I tried it, but it wouldn't compile. (I know I can also use FOR(Count=0;Count<300;Count++). Should it go in the same STRING event or under a COMMAND event?
David
Categories
- All Categories
- 2.5K AMX General Discussion
- 922 AMX Technical Discussion
- 514 AMX Hardware
- 502 AMX Control Products
- 3 AMX Video Distribution Products
- 9 AMX Networked AV (SVSI) Products
- AMX Workspace & Collaboration Products
- 3.4K AMX Software
- 151 AMX Resource Management Suite Software
- 386 AMX Design Tools
- 2.4K NetLinx Studio
- 135 Duet/Cafe Duet
- 248 NetLinx Modules & Duet Modules
- 57 AMX RPM Forum
- 228 MODPEDIA - The Public Repository of Modules for Everyone
- 943 AMX Specialty Forums
- 2.6K AMXForums Archive
- 2.6K AMXForums Archive Threads
- 1.5K AMX Hardware
- 432 AMX Applications and Solutions
- 249 Residential Forum
- 182 Tips and Tricks
- 146 AMX Website/Forums