Is there are a standard accepted way to byte-swap UUIDs for transmission over a network (or file storage)? (I want to send/store the 16 raw bytes rather than convert the UUID to a string representation.)
I thought at first I should partition the UUID into 4 32-bit integers and call htonl on each of them, but that didn't smell right. A UUID has internal structure (from RFC 4122):
typedef struct {
unsigned32 time_low;
unsigned16 time_mid;
unsigned16 time_hi_and_version;
unsigned8 clock_seq_hi_and_reserved;
unsigned8 clock_seq_low;
byte node[6];
} uuid_t;
Would it be correct to do:
...
uuid.time_low = htonl( uuid.time_low );
uuid.time_mid = htons( uuid.time_mid );
uuid.time_hi_and_version = htons( uuid.time_high_and_version );
/* other fields are represented as bytes and shouldn't be swapped */
....
before writing, and then the correpsonding ntoh...calls after reading at the other end?
Thanks.
Yes, that is the correct thing to do.
Each number (time_low, time_mid, time_hi_and_version) are subject to byte ordering. the node field is not. clock_seq_hi_and_reserved and clock_seq_low are also subject to byte ordering, but they are each one byte, so it doesn't matter.
Of course, it is up to you to make sure that you choose the right ordering on both ends, or understand what the ordering is on the other end if you don't control it. Microsoft of course uses little endian for their UUIDs. You can see Microsoft's definition of a UUID here.
Related
I am creating a game using the Mifare tags embedded in 8 different playing pieces. I will be using an Arduino NANO with the MFRC522 (library https://github.com/miguelbalboa/rfid) to do the actual reading of the tags, and am using an ER301 reader/writer (with eReader software) to assign playing piece numbers to them. I will be creating multiples of each piece to head off any issues I would have with loss due to breakage or theft (due to these being rather unique playing pieces). Since there will be 8 different pieces, and 4 copies of each piece, that would be 32 UIDs to keep up with. I would rather assign a different number to each of pieces, and the same number of each piece to its duplicates - so only 8 numbers to keep up with.
My question is - how do I read a certain block and sector with the MFRC522?
Specifically, sector 2, block 8 - because this is where the Hex equivalent of the playing piece number shows up (when it is assigned as a Product Name with the eReader software and the ER301 writer). I understand using the library for the MFRC522 to read the UID, but this is a bit more in-depth than my understanding.
I have written several Sketches for the Arduino, but this is my foray into the world of RFID, and is quite a bit more extensive than my previous Arduino projects. Once I can read the specific sector & block, the Arduino NANO will output a binary representation (on 4 of the digital I/Os) of which playing piece was placed.
The library you are using provides dedicated methods to perform read and write operations on MIFARE tags:
StatusCode MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
StatusCode MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
Since your description (sector 2, block 8) suggests that you are using MIFARE Classic tags, you would also need to authenticate to the tag in order to perform read/write operations. Thus, you would also need the authentication method:
StatusCode PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
Just as you would use the library to read the UID
if (mfrc522.PICC_ReadCardSerial()) {
Serial.print(F("Card UID:"));
dump_bytes(mfrc522.uid.uidByte, mfrc522.uid.size);
}
you could also access these read/write methods:
MFRC522::StatusCode status;
MFRC522::MIFARE_Key key;
byte buffer[18];
byte size = sizeof(buffer);
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; ++i) {
key.keyByte[i] = 0xFF;
}
if (mfrc522.PICC_ReadCardSerial()) {
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 8, &key, &(mfrc522.uid));
if (status == MFRC522::STATUS_OK) {
status = mfrc522.MIFARE_Read(8, buffer, &size);
if (status == MFRC522::STATUS_OK) {
Serial.print(F("Data (block = 8): "));
dump_bytes(buffer, 16);
}
}
}
Note that I assume block 8 (= sector 2, block 0) to be readbale using key A and that key A is set to the default transport key FF FF FF FF FF FF. If your other reader changed those values, you need to adapt the code accordingly. Moreover I used the pseudo-method dump_bytes(array, length) to indicate that the interesting value is the first length bytes of array. An implementation that actually prints those values is up to you.
Btw. a full example on how to use the library for read/write operations actually ships together with the library!. So you could just take a look at ReadAndWrite.ino on how to use that library.
The documentation for Arduino/Genuino 101's CurieBLE library states the following, in the section "Service Design Patterns":
A characteristic value can be up to 20 bytes long. This is a key
constraint in designing services. [...] You could also combine readings into a single characteristic, when a given sensor or actuator has multiple values associated with it.
[e.g. Accelerometer X, Y, Z => 200,133,150]
This is more efficient, but you need to be careful not to exceed the 20-byte limit. The accelerometer characteristic above, for example, takes 11 bytes as a ASCII-encoded string.
However, the typed Characteristic constructors available in the API are limited to the following:
BLEBoolCharacteristic
BLECharCharacteristic
BLEUnsignedCharCharacteristic
BLEShortCharacteristic
BLEUnsignedShortCharacteristic
BLEIntCharacteristic
BLEUnsignedIntCharacteristic
BLELongCharacteristic
BLEUnsignedLongCharacteristic
BLEFloatCharacteristic
BLEDoubleCharacteristic
None of these types of Characteristics appear to be able to hold a 20-byte string. (I have tried the BLECharCharacteristic, and it appears to pertain to a single char, not a char array.)
Using CurieBLE, how does one go about using a string as a characteristic value, as described in the documentation as an efficient practice?
Yours issue described here in official arduino 101 example. Few strings of code how to set an array:
BLECharacteristic heartRateChar("2A37", // standard 16-bit characteristic UUID
BLERead | BLENotify, 2);
...
const unsigned char heartRateCharArray[2] = { 0, (char)heartRate };
heartRateChar.setValue(heartRateCharArray, 2);
As you can see characteristic's value set using "setValue" function with desired array as an argument. You can pass a String as char* pointing to an array.
I'm trying to read data on a serial communication "COM1", using ADA based on RS 422,
as the following.
S_Port : Serial_Port;
Buffer : Ada.Streams.Stream_Element_Array(1..150);
GNAT.Serial_Communications.Open(Port => S_Port,Name => "COM1");
GNAT.Serial_Communications.Set(
Port => S_Port, Parity => Even, Block => False,
TimeOut => 4.0
);
GNAT.Serial_Communications.Read(S_Port,Buffer,Last);
The problem is that although the value of 'Last' changes from 9 to 27, the buffer has
much more than 9 or 27 bytes. I thought I can use 'Last' to mark the end of a message,
but that is not the case?
Also I can't seem to have an unbounded buffer to use the READ function, and must
define a certain size?
Thanks in advance.
I've not worked with this, but the fact that Last is changing values suggests that data is in fact being read in.
Assuming that's happening, since you're reading into a fixed size buffer, there's going to be junk in it unless you initialize the whole thing first. The elements in indices 1..Last will be overwritten, and the rest will be left as the original garbage values.
So the data that was read in is available in Buffer(1 .. Last).
I'm following the sparkfun tutorial for connecting an arduino to electric imp. I only have one arduino and imp, so I'm trying to get whatever I type in the arduino serial monitor to display in the imp node using server.show().
I've modified one of the functions in the sparkfun code to look like this:
function pollUart()
{
imp.wakeup(0.00001, pollUart.bindenv(this)); // schedule the next poll in 10us
local byte = hardware.uart57.read(); // read the UART buffer
// This will return -1 if there is no data to be read.
while (byte != -1) // otherwise, we keep reading until there is no data to be read.
{
// server.log(format("%c", byte)); // send the character out to the server log. Optional, great for debugging
// impeeOutput.set(byte); // send the valid character out the impee's outputPort
server.show(byte)
byte = hardware.uart57.read(); // read from the UART buffer again (not sure if it's a valid character yet)
toggleTxLED(); // Toggle the TX LED
}
}
server.show(byte) is only displaying seemingly random numbers. I have an idea of why this is, I just don't know how to fix it because I'm not that familiar with UARTs and squirrel.
local byte = hardware.uart57.read(); reads in the ascii characters from the arduino in byte form (I think), and they're not being 'translated' into their ascii characters before I use server.show(byte).
How do I do this in squirrel?
Also, I think polling every 10us is the wrong way to go here. I'd like to only poll when there's new information, but I also don't know how to do that in squirrel. Can someone point me to an example where this happens?
Thanks!
I think you are passing the wrong data type to the show method of the server object. The electric imp docs state that it takes a string, server.show(string). I think that local is the correct type to receive the value from hardware.uart57.read(). You can tell from the docs as well. So, you need to find a way to cast your byte to a string. I bet you could find the answer here. From what I read Squirrel use's Unicode so there is a probably a function that takes Unicode bytes and loads them into a string object.
So, I have worked on large systems in the past, like an iso stack session layer, and something like that is too big for what I need, but I do have some understanding of the big picture. What I have now is a serial point to point communications link, where some component is dropping data (often).
So I am going to have to write my own, reliable delivery system using it for transport. Can someone point me in the directions for basic algorithms, or even give a clue as to what they are called? I tried a Google, but end up with post graduate theories on genetic algorithms and such. I need the basics. e.g. 10-20 lines of pure C.
XMODEM. It's old, it's bad, but it is widely supported both in hardware and in software, with libraries available for literally every language and market niche.
HDLC - High-Level Data Link Control. It's the protocol which has fathered lots of reliable protocols over the last 3 decades, including the TCP/IP. You can't use it directly, but it is a template how to develop your own protocol. Basic premise is:
every data byte (or packet) is numbered
both sides of communication maintain locally two numbers: last received and last sent
every packet contains the copy of two number
every successful transmission is confirmed by sending back an empty (or not) packet with the updated numbers
if transmission is not confirmed within some timeout, send again.
For special handling (synchronization) add flags to the packet (often only one bit is sufficient, to tell that the packet is special and use). And do not forget the CRC.
Neither of the protocols has any kind of session support. But you can introduce one by simply adding another layer - a simple state machine and a timer:
session starts with a special packet
there should be at least one (potentially empty) packet within specified timeout
if this side hasn't sent a packet within the timeout/2, send an empty packet
if there was no packet seen from the other side of communication within the timeout, the session has been termianted
one can use another special packet for graceful session termination
That is as simple as session control can get.
There are (IMO) two aspects to this question.
Firstly, if data is being dropped then I'd look at resolving the hardware issues first, as otherwise you'll have GIGO
As for the comms protocols, your post suggests a fairly trivial system? Are you wanting to validate data (parity, sumcheck?) or are you trying to include error correction?
If validation is all that is required, I've got reliable systems running using RS232 and CRC8 sumchecks - in which case this StackOverflow page probably helps
If some components are droping data in a serial point to point link, there must exist some bugs in your code.
Firstly, you should comfirm that there is no problem in the physical layer's communication
Secondly, you need some konwledge about data communication theroy such like ARQ(automatic request retransmission)
Further thoughts, after considering your response to the first two answers... this does indicate hardware problems, and no amount of clever code is going to fix that.
I suggest you get an oscilloscope onto the link, which should help to determine where the fault lies. In particular look at the baud rate of the two sides (Tx, Rx) to ensure that they are within spec... auto-baud is often a problem?!
But look to see if drop out is regular, or can be sync-ed with any other activity.
on the sending side;
///////////////////////////////////////// XBee logging
void dataLog(int idx, int t, float f)
{
ubyte stx[2] = { 0x10, 0x02 };
ubyte etx[2] = { 0x10, 0x03 };
nxtWriteRawHS(stx, 2, 1);
wait1Msec(1);
nxtWriteRawHS(idx, 2, 1);
wait1Msec(1);
nxtWriteRawHS(t, 2, 1);
wait1Msec(1);
nxtWriteRawHS(f, 4, 1);
wait1Msec(1);
nxtWriteRawHS(etx, 2, 1);
wait1Msec(1);
}
on the receiving side
void XBeeMonitorTask()
{
int[] lastTick = Enumerable.Repeat<int>(int.MaxValue, 10).ToArray();
int[] wrapCounter = new int[10];
while (!XBeeMonitorEnd)
{
if (XBee != null && XBee.BytesToRead >= expectedMessageSize)
{
// read a data element, parse, add it to collection, see above for message format
if (XBee.BaseStream.Read(XBeeIncoming, 0, expectedMessageSize) != expectedMessageSize)
throw new InvalidProgramException();
//System.Diagnostics.Trace.WriteLine(BitConverter.ToString(XBeeIncoming, 0, expectedMessageSize));
if ((XBeeIncoming[0] != 0x10 && XBeeIncoming[1] != 0x02) || // dle stx
(XBeeIncoming[10] != 0x10 && XBeeIncoming[11] != 0x03)) // dle etx
{
System.Diagnostics.Trace.WriteLine("recover sync");
while (true)
{
int b = XBee.BaseStream.ReadByte();
if (b == 0x10)
{
int c = XBee.BaseStream.ReadByte();
if (c == 0x03)
break; // realigned (maybe)
}
}
continue; // resume at loop start
}
UInt16 idx = BitConverter.ToUInt16(XBeeIncoming, 2);
UInt16 tick = BitConverter.ToUInt16(XBeeIncoming, 4);
Single val = BitConverter.ToSingle(XBeeIncoming, 6);
if (tick < lastTick[idx])
wrapCounter[idx]++;
lastTick[idx] = tick;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => DataAdd(idx, tick * wrapCounter[idx], val)));
}
Thread.Sleep(2); // surely we can up with the NXT
}
}