Zmienna string o określonej/dynamicznej długości

0

Witam serdecznie,

Jestem początkujący więc proszę o wyrozumiałość. Próbuję napisać program który odczyta dane z gry. Łączy się on z grą za pomocą wtyczki simconnect i biblioteki .dll. Nie będę wrzucał całego kodu, bo jest raczej mało czytelny. Podzielę go na części:

Struktura:

struct DataRefs
{
    double overspeed_wrn;
    double inner_marker;
    double middle_marker;
    double outer_marker;
    char title[128]; //  <- tutaj jest problem!
};

Inicjalizacje (nie wiem właściwie jak to nazwać):

    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "OVERSPEED WARNING", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "INNER MARKER", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "MIDDLE MARKER", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "OUTER MARKER", "Bool");

    //
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "ATC FLIGHT NUMBER", "Variable length string"); // <- ta zmienna nie działa

Zmienne numeryczne działają bez problemu, a dla tekstowych nie zwraca nic. Próbowałem też innych zmiennych zwracających np. String64 ale również nie zwraca nic.

Próbowałem zadeklarować zmienną title również jako string ale bez efektu.

Na forum simconnect znalazłem jedno rozwiązanie. Wygląda to trochę inaczej bo dotyczy starszej wersji simconnect ale zaproponowano tam takie rozwiązanie:

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public String tailnumber;  // <----  w moim wypadku title

niestety u mnie kompilator zwraca błąd "...main.cpp|97|error: expected unqualified-id before '[' token|" w linii [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]

Pomóżcie proszę, bo nie mogę tego zrozumieć

KoSik

1

To drugie rozwiązanie to C#.

Niestety nie zamieściłeś istotnej części kodu (polecam lekturę), więc ciężko ci pomóc poza "użyj std::string dla stringów"

4

Ja dodam: jak na kogoś kto twierdzi, że jest początkujący, to zabrałeś się za zbyt skomplikowany problem (mieszanie języków programowania, jakaś dziwna biblioteka). Zapewne to jest główny przyczynek, który utrudnia ci zadania na tyle dobrego pytania, żeby koś z forum mógł ci pomóc.

0

To drugie rozwiązanie to C#

Wstyd mi ale nie odróżniam

istotnej części kodu

nie wiem co może być jeszcze istotne. Może po prostu wkleję cały kod.

zabrałeś się za zbyt skomplikowany problem

Niestety taki mam do rozwiązania. Pogram już od jakiegoś czasu działa i poradziłem sobie bez większych trudności. Chcę go natomiast nieco rozbudować i tutaj pojawił się problem.

mieszanie języków programowania

Mieszanie języków i owszem, bo więcej piszę w C ale na mikroprocesory więc ciężko mi się przerzucić.

Jestem świadomy tego, że może się okazać, iż rozwiązanie z char jest poprawne, a to simconnect nie zrzuca poprawnie danych ale chciałem tutaj zapytać bardziej doświadczonych

Cały kod:

extern "C" {
#include "Include/DirectOutput.h"
#include "Include/SimConnect.h"
#include "Include/leds.h"
}
#include <vector>
#include <iostream>
#include <cwchar>
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <map>
#include <thread>

#include <fstream>
#include <string>
#include "src/pugixml.hpp"

using namespace std;

//------zmienne--------------------------------------
HRESULT hr;
DWORD cbData = 0;
bool bRequestProcessed = false;
DWORD dwPage = 1;

bool blink;

SIMCONNECT_RECV* pData = NULL;
SIMCONNECT_RECV_SIMOBJECT_DATA* pObjData = NULL;

std::vector<void*> devices;
HANDLE hSimConnect = NULL;

//-----------------definicje---------------------------
enum DATA_DEFINE_ID
{
    DEFINITION_ID_AP,
};

enum DATA_REQUEST_ID
{
    REQUEST_AP_SETTINGS,
};

enum EVENT_ID
{
    EVENT_SET_AP_ALTITUDE,
};

std::vector<std::string> mfdLine {"AP_CRS1", "AP_HDG", "AP_VS"};
std::vector<std::string> diody {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""};
std::map<std::string, int> dek {{"LED_FIRE", 0}, {"LED_FIRE_A", 1}, {"LED_FIRE_B", 3}, {"LED_FIRE_D", 5}, {"LED_FIRE_E", 7}, {"LED_TOGGLE_1_2", 9}, {"LED_TOGGLE_3_4", 11}, {"LED_TOGGLE_5_6", 13}, {"LED_POV_2", 15}, {"LED_CLUTCH", 17}, {"LED_THROTTLE", 19},};

struct DataRefs
{
    double flaps;
    double spoilers_pos;
    double spoilers_armed;
    double spd;
    double gear;
    double ap_master;
    double ap_hdg_lock;
    double ap_nav1_lock;
    double ap_alt_lock;
    double ap_app_lock;
    double ap_nav_selected;
    double ap_hdg;
    double ap_alt;
    double ap_vs;
    double ap_spd;
    double ap_crs1;
    double ap_crs2;
    double ap_crs3;
    double autothrottle_lock;
    double altitude;
    double verticalspeed;
    double hdg;
    double rev;
    double lightlanding;
    double parkingbrake;
    double enginerpm1;
    double enginerpm2;
    double batt_master;
    double retr_gear;
    double light_taxi;
    double light_beacon;
    double light_nav;
    double light_strobe;
    double light_panel;
    double stall_wrn;
    double overspeed_wrn;
    double inner_marker;
    double middle_marker;
    double outer_marker;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    string tailnumber;
};
//-----------FUNKCJE------------------------------
void __stdcall DirectOutput_Device_Callback(void* hDevice, bool bAdded, void* pvContext) {
    if (bAdded) {
        devices.push_back(hDevice);
    }
    else {

    }
}

void __stdcall DirectOutput_Enumerate_Callback(void* hDevice, void* pvContext) {
    devices.push_back(hDevice);
}

void XMLParsing(void){
    using namespace pugi;
    std::cout << "Loading settings:\n";
    std::ifstream xml_file("settings.xml");
    if(!xml_file){
        std::cerr << "ERROR: opening XML file: " << std::endl;
    }
    xml_document doc;
    xml_parse_result res = doc.load(xml_file);
    if(!res){
        std::cerr << "ERROR: " << res.description() << std::endl;
    }
    xml_object_range<xml_named_node_iterator> sources =
        doc.child("root").children("leds");
    xml_named_node_iterator s;

    std::string jakiPzycisk, jakiStatus, jakaLinia;
    for(s = sources.begin(); s != sources.end(); ++s)
    {
        xml_object_range<xml_named_node_iterator> btns =
            s->children("btn");
        //-----LEDS-------
        xml_named_node_iterator v;
        for(v = btns.begin(); v != btns.end(); ++v){
            jakiPzycisk = v->attribute("name").as_string();
            diody[dek[jakiPzycisk]] = v->attribute("function").as_string();
            std::cout << "-> " << jakiPzycisk << " / " << v->attribute("function").as_string() << "\n";
        }

        //----MFD-----
        xml_object_range<xml_named_node_iterator> mfdLines =
            s->children("mfd");
        for(v = mfdLines.begin(); v != mfdLines.end(); ++v){
            jakaLinia = v->attribute("name").as_string();
            mfdLine[std::stoi(jakaLinia)] = v->attribute("function").as_string();
            std::cout << "-> MFD: " << jakaLinia << " / " << v->attribute("function").as_string() << "\n";
        }
    }
}

void mfd_Print(double spd, double vs, double alt){
    wchar_t txt[14];
    swprintf_s(txt, L"SPD: %.0f kts", spd);
    int txtsize = std::wcslen (txt);
    DirectOutput_SetString(devices[0], dwPage, 0, txtsize, txt);
    swprintf_s(txt, L"V/S: %.0f f/m", vs);
    txtsize = std::wcslen (txt);
    DirectOutput_SetString(devices[0], dwPage, 1, txtsize, txt);
    swprintf_s(txt, L"ALT: %.0f ft", alt);
    txtsize = std::wcslen (txt);
    DirectOutput_SetString(devices[0], dwPage, 2, txtsize, txt);
}

void mfdPrintLines(void){
    wchar_t txt[14];
    DataRefs* pDataRefs = NULL;
    pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*)pData;
    pDataRefs = (DataRefs*)&pObjData->dwData;

    for(uint8_t i;i<3;i++){
        if(mfdLine[i] == "SPD"){
            swprintf_s(txt, L"SPD: %.0f kts", pDataRefs->spd);
        } else if(mfdLine[i] == "ALT"){
            swprintf_s(txt, L"ALT: %.0f ft", pDataRefs->altitude);
        } else if(mfdLine[i] == "V/S"){
            swprintf_s(txt, L"V/S: %.0ff/m", pDataRefs->verticalspeed);
        } else if(mfdLine[i] == "HDG"){
            swprintf_s(txt, L"HDG: %.0f", pDataRefs->hdg);
        }  else if(mfdLine[i] == "AP_HDG"){
            swprintf_s(txt, L"ApHDG: %.0f", pDataRefs->ap_hdg);
        } else if(mfdLine[i] == "AP_ALT"){
            swprintf_s(txt, L"ApALT: %.0fft", pDataRefs->ap_alt);
        } else if(mfdLine[i] == "AP_V/S"){
            swprintf_s(txt, L"ApV/S: %.0ff/m", pDataRefs->ap_vs);
        } else if(mfdLine[i] == "AP_SPD"){
            swprintf_s(txt, L"ApSPD: %.0f kts", pDataRefs->ap_spd);
        } else if(mfdLine[i] == "AP_CRS1"){
            swprintf_s(txt, L"ApCRS1: %.0f", pDataRefs->ap_crs1);
        } else if(mfdLine[i] == "AP_CRS2"){
            swprintf_s(txt, L"ApCRS2: %.0f", pDataRefs->ap_crs2);
        } else {
            swprintf_s(txt, L"");
        }
        int txtsize = std::wcslen (txt);
        DirectOutput_SetString(devices[0], dwPage, i, txtsize, txt);
    }
}

void mfdClearLines(void){
    wchar_t txt[14];
   for(uint8_t i;i<3;i++){
        swprintf_s(txt, L"");
        int txtsize = std::wcslen (txt);
        DirectOutput_SetString(devices[0], dwPage, i, txtsize, txt);
    }
}

void clear_led(void){
    DirectOutput_SetLed(devices[0], dwPage, LED_TOGGLE_1_2_RED, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_TOGGLE_1_2_GREEN, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_TOGGLE_3_4_RED, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_TOGGLE_3_4_GREEN, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_TOGGLE_5_6_GREEN, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_TOGGLE_5_6_RED, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_CLUTCH_GREEN, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_CLUTCH_RED, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE_A_GREEN, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE_A_RED, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE_B_GREEN, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE_B_RED, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE_D_GREEN, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE_D_RED, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE_E_GREEN, 0);
    DirectOutput_SetLed(devices[0], dwPage, LED_FIRE_E_RED, 0);
}

void color_led(uint8_t nr, int8_t param){
    if(nr==LED_FIRE || nr==LED_THROTTLE){
        if(param==0){ //wylaczony
            DirectOutput_SetLed(devices[0], dwPage, nr, 0); //green
        } else {
            DirectOutput_SetLed(devices[0], dwPage, nr, 1); //green
        }
    } else {
        if(param==0){ //wylaczony
            DirectOutput_SetLed(devices[0], dwPage, nr, 1);  //red
            DirectOutput_SetLed(devices[0], dwPage, nr+1, 0); //green
        } else if (param==1){ //wlaczony
            DirectOutput_SetLed(devices[0], dwPage, nr, 0);  //red
            DirectOutput_SetLed(devices[0], dwPage, nr+1, 1); //green
        } else if (param==-1){ //diody wylaczone
            DirectOutput_SetLed(devices[0], dwPage, nr, 0);  //red
            DirectOutput_SetLed(devices[0], dwPage, nr+1, 0); //green
        }else { //stan posredni
            DirectOutput_SetLed(devices[0], dwPage, nr, 1);  //red
            DirectOutput_SetLed(devices[0], dwPage, nr+1, 1); //green
        }
    }

}

void flash(uint8_t ledNR){
    for(uint8_t x;x<10;x++){
        color_led(ledNR,0);
        Sleep(80);
        color_led(ledNR,-1);
        Sleep(50);
    }
}

void colorFlash(uint8_t ledNR, uint8_t color){
    for(uint8_t x;x<10;x++){
        color_led(ledNR,color);
        Sleep(80);
        color_led(ledNR,-1);
        Sleep(50);
    }
}

void set_led(void){
    DataRefs* pDataRefs = NULL;
    pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*)pData;
    pDataRefs = (DataRefs*)&pObjData->dwData;

    if(pDataRefs->batt_master > 10){  //jesli bateria wlaczona
        uint8_t i;
        for(i=0;i<20;i++){
            if (diody[i] == "RED"){
                color_led(i,0);
            } else if (diody[i] == "GREEN"){
                color_led(i,1);
            } else if (diody[i] == "ORANGE"){
                color_led(i,2);
            } else if(diody[i] == "GEAR"){
                if(pDataRefs->gear >0 && pDataRefs->gear <= 99){  //GEAR
                    color_led(i,2);
                } else if (pDataRefs->gear == 100){
                    color_led(i,1);
                } else {
                    color_led(i,0);
                }
            } else if (diody[i] == "PARKING_BRAKE"){
                color_led(i,pDataRefs->parkingbrake); //PARKING BRAKE
            } else if (diody[i] == "RPM_ENGINE_1"){
                if(pDataRefs->enginerpm1 >500){  //ENGINE 1 RPM
                    color_led(i,1);
                } else {
                    color_led(i,0);
                }
            } else if (diody[i] == "RPM_ENGINE_2"){
                if(pDataRefs->enginerpm2 >500){  //ENGINE 2 RPM
                    color_led(i,1);
                } else {
                    color_led(i,0);
                }
            } else if (diody[i] == "FLAPS"){
                if(pDataRefs->flaps >=10 && pDataRefs->flaps < 90){ //FLAPS
                    color_led(i,2);
                } else if (pDataRefs->flaps >=90){
                    color_led(i,1);
                } else {
                    color_led(i,0);
                }
            }  else if (diody[i] == "LANDING_LIGHTS"){
                color_led(i,pDataRefs->lightlanding);
            } else if (diody[i] == "AP_MASTER"){
                color_led(i,pDataRefs->ap_master);
            } else if (diody[i] == "REV_THRUST"){
                if(pDataRefs->rev < 0){ //REVERSE THRUST
                    color_led(i,0);
                } else {
                    color_led(i,1);
                }
            } else if (diody[i] == "TAXI_LIGHTS"){
                color_led(i,pDataRefs->light_taxi);
            }  else if (diody[i] == "NAV_LIGHTS"){
                color_led(i,pDataRefs->light_nav);
            } else if (diody[i] == "BEACON_LIGHTS"){
                color_led(i,pDataRefs->light_beacon);
            } else if (diody[i] == "STROBE_LIGHTS"){
                color_led(i,pDataRefs->light_strobe);
            } else if (diody[i] == "PANEL_LIGHTS"){
                color_led(i,pDataRefs->light_panel);
            } else if (diody[i] == "LIGHTS_COMBO"){
                if(pDataRefs->light_taxi == 1 && pDataRefs->lightlanding == 1){
                    color_led(i,0);
                } else if (pDataRefs->light_taxi == 1 && pDataRefs->lightlanding == 0){
                    color_led(i,2);
                } else if (pDataRefs->light_taxi == 0 && pDataRefs->lightlanding == 1){
                    color_led(i,1);
                } else {
                    color_led(i,-1);
                }
            } else if (diody[i] == "STALL_WARNING"){
                if(pDataRefs->stall_wrn == 1){
                    thread f1(flash, i);
                    f1.join();
                } else {
                    color_led(i,-1);
                }
            } else if (diody[i] == "OVERSPEED_WARNING"){
                if(pDataRefs->overspeed_wrn == 1){
                    thread f2(flash, i);
                    f2.join();
                } else {
                    color_led(i,-1);
                }
            } else if (diody[i] == "MARKERS"){
                if(pDataRefs->inner_marker == 1){
                    colorFlash(i,0);
                } else if(pDataRefs->middle_marker == 1){
                    colorFlash(i,2);
                } else if(pDataRefs->outer_marker == 1){
                    colorFlash(i,1);
                }
            } else if (diody[i] == "INNER_MARKER"){
                if(pDataRefs->inner_marker == 1){
                    thread f3(flash, i);
                    f3.join();
                } else {
                    color_led(i,-1);
                }
            } else if (diody[i] == "MIDDLE_MARKER"){
                if(pDataRefs->middle_marker == 1){
                    thread f4(flash, i);
                    f4.join();
                } else {
                    color_led(i,-1);
                }
            } else if (diody[i] == "OUTER_MARKER"){
                if(pDataRefs->outer_marker == 1){
                    thread f5(flash, i);
                    f5.join();
                } else {
                    color_led(i,-1);
                }
            } else if (diody[i] == "SPOILERS_ARMED"){
                color_led(i,pDataRefs->spoilers_armed);
            } else if (diody[i] == "SPOILERS"){
                if(pDataRefs->spoilers_pos < 5){
                    color_led(i,0);
                } else if (pDataRefs->spoilers_pos > 95){
                    color_led(i,1);
                } else {
                    color_led(i,2);
                }
            } else if (diody[i] == "AP_HDG_LOCK"){
                color_led(i,pDataRefs->ap_hdg_lock);
            } else if (diody[i] == "AP_NAV1_LOCK"){
                color_led(i,pDataRefs->ap_nav1_lock);
            } else if (diody[i] == "AP_ALT_LOCK"){
                color_led(i,pDataRefs->ap_alt_lock);
            } else if (diody[i] == "AP_APP_LOCK"){
                color_led(i,pDataRefs->ap_app_lock);
            } else if (diody[i] == "AUTOTHROTTLE_LOCK"){
                color_led(i,pDataRefs->autothrottle_lock);
            } else if (diody[i] == "AP_COURSE_COMBO"){
                if(pDataRefs->ap_hdg_lock == 0 && pDataRefs->ap_nav1_lock == 0 && pDataRefs->ap_app_lock == 0){
                    color_led(i,-1);
                } else if (pDataRefs->ap_app_lock == 1){
                    color_led(i,2); //orange
                } else if (pDataRefs->ap_nav1_lock == 1){
                    color_led(i,1); //green
                } else if (pDataRefs->ap_hdg_lock == 1){
                    color_led(i,0); //red
                }
            }
        }
    //mfd_Print(pDataRefs->spd, pDataRefs->verticalspeed, pDataRefs->altitude);
    mfdPrintLines();
    } else {
        clear_led();
        mfdClearLines();
    }
}

void glowny(void){
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "FLAPS HANDLE PERCENT", "Percent");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "SPOILERS HANDLE POSITION", "Percent");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "SPOILERS ARMED", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AIRSPEED INDICATED", "Knots");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "GEAR POSITION", "Percent");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT MASTER", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT HEADING LOCK", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT NAV1 LOCK", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT ALTITUDE LOCK", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT APPROACH HOLD", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT NAV SELECTED", "Number");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT HEADING LOCK DIR", "Degree");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT ALTITUDE LOCK VAR", "Feet");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT VERTICAL HOLD VAR", "Feet/minute");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOPILOT AIRSPEED HOLD VAR", "Knots");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "NAV OBS:1", "Degrees");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "NAV OBS:2", "Degrees");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "NAV OBS:3", "Degrees");

    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "AUTOTHROTTLE ACTIVE", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "Indicated Altitude", "feet");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "VERTICAL SPEED", "feet per minute");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "HEADING INDICATOR", "degrees");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "GENERAL ENG THROTTLE LEVER POSITION:1", "Percent");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "LIGHT LANDING", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "BRAKE PARKING POSITION", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "GENERAL ENG RPM:1", "Rpm");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "GENERAL ENG RPM:2", "Rpm");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "ELECTRICAL MAIN BUS VOLTAGE", "Volts");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "IS GEAR RETRACTABLE", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "LIGHT TAXI", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "LIGHT BEACON", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "LIGHT NAV", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "LIGHT STROBE", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "LIGHT PANEL", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "STALL WARNING", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "OVERSPEED WARNING", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "INNER MARKER", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "MIDDLE MARKER", "Bool");
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "OUTER MARKER", "Bool");

    //
    hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "ATC FLIGHT NUMBER", "String");



    hr = SimConnect_RequestDataOnSimObject(hSimConnect, REQUEST_AP_SETTINGS, DEFINITION_ID_AP, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND);
    if (FAILED(hr)){
        printf("RequestDataOnSimObject for AutopilotData structure - error\n");
    }
    bRequestProcessed = false;

    while (!bRequestProcessed){
        hr = SimConnect_GetNextDispatch(hSimConnect, &pData, &cbData);
        if (SUCCEEDED(hr)){
            set_led();
        }
        Sleep(100);
    }
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int main() {
    printf("X52 Dynamic LED ver 2.2\n          Saitek X52 PRO plugin for Microsoft Flight Simulator\n");
    printf("Created by KoSik -> [email protected]\n\n\n");

    XMLParsing();
    printf("Settings loaded!\n\n");

    int q=0;
    printf("Connecting with MSFS...");
    while(1){
        hr = SimConnect_Open(&hSimConnect, "Client Event", NULL, NULL, NULL, NULL);
        if (SUCCEEDED(hr)) {
            const wchar_t * name = L"X52_plugin";
            DirectOutput_Initialize(name);
            DirectOutput_RegisterDeviceCallback(*DirectOutput_Device_Callback, nullptr);
            DirectOutput_Enumerate(*DirectOutput_Enumerate_Callback, nullptr);
            const wchar_t * pageDebugName = L"X52_page";
            DirectOutput_AddPage(devices[0], dwPage, pageDebugName, FLAG_SET_AS_ACTIVE);
            const wchar_t * txt = L"Saitek X52 plugin";
            int txtsize = std::wcslen (txt);
            DirectOutput_SetString(devices[0], dwPage, 0, txtsize, txt);
            txt = L"  created by";
            txtsize = std::wcslen (txt);
            DirectOutput_SetString(devices[0], dwPage, 1, txtsize, txt);
            txt = L"     KoSik";
            txtsize = std::wcslen (txt);
            DirectOutput_SetString(devices[0], dwPage, 2, txtsize, txt);
            printf("\nConnected to SimConnect!\n");
            glowny();
            break;
        } else {
            hr = SimConnect_Close(hSimConnect);
            Sleep(5000);
            q++;
            printf(".");
        }
        if(q>60){
            printf("\nFailed to Connect with SimConnect\n");
            break;
        }
    }
    // Close
    hr = SimConnect_Close(hSimConnect);
    return 0;
}

0

_13th_Dragon dzięki serdeczne ale niestety niewiele z tego rozumiem. Będę musiał poszukać innego rozwiązania albo kogoś kto mi to wytłumaczy

0

Czyli wracamy do:

MarekR22 napisał(a):

Ja dodam: jak na kogoś kto twierdzi, że jest początkujący, to zabrałeś się za zbyt skomplikowany problem (mieszanie języków programowania, jakaś dziwna biblioteka). Zapewne to jest główny przyczynek, który utrudnia ci zadania na tyle dobrego pytania, żeby koś z forum mógł ci pomóc.

0

Ehhhh... Tak. Masz rację. Poprosiłem już moderatora o skasowanie wątku. Na szczęście na forach zagranicznych mają na tyle niski poziom, że rozumieją moje pytania i dla nich nie jestem za głupi żeby zadać pytanie.
Wrócę tutaj jak się doszkolę. Wróć! Nie wrócę, bo po co jak już wszystko będę wiedział!

0
Marcin Kosela napisał(a):

Wrócę tutaj jak się doszkolę. Wróć! Nie wrócę, bo po co jak już wszystko będę wiedział!

Po jakim czasie będziesz nastąpi to: - "wszystko będę wiedział"?
Zapewniam że nawet po 30 łatach nadał nie będziesz wiedział wszystkiego.

3

Generalnie masz problem ze zrozumieniem dokumentacji do biblioteki której używasz (albo nawet w ogóle jej nie czytałeś i używasz biblioteki na ślepo).

Po nazwie funkcji SimConnect_AddToDataDefinition doszedłem, że jest to biblioteka prepar3d (a właściwie to cała platforma symulacyjna). Jak rozumiem ty piszesz aplikację klienta, wysyłasz dane do biblioteki, dane są wysyłane do serwera, serwer przetwarza symulację i wysyła dane do klienta. W tej sytuacji podajesz do symulacji parametry i żądasz żeby serwer wysłał ci odpowiedź w odpowiednim układzie pamięci.

Jeśli wejdziesz tutaj: https://www.prepar3d.com/SDKv4/sdk/simconnect_api/references/general_functions.html#SimConnect_AddToDataDefinition
zobaczysz deklarację funkcji SimConnect_AddToDataDefinition, przyjmuje ona kilka parametrów:

HRESULT SimConnect_AddToDataDefinition(
  HANDLE  hSimConnect,
  SIMCONNECT_DATA_DEFINITION_ID  DefineID,
  const char*  DatumName,
  const char*  UnitsName,
  SIMCONNECT_DATATYPE  DatumType = SIMCONNECT_DATATYPE_FLOAT64,
  float  fEpsilon = 0,
  DWORD  DatumID = SIMCONNECT_UNUSED
);

Najbardziej interesujące z tego to jest DatumName, UnitsName. Musisz odpowiednio podać te parametry. One są dobrze opisane tutaj: http://www.prepar3d.com/SDK/Core%20Utilities%20Kit/Variables/Simulation%20Variables.html

Na przykład:

Simulation Variable Description Units Settable Multiplayer
OUTER MARKER Outer marker state Bool Y -
ATC FLIGHT NUMBER Flight Number used by ATC String (6) Y -

Dodatkowo jest parametr DatumType, którym określasz jakiego rodzaju danych spodziewasz się z serwera. Tutaj więcej na ten temat: https://www.prepar3d.com/SDKv4/sdk/simconnect_api/references/structures_and_enumerations.html#SIMCONNECT_DATATYPE

Najważniejsze z tego jest to, że jeśli tak wywołujesz funkcję:

hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "OUTER MARKER", "Bool");

to DatumType to jest domyślnie SIMCONNECT_DATATYPE_FLOAT64 (czyli double). I jeśli jest to pierwsze wywołanie tej funkcji dla konkretnego DefineID to w obiekcie który ci przyjdzie z serwera pierwszą zmienną w pamięci będzie double który właśnie okresla Outer marker.

I nawet jeśli jednostka Outer marker to jest Bool to nie ma typu bool w SDK. Możesz albo tutaj się spodziewać double albo próbować ustawić SIMCONNECT_DATATYPE_INT32 i w strukturze użyć uint32_t. Jeśli jednostka to String(6), to powinieneś spodziewać się Stringa o maksymalnie wielkości 6.
Jednym z typów które możesz podać jako DatumType jest SIMCONNECT_DATATYPE_STRING8.
Dodatkowo dokumentacja tutaj: https://www.prepar3d.com/SDKv4/sdk/references/variables/simulation_variables.html podaje, że:

Simulation variables are referenced from within SimConnect clients with the SimConnect_AddToDataDefinition call (see the SimConnect document for full details). When the units are listed as a structure or > as a string, enter the empty string, or simply NULL, in the units parameter of this function call.

For example:

hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "Kohlsman setting hg", "inHg");
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "Indicated Altitude", "feet");
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "Plane Latitude", "degrees");
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "Plane Longitude", "degrees");
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_2, "Category", NULL);              \\ string
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_2, "AI Waypoint List", NULL);      \\ structure
Unless the Units column in the following table identifies the units as a structure or a string, the data will be returned by default in a signed 64 bit floating point value. The SimConnect_AddToDataDefinition 
has an optional parameter to change this to a signed 32 or 64 bit integer, or a signed 32 bit floating point value.

Więc podejrzewam (nie jestem na 100% pewny), że jeśli wywołasz trzy takie funkcje (tylko je, w podanej kolejności):

    hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_ID_AP, "OUTER MARKER", "Bool" );
    hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_ID_AP, "ATC FLIGHT NUMBER",  nullptr, SIMCONNECT_DATATYPE_STRING8 );
    hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_ID_AP, "MIDDLE MARKER", "Bool" );

to struktura, która przychodzi z serwera wygląda tak:

struct Data
{
    double outer_marker;
    char atc_flight_number[ 8 ]; // SIMCONNECT_DATATYPE_STRING8, powinno wystarczyć dla ATC FLIGHT NUMBER
    double middle_marker;
};

Jest jeszcze SIMCONNECT_DATATYPE_STRINGV co oznacza variable length narrow string. Ale wtedy dane nie będą w strukturze. Zamiast tego musisz je odczytać za pomocą funkcji SimConnect_RetrieveString. Ale ludzie z forum mówią, że ta funkcja i tak nie działa (https://www.fsdeveloper.com/forum/threads/reading-an-aircraft-string-using-execute_calculator_code-issue.450361/)
Zamiast tego zawsze możesz użyć stringa ze stałym rozmiarem.

Zresztą, tutaj masz przykład ze stringiem title: https://www.prepar3d.com/SDKv4/sdk/simconnect_api/samples/request_data.html co by potwierdzało to co napisałem wyżej.

0

mwl4 serdecznie dziękuję za zainteresowanie i chęć pomocy.

Dobrze zrozumiałeś z tym, że ja piszę dla msfs nie p3d. Dla msfs, simconnect jest nieco zmodyfikowany ale nie różni się zbytnio.
Dokumentację biblioteki przestudiowałem i wiem jak działa. Tak jak wcześniej już napisałem, program działa bez zarzutu, odczytuje i zapisuje wszystkie zmienne liczbowe. Mam problem z wyprowadzeniem tylko tej jednej zmiennej typu string.
Wczoraj wieczorem odnalazłem informację właśnie na fsdeveloper, że funkcja SimConnect_RetrieveString nie działa w MSFS. Myślałem, że to problem ze zmienną - w sensie nie rozumiem co ktoś miał na myśli pisząc "Variable length string". Utwierdziłeś mnie więc w przekonaniu, że definiując dużą stałą tablicę powinno zadziałać (i używając oczywiście funkcji SimConnect_RetrieveString). Pozostaje znaleźć jakieś rozwiązanie, bo są programy które jakoś te parametry odczytują ale to już nie jest temat na to forum.

Jeszcze raz wielkie dzięki za włożoną pracę i zniżenie się do mojego poziomu mwl4.

Kolegów z góry też pozdrawiam (i proponuję przyjrzeć się jak powinno działać forum i, że jak się chce to da się pomóc, a nie tylko patrzeć z góry i tłumaczyć innym jak bardzo niski poziom reprezentują).

1

Źle zrozumiałeś. Variable length string to string zmiennej długości. To nie jest coś w rodzaju char data[ 256 ].
Generalnie:
SIMCONNECT_DATATYPE_STRING8 => char data[ 8 ]
SIMCONNECT_DATATYPE_STRING32 => char data[ 32 ]
SIMCONNECT_DATATYPE_STRING64 => char data[ 64 ]
SIMCONNECT_DATATYPE_STRING128 => char data[ 128 ]
SIMCONNECT_DATATYPE_STRING256 => char data[ 256 ]
SIMCONNECT_DATATYPE_STRING260 => char data[ 260 ]

Jeśli chcesz użyć SIMCONNECT_DATATYPE_STRINGV to wielkość stringa w strukturze jest dynamiczna i żeby wydobyć znaki i wielkość stringa musisz użyć SimConnect_RetrieveString. Tutaj https://www.prepar3d.com/SDKv4/sdk/simconnect_api/samples/variable_strings.html masz przykład jak użyć SimConnect_RetrieveString i SIMCONNECT_DATATYPE_STRINGV.

Jeśli SimConnect_RetrieveString nie działa bo jest źle zaimplementowane po stronie serwera to możesz użyć fixed length string:

struct Data
{
  char atc_flight_number[ 256 ];
};

//....
    hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_ID_AP, "ATC FLIGHT NUMBER",  nullptr, SIMCONNECT_DATATYPE_STRING256 );

Jeśli spodziewasz się stringa dłuższego niż 255 znaków (1 znak jest przeznaczony na null terminator) i SimConnect_RetrieveString nie działa to SDK nie przewiduje innego sposobu pobrania danych (czyt. nie da się).
Natomiast ja bym się upewnił, że to na pewno nie działa.

0

Rozumiem, że Variable length string to nie tablica statyczna ale sam podsunąłeś, że tak powinno działać. Oczywiście będzie problem w przypadku przepełnienia ale powinno działać.

W aktualnej dokumentacji simconnect jest informacja: String/ SimConnect_RetrieveString/ Bad response/ Returns empty strings (either a data or server problem) więc nie spodziewam się już wiele.

Sprawdziłem ten kod który mi podesłałeś i zwraca niestety tylko:
screenshot-20210204111202.png

0

Jeśli otrzymujesz jakiś błąd to najlepiej pokaż cały swój aktualny kod. Wtedy jestem w stanie jakoś pomóc.

0

Napisałem: Zamiast tego zawsze możesz użyć stringa ze stałym rozmiarem. Oczywiście jednocześnie miałem na myśli użycie np. SIMCONNECT_DATATYPE_STRING256. — mwl4

Również próbowałem

To ten kod który mi podesłałeś: https://www.prepar3d.com/SDKv4/sdk/simconnect_api/samples/variable_strings.html

Poprawiłem tylko aby było zgodnie z nową wersją:

hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "TITLE", "Variable length string");    // wide string
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC AIRLINE", "String64");
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC TYPE", "String64");

i usunałem linię (zakomentowana), bo nie ma takiej funkcji. Próbowałem też usunąć całkiem zmienną title ze względu na to, że ta funkcja nie istnieje.

if (//SUCCEEDED(SimConnect_RetrieveStringW(pData, cbData, &pS->strings, &pszTitle, &cbTitle)) &&
SUCCEEDED(SimConnect_RetrieveString(pData, cbData, reinterpret_cast<BYTE*>(pszTitle) + cbTitle, &pszAirline, &cbAirline)) &&
SUCCEEDED(SimConnect_RetrieveString(pData, cbData, reinterpret_cast<BYTE*>(pszAirline) + cbAirline, &pszType, &cbType)))

I jeszcze referencja dla nowej wersji:

SimConnect_RetrieveString
The SimConnect_RetrieveString function is used to assist in retrieving variable length strings from a structure.

Syntax
HRESULT SimConnect_RetrieveString(
        SimConnect_RECV*  pData,
        DWORD  cbData,
        void*  pStringV,
        char**  ppszString,
        DWORD*  pcbString
      );
Parameters
pData
  [in]  Pointer to a SimConnect_RECV structure, containing the data.
cbData
  [in]  The size of the structure that inherits the SimConnect_RECV structure, in bytes.
pStringV
  [in]  Pointer to a the start of the variable length string within the structure.
ppszString
  [in, out]  Specifies a pointer to a pointer to a character buffer that should be large enough to contain the maximum length of string that might be returned. On return this buffer should contain the retrieved string.
pcbString
  [in, out]  Pointer to a DWORD. On return this contains the length of the string in bytes.

Return Values
The function returns an HRESULT. Possible values include, but are not limited to, those in the following table.

Return value	Description
S_OK	The function succeeded.
E_FAIL	The function failed.
Example
struct StructVS {
        char title[1];
      }
      StructVS *pS = (StructVS*)&pObjData->dwData;
      char *pszTitle;
      DWORD cbTitle;
      hr = SimConnect_RetrieveString(pData, cbData, &pS->strings, &pszTitle, &cbTitle)))
Remarks
This function does not communicate with the SimConnect server, but is a helper function to assist in the handling of variable length strings. Its counterpart is the SimConnect_InsertString function. Note that this function works in the case where an empty string is in the structure returned by the server.
0

Tak jak już pisałem wcześniej nowa wersja różni się nieco o tej do xplane i p3d. Dokumentacje wrzuciłem tutaj . Zobacz plik SimConnect_Status_of_Simulation_Variables.html

Aktualny kod:

extern "C" {
#include "Include/DirectOutput.h"
#include "Include/SimConnect.h"
#include "Include/leds.h"
}
//Copyright (c) Lockheed Martin Corporation.  All rights reserved.
//------------------------------------------------------------------------------
//
//  SimConnect Variable String Sample
//
//    Description:
//                Shows how to extract three variable length strings from a
//                structure
//------------------------------------------------------------------------------

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

enum EVENT_ID {
    EVENT_SIM_START,
};

enum DATA_DEFINE_ID {
    DEFINITION_1
};

enum DATA_REQUEST_ID {
    REQUEST_1
};

struct StructVS
{
    BYTE    strings[1];   // variable-length strings
};

int        quit            = 0;
HANDLE    hSimConnect        = NULL;

void CALLBACK MyDispatchProcVS(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
{
    switch(pData->dwID)
    {
        case SIMCONNECT_RECV_ID_EVENT:
        {
            SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData;
            switch(evt->uEventID)
            {
                case EVENT_SIM_START:

                    // Send this request to get the user aircraft id
                    HRESULT hr = SimConnect_RequestDataOnSimObjectType(hSimConnect, REQUEST_1, DEFINITION_1, 0, SIMCONNECT_SIMOBJECT_TYPE_USER);
                    break;
            }
            break;
        }

        case SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE:
        {
            SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE*)pData;

            switch(pObjData->dwRequestID)
            {
                case REQUEST_1:
                {
                    StructVS *pS = (StructVS*)&pObjData->dwData;
                    //wchar_t*    pszTitle;       // wide string
                    char*       pszAirline;
                    char*       pszType;
                    DWORD       cbTitle;
                    DWORD       cbAirline;
                    DWORD       cbType;

                    // Note how the third parameter is moved along the data received.
                    // Reinterpret cast used to ensure pointer arithmatic is correct when using wide strings.
                    if (//SUCCEEDED(SimConnect_RetrieveString(pData, cbData, &pS->strings, &pszTitle, &cbTitle)) &&
                        SUCCEEDED(SimConnect_RetrieveString(pData, cbData, &pS->strings, &pszAirline, &cbAirline)) &&
                        SUCCEEDED(SimConnect_RetrieveString(pData, cbData, reinterpret_cast<BYTE*>(pszType) + cbType, &pszType, &cbType)))
                    {
                        // Note: Using %S string formatter rather than %s for the wide string title.
                        printf("\nTitle = \"\" \nAirline = \"%s\" \nType = \"%s\"", pszAirline, pszType);
                    }
                    else
                    {
                        printf("\nCouldn't retrive the strings.");
                    }
                    break;
                }
            }
            break;
        }

        case SIMCONNECT_RECV_ID_QUIT:
        {
            quit = 1;
            break;
        }

        case SIMCONNECT_RECV_ID_EXCEPTION:
        {
            SIMCONNECT_RECV_EXCEPTION *except = (SIMCONNECT_RECV_EXCEPTION*)pData;
            printf("\n\n***** EXCEPTION=%d  SendID=%d  Index=%d  cbData=%d\n", except->dwException, except->dwSendID, except->dwIndex, cbData);
            break;
        }

        default:
            printf("\nUNKNOWN DATA RECEIVED: pData=%p cbData=%d\n", pData, cbData);
            break;
    }
}

bool testVariableStrings()
{
    HANDLE hEventHandle = ::CreateEvent(NULL, FALSE, FALSE, NULL);

    if(hEventHandle == NULL)
    {
        printf("Error: Event creation failed!");
        return false;
    }

    HRESULT hr;

    if (SUCCEEDED(SimConnect_Open(&hSimConnect, "Variable Strings", NULL, 0, hEventHandle, 0)))
    {
        printf("\nConnected to Prepar3D!");

        // Set up a data definition contained a number of variable length strings
        //hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "TITLE",             "Variable length string");    // wide string
        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC AIRLINE",       "String64");
        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC TYPE",          "String64");

        // Request a simulation start event
        hr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SIM_START, "SimStart");

        while( 0 == quit && ::WaitForSingleObject(hEventHandle, INFINITE) == WAIT_OBJECT_0)
        {
            SimConnect_CallDispatch(hSimConnect, MyDispatchProcVS, NULL);
        }

        CloseHandle(hEventHandle);
        hr = SimConnect_Close(hSimConnect);
        return true;
    }
    return false;
}

int __cdecl _tmain(int argc, char* argv[])
{
    bool ok = testVariableStrings();
    return 0;
}
1

Ok. Z podanej przez Ciebie dokumentacji:

The result of SimVar operations depend on the correct usage of unit and type. Please refer to this list for the correct unit name and associated type.

unit name unit type
String64 SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64
Variable length string SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRINGV

Jeśli ty robisz tylko:

        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC AIRLINE",       "String64");
        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC TYPE",          "String64");

to jest to za mało, bo domyślnie SIMCONNECT_DATATYPE DatumType = SIMCONNECT_DATATYPE_FLOAT64.
I przede wszystkim, jeśli używasz String64 to w strukturze powinieneś mieć char data[ 64 ] i nie powinieneś używać SimConnect_RetrieveString (to jest tylko dla SIMCONNECT_DATATYPE_STRINGV).

Ja bym spróbował tak:

struct Data
{
    char atc_airline[ 64 ];
    char atc_type[ 64 ];
};
// .....
            SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE*)pData;

            switch(pObjData->dwRequestID)
            {
                case REQUEST_1:
                {
                    Data *pS = (Data*)&pObjData->dwData;
                    printf("\nAirline = \"%s\" \nType = \"%s\"", pS->atc_airline, pS->atc_type);
                    break;
                }

// ....
        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC AIRLINE", "String64", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );
        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC TYPE", "String64", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );

Ewentualnie jeśli to nie zadziała to próbowałbym jeszcze tak:

        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC AIRLINE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );
        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC TYPE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );

Cały kod:

extern "C" {
#include "Include/DirectOutput.h"
#include "Include/SimConnect.h"
#include "Include/leds.h"
}
//Copyright (c) Lockheed Martin Corporation.  All rights reserved.
//------------------------------------------------------------------------------
//
//  SimConnect Variable String Sample
//
//    Description:
//                Shows how to extract three variable length strings from a
//                structure
//------------------------------------------------------------------------------

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

enum EVENT_ID {
    EVENT_SIM_START,
};

enum DATA_DEFINE_ID {
    DEFINITION_1
};

enum DATA_REQUEST_ID {
    REQUEST_1
};

struct Data
{
    char atc_airline[ 64 ];
    char atc_type[ 64 ];
};

int        quit            = 0;
HANDLE    hSimConnect        = NULL;

void CALLBACK MyDispatchProcVS(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
{
    switch(pData->dwID)
    {
        case SIMCONNECT_RECV_ID_EVENT:
        {
            SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData;
            switch(evt->uEventID)
            {
                case EVENT_SIM_START:

                    // Send this request to get the user aircraft id
                    HRESULT hr = SimConnect_RequestDataOnSimObjectType(hSimConnect, REQUEST_1, DEFINITION_1, 0, SIMCONNECT_SIMOBJECT_TYPE_USER);
                    break;
            }
            break;
        }

        case SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE:
        {
            SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE*)pData;

            switch(pObjData->dwRequestID)
            {
                case REQUEST_1:
                {
                    Data *pS = (Data*)&pObjData->dwData;
                    printf("\nAirline = \"%s\" \nType = \"%s\"", pS->atc_airline, pS->atc_type);
                    break;
                }
            }
            break;
        }

        case SIMCONNECT_RECV_ID_QUIT:
        {
            quit = 1;
            break;
        }

        case SIMCONNECT_RECV_ID_EXCEPTION:
        {
            SIMCONNECT_RECV_EXCEPTION *except = (SIMCONNECT_RECV_EXCEPTION*)pData;
            printf("\n\n***** EXCEPTION=%d  SendID=%d  Index=%d  cbData=%d\n", except->dwException, except->dwSendID, except->dwIndex, cbData);
            break;
        }

        default:
            printf("\nUNKNOWN DATA RECEIVED: pData=%p cbData=%d\n", pData, cbData);
            break;
    }
}

bool testVariableStrings()
{
    HANDLE hEventHandle = ::CreateEvent(NULL, FALSE, FALSE, NULL);

    if(hEventHandle == NULL)
    {
        printf("Error: Event creation failed!");
        return false;
    }

    HRESULT hr;

    if (SUCCEEDED(SimConnect_Open(&hSimConnect, "Variable Strings", NULL, 0, hEventHandle, 0)))
    {
        printf("\nConnected to Prepar3D!");

        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC AIRLINE", "String64", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );
        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC TYPE", "String64", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64);

        // Request a simulation start event
        hr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SIM_START, "SimStart");

        while( 0 == quit && ::WaitForSingleObject(hEventHandle, INFINITE) == WAIT_OBJECT_0)
        {
            SimConnect_CallDispatch(hSimConnect, MyDispatchProcVS, NULL);
        }

        CloseHandle(hEventHandle);
        hr = SimConnect_Close(hSimConnect);
        return true;
    }
    return false;
}

int __cdecl _tmain(int argc, char* argv[])
{
    bool ok = testVariableStrings();
    return 0;
}
0

Teraz rozumiem. Czyli "String64" to jest typ wartości jaką chcę pobrać czyli dla obrotów->RPM, temperatury->celcius ale wszystkie wartości zwracane to double. Widać nie do końca to rozumiałem.

Poprawię post żeby nie pisać jednego pod drugim.

Zadziałało w momencie gdy zamknąłem MSFS, wtedy zwrócił te wartości. Nie wiem dlaczego tak się stało i nie analizowałem tego.

To rozwiązanie które mi podesłałeś działa:

hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC AIRLINE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_1, "ATC TYPE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );

Sprawdziłem jeszcze uruchamiając ten kod w moim programie. Wszystko działa jak należy.

Pozostaje jeszcze tylko to nieszczęsne TITLE z variable string ale i tak już bardzo dużo mi pomogłeś więc nie śmiem prosić o więcej.

Wielkie dzięki za poświęcony czas

1

Dla title: jeśli SimConnect_RetrieveString razem z SIMCONNECT_DATATYPE_STRINGV nie działa (zwraca jakiś error), to ja bym spróbował to wczytać do fixed length string'a:

struct Data
{
    char title[ 256 ];
};

// ...
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "TITLE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING256 );

Ale spróbowałbym najpierw czy na pewno SIMCONNECT_DATATYPE_STRINGV nie działa. Żeby to sprawdzić i się upewnić, że to działa dobrze potrzebujesz takiego kodu (nie jest ci potrzebna struktura, nawet nie możesz jej mieć bo z góry znany jest jej rozmiar).

// ....
            SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE*)pData;

            switch(pObjData->dwRequestID)
            {
                case REQUEST_1:
                {
                    char *data = reinterpret_cast< char * >( &pObjData->dwData );

                    double plane_pitch_degrees = *reinterpret_cast< double * >( data );
                    data += sizeof( double );

                    char *title = nullptr;
                    DWORD title_length = 0;
                    SimConnect_RetrieveString( pData, cbData, data, &title, &title_length ); // TODO: sprawdź result
                    data = reinterpret_cast< char * >( title ) + title_length;

                    double plane_altitude = *reinterpret_cast< double * >( data );
                    data += sizeof( double );

                    int32_t unlimited_fuel = *reinterpret_cast< int32_t * >( data );
                    data += sizeof( int32_t );

                    printf( "plane_pitch_degrees = %f, title = %s, plane_altitude = %f, unlimited_fuel = %u", plane_pitch_degrees, title, plane_altitude, unlimited_fuel );

// ....
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "PLANE PITCH DEGREES", "Radians", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_FLOAT64 );
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "TITLE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRINGV );
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "PLANE ALTITUDE", "Feet", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_FLOAT64 );
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "UNLIMITED FUEL", "Bool", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_INT32 );
0

WOW! Działa!

struct DataRefs
{
    char  airline[64];
    char  atc_type[64];
    char title[ 256 ];
};
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "ATC AIRLINE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "ATC TYPE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );
hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_ID_AP, "TITLE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING256 );
DataRefs* pDataRefs = NULL;
pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*)pData;
pDataRefs = (DataRefs*)&pObjData->dwData;

printf("airline: %s  / atc: %s / title: %s\n", pDataRefs->airline, pDataRefs->atc_type,pDataRefs->title);

Nie wiem jak dziękować :D

0

Wariant bez struktury wyrzuca błąd:

char *data = &pObjData->dwData;  //błąd

main.cpp|66|error: cannot convert 'DWORD*' {aka 'long unsigned int*'} to 'char*' in initialization|

i nie wiem czemu, bo int32_t to standardowy typ:

int32_t unlimited_fuel = *reinterpret_cast< int32_t * >( data );

main.cpp|79|error: 'int32_t' was not declared in this scope

Jako double powinno zadziałać (oczywiście po zmianie typu na default)

1

Ah, ok. Trzeba zrobić tak:

char *data = reinterpret_cast< char * >( &pObjData->dwData );

a co do int32_t to dodaj na sam początek:

#include <cstdint>
0

Dane niech będą dowodem ;:

Connected to Prepar3D!
UNKNOWN DATA RECEIVED: pData=0000000000769cb0 cbData=308
plane_pitch_degrees = 0.019273, title = TBM 930 Asobo, plane_altitude = 331.444812, unlimited_fuel = 0
plane_pitch_degrees = 0.019273, title = TBM 930 Asobo, plane_altitude = 331.444812, unlimited_fuel = 0
plane_pitch_degrees = 0.019273, title = TBM 930 Asobo, plane_altitude = 331.444812, unlimited_fuel = 0

Działa jak należy. Dodałem do kodu tylko wywołanie funkcji SimConnect_RequestDataOnSimObject żeby zwracał dane

Cały, działający kod:

extern "C" {
#include "Include/DirectOutput.h"
#include "Include/SimConnect.h"
#include "Include/leds.h"
#include <cstdint>
}
//Copyright (c) Lockheed Martin Corporation.  All rights reserved.
//------------------------------------------------------------------------------
//
//  SimConnect Variable String Sample
//
//    Description:
//                Shows how to extract three variable length strings from a
//                structure
//------------------------------------------------------------------------------

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

enum EVENT_ID {
    EVENT_SIM_START,
};

enum DATA_DEFINE_ID {
    DEFINITION_1
};

enum DATA_REQUEST_ID {
    REQUEST_1
};

struct StructVS
{
    BYTE    strings[1];   // variable-length strings
};

int        quit            = 0;
HANDLE    hSimConnect        = NULL;

void CALLBACK MyDispatchProcVS(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
{
    switch(pData->dwID)
    {
        case SIMCONNECT_RECV_ID_EVENT:
        {
            SIMCONNECT_RECV_EVENT *evt = (SIMCONNECT_RECV_EVENT*)pData;
            switch(evt->uEventID)
            {
                case EVENT_SIM_START:

                    // Send this request to get the user aircraft id
                    HRESULT hr = SimConnect_RequestDataOnSimObjectType(hSimConnect, REQUEST_1, DEFINITION_1, 0, SIMCONNECT_SIMOBJECT_TYPE_USER);
                    break;
            }
            break;
        }

        case SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE:
        {
            SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE*)pData;

            switch(pObjData->dwRequestID)
            {
                case REQUEST_1:
                {
                    char *data = reinterpret_cast< char * >( &pObjData->dwData );

                    double plane_pitch_degrees = *reinterpret_cast< double * >( data );
                    data += sizeof( double );

                    char *title = nullptr;
                    DWORD title_length = 0;
                    SimConnect_RetrieveString( pData, cbData, data, &title, &title_length ); // TODO: sprawdź result
                    data = reinterpret_cast< char * >( title ) + title_length;

                    double plane_altitude = *reinterpret_cast< double * >( data );
                    data += sizeof( double );

                    int32_t unlimited_fuel = *reinterpret_cast< int32_t * >( data );
                    data += sizeof( int32_t );

                    printf( "plane_pitch_degrees = %f, title = %s, plane_altitude = %f, unlimited_fuel = %u\n", plane_pitch_degrees, title, plane_altitude, unlimited_fuel );

                }
            }
            break;
        }

        case SIMCONNECT_RECV_ID_QUIT:
        {
            quit = 1;
            break;
        }

        case SIMCONNECT_RECV_ID_EXCEPTION:
        {
            SIMCONNECT_RECV_EXCEPTION *except = (SIMCONNECT_RECV_EXCEPTION*)pData;
            printf("\n\n***** EXCEPTION=%d  SendID=%d  Index=%d  cbData=%d\n", except->dwException, except->dwSendID, except->dwIndex, cbData);
            break;
        }

        default:
            printf("\nUNKNOWN DATA RECEIVED: pData=%p cbData=%d\n", pData, cbData);
            break;
    }
}

bool testVariableStrings()
{
    HANDLE hEventHandle = ::CreateEvent(NULL, FALSE, FALSE, NULL);

    if(hEventHandle == NULL)
    {
        printf("Error: Event creation failed!");
        return false;
    }

    HRESULT hr;

    if (SUCCEEDED(SimConnect_Open(&hSimConnect, "Variable Strings", NULL, 0, hEventHandle, 0)))
    {
        printf("\nConnected to Prepar3D!");

        hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "PLANE PITCH DEGREES", "Radians", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_FLOAT64 );
        hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "TITLE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRINGV );
        hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "PLANE ALTITUDE", "Feet", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_FLOAT64 );
        hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "UNLIMITED FUEL", "Bool", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_INT32 );

        // Request a simulation start event
        hr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SIM_START, "SimStart");

        hr = SimConnect_RequestDataOnSimObjectType(hSimConnect, REQUEST_1, DEFINITION_1, 0, SIMCONNECT_SIMOBJECT_TYPE_USER);

        while( 0 == quit && ::WaitForSingleObject(hEventHandle, INFINITE) == WAIT_OBJECT_0)
        {
            SimConnect_CallDispatch(hSimConnect, MyDispatchProcVS, NULL);
            hr = SimConnect_RequestDataOnSimObjectType(hSimConnect, REQUEST_1, DEFINITION_1, 0, SIMCONNECT_SIMOBJECT_TYPE_USER);
            Sleep(500);

        }

        CloseHandle(hEventHandle);
        hr = SimConnect_Close(hSimConnect);
        return true;
    }
    return false;
}

int __cdecl _tmain(int argc, char* argv[])
{
    bool ok = testVariableStrings();
    return 0;
}
0

Dobre masz oko ;)

Poprawiłem zanim odpowiedziałeś żeby spróbować czy ruszy i zapomniałem przywrócić. Teraz już wszystko poprawione

Jeszcze raz wielkie dzięki

1

Jeszcze tak tylko na koniec: żeby uprościć to czytanie danych możesz sobie zrobić klasę:

class DataStream
{
public:
    DataStream( SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *object, DWORD objectSize );

    double      ReadFloat64();
    float       ReadFloat32();
    int32_t     ReadInt32();
    const char *ReadStringV( uint32_t *outLength = nullptr );
    const char *ReadString8();
    const char *ReadString32();
    const char *ReadString64();
    const char *ReadString128();
    const char *ReadString256();
    const char *ReadString260();

private:
    const char *ReadStringFixed( uint32_t capacity );

private:
    SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *m_object = nullptr;
    DWORD m_objectSize = 0;

    const char *m_data = nullptr;
};

DataStream::DataStream( SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *object, DWORD objectSize )
    : m_object( object )
    , m_objectSize( objectSize )
    , m_data( reinterpret_cast< char * >( &object->dwData ) )
{
}

double DataStream::ReadFloat64()
{
    double result = *reinterpret_cast< const double * >( m_data );
    m_data += sizeof( double );
    return result;
}

float DataStream::ReadFloat32()
{
    float result = *reinterpret_cast< const float * >( m_data );
    m_data += sizeof( float );
    return result;
}

int32_t DataStream::ReadInt32()
{
    int32_t result = *reinterpret_cast< const int32_t * >( m_data );
    m_data += sizeof( int32_t );
    return result;
}

const char *DataStream::ReadStringV( uint32_t *outLength )
{
    char *result = nullptr;
    DWORD resultLength = 0;
    SimConnect_RetrieveString( m_object, m_objectSize, const_cast< char * >( m_data ), &result, &resultLength );
    m_data = reinterpret_cast< char * >( result ) + resultLength;
    if( outLength ) *outLength = resultLength;
    return result;
}

const char *DataStream::ReadString8() { return ReadStringFixed( 8 ); }
const char *DataStream::ReadString32() { return ReadStringFixed( 32 ); }
const char *DataStream::ReadString64() { return ReadStringFixed( 64 ); }
const char *DataStream::ReadString128() { return ReadStringFixed( 128 ); }
const char *DataStream::ReadString256() { return ReadStringFixed( 256 ); }
const char *DataStream::ReadString260() { return ReadStringFixed( 260 ); }

const char *DataStream::ReadStringFixed( uint32_t capacity )
{
    const char *result = m_data;
    m_data += capacity;
    return result;
}


/////////////////

            SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE*)pData;

            switch(pObjData->dwRequestID)
            {
                case REQUEST_1:
                {
                    DataStream ds( pObjData, cbData );
                    double planePitchDegrees = ds.ReadFloat64();
                    const char *title = ds.ReadStringV();
                    double planeAltitude = ds.ReadFloat64();
                    int32_t unlimitedFuel = ds.ReadInt32();
                    const char *atcAirline = ds.ReadString64();
                    const char *atcType = ds.ReadString64();

                    printf( "planePitchDegrees = %f, title = %s, planeAltitude = %f, unlimitedFuel = %u, atcAirline = %s, atcType = %s", 
                            planePitchDegrees, title, planeAltitude, unlimitedFuel, atcAirline, atcType );



/////////////////

hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "PLANE PITCH DEGREES", "Radians", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_FLOAT64 );
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "TITLE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRINGV );
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "PLANE ALTITUDE", "Feet", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_FLOAT64 );
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "UNLIMITED FUEL", "Bool", SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_INT32 );
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "ATC AIRLINE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );
hr = SimConnect_AddToDataDefinition( hSimConnect, DEFINITION_1, "ATC TYPE", nullptr, SIMCONNECT_DATATYPE::SIMCONNECT_DATATYPE_STRING64 );

Chociaż i to nawet nie wszystko. Teoretycznie możesz zbudować refleksję do klasy, którą generycznie możesz wpisać za pomocą SimConnect_AddToDataDefinition do definicji. A później taką klasę generycznie odczytać. Ale to już są trudniejsze rzeczy i pokazywać nie będę.

0

To teraz mam zajęcie na kolejne 3 miesiące żeby ogarnąć co tu się wydarzyło ;P Kawał dobrej roboty. Myślę, że nie jednemu się przyda

1 użytkowników online, w tym zalogowanych: 0, gości: 1