vovagorodok / ArduinoBleChess

Connect your chess eboard over Bluetooth
MIT License
4 stars 1 forks source link

Lichess with Arduino Nano 33 IoT #1

Closed vovagorodok closed 2 years ago

TimoKropp commented 2 years ago

I tried running your AVR/ESP32 examples but I am not sure where the incomaptibiltiy to the SAMD21 lays. It compiles and runs but does not show during the scan process of the app (it shows however when searching for bluetooth devices). This is the same result which I was able to generate with the following code:

#include <ArduinoBLE.h>

// cecp_protocol
#define SERVICE_UUID  "f5351050-b2c9-11ec-a0c0-b3bc53b08d33"
#define RX_UUID  "f53513ca-b2c9-11ec-a0c1-639b8957db99"
#define TX_UUID  "f535147e-b2c9-11ec-a0c2-8bbd706ec4e6"

BLEService OCBService(SERVICE_UUID); // create openchessboard(OCB)service

BLEStringCharacteristic OCBCharacteristic_RX(RX_UUID, BLEWrite, 64);
BLEStringCharacteristic OCBCharacteristic_TX(TX_UUID, BLERead | BLENotify, 64);

void setup() {
  Serial.begin(9600);
  while (!Serial);

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");
    while (1);
  }

  // set the local name peripheral advertises
  BLE.setLocalName("OPENCHESSBOARD");
  BLE.setDeviceName("OPENCHESSBOARD"); 
  // set the UUID for the service this peripheral advertises:
  BLE.setAdvertisedService(OCBService);

  // add the characteristics to the service
  OCBService.addCharacteristic(OCBCharacteristic_RX);
  OCBService.addCharacteristic(OCBCharacteristic_TX);

  // add the service
  BLE.addService(OCBService);

  // start advertising
  BLE.advertise();

  Serial.println("Bluetooth® device active, waiting for connections...");
}

void loop() {
  BLEDevice central = BLE.central();

  if (central) {
    Serial.print("Connected to central: ");
    // print the central's BT address:
    Serial.println(central.address());
  }
  delay(1000);

}
vovagorodok commented 2 years ago

Example optimized for AVR, by removing STL. Hmm, strange. Code that you show looks OK. I had similar issue in the past with ESP32. Issue was because peripheral device has service, but doesn't advertise it. Line solves issue:

advertising->addServiceUUID(SERVICE_UUID);

As I see You have added similar line:

BLE.setAdvertisedService(OCBService);

Perhaps order of this line can change behavior. Try:

// start advertising
BLE.setAdvertisedService(OCBService);
BLE.advertise();

Please check in nRF Connect if your device correctly advertise uuid:

TimoKropp commented 2 years ago

My example shows in nRF connect identical as you have shown in the images.

TimoKropp commented 2 years ago

In the Scanner window (left image) it shows "incomplete List of 128-Bit Servive UUIDs:" and then shows the correct UUID instead of complete list

vovagorodok commented 2 years ago

Just for double check. Have You enabled bluetooth and localization ? Because its required, and if was disabled scan doesn't find anything

TimoKropp commented 2 years ago

Yes it is enabled.

vovagorodok commented 2 years ago

And lichess app has localization permissions?

TimoKropp commented 2 years ago

And lichess app has localization permissions?

yes, that is what i checked first :)

vovagorodok commented 2 years ago

And you have visible UUID in FLAGS & SERVICES tab in nRF Connect (right image)?

TimoKropp commented 2 years ago

okay I tested it on a different device with a fresh installation and now it shows during scan. Maybe there was an issue during the apk installation.

vovagorodok commented 2 years ago

Nice! Please let me know if example works

TimoKropp commented 2 years ago

okay it seems to allow a connection during scan (works with both code examples) but when i go back to the main menu in the app, it repetitively shows "disconnected from Bluetooth device "

vovagorodok commented 2 years ago

For both code examples?

TimoKropp commented 2 years ago

For both code examples?

Your AVR/ESP32 example and my posted example.

vovagorodok commented 2 years ago

Can You check if application on AVR crashes and reboot system? (Looks that Android app try to reconnect, but than crash each time on AVR side)

TimoKropp commented 2 years ago

After your recent commits the error ble initialization error is shown. I think there went something wrong

vovagorodok commented 2 years ago

Ouu, I think that because of typo:

if (!begin(device));
{

insted:

if (!begin(device))
{

Fixed. Please check if works

TimoKropp commented 2 years ago

Init works now but still no debug output in serial monitor and the app shows repetitive disconnects.

vovagorodok commented 2 years ago

Added Serial.println("setup"); and Serial.println("loop");. Please check if it reboots, and You will see setup log each time. Show me all logs what you have from monitor

TimoKropp commented 2 years ago

Setup is only called once, so no device restart. It repetitively posts loop but nothing else.

vovagorodok commented 2 years ago

Added more logs, please check

TimoKropp commented 2 years ago

begin: BLE: 20000274 begin: ArduinoBleChessClass: 20000244 begin: Protocol: 2000026C CecpProtocol::begin: Protocol: 2000026C setup: BLE: 20000274 setup: ArduinoBleChessClass: 20000244 still no prints during scan

vovagorodok commented 2 years ago

What prints do You expect during scan? Device advertises and You find it during scan? Look that nothing received via BLE. Added logs for connected/discon./discover events and checking i any data on characteristic is available. Lets check..

vovagorodok commented 2 years ago

If You want we can try call via skype or another communicator in order to boost issue resolving

TimoKropp commented 2 years ago

still no changes, the new logs don't show up. The device advertise works since it shows up during scan but nothing more from that. Maybe the issue is on app side?

TimoKropp commented 2 years ago

If You want we can try call via skype or another communicator in order to boost issue resolving

let me see if I find the time next week :)

vovagorodok commented 2 years ago

still no changes, the new logs don't show up. The device advertise works since it shows up during scan but nothing more from that. Maybe the issue is on app side?

Hmm, hard to say. Works correctly with ESP32 and RaspberryPi (checked also with apk that was attached)

TimoKropp commented 2 years ago

If ESP32 works but not AVR, I would start by comparing the difference in both implementations. I think the device somehow stops listening after advertisment, or does not receive anything after advertisment (very unlikely).

TimoKropp commented 2 years ago

For example auto* advertising = server->getAdvertising(); advertising->setScanResponse(true); advertising->setMinPreferred(0x06); // functions that help with iPhone connections issue advertising->setMaxPreferred(0x12); This seems quite different to the AVR example.

TimoKropp commented 2 years ago

Also the example in the ArduinoBLE library starts with an initial value for an characteristics: https://github.com/arduino-libraries/ArduinoBLE/blob/master/examples/Peripheral/CallbackLED/CallbackLED.ino

Maybe this is missing this causes the app to immediately disconnect after the discovery?

But I am only guessing since I don't have that much time to debug currently.

TimoKropp commented 2 years ago

Also the example polls permanently in loop :(

vovagorodok commented 2 years ago

Perhaps ArduinoBLE implementation require pull in loop(). Added BLE.poll() to example

TimoKropp commented 2 years ago

Okay nice, polling works. It seems that the library does rely on polling. Not the best but I think it is okay for the chess board application since it not that fast.

vovagorodok commented 2 years ago

Ok, good to know. Library updated. In future CecpProtocol class will be refactored to state machine. What will be nice to have or what to remove in such library from your PoV? Interface will be changed until v1.0.0, because I'll test it on real device. Library will be added to PlatformIO at the end

TimoKropp commented 2 years ago

There are already some issues with the current implementation which a state machine could solve:

  1. when starting a game as black, the last move is only in the transmitted fen and it would be more useful to simply transmit the last move as move string. Only when canceling the game, the last move is indicated as "moved from phone".
  2. When a game is already running in the app and the device is reconnected, no game data is received. There again at least the last move needs to be requested/transmitted
  3. When making a move on the phone, the move should be broadcasted to the device so you can update your board state on the smart chess board.

There are some issues with the app:

  1. When enabling and disabling bluetooth in the app, no new scan is run and there is no indication of a connected device. Only a restart of the app allows a full new scan. On my other Device ( Huawei Tablet) the rescan works as the switch does disconnect the bluetooth connection. I guess that is an issue from the installation and app permission but it is not clear how to solve this in the nokia case. The permissions are correctly indicated in the app manager.
  2. When no device found during scan, the switch is not set back to off.
  3. When using the tablet, the device is stuck at "stop move: ", not clear why.
TimoKropp commented 2 years ago

Further if you try to login to a user account, the app crashes.

vovagorodok commented 2 years ago

Nice to see such precise testing

Let's see:

DEVICE SIDE:

  1. Perhaps I don't understand usecase. When I'm trying play with computer from screach as black:

    new game: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w
    moved from phone: d2d4
    please move: 

    Initial board state is received and wite move (last move) is received after that. If you play not from screach board already have recived moves before and we just recive current board state. If we will add additional move it will be redundant information and I think it's not ok to send same move twice. Additionaly it's not compatible with the XBoard protocol. Please describe more usecase if I didn't understand

  2. Hmm, how to reproduce this case? During disconnection from board there can be more than one move performed and I think that send only one last move does't solve that case. How do you think we can solve it? Send new game and fen when we connected again and chess board will compare what was lost during disconnection?

  3. Already solved by protocol. Look: https://github.com/vovagorodok/lichobile/blob/master/src/externalDevice/README.md case: When user performs a2a3 move from screen:. On protocol side we will see:

    -> go     // ask device to move
    -> force  // ask device to stop move, becasuse moved on screen
    -> a2a3   // send move performed on screen
    -> a7a6   // send oponent move
    -> go     // ask device to move

    In logs you will see:

    please move: 
    stop move: 
    moved from phone: b7b6
    moved from phone: g1f3
    please move: 

PHONE SIDE:

  1. Works as expected on all my devices. Perhaps It's because apk builded not correctly.

  2. Known issue :p Fixed: https://github.com/lichess-org/lichobile/pull/2101/commits/a921dff29b03751e44006b096b429cc22a7d95c4

  3. Hard to say what happens without full usecase description (parhaps it because apk not ok). EDIT: reproduced I'll take a look what happens

Further if you try to login to a user account, the app crashes.

I'm C++/Python dev and it's my first experience with mobile/java. I guess that because apk is not correctly build, and not correctlly support online play. Perhaps will be nice to ask guys from lichobile build full apk for us

TimoKropp commented 2 years ago

test case 1 (with tablet): game was started and its my turn with white (1 move played by black). After scan and connect, the following is shown: moved from phone: xboard please move: moved from phone: accepted setboard stop move: no input possible

vovagorodok commented 2 years ago

Fixed: https://github.com/vovagorodok/ArduinoBleChess/commit/34156a7d854ca13a2ad5a9faa6b1ab17a8e67f1b

Works in ESP because regexp of uci move, planed to add regexp for ArduinoBLE case

TimoKropp commented 2 years ago

test case 2 (with phone): game was startet as black, 1 white move was played: moved from phone: xboard please move: moved from phone: accepted setboard stop move: new game: rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b please move: still the last move is not indicated, at least not in the serial output.

after canceling the game I receive: stop move: moved from phone: d2d4 please move: stop move: moved from phone: d2d4 please move:

vovagorodok commented 2 years ago

Additional fix: https://github.com/vovagorodok/ArduinoBleChess/commit/8c513e6519cc94ccbab3145c24aa4caf404acf88

TimoKropp commented 2 years ago

It seems that the last move is only received on device side after the game was canceled/resigned in the app (reproducible)

TimoKropp commented 2 years ago

when closing the app and opening the game again: new game: rnbqkbnr/pp1p2pp/2p1p3/5p2/3PPP2/8/PPP3PP/RNBQKBNR w please move: the last move is not received.

vovagorodok commented 2 years ago

when closing the app and opening the game again: new game: rnbqkbnr/pp1p2pp/2p1p3/5p2/3PPP2/8/PPP3PP/RNBQKBNR w please move: the last move is not received.

Yes, because last move was recived before closing app and device was already triggered to move . Correct?

TimoKropp commented 2 years ago

aaah now I get the difference. There is an issue with playing offline/computer compared to with play with the computer over the main menu (I guess this is another endpoint). The offline version seems to work but the computer/online game does not.

vovagorodok commented 2 years ago

Yes, because last move was recived before closing app and device was already triggered to move . Correct?

But I don't get what the issue is here

TimoKropp commented 2 years ago

Yes, because last move was recived before closing app and device was already triggered to move . Correct?

But I don't get what the issue is here

Yes it is an issue with the online play against the computer. It works well if you only use the offline board.

TimoKropp commented 2 years ago

Do you try to support online play if this is permitted by the lichobile devs or do you only want to use offline play? I think the white pawn app does exactly that to allow online play. I would strongly prefer to play online vs. offline games :)

vovagorodok commented 2 years ago

Ok, lets summarize issues that we need to solve in order to simply track it:

  1. When a game is already running in the app and the device is reconnected, no game data is received. How to reproduce it?
  2. When using the tablet, the device is stuck at "stop move: ", not clear why. Reproduced and under investigation
  3. Online play. For me is important to. Was added (its almost common code for online/offline), but I can't build apk with online play and I don't know why (have warrning when app started Update required! .. even without my changes ). Lets ask lichobile devs to prepare full apk

Something missed?

TimoKropp commented 2 years ago

Ok, lets summarize issues that we need to solve in order to simply track it:

1. When a game is already running in the app and the device is reconnected, no game data is received.  How to reproduce it?

I receive the FEN but not the last move played. How to test it:

  1. start a game and play some moves
  2. restart/reprogram peripheral device
  3. reconnect bluetooth
  4. received game data: moved from phone: xboard please move: moved from phone: accepted setboard stop move: new game: rnbqkb1r/pp1ppp1p/6p1/2p5/3Pn3/1P3N2/P1P2PPP/RNBQKB1R w please move: