#include <stdio.h>
#include <string>
#include <iostream>
#include "zmq.h"
#include "zmq_utils.h"
#include <Windows.h>
char starter = 29;
char terminator = 30;
static const char arm_motorshield = 0;
static const char get_milliamps = 1;
static const char get_fault = 2;
static const char set_brakes = 3;
static const char set_speed = 4;
static const char set_brakes_A = 5;
static const char set_brakes_B = 6;
static const char set_speed_A = 7;
static const char set_speed_B = 8;
static const char echo_data = 9;
static const char set_max_speed = 10;
static const char I_AM_ALIVE = 111;
static const char CONNECTION_OK = 69;
static const char UN_ARM = 33;
struct Packet
{
private:
char data[7];
public:
Packet()
{
data[0] = starter;
data[6] = terminator;
}
Packet(const char action, int value_one, int value_two)
{
set(action, value_one, value_two);
}
Packet(const char action, char byte_a, char byte_b, char byte_c, char byte_d)
{
set(action, byte_a, byte_b, byte_c, byte_d);
}
void set(const char action, int value_one, int value_two)
{
data[0] = starter;
data[1] = action;
data[2] = ((value_one & 0xFF00) >> 8);
data[3] = (value_one & 0xFF);
data[4] = ((value_two & 0xFF00) >> 8);
data[5] = (value_two & 0xFF);
data[6] = terminator;
}
void set(const char action, char byte_a, char byte_b, char byte_c, char byte_d)
{
data[0] = starter;
data[1] = action;
data[2] = byte_a;
data[3] = byte_b;
data[4] = byte_c;
data[5] = byte_d;
data[6] = terminator;
}
void set(char * _data, size_t datasize = 7)
{
if (datasize > 7)
datasize = 7;
for (size_t i = 0; i < datasize; ++i)
{
data[i] = _data[i];
}
}
int GetValueOneLR()
{
return ((data[2] << 8) & data[3]);
}
int GetValueOneRL()
{
return ((data[3] << 8) & data[2]);
}
int GetValueTwoLR()
{
return ((data[4] << 8) & data[5]);
}
int GetValueTwoRL()
{
return ((data[5] << 8) & data[4]);
}
const char GetAction()
{
return data[1];
}
char GetB1()
{
return data[2];
}
char GetB2()
{
return data[3];
}
char GetB3()
{
return data[4];
}
char GetB4()
{
return data[5];
}
bool valid()
{
return (data[0] == starter && data[6] == terminator);
}
char * get()
{
return &data[0];
}
size_t size()
{
return 7;
}
};
#pragma comment(lib, "../libzmq.lib")
void DoCheckSendWithError(void *client, Packet& packetinfo)
{
if (zmq_send(client, packetinfo.get(), packetinfo.size(), ZMQ_DONTWAIT) == -1)
{
std::cout << "ZMQ !!!packetinfo!!! Send error: ";
int err = zmq_errno();
switch (err)
{
case EAGAIN:
std::cout << "EAGAIN";
break;
case ENOTSUP:
std::cout << "ENOTSUP";
break;
case EFSM:
std::cout << "EFSM";
break;
case ETERM:
std::cout << "ETERM";
break;
case ENOTSOCK:
std::cout << "ENOTSOCK";
break;
case EINTR:
std::cout << "EINTR";
break;
case EFAULT:
std::cout << "EFAULT";
break;
}
std::cout << "\r\n" << std::flush;
}
else
{
std::cout << "Send OK\r\n" << std::flush;
}
}
int main()
{
std::cout << "Exit with Left Ctrl+Q\r\n" << std::flush;
void *context = zmq_ctx_new();
void *client = zmq_socket(context, ZMQ_DEALER);
if (zmq_connect(client, "tcp://tank.mshome.net:5000") == 0)
{
std::cout << "CONNECTION OK\r\n" << std::flush;
char buffer[1024];
Packet packetinfo;
Packet alive(I_AM_ALIVE,0,0,0,0);
ULONGLONG time_last_alive_sent = 0;
ULONGLONG timenow;
while ((GetAsyncKeyState(VK_LCONTROL) && GetAsyncKeyState('Q')) == 0)
{
timenow = GetTickCount64();
if ((timenow - time_last_alive_sent) > 200)
{
time_last_alive_sent = timenow;
if (zmq_send(client, alive.get(), alive.size(), ZMQ_DONTWAIT) == -1)
{
std::cout << "ZMQ !!!ALIVE!!! Send error: ";
int err = zmq_errno();
switch (err)
{
case EAGAIN:
std::cout << "EAGAIN";
break;
case ENOTSUP:
std::cout << "ENOTSUP";
break;
case EFSM:
std::cout << "EFSM";
break;
case ETERM:
std::cout << "ETERM";
break;
case ENOTSOCK:
std::cout << "ENOTSOCK";
break;
case EINTR:
std::cout << "EINTR";
break;
case EFAULT:
std::cout << "EFAULT";
break;
}
std::cout << "\r\n" << std::flush;
}
}
char currentpacket;
if (zmq_recv(client, ¤tpacket, 1, ZMQ_DONTWAIT) != -1)
{
if (currentpacket == starter)
{
Sleep(16);
buffer[0] = currentpacket;
int received = zmq_recv(client, &buffer[1], 6, ZMQ_DONTWAIT);
if (received == 6)
{
packetinfo.set(buffer, 7);
switch (packetinfo.GetAction())
{
case get_milliamps:
{
std::cout << "Current stats:";
std::cout << "\r\n\tMotor 1: " << (unsigned int)packetinfo.GetValueOneLR() << " mA";
std::cout << "\r\n\tMotor 2: " << (unsigned int)packetinfo.GetValueTwoLR() << " mA";
std::cout << "\r\n\tMotor 1: " << (unsigned int)packetinfo.GetValueOneRL() << " mA";
std::cout << "\r\n\tMotor 2: " << (unsigned int)packetinfo.GetValueTwoRL() << " mA";
std::cout << "\r\n" << std::flush;
break;
}
case get_fault:
{
std::cout << "Fault stats:";
std::cout << "\r\n\tMotor 1: " << (bool)packetinfo.GetB1();
std::cout << "\r\n\tMotor 2: " << (bool)packetinfo.GetB2();
std::cout << "\r\n" << std::flush;
break;
}
case CONNECTION_OK:
{
std::cout << "Connection is still alive!!\r\n" << std::flush;
break;
}
default:
{
std::cout << "Unknown packet received\r\n" << std::flush;
break;
}
}
}
else if (received < 5 && received > 0)
{
std::cout << "Unknown sized packet received: \r\n";
std::cout << received << ": [" << std::hex << (int)buffer[0] << "|"
<< std::hex << (int)buffer[1] << "|"
<< std::hex << (int)buffer[2] << "|"
<< std::hex << (int)buffer[3] << "|"
<< std::hex << (int)buffer[4] << "|"
<< std::hex << (int)buffer[5] << "|"
<< std::hex << (int)buffer[6] << "]" << "\r\n" << std::flush;
}
}
}
if (GetAsyncKeyState('W') & 1)
{
packetinfo.set(set_speed, 200, 200);
DoCheckSendWithError(client, packetinfo);
}
if (GetAsyncKeyState('S') & 1)
{
packetinfo.set(set_brakes, 400, 400);
DoCheckSendWithError(client, packetinfo);
}
if (GetAsyncKeyState('Z') & 1)
{
packetinfo.set(set_speed, -200, -200);
DoCheckSendWithError(client, packetinfo);
}
if (GetAsyncKeyState('A') & 1)
{
packetinfo.set(set_speed, -200, 200);
DoCheckSendWithError(client, packetinfo);
}
if (GetAsyncKeyState('D') & 1)
{
packetinfo.set(set_speed, 200, -200);
DoCheckSendWithError(client, packetinfo);
}
if (GetAsyncKeyState('R') & 1)
{
packetinfo.set(set_speed, 0, 0);
DoCheckSendWithError(client, packetinfo);
}
if (GetAsyncKeyState('C') & 1)
{
packetinfo.set(get_milliamps, 0, 0);
DoCheckSendWithError(client, packetinfo);
}
if (GetAsyncKeyState('F') & 1)
{
packetinfo.set(get_fault, 0, 0);
DoCheckSendWithError(client, packetinfo);
}
if (GetAsyncKeyState('U') & 1)
{
packetinfo.set(UN_ARM, 5000, 3333);
DoCheckSendWithError(client, packetinfo);
}
Sleep(1);
}
}
else
{
std::cout << "CONNECTION FAIL\r\n" << std::flush;
}
zmq_ctx_destroy(&context);
return 0;
}