2024-01-22 17:35:55 +01:00
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <inttypes.h>
2024-01-24 22:08:06 +01:00
# include <math.h>
2024-01-22 17:35:55 +01:00
2024-01-24 22:08:06 +01:00
# include <mosquitto.h>
2024-01-22 17:35:55 +01:00
# include "network.h"
2024-01-22 22:00:14 +01:00
# include "mqtt.h"
# include "config.h"
2024-01-22 17:35:55 +01:00
2024-01-24 22:08:06 +01:00
# define MQTT_RREF_REQUEST_LENGTH_ID 3
# define MQTT_RREF_REQUEST_LENGTH_FREQ 3
# define MQTT_RREF_REQUEST_LENGTH_SEPARATOR 1
# define MQTT_RREF_REQUEST_SEPARATOR ' '
const int MQTT_RREF_REQUEST_START_ID = 0 ;
const int MQTT_RREF_REQUEST_START_FREQ = MQTT_RREF_REQUEST_START_ID + MQTT_RREF_REQUEST_LENGTH_ID + MQTT_RREF_REQUEST_LENGTH_SEPARATOR ;
const int MQTT_RREF_REQUEST_START_RREF = MQTT_RREF_REQUEST_START_FREQ + MQTT_RREF_REQUEST_LENGTH_FREQ + MQTT_RREF_REQUEST_LENGTH_SEPARATOR ;
const int MQTT_RREF_REQUEST_MIN_LENGTH = MQTT_RREF_REQUEST_LENGTH_ID + MQTT_RREF_REQUEST_LENGTH_FREQ + ( 2 * MQTT_RREF_REQUEST_LENGTH_SEPARATOR ) + 1 ; // at least one char for rref
int xPlaneSocket ;
struct mosquitto * mqtt ;
2024-02-01 23:54:36 +01:00
struct valueCacheElement
{
float value ;
bool force ;
} ;
struct valueCacheElement * valueCache = NULL ;
int valueCacheCount = 0 ;
2024-01-24 22:08:06 +01:00
# define XPLANE_RREF_MAX_LENGTH 400
2024-01-22 21:20:10 +01:00
struct dref_struct_in
{
int32_t dref_freq ;
int32_t dref_sender_index ; // the index the customer is using to define this dataref
2024-01-24 22:08:06 +01:00
char dref_string [ XPLANE_RREF_MAX_LENGTH ] ;
2024-01-22 17:35:55 +01:00
} ;
2024-01-22 21:20:10 +01:00
struct dref_struct_out
{
int32_t dref_sender_index ;
float dref_flt_value ;
2024-01-22 17:35:55 +01:00
} ;
2024-01-24 22:08:06 +01:00
int * strtoint ( char * in , size_t start , size_t n )
2024-01-22 21:20:10 +01:00
{
2024-01-24 22:08:06 +01:00
int * ret = malloc ( sizeof ( int ) ) ;
* ret = 0 ;
int offset = start + n - 1 ;
2024-01-22 17:35:55 +01:00
2024-01-24 22:08:06 +01:00
if ( offset < 0 )
2024-01-22 21:20:10 +01:00
{
2024-01-24 22:08:06 +01:00
return NULL ;
}
2024-02-01 23:54:36 +01:00
for ( int i = 0 ; i < n ; i + + )
{
2024-01-24 22:08:06 +01:00
int position = offset - i ;
if ( in [ position ] > = ' 0 ' & & in [ position ] < = ' 9 ' )
{
* ret + = ( in [ position ] - ' 0 ' ) * pow ( 10 , i ) ;
}
else
{
return NULL ;
}
}
return ret ;
}
2024-01-24 22:49:28 +01:00
void requestRrefFromXPlane ( const struct mosquitto_message * message )
2024-01-24 22:08:06 +01:00
{
2024-02-01 23:54:36 +01:00
int * index , * frequency ;
2024-01-24 22:08:06 +01:00
2024-01-24 22:49:28 +01:00
if ( message - > payloadlen > = MQTT_RREF_REQUEST_MIN_LENGTH )
{
2024-02-01 23:54:36 +01:00
index = strtoint ( message - > payload , MQTT_RREF_REQUEST_START_ID , MQTT_RREF_REQUEST_LENGTH_ID ) ;
2024-01-24 22:49:28 +01:00
frequency = strtoint ( message - > payload , MQTT_RREF_REQUEST_START_FREQ , MQTT_RREF_REQUEST_LENGTH_FREQ ) ;
2024-02-01 23:54:36 +01:00
if ( index = = NULL | | frequency = = NULL )
{
2024-01-24 22:49:28 +01:00
return ;
}
2024-02-01 23:54:36 +01:00
if ( * index < valueCacheCount )
{
valueCache [ * index ] . force = true ;
}
2024-01-24 22:49:28 +01:00
// prepare struct to send, make sure padding is with NULL bytes
struct dref_struct_in drefToRead = {
. dref_freq = * frequency ,
2024-02-01 23:54:36 +01:00
. dref_sender_index = * index } ;
2024-01-24 22:49:28 +01:00
memset ( drefToRead . dref_string , 0 , sizeof ( drefToRead . dref_string ) ) ;
strncpy ( drefToRead . dref_string , & ( ( char * ) message - > payload ) [ MQTT_RREF_REQUEST_START_RREF ] , message - > payloadlen - MQTT_RREF_REQUEST_START_RREF ) ;
sendToXPlane ( xPlaneSocket , DEST_SERVER , DEST_PORT , " RREF " , ( char * ) & drefToRead , sizeof ( drefToRead ) ) ;
}
}
void sendCommandToXPlane ( const struct mosquitto_message * message )
{
char * command ;
2024-02-01 23:54:36 +01:00
if ( message - > payloadlen > 0 )
{
2024-01-24 22:49:28 +01:00
sendToXPlane ( xPlaneSocket , DEST_SERVER , DEST_PORT , " CMND " , ( char * ) message - > payload , message - > payloadlen ) ;
}
}
void onMessage ( struct mosquitto * mqtt , void * obj , const struct mosquitto_message * message )
{
2024-01-24 22:08:06 +01:00
printf ( " Received message %.*s on topic %s \n " , message - > payloadlen , ( char * ) message - > payload , message - > topic ) ;
if ( strcmp ( message - > topic , " /xplane/meta/rref " ) = = 0 )
{
2024-01-24 22:49:28 +01:00
requestRrefFromXPlane ( message ) ;
}
else if ( strcmp ( message - > topic , " /xplane/meta/cmnd " ) = = 0 )
{
sendCommandToXPlane ( message ) ;
2024-01-22 21:20:10 +01:00
}
2024-01-24 22:08:06 +01:00
else
{
fprintf ( stderr , " Unkown topic %s \n " , message - > topic ) ;
}
}
2024-01-22 17:35:55 +01:00
2024-01-24 22:08:06 +01:00
int main ( )
{
2024-01-22 21:20:10 +01:00
// network
xPlaneSocket = createSocket ( SRC_PORT ) ;
if ( xPlaneSocket < 0 )
{
exit ( EXIT_FAILURE ) ;
}
2024-01-22 17:35:55 +01:00
2024-01-22 22:00:14 +01:00
// mqtt
2024-02-01 20:51:01 +01:00
mqtt = connectMqtt ( MQTT_USER1 , MQTT_PASS , onMessage ) ;
2024-01-24 22:08:06 +01:00
if ( mqtt = = NULL )
2024-01-22 21:20:10 +01:00
{
2024-01-24 22:08:06 +01:00
exit ( EXIT_FAILURE ) ;
2024-01-22 21:20:10 +01:00
}
2024-01-22 17:35:55 +01:00
2024-01-24 22:08:06 +01:00
// subscribe meta channel
recvMqtt ( mqtt , " /xplane/meta/# " ) ;
2024-01-22 21:20:10 +01:00
// read from network
char msg [ DGRAM_MSG_LENGTH + 1 ] ;
char payload [ RECV_BUFFER ] ;
2024-01-22 22:00:14 +01:00
char mqttTopic [ 100 ] , mqttPayload [ 512 ] ;
2024-01-22 21:20:10 +01:00
while ( 1 )
{
int payloadBytes = recvFromXPlane ( xPlaneSocket , msg , payload , RECV_BUFFER ) ;
2024-01-24 22:08:06 +01:00
if ( payloadBytes > = 0 )
2024-01-22 21:20:10 +01:00
{
if ( strcmp ( msg , " RREF " ) = = 0 )
{
2024-01-24 22:08:06 +01:00
printf ( " Received message type %s \n " , msg ) ;
printf ( " Received message data (%d) " , payloadBytes ) ;
for ( int i = 0 ; i < payloadBytes ; i + + )
{
printf ( " %02x " , payload [ i ] ) ;
}
printf ( " \n " ) ;
2024-01-24 22:29:48 +01:00
// continue if payloadBytes is valid (1 byte + 8 bytes each dref)
if ( ( payloadBytes - 1 ) % sizeof ( struct dref_struct_out ) = = 0 )
2024-01-22 21:20:10 +01:00
{
2024-01-24 22:29:48 +01:00
// loop throught all provided drefs
for ( int i = 1 ; i < payloadBytes ; i + = sizeof ( struct dref_struct_out ) )
{
memset ( mqttTopic , 0 , sizeof ( mqttTopic ) ) ;
memset ( mqttPayload , 0 , sizeof ( mqttPayload ) ) ;
2024-01-22 22:00:14 +01:00
2024-01-24 22:29:48 +01:00
struct dref_struct_out drefRead ;
memcpy ( & drefRead , & payload [ i ] , sizeof ( struct dref_struct_out ) ) ;
2024-01-22 17:35:55 +01:00
2024-02-01 23:54:36 +01:00
// add new element to array
if ( valueCache = = NULL )
{
valueCacheCount = drefRead . dref_sender_index + 10 ;
valueCache = calloc ( valueCacheCount , sizeof ( struct valueCacheElement ) ) ;
}
else if ( drefRead . dref_sender_index > = valueCacheCount )
{
valueCacheCount = drefRead . dref_sender_index + 10 ;
valueCache = reallocarray ( valueCache , valueCacheCount , sizeof ( struct valueCacheElement ) ) ;
}
else
{
// size of array is sufficient
}
if ( valueCache [ drefRead . dref_sender_index ] . force | | valueCache [ drefRead . dref_sender_index ] . value ! = drefRead . dref_flt_value )
{
valueCache [ drefRead . dref_sender_index ] . value = drefRead . dref_flt_value ;
printf ( " %d: %f \n " , drefRead . dref_sender_index , drefRead . dref_flt_value ) ;
sprintf ( mqttTopic , " /xplane/rref/%d " , drefRead . dref_sender_index ) ;
sprintf ( mqttPayload , " %f " , drefRead . dref_flt_value ) ;
sendMqtt ( mqtt , mqttTopic , mqttPayload , strlen ( mqttPayload ) ) ;
valueCache [ drefRead . dref_sender_index ] . force = false ;
}
else
{
// neither changed nor forced
}
2024-01-24 22:29:48 +01:00
}
2024-01-22 21:20:10 +01:00
}
else
{
exit ( EXIT_FAILURE ) ;
}
}
else
{
// unknown to me
}
}
else
{
exit ( EXIT_FAILURE ) ;
}
2024-01-24 22:08:06 +01:00
2024-02-01 23:54:36 +01:00
mosquitto_loop ( mqtt , 0 , 1 ) ;
2024-01-22 21:20:10 +01:00
}
2024-01-22 17:35:55 +01:00
2024-01-22 21:20:10 +01:00
// bye bye (and no, I don't care about error anymore; I'll exit anyway?!)
2024-01-22 22:00:14 +01:00
disconnectMqtt ( mqtt ) ;
2024-01-22 21:20:10 +01:00
closeSocket ( xPlaneSocket ) ;
exit ( EXIT_SUCCESS ) ;
2024-01-22 17:35:55 +01:00
}