<commit_before>const noble = require('@abandonware/noble');
const bleno = require('@abandonware/bleno');
const fs = require('fs');
const util = require('util');
const path = require('path');
const { EventEmitter } = require('events');

const writeFile = util.promisify(fs.writeFile);
const readFile = util.promisify(fs.readFile);

var BlenoPrimaryService = bleno.PrimaryService;
var BlenoCharacteristic = bleno.Characteristic;

class BluetoothFileExchangerCentral extends EventEmitter {
    constructor(serviceUUID, characteristicUUID, outputDirectory) {
        super();
        this.serviceUUID = serviceUUID;
        this.characteristicUUID = characteristicUUID;
        this.outputDirectory = outputDirectory;

        noble.on('stateChange', this.stateChangeHandler.bind(this));
        noble.on('discover', this.discoverHandler.bind(this));

        if (noble.state == 'poweredOn') {
            noble.startScanningAsync([this.serviceUUID], true);
        }
    }

    async disable() {
        await noble.stopScanningAsync();
        noble.removeAllListeners();
    }

    async stateChangeHandler(state) {
        console.log('(noble) on -> stateChange: ' + state);
        this.emit('stateChange', state);

        if (state === 'poweredOn') {
            console.log('Scanning');
            await noble.startScanningAsync([this.serviceUUID], true);
        } else {
            await noble.stopScanningAsync();
        }
    }

    discoverHandler(peripheral) {
        this.emit('discover', peripheral);
        peripheral.once('disconnect', () => this.emit('disconnect', peripheral));
    }

    /**
     * 
     * @param {*} peripheral The peripheral to receieve the file from
     */
    async receive(peripheral) {
        await noble.stopScanningAsync();
        await peripheral.connectAsync();

        const characteristics = await new Promise((resolve, reject) => {
            peripheral.discoverSomeServicesAndCharacteristics(
                [this.serviceUUID],
                [this.characteristicUUID],
                (error, services, characteristics) => {
                    if (error) {
                        reject(error);
                        return;
                    }

                    resolve(characteristics);
                }
            );
        });
        const characteristic = characteristics[0];

        const data = await new Promise((resolve, reject) => {
            characteristic.read((error, data) => {
                if (error) {
                    reject(error)
                    return;
                }
                resolve(data);
            });
        });
        await writeFile(path.join(this.outputDirectory, peripheral.advertisement.localName), data);
        await peripheral.disconnectAsync();
        await noble.startScanningAsync();
    }
}

class BluetoothFileExchangerPeripheral extends EventEmitter {
    constructor(serviceUUID, characteristicUUID, peripheralName, filePathSupplier) {
        super();
        this.serviceUUID = serviceUUID;
        this.characteristicUUID = characteristicUUID;
        this.peripheralName = peripheralName;
        this.filePathSupplier = filePathSupplier;

        bleno.on('stateChange', this.stateChangeHandler.bind(this));
        bleno.on('advertisingStart', this.advertisingStartHandler.bind(this));

        if (bleno.state === 'poweredOn') {
            bleno.startAdvertising(this.peripheralName, [this.serviceUUID]);
        }
    }

    async disable() {
        bleno.stopAdvertising()
        bleno.removeAllListeners();
    }

    stateChangeHandler(state) {
        this.emit('stateChange', state);
        console.log('(bleno) on -> stateChange: ' + state);

        if (state === 'poweredOn') {
            bleno.startAdvertising(this.peripheralName, [this.serviceUUID]);
        } else {
            bleno.stopAdvertising();
        }
    }
<commit_msg>Add proper await for bleno disabling<commit_after>const noble = require('@abandonware/noble');
const bleno = require('@abandonware/bleno');
const fs = require('fs');
const util = require('util');
const path = require('path');
const { EventEmitter } = require('events');

const writeFile = util.promisify(fs.writeFile);
const readFile = util.promisify(fs.readFile);

var BlenoPrimaryService = bleno.PrimaryService;
var BlenoCharacteristic = bleno.Characteristic;

class BluetoothFileExchangerCentral extends EventEmitter {
    constructor(serviceUUID, characteristicUUID, outputDirectory) {
        super();
        this.serviceUUID = serviceUUID;
        this.characteristicUUID = characteristicUUID;
        this.outputDirectory = outputDirectory;

        noble.on('stateChange', this.stateChangeHandler.bind(this));
        noble.on('discover', this.discoverHandler.bind(this));

        if (noble.state == 'poweredOn') {
            noble.startScanningAsync([this.serviceUUID], true);
        }
    }

    async disable() {
        await noble.stopScanningAsync();
        noble.removeAllListeners();
    }

    async stateChangeHandler(state) {
        console.log('(noble) on -> stateChange: ' + state);
        this.emit('stateChange', state);

        if (state === 'poweredOn') {
            console.log('Scanning');
            await noble.startScanningAsync([this.serviceUUID], true);
        } else {
            await noble.stopScanningAsync();
        }
    }

    discoverHandler(peripheral) {
        this.emit('discover', peripheral);
        peripheral.once('disconnect', () => this.emit('disconnect', peripheral));
    }

    /**
     * 
     * @param {*} peripheral The peripheral to receieve the file from
     */
    async receive(peripheral) {
        await noble.stopScanningAsync();
        await peripheral.connectAsync();

        const characteristics = await new Promise((resolve, reject) => {
            peripheral.discoverSomeServicesAndCharacteristics(
                [this.serviceUUID],
                [this.characteristicUUID],
                (error, services, characteristics) => {
                    if (error) {
                        reject(error);
                        return;
                    }

                    resolve(characteristics);
                }
            );
        });
        const characteristic = characteristics[0];

        const data = await new Promise((resolve, reject) => {
            characteristic.read((error, data) => {
                if (error) {
                    reject(error)
                    return;
                }
                resolve(data);
            });
        });
        await writeFile(path.join(this.outputDirectory, peripheral.advertisement.localName), data);
        await peripheral.disconnectAsync();
        await noble.startScanningAsync();
    }
}

class BluetoothFileExchangerPeripheral extends EventEmitter {
    constructor(serviceUUID, characteristicUUID, peripheralName, filePathSupplier) {
        super();
        this.serviceUUID = serviceUUID;
        this.characteristicUUID = characteristicUUID;
        this.peripheralName = peripheralName;
        this.filePathSupplier = filePathSupplier;

        bleno.on('stateChange', this.stateChangeHandler.bind(this));
        bleno.on('advertisingStart', this.advertisingStartHandler.bind(this));

        if (bleno.state === 'poweredOn') {
            bleno.startAdvertising(this.peripheralName, [this.serviceUUID]);
        }
    }

    async disable() {
        await new Promise((resolve, _) => {
            bleno.stopAdvertising(resolve);
        });
        bleno.removeAllListeners();
    }

    stateChangeHandler(state) {
        this.emit('stateChange', state);
        console.log('(bleno) on -> stateChange: ' + state);

        if (state === 'poweredOn') {
            bleno.startAdvertising(this.peripheralName, [this.serviceUUID]);
        } else {
            bleno.stopAdvertising();
        }
    }

{'fraction_non_alphanumeric': 0.11696869851729819, 'fraction_numerical': 0.0002534533012292485, 'mean_word_length': 2.3062421449518222, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7100468', 'n_tokens_mistral': 2105, 'n_tokens_neox': 2060, 'n_words': 372}