Moku API - Only Every Second Stream Works

Hi,
I am confronted with an issue in the Moku API when trying to start a data stream on the MokuGo device. Only every second stream works reliably. When I stop this reliably working stream and start another, my program is able to fetch a handful of packets until the stream seemingly ends. Afterwards I still need to manually stop the stream. When I start a new stream after this procedure, it works again. I was able to reproduce this behavior every single time I tried it.

Could this be a device bug, or am I handling the API incorrectly?

The error is always the same:

moku.exceptions.StreamException: End of stream

I am using version 3.2.0 of the Moku client and the Python API on Ubuntu 22.04.
Here is a minimal setup to reproduce the issue:

from moku.instruments import Datalogger
from moku.instruments import MultiInstrument
from moku.exceptions import MokuNotFound
import time

if __name__ == "__main__":
    address = "<moku_address>"
    print("Connect MokuGo")
    moku_device = MultiInstrument(address, force_connect = True, platform_id = 2)
    print("Set instrument")
    instrument = moku_device.set_instrument(1, Datalogger)
    print("Set connections")
    connections = [{"source": "Input1", "destination": "Slot1InA"},
                    {"source": "Input2", "destination": "Slot1InB"}]
    moku_device.set_connections(connections)
    print("Set input channels")
    moku_device.set_frontend(channel = 1, impedance = "1MOhm", coupling = "DC", attenuation = '0dB')
    moku_device.set_frontend(channel = 2, impedance = "1MOhm", coupling = "DC", attenuation = '0dB')

    try:
        instrument.start_streaming(sample_rate = 10000)
        print("Start receiving.")
        for i in range(100):
            data = instrument.get_stream_data()
            if data is not None:
                print(f"{i} ", end = "", flush = True)
        print("")
        print("End receiving.")

        time.sleep(5)
        print("Stop Streaming.")
        instrument.stop_streaming()

        instrument.start_streaming(sample_rate = 10000)
        print("Start receiving.")
        print("The error should emerge here.")
        for i in range(100):
            data = instrument.get_stream_data()
            if data is not None:
                print(f"{i} ", end = "", flush = True)
        print("")
        print("End receiving.")

        time.sleep(5)
        print("Stop Streaming.")
        instrument.stop_streaming()

    except Exception as e:
        print(f"[Error] {e}")
        instrument.stop_streaming()

Hi @Cycrus Cyril,

The End of stream exception is expected because this is more like a notification to users. We will need to handle this exception and continue running the rest of the script.

By the way, I would recommend calling the get_stream_data() in a while True loop with try block to fetch the streaming data and handle the exception. Hope this helps. Thank you very much!

Best regards,
Hank

Hi Hank,

thanks for your answer.
I would expect an “End of stream” exception to only emerge when I try to fetch from a stopped stream. But my stream was stopped and started again, so it should not throw anything.

Am I supposed to stop the stream and wait for the exception to occur in my receive message loop until I am allowed to start another stream?

Hi @Cycrus Cyril,

You are correct, but it has one thing I wanted to mention:

It is necessary to continuously calling get_stream_data() until you receive the End of stream. There are still data packs in the buffer even you stopped the stream. To avoid the error, it is important to read all data packs from the buffer. This code should work:

from moku.instruments import Datalogger
from moku.instruments import MultiInstrument
from moku.exceptions import MokuNotFound
import time

if __name__ == "__main__":
    address = "192.168.2.243"
    print("Connect MokuGo")
    moku_device = MultiInstrument(address, force_connect = True, platform_id = 2)
    print("Set instrument")
    instrument = moku_device.set_instrument(1, Datalogger)
    print("Set connections")
    connections = [{"source": "Input1", "destination": "Slot1InA"},
                    {"source": "Input2", "destination": "Slot1InB"}]
    moku_device.set_connections(connections)
    print("Set input channels")
    moku_device.set_frontend(channel = 1, impedance = "1MOhm", coupling = "DC", attenuation = '0dB')
    moku_device.set_frontend(channel = 2, impedance = "1MOhm", coupling = "DC", attenuation = '0dB')

    try:
        instrument.start_streaming(duration=10, sample_rate = 10000)
        print("Start receiving.")
        while True:
            try:
                data = instrument.get_stream_data()
                print(data)
            except Exception as e:
                print(f"[Error] {e}")
                break
                # instrument.stop_streaming()
        
        print("")
        print("End receiving.")

        time.sleep(5)
        print("Stop Streaming.")
        instrument.stop_streaming()

        instrument.start_streaming(duration=10, sample_rate = 10000)
        print("Start receiving.")
        print("The error should emerge here.")
        while True:
            try:
                data = instrument.get_stream_data()
                print(data)
            except Exception as e:
                print(f"[Error] {e}")
                break
                # instrument.stop_streaming()
        
        print("")
        print("End receiving.")

        time.sleep(5)
        print("Stop Streaming.")
        instrument.stop_streaming()

    except Exception as e:
        print(f"[Error] {e}")
        instrument.stop_streaming()

Hi Hank,

ok, I understand now. So the End of Stream exception is used as a signaling event when the stream is allowed to be stopped/left alone. Thank you for your help.

Best regards,
Cyril

1 Like