Created
October 24, 2018 06:51
-
-
Save eburlingame/9e059b1b2e1e28e72fa756cfe2de1702 to your computer and use it in GitHub Desktop.
Basic data retrieval from X-Plane using winsock2 over UDP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// XPlaneC.cpp : Defines the entry point for the console application. | |
// References | |
// http://www.nuclearprojects.com/xplane/xplaneref.html | |
// http://www.nuclearprojects.com/xplane/info.shtml | |
// https://docs.microsoft.com/en-us/windows/desktop/winsock/windows-sockets-error-codes-2 | |
// https://stackoverflow.com/questions/32471004/udp-client-not-receiving-udp-server-message | |
#include "stdafx.h" | |
#include <stdio.h> | |
#include <string.h> | |
#include <windows.h> // Needed for all Winsock stuff | |
#pragma comment(lib,"ws2_32.lib") //Winsock Library | |
//----- Defines --------------------------------------------------------------- | |
#define PORT_NUM 49003 // Port number used | |
#define IP_ADDR "127.0.0.1" // IP address of server1 (*** HARDWIRED ***) | |
#define XCHR char // (character, in local byte - order for the machine you are on) | |
#define XINT int // (4 - byte int, in local byte - order for the machine you are on) | |
#define XFLT float // (4 - byte ints and floats, in local byte - order for the machine you are on) | |
#define XDOB double // (double - precision float, in local byte - order for the machine you are on) | |
#define strDIM 500 | |
#define vehDIM 10 | |
#define net_SIZE_buff 1024 | |
typedef enum state { | |
LAT_LON_ALT = 20 | |
} State; | |
typedef struct lat_lon_alt_type { | |
float lat_deg; | |
float lon_deg; | |
float alt_ftmsl; | |
float alt_ftagl; | |
float on_runway; | |
float alt_ind; | |
float lat_orign; | |
float lon_orign; | |
} lat_lon_alt_type; | |
struct data_struct | |
{ | |
int index; // data index, the index into the list of variables you can output from the Data Output screen in X-Plane. | |
float data[8]; // the up to 8 numbers you see in the data output screen associated with that selection.. many outputs do not use all 8, though. | |
}; | |
void NET_send(int client, sockaddr_in server_addr, XCHR label[5], XCHR* data_in, XINT data_len) | |
{ | |
XCHR data_send[net_SIZE_buff]; | |
data_send[0] = label[0]; | |
data_send[1] = label[1]; | |
data_send[2] = label[2]; | |
data_send[3] = label[3]; | |
data_send[4] = 0; | |
memcpy(&data_send[5], data_in, data_len); // load in the data | |
data_len += 5; | |
XINT send_failed = (sendto(client, data_send, data_len, 0, (const struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)) != data_len); | |
if (send_failed < 0) | |
{ | |
int err = WSAGetLastError(); | |
printf("sendto() failed with error code : %d\n", err); | |
exit(-1); | |
} | |
} | |
void NET_recv(int client, sockaddr_in server_addr, XCHR *label, data_struct *data) | |
{ | |
XCHR data_out[net_SIZE_buff]; | |
int addr_len = sizeof(server_addr); | |
int retcode = recvfrom(client, data_out, net_SIZE_buff, 0, (struct sockaddr *)&server_addr, &addr_len); | |
if (retcode < 0) | |
{ | |
int err = WSAGetLastError(); | |
printf("recvfrom() failed with error code : %d\n", err); | |
exit(-1); | |
} | |
if (strncmp(data_out, "DATA", 4) == 0) | |
{ | |
memcpy(data, data_out + 5, sizeof(data_struct)); | |
} | |
} | |
int setup_socket(int *client_s, sockaddr_in *server_addr) | |
{ | |
int opt = 1; | |
*client_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
if (client_s < 0) | |
{ | |
printf("*** ERROR - socket() failed \n"); | |
} | |
//UDP Broadcast permissions | |
if (setsockopt(*client_s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)) == SOCKET_ERROR) | |
{ | |
printf("\nERROR in broadcasting ERROR CODE : %d \n", WSAGetLastError()); | |
closesocket(*client_s); | |
WSACleanup(); | |
return 1; | |
} | |
//UDP SOCKET Binding | |
if (bind(*client_s, (sockaddr *)server_addr, sizeof(sockaddr_in)) == SOCKET_ERROR) | |
{ | |
int err = WSAGetLastError(); | |
printf("\nUDP socket binding failed ERROR CODE : %d\n", err); | |
closesocket(*client_s); | |
WSACleanup(); | |
exit(-1); | |
} | |
} | |
//===== Main program ========================================================== | |
int main() | |
{ | |
WORD wVersionRequested = MAKEWORD(1, 1); // Stuff for WSA functions | |
WSADATA wsaData; // Stuff for WSA functions | |
int client_s; | |
sockaddr_in server_addr; | |
WSAStartup(wVersionRequested, &wsaData); | |
server_addr.sin_family = AF_INET; // Address family to use | |
server_addr.sin_port = htons(PORT_NUM); // Port num to use | |
server_addr.sin_addr.s_addr = INADDR_ANY; | |
setup_socket(&client_s, &server_addr); | |
for (;;) | |
{ | |
char label[5]; | |
data_struct d; | |
NET_recv(client_s, server_addr, label, &d); | |
//printf("Index: %d\n", d.index); | |
//for (int j = 0; j < 8; j++) | |
//{ | |
// printf("d[%d] = %.2f\n ", j, d.data[j]); | |
//} | |
//printf("\n"); | |
switch(d.index) | |
{ | |
case LAT_LON_ALT: | |
lat_lon_alt_type *t = (lat_lon_alt_type*) d.data; | |
printf("Lat: %f\n", t->lat_deg); | |
printf("Lon: %f\n", t->lon_deg); | |
printf("Alt MSL: %f\n", t->alt_ftmsl); | |
printf("ALt AGL: %f\n", t->alt_ftagl); | |
printf("Alt Ind: %f\n", t->alt_ind); | |
printf("On rwy: %f\n", t->on_runway); | |
printf("Lat Orign: %f\n", t->lat_orign); | |
printf("Lon Orign: %f\n", t->lon_orign); | |
break; | |
} | |
printf("\n"); | |
Sleep(100); | |
} | |
if (closesocket(client_s) < 0) | |
{ | |
printf("*** ERROR - closesocket() failed \n"); | |
exit(-1); | |
} | |
WSACleanup(); | |
return(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment