Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPC timeout #15

Open
luismasuelli opened this issue Oct 17, 2024 · 5 comments
Open

IPC timeout #15

luismasuelli opened this issue Oct 17, 2024 · 5 comments

Comments

@luismasuelli
Copy link

luismasuelli commented Oct 17, 2024

Steps to reproduce:

  1. Cloning the repository:
git clone https://github.com/gmag11/MetaTrader5-Docker-Image
  1. Inside the repository, build the image:
cd MetaTrader5-Docker-Image
docker build -t mt5
cd ..
  1. Use this compose file (the local image is tagged: mt5 - create as my-compose-file.yml):
version: '3'
services:
  mt5:
    image: mt5
    container_name: mt5
    volumes:
      - ./config:/config
    ports:
      - "3000:3000"
      - "8001:8001"
  1. launch the compose file:
docker compose -f my-compose-file.yaml up
  1. In the host machine, considering 8001 is exposed, use python3:

This is the code I try in Python (in my host machine).

from mt5linux import MetaTrader5
mt5 = MetaTrader5(host='192.168.my.ip',port=8001)
mt5.initialize()

Result:

mt5.initialize() returns False after a long time, and nothing is initialized.
mt5.last_error() returns (-10005, "IPC timeout").
mt5.version() returns an empty result.

I expect:

Everything to work fine.

@luismasuelli
Copy link
Author

In fact, let's get rid of any complexity.

  1. Launch the image however you want. It will report port 8001 is listening.
  2. Dive into the container (e.g. docker-compose exec ... or docker compose exec ... or docker exec ... depending on how you launched it).
  3. Open a python terminal.
from mt5linux import MetaTrader5
mt5 = MetaTrader5(host='127.0.0.1',port=8001)
mt5.initialize()

Either the same will happen or instead this error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/config/.local/lib/python3.9/site-packages/mt5linux/__init__.py", line 464, in initialize
    return self.__conn.eval(code)
  File "/config/.local/lib/python3.9/site-packages/rpyc/core/netref.py", line 240, in __call__
    return syncreq(_self, consts.HANDLE_CALL, args, kwargs)
  File "/config/.local/lib/python3.9/site-packages/rpyc/core/netref.py", line 63, in syncreq
    return conn.sync_request(handler, proxy, *args)
  File "/config/.local/lib/python3.9/site-packages/rpyc/core/protocol.py", line 473, in sync_request
    return self.async_request(handler, *args, timeout=timeout).value
  File "/config/.local/lib/python3.9/site-packages/rpyc/core/async_.py", line 100, in value
    self.wait()
  File "/config/.local/lib/python3.9/site-packages/rpyc/core/async_.py", line 49, in wait
    raise AsyncResultTimeout("result expired")
TimeoutError: result expired

@caiusCitiriga
Copy link

same here

@caiusCitiriga
Copy link

caiusCitiriga commented Nov 30, 2024

Here's an update for anyone interested:

I've managed to get this working starting from within the docker image as @luismasuelli tried. Then tried the same thing on the host and it worked too. What's the trick?

You have to first login into an account once from the meta trader UI. Then the initialize and other commands will start to work from the mt5linux bridge library.

For me this was a problem, since I needed the whole thing to be fully automated and headless.

I've came up with a temporary solution which is to use puppeteer to automate the first login process. Here's how I did:

import puppeteer from "puppeteer-core";
import { sleep } from "./utils";

(async () => {
  // Launch the browser and open a new blank page
  const browser = await puppeteer.launch({
    channel: "chrome",
    headless: false, // switch this to true to enable chrome headless mode
  });
  const page = await browser.newPage();

  // Set screen size.
  await page.setViewport({ width: 1920, height: 1080 });

  // Navigate the page to the vnc web page
  await page.goto("http://localhost:3000");

  // Give it a couple of seconds to render and stabilize
  await sleep(2);

  // Close any open menus
  page.keyboard.press("Escape");
  await sleep(0.3);

  // Open "File" menu
  page.keyboard.down("Meta");
  page.keyboard.up("Meta");
  page.keyboard.down("Alt");
  page.keyboard.down("F");
  await sleep(0.3);

  page.keyboard.up("Alt");
  page.keyboard.up("F");
  await sleep(0.3);

  // Open "Login to trade account" sub menu
  page.keyboard.press("L");
  await sleep(2);

  page.keyboard.press("Enter");
  console.log("Should have now been logged");

  await sleep(5);
  await browser.close();
})();

I used puppeteer-core since I already have Chrome installed. But you can opt for the full puppeteer installation that will also download the browser. You either need to have one of the puppeteer supported browsers installed and use the -core version, or allow puppeteer to install its own, by using the full version.

Check out puppeteer's documentation for more information and stuff you can do with it. It's super powerful. Unfortunately most of the cool things requires interaction with DOM elements, while kamsvnc renders the DOM within an iframe and then displays everything with a canvas element. However the keyboard interactions seems to work, which for the scope of this problem was all that I needed.

Of course to make this production ready, stable and scalable it needs more work, but it can be a somewhat decent starting point. The idea came to mind after learning about a python library called vncdotool, but this library only worked with a vnc client, and kamsvnc is 100% web based and requires no vnc client installed.

So I thought that maybe a keyboard keypress might be intercepted if automated via a tool like puppeteer.

Hope this helps someone

@luismasuelli
Copy link
Author

luismasuelli commented Nov 30, 2024 via email

@caiusCitiriga
Copy link

@luismasuelli I'll come out with an example soon, so you can give it a try 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants