Related
I am trying to create simple windows bluetooth client application. However after successfull connect the send() function is sending data only for a short duration. The subsequent calls to send() function fail with code: 10053 (WSAECONNABORTED).
From docs:
Software caused connection abort. An established connection was aborted by the software in your host computer, possibly due to a data transmission time-out or protocol error.
If I understand it correctly the error is occuring on Windows (client) side and not on the server side?
What could be causing it?
Also is it possible to somehow reconnect this socket?
The code (simplified, missing error checks):
#include <winsock2.h>
#include <ws2bth.h>
#include <iostream>
// {B62C4E8D-62CC-404b-BBBF-BF3E3BBB1374} ]taken from Microsoft example
DEFINE_GUID(gGuidServiceClass, 0xb62c4e8d, 0x62cc, 0x404b, 0xbb, 0xbf, 0xbf, 0x3e, 0x3b, 0xbb, 0x13, 0x74);
unsigned char dummyData [10] =
{
0x01, 0x02, 0x03, 0x04, 0x05,
0x01, 0x02, 0x03, 0x04, 0x05
};
int main(void)
{
WSAData wsaData = {0};
SOCKADDR_BTH btAddr = {0};
uint32_t flags = 0;
WSAStartup(MAKEWORD(2, 2), &wsaData);
btAddr.addressFamily = AF_BTH;
btAddr.serviceClassId = gGuidServiceClass;
btAddr.port = 0;
btAddr.btAddr = // hardcoded address here
SOCKET s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (SOCKET_ERROR == connect(s, (struct sockaddr *) &btAddr, sizeof(SOCKADDR_BTH)))
{
std::cout << "socket connect fail: " << WSAGetLastError() << std::endl;
return -1;
}
int32_t bytes = send(s, reinterpret_cast<char *>(dummyData), 10, 0);
if (bytes == 10)
{
std::cout << "first send success\n";
}
// success
// do some processing
// repeat
bytes = send(s, reinterpret_cast<char *>(dummyData), 10, 0);
if (bytes < 0)
{
// always fail with 10053
std::cout << "Error: " << WSAGetLastError() << std::endl;
}
closesocket(s);
WSACleanup();
return 0;
}
I have written a simple sketch to send a connect and publish packet to a cloudMQTT server. I get no errors back from the SIM900 but nothing shows up on the cloudMQTT dashboard.
#include <SoftwareSerial.h>
SoftwareSerial SoftSerial( 9, 10 );
// These varaibles are passed to functionality that generates the connect and publish packets. This code was taken from a sketch written by Ravi Pujar
unsigned int Counter = 0;
unsigned long datalength, CheckSum, RLength;
unsigned short topiclength;
unsigned char topic[30];
char str[250];
unsigned char encodedByte;
int X;
unsigned short MQTTProtocolNameLength;
unsigned short MQTTClientIDLength;
unsigned short MQTTUsernameLength;
unsigned short MQTTPasswordLength;
const char MQTTHost[30] = "hairdresser.cloudmqtt.com";
const char MQTTPort[10] = "18958";
const char MQTTClientID[20] = "ABCDEF";
const char MQTTTopic[30] = "valetron";
const char MQTTProtocolName[10] = "MQIsdp";
const char MQTTLVL = 0x03;
const char MQTTFlags = 0xC2;
const unsigned int MQTTKeepAlive = 60;
const char MQTTUsername[30] = "uroxeeil";
const char MQTTPassword[35] = "ifG3xIxaf5gT";
const char MQTTQOS = 0x00;
const char MQTTPacketID = 0x0001;
unsigned char buffer[ 64 ];
int counter = 0;
void setup()
{
// Set the babud rate of both the software serial and hardware serial
Serial.begin( 19200 );
SoftSerial.begin( 19200 );
delay(2000);
// This section of code sends AT commands to initialize the SIM900
//-------------- AT INITIALIZATION - This is working fine--------------//
SoftSerial.write( "\r\nAT\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIPSHUT\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIPMUX=0\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CGATT=1\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CSTT=\"myMTN\", \"\", \"\"\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIICR\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIFSR\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIPSTART=\"TCP\", \"hairdresser.cloudmqtt.com\", \"18958\"\r\n" );
delay(10000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-------------- END OF AT INITIALIZATION --------------//
//This is where the issue lies
// Send the connect packet. This code was written by Ravi Pujar
SoftSerial.write( "\r\nAT+CIPSEND\r\n" );
delay(3000);
SoftSerial.write(0x10);
MQTTProtocolNameLength = strlen(MQTTProtocolName);
MQTTClientIDLength = strlen(MQTTClientID);
MQTTUsernameLength = strlen(MQTTUsername);
MQTTPasswordLength = strlen(MQTTPassword);
datalength = MQTTProtocolNameLength + 2 + 4 + MQTTClientIDLength + 2 + MQTTUsernameLength + 2 + MQTTPasswordLength + 2;
X = datalength;
do {
encodedByte = X % 128;
X = X / 128;
if (X > 0) {
encodedByte |= 128;
}
SoftSerial.write(encodedByte);
}
while (X > 0);
SoftSerial.write(MQTTProtocolNameLength >> 8);
SoftSerial.write(MQTTProtocolNameLength & 0xFF);
SoftSerial.print(MQTTProtocolName);
SoftSerial.write(MQTTLVL); // LVL
SoftSerial.write(MQTTFlags); // Flags
SoftSerial.write(MQTTKeepAlive >> 8);
SoftSerial.write(MQTTKeepAlive & 0xFF);
SoftSerial.write(MQTTClientIDLength >> 8);
SoftSerial.write(MQTTClientIDLength & 0xFF);
SoftSerial.print(MQTTClientID);
SoftSerial.write(MQTTUsernameLength >> 8);
SoftSerial.write(MQTTUsernameLength & 0xFF);
SoftSerial.print(MQTTUsername);
SoftSerial.write(MQTTPasswordLength >> 8);
SoftSerial.write(MQTTPasswordLength & 0xFF);
SoftSerial.print(MQTTPassword);
SoftSerial.write(0x1A);
delay( 2000 );
// Send the publish packet. This code was written by Ravi Pujar
SoftSerial.print("\r\nAT+CIPSEND\r\n");
delay(3000);
memset(str, 0, 250);
topiclength = sprintf((char * ) topic, MQTTTopic);
datalength = sprintf((char * ) str, "%s%u", topic, Counter);
delay(1000);
Serial.write(0x30);
X = datalength + 2;
do {
encodedByte = X % 128;
X = X / 128;
if (X > 0) {
encodedByte |= 128;
}
SoftSerial.write(encodedByte);
}
while (X > 0);
SoftSerial.write(topiclength >> 8);
SoftSerial.write(topiclength & 0xFF);
SoftSerial.print(str);
SoftSerial.write(0x1A);
}
void loop()
{
// Display any response that has been sent after the first CIPSEND
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
}
This is the Serial output:
But nothing shows on the cloudMQTT server besides the IP of my device after the tcp connection is established.
So it was not working when trying to connect to the cloudMQTT server, but when I connected to my MQTT server or the test MQTT server, it worked. There must be an issue dealing with the protocol that the cloud mqttServer uses (MQIsdp) as apposed to the standard MQTT protocol that a normal MQTT server utilizes. I made a change to the connect packet so that it specified the MQTT protocol and pointed the TCP connection to the test server ( test.mosquitto.org ) and I can now Connect and Publish successfully.
For anyone who is just starting out with trying to interface an Arduino with a module like a SIM900 ( GPRS/GSM module ) to a MQTT server, I suggest you grasp a full understanding of standard AT Commands ( To establish a solid TCP connection to server ), how to compile the packets that will be sent through the GPRS module from the Arduino and lastly I suggest not using any code you have not written to achieve this. Learn how to establish the TCP connection with AT commands, then learn how to compile and send a connect packet by compiling the byte array yourself and sending it. Once you understand the packets and the communication between the client and the server, the MQTT world is your oyster.
You can use this code as a guideline but please try write as much of your own as possible:
#include <SoftwareSerial.h>
SoftwareSerial SoftSerial( 9, 10 );
// Go Look up the structure of MQTT packets and from there you will learn how to compile these
byte connectPacket[ 19 ] =
{
0x10, 0x11, 0x00, 0x04, 0x4D, 0x51, 0x54, 0x54, 0x04, 0x02, 0x00, 0x3C, 0x00, 0x05, 0x54, 0x32, 0x54, 0x49, 0x44
};
byte publishPacket[ 26 ] =
{
0x30, 0x18, 0x00, 0x0E, 0x54, 0x32, 0x54, 0x5F, 0x54, 0x6F, 0x70, 0x69, 0x63, 0x5F, 0x44, 0x65, 0x6D, 0x6F, 0x54, 0x65, 0x6D, 0x70, 0x3A, 0x20, 0x33, 0x30
};
unsigned char buffer[ 64 ];
int counter = 0;
// Simple function to send an AT command and see its response
void sendAtCommandWithResponse( char message[] )
{
SoftSerial.write( message );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
}
void setup()
{
Serial.begin( 19200 );
SoftSerial.begin( 19200 );
delay(10000);
// -- Configure the SIM900 and establish the TCP connection to the server
sendAtCommandWithResponse( "\r\nAT\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CIPSHUT\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CIPMUX=0\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CGATT=1\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CSTT=\"myMTN\", \"\", \"\"\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CIICR\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CIFSR\r\n" );
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIPSTART=\"TCP\", \"test.mosquitto.org\", \"1883\"\r\n" );
delay(10000);
//-----
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
// -- Send the connect packet
sendAtCommandWithResponse( "\r\nAT+CIPSEND\r\n" );
delay(3000);
SoftSerial.write( connectPacket, sizeof( connectPacket ) );
// This tells the SIM900 to send the packet
SoftSerial.write(0x1A);
delay(3000);
// -- Send the publish packet
sendAtCommandWithResponse( "\r\nAT+CIPSEND\r\n" );
delay(3000);
SoftSerial.write( publishPacket, sizeof( publishPacket ) );
// This tells the SIM900 to send the packet
SoftSerial.write(0x1A);
}
void loop()
{
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
}
How should I send 9 binary into serial port?
Is there anything wrong with this? I get no reaction from the serial port. What should I do for the write file?
#include <iostream>
#include <windows.h>
using namespace std;
int main(){
unsigned char data[9];
data[0] = { 0x00 };
data[1] = { 0x5A };
data[2] = { 0x56 };
data[3] = { 0xFF };
data[4] = { 0x04 };
data[5] = { 0x00 };
data[6] = { 0x00 };
data[7] = { 0x00 };
data[8] = { 0xB3 };
DWORD buffer = 0;
HANDLE port;
DCB dcb = { 0 };
port = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
//DCB dcb;
DWORD m_baudrate = 9600, m_bytesize = 8, m_parity = 0, m_stopbit = 1, ok, m_useRtsCts = 0;
dcb.DCBlength = sizeof(dcb);
GetCommState(port, &dcb);
dcb.BaudRate = m_baudrate;
dcb.ByteSize = (BYTE)m_bytesize;
dcb.Parity = m_parity;
dcb.StopBits = m_stopbit;
if (m_useRtsCts)
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fNull = FALSE;
dcb.fAbortOnError = FALSE;
ok = SetCommState(port, &dcb);
if (port){
BuildCommDCB("COM1:9600,n,8,1", &dcb);
cout << "Hello" << endl;
PurgeComm(port, PURGE_RXCLEAR | PURGE_TXCLEAR);
WriteFile(port, data, sizeof(data), &buffer, 0);
}
else{
cout << "World" << endl;
}
CloseHandle(port);
system("Pause");
return 0;
}
I can send the data but the binary cannot turn on the light. the hexadecimal code to turn everything on is
00 5A 56 FF 03 00 00 00 B2
how ever after i use CommUart asistant to open to port once then the things can function. Could anyone tell me what is the problem at the Open port there? Thank You!
can anyone tell me what is wrong?
However with this set of code i can run it normally? May i know where of my setting was wrong above there.
#include <iostream>
#include <corewindow.h>
using namespace std;
int main(){
//unsigned char data[9] = {0,90,86,255,3,0,0,0,178};
unsigned char data[9];
data[0] = { 0x00 };
data[1] = { 0x5A };
data[2] = { 0x56 };
data[3] = { 0xFF };
data[4] = { 0x03 };
data[5] = { 0x00 };
data[6] = { 0x00 };
data[7] = { 0x00 };
data[8] = { 0xB2 };
DWORD buffer = 0;
HANDLE port;
DCB dcb = { 0 };
port = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
if (port == (HANDLE)-1)
{
return 0;
}
SetupComm(port, 1024, 1024);
FillMemory(&dcb, sizeof(dcb), 0);
dcb.DCBlength = sizeof(dcb);
BuildCommDCB("9600,n,8,1", &dcb);
if (!SetCommState(port, &dcb))
{
return 0;
}
COMMTIMEOUTS to;
memset(&to, 0, sizeof(to));
to.ReadIntervalTimeout = 100;
to.ReadTotalTimeoutMultiplier = 10;
to.ReadTotalTimeoutConstant = 10;
SetCommTimeouts(port, &to);
PurgeComm(port, PURGE_TXCLEAR | PURGE_RXCLEAR);
if (port){
cout << "Hello" << endl;
WriteFile(port, data, sizeof(data), &buffer, 0);
system("pause");
data[0] = { 0x00 };
data[1] = { 0x5A };
data[2] = { 0x56 };
data[3] = { 0xFF };
data[4] = { 0x04 };
data[5] = { 0x00 };
data[6] = { 0x00 };
data[7] = { 0x00 };
data[8] = { 0xB3 };
WriteFile(port, data, sizeof(data), &buffer, 0);
}
else{
cout << "World" << endl;
}
CloseHandle(port);
system("pause");
return 0;
}
There is no way that code could work. It should not have compiled.
At a minimum, the first parameter to Writefile is the file handle, and the third parameter is the number of bytes to write.
WriteFile(
hcomm,
"the string",
strlen ("the string"),
Also, you probably need to set the serial port's characteristics. That can be done using the command line or control panel, but it is often useful for the program to handle the details itself, after opening the file:
DCB dcb;
dcb.DCBlength = sizeof(dcb);
GetCommState(m_hCom, &dcb); /* retrieve current settings */
dcb.BaudRate = m_baudrate; /* alter bits per second */
dcb.ByteSize = (BYTE)m_bytesize; /* bits per character */
dcb.Parity = m_parity;
dcb.StopBits = m_stopbit;
if (m_useRtsCts)
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_DISABLE; // no handshake
dcb.fNull = FALSE; /* don't strip NULs */
dcb.fAbortOnError = FALSE; /* keep going after errors */
ok=SetCommState(hcomm, &dcb);
Addendum
To write the nine binary values as character values, any of these techniques would work. All rely on expressing the binary numbers as bytes:
char data[] = "\000\132\124\000\003\000\000\000\261";
WriteFile(hcomm, data, sizeof data, NULL, NULL);
or
char data[] = {0, 0132, 0124, 0, 3, 0, 0, 0, 0261};
WriteFile(hcomm, data, sizeof data, NULL, NULL);
or
char data[] = {0, 0x5a, 0x54, 0, 3, 0, 0, 0, 0xb1};
WriteFile(hcomm, data, sizeof data, NULL, NULL);
Setting telepathy mode on, I'd assume that TS wants to send 9-bit data. A typical way to achieve it is to use parity as a 9th data bit. The main idea is to cause a parity error to signify the 9th bit set. The details depend on the available hardware ad drivers.
If uart supports MARK/SPACE parities, something like this would work:
send_9_bits(unsigned char data, bool ninth_bit) {
if(ninth_bit) set_parity_mark();
else set_parity_space();
uart_write(data);
}
with the receiving end to analyze parity error status:
unsigned short receive_9_bits() {
unsigned short data = uart_read();
bool ninth_bit;
if (even_parity(data & 0x00ff) {
ninth_bit = PARERR(data >> 8)? 1: 0;
} else {
ninth_bit = PARERR(data >> 8)? 0: 1;
}
return (data & 0x0ff) | (ninth_bit << 8);
}
The serial port cannot work with a baud rate of 0. The baud rate, byte size, parity and stop bits must all be set to match the settings used by the device you are communicating with. And only certain standard values are supported by the serial hardware.
A ^ ( (A >> 2) + (A << 5) + C ) == B
How to find A if B is const and C is variable? (C can be changed if there is no solution with it)
A is DWORD, B is DWORD, C is BYTE != 0
Edit1: after GalacticJello's answer, I've got another question: is there any way to do it without a loop (simplifying the expression)?
Why do I need this:
I am trying to make a reverse function (collision searcher) for
unsigned int X(const char* const in) { //strlen(in) is always < 127
unsigned int result = 0x12345678; //just for an example
for(int i = 0; in[i] != 0; ++i)
result ^= (result >> 2) + (result << 5) + in[i];
return result;
}
Currently I have a loop that generates random C and then searches A.
(I search A using a loop that generates a random value [for A] and checks if the above expression is true)
Edit2: This is my current code for searching collisions, that I am testing now..
#include <stdio.h>
#include <conio.h>
using namespace std;
unsigned int originalHash(const char* const in) {
unsigned int result = 0x12345678;
for(int i = 0; in[i] != 0; ++i) {
result = result ^ ((result >> 2) + (result << 5) + in[i]);
}
return result;
}
//A ^ ( (A >> 2) + (A << 5) + C ) == B
bool findSolutions(unsigned int inHash, char* _C, unsigned int* _A) { //Starts searching from *A and *C and writes there values on success.
unsigned int C = *_C;
if(C == 0) ++C;
unsigned int A = *_A;
for(C; C < 256; ++C) {
for(A; A < 0xFFFFFFFF; ++A) {
if((A ^ ( (A >> 2) + (A << 5) + C )) == inHash) {
*_C = C;
*_A = A;
return true;
}
}
A = 0;
}
return false;
}
bool findCollisions(unsigned int inHash, char* szOutStr) {
const unsigned int REQ_HASH = 0x12345678;
unsigned int prevHash = 0;
int curChar = 0;
do {
printf("Loop Begin:\tI = %i | H = %08x | rH = %08x\n", curChar, inHash, REQ_HASH);
if(!findSolutions(inHash, &szOutStr[curChar], &prevHash)) {
printf("Unable to find solutions for %08x\n", inHash);
if(curChar == 0) return false;
--curChar;
continue;
}
if(prevHash == REQ_HASH) {
szOutStr[curChar] = 0;
return true;
}
printf("Found solution:\tC = %02x (%c) | A = %08x\n", szOutStr[curChar], szOutStr[curChar], prevHash);
char firstSolutionC = szOutStr[curChar];
unsigned int firstSolutionA = prevHash;
printf("Trying to find alternative solutions..\n");
do {
if(!findSolutions(inHash, &szOutStr[curChar], &prevHash)) {
printf("Alternative solution not found!\n");
break;
}
printf("Alternative solution found [%s valid]:\tC = %02x (%c) | A = %08x\n", prevHash == REQ_HASH ? "" : "not", szOutStr[curChar], szOutStr[curChar], prevHash);
if(prevHash == REQ_HASH) {
szOutStr[curChar] = 0;
return true;
}
++prevHash;
} while(true);
szOutStr[curChar] = firstSolutionC;
prevHash = firstSolutionA;
printf("Using first solution:\tC = %02x (%c) | A = %08x\n", szOutStr[curChar], szOutStr[curChar], prevHash);
++curChar;
inHash = prevHash;
} while(curChar < 127);
return false;
}
int main(void) {
char mask[] = "hQh";
DWORD original = originalHash(mask);
printf("%s == %08x\n", mask, original);
char out[128];
memset(out, 0, sizeof out);
if(findCollisions(original, out))
printf("%08x == %s\n", original, out);
else
printf("Unable to find collisions\n");
getch();
return 0;
}
I'm just going to take a stab at the question (sorry for the C# code, but you should be able to get the gist):
A ^ ( (A >> 2) + (A << 5) + C ) == B
static List<Tuple<uint, uint>> FindSolutions(uint B)
{
var solutions = new List<Tuple<uint, uint>>();
for (uint C = 0; C < uint.MaxValue; C++)
{
for (uint A = 0; A < uint.MaxValue; A++)
{
uint guess = A ^ ((A >> 2) + (A << 5) + C);
if (guess == B)
solutions.Add(new Tuple<uint,uint>(A, C));
}
}
return solutions;
}
var solutions = FindSolutions(0x00000001);
If B is your constant (0x00000001 in this case), then the first few solutions for A and C are:
A = 0x8b439581, B= 0x00000001, C = 0x00000000
(0x8b439581 ^ ((22d0e560) + (6872B020) + 0)) == 0x00000001
0x8b439581 ^ (0x8b439580) == 0x00000001
0x00000001 == 0x00000001
others:
A = 0x9ba5e354, B= 0x00000001, C = 0x00000000
A = 0x00000000, B= 0x00000001, C = 0x00000000
A = 0x6a7ef9db, B= 0x00000001, C = 0x00000004
... etc.
EDIT:
To find collisions, you can simply perform a brute force through the keyspace.
Again, sorry for the C# code:
static uint originalHash(string input)
{
unt result = 0x12345678;
for (int i = 0; i < input.Length; i++)
result ^= (result >> 2) + (result << 5) + input[i];
return result;
}
var charset = new string(Enumerable.Range(1, 255).Select(i => (char)i).ToArray());
var hits = new List<string>();
var hashToFind = originalHash("hQh");
for (int wordNum = 1; wordNum < int.MaxValue; wordNum++)
{
var word = Utils.NumberToString(wordNum, charset);
var guess = originalHash(word);
if (guess == hashToFind)
{
Console.WriteLine("Found: " + word);
hits.Add(word);
}
}
Running the above code gave me the following collisions after a minute or two:
cê cë1 côÌ cõí cö c÷¦ cøG cùh dÌ1 dÍ dÒí dÓÌ dÖh d×G dئ dÙ e¬
e1 e²Ì e³í e¶G e·h e¸ e¹¦ f1 f f¦ f fh fG fí fÌ gm gn1
gq gr¦ gsG gth gwÌ gxí hO1 hP hQh hRG hS¦ hT hUí hVÌ i/ i01 i1G
i2h i3 i4¦ i5Ì i6í
Those don't translate well, here's the byte values:
{ 0x63, 0xEA, 0x10, }
{ 0x63, 0xEB, 0x31, }
{ 0x63, 0xF4, 0xCC, }
{ 0x63, 0xF5, 0xED, }
{ 0x63, 0xF6, 0x85, }
{ 0x63, 0xF7, 0xA6, }
{ 0x63, 0xF8, 0x47, }
{ 0x63, 0xF9, 0x68, }
{ 0x64, 0xCC, 0x31, }
{ 0x64, 0xCD, 0x10, }
{ 0x64, 0xD2, 0xED, }
{ 0x64, 0xD3, 0xCC, }
{ 0x64, 0xD6, 0x68, }
{ 0x64, 0xD7, 0x47, }
{ 0x64, 0xD8, 0xA6, }
{ 0x64, 0xD9, 0x85, }
{ 0x65, 0xAC, 0x10, }
{ 0x65, 0xAD, 0x31, }
{ 0x65, 0xB2, 0xCC, }
{ 0x65, 0xB3, 0xED, }
{ 0x65, 0xB6, 0x47, }
{ 0x65, 0xB7, 0x68, }
{ 0x65, 0xB8, 0x85, }
{ 0x65, 0xB9, 0xA6, }
{ 0x66, 0x8D, 0x31, }
{ 0x66, 0x8E, 0x10, }
{ 0x66, 0x91, 0xA6, }
{ 0x66, 0x92, 0x85, }
{ 0x66, 0x93, 0x68, }
{ 0x66, 0x94, 0x47, }
{ 0x66, 0x97, 0xED, }
{ 0x66, 0x98, 0xCC, }
{ 0x67, 0x6D, 0x10, }
{ 0x67, 0x6E, 0x31, }
{ 0x67, 0x71, 0x85, }
{ 0x67, 0x72, 0xA6, }
{ 0x67, 0x73, 0x47, }
{ 0x67, 0x74, 0x68, }
{ 0x67, 0x77, 0xCC, }
{ 0x67, 0x78, 0xED, }
{ 0x68, 0x4F, 0x31, }
{ 0x68, 0x50, 0x10, }
{ 0x68, 0x51, 0x68, }
{ 0x68, 0x52, 0x47, }
{ 0x68, 0x53, 0xA6, }
{ 0x68, 0x54, 0x85, }
{ 0x68, 0x55, 0xED, }
{ 0x68, 0x56, 0xCC, }
{ 0x69, 0x2F, 0x10, }
{ 0x69, 0x30, 0x31, }
{ 0x69, 0x31, 0x47, }
{ 0x69, 0x32, 0x68, }
{ 0x69, 0x33, 0x85, }
{ 0x69, 0x34, 0xA6, }
{ 0x69, 0x35, 0xCC, }
{ 0x69, 0x36, 0xED, }
In my program which sends bytes to a serial port, I receive bytes which I send. I don't want to receive bytes which I send, and I don't know how to do this?
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/ioctl.h>
int fd;
struct termios tio, old_tio;
time_t SubTime_mSec(timeval val1, timeval val2)
{
timeval tv;
if (val1.tv_sec > val2.tv_sec) return (0);
if (val1.tv_sec == val2.tv_sec)
if (val1.tv_usec > val2.tv_usec) return (0);
tv.tv_sec = val2.tv_sec - val1.tv_sec;
if (val1.tv_usec < val2.tv_usec) {
tv.tv_usec = val2.tv_usec - val1.tv_usec;
} else {
tv.tv_sec --;
tv.tv_usec = 1000000 + val2.tv_usec - val1.tv_usec;
}
return(tv.tv_sec*1000 + tv.tv_usec/1000);
}
void RTUOutMessage(int cnt1, int cnt2)
{
unsigned char msg[13] = {0x01, 0x10, 0x00, 0x2F, 0x00, 0x02, 0x04, 0x4B, 0x64, 0x3D, 0xD9, 0x36, 0xC6};
int Len = 13;
int status, i, j;
ioctl(fd, TIOCMGET, &status);
status = status | TIOCM_RTS | TIOCM_DTR;
ioctl(fd, TIOCMSET, &status);
write(fd, msg, Len);
for (j = 0; j < cnt1; j ++)
for (i = 0; i < cnt2; i ++);
ioctl(fd, TIOCMGET, &status);
status &= ~TIOCM_RTS;
status &= ~TIOCM_DTR;
ioctl(fd, TIOCMSET, &status);
timeval start_t, curr_t;
char Buff[80];
int l;
gettimeofday(&start_t, NULL);
curr_t = start_t;
while (SubTime_mSec(start_t, curr_t) < 1000) {
l = read(fd, Buff, 80);
if (l > 0) {
printf("BUFFER=");
for(i = 0; i < l; i++) {
printf(" %x", Buff[i]);
}
//printf("\n");
}
gettimeofday(&curr_t, NULL);
}
}
void InitPort(void)
{
int StopBits = 2;
if ((fd = open("/dev/ttyAM2", O_RDWR | O_NDELAY)) < 0) {
printf("Couldn't open //dev//ttyAM2\n");
}
tcflush(fd, TCIOFLUSH);
int n = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, n & ~O_NDELAY);
tcgetattr(fd, &old_tio);
tcgetattr(fd, &tio);
cfsetospeed(&tio, (speed_t)B9600);
cfsetispeed(&tio, (speed_t)B9600);
tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8;
tio.c_cflag |= CLOCAL | CREAD ;
tio.c_cflag &= ~OFILL;
//parity
tio.c_cflag &= ~(PARENB | PARODD);
tio.c_cflag &= ~CRTSCTS;
if (StopBits == 2) tio.c_cflag |= CSTOPB;
else tio.c_cflag &= ~CSTOPB;
tio.c_iflag=IGNBRK;
tio.c_iflag &= ~(IXON|IXOFF|IXANY);
tio.c_lflag=0;
tio.c_oflag=0;
tio.c_cc[VTIME]=0;
tio.c_cc[VMIN]=0;
if (tcsetattr(fd, TCSANOW, &tio)!=0) printf("tcsetattr() 1 failed\n");
int mcs=0;
ioctl(fd, TIOCMGET, &mcs);
mcs |= TIOCM_RTS;
ioctl(fd, TIOCMSET, &mcs);
if (tcgetattr(fd, &tio)!=0) printf("tcgetattr() 4 failed\n");
tio.c_cflag &= ~CRTSCTS;
if (tcsetattr(fd, TCSANOW, &tio)!=0) printf("tcsetattr() 2 failed\n");
}
int main(int argc, char **argv)
{
InitPort();
int cnt1, cnt2;
cnt1 = 3;
cnt2 = 20000;
cnt1 = atoi(argv[1]);
cnt2 = atoi(argv[2]);
for(;;) {
RTUOutMessage(cnt1, cnt2);
usleep(1000000);
}
tcsetattr(fd, TCSANOW, &old_tio);
close(fd);
printf("End\n");
return 0;
}
If you are receiving the chars that you sent, then the remote's serial port is apparently echoing its input.
You will either have to disable input echo at the other device, or perform "echo cancellation" in your receive logic. I.E. create an "echo FIFO". Each byte output to the serial port is also written to the "echo FIFO". Set a flag indicating that an echo is expected. As input is received, compare it to the "echo FIFO", and remove chars when it matches, and toss the receive char. If no match, then accept receive char. Clear the echo flag when the "echo FIFO" is empty.
BTW the code appears to set the serial port to raw or non-canonical mode. The preferred method would be to use
cfmakeraw(&tio);
rather than
tio.c_iflag=IGNBRK;
tio.c_iflag &= ~(IXON|IXOFF|IXANY);
tio.c_lflag=0;
tio.c_oflag=0;