Android Question Python Convert To B4A Language or Java

Hi, i have this code by a company, i have to implement this in my b4a app but i realy dont know how to convert it in java or b4a.
Can i have a help pls? are just 2 week that i not have any result.....


PythonCode:
import asyncio
import crcmod
from crcmod.predefined import *
import datetime
from bleak import BleakClient
from bleak.backends.characteristic import BleakGATTCharacteristic
import subprocess
import sys

# UUID service to connect
SERVICE_UUID = "00005301-0000-0041-4c50-574953450000"

# Write characteristics
CHARACTERISTIC_UUID_WRITE = "00005302-0000-0041-4c50-574953450000"

# Read characteristics
CHARACTERISTIC_UUID_NOTIFY = "00005303-0000-0041-4c50-574953450000"

# Standard Ack
STD_ACK = [0x05,0x01,0x40,0x01,0x00,0x01,0xb8,0x55,0x81,0x09,0x40,0x01,0x02,0x01,0x46,0xB0,0x77,0xE2,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0xF0,0x72]
STD2_ACK = [0x05,0x01,0x40,0x02,0x00,0x01,0x48,0x55]

# End session
END_SESSION_PRE = [0x81,0x02,0x40]

# End session post
END_SESSION_POST1 = [0x03,0x01]
END_SESSION_POST2 = [0x77,0xFF,0x67,0xB0]

# Block index
index = 0

# Procedura principale
async def main(device_address):
    
    def Crc16(message: bytearray):
        # Configurazione del modulo Crc-16 secondo la specifica DDCMP
        crc_mod = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0x0000, xorOut=0x0000)
        bmessage = bytes(message)
        crc_value = crc_mod(bmessage)
        return crc_value.to_bytes(2)
    
    def AppendCrc16(message: bytearray):
        res = Crc16(message)
        return res
    
    async def ReadDataBlock(data):
        preack = [0x05, 0x01, 0x40]
        postind = [0x00, 0x01]
        ack = []
        global index
        if data[0] == 0x81:
            # Verifica se è l'ultimo blocco di dati
            if data[2] != 0x40:
                print("Ultimo blocco...")
                # Rispondi con un'acknowledgement
                ack.extend(preack)
                ack.extend(index.to_bytes(1, 'little'))
                ack.extend(postind)
                ack_crc = AppendCrc16(ack)
                ack.extend(ack_crc[1:])
                ack.extend(ack_crc[0:])
                await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(ack), response=False)
                print("Inviato: Rispondi con un'acknowledgement ", ack)
                # Termina il blocco

                end_session = []
                end_session.extend(END_SESSION_PRE)
                end_session.extend(index.to_bytes(1, 'little'))
                end_session.extend(END_SESSION_POST1)
                end_session_crc = AppendCrc16(end_session)
                end_session.extend(end_session_crc[1:])
                end_session.extend(end_session_crc[0:])
                await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(end_session), response=False)
                print("Inviato: Termina il blocco endSession ", end_session)
                await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(END_SESSION_POST2), response=False)
                print("Inviato: Termina il blocco endSession2 ", END_SESSION_POST2)
                await asyncio.sleep(1)
                return
            
            print("Leggi EVA-DTS audit...")
            # Rispondi con un'acknowledgement per il blocco con l'ID di sequenza
            ack.extend(preack)
            ack.extend(index.to_bytes(1, 'little'))
            ack.extend(postind)
            ack_crc = AppendCrc16(ack)
            ack.extend(ack_crc[1:])
            ack.extend(ack_crc[0:])

            await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(ack), response=False)
            print("Inviato: Rispondi con un'acknowledgement per il blocco con l'ID di sequenza ", ack)
            if index < 255:
                index += 1
            else:
                index = 0
            print("Indice", index)
            await asyncio.sleep(1)
    
    async def handle_rx(_: BleakGATTCharacteristic, data: bytearray):
        print("Ricevuto HandleRX: ", data.hex())
        if start_read_block:
            await ReadDataBlock(data)
    
    def return_chunk(data, uw):
        # Calcola la dimensione del chunk basata sulla caratteristica bl
        data_payload_size = uw.max_write_without_response_size - 3
        chunks = []
        for i in range(0, len(data), data_payload_size):
            chunk = data[i:i + data_payload_size]
            chunks.append(chunk)
        return chunks

    async with BleakClient(device_address) as client:
        global index
        print(f"Connesso a {device_address}")
        
        start = [0x05, 0x06, 0x40, 0x00, 0x08, 0x01, 0x5B, 0x95]
        service = client.services
        
        uw = service.get_characteristic(CHARACTERISTIC_UUID_WRITE)
        start_read_block = False
        index = 0
        await client.start_notify(CHARACTERISTIC_UUID_NOTIFY, handle_rx)
        await asyncio.sleep(1)
        
        # Il primo messaggio START è sempre ignorato dalla scheda di destinazione
        await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(start), response=False)
        await asyncio.sleep(1)
        print("Inviato Primo Messaggio START ", start)
        
        # Ripeti START
        await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(start), response=False)
        await asyncio.sleep(1)
        print("Inviato Secondo Messaggio START ", start)

        # Chi sei: timestamp utilizza il formato BCD
        current = datetime.datetime.now()
        cy = current.year % 100
        date_dmy = [int(str(current.day), 16), int(str(current.month), 16), int(str(cy), 16)]
        date_hms = [int(str(current.hour), 16), int(str(current.minute), 16), int(str(current.second), 16)]
        pre_who = [0x81, 0x10, 0x40, 0x00, 0x01, 0x01, 0x0a, 0x42, 0x77, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00]
        post_who = [0x00, 0x00, 0x0c]
        who_are_you_msg = []
        who_are_you_msg.extend(pre_who)
        who_are_you_msg.extend(date_dmy)
        who_are_you_msg.extend(date_hms)
        who_are_you_msg.extend(post_who)

        who_are_you_msg_crc = AppendCrc16(who_are_you_msg)
        who_are_you_msg.extend(who_are_you_msg_crc[1:])
        who_are_you_msg.extend(who_are_you_msg_crc[0:])

        chks = return_chunk(who_are_you_msg, uw)
        for ch in chks:
            await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(ch), response=False)
            print("Inviato I Chunk del messaggio WhoAreYou: ", ch)
        await asyncio.sleep(1)

        # Invia ACK
        chks2 = return_chunk(STD_ACK, uw)
        for ch2 in chks2:
            await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(ch2), response=False)
            print("Inviato Ack", ch2)
        await asyncio.sleep(2)
        
        # Leggi EVA-DTS...
        # Invia ACK del primo blocco EVA-DTS
        await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(STD2_ACK), response=False)
        print("Inviato Leggi EVA-DTS ", STD2_ACK)
        index = 3

        start_read_block = True
        await asyncio.sleep(5)

        await client.stop_notify(CHARACTERISTIC_UUID_NOTIFY)
        print("Disconnesso da ", device_address)


if __name__ == "__main__":
    device_address = "00:A0:50:43:89:DD"  # Inserisci qui l'indirizzo MAC del dispositivo a cui collegarsi
    # Esegui la funzione per avviare la ricerca
    asyncio.run(main(device_address))
 

JohnJ

Member
Licensed User
Longtime User
Hi, i have this code by a company, i have to implement this in my b4a app but i realy dont know how to convert it in java or b4a.
Can i have a help pls? are just 2 week that i not have any result.....


PythonCode:
import asyncio
import crcmod
from crcmod.predefined import *
import datetime
from bleak import BleakClient
from bleak.backends.characteristic import BleakGATTCharacteristic
import subprocess
import sys

# UUID service to connect
SERVICE_UUID = "00005301-0000-0041-4c50-574953450000"

# Write characteristics
CHARACTERISTIC_UUID_WRITE = "00005302-0000-0041-4c50-574953450000"

# Read characteristics
CHARACTERISTIC_UUID_NOTIFY = "00005303-0000-0041-4c50-574953450000"

# Standard Ack
STD_ACK = [0x05,0x01,0x40,0x01,0x00,0x01,0xb8,0x55,0x81,0x09,0x40,0x01,0x02,0x01,0x46,0xB0,0x77,0xE2,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0xF0,0x72]
STD2_ACK = [0x05,0x01,0x40,0x02,0x00,0x01,0x48,0x55]

# End session
END_SESSION_PRE = [0x81,0x02,0x40]

# End session post
END_SESSION_POST1 = [0x03,0x01]
END_SESSION_POST2 = [0x77,0xFF,0x67,0xB0]

# Block index
index = 0

# Procedura principale
async def main(device_address):
   
    def Crc16(message: bytearray):
        # Configurazione del modulo Crc-16 secondo la specifica DDCMP
        crc_mod = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0x0000, xorOut=0x0000)
        bmessage = bytes(message)
        crc_value = crc_mod(bmessage)
        return crc_value.to_bytes(2)
   
    def AppendCrc16(message: bytearray):
        res = Crc16(message)
        return res
   
    async def ReadDataBlock(data):
        preack = [0x05, 0x01, 0x40]
        postind = [0x00, 0x01]
        ack = []
        global index
        if data[0] == 0x81:
            # Verifica se è l'ultimo blocco di dati
            if data[2] != 0x40:
                print("Ultimo blocco...")
                # Rispondi con un'acknowledgement
                ack.extend(preack)
                ack.extend(index.to_bytes(1, 'little'))
                ack.extend(postind)
                ack_crc = AppendCrc16(ack)
                ack.extend(ack_crc[1:])
                ack.extend(ack_crc[0:])
                await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(ack), response=False)
                print("Inviato: Rispondi con un'acknowledgement ", ack)
                # Termina il blocco

                end_session = []
                end_session.extend(END_SESSION_PRE)
                end_session.extend(index.to_bytes(1, 'little'))
                end_session.extend(END_SESSION_POST1)
                end_session_crc = AppendCrc16(end_session)
                end_session.extend(end_session_crc[1:])
                end_session.extend(end_session_crc[0:])
                await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(end_session), response=False)
                print("Inviato: Termina il blocco endSession ", end_session)
                await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(END_SESSION_POST2), response=False)
                print("Inviato: Termina il blocco endSession2 ", END_SESSION_POST2)
                await asyncio.sleep(1)
                return
           
            print("Leggi EVA-DTS audit...")
            # Rispondi con un'acknowledgement per il blocco con l'ID di sequenza
            ack.extend(preack)
            ack.extend(index.to_bytes(1, 'little'))
            ack.extend(postind)
            ack_crc = AppendCrc16(ack)
            ack.extend(ack_crc[1:])
            ack.extend(ack_crc[0:])

            await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(ack), response=False)
            print("Inviato: Rispondi con un'acknowledgement per il blocco con l'ID di sequenza ", ack)
            if index < 255:
                index += 1
            else:
                index = 0
            print("Indice", index)
            await asyncio.sleep(1)
   
    async def handle_rx(_: BleakGATTCharacteristic, data: bytearray):
        print("Ricevuto HandleRX: ", data.hex())
        if start_read_block:
            await ReadDataBlock(data)
   
    def return_chunk(data, uw):
        # Calcola la dimensione del chunk basata sulla caratteristica bl
        data_payload_size = uw.max_write_without_response_size - 3
        chunks = []
        for i in range(0, len(data), data_payload_size):
            chunk = data[i:i + data_payload_size]
            chunks.append(chunk)
        return chunks

    async with BleakClient(device_address) as client:
        global index
        print(f"Connesso a {device_address}")
       
        start = [0x05, 0x06, 0x40, 0x00, 0x08, 0x01, 0x5B, 0x95]
        service = client.services
       
        uw = service.get_characteristic(CHARACTERISTIC_UUID_WRITE)
        start_read_block = False
        index = 0
        await client.start_notify(CHARACTERISTIC_UUID_NOTIFY, handle_rx)
        await asyncio.sleep(1)
       
        # Il primo messaggio START è sempre ignorato dalla scheda di destinazione
        await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(start), response=False)
        await asyncio.sleep(1)
        print("Inviato Primo Messaggio START ", start)
       
        # Ripeti START
        await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(start), response=False)
        await asyncio.sleep(1)
        print("Inviato Secondo Messaggio START ", start)

        # Chi sei: timestamp utilizza il formato BCD
        current = datetime.datetime.now()
        cy = current.year % 100
        date_dmy = [int(str(current.day), 16), int(str(current.month), 16), int(str(cy), 16)]
        date_hms = [int(str(current.hour), 16), int(str(current.minute), 16), int(str(current.second), 16)]
        pre_who = [0x81, 0x10, 0x40, 0x00, 0x01, 0x01, 0x0a, 0x42, 0x77, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00]
        post_who = [0x00, 0x00, 0x0c]
        who_are_you_msg = []
        who_are_you_msg.extend(pre_who)
        who_are_you_msg.extend(date_dmy)
        who_are_you_msg.extend(date_hms)
        who_are_you_msg.extend(post_who)

        who_are_you_msg_crc = AppendCrc16(who_are_you_msg)
        who_are_you_msg.extend(who_are_you_msg_crc[1:])
        who_are_you_msg.extend(who_are_you_msg_crc[0:])

        chks = return_chunk(who_are_you_msg, uw)
        for ch in chks:
            await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(ch), response=False)
            print("Inviato I Chunk del messaggio WhoAreYou: ", ch)
        await asyncio.sleep(1)

        # Invia ACK
        chks2 = return_chunk(STD_ACK, uw)
        for ch2 in chks2:
            await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(ch2), response=False)
            print("Inviato Ack", ch2)
        await asyncio.sleep(2)
       
        # Leggi EVA-DTS...
        # Invia ACK del primo blocco EVA-DTS
        await client.write_gatt_char(CHARACTERISTIC_UUID_WRITE, bytes(STD2_ACK), response=False)
        print("Inviato Leggi EVA-DTS ", STD2_ACK)
        index = 3

        start_read_block = True
        await asyncio.sleep(5)

        await client.stop_notify(CHARACTERISTIC_UUID_NOTIFY)
        print("Disconnesso da ", device_address)


if __name__ == "__main__":
    device_address = "00:A0:50:43:89:DD"  # Inserisci qui l'indirizzo MAC del dispositivo a cui collegarsi
    # Esegui la funzione per avviare la ricerca
    asyncio.run(main(device_address))
I copied that code and plugged it into Copilot. It came back with this.

Alright, let’s break this down. This code is for connecting to a Bluetooth device using the Bleak library in Python. The general purpose seems to be communication with a device, likely for reading and writing data blocks. Let's dive into the key parts:

  1. Imports and UUIDs:
    • The code imports necessary libraries and sets up UUIDs for the Bluetooth service and characteristics.
  2. Standard Acknowledgements and Session End:
    • There are predefined lists for standard acknowledgements and ending sessions.
  3. CRC Functions:
    • Functions to compute CRC-16 (Cyclic Redundancy Check) values to ensure data integrity.
  4. main Function:
    • The main function main(device_address) is asynchronous and handles the connection and communication with the Bluetooth device.
  5. ReadDataBlock Function:
    • This asynchronous function reads and responds to data blocks from the device.
  6. Handle Data Reception (handle_rx):
    • This function handles incoming data and processes it through ReadDataBlock.
  7. Chunk Splitting:
    • The return_chunk function splits data into chunks based on the maximum write size.
  8. Connecting to the Device:
    • The code connects to the Bluetooth device using BleakClient, starts notifications, and sends several initial messages to the device.
  9. Sending WhoAreYou Message:
    • It constructs and sends a “Who are you” message, including the current date and time in BCD format.
  10. Acknowledging EVA-DTS:
    • It sends acknowledgements for EVA-DTS data blocks and handles reading these blocks.
This setup essentially allows for reading and writing data blocks to a specific Bluetooth device, handling acknowledgements, and verifying data integrity using CRC-16. Let me know if you need more details or help understanding a specific part!
 
Upvote 0
I copied that code and plugged it into Copilot. It came back with this.

Alright, let’s break this down. This code is for connecting to a Bluetooth device using the Bleak library in Python. The general purpose seems to be communication with a device, likely for reading and writing data blocks. Let's dive into the key parts:

  1. Imports and UUIDs:
    • The code imports necessary libraries and sets up UUIDs for the Bluetooth service and characteristics.
  2. Standard Acknowledgements and Session End:
    • There are predefined lists for standard acknowledgements and ending sessions.
  3. CRC Functions:
    • Functions to compute CRC-16 (Cyclic Redundancy Check) values to ensure data integrity.
  4. main Function:
    • The main function main(device_address) is asynchronous and handles the connection and communication with the Bluetooth device.
  5. ReadDataBlock Function:
    • This asynchronous function reads and responds to data blocks from the device.
  6. Handle Data Reception (handle_rx):
    • This function handles incoming data and processes it through ReadDataBlock.
  7. Chunk Splitting:
    • The return_chunk function splits data into chunks based on the maximum write size.
  8. Connecting to the Device:
    • The code connects to the Bluetooth device using BleakClient, starts notifications, and sends several initial messages to the device.
  9. Sending WhoAreYou Message:
    • It constructs and sends a “Who are you” message, including the current date and time in BCD format.
  10. Acknowledging EVA-DTS:
    • It sends acknowledgements for EVA-DTS data blocks and handles reading these blocks.
This setup essentially allows for reading and writing data blocks to a specific Bluetooth device, handling acknowledgements, and verifying data integrity using CRC-16. Let me know if you need more details or help understanding a specific part!
i try to (in this week) to "translate" with help of chatgpt this code in java, the app can connect with the hexis device but i dont have the same result and output


My java translate version:
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.zip.CRC32;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothGattDescriptor;

//Function call by B4A part
public void ConnectionHexisViaMAC(String mac,Context context)
{
    BluetoothHexis bluetoothHexis;
    bluetoothHexis = new BluetoothHexis();
    bluetoothHexis.connect(mac);
}

//Hexis device class
public class BluetoothHexis
{
    // UUID service to connect
    private final String SERVICE_UUID = "00005301-0000-0041-4c50-574953450000";

    // Write characteristics
    private final String CHARACTERISTIC_UUID_WRITE = "00005302-0000-0041-4c50-574953450000";

    // Read characteristics
    private final String CHARACTERISTIC_UUID_NOTIFY = "00005303-0000-0041-4c50-574953450000";

    //START ACK
    byte[] START_ACK =
    {
        (byte)0x05, (byte)0x06, (byte)0x40, (byte)0x00 ,(byte)0x08,
        (byte)0x01 ,(byte)0x5B, (byte)0x95
    };

    //Standard Ack
    byte[] STD_ACK =
    {
        (byte) 0x05, (byte) 0x01, (byte) 0x40, (byte) 0x01, (byte) 0x00,
        (byte) 0x01, (byte) 0xb8, (byte) 0x55, (byte) 0x81, (byte) 0x09,
        (byte) 0x40, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x46,
        (byte) 0xB0, (byte) 0x77, (byte) 0xE2, (byte) 0x00, (byte) 0x01,
        (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0xF0, (byte) 0x72
    };

    byte[] STD2_ACK =
    {
        (byte) 0x05, (byte) 0x01, (byte) 0x40, (byte) 0x02, (byte) 0x00,
        (byte) 0x01, (byte) 0x48, (byte) 0x55
    };

    // End session
    private final byte[] END_SESSION_PRE = {(byte)0x81, (byte) 0x02, (byte) 0x40};

    // End session post
    private final byte[] END_SESSION_POST1 = {(byte) 0x03, (byte)0x01};
    private final byte[] END_SESSION_POST2 = {(byte) 0x77, (byte) 0xFF,(byte) 0x67,(byte) 0xB0};

    // Block index
    private int index = 0;

    private BluetoothGatt gatt;
    private BluetoothDevice device;
    private boolean startReadBlock = false;
    private int StartAckCount = 1;

    public CompletableFuture<Void> connect(String deviceAddress)
    {
        CompletableFuture<Void> future = new CompletableFuture<>();

        BluetoothManager bluetoothManager = getSystemService(BluetoothManager.class);
        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
        device = bluetoothAdapter.getRemoteDevice(deviceAddress);

        gatt = device.connectGatt(null, false, new BluetoothGattCallback()
        {
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
            {
                 if (newState == BluetoothGatt.STATE_CONNECTED) {
                    BA.Log("Connected to GATT server.");
                    gatt.discoverServices();
                } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
                    BA.Log("Disconnected from GATT server, status: " + status);
                    future.complete(null);
                }
            }

            @Override
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                if (status == BluetoothGatt.GATT_SUCCESS)
                {
                    BluetoothGattService service = gatt.getService(UUID.fromString(SERVICE_UUID));
                    if (service != null)
                    {
                        BluetoothGattCharacteristic characteristicNotify = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_UUID_NOTIFY));
                        BluetoothGattCharacteristic characteristicWrite  = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_UUID_WRITE));
                        characteristicWrite.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                        if (characteristicNotify != null)
                        {
                            startCommunication(gatt,characteristicNotify,characteristicWrite);
                            
                        }else{
                            BA.Log("Notification characteristic not found.");
                        }
                    } else
                    {
                        BA.Log("Service not found.");
                    }
                }
            }

            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
            {
                byte[] data = characteristic.getValue();
                BA.Log("Received HandleRX: " + bytesToHex(data));
                if (startReadBlock)
                {
                    readDataBlock(data);
                }
            }

            @Override
            public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    BA.Log("Characteristic written successfully.");
                } else {
                    BA.Log("Error writing characteristic: " + status);
                }
            }

            @Override
            public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
                super.onDescriptorWrite(gatt, descriptor, status);
                BA.Log("onDescriptorWrite :" + ((status == BluetoothGatt.GATT_SUCCESS) ? "Sucess" : "false"));
            }
        });

        return future;
    }

    // Costruzione del messaggio WhoAreYou con timestamp-------------------------------------
    private byte[] BuildWhoYouAreMessage(BluetoothGattCharacteristic characteristicWrite)
    {
        LocalDateTime current = LocalDateTime.now();
        byte cy = (byte) (current.getYear() % 100);
        byte[] dateDmy = {(byte) current.getDayOfMonth(), (byte) current.getMonthValue(), cy};
        byte[] dateHms = {(byte) current.getHour(), (byte) current.getMinute(), (byte) current.getSecond()};
        byte[] preWho  = {(byte) 0x81, (byte) 0x10, (byte) 0x40, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x0a, (byte) 0x42, (byte) 0x77, (byte) 0xe0, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
        byte[] postWho = {(byte) 0x00, (byte) 0x00, (byte)0x0c};

        List<Byte> whoAreYouMsg = new ArrayList<>();
        for (byte b : preWho ) whoAreYouMsg.add(b);
        for (byte b : dateDmy) whoAreYouMsg.add(b);
        for (byte b : dateHms) whoAreYouMsg.add(b);
        for (byte b : postWho) whoAreYouMsg.add(b);

        byte[] whoAreYouMsgArray = new byte[whoAreYouMsg.size()];
        for (int i = 0; i < whoAreYouMsg.size(); i++) whoAreYouMsgArray[i] = whoAreYouMsg.get(i);

        byte[] whoAreYouMsgCrc = appendCRC16(whoAreYouMsgArray);
        whoAreYouMsgArray = concatenate(whoAreYouMsgArray, whoAreYouMsgCrc);

        return whoAreYouMsgArray;
    }
    //-----------------------------------------------------------------------------------

    private void startCommunication(BluetoothGatt bluetoothGatt,BluetoothGattCharacteristic characteristicNotify, BluetoothGattCharacteristic characteristicWrite)
    {
        startReadBlock = false; index = 0;

        //Notifica a True
        bluetoothGatt.setCharacteristicNotification(characteristicNotify, true);
        BluetoothGattDescriptor descriptor = characteristicNotify.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        boolean descriptorsucc = bluetoothGatt.writeDescriptor(descriptor);
        BA.Log("Descriptor write initiated. Success: " + descriptorsucc);

            sleepThread(1000);
            // Invio dei messaggi START (il primo sarà sempre ignorato dalla scheda di destinazione)
            handler.postDelayed(new Runnable()
            {
                    @Override
                    public void run()
                    {
                        if(descriptorsucc)
                        {
                            //start message
                            writeCharacteristicForStart(CHARACTERISTIC_UUID_WRITE, START_ACK);
                            //sleepThread(1000);
                            writeCharacteristicForStart(CHARACTERISTIC_UUID_WRITE, START_ACK);

                            //who you are message
                            List<byte[]> chunks = returnChunks(BuildWhoYouAreMessage(characteristicWrite), characteristicWrite);
                            for (byte[] chunk : chunks)
                            {
                                writeCharacteristic(CHARACTERISTIC_UUID_WRITE, chunk, "Inviato I Chunk del messaggio WhoAreYou: " + bytesToHex(chunk));
                            }
                            //sleepThread(1000);

                            //Invia ACK
                            List<byte[]> ackChunks = returnChunks(STD_ACK, characteristicWrite);
                            for (byte[] chunk : ackChunks) writeCharacteristic(CHARACTERISTIC_UUID_WRITE, chunk, "Inviato Ack " + bytesToHex(chunk));
                            
                            //sleepThread(2000);
                            
                            //Invia ACK 2
                            writeCharacteristic(CHARACTERISTIC_UUID_WRITE, STD2_ACK,"Inviato Leggi EVA-DTS " + bytesToHex(STD2_ACK));

                            index = 3;
                            startReadBlock = true;
                            //sleepThread(5000);
                            bluetoothGatt.setCharacteristicNotification(characteristicNotify, false);
                            BluetoothGattDescriptor descriptor = characteristicNotify.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
                            descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
                            BA.Log("Descriptor write initiated. Success: " + bluetoothGatt.writeDescriptor(descriptor));
                        }
                        
            }
                
            }, 1000); 
    }

    private void readDataBlock(byte[] data)
    {
        BA.Log("ENTRO IN READ DATA BLOCK");
        byte[] preack = {0x05, 0x01, 0x40};
        byte[] postind = {0x00, 0x01};
        byte[] ack;
        BA.Log("Data[0] = " + data[0]);
        if (data[0] == (byte) 0x81)
        {
            if (data[2] != 0x40) {
                BA.Log("Last block...");
                ack = new byte[preack.length + 1 + postind.length + 2];
                System.arraycopy(preack, 0, ack, 0, preack.length);
                ack[preack.length] = (byte) index;
                System.arraycopy(postind, 0, ack, preack.length + 1, postind.length);
                byte[] ackCrc = appendCRC16(Arrays.copyOf(ack, ack.length - 2));
                System.arraycopy(ackCrc, 1, ack, ack.length - 2, 1);
                ack[ack.length - 1] = ackCrc[0];

                handler.postDelayed(new Runnable()
                {
                        @Override
                        public void run()
                        {
                            writeCharacteristic(CHARACTERISTIC_UUID_WRITE, ack,"Sent: Respond with acknowledgement " + Arrays.toString(ack));
                        }
                    
                }, 1000); 
                
                //BA.Log("Sent: Respond with acknowledgement " + Arrays.toString(ack));

                byte[] endSession = new byte[END_SESSION_PRE.length + 1 + END_SESSION_POST1.length + 2];
                System.arraycopy(END_SESSION_PRE, 0, endSession, 0, END_SESSION_PRE.length);
                endSession[END_SESSION_PRE.length] = (byte) index;
                System.arraycopy(END_SESSION_POST1, 0, endSession, END_SESSION_PRE.length + 1, END_SESSION_POST1.length);
                byte[] endSessionCrc = appendCRC16(Arrays.copyOf(endSession, endSession.length - 2));
                System.arraycopy(endSessionCrc, 1, endSession, endSession.length - 2, 1);
                endSession[endSession.length - 1] = endSessionCrc[0];

                writeCharacteristic(CHARACTERISTIC_UUID_WRITE, endSession,"");
                BA.Log("Sent: End block endSession " + Arrays.toString(endSession));
                writeCharacteristic(CHARACTERISTIC_UUID_WRITE, END_SESSION_POST2,"");
                BA.Log("Sent: End block endSession2 " + Arrays.toString(END_SESSION_POST2));
                return;
            }

            BA.Log("Read EVA-DTS audit...");
            ack = new byte[preack.length + 1 + postind.length + 2];
            System.arraycopy(preack, 0, ack, 0, preack.length);
            ack[preack.length] = (byte) index;
            System.arraycopy(postind, 0, ack, preack.length + 1, postind.length);
            byte[] ackCrc = appendCRC16(Arrays.copyOf(ack, ack.length - 2));
            System.arraycopy(ackCrc, 1, ack, ack.length - 2, 1);
            ack[ack.length - 1] = ackCrc[0];

            writeCharacteristic(CHARACTERISTIC_UUID_WRITE, ack,"");
            BA.Log("Sent: Respond with acknowledgement for block with sequence ID " + Arrays.toString(ack));
            if (index < 255) {
                index++;
            } else {
                index = 0;
            }
            BA.Log("Index " + index);
        }
    }

    //FUNZIONI DI MANAGEMENT PER LO SCAMBIO BOTTA E RISPOSTA CON HEXIS-------------------------------------------------------------------------------------------

    private byte[] crc16(byte[] message)
    {
        CRC32 crc = new CRC32();
        crc.update(message);
        long crcValue = crc.getValue();
        return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort((short) crcValue).array();
    }

    private byte[] appendCRC16(byte[] data)
    {
        CRC32 crc = new CRC32();
        crc.update(data, 0, data.length);
        long checksum = crc.getValue();

        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.putInt((int) checksum);
        byte[] result = new byte[2];
        result[0] = buffer.get(2);
        result[1] = buffer.get(3);
        return result;
    }

    private byte[] concatenate(byte[] first, byte[] second)
     {
        byte[] result = new byte[first.length + second.length];
        System.arraycopy(first, 0, result, 0, first.length);
        System.arraycopy(second, 0, result, first.length, second.length);
        return result;
    }

    private String bytesToHex(byte[] bytes)
    {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }

    private void sleepThread(int milliseconds)
    {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            BA.Log("Interruzione del thread: " + e.getMessage());
        }
    }
    
    private List<byte[]> returnChunks(byte[] data, BluetoothGattCharacteristic characteristic)
    {
        int chunkSize = characteristic.getWriteType() == BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT ? 20 : 512;
        List<byte[]> chunks = new ArrayList<>();

        for (int i = 0; i < data.length; i += chunkSize) {
            chunks.add(Arrays.copyOfRange(data, i, Math.min(data.length, i + chunkSize)));
        }

        return chunks;
    }
    

    private void writeCharacteristic(String uuid, byte[] data, String msg)
    {
        BluetoothGattService service = gatt.getService(UUID.fromString(SERVICE_UUID));
        StartAckCount++;

        if (service != null) {
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(uuid));
            if (characteristic != null)
            {
                characteristic.setValue(data);
                boolean success = gatt.writeCharacteristic(characteristic);
                //BA.Log("Writing to characteristic " + uuid + ": " + bytesToHex(data) + ", success: " + success);
                if(success) BA.Log(msg);

            } else {
                BA.Log("Characteristic not found: " + uuid);
            }
        } else {
            BA.Log("Service not found: " + SERVICE_UUID);
        }
    }

    private void writeCharacteristicForStart(String uuid, byte[] data)
    {
        BluetoothGattService service = gatt.getService(UUID.fromString(SERVICE_UUID));

        if (service != null)
        {
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(uuid));
            if (characteristic != null) {
                characteristic.setValue(data);
                boolean success = gatt.writeCharacteristic(characteristic);
                
                if(success)
                {
                    BA.Log("Inviato " + StartAckCount + " START (se 1 Verrà Ignorato False) " + bytesToHex(START_ACK));
                }else{
                    StartAckCount++;
                }
            } else {
                BA.Log("Characteristic not found: " + uuid);
            }
        } else {
            BA.Log("Service not found: " + SERVICE_UUID);
        }
    }
}

b4a Call java part:
Private Sub bluetoothListViewCoges_ItemClick (Index As Int, Value As Object)
    Try
        'Dim Securcode As String = setta_securcode
        
        If(CurrDeviceRilevazione = "COGES") Then
            'Corrado 21/11/2023-----------------------------
            Log("chiamata connected: "&joCOG.RunMethod("ConnectAndRilevaCoges",Array(ctxtCOG, Index, setta_securcode)))
            pnlListBluetoothCoges.Enabled=False
            pnlListBluetoothCoges.Visible=False
            lbltitleCoges.Text="BTDataKey Coges"
            pnlGestioneDispositivoCoges.Enabled=True
            pnlGestioneDispositivoCoges.Visible=True
            'fine Corrado 21/11/2023------------------------
        Else If(CurrDeviceRilevazione = "Hexis") Then
            jo2.RunMethod("ConnectionHexisViaMAC",Array("00:A0:50:43:89:DD",ctxtCOG)) : Return
        End If
        
    Catch
        bluetoothListViewCoges.Clear
        pnlCoges.Enabled=False
        pnlCoges.Visible=False
        pnlRilevaCoges.Visible=False
        pnlRilevaCoges.Enabled=False
        pnlListBluetoothCoges.Enabled=True
        pnlListBluetoothCoges.Visible=True
        lbltitleCoges.Text="DISPOSITIVI COGES"
        pnlDispositivi.Visible=True
        pnlDispositivi.Enabled=True
        Msgbox2Async(joCOG.RunMethod("getErrorMSG",Null), "ATTENZIONE","OK","","",LoadBitmap(File.DirAssets,"iniziale-rosso - copia.png"),False)
        Log(LastException)
    End Try
End Sub
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
?
BLE GATT and Calculation CRC 16

 
Upvote 0
by the way, from my java i have this output
[b4a with my java code output]

b4a my java output:
Device Nome: SLCOG-92412433A00

Device Nome: SLCOG-92412433A00 MAC: 00:A0:50:43:89:DD

Descriptor write initiated. Success: true

Inviato 1 START (se 1 Verrà Ignorato False) 05 06 40 00 08 01 5B 95

Inviato I Chunk del messaggio WhoAreYou: 81 10 40 00 01 01 0A 42 77 E0 00 00 00 00 00 1F 0A 18 09 37 18 00 00 0C CF B4

Inviato Leggi EVA-DTS 05 01 40 02 00 01 48 55

but its no correct, because i have to obtaine something like that
[python original output]

python original code: output:
Connesso a 00:A0:50:43:89:DD

Inviato Primo Messaggio START  [5, 6, 64, 0, 8, 1, 91, 149]

Inviato Secondo Messaggio START  [5, 6, 64, 0, 8, 1, 91, 149]

Inviato I Chunk del messaggio WhoAreYou:  [129, 16, 64, 0, 1, 1, 10, 66, 119, 224, 0, 0, 0, 0, 0, 49, 16]

Inviato I Chunk del messaggio WhoAreYou:  [36, 9, 83, 38, 0, 0, 12, 52, 217, 52]

Ricevuto (hex): 050740080801e797050140010001b85581154001

byte non leggibili

Ricevuto (hex): 0101978288e001000000003030303030303030aa

byte non leggibili

Ricevuto (hex): bb0000ffffe9c2

byte non leggibili

Inviato Ack [5, 1, 64, 1, 0, 1, 184, 85, 129, 9, 64, 1, 2, 1, 70, 176, 119]

Inviato Ack [226, 0, 1, 1, 0, 0, 0, 0, 240, 114]

Ricevuto (hex): 0501400200014855810940020201b6b088e20101

byte non leggibili

Ricevuto (hex): 010000ffffa4f6

byte non leggibili

Inviato Leggi EVA-DTS  [5, 1, 64, 2, 0, 1, 72, 85]

Ricevuto (hex): 810940020201b6b0

byte non leggibili

Leggi EVA-DTS audit...

Inviato: Rispondi con un'acknowledgement per il blocco con l'ID di sequenza  [5, 1, 64, 3, 0, 1, 25, 149, 25]

Indice 4

Ricevuto (hex): 88e20101010000ffffa4f6

byte non leggibili

Ricevuto (hex): 810940020201b6b0

byte non leggibili

Leggi EVA-DTS audit...

Inviato: Rispondi con un'acknowledgement per il blocco con l'ID di sequenza  [5, 1, 64, 4, 0, 1, 168, 84, 168]

Indice 5

Ricevuto (hex): 88e20101010000ffffa4f6
 
Upvote 0
Top