nanoporetech / minknow_api

Protobuf and gRPC specifications for the MinKNOW API
Other
55 stars 12 forks source link

Question Regarding Development with Simulation #42

Open biosero-simon opened 2 years ago

biosero-simon commented 2 years ago

Hi,

I'm currently working on a driver for the device and do not have access to the physical machine. Is there documentation around using a simulated device? I'm having issues with the method call.

Best, Simon

0x55555555 commented 2 years ago

Hi @biosero-simon , can you be more specific around what method you are calling and what is happening?

What version of the software are you using? What OS are you using, and what device are you trying to simulate?

biosero-simon commented 2 years ago

Hi George,

I'm trying to simulate a MinION using version 5.2.13

Using Windows 10, C#, .NET 6.

        channel = GrpcChannel.ForAddress(ipAddress + ':' + port);
        manager = new MinknowApi.Manager.ManagerService.ManagerServiceClient(channel);

        var request = new AddSimulatedDeviceRequest();
        request.Name = "MS12345";
        request.Type = SimulatedDeviceType.SimulatedAuto;
        manager.add_simulated_device(request);

--> Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: PartialChain", DebugException="System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: PartialChain at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception) at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions) at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm) at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.AddHttp2ConnectionAsync(HttpRequestMessage request) at System.Threading.Tasks.TaskCompletionSourceWithCancellation1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.GetHttp2ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at Grpc.Net.Client.Balancer.Internal.BalancerHttpHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at Grpc.Net.Client.Internal.GrpcCall2.RunCall(HttpRequestMessage request, Nullable`1 timeout)

biosero-simon commented 2 years ago

End goal is to integrate into an existing project using .NET Framework 4.8, seeing that .NET Framework 4.8 does not support gRPC over HTTP/2, a second question would be whether this is even possible using .NET Framework

0x55555555 commented 2 years ago

Hi @biosero-simon ,

a second question would be whether this is even possible using .NET Framework

I cant really comment here - I am not a .NET expert.

It looks like you are having issues connecting to minknow even before you get a simulated device setup.

Where is minknow running? on the local device, or a remote device?

When you dont use our python support library, you must handle the gRPC SSL setup yourself, this is your current issue.

See https://github.com/nanoporetech/minknow_api/blob/master/python/minknow_api/__init__.py#L344 for how we handle this.

Once you have a connection I can assist you setting up simulation, if required.

biosero-simon commented 2 years ago

Minknow is running locally.

Is it possible to set up an insecure connection with the server?

0x55555555 commented 2 years ago

Is it possible to set up an insecure connection with the server?

It is not, the minknow service requires a secure connection - gRPC does natively support these.

biosero-simon commented 2 years ago

Hi George, I have a connection and am attempting to use a simulated device. The device however is reporting back no port on which I can connect the protocol channel to. Can you guide me on fixing this?

0x55555555 commented 2 years ago

Can you describe more what youve done to get a simulated device, and what specific responses from API's you are seeing please?

Thanks,

biosero-simon commented 2 years ago

I have attached an image of the position below.

Manager is set up, simulated device is added successfully, but the RPC ports are null on the device connection.

image

0x55555555 commented 2 years ago

Can you share your mk_manager log file, and a script youve run to trigger this?

Are you providing time for the sequencer to initialise after adding the sequencer?

Thanks,

biosero-simon commented 2 years ago

mk_manager_svc_log-2022-09-21_17-45-45.txt

biosero-simon commented 2 years ago

Would be happy to hop on a call and share my screen to walk you through the code. The project consists of multiple different classes to manage the calls, similar to the python client within the repo.

biosero-simon commented 2 years ago

Can push meetings this morning

0x55555555 commented 2 years ago

From your log:

2022-09-22 04:48:48.951329    INFO: hardware_state_changed (host)
    name: MS99999
    os_identifier: 
    state: ready
2022-09-22 04:48:49.667186    INFO: instance_started (host)
    grpc_secure_port: 8000
    grpcweb_tls_port: 8001
    instance: MS99999
2022-09-22 04:51:50.020448    INFO: hardware_state_changed (host)
    name: MS99999
    os_identifier: <unchanged>
    state: absent
2022-09-22 04:51:55.188033    INFO: instance_stopped (host)
    instance: MS99999
    std_ec: (0:std::system): [0x00007FF7F5D5B910]: The operation completed successfully
2022-09-22 04:53:12.363774    INFO: attempt_to_remove_simulated_device_that_does_not_exist (host)
    name: MS99999

You can see the device is added, then 1s later ports are assigned, then its eventually stopped (I assume your code stops the device).

How are you monitoring for device connections? do you watch a stream, or query the flow cell info once?

What happens if you add the device, then poll flow_cell_positions() once a second for a minute?

I suspect your code is not waiting long enough for the device to initialise - but cant say more without a clear reproducible segment of code.

Thanks,

0x55555555 commented 2 years ago

I've got no idea how to escape github and setup a call - I'm around in 1h to talk through your code - if we can work out a call!

biosero-simon commented 2 years ago

Great, I can send you an invite if there is a good email I can use?

biosero-simon commented 2 years ago

My email is simoncoelho@biosero.com if it's easier for you to email me too

0x55555555 commented 2 years ago

I've emailed a zoom link

ChristopherAdelmann commented 7 months ago

Hello @0x55555555, I had a similar issue while using the minknow API. After creating a simulated device, it appears in the minknow UI. The problem is that it returns false when I check if the device is running. If I try to connect anyway, an "Invalid port for connection to [...]" error is thrown. Some assistance with this issue would be great. Here is the according code:

    def connect_to_positions(
        self, run_config: RunConfig, retries: int = 3
    ) -> List[mk.Connection]:
        positions = self.get_sequencing_positions(run_config)

        connections: List[mk.Connection] = []

        for position in positions:
            for _ in range(retries):
                try:
                    if not position.running:
                        raise Exception(f"Position {position.name} is not running.")

                    connections.append(position.connect())
                    break
                except Exception as e:
                    print(
                        f"Failed to connect to position {position.name}. Retrying... Info: {e}"
                    )
                    time.sleep(5)

        if len(connections) != run_config.replicate_count:
            raise Exception(
                f"Could not connect to all positions. Expected {run_config.replicate_count}, got {len(connections)}"
            )
        return connections
    def __create_simulated_position(self, name: Optional[str] = None) -> str:
        def generate_random_string(length=8) -> str:
            characters = string.ascii_letters + string.digits
            random_string = "".join(secrets.choice(characters) for _ in range(length))
            return random_string

        if name is None:
            name = generate_random_string()

        if self.__get_sequencing_position_by_position_id(name) is not None:
            return name

        self.manager.add_simulated_device(
            name,
            mk.manager_pb2.SimulatedDeviceType.SIMULATED_P2,  # type: ignore
        )

        return name

[Other code that returns the simulated devices if requested]