Skip to content

Instantly share code, notes, and snippets.

@eburlingame
Created October 24, 2018 06:51
Show Gist options
  • Save eburlingame/9e059b1b2e1e28e72fa756cfe2de1702 to your computer and use it in GitHub Desktop.
Save eburlingame/9e059b1b2e1e28e72fa756cfe2de1702 to your computer and use it in GitHub Desktop.
Basic data retrieval from X-Plane using winsock2 over UDP
// 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