1. This forum is obsolete and read-only. Feel free to contact us at support.keenswh.com

Data Transfer using Laser Antennas

Discussion in 'Programming Released Codes' started by SigmaStrain, Mar 10, 2015.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. SigmaStrain

    SigmaStrain Trainee Engineer

    Messages:
    27
    Good evening all,

    I've written some code that will allow you to transmit, receive and retransmit messages using Laser antennas. The way it works is by using the "Detailed Info" string of the laser antennas. The system also uses a "message closure" protocol so it knows when to save or retransmit messages. The code can be described as such:

    Sending:
    1. Copy message from onboard lcd panel called "lcd"
    2. Change name of Laser Antenna to message.
    3. Power Laser Antenna off
    4. Power Laser Antenna on
    5. wait 350 game ticks
    6. Copy closure message ("[...]") to name of laser antenna
    7. Power Laser Antenna off
    8. Power Laser Antenna on
    9. wait 350 game ticks
    10. exit

    Receiving:
    1. Copy message from detailed info of onboard laser antenna
    2. wait until closure message("[...]") is received.
    3. once closure message is received, copy message text to onboard lcd panel
    4. wait for further messages

    retransmission:
    1. receive message
    2. wait until closure message is received.
    3. once closure message is received, start message transmission
    4. send message
    5. send closure message
    6. wait for further messages

    Here is the code:

    Sending:
    to use:
    you need 1 programming block, 1 lcd display named "lcd", 1 timer block named 'tb' with its actions set to run your programming block, and one LA.
    I recommend setting your LA's name to '000' to start with because that character string is treated as a "null" message by the system.

    Code:
    IMyLaserAntenna la1;
    IMyTextPanel lcd;
    int ticks = 0;
    int waitTicks = 0;    //number of ticks to wait
    IMyTerminalBlock tb;
    bool closure = false;
    bool send = true;    //if we're still in the process of sending our message
    bool wait = false;    //if we're in wait mode
    void Main()
    {
        if(ticks == 0)
        {
           init();
            ticks++;
            tb.ApplyAction("TriggerNow");
           return;
        }
        
        if(wait == false)    //if we're not in wait mode
        {
            if(closure == false)
            {
                la1.SetCustomName(lcd.GetPublicText());    //get the message from our lcd display
                closure = true;
                wait = true;    //set wait mode to true
            }
            else
            {
                la1.SetCustomName("[...]");
                lcd.WritePublicText("");
                closure = false;
                wait = true;
            }
            la1.GetActionWithName("OnOff_Off").Apply(la1);    //every five frames cycle the laser antenna off
        }
        else //We're in wait mode
        {
            if(waitTicks ==0)    //first run
            {
                la1.GetActionWithName("OnOff_On").Apply(la1);    //turn on the laser antenna
            }
            if(waitTicks == 350) //if we've waited 350 ticks
            {
                wait = false;
                waitTicks = 0;    //reset the number of ticks to wait
                if(closure == false)    //no longer need to send the closure string
                {
                    return;    //exit code execution
                }
            }
            else
            {
                waitTicks++; 
            }
                                                                                           
        }
        
        
        lcd.ShowTextureOnScreen();
        lcd.ShowPublicTextOnScreen();
        ticks++;
        tb.ApplyAction("TriggerNow");
        
    }
            void init()
            {
                    la1 = (IMyLaserAntenna)get_laser();    //get the laser antenna 
                    tb = get_block("tb"); 
                    lcd = (IMyTextPanel)get_block("lcd");
            }
            IMyTerminalBlock get_block(string name) 
            { 
                List<IMyTerminalBlock> blks = GridTerminalSystem.Blocks; 
                 
                for (int i = 0; i < blks.Count; i++) 
                { 
                    if (blks[i].CustomName.StartsWith(name)) 
                    { 
                        return blks[i]; 
                    } 
                } 
                throw new Exception(name + " Not Found"); 
                return null; 
            }
            IMyTerminalBlock get_laser() 
            { 
                List<IMyTerminalBlock> c = new List<IMyTerminalBlock>(); 
                GridTerminalSystem.GetBlocksOfType<IMyLaserAntenna>(c); 
                return c[0]; 
            }
    
    Receiving:
    to use:
    you need 1 programming block, 1 lcd display named "lcd" 1 timer block named 'tb' with its actions set to run your programming block, and one LA.

    Code:
    IMyLaserAntenna la1; 
    IMyTextPanel lcd; 
    int ticks = 0; 
    IMyTerminalBlock tb; 
    string receivedMessage;
    string lastMessage;
    bool Closure;
    void Main() 
    { 
        if(ticks == 0) 
        { 
           init(); 
            ticks++; 
            tb.ApplyAction("TriggerNow"); 
           return; 
        } 
        
         
         
     if(la1.DetailedInfo[48] == 'n')    //if we're connected 
        { 
     
            receivedMessage = la1.DetailedInfo.Substring(58);    //grab the message to send 
            if(receivedMessage !="000")    //if we're not getting the default value for the send antenna 
            { 
     
                    if(Closure==true)    //if we still need to receive the closure message 
                    { 
                        if(receivedMessage == "[...]")    //if we've received the closure message 
                        { 
                            lastMessage = lastMessage+"\n"+lcd.GetPublicText();    //preserve old messages
                            lcd.WritePublicText(lastMessage);
                            lcd.ShowTextureOnScreen();
                            lcd.ShowPublicTextOnScreen(); 
                            Closure = false;    //when we enter receive mode, we'll need to receive the  closure string 
                        } 
                    } 
                    else    //if we don't need to receive a closure message 
                    { 
                        if(receivedMessage != "[...]") 
                        { 
                            Closure = true;    //flag to receive closure string 
                            lastMessage = receivedMessage;    //this is now the last message received 
                        } 
                    } 
                 
            } 
        }
    
        ticks++; 
        tb.ApplyAction("TriggerNow"); 
         
    } 
            void init() 
            { 
                    la1 = (IMyLaserAntenna)get_laser();    //get the laser antenna  
                    tb = get_block("tb");  
                    lcd = (IMyTextPanel)get_block("lcd"); 
            } 
            IMyTerminalBlock get_block(string name)  
            {  
                List<IMyTerminalBlock> blks = GridTerminalSystem.Blocks;  
                  
                for (int i = 0; i < blks.Count; i++)  
                {  
                    if (blks[i].CustomName.StartsWith(name))  
                    {  
                        return blks[i];  
                    }  
                }  
                throw new Exception(name + " Not Found");  
                return null;  
            } 
     
            IMyTerminalBlock get_laser()  
            {  
                List<IMyTerminalBlock> c = new List<IMyTerminalBlock>();  
                GridTerminalSystem.GetBlocksOfType<IMyLaserAntenna>(c);  
                return c[0];  
            }
    


    Retransmission:
    to use:
    you need 1 programming block, 1 timer block named 'tb' with its actions set to run your programming block, one LA named 'Recv', and one LA named '000'.

    Code:
    static IMyLaserAntenna Receiver;
    static IMyLaserAntenna Sender;
    static IMyTerminalBlock tb;    //our timer block
    static string receivedMessage;
    static bool Wait = false;    //we need to wait for around 350 ticks for the laser antennas to reconnect.
    static bool SendClosure = false;    //boolean to determine if we need to send the send closure flag
    static bool SendMode = false;    //are we in send mode or receive mode? false means we're in receive mode
    static bool Closure = false;    //do we still need to receive the closure string? false means no
    static string lastMessage = "";    //the last message received by us. we need this to ensure we don't send multiples of
                                                    //the same message
    static int ticks = 0;    //number of ticks the program has run
    static int SendTicks = 0;    //counter used to time the sending of messages
    void Main()
    {
        if(ticks == 0)    //first run
        {
            init();
            ticks++;
            tb.ApplyAction("TriggerNow");
        }
    if(SendMode == false)    //if we're in receive mode
    {
        if(Receiver.DetailedInfo[48] == 'n')    //if we're connected
        {
            receivedMessage = Receiver.DetailedInfo.Substring(58);    //grab the message to send
            if(receivedMessage !="000")    //if we're not getting the default value for the send antenna
            {
                    if(Closure==true)    //if we still need to receive the closure message
                    {
                        if(receivedMessage == "[...]")    //if we've received the closure message
                        {
                            SendMode = true;    //enter send mode
                            Closure = false;    //when we enter receive mode, we'll need to receive the  closure string
                        }
                    }
                    else    //if we don't need to receive a closure message
                    {
                        if(receivedMessage != "[...]")
                        {
                            Closure = true;    //flag to receive closure string
                            lastMessage = receivedMessage;    //this is now the last message received
                        }
                    }
                
            }
        }
    }
    else    //we're in send mode
    {
        if(Wait == false)    //we're not in wait mode
        {
            if(SendClosure == false)    //if we don't need to send the closure message
            {
                Sender.SetCustomName(lastMessage);    //update the name of our sending antenna
                Sender.ApplyAction("OnOff_Off");    //turn the antenna off
                Wait = true;    //sent the wait flag
                SendClosure = true;    //set the send closure message flag
            }
            else
            {
                Sender.SetCustomName("[...]");   //send the closure message
                Sender.ApplyAction("OnOff_Off");    //turn the antenna off
                Wait = true;
                SendClosure = false;    //so now we don't need to send the closure message
            }
        }
        else    //we're in wait mode
        {
            if(SendTicks == 0)    //if this is the first time we've entered wait mode
            {
                Sender.GetActionWithName("OnOff_On").Apply(Sender);    //turn the sender antenna on
            }
            
            if(SendTicks == 350)    //if we've waited 350 ticks
            {
                Wait = false;    //turn off the wait flag
                SendTicks = 0;
                if(SendClosure == false)    //if we don't still need to send the closure message
                {
                    SendMode = false;        //switch back to receive mode
                    
                }
               
            }
            else
            {
                SendTicks++; 
            }   
        }
    }
        ticks++;
        tb.ApplyAction("TriggerNow");
    }
    void init()
    {
        Receiver = (IMyLaserAntenna)get_block("Recv");
        Sender = (IMyLaserAntenna)get_block("000");
        tb = get_block("tb");
    }
    
            IMyTerminalBlock get_block(string name)   
            {   
                List<IMyTerminalBlock> blks = GridTerminalSystem.Blocks;   
                   
                for (int i = 0; i < blks.Count; i++)   
                {   
                    if (blks[i].CustomName.StartsWith(name))   
                    {   
                        return blks[i];   
                    }   
                }   
                throw new Exception(name + " Not Found");   
                return null;   
            } 
    
    
     
    • Informative Informative x 3
    • Like Like x 1
  2. Tony Hughes

    Tony Hughes Junior Engineer

    Messages:
    715
    Well done SigmaStrain, that's a really good piece of illustrative code demonstrating how to read from the LCD panel and transmit data between grids.

    I'll give it a try this evening, when I've got some time.

    With a few adaptions, that will be useful for all sorts of applications.
     
  3. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    OMG OMG OMG

    OMG

    so many things possible now that it's been cracked!!!
     
  4. mze9412

    mze9412 Junior Engineer

    Messages:
    791
    Very nice! I would only suggest making your ifs a little bit smaller/more efficient

    And usually it is recommended to use the true case in the if and put the false case in the else branch for better readability, but that is something based on personal taste in the end ;)
     
  5. SigmaStrain

    SigmaStrain Trainee Engineer

    Messages:
    27
    Thanks for the suggestion and for taking the time to reply and read the code. Have you tried it out? I'm curious as to what everyone will end up using this for.
     
  6. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    Outside of the obvious of being able to have a script on one grid activate a script/action on another..

    I'd like to see some sort of proximity alert type thing where some outlying beacon buoys detect and enemy getting close and turn on the defenses, maybe dispatch a defense drone to coordinates.

    I've had a long-standing request for a "formations" script, which I think this should make possible now.. want to explore in a mobile base ship and have a large miner tag along in formation. Maybe a warship too. A laser connection to each ship would kind of limit things but it sure beats having to fly them all separately.
     
  7. shimonu

    shimonu Apprentice Engineer

    Messages:
    396
    Only problem is it take time to update data (turn off/on laser antenna = take time to reconnect). Making "all ships fly there" could work but no fast updates to flight course.
    For formation we would be needing also laser antenna on main ship for each followin ship (or make chain to send back and forth).
    If we could refresh without reconecting... (and I was hoping on making "slave" decoy ships to follow "main" fighter)

    "laser antenna permanent connection" I am curious if there are any interesting changes from today update (at work, can't check anything)
     
  8. Zourin

    Zourin Apprentice Engineer

    Messages:
    142
    This could, in theory, be used for a kind of autopilot. The ability to transmit across laser antenna means being able to relay remote coordinates of blocks. On top of that, the laser antenna connection implies zero obstacles between them. Therefore, align ship, engage thrust, and coast until you're within 1000m of the destination coordinates before restoring Inertia dampening.

    The destination coordinates don't even have to be fixed, you could 'auto' to a mobile position like this, as long as you're not transmitting a LOS signal through an obstacle course.

    Depending on how good the trigonometry is, it's possible track deviation from the original vector and correct.
     
    Last edited by a moderator: Mar 22, 2015
  9. Panda72

    Panda72 Trainee Engineer

    Messages:
    30
    First, thanks for the awesome idea and reasearch! I'm trying to develop something with this and looking at your code, am a bit confused. What is the 350 tick wait for?

    I went a slightly different route and it "seems" to work, but I need to make sure I'm not missing something. I allow the LAs to connect, and then immediately disconnect. So my code looks like:

    Code:
    void reportStatus()
    {
        LAAft.SetCustomName("Beluga Laser Antenna Aft [" + DateTime.Now.ToString("hhmmss") + ":" 
            + Status + ":" + pctFull.ToString("###.#") + ":" + LAAft.GetPosition().ToString() + "]");
        if (!LAAft.Enabled)
        {
            LAAft.ApplyAction("OnOff_On");
        }
        if (LAAft.DetailedInfo.Contains("Connected to"))
        {
            LAAft.ApplyAction("OnOff_Off");
        }
        
    }
    
    Am I missing something with the enforced wait time? This waits until it is connected and then immediately shuts it off. It will wait forever while it is "Trying to Connect" or can't connect or anything else.
     
  10. shimonu

    shimonu Apprentice Engineer

    Messages:
    396
    Or for docking. Send position of station connector, rotate ship to match connectors (I know it has to be customized for each ship)
     
  11. Panda72

    Panda72 Trainee Engineer

    Messages:
    30
    Well, this was fun! (at least in my opinion). I have my remote miner returning its status, position, and cargo capactiy to an LA so I can constantly monitor it. Lots more to do, but its a start. My biggest issue is trying to keep the LA connected as the ship itself blocks about 180 degrees of line of sight back to home base.

    [​IMG]
     
    • Like Like x 1
  12. SigmaStrain

    SigmaStrain Trainee Engineer

    Messages:
    27
    The wait time was determined through tests. It takes approx 350 ticks to reconnect laser antennas.
     
  13. Panda72

    Panda72 Trainee Engineer

    Messages:
    30
    ok, makes sense. Seems a little more straightforward (to me) to do it the way I did. I don't count ticks, I just turn it off once it connects and sends the message and then turn it back on again next tick. Seems to work fine in my world.

    It would be really nice if in a new version it didn't require the on/off cycle at all of course.
     
  14. SpecFrigateBLK3

    SpecFrigateBLK3 Senior Engineer

    Messages:
    1,133
    Could you write a simpler version, one which updates every ten seconds? I'd like to have it transfer the updated coordinates of the scout (updated every ten seconds by scout-side PB) to the instruction panel for NAV Autopilot, along with instructions based on the scout ship pilot's choice?
    May even just manually trigger the script by remote control?
     
  15. Warixx

    Warixx Trainee Engineer

    Messages:
    85
    I just noticed the "known receivers" list being updated every time "permanent connection" is changed (or the antenna gets a "connect to receiver" order). So if we could somehow get the names of the know receivers, we could send messages instantaneously. Unfortunately we have no access to this list, to my knowledge?
     
  16. mexmer

    mexmer Senior Engineer

    Messages:
    1,977
    no, we don't it's one of many things on my TODO list, related to terminalextension changes .... well, since publishing of sourcecode ... list is only growing, my free time unfortunately not
     
  17. Codebender

    Codebender Apprentice Engineer

    Messages:
    196
    Is it possible to have a 2 way transceiver with this?
     
  18. Wicorel

    Wicorel Senior Engineer

    Messages:
    1,263
    Yes it is.

    I have been coding one the past couple of days and will be making a alpha release soon.

    It has an interface to allow packets to be sent and received.

    I will announce in this forum.

    EDIT: Post started and a testing world available. VERY work-in-progress, but it does demonstrate the functionality.

    https://forum.keenswh.com/threads/wip-wico-antenna-network-wan.7372286/
     
    Last edited: Nov 6, 2015
    • Informative Informative x 1
  19. DoubleCouponDay

    DoubleCouponDay Apprentice Engineer

    Messages:
    123
    i noticed that the change in name of antenna is available, without needing a reboot, by pressing the copy target coords button. unfortunately its twin Vector3D TargetCoords, available with ingame programming, does not return antenna name. so close! :(

    on the brightside, there is an option to communicate in binary with bool IsPermanent and isPerm because changing this option effects the reading on the receiver without breaking the connection. you could also have two states of a program such as 'i am or am not under attack'. many, many possibilities here without the delay.

    https://forum.keenswh.com/threads/la...on-without-the-delay.7375386/#post-1286897402
     
    Last edited: Nov 30, 2015
  20. Concave

    Concave Apprentice Engineer

    Messages:
    112
    I'm not seeing the IMyLaserAntenna in the documentation, has something been changed?
     
  21. DoubleCouponDay

    DoubleCouponDay Apprentice Engineer

    Messages:
    123
    It's still working; I tested last night :]
     
  22. Udrakan

    Udrakan Apprentice Engineer

    Messages:
    111
    Can somebody explain to me how to make sensor on forward base detecting enemy set off an alarm in my main base? Both connected with laser antennas. I have 500+h in space engineers and I havent touched programmable block yet. Looks very interisting.
     
  23. Wicorel

    Wicorel Senior Engineer

    Messages:
    1,263
    My antenna network script does that.

    The example world has a timer sending a message back to a base that turns a light on/off.

    If you want a more specific example, publish a world with your main and forward base and I'll add the communication as an example.
     
    • Like Like x 1
Thread Status:
This last post in this thread was made more than 31 days old.