1. #1
    OK, I know, I'm a geek, and I can't resist a challenge like this.

    This is probably the most minimalistic DeviceLink program possible, but it has the basics from which you can build something.

    The program is written to run under Linux (probably any *nix like OS will do, and probably most others as well, as long as they use the posix networking APIs.)

    The machine running IL-2 is hardcoded to network address 192.168.1.3. Change that as required.

    Before running it, you must enable DeviceLink in IL-2 by adding the below to your conf.ini:

    <pre class="ip-ubbcode-code-pre">
    [DeviceLink]
    IPS=<IP-addr of machine running sample prog>
    PORT=10000
    </pre>

    A sample run is shown below:
    <pre class="ip-ubbcode-code-pre">
    bash-2.05b$ ./a.out
    R/2/22/
    response is [26]"A/2\1.00/22\Il-2_1941_Late"
    R/40/30/
    response is [18]"A/40\1.100/30\0.36"
    R/80/
    response is [10]"A/80\-1.00"
    </pre>

    OK, it's nothing fancy, but the communication is there.

    The program (with all its bugs and shortcomings, for example it erroneously expects a response from all commands, so if you enter a command without response, it will hang):
    <pre class="ip-ubbcode-code-pre">
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>
    #include <stdio.h>


    int main(void)
    {
    int sock;
    struct sockaddr_in other_end;
    struct sockaddr_in this_end;

    other_end.sin_port = htons(10000);
    other_end.sin_addr.s_addr = inet_addr("192.168.1.3");
    other_end.sin_family = AF_INET;
    memset(&other_end.sin_zero, 0, sizeof(other_end.sin_zero));
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
    perror("socket failed");
    return errno;
    }

    this_end.sin_port=htons(0);
    this_end.sin_addr.s_addr=htons(INADDR_ANY);
    this_end.sin_family=AF_INET;
    memset(&this_end.sin_zero, 0, sizeof(this_end.sin_zero));
    if (bind(sock, &this_end, sizeof(this_end)) < 0)
    {
    perror("bind");
    errno=0;
    goto close_sock;
    }
    for (;
    {
    char buff[128];
    size_t len;
    if (fgets(buff, sizeof(buff), stdin) < 0) break;
    len = strlen(buff);
    if (sendto(sock, buff, len, 0, &other_end, sizeof(other_end)) < len)
    {
    perror("sendto");
    errno=0;
    break;
    }
    if (buff[0] == 'R')
    {
    buff[0]=0;
    len = recvfrom(sock, buff, sizeof(buff), 0, NULL, NULL);
    if (len < 0)
    {
    perror("recvfrom");
    errno=0;
    break;
    }
    printf("response is [%d]\"%.*s\"\n", len, len, buff);
    }
    }
    close_sock:
    if (errno) perror("Leaving");
    close(sock);
    return errno;
    }

    </pre>
    Share this post

  2. #2
    OK, I know, I'm a geek, and I can't resist a challenge like this.

    This is probably the most minimalistic DeviceLink program possible, but it has the basics from which you can build something.

    The program is written to run under Linux (probably any *nix like OS will do, and probably most others as well, as long as they use the posix networking APIs.)

    The machine running IL-2 is hardcoded to network address 192.168.1.3. Change that as required.

    Before running it, you must enable DeviceLink in IL-2 by adding the below to your conf.ini:

    <pre class="ip-ubbcode-code-pre">
    [DeviceLink]
    IPS=&lt;IP-addr of machine running sample prog&gt;
    PORT=10000
    </pre>

    A sample run is shown below:
    <pre class="ip-ubbcode-code-pre">
    bash-2.05b$ ./a.out
    R/2/22/
    response is [26]"A/2\1.00/22\Il-2_1941_Late"
    R/40/30/
    response is [18]"A/40\1.100/30\0.36"
    R/80/
    response is [10]"A/80\-1.00"
    </pre>

    OK, it's nothing fancy, but the communication is there.

    The program (with all its bugs and shortcomings, for example it erroneously expects a response from all commands, so if you enter a command without response, it will hang):
    <pre class="ip-ubbcode-code-pre">
    #include &lt;sys/types.h&gt;
    #include &lt;sys/socket.h&gt;
    #include &lt;netinet/in.h&gt;
    #include &lt;arpa/inet.h&gt;
    #include &lt;errno.h&gt;
    #include &lt;stdio.h&gt;


    int main(void)
    {
    int sock;
    struct sockaddr_in other_end;
    struct sockaddr_in this_end;

    other_end.sin_port = htons(10000);
    other_end.sin_addr.s_addr = inet_addr("192.168.1.3");
    other_end.sin_family = AF_INET;
    memset(&other_end.sin_zero, 0, sizeof(other_end.sin_zero));
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock &lt; 0)
    {
    perror("socket failed");
    return errno;
    }

    this_end.sin_port=htons(0);
    this_end.sin_addr.s_addr=htons(INADDR_ANY);
    this_end.sin_family=AF_INET;
    memset(&this_end.sin_zero, 0, sizeof(this_end.sin_zero));
    if (bind(sock, &this_end, sizeof(this_end)) &lt; 0)
    {
    perror("bind");
    errno=0;
    goto close_sock;
    }
    for (;
    {
    char buff[128];
    size_t len;
    if (fgets(buff, sizeof(buff), stdin) &lt; 0) break;
    len = strlen(buff);
    if (sendto(sock, buff, len, 0, &other_end, sizeof(other_end)) &lt; len)
    {
    perror("sendto");
    errno=0;
    break;
    }
    if (buff[0] == 'R')
    {
    buff[0]=0;
    len = recvfrom(sock, buff, sizeof(buff), 0, NULL, NULL);
    if (len &lt; 0)
    {
    perror("recvfrom");
    errno=0;
    break;
    }
    printf("response is [%d]\"%.*s\"\n", len, len, buff);
    }
    }
    close_sock:
    if (errno) perror("Leaving");
    close(sock);
    return errno;
    }

    </pre>
    Share this post

  3. #3
    BTW, there seems to be a small bug in DeviceLink. Set commands seem impossible to combine, or the syntax for doing so is different from what the docs say.

    I can combine as many get commands as I feel like in one line, while I have only managed with single set commands, never sets combined with other sets or with gets. Ironically, this means that the very example posted in devicelink.txt, does not work, since it combines the query of altitude with the setting of power.

    Also... I guess this is the way things are usually done in the IP world, but having string commands/responses that must be generated and parsed in both ends, instead of binary packets that are just interpreted from packet start, offset and field-size, seems like a waste of CPU cycles and latency. Although, admittedly, it makes it easier to test it with a simple program like the above.
    _
    /Bjorn.
    Share this post

  4. #4
    Further testing...

    It seems like I cannot combine commands which takes paremeters with any other commands, or rather that no command can follow after one which takes parameters. As long as the one requiring a parameter is the last one, then it's OK.

    Unfortunately there are also some gets which require parameters (for exampple, the engine status gauges have an engine ID as its parameter.)

    Seems like there's a problem with knowing when the parameter ends and the next command begins. A / or \ or space is not it, however.
    _
    /Bjorn.
    Share this post

  5. #5
    So, umm, err.. nice coding for your example program to demonstrate devicelink, but for us that are clueless and lost our propeller beanies, what exactly does it do?? i look at it, and can only boggle.. the lights are on, but nobody is home, comprehension wise...
    Share this post

  6. #6
    Share this post

  7. #7
    BaldieJr's Avatar Senior Member
    Join Date
    May 2003
    Location
    this don\'t make no sense!
    Posts
    4,282
    bah. i have to run, cant test. promised in-laws dinner...

    possible \ escaping? just a thought.

    <pre class="ip-ubbcode-code-pre">
    My Specs (read 'em and weep):
    * Automatically grinds whole beans before brewing
    * Fully programmable 24 hours in advance
    * Brew Pause feature lets you enjoy a cup before brewing has finished
    * Automatically shuts off when brewing is complete
    * Grind-off feature for brewing ground coffee
    * 1-4 cup feature to accommodate coffee for one
    * 10-cup double-wall insulated thermal carafe to keep your coffee hot long after brewing
    * Gold tone commercial-style permanent filter eliminates the need to buy coffee filters
    * Charcoal water filter removes impurities from the water
    * Separate grinder chamber and filter area allow for easy cleanup
    * Limited 3-year warranty
    </pre>
    Share this post

  8. #8
    GT182's Avatar Banned
    Join Date
    Mar 2003
    Posts
    2,144
    BaldieJr, too bad yer device program is AI only.

    "GT182" / "vonSpinmeister"
    www.bombs-away.net
    "Fly to Survive, Survive to Fly"
    Share this post

  9. #9
    BaldieJr's Avatar Senior Member
    Join Date
    May 2003
    Location
    this don\'t make no sense!
    Posts
    4,282
    You gotta check and make sure something isn't stripping \'s from yout input (i barely read compiled languanges, but i've been down this road lots of times with interpreted stuff and sockets).

    I did:
    R/40/401/81\1/80

    with a one-shot write in lua. Results:
    A/40\47.56/80\1.00

    Auto pilot (401) was turned off and power went to max (1- the example is porked, you only get -1.00 thru 1.00.

    I'm going to pound out a few longer examples and will post results here, but it appears to be working.

    <pre class="ip-ubbcode-code-pre">
    My Specs (read 'em and weep):
    * Automatically grinds whole beans before brewing
    * Fully programmable 24 hours in advance
    * Brew Pause feature lets you enjoy a cup before brewing has finished
    * Automatically shuts off when brewing is complete
    * Grind-off feature for brewing ground coffee
    * 1-4 cup feature to accommodate coffee for one
    * 10-cup double-wall insulated thermal carafe to keep your coffee hot long after brewing
    * Gold tone commercial-style permanent filter eliminates the need to buy coffee filters
    * Charcoal water filter removes impurities from the water
    * Separate grinder chamber and filter area allow for easy cleanup
    * Limited 3-year warranty
    </pre>
    Share this post

  10. #10
    BaldieJr's Avatar Senior Member
    Join Date
    May 2003
    Location
    this don\'t make no sense!
    Posts
    4,282
    Yuk. Buggy.

    You can't set multiple params that require a value. You can only set non-value keys (auto pilots and lights etc).

    Some of these dont return thier states, like cockpit lights, which kinda makes it no fun... i cant check the state of the cockpit lights and set hardware to its value? oh well.

    I'm wondering if setting axis values has to be independant of a get. I'll try it.

    <pre class="ip-ubbcode-code-pre">
    My Specs (read 'em and weep):
    * Automatically grinds whole beans before brewing
    * Fully programmable 24 hours in advance
    * Brew Pause feature lets you enjoy a cup before brewing has finished
    * Automatically shuts off when brewing is complete
    * Grind-off feature for brewing ground coffee
    * 1-4 cup feature to accommodate coffee for one
    * 10-cup double-wall insulated thermal carafe to keep your coffee hot long after brewing
    * Gold tone commercial-style permanent filter eliminates the need to buy coffee filters
    * Charcoal water filter removes impurities from the water
    * Separate grinder chamber and filter area allow for easy cleanup
    * Limited 3-year warranty
    </pre>
    Share this post