Checksum of all strings sent to stream by print and println

Are there any simple solution to calculate checksum of bunch of data sent to the stream (Ethernet client, for example)?

I see only solution to make set of my wrapper-functions which will accept all datatypes acceptable by print(println), inside these functions will calculate checksum and call real print (println).

Are there more elegant solution?

As far as i understood by brief looking, seems like the best way is to extend EthernetClient class and override write function overthere, adding checksum calculations... Is this right approach? Are there any samples? Never do inherited classes in arduino encironment.

Checksums - you must know your data

There are several methods to create checksums. However, you must know how many data you have got.
If you cannot include the checksum in your data, send it as an extra packet.

Yes, you are right, i know my data, and i know the best way to calculate checksum is to inject my code to the stream, this is the only one place where all my data pass throu. This is sensors-poll system, it polls various sensors and sends information to the network server as combined url string, like: "http://mydomainname/mypage?sensorid1=123&sensorid2=456...". I would like to wrap whole url-string in checksum to verify integrity on the server side. I am using mix of EthernetClient.print and .println with string constants and with numeric variables so it is hard to calculate checksum in other places.

And i would like to kindly mention my question is not about how to calculate checksum, my question is about how to inject my code into stream print and println (write?) functions to perform some sort of monitoring of all bytes (in my case - calculate checksum) sent to stream.

Then you would have to add to the stream class a method to initiate the checksum and a method to return the checksum.

Wrapper functions can be given the inline directive so they don't add another actual function call when they are executed: the compiler copies the function code inline with the main code so there isn't a function call.

MorganS:
Then you would have to add to the stream class a method to initiate the checksum and a method to return the checksum.

Yes it is, that is what I was thinking about. But EthernetClient which I am using doesn't have "print()" and "println()" methods, is is not really clear for me where shoud I do checksum calculation. Method "write()" ?

MorganS:
Wrapper functions can be given the inline directive so they don't add another actual function call when they are executed: the compiler copies the function code inline with the main code so there isn't a function call.

I did not get this... Can you give some example?

SergeS:
Yes it is, that is what I was thinking about. But EthernetClient which I am using doesn't have "print()" and "println()" methods, is is not really clear for me where shoud I do checksum calculation. Method "write()" ?

Well, you probably didn't want the long explanation but this is a really great time to introduce object-oriented programming. For libraries which run LCD's or Ethernet or even just Serial, it would be a waste of time to copy-paste all the print functions into them. There's actually quite a lot in there. So they all use the Stream class to provide the basic functionality of printing numbers, strings and whatever. But the Stream class doesn't know how to print to every different device. So it has a virtual function called write() which just writes one character to the output device. Each different device will have a real implementation of that function, which does the special work for that device (I2C, SPI, buffering, whatever) and then Stream can call that function when printing any character.

If you want to checksum every single character written to the device or you have sufficient control to start/stop/reset/display the checksum, then yes, just modify the real function write() inside the Ethernet library. No need to bother Stream with this detail.

SergeS:
I did not get this... Can you give some example?

inline void wrapperPrint(char c) {
    globalChecksum += c;
    thingy.print(c);
}

The inline directive will mean the compiler will try to write those two lines out in full each time, instead of using a function call. There may be reasons why it doesn't but you can usually assume that it will.

But you'd have to have many versions of this for all the different types you want to print. If you have access to modify the write() function, then use that.

SergeS:
And i would like to kindly mention my question is not about how to calculate checksum, my question is about how to inject my code into stream print and println (write?) functions to perform some sort of monitoring of all bytes (in my case - calculate checksum) sent to stream.

What will the device that receives the data do with the checksum?
How will it do that?
Maybe that code will give you ideas for your code to generate the checksum?

...R

MorganS:
Well, you probably didn't want the long explanation but this is a really great time to introduce object-oriented programming. For libraries which run LCD's or Ethernet or even just Serial, it would be a waste of time to copy-paste all the print functions into them. There's actually quite a lot in there. So they all use the Stream class to provide the basic functionality of printing numbers, strings and whatever. But the Stream class doesn't know how to print to every different device. So it has a virtual function called write() which just writes one character to the output device. Each different device will have a real implementation of that function, which does the special work for that device (I2C, SPI, buffering, whatever) and then Stream can call that function when printing any character.

If you want to checksum every single character written to the device or you have sufficient control to start/stop/reset/display the checksum, then yes, just modify the real function write() inside the Ethernet library. No need to bother Stream with this detail.

inline void wrapperPrint(char c) {

globalChecksum += c;
    thingy.print(c);
}




The inline directive will mean the compiler will try to write those two lines out in full each time, instead of using a function call. There may be reasons why it doesn't but you can usually assume that it will.

But you'd have to have many versions of this for all the different types you want to print. If you have access to modify the write() function, then use that.

Thank you for long and good explanation, I am a little bit :slight_smile: familiar with OOP concept, i am a long time Delphi, java and php programmer, but i am not so familiar with c++ as far as with arduino classes hierarchy, this is my problem, i believe. I have looked inside EthernetClient library, seems like I could do what i want to do by modifying code there, but i do not really wish to modify standard library, I would like to (try to) make my own class derived from EthernetClient and override write() there. But I did not really get yet how to do it.
I see it like this:

in h-file (just copy from base-class):

class MyEthernetClient : public EthernetClient {
public:
  virtual size_t write(const uint8_t *buf, size_t size);
}

in cpp-file:

size_t MyEthernetClient::write(const uint8_t *buf, size_t size) {
 //perform my checksum calculatons here
  return size write (buf, size); //here is base-class (EthernetClient) method call
}

is this legal approach? At least in java and delphi I was able to do some similar tricks... Sure, I will need few extra methods to get checksum, reset checksum, etc., it is clear how to do it, not clear how to properly override write(...) to not brake existing functionality and add required features. And in this case seems like I do not need to modify many functions to cover all different datatypes.

Robin2:
What will the device that receives the data do with the checksum?
How will it do that?
Maybe that code will give you ideas for your code to generate the checksum?

Device on the other side is web-server on NAS (actually, php-script), I am also planning to calculate checksum, verify it against transmitted checksum and reject all data if checksums are not match. I did not see potential problems here, it should be easy.

SergeS:
Device on the other side is web-server on NAS (actually, php-script),

That makes me wonder why you cannot construct the message you want to send in a char or byte array, calculate the checksum, add it into the array and then send the array.

That would completely eliminate the need to calculate the checksum on the fly and the need to inject anything into the data stream.

...R

Robin2:
That makes me wonder why you cannot construct the message you want to send in a char or byte array, calculate the checksum, add it into the array and then send the array.

That would completely eliminate the need to calculate the checksum on the fly and the need to inject anything into the data stream.

Yes, it is, but my message is html string with multiple parameters, it includes text constant and various data, i would like to protect by checksum not only variables, but constant part too.
Here is the simplified sample of my message i generate (with no quotes): "?sid1=12.34&sid2=56&sid3=789&sid4=0.12&log=LOW_BATTERY&passwrd=secret&checksum=".

Finally, the programming is the art of possible ;-), is this possible to calculate (stream) checksum on the fly? ;-). If so why would not do that? There are a lot of ways how to bypass the problem, how to avoid this sort of calculations, but i do not want to avoid :wink:

SergeS:
but i do not want to avoid :wink:

That is your entitlement.

I look for the easy options myself.

...R

Robin2:
That is your entitlement.

I look for the easy options myself.

If i will not find the way how to do it, i will use you suggestion to calculate checksum only for variable part of data. I believe will try today or tomorrow.

I don't get it. You know what you want to send so why can't you just make an 8bit CRC and append it to the end of the array you are wanting to send.

Send the array to the receiver.

Receiver also does a CRC check (8 bits) of the array it has received (minus the last byte) and ensures they match.

Johnny010:
I don't get it. You know what you want to send so why can't you just make an 8bit CRC and append it to the end of the array you are wanting to send.

Send the array to the receiver.

Receiver also does a CRC check (8 bits) of the array it has received (minus the last byte) and ensures they match.

I have already answered, see here: Checksum of all strings sent to stream by print and println - #4 by SergeS - Project Guidance - Arduino Forum

Here is sample of my code:

  for (byte i=0; i<SensorsNum; i++)
    {
    client.print(F("&SID"));
    client.print(SID_arr[i]);
    client.print(F("="));
    client.print(stat[i].average());   client.print(F(","));
    client.print(stat[i].minimum());   client.print(F(","));
    client.print(stat[i].maximum());   client.print(F(","));
    client.print(stat[i].pop_stdev()); client.print(F(","));
    }

  client.print(F("&HUBID=")); client.print(SensorHubID); client.print(F(","));
  client.print(F("&CNT=")); client.print(SentCNT); client.print(F(","));
  // 
  client.print(F("&PWD=")); client.print(ArdPwd); client.println(F(" HTTP/1.0"));

I would like to have checksum for whole string receiver will receive. Including string literals in quotes, not only my variables. To calculate checksum for my variables is the simplest, but not elegant :-), solution.

I still can not see why you can not form a single string that you will send, place it in to a char array, do a CRC8bit CHK and add it as the second to last byte of the array and just send it?

PSUEDO

String to_send = one single long string built up using your individual ones...
array of characters = to_send;
replace last character in array of characters with 8bitCRC
add the string terminator character
send

To do it inside the ethernet class, you would have to add a few functions to "reset" the CRC at the beginning of your protected string and then read it out again afterwards. (Or maybe just a writeCRC() method.)

Outside the class, you need to use the sprintf() family of functions to convert the variables to decimal strings. Or write your own function to do that conversion.

My preferred method is useful when I have fixed-point variables. For example battVoltage=125 is used to represent 12.5V at the battery. But the data transmission always includes the decimal point. So I write my own writeWithCRC(int Val, int DecimalPlaces) which writes out individual characters while adding them to the CRC. writeWithCRC(char C) will write individual characters to spell out "?SP=" or whatever.

SergeS:
If i will not find the way how to do it, i will use you suggestion to calculate checksum only for variable part of data. I believe will try today or tomorrow.

You can use my idea for the complete message, not just the variables.

...R

Robin2:
You can use my idea for the complete message, not just the variables.

Could you show some sample?