Debugging incoming hex (or, 1-wire modules?)
amxhobbyist
Posts: 90
I don't see that a 1-wire (iButton) Netlinx module exists, and thus am embarking on a task to write one for the Dallas DS9097U. If there is one already out there, please let me know where to find it so I can save myself a lot of pain.
I write code a bit different; lots of trial and error, throwing commands at devices to see what they return in various circumstances, etc. It works for me.
The problem: Almost everything for this device is in hex, and it's impossible to determine what the interface is actually sending me (for troubleshooting purposes) because I don't know how to display it in a format I can read. (I'm currently pushing all incoming data to syslog so I can watch what happens when I throw various commands at it).
The question: How can I convert this data to something readable (hextoi doesn't seem to help at all, so I tried itoa the result of the hextoi and just get 0s)? Alternately, is there a good terminal emulator (for linux or windows) that will let me send hex & display incoming hex in a manner I can interpret?
I wrote some Axcess code to interface with a cm11a "activehome" X-10 interface a couple of years back. That was mostly hex as well, but it was straightforward: The device responded exactly as the documentation said it would. This one doesn't, so I need to see what it's really trying to tell me.
Thank you.
I write code a bit different; lots of trial and error, throwing commands at devices to see what they return in various circumstances, etc. It works for me.
The problem: Almost everything for this device is in hex, and it's impossible to determine what the interface is actually sending me (for troubleshooting purposes) because I don't know how to display it in a format I can read. (I'm currently pushing all incoming data to syslog so I can watch what happens when I throw various commands at it).
The question: How can I convert this data to something readable (hextoi doesn't seem to help at all, so I tried itoa the result of the hextoi and just get 0s)? Alternately, is there a good terminal emulator (for linux or windows) that will let me send hex & display incoming hex in a manner I can interpret?
I wrote some Axcess code to interface with a cm11a "activehome" X-10 interface a couple of years back. That was mostly hex as well, but it was straightforward: The device responded exactly as the documentation said it would. This one doesn't, so I need to see what it's really trying to tell me.
Thank you.
0
Comments
Post a command from the data return of your device and also what you'd like it to be converted too.
This is a program that is a terminal emulator that lets you send and recieve ascii,hex,and other formats. You can search for a free download at google
Quick example: When a new device arrives on the bus, the unit is supposed to send XXXXXX01b, where the X's are undefined. It's sending something, since I get an entry in my syslog with extended ascii characters, but that doesn't help me in seeing what it actually sent back.
How do I search a hex string? I was using:
tmp = right_string (onewirebuffer,1)
if (tmp = "$1b") { // do something }
But this trigger isn't running. I'm guessing right_string doesn't work on hex data.
Steve,
Thank you for the info. That should help me query this device back and forth to see what it's really doing so I can write Netlinx code to talk to it.
The real world syntax for HEX is "0x00" not "$", this is a AMX thing.
If you are looking for HEX "0x1b", most devices retyrn it as "1B".
Example:
DATA.TEXT
The real world syntax for HEX is "0x00" not "$", this is an AMX thing.
If you are looking for HEX "0x1b", most devices return it as '1B'.
Example:
DATA.TEXT[DEVICE??]
{
STRING:
{
IF(FIND_STRING(DATA.TEXT, '1b', 1))
//DO SOMETHING
}
}
Hope this helps!
- Chip
Quick example, I issue a reset pulse to the device with:
send string dev_rs232_1wire,"$00,$C1"
I get the following response in syslog:
May 4 19:57:44 ni3000 OneWireModule: Raw: ^A
May 4 19:57:44 ni3000 OneWireModule: itohex: 1
May 4 19:57:44 ni3000 OneWireModule: hextoi:
May 4 19:57:44 ni3000 OneWireModule: itoa: 1
May 4 19:57:44 ni3000 OneWireModule: Raw: ^A?
May 4 19:57:44 ni3000 OneWireModule: itohex: 1
May 4 19:57:44 ni3000 OneWireModule: hextoi:
May 4 19:57:44 ni3000 OneWireModule: itoa: 1
May 4 19:57:46 ni3000 OneWireModule: $01,$CD
May 4 19:57:46 ni3000 OneWireModule: cleared
The second to last line ($01,$CD) is from your debug code, and 0xCD is the appropriate response to a reset, so I've got that working. The entire response is generated with the following Netlinx code: (I wanted to run various conversions since I wasn't positive what the device would be spitting out during different operations)
Simple enough. Now, according to the manual for the chip inside the DS9097U, when a new device arrives on the 1-wire bus, "The DS2480B will recognize this unsolicited presence pulse and notify the host by sending a byte such as XXXXXX01b. The Xs represent undefined bit values. The fact that the host receives the byte unsolicited together with the pattern 01b in the least significant 2 bits marks the bus arrival."
When I add a device to the bus I get no response from your code. I simply get:
May 4 19:57:38 ni3000 OneWireModule: Raw: ?
May 4 19:57:38 ni3000 OneWireModule: itohex: CD
May 4 19:57:38 ni3000 OneWireModule: hextoi:
May 4 19:57:38 ni3000 OneWireModule: itoa: 205
May 4 19:57:40 ni3000 OneWireModule: cleared
So, I'm a bit stumped on how to proceed. Any advice would be greatly appreciated. (Also... when this code is finished & tested, I will release the module under the GPL for all to use)
I now have a more direct question: How do I do that?
Example: I receive the incoming byte 0xCD. I have to break that into it's binary value (11001101) and then check to see if the last two bits are 01. If so, I know a device has just arrived on the bus and I can therefore take action.
As Alex said, BAND is one way to check the response from the device to see if specific flags are set. For instance, if cResponse below is a CHAR that represents a byte received from the device and you wish to check to see if the last 2 bits are 01, then do:
You could alternately mask off all of the other bits and store the result and then do a simple test in the event you need to test this result more than once (such as storing the status for later use throughout a module):
In addition to BAND, Netlinx supports BOR, BXOR, and BNOT bitwise operations as well as left and right shift operations. The negation operator (~) can be useful in bitwise operations also. If you wanted to check to see if any bits other than the last 2 bits in cResponse are set (as an example), you could do the following instead of creating the hex equivalent:
For other bit combinations, simply form the hex equivalent of the bit string you wish to check and the technique should work. Netlinx does not currently support a method of specifying constants in binary format as many languages do. This would be a nice addition to Netlinx/Studio as bitwise operations are common with certain device types and while converting binary to hex is not a tremendous challenge, having a binary constant format would be useful and could improve the self-documenting aspects of code that deals with bitwise operations.
I wanted to correct something in my last post to make sure I don't totally confuse someone. In my last code sample, I was trying to illustrate that you could use the negation operator (~) to create a mask allowing you to check to see if any bits other than the last 2 bits were set. I inadvertantly used the wrong hex mask - here is the corrected code sample:
The original sample would have been fine for testing all bits except for the last 1 but was not correct for checking the last 2 bits. Sorry for any confusion.
Reese
1. The BAND doesn't seem to work:
In syslog, I get:
May 8 20:34:30 ni3000 OneWireModule: itohex: CD
May 8 20:34:32 ni3000 OneWireModule: cleared
So the BAND isn't matching. But 0xCD is 11001101, which means the BAND should work, right? Do I need to break onewirebuffer down somehow? I do get a warning, "C10571: Converting type [string] to [CHAR]", on compile.
2. How can I break onewirebuffer down into individual bits and/or bytes? Data is going to be streaming at this thing and any individual "string:" event may contain several bytes that need to be looked at individually. In another module I wrote, I had an incoming pattern to work with so I built a queue and processed it with "remove_string". Can I do something similar with an individual bit and/or byte?
Working on the bit level is new to me, not just within Netlinx, so I'm having to learn as I go. The last time I got this close to a device I only had to deal with full bytes. But I'm making a lot of progress thanks to you folks.
Really I'm surprised a 1-wire module doesn't already exist. If you've never worked with 1-wire devices, you owe it to yourself to try. Really nice for access control (iButtons) and temperature sensing applications, and absolutely dirt cheap. Hopefully I'll have a basic module released soon.
In your comparison, you're trying to take a potentially multiple character string and comparing it to a single character. You'd probably want to do something like this instead:
If the message that comes in is one or more bytes, all of them will get checked.
Your code nukes the contents of the buffer two seconds after it gets a message - I'd question why, but I'll save that for a different discussion. With that code in place, the above example would re-examine contents of onewirebuffer if more than one string comes in during a two second time period. (Which could happen if you get a string in that's larger than your processor's 232 hardware buffer, or if there's any kind of pause in the incoming message, or if the device simply generates more than one message in that time period)
REMOVE_STRING is great and is very helpful IF you already know the characters you want to remove up to in a string. You may have been thinking of GET_BUFFER_CHAR? That would have gone like this:
Chances are that you could get messages larger than one character in, so that method probably won't help you much as it destroys the contents of the buffer as it goes.
So this iButton stuff - are all the messges 1 character, all the time? If not, how are you supposed to tell the difference between the "online" message and any other?
- Chip
Just for troubleshooting something else.
Yes, GET_BUFFER_CHAR is what I wanted. Thank you!
They appear to be all one character. So far all of the docs I've read deal with individual "packets" of one byte.
The "online" message is recognized because it is (a) unsolicited, and (b) has "the pattern 01b in the least significant 2 bits" according to the docs. All other 1-wire operations originate from the host (such as reading the value of a tempreature sensor, reading/writing to a crypto ibutton, etc). So when you use an iButton for access control use, you press the button against a contact pad. It is recognized, a "new device online" message is sent, you search the bus for the new device during which you obtain it's unique 64 bit ID. That is compared against a list of valid IDs and, if valid, you perform some action.
It's not an incredibly complicated system, once you know how to play with bits in the programming langauge you're using.
The problem with the If( nResponse BAND $01 ) condition is that it will be true if the last 2 bits of nResponse are 01 or 11, so wrong half the time if you are specifically looking for 01.
The correct statment should be:
if( ( nResponse BAND 1 ) and !( nResponse BAND 2 ) )
{
do something
}
The second part of the statement makes sure that the 2nd bit isn't a 1.
2 is 10 in binary.
11 BAND 10 = 10
NOT 10 = 0 ( NOT anything else than 0 will equal 0 )
01 BAND 10 = 00
NOT 00 = 1
by the way, writting $01 or 1 is the same, from 0 to 9...
I hope this helps...
D
But alexanbo didn't:
So yeah, a better test would have been
Thanks for pointing that out, Daniel...
- Chip