fetch pxt-microbit v2.2.30 (#102)
* undo buttonEvent * fetch microbit v2.2.30 Co-authored-by: Amerlander <gitkraken@juriwolf.de>
This commit is contained in:
		@@ -1,4 +0,0 @@
 | 
			
		||||
# radio
 | 
			
		||||
 | 
			
		||||
The radio library.
 | 
			
		||||
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
  "radio._packetProperty": "Gets a packet property.",
 | 
			
		||||
  "radio._packetProperty|param|type": "the packet property type, eg: PacketProperty.time",
 | 
			
		||||
  "radio.onDataPacketReceived": "Deprecated. Use onDataReceived() instead\nRegisters code to run when the radio receives a packet. Also takes the\nreceived packet from the radio queue.",
 | 
			
		||||
  "radio.onDataReceived": "Registers code to run when a packet is received over radio.",
 | 
			
		||||
  "radio.onDataReceived": "Used internally by the library.",
 | 
			
		||||
  "radio.onReceivedBuffer": "Registers code to run when the radio receives a buffer.",
 | 
			
		||||
  "radio.onReceivedBufferDeprecated": "Registers code to run when the radio receives a buffer. Deprecated, use\nonReceivedBuffer instead.",
 | 
			
		||||
  "radio.onReceivedNumber": "Registers code to run when the radio receives a number.",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "radio",
 | 
			
		||||
    "description": "The radio services",
 | 
			
		||||
    "files": [
 | 
			
		||||
        "README.md",
 | 
			
		||||
        "shims.d.ts",
 | 
			
		||||
        "enums.d.ts",
 | 
			
		||||
        "radio.cpp",
 | 
			
		||||
        "radio.ts",
 | 
			
		||||
        "deprecated.ts"
 | 
			
		||||
    ],
 | 
			
		||||
    "icon": "./static/packages/radio/icon.png",
 | 
			
		||||
    "public": true,
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "core": "file:../core"
 | 
			
		||||
    },
 | 
			
		||||
    "additionalFilePath": "../../node_modules/pxt-common-packages/libs/radio",
 | 
			
		||||
    "yotta": {
 | 
			
		||||
        "config": {
 | 
			
		||||
            "microbit-dal": {
 | 
			
		||||
@@ -22,6 +8,5 @@
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "installedVersion": "rlfgis"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,126 +0,0 @@
 | 
			
		||||
#include "pxt.h"
 | 
			
		||||
 | 
			
		||||
using namespace pxt;
 | 
			
		||||
 | 
			
		||||
//% color=#E3008C weight=96 icon="\uf012"
 | 
			
		||||
namespace radio {
 | 
			
		||||
 | 
			
		||||
    bool radioEnabled = false;
 | 
			
		||||
 | 
			
		||||
    int radioEnable() {
 | 
			
		||||
        int r = uBit.radio.enable();
 | 
			
		||||
        if (r != MICROBIT_OK) {
 | 
			
		||||
            uBit.panic(43);
 | 
			
		||||
            return r;
 | 
			
		||||
        }
 | 
			
		||||
        if (!radioEnabled) {
 | 
			
		||||
            uBit.radio.setGroup(pxt::programHash());
 | 
			
		||||
            uBit.radio.setTransmitPower(6); // start with high power by default
 | 
			
		||||
            radioEnabled = true;
 | 
			
		||||
        }
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Sends an event over radio to neigboring devices
 | 
			
		||||
    */
 | 
			
		||||
    //% blockId=radioRaiseEvent block="radio raise event|from source %src=control_event_source_id|with value %value=control_event_value_id"
 | 
			
		||||
    //% blockExternalInputs=1
 | 
			
		||||
    //% advanced=true
 | 
			
		||||
    //% weight=1
 | 
			
		||||
    //% help=radio/raise-event
 | 
			
		||||
    void raiseEvent(int src, int value) {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
 | 
			
		||||
        uBit.radio.event.eventReceived(MicroBitEvent(src, value, CREATE_ONLY));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Internal use only. Takes the next packet from the radio queue and returns its contents + RSSI in a Buffer
 | 
			
		||||
     */
 | 
			
		||||
    //%
 | 
			
		||||
    Buffer readRawPacket() {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return mkBuffer(NULL, 0);
 | 
			
		||||
 | 
			
		||||
        PacketBuffer p = uBit.radio.datagram.recv();
 | 
			
		||||
        if (p == PacketBuffer::EmptyPacket)
 | 
			
		||||
            return mkBuffer(NULL, 0);
 | 
			
		||||
 | 
			
		||||
        int rssi = p.getRSSI();
 | 
			
		||||
        uint8_t buf[MICROBIT_RADIO_MAX_PACKET_SIZE + sizeof(int)]; // packet length + rssi
 | 
			
		||||
        memset(buf, 0, sizeof(buf));
 | 
			
		||||
        memcpy(buf, p.getBytes(), p.length()); // data
 | 
			
		||||
        memcpy(buf + MICROBIT_RADIO_MAX_PACKET_SIZE, &rssi, sizeof(int)); // RSSi - assumes Int32LE layout
 | 
			
		||||
        return mkBuffer(buf, sizeof(buf));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Internal use only. Sends a raw packet through the radio (assumes RSSI appened to packet)
 | 
			
		||||
     */
 | 
			
		||||
    //% async
 | 
			
		||||
    void sendRawPacket(Buffer msg) {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK || NULL == msg) return;
 | 
			
		||||
 | 
			
		||||
        // don't send RSSI data; and make sure no buffer underflow
 | 
			
		||||
        int len = msg->length - sizeof(int);
 | 
			
		||||
        if (len > 0)
 | 
			
		||||
            uBit.radio.datagram.send(msg->data, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers code to run when a packet is received over radio.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/on-data-received
 | 
			
		||||
    //% weight=50
 | 
			
		||||
    //% blockId=radio_datagram_received_event block="radio on data received" blockGap=8
 | 
			
		||||
    //% deprecated=true
 | 
			
		||||
    void onDataReceived(Action body) {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
 | 
			
		||||
        registerWithDal(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, body);
 | 
			
		||||
        uBit.radio.datagram.recv(); // wake up read code
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the group id for radio communications. A micro:bit can only listen to one group ID at any time.
 | 
			
		||||
     * @param id the group id between ``0`` and ``255``, eg: 1
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/set-group
 | 
			
		||||
    //% weight=100
 | 
			
		||||
    //% blockId=radio_set_group block="radio set group %ID"
 | 
			
		||||
    //% id.min=0 id.max=255
 | 
			
		||||
    void setGroup(int id) {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
 | 
			
		||||
        uBit.radio.setGroup(id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Change the output power level of the transmitter to the given value.
 | 
			
		||||
    * @param power a value in the range 0..7, where 0 is the lowest power and 7 is the highest. eg: 7
 | 
			
		||||
    */
 | 
			
		||||
    //% help=radio/set-transmit-power
 | 
			
		||||
    //% weight=9 blockGap=8
 | 
			
		||||
    //% blockId=radio_set_transmit_power block="radio set transmit power %power"
 | 
			
		||||
    //% power.min=0 power.max=7
 | 
			
		||||
    //% advanced=true
 | 
			
		||||
    void setTransmitPower(int power) {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
 | 
			
		||||
        uBit.radio.setTransmitPower(power);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Change the transmission and reception band of the radio to the given channel
 | 
			
		||||
    * @param band a frequency band in the range 0 - 83. Each step is 1MHz wide, based at 2400MHz.
 | 
			
		||||
    **/
 | 
			
		||||
    //% help=radio/set-frequency-band
 | 
			
		||||
    //% weight=8 blockGap=8
 | 
			
		||||
    //% blockId=radio_set_frequency_band block="radio set frequency band %band"
 | 
			
		||||
    //% band.min=0 band.max=83
 | 
			
		||||
    //% advanced=true
 | 
			
		||||
    void setFrequencyBand(int band) {
 | 
			
		||||
        if (radioEnable() != MICROBIT_OK) return;
 | 
			
		||||
        uBit.radio.setFrequencyBand(band);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,444 +0,0 @@
 | 
			
		||||
 | 
			
		||||
enum RadioPacketProperty {
 | 
			
		||||
    //% blockIdentity=radio._packetProperty
 | 
			
		||||
    //% block="signal strength"
 | 
			
		||||
    SignalStrength = 2,
 | 
			
		||||
    //% blockIdentity=radio._packetProperty
 | 
			
		||||
    //% block="time"
 | 
			
		||||
    Time = 0,
 | 
			
		||||
    //% block="serial number"
 | 
			
		||||
    //% blockIdentity=radio._packetProperty
 | 
			
		||||
    SerialNumber = 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Communicate data using radio packets
 | 
			
		||||
 */
 | 
			
		||||
//% color=#E3008C weight=96 icon="\uf012"
 | 
			
		||||
namespace radio {
 | 
			
		||||
 | 
			
		||||
    const MAX_FIELD_DOUBLE_NAME_LENGTH = 8;
 | 
			
		||||
    const MAX_PAYLOAD_LENGTH = 20;
 | 
			
		||||
    const PACKET_PREFIX_LENGTH = 9;
 | 
			
		||||
    const VALUE_PACKET_NAME_LEN_OFFSET = 13;
 | 
			
		||||
    const DOUBLE_VALUE_PACKET_NAME_LEN_OFFSET = 17;
 | 
			
		||||
 | 
			
		||||
    // Packet Spec:
 | 
			
		||||
    // | 0              | 1 ... 4       | 5 ... 8           | 9 ... 28
 | 
			
		||||
    // ----------------------------------------------------------------
 | 
			
		||||
    // | packet type    | system time   | serial number     | payload
 | 
			
		||||
    //
 | 
			
		||||
    // Serial number defaults to 0 unless enabled by user
 | 
			
		||||
 | 
			
		||||
    // payload: number (9 ... 12)
 | 
			
		||||
    const PACKET_TYPE_NUMBER = 0;
 | 
			
		||||
    // payload: number (9 ... 12), name length (13), name (14 ... 26)
 | 
			
		||||
    const PACKET_TYPE_VALUE = 1;
 | 
			
		||||
    // payload: string length (9), string (10 ... 28)
 | 
			
		||||
    const PACKET_TYPE_STRING = 2;
 | 
			
		||||
    // payload: buffer length (9), buffer (10 ... 28)
 | 
			
		||||
    const PACKET_TYPE_BUFFER = 3;
 | 
			
		||||
    // payload: number (9 ... 16)
 | 
			
		||||
    const PACKET_TYPE_DOUBLE = 4;
 | 
			
		||||
    // payload: number (9 ... 16), name length (17), name (18 ... 26)
 | 
			
		||||
    const PACKET_TYPE_DOUBLE_VALUE = 5;
 | 
			
		||||
 | 
			
		||||
    let transmittingSerial: boolean;
 | 
			
		||||
    let initialized = false;
 | 
			
		||||
 | 
			
		||||
    export let lastPacket: RadioPacket;
 | 
			
		||||
    let onReceivedNumberHandler: (receivedNumber: number) => void;
 | 
			
		||||
    let onReceivedValueHandler: (name: string, value: number) => void;
 | 
			
		||||
    let onReceivedStringHandler: (receivedString: string) => void;
 | 
			
		||||
    let onReceivedBufferHandler: (receivedBuffer: Buffer) => void;
 | 
			
		||||
 | 
			
		||||
    function init() {
 | 
			
		||||
        if (initialized) return;
 | 
			
		||||
        initialized = true;
 | 
			
		||||
        onDataReceived(handleDataReceived);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function handleDataReceived() {
 | 
			
		||||
        let buffer: Buffer = readRawPacket();
 | 
			
		||||
        while (buffer && buffer.length) {
 | 
			
		||||
            lastPacket = RadioPacket.getPacket(buffer);
 | 
			
		||||
            switch (lastPacket.packetType) {
 | 
			
		||||
                case PACKET_TYPE_NUMBER:
 | 
			
		||||
                case PACKET_TYPE_DOUBLE:
 | 
			
		||||
                    if (onReceivedNumberHandler)
 | 
			
		||||
                        onReceivedNumberHandler(lastPacket.numberPayload);
 | 
			
		||||
                    break;
 | 
			
		||||
                case PACKET_TYPE_VALUE:
 | 
			
		||||
                case PACKET_TYPE_DOUBLE_VALUE:
 | 
			
		||||
                    if (onReceivedValueHandler)
 | 
			
		||||
                        onReceivedValueHandler(lastPacket.stringPayload, lastPacket.numberPayload);
 | 
			
		||||
                    break;
 | 
			
		||||
                case PACKET_TYPE_BUFFER:
 | 
			
		||||
                    if (onReceivedBufferHandler)
 | 
			
		||||
                        onReceivedBufferHandler(lastPacket.bufferPayload);
 | 
			
		||||
                    break;
 | 
			
		||||
                case PACKET_TYPE_STRING:
 | 
			
		||||
                    if (onReceivedStringHandler)
 | 
			
		||||
                        onReceivedStringHandler(lastPacket.stringPayload);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                // read next packet if any
 | 
			
		||||
                buffer = readRawPacket();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers code to run when the radio receives a number.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/on-received-number
 | 
			
		||||
    //% blockId=radio_on_number_drag block="on radio received" blockGap=16
 | 
			
		||||
    //% useLoc="radio.onDataPacketReceived" draggableParameters=reporter
 | 
			
		||||
    export function onReceivedNumber(cb: (receivedNumber: number) => void) {
 | 
			
		||||
        init();
 | 
			
		||||
        onReceivedNumberHandler = cb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers code to run when the radio receives a key value pair.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/on-received-value
 | 
			
		||||
    //% blockId=radio_on_value_drag block="on radio received" blockGap=16
 | 
			
		||||
    //% useLoc="radio.onDataPacketReceived" draggableParameters=reporter
 | 
			
		||||
    export function onReceivedValue(cb: (name: string, value: number) => void) {
 | 
			
		||||
        init();
 | 
			
		||||
        onReceivedValueHandler = cb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers code to run when the radio receives a string.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/on-received-string
 | 
			
		||||
    //% blockId=radio_on_string_drag block="on radio received" blockGap=16
 | 
			
		||||
    //% useLoc="radio.onDataPacketReceived" draggableParameters=reporter
 | 
			
		||||
    export function onReceivedString(cb: (receivedString: string) => void) {
 | 
			
		||||
        init();
 | 
			
		||||
        onReceivedStringHandler = cb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers code to run when the radio receives a buffer.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/on-received-buffer blockHidden=1
 | 
			
		||||
    //% blockId=radio_on_buffer_drag block="on radio received" blockGap=16
 | 
			
		||||
    //% useLoc="radio.onDataPacketReceived" draggableParameters=reporter
 | 
			
		||||
    export function onReceivedBuffer(cb: (receivedBuffer: Buffer) => void) {
 | 
			
		||||
        init();
 | 
			
		||||
        onReceivedBufferHandler = cb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns properties of the last radio packet received.
 | 
			
		||||
     * @param type the type of property to retrieve from the last packet
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/received-packet
 | 
			
		||||
    //% weight=11 blockGap=8
 | 
			
		||||
    //% blockId=radio_received_packet block="received packet %type=radio_packet_property" blockGap=16
 | 
			
		||||
    export function receivedPacket(type: number) {
 | 
			
		||||
        if (lastPacket) {
 | 
			
		||||
            switch (type) {
 | 
			
		||||
                case RadioPacketProperty.Time: return lastPacket.time;
 | 
			
		||||
                case RadioPacketProperty.SerialNumber: return lastPacket.serial;
 | 
			
		||||
                case RadioPacketProperty.SignalStrength: return lastPacket.signal;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a packet property.
 | 
			
		||||
     * @param type the packet property type, eg: PacketProperty.time
 | 
			
		||||
     */
 | 
			
		||||
    //% blockId=radio_packet_property block="%note"
 | 
			
		||||
    //% shim=TD_ID blockHidden=1
 | 
			
		||||
    export function _packetProperty(type: RadioPacketProperty): number {
 | 
			
		||||
        return type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export class RadioPacket {
 | 
			
		||||
        public static getPacket(data: Buffer) {
 | 
			
		||||
            // last 4 bytes is RSSi
 | 
			
		||||
            return new RadioPacket(data);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static mkPacket(packetType: number) {
 | 
			
		||||
            const res = new RadioPacket();
 | 
			
		||||
            res.data[0] = packetType;
 | 
			
		||||
            return res;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private constructor(public readonly data?: Buffer) {
 | 
			
		||||
            if (!data) this.data = control.createBuffer(DAL.MICROBIT_RADIO_MAX_PACKET_SIZE + 4);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get signal() {
 | 
			
		||||
            return this.data.getNumber(NumberFormat.Int32LE, this.data.length - 4);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get packetType() {
 | 
			
		||||
            return this.data[0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get time() {
 | 
			
		||||
            return this.data.getNumber(NumberFormat.Int32LE, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        set time(val: number) {
 | 
			
		||||
            this.data.setNumber(NumberFormat.Int32LE, 1, val);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get serial() {
 | 
			
		||||
            return this.data.getNumber(NumberFormat.Int32LE, 5);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        set serial(val: number) {
 | 
			
		||||
            this.data.setNumber(NumberFormat.Int32LE, 5, val);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get stringPayload() {
 | 
			
		||||
            const offset = getStringOffset(this.packetType) as number;
 | 
			
		||||
            return offset ? this.data.slice(offset + 1, this.data[offset]).toString() : undefined;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        set stringPayload(val: string) {
 | 
			
		||||
            const offset = getStringOffset(this.packetType) as number;
 | 
			
		||||
            if (offset) {
 | 
			
		||||
                const buf = control.createBufferFromUTF8(truncateString(val, getMaxStringLength(this.packetType)));
 | 
			
		||||
                this.data[offset] = buf.length;
 | 
			
		||||
                this.data.write(offset + 1, buf);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get numberPayload() {
 | 
			
		||||
            switch (this.packetType) {
 | 
			
		||||
                case PACKET_TYPE_NUMBER:
 | 
			
		||||
                case PACKET_TYPE_VALUE:
 | 
			
		||||
                    return this.data.getNumber(NumberFormat.Int32LE, PACKET_PREFIX_LENGTH);
 | 
			
		||||
                case PACKET_TYPE_DOUBLE:
 | 
			
		||||
                case PACKET_TYPE_DOUBLE_VALUE:
 | 
			
		||||
                    return this.data.getNumber(NumberFormat.Float64LE, PACKET_PREFIX_LENGTH);
 | 
			
		||||
            }
 | 
			
		||||
            return undefined;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        set numberPayload(val: number) {
 | 
			
		||||
            switch (this.packetType) {
 | 
			
		||||
                case PACKET_TYPE_NUMBER:
 | 
			
		||||
                case PACKET_TYPE_VALUE:
 | 
			
		||||
                    this.data.setNumber(NumberFormat.Int32LE, PACKET_PREFIX_LENGTH, val);
 | 
			
		||||
                    break;
 | 
			
		||||
                case PACKET_TYPE_DOUBLE:
 | 
			
		||||
                case PACKET_TYPE_DOUBLE_VALUE:
 | 
			
		||||
                    this.data.setNumber(NumberFormat.Float64LE, PACKET_PREFIX_LENGTH, val);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        get bufferPayload() {
 | 
			
		||||
            const len = this.data[PACKET_PREFIX_LENGTH];
 | 
			
		||||
            return this.data.slice(PACKET_PREFIX_LENGTH + 1, len);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        set bufferPayload(b: Buffer) {
 | 
			
		||||
            const len = Math.min(b.length, MAX_PAYLOAD_LENGTH - 1);
 | 
			
		||||
            this.data[PACKET_PREFIX_LENGTH] = len;
 | 
			
		||||
            this.data.write(PACKET_PREFIX_LENGTH + 1, b.slice(0, len));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        hasString() {
 | 
			
		||||
            return this.packetType === PACKET_TYPE_STRING ||
 | 
			
		||||
                this.packetType === PACKET_TYPE_VALUE ||
 | 
			
		||||
                this.packetType === PACKET_TYPE_DOUBLE_VALUE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        hasNumber() {
 | 
			
		||||
            return this.packetType === PACKET_TYPE_NUMBER ||
 | 
			
		||||
                this.packetType === PACKET_TYPE_DOUBLE ||
 | 
			
		||||
                this.packetType === PACKET_TYPE_VALUE ||
 | 
			
		||||
                this.packetType === PACKET_TYPE_DOUBLE_VALUE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Broadcasts a number over radio to any connected micro:bit in the group.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/send-number
 | 
			
		||||
    //% weight=60
 | 
			
		||||
    //% blockId=radio_datagram_send block="radio send number %value" blockGap=8
 | 
			
		||||
    export function sendNumber(value: number) {
 | 
			
		||||
        let packet: RadioPacket;
 | 
			
		||||
 | 
			
		||||
        if (value === (value | 0)) {
 | 
			
		||||
            packet = RadioPacket.mkPacket(PACKET_TYPE_NUMBER);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            packet = RadioPacket.mkPacket(PACKET_TYPE_DOUBLE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        packet.numberPayload = value;
 | 
			
		||||
        sendPacket(packet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Broadcasts a name / value pair along with the device serial number
 | 
			
		||||
    * and running time to any connected micro:bit in the group. The name can
 | 
			
		||||
    * include no more than 8 characters.
 | 
			
		||||
    * @param name the field name (max 8 characters), eg: "name"
 | 
			
		||||
    * @param value the numeric value
 | 
			
		||||
    */
 | 
			
		||||
    //% help=radio/send-value
 | 
			
		||||
    //% weight=59
 | 
			
		||||
    //% blockId=radio_datagram_send_value block="radio send|value %name|= %value" blockGap=8
 | 
			
		||||
    export function sendValue(name: string, value: number) {
 | 
			
		||||
        let packet: RadioPacket;
 | 
			
		||||
 | 
			
		||||
        if (value === (value | 0)) {
 | 
			
		||||
            packet = RadioPacket.mkPacket(PACKET_TYPE_VALUE);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            packet = RadioPacket.mkPacket(PACKET_TYPE_DOUBLE_VALUE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        packet.numberPayload = value;
 | 
			
		||||
        packet.stringPayload = name;
 | 
			
		||||
        sendPacket(packet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Broadcasts a string along with the device serial number
 | 
			
		||||
     * and running time to any connected micro:bit in the group.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/send-string
 | 
			
		||||
    //% weight=58
 | 
			
		||||
    //% blockId=radio_datagram_send_string block="radio send string %msg"
 | 
			
		||||
    //% msg.shadowOptions.toString=true
 | 
			
		||||
    export function sendString(value: string) {
 | 
			
		||||
        const packet = RadioPacket.mkPacket(PACKET_TYPE_STRING);
 | 
			
		||||
        packet.stringPayload = value;
 | 
			
		||||
        sendPacket(packet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Broadcasts a buffer (up to 19 bytes long) along with the device serial number
 | 
			
		||||
     * and running time to any connected micro:bit in the group.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/send-buffer
 | 
			
		||||
    //% weight=57
 | 
			
		||||
    //% advanced=true
 | 
			
		||||
    export function sendBuffer(msg: Buffer) {
 | 
			
		||||
        const packet = RadioPacket.mkPacket(PACKET_TYPE_BUFFER);
 | 
			
		||||
        packet.bufferPayload = msg;
 | 
			
		||||
        sendPacket(packet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Writes the last received packet to serial as JSON. This should be called
 | 
			
		||||
    * within an ``onDataPacketReceived`` callback.
 | 
			
		||||
    */
 | 
			
		||||
    //% help=radio/write-received-packet-to-serial
 | 
			
		||||
    //% weight=3
 | 
			
		||||
    //% blockId=radio_write_packet_serial block="radio write received packet to serial"
 | 
			
		||||
    //% advanced=true
 | 
			
		||||
    export function writeReceivedPacketToSerial() {
 | 
			
		||||
        if (lastPacket) writeToSerial(lastPacket)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Set the radio to transmit the serial number in each message.
 | 
			
		||||
    * @param transmit value indicating if the serial number is transmitted, eg: true
 | 
			
		||||
    */
 | 
			
		||||
    //% help=radio/set-transmit-serial-number
 | 
			
		||||
    //% weight=8 blockGap=8
 | 
			
		||||
    //% blockId=radio_set_transmit_serial_number block="radio set transmit serial number %transmit"
 | 
			
		||||
    //% advanced=true
 | 
			
		||||
    export function setTransmitSerialNumber(transmit: boolean) {
 | 
			
		||||
        transmittingSerial = transmit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the received signal strength indicator (RSSI) from the last packet taken
 | 
			
		||||
     * from the radio queue (via ``receiveNumber``, ``receiveString``, etc). Not supported in simulator.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/received-signal-strength
 | 
			
		||||
    //% weight=40
 | 
			
		||||
    //% blockId=radio_datagram_rssi block="radio received signal strength"
 | 
			
		||||
    //% deprecated=true blockHidden=true
 | 
			
		||||
    export function receivedSignalStrength(): number {
 | 
			
		||||
        return lastPacket ? lastPacket.signal : 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function writeToSerial(packet: RadioPacket) {
 | 
			
		||||
        serial.writeString("{");
 | 
			
		||||
        serial.writeString("\"t\":");
 | 
			
		||||
        serial.writeString("" + packet.time);
 | 
			
		||||
        serial.writeString(",\"s\":");
 | 
			
		||||
        serial.writeString("" + packet.serial);
 | 
			
		||||
 | 
			
		||||
        if (packet.hasString()) {
 | 
			
		||||
            serial.writeString(",\"n\":\"");
 | 
			
		||||
            serial.writeString(packet.stringPayload);
 | 
			
		||||
            serial.writeString("\"");
 | 
			
		||||
        }
 | 
			
		||||
        if (packet.packetType == PACKET_TYPE_BUFFER) {
 | 
			
		||||
            serial.writeString(",\"b\":\"");
 | 
			
		||||
            // TODO: proper base64 encoding
 | 
			
		||||
            serial.writeString(packet.bufferPayload.toString());
 | 
			
		||||
            serial.writeString("\"");
 | 
			
		||||
        }
 | 
			
		||||
        if (packet.hasNumber()) {
 | 
			
		||||
            serial.writeString(",\"v\":");
 | 
			
		||||
            serial.writeString("" + packet.numberPayload);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        serial.writeString("}\r\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function sendPacket(packet: RadioPacket) {
 | 
			
		||||
        packet.time = input.runningTime();
 | 
			
		||||
        packet.serial = transmittingSerial ? control.deviceSerialNumber() : 0;
 | 
			
		||||
        radio.sendRawPacket(packet.data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function truncateString(str: string, bytes: number) {
 | 
			
		||||
        str = str.substr(0, bytes);
 | 
			
		||||
        let buff = control.createBufferFromUTF8(str);
 | 
			
		||||
 | 
			
		||||
        while (buff.length > bytes) {
 | 
			
		||||
            str = str.substr(0, str.length - 1);
 | 
			
		||||
            buff = control.createBufferFromUTF8(str);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return str;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getStringOffset(packetType: number) {
 | 
			
		||||
        switch (packetType) {
 | 
			
		||||
            case PACKET_TYPE_STRING:
 | 
			
		||||
                return PACKET_PREFIX_LENGTH;
 | 
			
		||||
            case PACKET_TYPE_VALUE:
 | 
			
		||||
                return VALUE_PACKET_NAME_LEN_OFFSET;
 | 
			
		||||
            case PACKET_TYPE_DOUBLE_VALUE:
 | 
			
		||||
                return DOUBLE_VALUE_PACKET_NAME_LEN_OFFSET;
 | 
			
		||||
            default:
 | 
			
		||||
                return undefined;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getMaxStringLength(packetType: number) {
 | 
			
		||||
        switch (packetType) {
 | 
			
		||||
            case PACKET_TYPE_STRING:
 | 
			
		||||
                return MAX_PAYLOAD_LENGTH - 2;
 | 
			
		||||
            case PACKET_TYPE_VALUE:
 | 
			
		||||
            case PACKET_TYPE_DOUBLE_VALUE:
 | 
			
		||||
                return MAX_FIELD_DOUBLE_NAME_LENGTH;
 | 
			
		||||
            default:
 | 
			
		||||
                return undefined;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								libs/radio/shims.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								libs/radio/shims.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -28,12 +28,12 @@ declare namespace radio {
 | 
			
		||||
    function sendRawPacket(msg: Buffer): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers code to run when a packet is received over radio.
 | 
			
		||||
     * Used internally by the library.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/on-data-received
 | 
			
		||||
    //% weight=50
 | 
			
		||||
    //% weight=0
 | 
			
		||||
    //% blockId=radio_datagram_received_event block="radio on data received" blockGap=8
 | 
			
		||||
    //% deprecated=true shim=radio::onDataReceived
 | 
			
		||||
    //% deprecated=true blockHidden=1 shim=radio::onDataReceived
 | 
			
		||||
    function onDataReceived(body: () => void): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -97,19 +97,6 @@ namespace radio {
 | 
			
		||||
        onReceivedBuffer(cb);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Reads the next packet from the radio queue and and writes it to serial
 | 
			
		||||
    * as JSON.
 | 
			
		||||
    */
 | 
			
		||||
    //% help=radio/write-value-to-serial
 | 
			
		||||
    //% weight=3
 | 
			
		||||
    //% blockId=radio_write_value_serial block="radio write value to serial"
 | 
			
		||||
    //% deprecated=true
 | 
			
		||||
    export function writeValueToSerial() {
 | 
			
		||||
        const p = RadioPacket.getPacket(radio.readRawPacket());
 | 
			
		||||
        writeToSerial(p);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the number payload from the last packet taken from the radio queue
 | 
			
		||||
     * (via ``receiveNumber``, ``receiveString``, etc) or 0 if that packet did not
 | 
			
		||||
@@ -185,4 +172,67 @@ namespace radio {
 | 
			
		||||
        lastPacket = RadioPacket.getPacket(readRawPacket());
 | 
			
		||||
        return receivedString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the received signal strength indicator (RSSI) from the last packet taken
 | 
			
		||||
     * from the radio queue (via ``receiveNumber``, ``receiveString``, etc). Not supported in simulator.
 | 
			
		||||
     */
 | 
			
		||||
    //% help=radio/received-signal-strength
 | 
			
		||||
    //% weight=40
 | 
			
		||||
    //% blockId=radio_datagram_rssi block="radio received signal strength"
 | 
			
		||||
    //% deprecated=true blockHidden=true
 | 
			
		||||
    export function receivedSignalStrength(): number {
 | 
			
		||||
        return lastPacket ? lastPacket.signal : 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Reads the next packet from the radio queue and and writes it to serial
 | 
			
		||||
    * as JSON.
 | 
			
		||||
    */
 | 
			
		||||
    //% help=radio/write-value-to-serial
 | 
			
		||||
    //% weight=3
 | 
			
		||||
    //% blockId=radio_write_value_serial block="radio write value to serial"
 | 
			
		||||
    //% deprecated=true
 | 
			
		||||
    export function writeValueToSerial() {
 | 
			
		||||
        const p = RadioPacket.getPacket(radio.readRawPacket());
 | 
			
		||||
        writeToSerial(p);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
    * Writes the last received packet to serial as JSON. This should be called
 | 
			
		||||
    * within an ``onDataPacketReceived`` callback.
 | 
			
		||||
    */
 | 
			
		||||
    //% help=radio/write-received-packet-to-serial
 | 
			
		||||
    //% weight=3
 | 
			
		||||
    //% blockId=radio_write_packet_serial block="radio write received packet to serial"
 | 
			
		||||
    //% advanced=true deprecated=true
 | 
			
		||||
    export function writeReceivedPacketToSerial() {
 | 
			
		||||
        if (lastPacket) writeToSerial(lastPacket)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function writeToSerial(packet: RadioPacket) {
 | 
			
		||||
        serial.writeString("{");
 | 
			
		||||
        serial.writeString("\"t\":");
 | 
			
		||||
        serial.writeString("" + packet.time);
 | 
			
		||||
        serial.writeString(",\"s\":");
 | 
			
		||||
        serial.writeString("" + packet.serial);
 | 
			
		||||
 | 
			
		||||
        if (packet.hasString()) {
 | 
			
		||||
            serial.writeString(",\"n\":\"");
 | 
			
		||||
            serial.writeString(packet.stringPayload);
 | 
			
		||||
            serial.writeString("\"");
 | 
			
		||||
        }
 | 
			
		||||
        if (packet.packetType == PACKET_TYPE_BUFFER) {
 | 
			
		||||
            serial.writeString(",\"b\":\"");
 | 
			
		||||
            // TODO: proper base64 encoding
 | 
			
		||||
            serial.writeString(packet.bufferPayload.toString());
 | 
			
		||||
            serial.writeString("\"");
 | 
			
		||||
        }
 | 
			
		||||
        if (packet.hasNumber()) {
 | 
			
		||||
            serial.writeString(",\"v\":");
 | 
			
		||||
            serial.writeString("" + packet.numberPayload);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        serial.writeString("}\r\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,349 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Tests for the radio. Press A on mbit 1 and B on mbit 2 to run the tests.
 | 
			
		||||
 * Sends random ints, doubles, strings, and buffers and checks them on
 | 
			
		||||
 * the other side
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
class FastRandom {
 | 
			
		||||
    private lfsr: number;
 | 
			
		||||
    public seed: number;
 | 
			
		||||
 | 
			
		||||
    constructor(seed?: number) {
 | 
			
		||||
        if (seed === undefined) seed = Math.randomRange(0x0001, 0xFFFF);
 | 
			
		||||
        this.seed = seed;
 | 
			
		||||
        this.lfsr = seed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    next(): number {
 | 
			
		||||
        return this.lfsr = (this.lfsr >> 1) ^ ((-(this.lfsr & 1)) & 0xb400);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    randomRange(min: number, max: number): number {
 | 
			
		||||
        return min + (max > min ? this.next() % (max - min + 1) : 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    reset() {
 | 
			
		||||
        this.lfsr = this.seed;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum TestStage {
 | 
			
		||||
    Integer,
 | 
			
		||||
    String,
 | 
			
		||||
    Double,
 | 
			
		||||
    IntValue,
 | 
			
		||||
    DblValue,
 | 
			
		||||
    Buffer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const TEST_COUNT = 30;
 | 
			
		||||
 | 
			
		||||
radio.setGroup(78)
 | 
			
		||||
const rand = new FastRandom(1234);
 | 
			
		||||
 | 
			
		||||
let stage = TestStage.Integer;
 | 
			
		||||
 | 
			
		||||
function initSender() {
 | 
			
		||||
    let lastReceived: number;
 | 
			
		||||
    let lastString: string;
 | 
			
		||||
    let testIndex = 0;
 | 
			
		||||
    let lastBuf: Buffer;
 | 
			
		||||
 | 
			
		||||
    let lastAck = -1;
 | 
			
		||||
 | 
			
		||||
    rand.reset();
 | 
			
		||||
    basic.clearScreen();
 | 
			
		||||
 | 
			
		||||
    // Send loop
 | 
			
		||||
    control.inBackground(function () {
 | 
			
		||||
        while (true) {
 | 
			
		||||
            for (let i = 0; i < TEST_COUNT; i++) {
 | 
			
		||||
                toggle(testIndex);
 | 
			
		||||
 | 
			
		||||
                if (stage === TestStage.Integer) {
 | 
			
		||||
                    lastReceived = getNextInt();
 | 
			
		||||
                }
 | 
			
		||||
                else if (stage === TestStage.Double) {
 | 
			
		||||
                    lastReceived = getNextDouble();
 | 
			
		||||
                }
 | 
			
		||||
                else if (stage === TestStage.IntValue) {
 | 
			
		||||
                    lastString = getNextName();
 | 
			
		||||
                    console.log(truncateString(lastString, 8))
 | 
			
		||||
                    lastReceived = getNextInt();
 | 
			
		||||
                }
 | 
			
		||||
                else if (stage === TestStage.DblValue) {
 | 
			
		||||
                    lastString = getNextName();
 | 
			
		||||
                    lastReceived = getNextDouble();
 | 
			
		||||
                }
 | 
			
		||||
                else if (stage === TestStage.String) {
 | 
			
		||||
                    lastString = getNextString();
 | 
			
		||||
                    console.log(truncateString(lastString, 19))
 | 
			
		||||
                }
 | 
			
		||||
                else if (stage === TestStage.Buffer) {
 | 
			
		||||
                    lastBuf = getNextBuffer();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                while (lastAck !== testIndex) {
 | 
			
		||||
                    if (stage === TestStage.Integer || stage === TestStage.Double) {
 | 
			
		||||
                        radio.sendNumber(lastReceived)
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (stage === TestStage.IntValue || stage === TestStage.DblValue) {
 | 
			
		||||
                        radio.sendValue(lastString, lastReceived)
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (stage === TestStage.String) {
 | 
			
		||||
                        radio.sendString(lastString);
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (stage === TestStage.Buffer) {
 | 
			
		||||
                        radio.sendBuffer(lastBuf);
 | 
			
		||||
                    }
 | 
			
		||||
                    basic.pause(10);
 | 
			
		||||
                }
 | 
			
		||||
                testIndex++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            stage++;
 | 
			
		||||
            if (stage > TestStage.Buffer) {
 | 
			
		||||
                basic.showIcon(IconNames.Yes);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    radio.onReceivedNumber(function (receivedNumber: number) {
 | 
			
		||||
        if (receivedNumber > lastAck) {
 | 
			
		||||
            lastAck = receivedNumber;
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let lastReceived: number;
 | 
			
		||||
let lastString: string;
 | 
			
		||||
let testIndex = -1;
 | 
			
		||||
let running = true;
 | 
			
		||||
let lastBuf: Buffer;
 | 
			
		||||
 | 
			
		||||
let lastPacket = new radio.Packet();
 | 
			
		||||
let currentPacket = new radio.Packet();
 | 
			
		||||
 | 
			
		||||
function truncateString(str: string, bytes: number) {
 | 
			
		||||
    str = str.substr(0, bytes);
 | 
			
		||||
    let buff = control.createBufferFromUTF8(str);
 | 
			
		||||
 | 
			
		||||
    while (buff.length > bytes) {
 | 
			
		||||
        str = str.substr(0, str.length - 1);
 | 
			
		||||
        buff = control.createBufferFromUTF8(str);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function initReceiver() {
 | 
			
		||||
 | 
			
		||||
    rand.reset();
 | 
			
		||||
 | 
			
		||||
    basic.clearScreen();
 | 
			
		||||
 | 
			
		||||
    radio.onDataReceived(function () {
 | 
			
		||||
        radio.receiveNumber();
 | 
			
		||||
 | 
			
		||||
        currentPacket.receivedNumber = radio.receivedNumber();
 | 
			
		||||
        currentPacket.receivedString = radio.receivedString();
 | 
			
		||||
        currentPacket.receivedBuffer = radio.receivedBuffer();
 | 
			
		||||
 | 
			
		||||
        if (currentPacket.receivedNumber === lastPacket.receivedNumber &&
 | 
			
		||||
            currentPacket.receivedString === lastPacket.receivedString &&
 | 
			
		||||
            checkBufferEqual(currentPacket.receivedBuffer, lastPacket.receivedBuffer)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lastPacket.receivedNumber = currentPacket.receivedNumber
 | 
			
		||||
        lastPacket.receivedString = currentPacket.receivedString
 | 
			
		||||
        lastPacket.receivedBuffer = currentPacket.receivedBuffer
 | 
			
		||||
 | 
			
		||||
        switch (stage) {
 | 
			
		||||
            case TestStage.Integer:
 | 
			
		||||
                verifyInt(radio.receivedNumber());
 | 
			
		||||
                break;
 | 
			
		||||
            case TestStage.Double:
 | 
			
		||||
                verifyDouble(radio.receivedNumber());
 | 
			
		||||
                break;
 | 
			
		||||
            case TestStage.IntValue:
 | 
			
		||||
                verifyIntValue(radio.receivedString(), radio.receivedNumber());
 | 
			
		||||
                break;
 | 
			
		||||
            case TestStage.DblValue:
 | 
			
		||||
                verifyDblValue(radio.receivedString(), radio.receivedNumber());
 | 
			
		||||
                break;
 | 
			
		||||
            case TestStage.String:
 | 
			
		||||
                verifyString(radio.receivedString());
 | 
			
		||||
                break;
 | 
			
		||||
            case TestStage.Buffer:
 | 
			
		||||
                verifyBuffer(radio.receivedBuffer());
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    control.inBackground(function () {
 | 
			
		||||
        while (running) {
 | 
			
		||||
            radio.sendNumber(testIndex);
 | 
			
		||||
            basic.pause(10)
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function nextTest() {
 | 
			
		||||
    testIndex++;
 | 
			
		||||
    toggle(testIndex);
 | 
			
		||||
    console.log(`test ${testIndex}`)
 | 
			
		||||
    if (((testIndex + 1) % TEST_COUNT) === 0) {
 | 
			
		||||
        stage++;
 | 
			
		||||
 | 
			
		||||
        if (stage > TestStage.Buffer) {
 | 
			
		||||
            basic.showIcon(IconNames.Yes)
 | 
			
		||||
            running = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function verifyInt(int: number) {
 | 
			
		||||
    if (int === lastReceived) return;
 | 
			
		||||
    lastReceived = int;
 | 
			
		||||
    if (lastReceived != getNextInt()) fail();
 | 
			
		||||
    nextTest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function verifyDouble(dbl: number) {
 | 
			
		||||
    if (dbl === lastReceived) return;
 | 
			
		||||
    lastReceived = dbl;
 | 
			
		||||
    if (lastReceived != getNextDouble()) fail();
 | 
			
		||||
    nextTest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function verifyIntValue(name: string, val: number) {
 | 
			
		||||
    if (val === lastReceived) return;
 | 
			
		||||
    lastReceived = val;
 | 
			
		||||
 | 
			
		||||
    if (name != truncateString(getNextName(), 8) || lastReceived != getNextInt()) fail();
 | 
			
		||||
    nextTest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function verifyDblValue(name: string, val: number) {
 | 
			
		||||
    if (val === lastReceived) return;
 | 
			
		||||
    lastReceived = val;
 | 
			
		||||
 | 
			
		||||
    if (name != truncateString(getNextName(), 8) || lastReceived != getNextDouble()) fail();
 | 
			
		||||
    nextTest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function verifyString(str: string) {
 | 
			
		||||
    if (!str || str === lastString) return;
 | 
			
		||||
 | 
			
		||||
    lastString = str;
 | 
			
		||||
    let next = truncateString(getNextString(), 19);
 | 
			
		||||
 | 
			
		||||
    if (lastString !== next) {
 | 
			
		||||
        console.log(`got ${control.createBufferFromUTF8(lastString).toHex()} expected ${control.createBufferFromUTF8(next).toHex()}`)
 | 
			
		||||
    }
 | 
			
		||||
    nextTest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function verifyBuffer(buf: Buffer) {
 | 
			
		||||
    if (checkBufferEqual(lastBuf, buf)) return;
 | 
			
		||||
 | 
			
		||||
    lastBuf = buf;
 | 
			
		||||
 | 
			
		||||
    if (!checkBufferEqual(lastBuf, getNextBuffer())) {
 | 
			
		||||
        fail();
 | 
			
		||||
    }
 | 
			
		||||
    nextTest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fail() {
 | 
			
		||||
    control.panic(testIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
let _lastInt: number;
 | 
			
		||||
let _lastDbl: number;
 | 
			
		||||
let _lastStr: string;
 | 
			
		||||
let _lastBuf: Buffer;
 | 
			
		||||
let _lastNam: string;
 | 
			
		||||
 | 
			
		||||
function getNextInt(): number {
 | 
			
		||||
    let res = rand.next();
 | 
			
		||||
    if (!res || res === _lastInt) return getNextInt();
 | 
			
		||||
    _lastInt = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getNextDouble(): number {
 | 
			
		||||
    let res = rand.next() / rand.next();
 | 
			
		||||
    if (res === _lastDbl) return getNextDouble();
 | 
			
		||||
    _lastDbl = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getNextString(): string {
 | 
			
		||||
    let len = rand.randomRange(1, 19);
 | 
			
		||||
    let res = "";
 | 
			
		||||
    for (let i = 0; i < len; i++) {
 | 
			
		||||
        res += String.fromCharCode(rand.next() & 0xbfff);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (res === _lastStr) return getNextString();
 | 
			
		||||
 | 
			
		||||
    _lastStr = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getNextName(): string {
 | 
			
		||||
    let len = rand.randomRange(1, 8);
 | 
			
		||||
    let res = "";
 | 
			
		||||
    for (let i = 0; i < len; i++) {
 | 
			
		||||
        res += String.fromCharCode(rand.next() & 0xbfff);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (res === _lastNam) return getNextName();
 | 
			
		||||
 | 
			
		||||
    _lastNam = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getNextBuffer(): Buffer {
 | 
			
		||||
    let len = rand.randomRange(0, 8);
 | 
			
		||||
    let res = control.createBuffer(len);
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < len; i++) {
 | 
			
		||||
        res[i] = rand.next() & 0xff;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (checkBufferEqual(_lastBuf, res)) return getNextBuffer();
 | 
			
		||||
 | 
			
		||||
    _lastBuf = res;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function checkBufferEqual(a: Buffer, b: Buffer) {
 | 
			
		||||
    if (a === b) return true;
 | 
			
		||||
    if ((!a && b) || (a && !b)) return false;
 | 
			
		||||
    if (a.length != b.length) return false;
 | 
			
		||||
    for (let i = 0; i < a.length; i++) {
 | 
			
		||||
        if (a[i] !== b[i]) return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input.onButtonPressed(Button.A, function () {
 | 
			
		||||
    basic.showString("S");
 | 
			
		||||
    initSender();
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
input.onButtonPressed(Button.B, function () {
 | 
			
		||||
    basic.showString("R");
 | 
			
		||||
    initReceiver();
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
function toggle(index: number) {
 | 
			
		||||
    const x = index % 5;
 | 
			
		||||
    const y = Math.idiv(index, 5) % 5;
 | 
			
		||||
    led.toggle(x, y);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user